bloom: blend blur result with the scene

This commit is contained in:
Zack Buhman 2026-01-08 23:49:33 -06:00
parent 48b1c3b8d4
commit 0c27a5aeac
3 changed files with 156 additions and 46 deletions

View File

@ -1,11 +1,11 @@
float2 vInvScreenSize; float2 vInvScreenSize;
float2 vDir; float2 vDir;
Texture2D txDiffuse; Texture2D txDiffuseA;
SamplerState samPoint { SamplerState samPoint {
Filter = MIN_MAG_MIP_POINT; Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap; AddressU = CLAMP;
AddressV = Wrap; AddressV = CLAMP;
}; };
struct VS_INPUT struct VS_INPUT
@ -29,38 +29,79 @@ PS_INPUT VS(VS_INPUT input)
return output; return output;
} }
static const float offset[] = {0.0, 1.0, 2.0, 3.0, 4.0}; static const float offset[11] = {
static const float weight[] = { // sigma 1.75, radius 4 -9.406430666971303,
0.22720403874968215, -7.425801606895373,
0.19382872916158458, -5.445401742210555,
0.12033793944552469, -3.465172537482815,
0.05436431541122633, -1.485055021558738,
0.01786699660682331, 0.4950160492928826,
2.4751038298192056,
4.455269417428358,
6.435576703455285,
8.41608382089975,
10
};
static const float weight[11] = {
0.0276904183309881,
0.05417056378718292,
0.09049273288108622,
0.12908964856395883,
0.15725301673321052,
0.16358389071865348,
0.14531705460040129,
0.11023607138371759,
0.0714102715628023,
0.03950209624702099,
0.011254235190977919
}; };
float4 PS(PS_INPUT input) : SV_Target float4 PS(PS_INPUT input) : SV_Target
{ {
float4 texColor = txDiffuse.Sample(samPoint, input.Tex) * weight[0]; float4 texColor = float4(0, 0, 0, 0);
for (int i = 1; i < 5; i++) { for (int i = 0; i < 11; i++) {
float2 texOffset = vDir * offset[i] * vInvScreenSize; float2 texOffset = vDir * offset[i] * vInvScreenSize;
texColor += txDiffuse.Sample(samPoint, input.Tex + texOffset) * weight[i]; texColor += txDiffuseA.Sample(samPoint, input.Tex + texOffset) * weight[i];
texColor += txDiffuse.Sample(samPoint, input.Tex - texOffset) * weight[i];
} }
return texColor; return texColor;
} }
BlendState Blending BlendState DisableBlending
{ {
BlendEnable[0] = FALSE; BlendEnable[0] = FALSE;
}; };
BlendState EnableBlending
{
BlendEnable[0] = TRUE;
SrcBlend = ONE;
DestBlend = ONE;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
};
DepthStencilState DisableDepth DepthStencilState DisableDepth
{ {
DepthEnable = FALSE; DepthEnable = FALSE;
DepthWriteMask = ZERO; DepthWriteMask = ZERO;
}; };
float4 PSBlend(PS_INPUT input) : SV_Target
{
float4 texColor = float4(0, 0, 0, 0);
for (int i = 0; i < 11; i++) {
float2 texOffset = vDir * offset[i] * vInvScreenSize;
texColor += txDiffuseA.Sample(samPoint, input.Tex + texOffset) * weight[i];
}
texColor = float4(1, 1, 1, 1) - exp2(-texColor * 3.0);
return float4(texColor.xyz, 1);
}
technique10 Bloom technique10 Bloom
{ {
pass P0 pass P0
@ -68,7 +109,19 @@ technique10 Bloom
SetVertexShader(CompileShader(vs_4_0, VS())); SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(NULL); SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0, PS())); SetPixelShader(CompileShader(ps_4_0, PS()));
SetBlendState(Blending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff); SetBlendState(DisableBlending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff);
SetDepthStencilState(DisableDepth, 0);
}
}
technique10 BloomBlend
{
pass P0
{
SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0, PSBlend()));
SetBlendState(EnableBlending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff);
SetDepthStencilState(DisableDepth, 0); SetDepthStencilState(DisableDepth, 0);
} }
} }

View File

@ -46,14 +46,15 @@ D3DXMATRIX g_Projection;
// bloom // bloom
ID3D10RenderTargetView * g_pRenderTargetViewTexture[2] = { NULL, NULL }; ID3D10RenderTargetView * g_pRenderTargetViewTexture[2] = { NULL, NULL };
ID3D10ShaderResourceView * g_pRenderTargetShaderResourceView[2] = { NULL, NULL }; ID3D10ShaderResourceView * g_pRenderTargetShaderResourceViewTexture[2] = { NULL, NULL };
ID3D10Effect * g_pEffectBloom = NULL; ID3D10Effect * g_pEffectBloom = NULL;
ID3D10EffectTechnique * g_pTechniqueBloom = NULL; ID3D10EffectTechnique * g_pTechniqueBloom = NULL;
ID3D10EffectTechnique * g_pTechniqueBloomBlend = NULL;
ID3D10InputLayout * g_pVertexLayoutBloom = NULL; ID3D10InputLayout * g_pVertexLayoutBloom = NULL;
const DWORD g_dwVertexBufferCountBloom = 1; const DWORD g_dwVertexBufferCountBloom = 1;
ID3D10Buffer * g_pVertexBuffersBloom[g_dwVertexBufferCountBloom]; ID3D10Buffer * g_pVertexBuffersBloom[g_dwVertexBufferCountBloom];
ID3D10EffectShaderResourceVariable * g_pDiffuseVariableBloom = NULL; ID3D10EffectShaderResourceVariable * g_pDiffuseAVariableBloom = NULL;
ID3D10EffectVectorVariable * g_pInvScreenSizeVariableBloom = NULL; ID3D10EffectVectorVariable * g_pInvScreenSizeVariableBloom = NULL;
ID3D10EffectVectorVariable * g_pDirVariableBloom = NULL; ID3D10EffectVectorVariable * g_pDirVariableBloom = NULL;
@ -82,6 +83,7 @@ ID3D10InputLayout * g_pVertexLayoutStatic = NULL;
ID3D10EffectMatrixVariable * g_pWorldVariableStatic = NULL; ID3D10EffectMatrixVariable * g_pWorldVariableStatic = NULL;
ID3D10EffectMatrixVariable * g_pViewVariableStatic = NULL; ID3D10EffectMatrixVariable * g_pViewVariableStatic = NULL;
ID3D10EffectMatrixVariable * g_pProjectionVariableStatic = NULL; ID3D10EffectMatrixVariable * g_pProjectionVariableStatic = NULL;
ID3D10EffectMatrixVariable * g_pWorldNormalVariableStatic = NULL;
ID3D10EffectVectorVariable * g_pOutputColorVariableStatic = NULL; ID3D10EffectVectorVariable * g_pOutputColorVariableStatic = NULL;
// cube // cube
@ -275,7 +277,7 @@ HRESULT InitDirect3DViews()
hr = CreateTextureRenderTargetView(backBufferSurfaceDesc.Width, hr = CreateTextureRenderTargetView(backBufferSurfaceDesc.Width,
backBufferSurfaceDesc.Height, backBufferSurfaceDesc.Height,
&g_pRenderTargetViewTexture[i], &g_pRenderTargetViewTexture[i],
&g_pRenderTargetShaderResourceView[i]); &g_pRenderTargetShaderResourceViewTexture[i]);
if (FAILED(hr)) { if (FAILED(hr)) {
return hr; return hr;
} }
@ -533,9 +535,10 @@ HRESULT InitBloomBuffers()
} }
g_pTechniqueBloom = g_pEffectBloom->GetTechniqueByName("Bloom"); g_pTechniqueBloom = g_pEffectBloom->GetTechniqueByName("Bloom");
g_pTechniqueBloomBlend = g_pEffectBloom->GetTechniqueByName("BloomBlend");
g_pInvScreenSizeVariableBloom = g_pEffectBloom->GetVariableByName("vInvScreenSize")->AsVector(); g_pInvScreenSizeVariableBloom = g_pEffectBloom->GetVariableByName("vInvScreenSize")->AsVector();
g_pDirVariableBloom = g_pEffectBloom->GetVariableByName("vDir")->AsVector(); g_pDirVariableBloom = g_pEffectBloom->GetVariableByName("vDir")->AsVector();
g_pDiffuseVariableBloom = g_pEffectBloom->GetVariableByName("txDiffuse")->AsShaderResource(); g_pDiffuseAVariableBloom = g_pEffectBloom->GetVariableByName("txDiffuseA")->AsShaderResource();
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// layout // layout
@ -618,8 +621,8 @@ HRESULT InitStaticEffect()
D3D10_INPUT_ELEMENT_DESC layout[] = { D3D10_INPUT_ELEMENT_DESC layout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, {"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
}; };
UINT numElements = (sizeof (layout)) / (sizeof (layout[0])); UINT numElements = (sizeof (layout)) / (sizeof (layout[0]));
@ -642,6 +645,7 @@ HRESULT InitStaticEffect()
g_pWorldVariableStatic = g_pEffectStatic->GetVariableByName("World")->AsMatrix(); g_pWorldVariableStatic = g_pEffectStatic->GetVariableByName("World")->AsMatrix();
g_pViewVariableStatic = g_pEffectStatic->GetVariableByName("View")->AsMatrix(); g_pViewVariableStatic = g_pEffectStatic->GetVariableByName("View")->AsMatrix();
g_pProjectionVariableStatic = g_pEffectStatic->GetVariableByName("Projection")->AsMatrix(); g_pProjectionVariableStatic = g_pEffectStatic->GetVariableByName("Projection")->AsMatrix();
g_pWorldNormalVariableStatic = g_pEffectStatic->GetVariableByName("WorldNormal")->AsMatrix();
g_pOutputColorVariableStatic = g_pEffectStatic->GetVariableByName("vOutputColor")->AsVector(); g_pOutputColorVariableStatic = g_pEffectStatic->GetVariableByName("vOutputColor")->AsVector();
return S_OK; return S_OK;
@ -835,7 +839,7 @@ HRESULT InitDirect3DDevice()
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
D3D10_INPUT_ELEMENT_DESC layout[] = { D3D10_INPUT_ELEMENT_DESC layout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 2, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 2, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
{"NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 3, 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, {"NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 3, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
@ -1147,7 +1151,7 @@ void RenderModel(float t)
} }
} }
void RenderMeshStatic(const Mesh * mesh) void RenderMeshStatic(const Mesh * mesh, float t)
{ {
g_pViewVariableStatic->SetMatrix((float *)&g_View); g_pViewVariableStatic->SetMatrix((float *)&g_View);
g_pProjectionVariableStatic->SetMatrix((float *)&g_Projection); g_pProjectionVariableStatic->SetMatrix((float *)&g_Projection);
@ -1171,11 +1175,18 @@ void RenderMeshStatic(const Mesh * mesh)
D3DXMATRIX mLight; D3DXMATRIX mLight;
D3DXMATRIX mLightScale; D3DXMATRIX mLightScale;
D3DXVECTOR3 vLightPos = g_vLightDirs[m] * (1.25f * (m + 1)); D3DXVECTOR3 vLightPos = g_vLightDirs[m] * (1.25f * (m + 1));
D3DXMATRIX mLightRotate;
D3DXMatrixRotationX(&mLightRotate, t * (1 + -2 * m));
D3DXMatrixTranslation(&mLight, vLightPos.x, vLightPos.y, vLightPos.z); D3DXMatrixTranslation(&mLight, vLightPos.x, vLightPos.y, vLightPos.z);
D3DXMatrixScaling(&mLightScale, 0.05f, 0.05f, 0.05f); D3DXMatrixScaling(&mLightScale, 0.05f, 0.05f, 0.05f);
mLight = mLightScale * mLight; mLight = mLightRotate * mLightScale * mLight;
g_pWorldVariableStatic->SetMatrix((float *)&mLight); g_pWorldVariableStatic->SetMatrix((float *)&mLight);
D3DXMATRIX mLightNormal;
D3DXMatrixTranspose(&mLightNormal, D3DXMatrixInverse(&mLightNormal, NULL, &mLight));
g_pWorldNormalVariableStatic->SetMatrix((float *)&mLightNormal);
g_pOutputColorVariableStatic->SetFloatVector((float *)&g_vLightColors[m]); g_pOutputColorVariableStatic->SetFloatVector((float *)&g_vLightColors[m]);
for (UINT p = 0; p < techDesc.Passes; p++) { for (UINT p = 0; p < techDesc.Passes; p++) {
@ -1287,28 +1298,57 @@ void RenderBloom()
D3D10_TECHNIQUE_DESC techDesc; D3D10_TECHNIQUE_DESC techDesc;
g_pTechniqueBloom->GetDesc(&techDesc); g_pTechniqueBloom->GetDesc(&techDesc);
// horizontal
D3DXVECTOR2 dirHorizontal = D3DXVECTOR2(1.0, 0.0); D3DXVECTOR2 dirHorizontal = D3DXVECTOR2(1.0, 0.0);
g_pDirVariableBloom->SetFloatVector((float *)dirHorizontal); D3DXVECTOR2 dirVertical = D3DXVECTOR2(0.0, 1.0);
g_pDiffuseVariableBloom->SetResource(g_pRenderTargetShaderResourceView[0]);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetViewTexture[1], NULL);
// horizontal
g_pDirVariableBloom->SetFloatVector((float *)dirHorizontal);
g_pDiffuseAVariableBloom->SetResource(g_pRenderTargetShaderResourceViewTexture[0]);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetViewTexture[1], NULL);
for (UINT p = 0; p < techDesc.Passes; p++) {
g_pTechniqueBloom->GetPassByIndex(p)->Apply(0);
g_pd3dDevice->Draw(4, 0);
}
g_pd3dDevice->OMSetRenderTargets(0, NULL, NULL);
ID3D10ShaderResourceView * srv[] = { NULL };
for (int i = 0; i < 2; i++) {
g_pd3dDevice->PSSetShaderResources(0, 1, srv);
// vertical
g_pDirVariableBloom->SetFloatVector((float *)dirVertical);
g_pDiffuseAVariableBloom->SetResource(g_pRenderTargetShaderResourceViewTexture[1]);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetViewTexture[0], NULL);
for (UINT p = 0; p < techDesc.Passes; p++) { for (UINT p = 0; p < techDesc.Passes; p++) {
g_pTechniqueBloom->GetPassByIndex(p)->Apply(0); g_pTechniqueBloom->GetPassByIndex(p)->Apply(0);
g_pd3dDevice->Draw(4, 0); g_pd3dDevice->Draw(4, 0);
} }
// vertical g_pd3dDevice->PSSetShaderResources(0, 1, srv);
D3DXVECTOR2 dirVertical = D3DXVECTOR2(0.0, 1.0);
g_pDirVariableBloom->SetFloatVector((float *)dirVertical);
g_pDiffuseVariableBloom->SetResource(g_pRenderTargetShaderResourceView[1]);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);
// horizontal
g_pDirVariableBloom->SetFloatVector((float *)dirHorizontal);
g_pDiffuseAVariableBloom->SetResource(g_pRenderTargetShaderResourceViewTexture[0]);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetViewTexture[1], NULL);
for (UINT p = 0; p < techDesc.Passes; p++) { for (UINT p = 0; p < techDesc.Passes; p++) {
g_pTechniqueBloom->GetPassByIndex(p)->Apply(0); g_pTechniqueBloom->GetPassByIndex(p)->Apply(0);
g_pd3dDevice->Draw(4, 0); g_pd3dDevice->Draw(4, 0);
} }
}
D3D10_TECHNIQUE_DESC techDescBlend;
g_pTechniqueBloomBlend->GetDesc(&techDescBlend);
// vertical
g_pDirVariableBloom->SetFloatVector((float *)dirVertical);
g_pDiffuseAVariableBloom->SetResource(g_pRenderTargetShaderResourceViewTexture[1]);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);
for (UINT p = 0; p < techDescBlend.Passes; p++) {
g_pTechniqueBloomBlend->GetPassByIndex(p)->Apply(0);
g_pd3dDevice->Draw(4, 0);
}
} }
void Update(float t) void Update(float t)
@ -1346,9 +1386,7 @@ void Render()
// clear // clear
const float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f }; const float ClearColor[4] = { 0.2f, 0.125f, 0.2f, 1.0f };
//g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetViewTexture[0], g_pDepthStencilView);
//g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetViewTexture[0], ClearColor);
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView); g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetView, ClearColor); g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
g_pd3dDevice->ClearDepthStencilView(g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0); g_pd3dDevice->ClearDepthStencilView(g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
@ -1356,9 +1394,17 @@ void Render()
// render // render
RenderModel(t); RenderModel(t);
RenderFont(); RenderFont();
RenderMeshStatic(cube::node_0.mesh);
//RenderBloom(); const float ClearColorZero[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
ID3D10RenderTargetView * RenderTargets[] = {
g_pRenderTargetView,
g_pRenderTargetViewTexture[0],
};
g_pd3dDevice->OMSetRenderTargets(2, RenderTargets, g_pDepthStencilView);
g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetViewTexture[0], ClearColorZero);
RenderMeshStatic(cube::node_0.mesh, t);
RenderBloom();
// present // present
g_pSwapChain->Present(0, 0); g_pSwapChain->Present(0, 0);

View File

@ -2,6 +2,8 @@ matrix World;
matrix View; matrix View;
matrix Projection; matrix Projection;
matrix WorldNormal;
float3 vOutputColor; float3 vOutputColor;
struct VS_INPUT struct VS_INPUT
@ -18,6 +20,12 @@ struct PS_INPUT
float2 Tex : TEXCOORD0; float2 Tex : TEXCOORD0;
}; };
struct PS_OUTPUT
{
float4 color0 : SV_TARGET0;
float4 color1 : SV_TARGET1;
};
PS_INPUT VS(VS_INPUT input) PS_INPUT VS(VS_INPUT input)
{ {
PS_INPUT output = (PS_INPUT)0; PS_INPUT output = (PS_INPUT)0;
@ -26,16 +34,19 @@ PS_INPUT VS(VS_INPUT input)
output.Pos = mul(output.Pos, View); output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection); output.Pos = mul(output.Pos, Projection);
output.Normal = mul(output.Normal, World).xyz; output.Normal = mul(input.Normal, WorldNormal).xyz;
output.Tex = input.Tex; output.Tex = input.Tex;
return output; return output;
} }
float4 PS(PS_INPUT input) : SV_Target PS_OUTPUT PS(PS_INPUT input)
{ {
return float4(vOutputColor, 1.0); PS_OUTPUT output;
output.color0 = float4(vOutputColor, 1.0);
output.color1 = float4(vOutputColor, 1.0);
return output;
} }
BlendState DisableBlending BlendState DisableBlending