Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Archives
Today
Total
관리 메뉴

codingfarm

29. 스텐실 적용(Stenciling) 본문

computer graphics/DirectX12

29. 스텐실 적용(Stenciling)

scarecrow1992 2021. 10. 3. 21:35

 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에 부착된다.(즉, 이후의 작업에서 서로 연관된다)

[좌 : 반전시킨 해골을 그대로 출력, 우 : 거울이 없는곳을 stencil 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형식의 예는 아래와 같다.

  1. DXGI_FORMAT_D32_FLOAT_S8X24_UINT 
    • depth : 32bit 부동 소수점
    • stencil : [0, 255] 구간의 8bit 부호없는 정수 스텐실
    • other : 24bit의 채움(pading) 용으로 쓰이는 용도 없는 데이터
  2. 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, 00, 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
Comments