일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 다익스트라
- String
- Trie
- Stored Procedure
- SQL
- Brute Force
- DP
- 스토어드 프로시저
- Dijkstra
- 그래프
- Two Points
- Hash
- MYSQL
- 이진탐색
- union find
- binary search
- two pointer
- Today
- Total
codingfarm
29. 스텐실 적용(Stenciling) 본문
0. 개요
- 용도 : 특정 픽셀 단편(pixel fragment)들이 back buffer에 기록되지 못하게 한다.
- 실제 판화를 만들때 쓰이는 스텐실과 같은 역할
- depth buffer에도 기록하지 못하게 함
- stencil buffer는 back buffer 및 depth buffer와 해상도가 같다
- stencil buffer의 $ij$번째 픽셀은 back buffer나 depth buffer의 $ij$번째 픽셀과 대응된다
- stencil buffer를 지정 하면 그 버퍼는 depth buffer에 부착된다.(즉, 이후의 작업에서 서로 연관된다)
D3D12_DEPTH_STENCIL_DESC 구조체를 채우고 이것을 PSO의 D3D12_GRAPHICS_PIPELINE_STATE_DESC::DepthStencilState 필드에 설정하여 stencil buffer를 depth buffer와 함께 설정할 수 있다.
1. Depth/Stencil Formats and Clearing
depth/stencil buffer는 하나의 텍스처이다. 이를 생성하기 위해선 아래와 같은특정한 자료형식을 지정해야한다
DXGI_FORMAT_<depth type>_<stencil type>
사용 가능한 DXGI_FORMAT형식의 예는 아래와 같다.
- DXGI_FORMAT_D32_FLOAT_S8X24_UINT
- depth : 32bit 부동 소수점
- stencil : [0, 255] 구간의 8bit 부호없는 정수 스텐실
- other : 24bit의 채움(pading) 용으로 쓰이는 용도 없는 데이터
- DXGI_FORMAT_D24_UNORM_S8_UINT
- depth : [0, 1]로 사상되는 부호없는 24bit 값
- stencil : [0, 255]로 사상되는 부호없는 8bit 정수 값
depth/stencil buffer의 type 은 D3D12_DEPTH_STENCIL_VIEW_DESC의 format 필드에 설정하면된다
1
2
3
|
DXGI_FORMAT mDepthStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
dsvDesc.Format = mDepthStencilFormat;
|
cs |
1-1. Clear
Stencil buffer는 depth buffer와 함께 각 프레임의 시작에서 특정한 값으로 재설정 해야한다. 재 설정에 쓰이는 함수는 아래와 같다.
1
2
3
4
5
6
7
8
|
void ID3D12GraphicsCommandList::ClearDepthStencilView(
D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView,
D3D12_CLEAR_FLAGS ClearFlags,
FLOAT Depth,
UINT8 Stencil,
UINT NumRects,
const D3D12_RECT *pRects
);
|
cs |
이 함수는 이미 예전부터 아래처럼 호출해 왔다
1
2
3
|
mCommandList->ClearDepthStencilView(DepthStencilView(),
D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL,
1.0f, 0, 0, nullptr);
|
cs |
depth를 1.0f로, stencil을 0으로 설정하도록 cmd list에 명령을 넣는다.
2. 스텐실 판정(The Stencil Test)
stencil buffer를 이용하여 주어진 한 픽셀이 후면 버퍼에 기록될지 아닐지를 판정하는 의사코드는 아래와 같다.
1
2
3
4
|
if( StencilRef & StencilReadMask $\underline{\triangleleft }$ Value & StencilReadMask )
픽셀 허용
else
픽셀 기각
|
cs |
스텐실 판정 타이밍 : 필셀이 래스터화 되는 과정(출력 병합기 단계)
$\underline{\triangleleft }$ : 응용 프로그램이 선택한 비교 함수
StencilRef : 스텐실 기준 값
Value : 스텐실 버퍼에 이미 있던 픽셀의 값
StencilReadMask : 응용 프로그램이 지정한 마스킹 값
StencilReadMask, $\underline{\triangleleft }$는 D3D12_DEPTH_STENCIL_DESC 구조체에서 설정하며
Value는 Stencil Buffer에 저장되어 있는 값으로 ClearDepthStencilView 메서드로 초기화 가능하다.
StencilRef는 ID3D12GraphicsCommandList::OMSetStencilRef 메서드로 초기화 한다
스텐실 기준값 설정
1
2
3
4
5
6
|
void OMSetStencilRef(
UINT StencilRef
);
mCommandList->OMSetStencilRef(1);
|
cs |
이 함수를 통해 스텐실 판정에서의 Value 변수를 설정한다.
Value 변수는 스텐실 판정에 사용됨가 동시에 D3D12_DEPTH_STENCILOP_DESC 의 D3D12_STENCIL_OP type 필드에 D3D12_STENCIL_OP_REPLACE를 적용 했을때, 판정 성공시 stencil buffer에 작성될 값으로도 쓰인다.
비교 연산자($\underline{\triangleleft }$)
D3D12_COMPARISON_FUNC 열거형에 정의된 것 중 하나를 사용
1
2
3
4
5
6
7
8
9
10
|
typedef enum D3D12_COMPARISON_FUNC {
D3D12_COMPARISON_FUNC_NEVER,
D3D12_COMPARISON_FUNC_LESS,
D3D12_COMPARISON_FUNC_EQUAL,
D3D12_COMPARISON_FUNC_LESS_EQUAL,
D3D12_COMPARISON_FUNC_GREATER,
D3D12_COMPARISON_FUNC_NOT_EQUAL,
D3D12_COMPARISON_FUNC_GREATER_EQUAL,
D3D12_COMPARISON_FUNC_ALWAYS
} ;
|
cs |
1. D3D12_COMPARISON_NEVER: The function always returns false.
2. D3D12_COMPARISON_LESS: Replace $\underline{\triangleleft }$ with the < operator.
3. D3D12_COMPARISON_EQUAL: Replace $\underline{\triangleleft }$ with the == operator.
4. D3D12_COMPARISON_LESS_EQUAL: Replace $\underline{\triangleleft }$ with the ≤ operator.
5. D3D12_COMPARISON_GREATER: Replace $\underline{\triangleleft }$ with the > operator.
6. D3D12_COMPARISON_NOT_EQUAL: Replace $\underline{\triangleleft }$ with the ! = operator.
7. D3D12_COMPARISON_GREATER_EQUAL: Replace $\underline{\triangleleft }$ with the ≥ operator.
8. D3D12_COMPARISON_ALWAYS: The function always returns true.
3. Depth/Stencil 상태 서술
Depth/Stencil 상태는 D3D12_DEPTH_STENCIL_DESC 구조체를 채워서 서술한다.
1
2
3
4
5
6
7
8
9
10
|
typedef struct D3D12_DEPTH_STENCIL_DESC {
BOOL DepthEnable;
D3D12_DEPTH_WRITE_MASK DepthWriteMask;
D3D12_COMPARISON_FUNC DepthFunc;
BOOL StencilEnable;
UINT8 StencilReadMask;
UINT8 StencilWriteMask;
D3D12_DEPTH_STENCILOP_DESC FrontFace;
D3D12_DEPTH_STENCILOP_DESC BackFace;
} D3D12_DEPTH_STENCIL_DESC;
|
cs |
depth 상태와 stencil 상태를 하나의 서술형 구조체에서 설정하며, 상단의 3개는 depth 관련 설정, 하단의 5개는 stencil 관련 설정이다.
깊이 설정
1. BOOL DepthEnable
depth buffering의 활성화 여부를 설정한다.
FALSE : 깊이 판정 X, 판정 자체를 하지 않으므로 DepthWriteMask에 어떤 설정이 되었든 쓰기도 하지 않는다.
2. D3D12_DEPTH_WRITE_MASK DepthWriteMask
depth buffer에 대한 쓰기 활성화 여부를 설정
D3D12_DEPTH_WRITE_MASK_ZERO 혹은 D3D12_DEPTH_WRITE_MASK_ALL 둘중 하나를 지정한다.
D3D12_DEPTH_WRITE_MASK_ZERO : 쓰기가 비활성화됨
D3D12_DEPTH_WRITE_MASK_ALL : 쓰기가 활성화 됨
DepthEnable이 활성화 되었다면 깊이 판정 자체는 여전히 유효하며, 비활성화 되었다면 이 필드에는 어떤 값을 설정하든 무효하다.
3. D3D12_COMPARISON_FUNC DepthFunc
깊이 판정에 쓰이는 비교 함수를 결정하는 필드
D3D12_COMPARISON_FUNC의 열거형 멤버중 하나를 설정, 통상적인 깊이판정에서는 D3D12_COMPARISON_FUNC_LESS를 설정함
스텐실 설정
4. BOOL StencilEnable
스텐실 판정에 대한 활성화, 비활성화 여부를 결정
5. UINT8 StencilReadMask
이전에 살펴봤던 스텐실 판정 의사코드의 StencilReadMask에 해당하는 값을 설정
기본값은 아래와 같다
1
|
#define D3D12_DEFAULT_STENCIL_READ_MASK (0xff)
|
cs |
이는 어떤 비트도 마스킹(0으로 설정) 하지 않는것에 해당
6. UINT8 StencilWriteMask
스텐실 버퍼 갱신시 특정 비트 값들이 기록되지 않게 하는 비트 마스크
가령 최상위 비트 네개가 기록되지 않게 하려면 0x0f를 사용한다.
기본값은 아래처럼 어떤 비트도 막지 않는 마스크다
1
|
#define D3D12_DEFAULT_STENCIL_WRITE _MASK (0xff)
|
cs |
7. D3D12_DEPTH_STENCILOP_DESC FrontFace, BackFace
전면/후면 삼각형에 대한 스텐실 버퍼 적용 방식을 서술하는 구조체를 지정
1
2
3
4
5
6
|
typedef struct D3D12_DEPTH_STENCILOP_DESC {
D3D12_STENCIL_OP StencilFailOp;
D3D12_STENCIL_OP StencilDepthFailOp;
D3D12_STENCIL_OP StencilPassOp;
D3D12_COMPARISON_FUNC StencilFunc;
} D3D12_DEPTH_STENCILOP_DESC;
|
cs |
1. D3D12_STENCIL_OP StencilFailOp
픽셀 단편이 스텐실 판정에 실패했을 때 스텐실 버퍼를 갱신하는 방식을 결정하는 필드
2. D3D12_STENCIL_OP StencilDepthFailOp
스텐실 판정을 통과 했지만 깊이 판정에는 실패 했을때 스텐실 버퍼를 갱신하는 방식을 결정하는 필드
3. D3D12_STENCIL_OP StencilPassOp
픽셀 단편이 스텐실 판정과 깊이 판정을 모두 통과했을 때 스텐실 버퍼를 갱신하는 방식을 결정하는 필드
4. D3D12_COMPARISON_FUNC StencilFunc
스텐실 판정 비교 함수를 결정하는 멤버
1-3. Depth/Stencil 상태의 생성 및 묶기
깊이/스텐실 버퍼를 서술하는 D3D12_DEPTH_STENCIL_DESC 구조체를 다 채웠다면, 그것을 PSO의 D3D12_GRAPHICS_PIPELINE_STATE_DESC::DepthStencilState 필드에 배정하면 된다.
그 PSO와 함께 렌더링되는 모든 기하구조에는 해당 깊이/스텐실 버퍼 설정들이 적용된다.
'computer graphics > DirectX12' 카테고리의 다른 글
30. 계산 셰이더(Compute Shader) - 작성중 (0) | 2021.10.17 |
---|---|
28. 혼합(Blending) - 작성 중 (0) | 2021.09.27 |
27-1. 텍스처적용 예제 코드 (0) | 2021.09.22 |
27. 텍스처 적용(Texturing) (0) | 2021.09.19 |
26. 좌표 변환 (0) | 2021.08.23 |