• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

Direct3D11 공부 42일차(GaussianBlur)

04 Aug 2021

Reading time ~3 minutes

GaussianBlur

이 전에는 Blur 처리를 간단한 방법으로 만들었지만, 좀 더 자연스럽게 만들기 위해 Gaussian함수를 사용해서 만들어 보자

이 분포가 가우시안 분포도이다. 이 분포도를 활요해서 중간 부분을 좀 더 강하게 블러 해준다.

Shader

104_GaussianBlur.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);
}

const int GaussBlurCount = 6;
static const float Weights[13] =
{
    0.0561f, 0.1353f, 0.2780f, 0.4868f, 0.7261f, 0.9231f,
    1.0f,
    0.9231f, 0.7261f, 0.4868f, 0.2780f, 0.1353f, 0.0561f
};

float4 PS_GausianBlurX(VertexOutput input) : SV_Target
{
    float2 uv = input.Uv;
    float u = PixelSize.x;
    
    float sum = 0;
    float4 color = 0;
    for (int i = -GaussBlurCount; i < GaussBlurCount; i++)
    {
        float2 temp = uv + float2(u * (float) i, 0.0f);
        color += Weights[6 + i] * DiffuseMap.Sample(LinearSampler, temp);
        
        sum += Weights[6 + i];
    }
    color /= sum;

    return float4(color.rgb, 1.0f);
}

float4 PS_GaussianBlurY(VertexOutput input) : SV_Target
{
    float2 uv = input.Uv;
    float v = PixelSize.y;
    
    float sum = 0;
    float4 color = 0;
    for (int i = -GaussBlurCount; i <= +GaussBlurCount; i++)
    {
        float2 temp = uv + float2(0.0f, v * (float) i);
        color += Weights[6 + i] * DiffuseMap.Sample(LinearSampler, temp);
        
        sum += Weights[6 + i];
    }
    color /= sum;
    
    return float4(color.rgb, 1);
}

struct PixelOutput_GaussianBlur2
{
    float4 Color0 : SV_Target0;
    float4 Color1 : SV_Target1;
};

PixelOutput_GaussianBlur2 PS_GaussianBlurMrt(VertexOutput input)
{
    PixelOutput_GaussianBlur2 output;

    float2 uv = input.Uv;
    float u = PixelSize.x;
    
    float sum = 0;
    float4 color = 0;
    for (int i = -GaussBlurCount; i < GaussBlurCount; i++)
    {
        float2 temp = uv + float2(u * (float) i, 0.0f);
        color += Weights[6 + i] * DiffuseMap.Sample(LinearSampler, temp);
        
        sum += Weights[6 + i];
    }
    color /= sum;
    
    output.Color0 = float4(color.rgb, 1);
    
    uv = input.Uv;
    float v = PixelSize.y;
    
    sum = 0;
    color = 0;
    for (int j = -GaussBlurCount; j <= +GaussBlurCount; j++)
    {
        float2 temp = uv + float2(0.0f, v * (float) j);
        color += Weights[6 + j] * DiffuseMap.Sample(LinearSampler, temp);
        
        sum += Weights[6 + j];
    }
    color /= sum;
    
    output.Color1 = float4(color.rgb, 1);
    
    return output;
}

Texture2D GaussianMrt[2];
float4 PS_GaussianCombined(VertexOutput input) : SV_Target
{
    float4 color0 = GaussianMrt[0].Sample(LinearSampler, input.Uv);
    float4 color1 = GaussianMrt[1].Sample(LinearSampler, input.Uv);
    
    return float4((color0.rgb + color1.rgb) * 0.5f, 1.0f);
}

technique11 T0
{
    P_VP(P0, VS, PS_Diffuse)
    P_VP(P1, VS, PS_GausianBlurX)
    P_VP(P2, VS, PS_GaussianBlurY)
    P_VP(P3, VS, PS_GaussianBlurMrt)
    P_VP(P4, VS, PS_GaussianCombined)
}

X축과 Y축을 계산한 뒤, 그 값들을 섞어준다.

GaussianBlur Class+

GaussianBlur2.cpp
void GaussianBlurDemo2::Initialize()
{
	Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
	Context::Get()->GetCamera()->Position(1, 36, -85);
	((Freedom *)Context::Get()->GetCamera())->Speed(50,2);

	Performance performence;
	shader = new Shader(L"96_Billboard.fxo");

	float width = D3D::Width(), height = D3D::Height();

	renderTarget[0] = new RenderTarget((UINT)width, (UINT)height);
	renderTarget[1] = new RenderTarget((UINT)width, (UINT)height);
	renderTarget[2] = new RenderTarget((UINT)width, (UINT)height);

	depthStencil = new DepthStencil((UINT)width, (UINT)height);
	viewport = new Viewport(D3D::Width(), D3D::Height());

	render2D = new Render2D();
	render2D->GetTransform()->Scale(355.0f, 200.0f, 1);
	render2D->GetTransform()->Position(200.0f ,150.0f , 0);
	render2D->SRV(renderTarget[0]->SRV());

	postEffect = new PostEffect(L"104_GaussianBlur.fxo");
		
	sky = new CubeSky(L"Environment/GrassCube1024.dds");

	Billboards();

	Mesh();
	Airplane();
	Kachujin();
	KachujinCollider();
	KachujinWeapon();

	PointLighting();
	SpotLighting();
}

void GaussianBlurDemo2::PreRender()
{
	renderTarget[0]->PreRender(depthStencil);
	viewport->RSSetViewport();

	// Render
	{
		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);

	// MRT
	{
		RenderTarget* temp[2];
		temp[0] = renderTarget[1];
		temp[1] = renderTarget[2];

		RenderTarget::PreRender(temp, 2, depthStencil);

		postEffect->Pass(3);
		postEffect->SRV(renderTarget[0]->SRV());
		postEffect->Render();
	}

	// Combined
	{
		renderTarget[0]->PreRender(depthStencil);

		ID3D11ShaderResourceView* srvs[2];
		srvs[0] = renderTarget[1]->SRV();
		srvs[1] = renderTarget[2]->SRV();

		postEffect->Pass(4);
		postEffect->GetShader()->AsSRV("GaussianMrt")->SetResourceArray(srvs, 0, 2);
		postEffect->Render();
	}
}

void GaussianBlurDemo2::PostRender()
{
	postEffect->Pass(0);
	postEffect->SRV(renderTarget[0]->SRV());
	postEffect->Render();
	render2D->Render();
}

두개의 SRV를 받은 뒤, Shader의 Combine의 값으로 갖고온다.

이렇게 갖고오게 되면

전보다 조금 더 자연스럽게 나온다.



DirectX Share Tweet +1