수업


주제

  • DirectX11 기반 3D 엔진에서 UV 좌표를 활용한 텍스처 매핑 시스템 구현을 목표로 한다.
  • 정점(Vertex)에 UV 정보를 추가하고, 해당 UV를 기준으로 텍스처 이미지를 렌더링에 반영하는 전체 흐름을 실습한다.
  • Shader(HLSL)에서 텍스처 샘플링을 수행하고, ResourceManager를 통해 텍스처 자원을 효율적으로 관리한다.

개념

  • 텍스처(Texture): 3D 모델의 표면에 입히는 2D 이미지.
  • UV 좌표: 텍스처 이미지의 상대 좌표계. 0.0~1.0 범위를 가지며 U는 가로, V는 세로를 의미.
  • VertexTextureData: 정점의 위치(Vec3)와 UV 좌표(Vec2)를 포함한 구조체.
  • 텍스처 매핑: 정점에 정의된 UV 좌표를 기반으로 해당 위치의 텍스처 이미지를 샘플링하여 픽셀 셰이더에서 색상을 출력하는 과정.
  • ShaderResourceView(SRV): 텍스처를 GPU에 전달하고 HLSL Shader에서 접근할 수 있도록 돕는 인터페이스.
  • SamplerState: 텍스처를 어떻게 샘플링할 것인가(보간, 래핑 등)를 정의하는 상태.
  • ResourceManager: 텍스처 리소스를 효율적으로 로드하고 공유하는 관리자 클래스.

용어정리

용어설명
VertexTextureData위치(Vec3) + UV(Vec2)를 포함한 텍스처용 정점 구조체
UV 좌표텍스처 좌표계 (0,0) ~ (1,1), 왼쪽 위 기준
Texture2DHLSL 셰이더에서 2D 텍스처를 의미
SamplerState샘플링 필터링, 테두리 처리 방식 등을 지정
ShaderResourceViewGPU 리소스를 셰이더에서 접근할 수 있게 하는 객체
RESOURCESResourceManager의 싱글톤 인스턴스를 간편하게 접근할 수 있게 하는 매크로
CreateQuad4개의 정점과 6개의 인덱스를 생성해 사각형을 만드는 헬퍼 함수

코드 분석

✅ Vertex 구조 정의

struct VertexTextureData
{
	Vec3 position = { 0, 0, 0 };
	Vec2 uv = { 0, 0 };
};
  • 정점의 위치와 UV 좌표를 모두 포함해 텍스처 매핑에 필요한 정보를 담는다.

✅ GeometryHelper::CreateQuad

void GeometryHelper::CreateQuad(shared_ptr<Geometry<VertexTextureData>> geometry)
{
	vector<VertexTextureData> vtx(4);

	vtx[0].position = Vec3(-0.5f, -0.5f, 0.f); vtx[0].uv = Vec2(0.f, 1.f);
	vtx[1].position = Vec3(-0.5f,  0.5f, 0.f); vtx[1].uv = Vec2(0.f, 0.f);
	vtx[2].position = Vec3( 0.5f, -0.5f, 0.f); vtx[2].uv = Vec2(1.f, 1.f);
	vtx[3].position = Vec3( 0.5f,  0.5f, 0.f); vtx[3].uv = Vec2(1.f, 0.f);

	geometry->SetVertices(vtx);
	geometry->SetIndices({ 0, 1, 2, 2, 1, 3 });
}
  • 시계 방향으로 4개의 정점 배치
  • UV 좌표를 정확히 설정해 텍스처가 왜곡 없이 사각형 전체에 맵핑되도록 한다

✅ Shader - 04. World.fx

Texture2D Texture0;
SamplerState Sampler0;

VertexOutput VS(VertexInput input)
{
	VertexOutput output;
	output.position = mul(input.position, World);
	output.position = mul(output.position, View);
	output.position = mul(output.position, Projection);
	output.uv = input.uv;
	return output;
}

float4 PS(VertexOutput input) : SV_TARGET
{
	return Texture0.Sample(Sampler0, input.uv);
}
  • VS: 정점 위치를 World → View → Projection 변환하고 UV 좌표 전달
  • PS: 전달받은 UV 좌표를 기준으로 Texture0 텍스처에서 샘플링하여 픽셀 색상 결정

✅ TextureDemo.h

shared_ptr<Geometry<VertexTextureData>> _geometry;
shared_ptr<VertexBuffer> _vertexBuffer;
shared_ptr<IndexBuffer> _indexBuffer;
Matrix _world = Matrix::Identity;
shared_ptr<GameObject> _camera;
shared_ptr<Texture> _texture;
  • 텍스처 렌더링을 위한 구성 요소를 선언
  • _texture는 실제 텍스처 데이터를 관리한다

✅ TextureDemo::Init

_shader = make_shared<Shader>(L"04. World.fx");

_geometry = make_shared<Geometry<VertexTextureData>>();
GeometryHelper::CreateQuad(_geometry);

_vertexBuffer = make_shared<VertexBuffer>();
_vertexBuffer->Create(_geometry->GetVertices());

_indexBuffer = make_shared<IndexBuffer>();
_indexBuffer->Create(_geometry->GetIndices());

_camera = make_shared<GameObject>();
_camera->GetOrAddTransform();
_camera->AddComponent(make_shared<Camera>());
_camera->AddComponent(make_shared<CameraScript>());
_camera->GetTransform()->SetPosition(Vec3(0.f, 0.f, -2.f));

// 텍스처 로드
_texture = RESOURCES->Load<Texture>(L"Veigar", L"..\\Resources\\Textures\\veigar.jpg");
  • Camera + CameraScript 조립
  • ResourceManager를 통해 텍스처 로드 및 캐싱 처리

✅ TextureDemo::Render

_shader->GetMatrix("World")->SetMatrix((float*)&_world);
_shader->GetMatrix("View")->SetMatrix((float*)&Camera::S_MatView);
_shader->GetMatrix("Projection")->SetMatrix((float*)&Camera::S_MatProjection);

// 텍스처 SRV 설정
_shader->GetSRV("Texture0")->SetResource(_texture->GetComPtr().Get());

uint32 stride = _vertexBuffer->GetStride();
uint32 offset = _vertexBuffer->GetOffset();
DC->IASetVertexBuffers(0, 1, _vertexBuffer->GetComPtr().GetAddressOf(), &stride, &offset);
DC->IASetIndexBuffer(_indexBuffer->GetComPtr().Get(), DXGI_FORMAT_R32_UINT, 0);
_shader->DrawIndexed(0, 0, _indexBuffer->GetCount(), 0, 0);
  • ShaderResourceView를 통해 Texture0과 텍스처 자원 연결
  • 정점/인덱스 버퍼 바인딩 후 텍스처가 입혀진 사각형 렌더링

핵심

  1. VertexTextureData 구조체로 위치 + UV 정보를 정의해 텍스처 매핑을 가능하게 한다
  2. CreateQuad 함수에서 UV 좌표를 지정해 정확한 텍스처 위치 매핑을 수행한다
  3. Shader에서는 Texture2D와 SamplerState를 통해 UV 위치에 따라 색상 샘플링
  4. 픽셀 셰이더는 Texture0.Sample(Sampler0, uv)로 색상 결정
  5. ResourceManager를 통해 텍스처 중복 로딩을 방지하고 리소스를 효율적으로 재사용
  6. ShaderResourceView를 통해 텍스처와 셰이더 변수(Texture0)를 연결
  7. Render 함수에서 World/View/Projection 행렬과 텍스처 리소스를 셰이더에 바인딩 후 그리기

profile
李家네_공부방

0개의 댓글