1. 개발 현황

1. Subdivision

2. Draw Normal Vector

 

2. 상세 개발 내용

1. Subdivision

void Subdivide(VertexIn inVerts[3], out VertexIn outVerts[6])
{
    //         1(5)                
    //          *                
    //         / \               
    //        /   \              
    // m0(1) *-----* m1(3)       
    //      / \   / \            
    //     /   \ /   \           
    //    *-----*-----*          
    // 0(0)   m2(2)   2(4)          
    
    VertexIn m[3];
    
    // 각 변의 중점을 계산
    m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL);
    m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL);
    m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL);
    
    // // 단위 구에 투영
    // m[0].PosL = normalize(m[0].PosL);
    // m[1].PosL = normalize(m[1].PosL);
    // m[2].PosL = normalize(m[2].PosL);
    
    // 법선을 유도
    m[0].NormalL = m[0].PosL;
    m[1].NormalL = m[1].PosL;
    m[2].NormalL = m[2].PosL;
    
    // 텍스처 좌표를 보간
    m[0].TexC = 0.5f * (inVerts[0].TexC + inVerts[1].TexC);
    m[1].TexC = 0.5f * (inVerts[1].TexC + inVerts[2].TexC);
    m[2].TexC = 0.5f * (inVerts[2].TexC + inVerts[0].TexC);
    
    outVerts[0] = inVerts[0];
    outVerts[1] = m[0];
    outVerts[2] = m[2];
    outVerts[3] = m[1];
    outVerts[4] = inVerts[2];
    outVerts[5] = inVerts[1];
}

void OutputSubdivision(VertexIn v[6], inout TriangleStream<GeoOut> triStream)
{
    GeoOut gout[6];
    
    [unroll]
    for (int i = 0; i < 6; ++i)
    {
        // world space로 변환
        float4 posW = mul(float4(v[i].PosL, 1.0f), gWorld);
        gout[i].PosW = posW.xyz;
        gout[i].NormalW = mul(v[i].NormalL, (float3x3) gWorldInvTranspose);
        
        // homogeneous clip space로 변환
        gout[i].PosH = mul(posW, gViewProj);
        
        float4 texC = mul(float4(v[i].TexC, 0.0f, 1.0f), gTexTransform);
        gout[i].TexC = mul(texC, gMatTransform).xy;
    }
    //         1(5)                     1(5)                
    //          *                        *                
    //         / \                      / \             <- Strip 2 (1 5 3)
    //        /   \                    /   \              
    // m0(1) *-----* m1(3)  ->  m0(1) *-----* m1(3)       
    //      / \   / \                / \   / \            
    //     /   \ /   \              / 0 \ /   \         <- Strip 1 (0 1 2 3 4) -> (0 1 2) / (1 2 3) / (2 3 4)
    //    *-----*-----*            *-----*-----*          
    // 0(0)   m2(2)   2(4)       0(0)   m2(2)   2(4)          
    
    // 삼각형을 2개의 띠로 그린다.
    // 1. 띠 1: 아래쪽 삼각형 세 개
    // 2. 띠 2: 위쪽 삼각형 1개
    [unroll]
    for (int j = 0; j < 5; ++j)
    {
        triStream.Append(gout[j]);
    }
    triStream.RestartStrip();
    
    triStream.Append(gout[1]);
    triStream.Append(gout[5]);
    triStream.Append(gout[3]);
}

[maxvertexcount(8)]
void main(triangle VertexIn gin[3], inout TriangleStream<GeoOut> triStream)
{
    VertexIn v[6];
    Subdivide(gin, v);
    OutputSubdivision(v, triStream);
}

2. Draw Normal Vector

1) Shader

1.1) Vertex Shader:

모델의 위치 정보 전달

1.2) Geometry Shader

vertex shader에서 전달된 위치, 노멀 정보를 바탕으로, 현재 위치와 노멀 방향으로 이동된 두 점을 만들어 pixel shader로 전달

[maxvertexcount(2)]
void main(point NormalGeometryShaderInput input[1], inout LineStream<NormalPixelShaderInput> outputStream)
{
    NormalPixelShaderInput output;
    
    float4 posW = mul(input[0].PosL, gWorld);
    float4 normalL = float4(input[0].NormalL, 0.0);
    float4 normalW = mul(normalL, gWorldInvTranspose);	// 노멀벡터의 수직 속성을 유지하기 위해 inv transpose 적용
    normalW = float4(normalize(normalW.xyz), 0.0);
    
    output.pos = mul(posW, gViewProj);
    output.color = float3(1.0, 1.0, 0.0);
    outputStream.Append(output);
    
    output.pos = mul(posW + lineScale * normalW, gViewProj);
    output.color = float3(1.0, 0.0, 0.0);
    outputStream.Append(output);
}

1.3) Pixel Shader

전달된 위치 정보에 맞춰 색 출력

 

2) PSO 설정

구현한 Shader와 쌍이 맞는 PrimitiveTopologyType을 선택해주어 오류가 발생하지 않도록 한다. (D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT)

D3D12_GRAPHICS_PIPELINE_STATE_DESC normalPsoDesc
{
    /* ID3D12RootSignature* pRootSignature                              */.pRootSignature = mRootSignature.Get(),
    /* D3D12_SHADER_BYTECODE VS                                         */.VS = {reinterpret_cast<BYTE*>(mShaders["normalVS"]->GetBufferPointer()), mShaders["normalVS"]->GetBufferSize()},
    /* D3D12_SHADER_BYTECODE PS                                         */.PS = {reinterpret_cast<BYTE*>(mShaders["normalPS"]->GetBufferPointer()), mShaders["normalPS"]->GetBufferSize()},
    /* D3D12_SHADER_BYTECODE DS                                         */.DS = {NULL, 0},
    /* D3D12_SHADER_BYTECODE HS                                         */.HS = {NULL, 0},
    /* D3D12_SHADER_BYTECODE GS                                         */.GS = {reinterpret_cast<BYTE*>(mShaders["normalGS"]->GetBufferPointer()), mShaders["normalGS"]->GetBufferSize()},,
    /* D3D12_STREAM_OUTPUT_DESC StreamOutput{                           */.StreamOutput = {
    /*      const D3D12_SO_DECLARATION_ENTRY* pSODeclaration{           */  NULL,
    /*          UINT Stream;                                            */
    /*          LPCSTR SemanticName;                                    */
    /*          UINT SemanticIndex;                                     */
    /*          BYTE StartComponent;                                    */
    /*          BYTE ComponentCount;                                    */
    /*          BYTE OutputSlot;                                        */
    /*      }                                                           */
    /*      UINT NumEntries;                                            */  0,
    /*      const UINT* pBufferStrides;                                 */  0,
    /*      UINT NumStrides;                                            */  0,
    /*      UINT RasterizedStream;                                      */  0
    /* }                                                                */},
    /* D3D12_BLEND_DESC BlendState{                                     */.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT),
    /*      BOOL AlphaToCoverageEnable                                  */
    /*      BOOL IndependentBlendEnable                                 */
    /*      D3D12_RENDER_TARGET_BLEND_DESC RenderTarget[8]              */
    /* }                                                                */
    /* UINT SampleMask                                                  */.SampleMask = UINT_MAX,
    /* D3D12_RASTERIZER_DESC RasterizerState{                           */.RasterizerState = { // CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
    /*      D3D12_FILL_MODE FillMode                                    */      D3D12_FILL_MODE_SOLID, // D3D12_FILL_MODE_WIREFRAME,
    /*      D3D12_CULL_MODE CullMode                                    */      D3D12_CULL_MODE_BACK,
    /*      BOOL FrontCounterClockwise                                  */      false,
    /*      INT DepthBias                                               */      D3D12_DEFAULT_DEPTH_BIAS,
    /*      FLOAT DepthBiasClamp                                        */      D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
    /*      FLOAT SlopeScaledDepthBias                                  */      D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
    /*      BOOL DepthClipEnable                                        */      true,
    /*      BOOL MultisampleEnable                                      */      false,
    /*      BOOL AntialiasedLineEnable                                  */      false,
    /*      UINT ForcedSampleCount                                      */      0,
    /*      D3D12_CONSERVATIVE_RASTERIZATION_MODE ConservativeRaster    */      D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
    /* }                                                                */},
    /* D3D12_DEPTH_STENCIL_DESC DepthStencilState {                     */.DepthStencilState = { // CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
    /*      BOOL DepthEnable                                            */      .DepthEnable = true,
    /*      D3D12_DEPTH_WRITE_MASK DepthWriteMask                       */      .DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL,
    /*      D3D12_COMPARISON_FUNC DepthFunc                             */      .DepthFunc = D3D12_COMPARISON_FUNC_LESS,
    /*      BOOL StencilEnable                                          */      .StencilEnable = false,
    /*      UINT8 StencilReadMask                                       */      .StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK,
    /*      UINT8 StencilWriteMask                                      */      .StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK,
    /*      D3D12_DEPTH_STENCILOP_DESC FrontFace {                      */      .FrontFace = {
    /*          D3D12_STENCIL_OP StencilFailOp                          */          .StencilFailOp = D3D12_STENCIL_OP_KEEP,
    /*          D3D12_STENCIL_OP StencilDepthFailOp                     */          .StencilDepthFailOp = D3D12_STENCIL_OP_KEEP,
    /*          D3D12_STENCIL_OP StencilPassOp                          */          .StencilPassOp = D3D12_STENCIL_OP_KEEP,
    /*          D3D12_COMPARISON_FUNC StencilFunc                       */          .StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS
    /*      }                                                           */      },
    /*      D3D12_DEPTH_STENCILOP_DESC BackFace                         */      .BackFace = {
    /*          D3D12_STENCIL_OP StencilFailOp                          */          .StencilFailOp = D3D12_STENCIL_OP_KEEP,
    /*          D3D12_STENCIL_OP StencilDepthFailOp                     */          .StencilDepthFailOp = D3D12_STENCIL_OP_KEEP,
    /*          D3D12_STENCIL_OP StencilPassOp                          */          .StencilPassOp = D3D12_STENCIL_OP_KEEP,
    /*          D3D12_COMPARISON_FUNC StencilFunc                       */          .StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS
    /*      }                                                           */      },
    /* }                                                                */ },
    /* D3D12_INPUT_LAYOUT_DESC InputLayout{                             */.InputLayout = {
    /*      const D3D12_INPUT_ELEMENT_DESC* pInputElementDescs          */      .pInputElementDescs = mInputLayout.data(),
    /*      UINT NumElements                                            */      .NumElements = (UINT)mInputLayout.size()
    /*  }                                                               */ },
    /* D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue               */.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED,
    /* D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType              */.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, // D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
    /* UINT NumRenderTargets                                            */.NumRenderTargets = 1,
    /* DXGI_FORMAT RTVFormats[8]                                        */.RTVFormats = {mBackBufferFormat, DXGI_FORMAT_UNKNOWN,DXGI_FORMAT_UNKNOWN,DXGI_FORMAT_UNKNOWN,DXGI_FORMAT_UNKNOWN,DXGI_FORMAT_UNKNOWN,DXGI_FORMAT_UNKNOWN,DXGI_FORMAT_UNKNOWN},   // 0
    /* DXGI_FORMAT DSVFormat                                            */.DSVFormat = mDepthStencilFormat,
    /* DXGI_SAMPLE_DESC SampleDesc{                                     */.SampleDesc = {
    /*      UINT Count;                                                 */      .Count = m4xMsaaState ? 4u : 1u,
    /*      UINT Quality;                                               */      .Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0
    /*  }                                                               */},
    /* UINT NodeMask                                                    */.NodeMask = 0,
    /* D3D12_CACHED_PIPELINE_STATE CachedPSO                            */.CachedPSO = {NULL, 0},
    /* D3D12_PIPELINE_STATE_FLAGS Flags                                 */.Flags = D3D12_PIPELINE_STATE_FLAG_NONE
};

3. TODO

- Subdivision 동작 중 Texture 좌표 전달 오류 수정

 

4. 참고자료

- Introduction to 3D Game Programming with DirectX 12, Luna, Frank (2016)

 

728x90
반응형

+ Recent posts