DirectX 11 스터디 - 텍스쳐 UV맵핑 (ShaderResourceView)
이전 노트에서 인덱스버퍼까지 다룸.
이번엔 Shader Resource View 를 생성해서 png 텍스쳐 파일을 로드하고 버텍스컬러 대신 uv 좌표를 입력해서 폴리곤 위에 텍스쳐를 띄워본다.
1. ShaderResourceVIew 생성 / 리소스 로드
2. 셰이더 수정
3. 랜더링 함수 호출
이 순서로 진행.
1. ShaderResourceVIew 생성 / 리소스 로드
ID3D11ShaderResourceView 생성.
이 때 텍스쳐 리소스도 같이 로드.
//
ComPtr<ID3D11ShaderResourceView _shaderResourceView = nullptr;
//
void Game::CreateSRV()
{
// DirectXTex 라이브러리를 사용.
DirectX::TexMetadata md;
DirectX::ScratchImage img;
HRESULT hr = ::LoadFromWICFile(L"Skeleton.png", WIC_FLAGS_NONE, &md, img);
CHECK(hr);
hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), 1, md, _shaderResourceView.GetAddressOf());
CHECK(hr);
}
2. 셰이더 수정
기존 Pixel Shader 에서 버텍스 컬러만 받아서 리턴하던 것을, uv 좌표를 받아 Texture2D 레지스터로 받아서 샘플러를 거쳐 리턴해주도록 하면 됨. Default.hlsl 셰이더를 아래처럼 수정.
struct VS_INPUT
{
float4 position :POSITION;
//float4 color : COLOR;
float2 uv : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position :SV_POSITION;
//float4 color : COLOR;
float2 uv : TEXCOORD;
};
VS_OUTPUT VS(VS_INPUT input)
{
VS_OUTPUT output;
output.position = input.position;
//output.color = input.color;
output.uv = input.uv;
return output;
}
Texture2D texture0 : register(t0); // t0, s0 은 레지스터 이름.
SamplerState sampler0 : register(s0);
float4 PS(VS_OUTPUT input) : SV_Target
{
//return input.color;
//float4 color = ceil(input.color * 5) / 5.0f;
float4 color = texture0.Sample(sampler0, input.uv);
return color;
}
3. 랜더링 함수 호출
이제 Render() 함수로 이동해서, Draw 호출 전에 앞에서 생성한 ShaderResourceView 를 설정해주면 됨. 이 때 셰이더에서 t0 레지스터로 텍스쳐를 받기로 했기 때문에, 첫 번째 인자도 0으로 넘겨준다.
// Pixel Shader
_deviceContext->PSSetShader(_pixelShader.Get(), nullptr, 0);
_deviceContext->PSSetShaderResources(0, 1, _shaderResourceView.GetAddressOf());
여기까지 설정하면 텍스쳐 리소스 로딩부터 uv 맵핑까지 끝.
여기까지 기본 구현은 끝.
ShaderResourceView 를 2개 만들어서 t0, t1 레지스터로 전달해서 텍스쳐를 섞어볼 수도 있음.
ComPtr<ID3D11ShaderResourceView> _shaderResourceView0;
ComPtr<ID3D11ShaderResourceView> _shaderResourceView1;
void Game::CreateSRV()
{
// DirectXTex 라이브러리를 사용.
DirectX::TexMetadata md;
DirectX::ScratchImage img;
HRESULT hr = ::LoadFromWICFile(L"Skeleton.png", WIC_FLAGS_NONE, &md, img);
CHECK(hr);
hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), 1, md, _shaderResourceView0.GetAddressOf());
CHECK(hr);
hr = ::LoadFromWICFile(L"Golem.png", WIC_FLAGS_NONE, &md, img);
CHECK(hr);
hr = ::CreateShaderResourceView(_device.Get(), img.GetImages(), 1, md, _shaderResourceView1.GetAddressOf());
CHECK(hr);
}
_deviceContext->PSSetShaderResources(0, 1, _shaderResourceView0.GetAddressOf());
_deviceContext->PSSetShaderResources(1, 1, _shaderResourceView1.GetAddressOf());
이렇게, Golem.png 를 ShaderResourceView1 객체로 로드해서 Render() 함수에서 연결해주고, 픽셀셰이더 코드를 아래처럼 곱연산으로 섞어주면 아래처럼 보여짐.
<리얼-타임 렌더링(REAL-TIME RENDERING) 4/e> 구입 링크
https://link.coupang.com/a/8VWas
<DirectX 12를 이용한 3D 게임 프로그래밍 입문> 구입 링크
https://link.coupang.com/a/8V4Wq
유니티 에셋 스토어 링크
https://assetstore.unity.com?aid=1011lvz7h
(링크를 통해 도서/에셋 구입시 일정액의 수수료를 지급받습니다.)