[ 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 라이센스를 따릅니다.