Bloom
뭔가 자고 일어난 느낌으로 뽀샤시해 보이는 느낌을 만들어보자
이 전에 만들었던 GaussianBlur를 사용한다.
Shader
106_bloom.fx
#include "00_Global.fx"
#include "00_Light.fx"
float2 PixelSize;
struct VertexOutput
{
float4 Position : SV_Position;
float2 Uv : UV;
};
VertexOutput VS(float4 Position : Position)
{
VertexOutput output;
output.Position = Position;
output.Uv.x = Position.x * 0.5f + 0.5f;
output.Uv.y = -Position.y * 0.5f + 0.5f;
return output;
}
float4 PS_Diffuse(VertexOutput intput) : SV_Target
{
return DiffuseMap.Sample(LinearSampler, intput.Uv);
}
float Threshold = 0.6f;
float4 PS_Luminosity(VertexOutput input) : SV_Target
{
float4 color = DiffuseMap.Sample(LinearSampler, input.Uv);
return saturate((color - Threshold) / (1 - Threshold));
}
#define MAX_SAMPLE_COUNT 33
int SampleCount = 15;
float2 Offsets[MAX_SAMPLE_COUNT];
float Weights[MAX_SAMPLE_COUNT];
float4 PS_Blur(VertexOutput input) : SV_Target
{
float4 color = 0;
for (int i = 0; i < SampleCount; i++)
color += DiffuseMap.Sample(LinearSampler, input.Uv + Offsets[i]) * Weights[i];
return color;
}
Texture2D LuminosityMap;
Texture2D BlurMap;
float4 PS_Composite(VertexOutput input) : SV_Target
{
float4 luminosity = LuminosityMap.Sample(LinearSampler, input.Uv);
float4 blur = BlurMap.Sample(LinearSampler, input.Uv);
luminosity *= (1.0f - saturate(blur));
return float4((luminosity + blur).rgb, 1.0f);
}
technique11 T0
{
P_VP(P0, VS, PS_Diffuse)
P_VP(P1, VS, PS_Luminosity)
P_VP(P2, VS, PS_Blur)
P_VP(P3, VS, PS_Composite)
}
우선 PS_Composite에서 밝은 색상을 좀 더 올려주고 어두운 색은 더 어둡게 표현해준다.
그런 뒤, 받아온 Weight와 Offset을 활용해서 PS_Blur에서 블러를 적용시켜 주고,
PS_Composite을 활용해서 두 값을 합쳐준다.
BloomDemo Class
BloomDemo.cpp
void BloomDemo::PreRender()
{
viewport->RSSetViewport();
// Render
{
renderTarget[0]->PreRender(depthStencil);
sky->Render();
Pass(0, 1, 2);
wall->Render();
sphere->Render();
brick->Render();
cylinder->Render();
stone->Render();
cube->Render();
floor->Render();
grid->Render();
airplane->Render();
kachujin->Render();
weapon->Render();
billboard->Render();
}
Vector2 PixelSize = Vector2(1.0f / D3D::Width(), 1.0f / D3D::Height());
postEffect->GetShader()->AsVector("PixelSize")->SetFloatVector(PixelSize);
// Luminocity
{
renderTarget[1]->PreRender(depthStencil);
postEffect->Pass(1);
postEffect->SRV(renderTarget[0]->SRV());
postEffect->Render();
}
SetBlur();
// BlurX
{
postEffect->GetShader()->AsScalar("Weights")->SetFloatArray(&weightX[0], 0, weightX.size());
postEffect->GetShader()->AsVector("Offsets")->SetRawValue(&offsetX[0], 0, sizeof(Vector2) * offsetX.size());
renderTarget[2]->PreRender(depthStencil);
viewport->RSSetViewport();
postEffect->SRV(renderTarget[1]->SRV());
postEffect->Pass(2);
postEffect->Render();
}
// BlurY
{
postEffect->GetShader()->AsScalar("Weights")->SetFloatArray(&weightY[0], 0, weightY.size());
postEffect->GetShader()->AsVector("Offsets")->SetRawValue(&offsetY[0], 0, sizeof(Vector2) * offsetY.size());
renderTarget[3]->PreRender(depthStencil);
viewport->RSSetViewport();
postEffect->SRV(renderTarget[2]->SRV());
postEffect->Pass(2);
postEffect->Render();
}
// Composite
{
renderTarget[4]->PreRender(depthStencil);
viewport->RSSetViewport();
postEffect->GetShader()->AsSRV("LuminosityMap")->SetResource(renderTarget[1]->SRV());
postEffect->GetShader()->AsSRV("BlurMap")->SetResource(renderTarget[3]->SRV());
postEffect->Pass(3);
postEffect->Render();
}
}
void BloomDemo::Render()
{
}
void BloomDemo::PostRender()
{
postEffect->Pass(0);
postEffect->SRV(renderTarget[4]->SRV());
postEffect->Render();
render2D->Render();
}
void BloomDemo::SetBlur()
{
float x = 1.0f / D3D::Width();
float y = 1.0f / D3D::Height();
GetBlurParameter(weightX, offsetX, x, 0);
GetBlurParameter(weightY, offsetY, 0, y);
}
void BloomDemo::GetBlurParameter(vector<float>& weights, vector<Vector2>& offsets, float x, float y)
{
weights.clear();
weights.assign(blurCount, float());
offsets.clear();
offsets.assign(blurCount, Vector2());
weights[0] = GetGaussFunction(0); //1
offsets[0] = Vector2(0, 0);
float sum = weights[0];
for (UINT i = 0; i < blurCount / 2; i++)
{
float temp = GetGaussFunction((float)(i + 1));
weights[i * 2 + 1] = temp;
weights[i * 2 + 2] = temp;
sum += temp * 2;
Vector2 temp2 = Vector2(x, y) * (i * 2 + 1.5f);
offsets[i * 2 + 1] = temp2;
offsets[i * 2 + 2] = -temp2;
}
for (UINT i = 0; i < blurCount; i++)
weights[i] /= sum;
}
// 가우스 함수
float BloomDemo::GetGaussFunction(float val)
{
return (float)((1.0 / sqrt(2 * Math::PI * blurCount)) * exp(-(val * val) / (2 * blurCount * blurCount)));
}
BlurCount를 정해준뒤 이 BlurCount로 offset과 weight를 계산 해준뒤, Shader에 값을 넘겨준다.
그런 뒤 밝기와 Blur를 받아와 넘겨준뒤 값을 섞어준다.
위에서 말한 효과가 나온다.