Sampling과 관련된 부분을 실습해 본다.
1. 06. SamplerDemo 클래스 생성하기
탐색기에서 05. TextureDemo를 복제해서 이름을 06. SamplerDemo로 수정한다.
솔루션 탐색기에서 Client/Game 필터에 넣어준다.
코드 내용도 SamplerDemo에 맞게 수정한다.
void SamplerDemo::Init()
{
_shader = make_shared<Shader>(L"05. Sampler.fx");
이 부분도 05. Sampler.fx로 수정한다.
2. 05. Sampler.fx 셰이더 생성하기
탐색기에서 Shaders 폴더의 04. Texture.fx를 복제하여 이름을 05. Sampler.fx로 바꿔준다.
그리고 Main/Shaders로 넣어준다.
SamplerState Sampler0;
샘플링을 했을 때 SamplerState로 여러 옵션을 정해줄 수 있는데, 그 부분을 테스트해본다.
wireframe은 사용 안 할 것이니
RasterizerState FillModeWireFrame
{
FillMode = Wireframe;
};
이 부분은 제거한다.
설정할 수 있는 게 2가지가 있다고 보면 된다.
Filter 관련 부분
Address 관련 부분을 설정할 수 있다.
SamplerState에서 Sampler란 UV좌표에 따라 UV매핑이라는 게 꼭짓점, 정점마다 UV 좌표를 지정해 주면 그거에 맞게끔 텍스쳐를 발라주는 개념이다.
Filter 같은 경우는 만약에 정확하게 이미지 사이즈에 해당하는 메시가 있어서 그 크기에 딱 오려 붙일 수 있으면 좋겠지만 보통은 그렇지 않기 때문에 확대/축소를 할 때 중간값을 처리하는데 필요하다.
Filter = 확대/축소 일어났을 때 중간 값을 처리하는 방식
Address = UV가 1보다 컸을 때, 나머지 부분을 어떻게 처리?
전 시간에 Grid로 테스트한 게 Address와 관련이 있다고 할 수 있다.
사실상 이 Address가 중요하다.
05. Sampler.fx에
uint Address;
이 변수를 만들어서 여기에 값을 세팅한 다음에 이 값을 통해서 뭔가 할 수 있게 만들어 준다.
값을 세팅해서 여러 개 중에서 골라줄 것이다.
1) SamplerState 4개 만들어 주기
SamplerState를 만들어 줄 건데 Sampler0 같은 기본값 아니라 AddressU와 AddressV를 세팅할 수 있게 한다.
SamplerState SamplerAddressWrap
{
// U가 넘어 갔을 때, V가 넘어갔을 때 무엇을 할 것이냐
// 대부분은 둘 다 똑같은 경우로 두는 경우가 많다.
AddressU = Wrap;
AddressV = Wrap;
};
SamplerState SamplerAddressMirror
{
AddressU = Mirror;
AddressV = Mirror;
};
SamplerState SamplerAddressClamp
{
// Clamp는 뭔가 자르는 느낌
AddressU = Clamp;
AddressV = Clamp;
};
SamplerState SamplerAddressBorder
{
// 2D 때 실습해 본 적이 있다.
AddressU = Border;
AddressV = Border;
BorderColor = float4(1, 0, 0, 1);
};
이렇게 SamplerState를 4개 만들어 주고,
2) uint Address값에 따라 SameplerState 선택하게 PS 만들어주기
기존에 있던 PS는 삭제하고 PS를 새롭게 만들어준다.
float4 PS(VertexOutput input) : SV_TARGET
{
if (Address == 0)
return Texture0.Sample(SamplerAddressWrap, input.uv);
if (Address == 1)
return Texture0.Sample(SamplerAddressMirror, input.uv);
if (Address == 2)
return Texture0.Sample(SamplerAddressClamp, input.uv);
if (Address == 3)
return Texture0.Sample(SamplerAddressBorder, input.uv);
return Texture0.Sample(Sampler0, input.uv);
}
추가적인 옵션도 넣을 수 있다.
예를 들어 filter를 테스트하고 싶었다고 하면,
SamplerState SamplerAddressMirror
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Mirror;
AddressV = Mirror;
};
이렇게 추가적인 Filtert 옵션도 정해줄 수 있는데 중간값 보정은 티가 잘 안 나니까 그냥 눈에 띄는 Address 부분만 해본다.
이렇게 4가지 방식 중 하나를 골라주는 것이다.
Technique을 골라 줄 때는 FillModeWireFrame을 삭제했으니 P1는 삭제하고 기본 P0 만 남긴다.
technique11 T0
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS())); // 버전은 5.0, main 함수는 VS다는 뜻
SetPixelShader(CompileShader(ps_5_0, PS()));
}
};
이렇게 세팅이 끝났다.
3. SamplerDemo::Render에서 05. Sampler.fx의 uint Address 값 세팅하기
SamplerDemo::Render에서 추가적으로 Address가 세팅이 되어야 한다.
enum ADDRESS_VALUE
{
ADDRESS_WRAP = 0,
ADDRESS_MIRROR = 1,
ADDRESS_CLAMP = 2,
ADDRESS_BORDER = 3,
};
이걸 이용해서 Shader에다가 세팅해 주면 된다.
_shader->GetScalar("Address")->SetInt(ADDRESS_WRAP);
이렇게 세팅을 해준다.
Main.cpp에서
#include "06. SamplerDemo.h"
를 추가하고
WinMain에서
desc.app = make_shared<SamplerDemo>(); // 실행 단위
이렇게 세팅한다.
4. 테스트하기
1) _shader->GetScalar("Address")->SetInt(ADDRESS_WRAP); 로 세팅한 경우
이게 ADDRESS_WRAP모드이다.
2) _shader->GetScalar("Address")->SetInt(ADDRESS_MIRROR); 로 세팅한 경우
_shader->GetScalar("Address")->SetInt(ADDRESS_MIRROR);
이렇게 세팅을 하면
묘하게 달라졌다.
대칭적으로 바라보는 반사되는 식으로 이루어진다.
3) _shader->GetScalar("Address")->SetInt(ADDRESS_CLAMP); 로 세팅한 경우
ADDRESS_CLAMP로 세팅을 하면
기본값이 ADDRESS_CLAMP인 듯하다.
4) _shader->GetScalar("Address")->SetInt(ADDRESS_BORDER); 로 세팅한 경우
마지막으로 ADDRESS_BORDER로 테스트를 하면
벗어나면 지정한 색으로 밀어줄 것이다.
5) BorderColor를 float4(0, 1, 0, 1); 로 세팅한 경우
만약에 05. Sampler.fx에서
SamplerState SamplerAddressBorder
{
// 2D 때 실습해 본 적이 있다.
AddressU = Border;
AddressV = Border;
BorderColor = float4(0, 1, 0, 1);
};
이렇게 Green으로 설정하고 하면
이렇게 세팅이 되는 걸 볼 수 있다.
void SamplerDemo::Render()
{
// ?
_shader->GetMatrix("World")->SetMatrix((float*)&_world);
_shader->GetMatrix("View")->SetMatrix((float*)&Camera::S_MatView);
_shader->GetMatrix("Projection")->SetMatrix((float*)&Camera::S_MatProjection);
_shader->GetSRV("Texture0")->SetResource(_texture->GetComPtr().Get());
enum ADDRESS_VALUE
{
ADDRESS_WRAP = 0,
ADDRESS_MIRROR = 1,
ADDRESS_CLAMP = 2,
ADDRESS_BORDER = 3,
};
_shader->GetScalar("Address")->SetInt(ADDRESS_BORDER);
uint32 stride = _vertexBuffer->GetStride();
uint32 offset = _vertexBuffer->GetOffset();
// DeviceContext에서 IA단계에서 사용할 VertextBuffer를 묶어주는 함수였다.
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);
}
이렇게 SamplerDemo::Render에서 테스트를 해보았다.
정확히 어떤 값이 뭐였는지 기억을 못 해도 되지만 내가 어떤 게 필요한지 기억해서 적당히 세팅하는 걸 고려할 수 있다.
ADDRESS_WRAP으로 되돌린다.
5. 맺음말
샘플링이란 게 이런 용도였다. UV 좌표랑 관련이 있고, UV비율에 따라서 정점에 맞도록 발라주는 게 Sampler인데
그중에서 Fillter와 Address는 UV가 1보다 컸을 때 나머지 부분을 어떻게 채울 것인가와 관련이 있는 옵션이라는 걸 실습을 통해 알 수 있었다.
만약 2D 때처럼 옵션을 통해서 하면 힘들게 바꿔야 하지만 지금은 편리하게 세팅하면 알아듣고 나머지 부분들이 연동이 되어서 자동으로 고쳐지니 실습할 때도 편리하게 작업할 수 있다.
'DirectX' 카테고리의 다른 글
40. DirectX11 3D 입문_Normal (0) | 2024.02.09 |
---|---|
39. DirectX11 3D 입문_HeightMap (0) | 2024.02.08 |
37. DirectX11 3D 입문_Geometry (0) | 2024.02.06 |
36. DirectX11 3D 입문_텍스처 (0) | 2024.02.06 |
35. DirectX11 3D 입문_카메라 (0) | 2024.02.05 |
댓글