
Geometry Shader는 기하 정보를 더 자세하게 만드는 쉐이더이다.
글로만 보면 잘 이해가 안되니 코드를 살펴보자.
m_constantData.width = 2.4f;
D3D11Utils::CreateConstantBuffer(device, m_constantData, m_constantBuffer);
// Geometry shader 초기화하기
D3D11Utils::CreateGeometryShader(
device, L"BillboardPointsGeometryShader.hlsl", m_geometryShader);
Geometry Shader 역시 ConstantBuffer을 사용할 수 있기 때문에 GeometryShader을 위한 ConstantBuffer을 만들고
VS, PS와 같은 방식으로 CreateGeometryShader을 한다. gs_5_0를 버전으로 쓰는 것 제외하고 내부 코드도 비슷하다.
context->GSSetConstantBuffers(0, 1, m_constantBuffer.GetAddressOf());
context->GSSetShader(m_geometryShader.Get(), 0, 0);
//.. drawIndexed or draw 이후
context->GSSetShader(nullptr, 0, 0);
Render에서 GSSetConstantBuffers와 GSSetShader을 하는 것도 동일하다. 한번 Geomtry Shader을 Set하면
다른 GeometryShader을 사용하지 않는 물체에도 적용될 수 있기 때문에 draw 이후에 nullptr로 세팅해줘야 한다.
struct PixelShaderInput
{
float4 pos : SV_POSITION; // not POSITION
float2 texCoord : TEXCOORD; // 텍스춰 좌표 추가
uint primID : SV_PrimitiveID;
};
쉐이더를 보면, GeometryShader.hlsl에서 SV_PrimitiveID라는 Semantics가 새로 등장했다.
SV_PrimitiveID는 래스터라이즈를 할 때 가장 기본이 되는 최소 단위이다.
최소 단위가 Point라면 몇번째 Point인지 삼각형이라면 몇번째 삼각형인지 지정해줄 수 있다.
[maxvertexcount(4)]
void main(point GeometryShaderInput input[1], uint primID : SV_PrimitiveID,
inout PointStream<PixelShaderInput> outputStream)
쉐이더의 메인 함수도 VS, PS와는 조금 다르다. 먼저 [maxvertexcount]는 GS가 만들어낼 수 있는 정점의 최대 개수이다.
GeomtryShaderInput은 GS에 입력하는 정보, PointStream<PixelShaderInput>은 GS에서 출력하는 정보이다.
현재는 PrimitiveTopology가 POINTLIST로 정점 1개씩 받고 있으므로 input 안의 대괄호가 [1]이고 출력 형태 역시
PointStream이다. 삼각형을 출력할 경우 TriangleStream이 된다.
PixelShaderInput output;
output.pos = input[0].pos;
for (int i = 0; i < 100; i ++)
{
output.pos = input[0].pos + float4(0.0, 0.003, 0.0, 0.0) * float(i);
output.pos = mul(output.pos, view);
output.pos = mul(output.pos, proj);
output.primID = primID;
outputStream.Append(output);
}
main 내부는 output에 정보를 추가해서 ouputStream에 출력될 정점들을 하나씩 추가하는 형식이다.
출력형식을 PointStream에서 TriangleStream으로 바꾸면 GS에서 삼각형을 그릴 수 있는데, GS는
TriangleStrip 방식으로 삼각형을 그리기 때문에 정점 3개로 삼각형 1개, 정점 4개로 삼각형 2개를 그릴 수 있다.
기존대로 정점 6개로 삼각형 2개를 그리는 TriangleList 방식을 사용하고 싶다면, 정점 3개로 삼각형을 하나 그리고,
outputStream.RestartStrip() 함수를 이용해 다시 정점3개로 삼각형을 그릴 수 있다.
'그래픽스' 카테고리의 다른 글
| [그래픽스] Mipmap, LOD (0) | 2023.07.21 |
|---|---|
| [그래픽스] Hull Shader, Tessellation, Domain Shader (0) | 2023.07.21 |
| [그래픽스] 쿼터니언(실습) (0) | 2023.07.19 |
| [그래픽스] 쿼터니언(이론) (0) | 2023.07.19 |
| [그래픽스] Picking (렌더타겟 2개 이용, GPU->CPU로 데이터 복사) (0) | 2023.07.19 |