포스트

[ Dx11 ] (solution) 모션 블러 속도 최적화

문제


레퍼런스인 accumulation과 depthpeeling의 속도 차이를 비교했을 때, 아래와 같은 결과가 나왔다. 이는 그냥 단순히 여러 번 이미지를 그리는 것보다 느리므로, depthpeeling 알고리즘에 문제가 있다는 결론이므로, 이를 해결하기 위해 알고리즘을 수정했다.

해결


기존 알고리즘에서 아래와 같이 depthpeeling layer 별 이미지를 생성했다. 그러나 레이어의 크기가 클 수록 이는 기하급수적으로 증가하여 단순한 accumulation 보다 낮은 성능을 보이게 된다. 따라서 이를 해결하기 위해 알고리즘을 수정했다.

depthpeeling 이미지는 처음 렌더링 후, 다음 레이어 렌더링을 위해 이전 정보가 존재해야한다. 따라서 레이어 정보를 저장하였으나, 렌더링에 실질적으로 필요한 것은 이전 레이어와 현재 레이어 정보 2가지이다. 따라서 이 2개만을 활용, 렌더링에 사용함으로써 성능을 높였다.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

void DepthPeeling(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext)
{

    //-----------------------------------------------------------------------------
    // 	   1PASS:	Clear Texture
    //-----------------------------------------------------------------------------

    g_pDepthPeelingTech = g_pDepthPeelingEffect->GetTechniqueByName("ClearTexture");
    g_pDepthPeelingTech->GetPassByIndex(0)->Apply(0, pd3dImmediateContext);

    pd3dImmediateContext->OMSetRenderTargets(N_LAYER, g_pColorMap_RenderingClass->ppRTVs, NULL);
    g_pFSQ->RenderFSQ(pd3dImmediateContext, g_pLayout, g_pDepthPeelingTech, techDesc, g_pDepthPeelingEffect);

    pd3dImmediateContext->OMSetRenderTargets(N_LAYER, g_pMotionVectorMap_RenderingClass->ppRTVs, NULL);
    g_pFSQ->RenderFSQ(pd3dImmediateContext, g_pLayout, g_pDepthPeelingTech, techDesc, g_pDepthPeelingEffect);

    pd3dImmediateContext->OMSetRenderTargets(1, g_pMotionVectorSquareMap_RenderingClass->ppRTVs, NULL);
    g_pFSQ->RenderFSQ(pd3dImmediateContext, g_pLayout, g_pDepthPeelingTech, techDesc, g_pDepthPeelingEffect);


    pd3dImmediateContext->OMSetRenderTargets(N_LAYER, g_pNormalMap_RenderingClass->ppRTVs, NULL);
    g_pFSQ->RenderFSQ(pd3dImmediateContext, g_pLayout, g_pDepthPeelingTech, techDesc, g_pDepthPeelingEffect);

    //-----------------------------------------------------------------------------
    // 	   2PASS:	DepthPeeling Render
    //-----------------------------------------------------------------------------

    //g_pSkybox->BeforeFrameRender(g_Camera.GetViewMatrix(), g_Camera.GetProjMatrix(), 10.0f, 0.0f, 0.0f, 0.f);
    //g_pSkybox->Render(pd3dImmediateContext, g_pLayout, g_pDepthPeelingTech, techDesc, g_pDepthPeelingEffect);

    ID3D11ShaderResourceView* DepthBuffer_SRVs[] =
    {
        g_pDepthBuffer_RenderingClass[0]->GetShaderResourceView(),
        g_pDepthBuffer_RenderingClass[1]->GetShaderResourceView()
    };

    ID3D11DepthStencilView* DepthBuffer_DSVs[] =
    {
        g_pDepthBuffer_RenderingClass[0]->GetDepthStencilView(),
        g_pDepthBuffer_RenderingClass[1]->GetDepthStencilView()
    };

    pd3dImmediateContext->ClearDepthStencilView(DepthBuffer_DSVs[1], D3D11_CLEAR_DEPTH, 0.0, 0);

    for (int layer = 0; layer < N_LAYER; layer++)
    {
        int currId = layer % 2;
        int prevId = 1 - currId;

        if (layer == 0)
        {
            ID3D11RenderTargetView* Layers_RTVs[] =
            {
                g_pColorMap_RenderingClass->ppRTVs[layer],
                g_pMotionVectorMap_RenderingClass->ppRTVs[layer],
                g_pMotionVectorSquareMap_RenderingClass->ppRTVs[layer],
                g_pNormalMap_RenderingClass ->ppRTVs[layer]
            };

            pd3dImmediateContext->ClearDepthStencilView(DepthBuffer_DSVs[currId], D3D11_CLEAR_DEPTH, 1.0, 0);
            //pd3dImmediateContext->OMSetRenderTargets(3, Layers_RTVs, NULL);

            pd3dImmediateContext->OMSetRenderTargets(4, Layers_RTVs, NULL);

            //g_pDepthPeelingTech = g_pDepthPeelingEffect->GetTechniqueByName("DepthPeelingRendering");
            g_pDepthPeelingTech = g_pDepthPeelingEffect->GetTechniqueByName("DepthPeelingRenderingWithSkybox");
            g_pDepthPeelingTech->GetPassByIndex(0)->Apply(0, pd3dImmediateContext);
            g_effectSRV_depthBuffer->SetResource(DepthBuffer_SRVs[prevId]);
            //pd3dImmediateContext->OMSetRenderTargets(3, Layers_RTVs, DepthBuffer_DSVs[currId]);

            pd3dImmediateContext->OMSetRenderTargets(4, Layers_RTVs, DepthBuffer_DSVs[currId]);

            boxDrawing = true;
            renderPerObjects(pd3dImmediateContext, g_pDepthPeelingTech, g_pDepthPeelingEffect);

        }

        else
        {
            ID3D11RenderTargetView* Layers_RTVs[] =
            {
                g_pColorMap_RenderingClass->ppRTVs[layer],
                g_pMotionVectorMap_RenderingClass->ppRTVs[layer],
                g_pNormalMap_RenderingClass->ppRTVs[layer]
            };

            pd3dImmediateContext->ClearDepthStencilView(DepthBuffer_DSVs[currId], D3D11_CLEAR_DEPTH, 1.0, 0);
            //pd3dImmediateContext->OMSetRenderTargets(2, Layers_RTVs, NULL);
            pd3dImmediateContext->OMSetRenderTargets(3, Layers_RTVs, NULL);

            g_pDepthPeelingTech = g_pDepthPeelingEffect->GetTechniqueByName("DepthPeelingRendering");
            g_pDepthPeelingTech->GetPassByIndex(0)->Apply(0, pd3dImmediateContext);
            g_effectSRV_depthBuffer->SetResource(DepthBuffer_SRVs[prevId]);

            //pd3dImmediateContext->OMSetRenderTargets(2, Layers_RTVs, DepthBuffer_DSVs[currId]);
            pd3dImmediateContext->OMSetRenderTargets(3, Layers_RTVs, DepthBuffer_DSVs[currId]);
            renderPerObjects(pd3dImmediateContext, g_pDepthPeelingTech, g_pDepthPeelingEffect);
        }
    }

    pd3dImmediateContext->GenerateMips(g_pMotionVectorMap_RenderingClass->ppSRVs[0]);
    pd3dImmediateContext->GenerateMips(g_pMotionVectorSquareMap_RenderingClass->ppSRVs[0]);

    //---------------------------------------------------------------------------------
    //PASS 3 Make MotionBlur on FullSceenQuad
    //---------------------------------------------------------------------------------

    ID3D11RenderTargetView* Layers_RTVs = g_pPrintMotionBlurClass->GetRenderTargetView();

    pd3dImmediateContext->OMSetRenderTargets(1, &Layers_RTVs, NULL);
    g_pDepthPeelingTech = g_pDepthPeelingEffect->GetTechniqueByName("MotionBlur");
    g_pDepthPeelingTech->GetPassByIndex(0)->Apply(0, pd3dImmediateContext);
    g_pFSQ->RenderFSQ(pd3dImmediateContext, g_pLayout, g_pDepthPeelingTech, techDesc, g_pDepthPeelingEffect);

    //---------------------------------------------------------------------------------
    //PASS 4 Denoising
    //---------------------------------------------------------------------------------

    ID3D11RenderTargetView* pRTV = DXUTGetD3D11RenderTargetView();
    pd3dImmediateContext->OMSetRenderTargets(1, &pRTV, NULL);
    g_pDepthPeelingTech = g_pDepthPeelingEffect->GetTechniqueByName("Denoising");
    g_pDepthPeelingTech->GetPassByIndex(0)->Apply(0, pd3dImmediateContext);
    g_pFSQ->RenderFSQ(pd3dImmediateContext, g_pLayout, g_pDepthPeelingTech, techDesc, g_pDepthPeelingEffect);

    static int frame = 0;
    CString fileName = "motion blur";
    if (frame >= 1 && frame <= 100) renderTagetToImageFile(pd3dDevice, pd3dImmediateContext, pRTV, frame, fileName);
    frame++;


}


아래와 같이 성능이 확연히 증가한 것을 확인할 수 있었다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.