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 vDir;
Texture2D txDiffuse;
Texture2D txDiffuseA;
SamplerState samPoint {
Filter = MIN_MAG_MIP_POINT;
AddressU = Wrap;
AddressV = Wrap;
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
struct VS_INPUT
@ -29,38 +29,79 @@ PS_INPUT VS(VS_INPUT input)
return output;
}
static const float offset[] = {0.0, 1.0, 2.0, 3.0, 4.0};
static const float weight[] = { // sigma 1.75, radius 4
0.22720403874968215,
0.19382872916158458,
0.12033793944552469,
0.05436431541122633,
0.01786699660682331,
static const float offset[11] = {
-9.406430666971303,
-7.425801606895373,
-5.445401742210555,
-3.465172537482815,
-1.485055021558738,
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 texColor = txDiffuse.Sample(samPoint, input.Tex) * weight[0];
for (int i = 1; i < 5; i++) {
float4 texColor = float4(0, 0, 0, 0);
for (int i = 0; i < 11; i++) {
float2 texOffset = vDir * offset[i] * vInvScreenSize;
texColor += txDiffuse.Sample(samPoint, input.Tex + texOffset) * weight[i];
texColor += txDiffuse.Sample(samPoint, input.Tex - texOffset) * weight[i];
texColor += txDiffuseA.Sample(samPoint, input.Tex + texOffset) * weight[i];
}
return texColor;
}
BlendState Blending
BlendState DisableBlending
{
BlendEnable[0] = FALSE;
};
BlendState EnableBlending
{
BlendEnable[0] = TRUE;
SrcBlend = ONE;
DestBlend = ONE;
BlendOp = ADD;
SrcBlendAlpha = ZERO;
DestBlendAlpha = ZERO;
BlendOpAlpha = ADD;
};
DepthStencilState DisableDepth
{
DepthEnable = FALSE;
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
{
pass P0
@ -68,7 +109,19 @@ technique10 Bloom
SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(NULL);
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);
}
}

View File

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

View File

@ -2,6 +2,8 @@ matrix World;
matrix View;
matrix Projection;
matrix WorldNormal;
float3 vOutputColor;
struct VS_INPUT
@ -18,6 +20,12 @@ struct PS_INPUT
float2 Tex : TEXCOORD0;
};
struct PS_OUTPUT
{
float4 color0 : SV_TARGET0;
float4 color1 : SV_TARGET1;
};
PS_INPUT VS(VS_INPUT input)
{
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, Projection);
output.Normal = mul(output.Normal, World).xyz;
output.Normal = mul(input.Normal, WorldNormal).xyz;
output.Tex = input.Tex;
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