SamplerState 설정을 통해 UV 좌표가 범위를 벗어났을 때 Wrap, Mirror, Clamp, Border 방식으로 각각 어떻게 시각적으로 출력되는지를 확인하고,Address 값을 통해 픽셀 셰이더에서 동적으로 샘플링 방식을 변경하는 구조를 구현한다.텍스처 샘플링(Sampling): 픽셀 셰이더에서 텍스처와 UV 좌표를 통해 특정 위치의 색상을 추출하는 과정.
SamplerState: HLSL에서 텍스처 샘플링에 사용할 Filter (보간 방식)와 Address Mode (UV 초과 처리 방식)을 정의하는 상태 객체.
Filter: 텍스처가 확대되거나 축소될 때 중간 색상(보간값)을 어떻게 계산할지 결정함.
Address Mode: 텍스처 좌표(UV)가 0~1의 범위를 벗어났을 때 어떤 방식으로 텍스처를 표시할지를 지정함.
각 Address Mode는 다음과 같은 특징을 가진다:
| 모드 | 설명 |
|---|---|
| Wrap | UV > 1 일 때 텍스처가 반복됨 |
| Mirror | UV > 1 일 때 대칭적으로 반사되어 반복됨 |
| Clamp | 텍스처 가장자리 픽셀이 고정된 상태로 계속 채워짐 |
| Border | 텍스처 범위를 벗어난 영역은 지정한 색상(BorderColor)으로 채워짐 |
| 용어 | 설명 |
|---|---|
| UV 좌표 | 텍스처 매핑에 사용되는 2D 정규 좌표계. (0,0)~(1,1) 범위를 갖는다 |
| SamplerState | 텍스처 샘플링 방식과 UV 초과 처리 방식을 정의하는 HLSL 상태 객체 |
| Address Mode | UV 범위를 벗어난 좌표의 처리 방식 (Wrap, Mirror, Clamp, Border) |
| Filter | 확대/축소 시 보간 처리 방식 (예: Linear, Point 등) |
| BorderColor | Border 모드 사용 시 텍스처 외 영역을 채우는 색상 |
| Shader Resource View (SRV) | GPU 텍스처 자원을 셰이더에 전달할 때 사용하는 인터페이스 |
Sampler.fxmatrix World;
matrix View;
matrix Projection;
Texture2D Texture0;
uint Address;
struct VertexInput {
float4 position : POSITION;
float2 uv : TEXCOORD;
};
struct VertexOutput {
float4 position : SV_POSITION;
float2 uv : TEXCOORD;
};
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;
}
SamplerState SamplerAddressWrap {
AddressU = Wrap;
AddressV = Wrap;
};
SamplerState SamplerAddressMirror {
AddressU = Mirror;
AddressV = Mirror;
};
SamplerState SamplerAddressClamp {
AddressU = Clamp;
AddressV = Clamp;
};
SamplerState SamplerAddressBorder {
AddressU = Border;
AddressV = Border;
BorderColor = float4(1, 0, 0, 1); // 붉은색으로 외곽 표시
};
BorderColor는 오직 Border 모드에서만 적용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(SamplerAddressClamp, input.uv); // 기본값
}
Address 값에 따라 어떤 SamplerState를 사용할지를 분기technique11 T0 {
pass P0 {
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
};
SamplerDemo::Render()enum ADDRESS_VALUE {
ADDRESS_WRAP = 0,
ADDRESS_MIRROR = 1,
ADDRESS_CLAMP = 2,
ADDRESS_BORDER = 3
};
// 행렬 및 텍스처 바인딩
_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());
// 샘플링 모드 선택
_shader->GetScalar("Address")->SetInt(ADDRESS_WRAP); // 테스트 시 0~3 변경 가능
// 정점/인덱스 버퍼 바인딩 및 드로우
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);
enum과 SetInt()를 이용해 Sampler.fx에 설정된 Address 값 전달SamplerState를 선언하고, AddressU/AddressV를 Wrap, Mirror, Clamp, Border로 설정한다.Filter는 확대/축소 시 중간값을 보간하는 방식이지만, 시각적인 차이는 Address보단 미묘하므로 실습에선 Address 위주로 테스트.GetScalar("Address")->SetInt()를 통해 Address 값을 실시간으로 셰이더에 전달한다.