오늘은 텍스처 관련 데모앱을 분석해보자.

 

우선 데모앱을 실행해보면 텍스처가 적용된 큐브가 보이는데 잘보면 밑부분은 어둡게 되어있어 빛까지 적용된 것을 볼 수 있다. 

이 텍스처와 빛이 코드로 어떻게 구현되어있는지 살펴보자. 기존에는 uv좌표를 통해 텍스처를 매핑해줬었다. 
이때 uv좌표는 텍스처의 비율이라고 보면 된다. 만약 텍스처를 매핑했을 때 잘 떨어지지 않는 부분이 있다면 보간이 이루어지게 된다.

이번 코드에도 보면 SRV를 기반으로 텍스처를 묘사하고 이를 shader쪽에 넘겨줘서 uv좌표를 통해 맵핑을 해주는 것이다.

ComPtr<ID3D11ShaderResourceView> _diffuseMapSRV;

HRESULT hr = ::LoadFromWICFile(L"../Resources/Textures/WoodCrate01.dds", WIC_FLAGS_NONE, &md, img);
CHECK(hr);

// 여러 버전이 있음. (~CreateShaderResourceViewEx)
hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), img.GetImageCount(), md, _diffuseMapSRV.GetAddressOf());
CHECK(hr);

 

shader 코드에서 TEXCOORD부분이 uv좌표를 나타내는 부분이다. 이 uv좌표와 샘플러 함수를 통해 텍스처를 입혀주는 것이다.

struct VertexIn
{
	float3 PosL    : POSITION;
	float3 NormalL : NORMAL;
	float2 Tex     : TEXCOORD;
};

struct VertexOut
{
	float4 PosH    : SV_POSITION;
	float3 PosW    : POSITION;
	float3 NormalW : NORMAL;
	float2 Tex     : TEXCOORD;
};

float4 texColor = float4(1, 1, 1, 1);
if (gUseTexure)
{
	// Sample texture.
	texColor = gDiffuseMap.Sample(samAnisotropic, pin.Tex);
}

 

좀 더 자세히 알아보자

우선 큐브를 만드는 부분에서 uv좌표를 설정해줘야한다.

geoGen.CreateBox(1.0f, 1.0f, 1.0f, box);

 

이 CreateBox함수가 선언된 클래스의 헤더파일 코드를 보면 정점을 정의하는 구조체에서 UV좌표부분이 추가되어 있다. 

struct Vertex
{
	Vertex() : position(0, 0, 0), normal(0, 0, 0), tangentU(0, 0, 0), texC(0, 0) {}
	Vertex(const XMFLOAT3& p, const XMFLOAT3& n, const XMFLOAT3& t, const XMFLOAT2& uv)
		: position(p), normal(n), tangentU(t), texC(uv){}
	Vertex(
		float px, float py, float pz, 
		float nx, float ny, float nz,
		float tx, float ty, float tz,
		float u, float v)
		: position(px,py,pz), normal(nx,ny,nz),
		  tangentU(tx, ty, tz), texC(u,v){}

	XMFLOAT3 position;
	XMFLOAT3 normal;
	XMFLOAT3 tangentU;
	XMFLOAT2 texC;			//UV
};

 

그리고 텍스처를 SRV로 받아서 샘플링할 때도 여러가지 방법이 있는데 이것은 쉐이더 코드의 SamplerState를 통해 정의해줄 수 있다.

SamplerState samAnisotropic
{
	Filter = ANISOTROPIC;
	MaxAnisotropy = 4;

	AddressU = WRAP;		//넘어가면 반복
	AddressV = WRAP;
};

 

이때 조명은 여러 가지 계산을 해보면서 제일 자연스러운 것을 채택하는 것이 좋다. 여기서는 텍스처컬러에 Ambient와 Diffuse값을 더한 부분을 곱해주고 Specular는 이 값에 더해주어서 반짝이는 효과가 텍스처자체 색상에는 영향을 주지 않도록 했다.

// Modulate with late add.
litColor = texColor * (ambient + diffuse) + spec;

 

여기서 만약 파도와 같이 텍스처가 움직이는 모션에 맞춰주려면 uv좌표가 고정된 것이 아닌 변화해야한다. 

v[i].tex.x = 0.5f + _waves[i].x / _waves.Width();
v[i].tex.y = 0.5f - _waves[i].z / _waves.Depth();

 

+ Recent posts