본문 바로가기

게임수학/CK소프트렌더러

WireFrame Rendering

정사각형 메시는 두개의 삼각형 메시의 정보로 이루어졌다.

메시의 인덱스 버퍼와 버텍스 버퍼를 활용하여 와이어프레임 방식으로 정사각형을 그려보자.

 

// 아핀 변환 행렬 ( 크기 ) 
Vector3 sBasis1(currentScale, 0.f, 0.f);
Vector3 sBasis2(0.f, currentScale, 0.f);
Vector3 sBasis3 = Vector3::UnitZ;
Matrix3x3 sMatrix(sBasis1, sBasis2, sBasis3);

// 아핀 변환 행렬 ( 회전 ) 
float sin = 0.f, cos = 0.f;
Math::GetSinCos(sin, cos, currentDegree);
Vector3 rBasis1(cos, sin, 0.f);
Vector3 rBasis2(-sin, cos, 0.f);
Vector3 rBasis3 = Vector3::UnitZ;
Matrix3x3 rMatrix(rBasis1, rBasis2, rBasis3);

// 아핀 변환 행렬 ( 이동 ) 
Vector3 tBasis1 = Vector3::UnitX;
Vector3 tBasis2 = Vector3::UnitY;
Vector3 tBasis3(currentPosition.X, currentPosition.Y, 1.f);
Matrix3x3 tMatrix(tBasis1, tBasis2, tBasis3);

// 모든 아핀 변환을 곱한 합성 행렬. 크기-회전-이동 순으로 적용
Matrix3x3 finalMatrix = tMatrix * rMatrix * sMatrix;

// 행렬을 적용한 메시 정보를 사용해 물체를 렌더링
static std::vector<Vertex2D> vertices(vertexCount);
for (size_t vi = 0; vi < vertexCount; ++vi)
{
	vertices[vi].Position = finalMatrix * rawVertices[vi].Position;
}

	// 변환된 정점을 잇는 선 그리기
	for (size_t ti = 0; ti < triangleCount; ++ti)
	{
		size_t bi = ti * 3;
		r.DrawLine(vertices[indices[bi]].Position, vertices[indices[bi + 1]].Position, _WireframeColor);
		r.DrawLine(vertices[indices[bi]].Position, vertices[indices[bi + 2]].Position, _WireframeColor);
		r.DrawLine(vertices[indices[bi + 1]].Position, vertices[indices[bi + 2]].Position, _WireframeColor);
	}

 

Square WireFrame

 

 

 

 

 

텍스쳐 매핑

 메시에 이미지를 입히기 위해서 변환된 데이터를 '텍스처' 라고 부른다. 이를 텍스쳐에 이미지를 매핑하는 작업을 텍스처 매핑이라고 한다. 렌더링을 구현하는 과정에서 텍스처를 구성하는 좌표는 2차원 UV 좌표계를 사용한다. UV 좌표계는 2차원 벡터로 구성되어 가로 정보는 U, 세로 정보는 V로 저장된다. 

 

  // 행렬을 적용한 메시 정보를 사용해 물체를 렌더링
  static std::vector<Vertex2D> vertices(vertexCount);
  for (size_t vi = 0; vi < vertexCount; ++vi)
  {
      vertices[vi].Position = finalMatrix * rawVertices[vi].Position;
      vertices[vi].UV = rawVertices[vi].UV;
  }
  
  
        // 삼각형을 둘러싼 사각형 영역의 픽셀을 모두 순회
        for (int x = lowerLeftPoint.X; x <= upperRightPoint.X; ++x)
        {
            for (int y = upperRightPoint.Y; y <= lowerLeftPoint.Y; ++y)
            {
                ScreenPoint fragment = ScreenPoint(x, y);
                Vector2 pointToTest = fragment.ToCartesianCoordinate(_ScreenSize);
                Vector2 w = pointToTest - tv[0].Position;
                float wdotu = w.Dot(u);
                float wdotv = w.Dot(v);

                // 분자 값을 구하고 최종 무게중심좌표 산출
                float s = (wdotv * udotv - wdotu * vdotv) * invDenominator;
                float t = (wdotu * udotv - wdotv * udotu) * invDenominator;
                float oneMinusST = 1.f - s - t;

                // 컨벡스 조건을 만족할 때만 점 찍기
                if (((s >= 0.f) && (s <= 1.f)) && ((t >= 0.f) && (t <= 1.f)) && ((oneMinusST >= 0.f) && (oneMinusST <= 1.f)))
                {
                    Vector2 targetUV = tv[0].UV * oneMinusST + tv[1].UV * s + tv[2].UV * t;
                    r.DrawPoint(fragment, texture.GetSample(targetUV));
                }
            }
        }

 

'게임수학 > CK소프트렌더러' 카테고리의 다른 글

벡터 크기와 이동  (0) 2024.09.10
CMaker 소프트렌더러 첫 실습  (0) 2024.09.10
CK 소프트 렌더러 입력 축  (0) 2024.09.10