본문 바로가기

DirectX11 3D/기본 문법

<DirectX11 3D> 105 - GaussianBlur

 

필요한 개념


3. Gaussian Blur
Gaussian Blur : 게임에서 흔히 사용되는 블러 방식, 가우스 함수를 이용해 계산한 블러 횟수 당 가중치를 곱한 방식
좀 더 부드럽고 자연스러운 결과가 나옴(우리는 이전까지는 선형을 사용했다.)
일반적으로 블러를 먹이면 가우시안 블러를 사용한다.
이거는 MRT를 이용한다.(x한번하고 한번한 결과에 Y한다, MRT를 이용한다면 2개를 동시에 빼낼 수 있다. 이것을 합산해서 쓰는 방식으로)
가중치를 같이 계산해서 블러를 계산, 가중치를 합한다음 평균으로 나눠서 사용

X방향 결과에 다가 Y방향을 합산한 방식(렌더링한 결과에다가 렌더링을 수행해서 중첩가능)


// GaussianBlurX
{
renderTarget[1]->PreRender(depthStencil);
postEffect->Pass(3);
postEffect->SRV(renderTarget[0]->SRV());
postEffect->Render();
}

// GaussianBlurX
{
renderTarget[2]->PreRender(depthStencil);
postEffect->Pass(4);
// BlurX 결과에 BlurY의 결과를 중첩
postEffect->SRV(renderTarget[1]->SRV());
postEffect->Render();
}


정리 
Blur : 주변의 픽셀을 합산하여 평균을 계산
Gaussian Blur : 가우스 함수를 이용하여 가중치를 계산해 블러를 만드는 방식
렌더링한 결과에 다시 렌더링을 수행해 중첩할 수 있다.

이전에는 X방향하고 결과 RenderTargetView를 넘겨줘서 Y방향에 합산해줬다.
그런데 지금은 MRT로 한다.

Tip)
shader 작성시에 Technique로 분리시켜 놓는 것도 중요하다. 각종 기능들은 헤더로 만들고 실제 부분은 Technique만 들어가도록 하면 좋다.
Technique Write...

MRT를 이용시 완전 똑같이 나오지는 않는데, 거의 유사하게 나온다.

RTV 2개로도 가능하지만(X방향하고 Y방향 먹이는 방법), MRT로 한번에 가능하다.(MRT로 합치는 방법)

 

 

 

 

 

RTV 사용시

 


 

GaussianBlurDemo.h


더보기
#pragma once
#include "Systems/IExecute.h"

class GaussianBlurDemo : public IExecute
{
public:
	virtual void Initialize() override;
	virtual void Ready() override {}
	virtual void Destroy() override {}
	virtual void Update() override;
	virtual void PreRender() override;
	virtual void Render() override;
	virtual void PostRender() override;
	virtual void ResizeScreen() override {}

private:
	void Billboards();
	void Mesh();
	void Airplane();
	void Kachujin();
	void KachujinCollider();
	void KachujinWeapon();
	void PointLighting();
	void SpotLighting();

	void Pass(UINT mesh, UINT model, UINT anim);

private:
	Shader* shader;

	// 0 : 원본, 1 : X 방향(GaussianBlur), 2: X 방향 + Y 방향
	RenderTarget* renderTarget[3];
	DepthStencil* depthStencil;
	// 메인의 Viewport를 사용해도 상관은 없지만,
	// RTV, DSV, Viewport를 1:1:1로 만드는 것이 편하다.
	Viewport* viewport;
	Render2D* render2D;
	// PostEffect 효과를 먹이기위해
	PostEffect* postEffect;


	Billborad* billboard;

	CubeSky* sky;

	Material* floor;
	Material* stone;
	Material* brick;
	Material* wall;

	MeshRender* cube;
	MeshRender* cylinder;
	MeshRender* sphere;
	MeshRender* grid;

	ModelRender* airplane = NULL;


	ModelAnimator* kachujin = NULL;
	Transform* colliderInitTransforms;
	ColliderObject** colliders;

	ModelRender* weapon = NULL;
	Transform* weaponInitTransform;

	vector<MeshRender*> meshes;
	vector<ModelRender*> models;
	vector<ModelAnimator*> animators;
};

 

 

 

 

 

 

 

GaussianBlurDemo.cpp


더보기
#include "stdafx.h"
#include "GaussianBlurDemo.h"

void GaussianBlurDemo::Initialize()
{
	Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
	Context::Get()->GetCamera()->Position(1, 36, -85);

	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(width, height);
	
	render2D = new Render2D();
	render2D->GetTransform()->Scale(355, 200, 1);
	render2D->GetTransform()->Position(200, 120, 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 GaussianBlurDemo::Update()
{
	sky->Update();

	cube->Update();
	grid->Update();
	cylinder->Update();
	sphere->Update();

	airplane->Update();
	kachujin->Update();

	Matrix worlds[MAX_MODEL_TRANSFORMS];
	for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
	{
		kachujin->GetAttachTransform(i, worlds);

		weapon->GetTransform(i)->World(weaponInitTransform->World() * worlds[40]);
	}

	weapon->UpdateTransforms();
	weapon->Update();

	billboard->Update();

	render2D->Update();
	postEffect->Update();
}

void GaussianBlurDemo::PreRender()
{
	// SRV, DSV를 세팅하고 그쪽 backBuffer를 클리어함
	// 다른 렌더타킷으로 교체하기까지 여기다가 계속 그려짐
	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);


	// GaussianBlurX
	{
		renderTarget[1]->PreRender(depthStencil);

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

	}
	
	// GaussianBlurX
	{
		renderTarget[2]->PreRender(depthStencil);

		postEffect->Pass(2);
		// BlurX 결과에 BlurY의 결과를 중첩
		postEffect->SRV(renderTarget[1]->SRV());
		postEffect->Render();

	}
}

void GaussianBlurDemo::Render()
{

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

	render2D->Render();
}


void GaussianBlurDemo::Billboards()
{
	billboard = new Billborad(shader);
	billboard->Pass(4);
	billboard->AddTexture(L"Terrain/grass_14.tga");
	billboard->AddTexture(L"Terrain/grass_07.tga");
	billboard->AddTexture(L"Terrain/grass_11.tga");
	
	for (UINT i = 0; i < 1200; i++)
	{
		Vector2 scale = Math::RandomVec2(1, 3);
		// 5(밑에 판 크기가 -5 ~ 5 -> 10) * 12(grid 크기) = 60
		Vector2 position = Math::RandomVec2(-60, 60);

		billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 0);
	}

	for (UINT i = 0; i < 300; i++)
	{
		Vector2 scale = Math::RandomVec2(1, 3);
		Vector2 position = Math::RandomVec2(-60, 60);

		billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 1);
	}

	for (UINT i = 0; i < 700; i++)
	{
		Vector2 scale = Math::RandomVec2(1, 3);
		Vector2 position = Math::RandomVec2(-60, 60);

		billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 2);
	}

}

void GaussianBlurDemo::Mesh()
{
	//Create Material
	{
		floor = new Material(shader);
		floor->DiffuseMap("Floor.png");
		floor->Specular(1, 1, 1, 20);
		floor->SpecularMap("Floor_Specular.png");
		floor->NormalMap("Floor_Normal.png");

		stone = new Material(shader);
		stone->DiffuseMap("Stones.png");
		stone->Specular(1, 1, 1, 20);
		stone->SpecularMap("Stones_Specular.png");
		stone->Emissive(1.0f, 1.0f, 1.0f, 0.3f);
		stone->NormalMap("Stones_Normal.png");


		brick = new Material(shader);
		brick->DiffuseMap("Bricks.png");
		brick->Specular(1, 0.3f, 0.3f, 20);
		brick->SpecularMap("Bricks_Specular.png");
		brick->Emissive(1.0f, 1.0f, 1.0f, 0.3f);
		brick->NormalMap("Bricks_Normal.png");

		wall = new Material(shader);
		wall->DiffuseMap("Wall.png");
		wall->Specular(1, 1, 1, 20);
		wall->SpecularMap("Wall_Specular.png");
		wall->Emissive(1.0f, 1.0f, 1.0f, 0.3f);
		wall->NormalMap("Wall_Normal.png");
	}

	//Create Mesh
	{
		Transform* transform = NULL;

		cube = new MeshRender(shader, new MeshCube());
		transform = cube->AddTransform();
		transform->Position(0, 5, 0);
		transform->Scale(20, 10, 20);

		grid = new MeshRender(shader, new MeshGrid(5, 5));
		transform = grid->AddTransform();
		transform->Position(0, 0, 0);
		transform->Scale(12, 1, 12);

		cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20));
		sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20));
		for (UINT i = 0; i < 5; i++)
		{
			transform = cylinder->AddTransform();
			transform->Position(-30, 6, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);

			transform = cylinder->AddTransform();
			transform->Position(30, 6, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);


			transform = sphere->AddTransform();
			transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);

			transform = sphere->AddTransform();
			transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);
		}
	}

	sphere->UpdateTransforms();
	cylinder->UpdateTransforms();
	cube->UpdateTransforms();
	grid->UpdateTransforms();

	meshes.push_back(sphere);
	meshes.push_back(cylinder);
	meshes.push_back(cube);
	meshes.push_back(grid);
}

void GaussianBlurDemo::Airplane()
{
	airplane = new ModelRender(shader);
	airplane->ReadMesh(L"B787/Airplane");
	airplane->ReadMaterial(L"B787/Airplane");

	Transform* transform = airplane->AddTransform();
	transform->Position(2.0f, 9.91f, 2.0f);
	transform->Scale(0.004f, 0.004f, 0.004f);
	airplane->UpdateTransforms();

	models.push_back(airplane);
}

void GaussianBlurDemo::Kachujin()
{
	kachujin = new ModelAnimator(shader);
	kachujin->ReadMesh(L"Kachujin/Mesh");
	kachujin->ReadMaterial(L"Kachujin/Mesh");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Idle");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Walk");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Run");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Slash");
	kachujin->ReadClip(L"Kachujin/Salsa Dancing");


	Transform* transform = NULL;

	transform = kachujin->AddTransform();
	transform->Position(0, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(0, 0, 1.0f);

	transform = kachujin->AddTransform();
	transform->Position(-15, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(1, 1, 1.0f);

	transform = kachujin->AddTransform();
	transform->Position(-30, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(2, 2, 0.75f);

	transform = kachujin->AddTransform();
	transform->Position(15, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayBlendMode(3, 0, 1, 2);
	kachujin->SetBlendAlpha(3, 1.5f);

	transform = kachujin->AddTransform();
	transform->Position(30, 0, -32.5f);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(4, 4, 0.75f);

	kachujin->UpdateTransforms();

	animators.push_back(kachujin);
}

void GaussianBlurDemo::KachujinCollider()
{
	UINT count = kachujin->GetTransformCount();
	colliders = new  ColliderObject * [count];

	colliderInitTransforms = new Transform();
	colliderInitTransforms->Position(-2.9f, 1.45f, -50.0f);
	colliderInitTransforms->Scale(5, 5, 75);

	for (UINT i = 0; i < count; i++)
	{
		colliders[i] = new ColliderObject();

		//colliders[i]->Init = new Transform();
		//colliders[i]->Init->Position(0, 0, 0);
		//colliders[i]->Init->Scale(10, 30, 10);

		colliders[i]->Transform = new Transform();
		//colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init);
		colliders[i]->Collider = new Collider(colliders[i]->Transform, colliderInitTransforms);
	}
}

void GaussianBlurDemo::KachujinWeapon()
{
	weapon = new ModelRender(shader);
	weapon->ReadMesh(L"Weapon/Sword");
	weapon->ReadMaterial(L"Weapon/Sword");

	UINT count = kachujin->GetTransformCount();
	for (UINT i = 0; i < count; i++)
		weapon->AddTransform();

	weapon->UpdateTransforms();
	models.push_back(weapon);


	weaponInitTransform = new Transform();
	weaponInitTransform->Position(-2.9f, 1.45f, -6.45f);
	weaponInitTransform->Scale(0.5f, 0.5f, 0.75f);
	weaponInitTransform->Rotation(0, 0, 1);
}

void GaussianBlurDemo::PointLighting()
{
	PointLight light;
	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient
		Color(0.0f, 0.0f, 1.0f, 1.0f), //Diffuse
		Color(0.0f, 0.0f, 0.7f, 1.0f), //Specular
		Color(0.0f, 0.0f, 0.7f, 1.0f), //Emissive
		Vector3(-30, 10, -30), 5.0f, 0.9f // 위치, 범위, 강도
	};
	Lighting::Get()->AddPointLight(light);

	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f),
		Color(1.0f, 0.0f, 0.0f, 1.0f),
		Color(0.6f, 0.2f, 0.0f, 1.0f),
		Color(0.6f, 0.3f, 0.0f, 1.0f),
		Vector3(15, 10, -30), 10.0f, 0.3f
	};
	Lighting::Get()->AddPointLight(light);

	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient
		Color(0.0f, 1.0f, 0.0f, 1.0f), //Diffuse
		Color(0.0f, 0.7f, 0.0f, 1.0f), //Specular
		Color(0.0f, 0.7f, 0.0f, 1.0f), //Emissive
		Vector3(-5, 1, -17.5f), 5.0f, 0.9f
	};
	Lighting::Get()->AddPointLight(light);

	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f),
		Color(0.0f, 0.0f, 1.0f, 1.0f),
		Color(0.0f, 0.0f, 0.7f, 1.0f),
		Color(0.0f, 0.0f, 0.7f, 1.0f),
		Vector3(-10, 1, -17.5f), 5.0f, 0.9f
	};
	Lighting::Get()->AddPointLight(light);
}

void GaussianBlurDemo::SpotLighting()
{
	SpotLight light;
	light =
	{
		Color(0.3f, 1.0f, 0.0f, 1.0f),
		Color(0.7f, 1.0f, 0.0f, 1.0f),
		Color(0.3f, 1.0f, 0.0f, 1.0f),
		Color(0.3f, 1.0f, 0.0f, 1.0f),
		Vector3(-15, 20, -30), 25.0f,
		Vector3(0, -1, 0), 30.0f, 0.4f
	};
	Lighting::Get()->AddSpotLight(light);

	light =
	{
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Vector3(0, 20, -30), 30.0f,
		Vector3(0, -1, 0), 40.0f, 0.55f
	};
	Lighting::Get()->AddSpotLight(light);
}

void GaussianBlurDemo::Pass(UINT mesh, UINT model, UINT anim)
{
	for (MeshRender* temp : meshes)
		temp->Pass(mesh);

	for (ModelRender* temp : models)
		temp->Pass(model);

	for (ModelAnimator* temp : animators)
		temp->Pass(anim);
}

 

 

MRT 사용시


 

 

GaussianBlurDemo2.h


더보기
#pragma once
#include "Systems/IExecute.h"

// Mrt로

class GaussianBlurDemo2 : public IExecute
{
public:
	virtual void Initialize() override;
	virtual void Ready() override {}
	virtual void Destroy() override {}
	virtual void Update() override;
	virtual void PreRender() override;
	virtual void Render() override;
	virtual void PostRender() override;
	virtual void ResizeScreen() override {}

private:
	void Billboards();
	void Mesh();
	void Airplane();
	void Kachujin();
	void KachujinCollider();
	void KachujinWeapon();
	void PointLighting();
	void SpotLighting();

	void Pass(UINT mesh, UINT model, UINT anim);

private:
	Shader* shader;

	// 0 : 원본, 1 : X 방향(GaussianBlur), 2: X 방향 + Y 방향
	RenderTarget* renderTarget[3];
	DepthStencil* depthStencil;
	// 메인의 Viewport를 사용해도 상관은 없지만,
	// RTV, DSV, Viewport를 1:1:1로 만드는 것이 편하다.
	Viewport* viewport;
	Render2D* render2D;
	// PostEffect 효과를 먹이기위해
	PostEffect* postEffect;


	Billborad* billboard;

	CubeSky* sky;

	Material* floor;
	Material* stone;
	Material* brick;
	Material* wall;

	MeshRender* cube;
	MeshRender* cylinder;
	MeshRender* sphere;
	MeshRender* grid;

	ModelRender* airplane = NULL;


	ModelAnimator* kachujin = NULL;
	Transform* colliderInitTransforms;
	ColliderObject** colliders;

	ModelRender* weapon = NULL;
	Transform* weaponInitTransform;

	vector<MeshRender*> meshes;
	vector<ModelRender*> models;
	vector<ModelAnimator*> animators;
};

 

 

 

 

 

 

 

GaussianBlurDemo2.cpp


더보기
#include "stdafx.h"
#include "GaussianBlurDemo2.h"

void GaussianBlurDemo2::Initialize()
{
	Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
	Context::Get()->GetCamera()->Position(1, 36, -85);

	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(width, height);
	
	render2D = new Render2D();
	render2D->GetTransform()->Scale(355, 200, 1);
	render2D->GetTransform()->Position(200, 120, 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::Update()
{
	sky->Update();

	cube->Update();
	grid->Update();
	cylinder->Update();
	sphere->Update();

	airplane->Update();
	kachujin->Update();

	Matrix worlds[MAX_MODEL_TRANSFORMS];
	for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
	{
		kachujin->GetAttachTransform(i, worlds);

		weapon->GetTransform(i)->World(weaponInitTransform->World() * worlds[40]);
	}

	weapon->UpdateTransforms();
	weapon->Update();

	billboard->Update();

	render2D->Update();
	postEffect->Update();
}

void GaussianBlurDemo2::PreRender()
{
	// SRV, DSV를 세팅하고 그쪽 backBuffer를 클리어함
	// 다른 렌더타킷으로 교체하기까지 여기다가 계속 그려짐
	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();
	}

	// Combine(RTV 합치기)
	{
		renderTarget[0]->PreRender(depthStencil);

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

		postEffect->Pass(4);
		// 2개 리소스 그대로 집어놈
		// 1. 들어갈 배열 2. 몇번 부터 넣을 꺼냐 3. 몇개 넣을 꺼냐
		postEffect->GetShader()->AsSRV("GaussianMrt")->SetResourceArray(srvs, 0, 2);
		postEffect->Render();
	}
}

void GaussianBlurDemo2::Render()
{

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

	render2D->Render();
}


void GaussianBlurDemo2::Billboards()
{
	billboard = new Billborad(shader);
	billboard->Pass(4);
	billboard->AddTexture(L"Terrain/grass_14.tga");
	billboard->AddTexture(L"Terrain/grass_07.tga");
	billboard->AddTexture(L"Terrain/grass_11.tga");
	
	for (UINT i = 0; i < 1200; i++)
	{
		Vector2 scale = Math::RandomVec2(1, 3);
		// 5(밑에 판 크기가 -5 ~ 5 -> 10) * 12(grid 크기) = 60
		Vector2 position = Math::RandomVec2(-60, 60);

		billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 0);
	}

	for (UINT i = 0; i < 300; i++)
	{
		Vector2 scale = Math::RandomVec2(1, 3);
		Vector2 position = Math::RandomVec2(-60, 60);

		billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 1);
	}

	for (UINT i = 0; i < 700; i++)
	{
		Vector2 scale = Math::RandomVec2(1, 3);
		Vector2 position = Math::RandomVec2(-60, 60);

		billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 2);
	}

}

void GaussianBlurDemo2::Mesh()
{
	//Create Material
	{
		floor = new Material(shader);
		floor->DiffuseMap("Floor.png");
		floor->Specular(1, 1, 1, 20);
		floor->SpecularMap("Floor_Specular.png");
		floor->NormalMap("Floor_Normal.png");

		stone = new Material(shader);
		stone->DiffuseMap("Stones.png");
		stone->Specular(1, 1, 1, 20);
		stone->SpecularMap("Stones_Specular.png");
		stone->Emissive(1.0f, 1.0f, 1.0f, 0.3f);
		stone->NormalMap("Stones_Normal.png");


		brick = new Material(shader);
		brick->DiffuseMap("Bricks.png");
		brick->Specular(1, 0.3f, 0.3f, 20);
		brick->SpecularMap("Bricks_Specular.png");
		brick->Emissive(1.0f, 1.0f, 1.0f, 0.3f);
		brick->NormalMap("Bricks_Normal.png");

		wall = new Material(shader);
		wall->DiffuseMap("Wall.png");
		wall->Specular(1, 1, 1, 20);
		wall->SpecularMap("Wall_Specular.png");
		wall->Emissive(1.0f, 1.0f, 1.0f, 0.3f);
		wall->NormalMap("Wall_Normal.png");
	}

	//Create Mesh
	{
		Transform* transform = NULL;

		cube = new MeshRender(shader, new MeshCube());
		transform = cube->AddTransform();
		transform->Position(0, 5, 0);
		transform->Scale(20, 10, 20);

		grid = new MeshRender(shader, new MeshGrid(5, 5));
		transform = grid->AddTransform();
		transform->Position(0, 0, 0);
		transform->Scale(12, 1, 12);

		cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20));
		sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20));
		for (UINT i = 0; i < 5; i++)
		{
			transform = cylinder->AddTransform();
			transform->Position(-30, 6, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);

			transform = cylinder->AddTransform();
			transform->Position(30, 6, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);


			transform = sphere->AddTransform();
			transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);

			transform = sphere->AddTransform();
			transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f);
			transform->Scale(5, 5, 5);
		}
	}

	sphere->UpdateTransforms();
	cylinder->UpdateTransforms();
	cube->UpdateTransforms();
	grid->UpdateTransforms();

	meshes.push_back(sphere);
	meshes.push_back(cylinder);
	meshes.push_back(cube);
	meshes.push_back(grid);
}

void GaussianBlurDemo2::Airplane()
{
	airplane = new ModelRender(shader);
	airplane->ReadMesh(L"B787/Airplane");
	airplane->ReadMaterial(L"B787/Airplane");

	Transform* transform = airplane->AddTransform();
	transform->Position(2.0f, 9.91f, 2.0f);
	transform->Scale(0.004f, 0.004f, 0.004f);
	airplane->UpdateTransforms();

	models.push_back(airplane);
}

void GaussianBlurDemo2::Kachujin()
{
	kachujin = new ModelAnimator(shader);
	kachujin->ReadMesh(L"Kachujin/Mesh");
	kachujin->ReadMaterial(L"Kachujin/Mesh");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Idle");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Walk");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Run");
	kachujin->ReadClip(L"Kachujin/Sword And Shield Slash");
	kachujin->ReadClip(L"Kachujin/Salsa Dancing");


	Transform* transform = NULL;

	transform = kachujin->AddTransform();
	transform->Position(0, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(0, 0, 1.0f);

	transform = kachujin->AddTransform();
	transform->Position(-15, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(1, 1, 1.0f);

	transform = kachujin->AddTransform();
	transform->Position(-30, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(2, 2, 0.75f);

	transform = kachujin->AddTransform();
	transform->Position(15, 0, -30);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayBlendMode(3, 0, 1, 2);
	kachujin->SetBlendAlpha(3, 1.5f);

	transform = kachujin->AddTransform();
	transform->Position(30, 0, -32.5f);
	transform->Scale(0.075f, 0.075f, 0.075f);
	kachujin->PlayTweenMode(4, 4, 0.75f);

	kachujin->UpdateTransforms();

	animators.push_back(kachujin);
}

void GaussianBlurDemo2::KachujinCollider()
{
	UINT count = kachujin->GetTransformCount();
	colliders = new  ColliderObject * [count];

	colliderInitTransforms = new Transform();
	colliderInitTransforms->Position(-2.9f, 1.45f, -50.0f);
	colliderInitTransforms->Scale(5, 5, 75);

	for (UINT i = 0; i < count; i++)
	{
		colliders[i] = new ColliderObject();

		//colliders[i]->Init = new Transform();
		//colliders[i]->Init->Position(0, 0, 0);
		//colliders[i]->Init->Scale(10, 30, 10);

		colliders[i]->Transform = new Transform();
		//colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init);
		colliders[i]->Collider = new Collider(colliders[i]->Transform, colliderInitTransforms);
	}
}

void GaussianBlurDemo2::KachujinWeapon()
{
	weapon = new ModelRender(shader);
	weapon->ReadMesh(L"Weapon/Sword");
	weapon->ReadMaterial(L"Weapon/Sword");

	UINT count = kachujin->GetTransformCount();
	for (UINT i = 0; i < count; i++)
		weapon->AddTransform();

	weapon->UpdateTransforms();
	models.push_back(weapon);


	weaponInitTransform = new Transform();
	weaponInitTransform->Position(-2.9f, 1.45f, -6.45f);
	weaponInitTransform->Scale(0.5f, 0.5f, 0.75f);
	weaponInitTransform->Rotation(0, 0, 1);
}

void GaussianBlurDemo2::PointLighting()
{
	PointLight light;
	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient
		Color(0.0f, 0.0f, 1.0f, 1.0f), //Diffuse
		Color(0.0f, 0.0f, 0.7f, 1.0f), //Specular
		Color(0.0f, 0.0f, 0.7f, 1.0f), //Emissive
		Vector3(-30, 10, -30), 5.0f, 0.9f // 위치, 범위, 강도
	};
	Lighting::Get()->AddPointLight(light);

	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f),
		Color(1.0f, 0.0f, 0.0f, 1.0f),
		Color(0.6f, 0.2f, 0.0f, 1.0f),
		Color(0.6f, 0.3f, 0.0f, 1.0f),
		Vector3(15, 10, -30), 10.0f, 0.3f
	};
	Lighting::Get()->AddPointLight(light);

	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient
		Color(0.0f, 1.0f, 0.0f, 1.0f), //Diffuse
		Color(0.0f, 0.7f, 0.0f, 1.0f), //Specular
		Color(0.0f, 0.7f, 0.0f, 1.0f), //Emissive
		Vector3(-5, 1, -17.5f), 5.0f, 0.9f
	};
	Lighting::Get()->AddPointLight(light);

	light =
	{
		Color(0.0f, 0.0f, 0.0f, 1.0f),
		Color(0.0f, 0.0f, 1.0f, 1.0f),
		Color(0.0f, 0.0f, 0.7f, 1.0f),
		Color(0.0f, 0.0f, 0.7f, 1.0f),
		Vector3(-10, 1, -17.5f), 5.0f, 0.9f
	};
	Lighting::Get()->AddPointLight(light);
}

void GaussianBlurDemo2::SpotLighting()
{
	SpotLight light;
	light =
	{
		Color(0.3f, 1.0f, 0.0f, 1.0f),
		Color(0.7f, 1.0f, 0.0f, 1.0f),
		Color(0.3f, 1.0f, 0.0f, 1.0f),
		Color(0.3f, 1.0f, 0.0f, 1.0f),
		Vector3(-15, 20, -30), 25.0f,
		Vector3(0, -1, 0), 30.0f, 0.4f
	};
	Lighting::Get()->AddSpotLight(light);

	light =
	{
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Color(1.0f, 0.2f, 0.9f, 1.0f),
		Vector3(0, 20, -30), 30.0f,
		Vector3(0, -1, 0), 40.0f, 0.55f
	};
	Lighting::Get()->AddSpotLight(light);
}

void GaussianBlurDemo2::Pass(UINT mesh, UINT model, UINT anim)
{
	for (MeshRender* temp : meshes)
		temp->Pass(mesh);

	for (ModelRender* temp : models)
		temp->Pass(model);

	for (ModelAnimator* temp : animators)
		temp->Pass(anim);
}

 

 

 

 

 

 

 

 

 

104_GaussianBlur.fx


더보기
#include "00_Global.fx"
#include "00_Light.fx"


float2 PixelSize;

struct VertexOutput
{
    float4 Positon : SV_Position;
    float2 Uv : Uv;
};

VertexOutput VS(float4 Position : Position)
{
    VertexOutput output;
    
    output.Positon = 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 input) : SV_Target
{
    return DiffuseMap.Sample(LinearSampler, input.Uv);
}

// 가우스함수로 만들어 놓은 상수(테스트용)
// bloom에서 다룰 예정(가우스함수식은)
const int GaussBlurCount = 6;
static const float Weights[13] =
{
    0.0561f, 0.1353f, 0.2780f, 0.4868f, 0.7261f, 0.9231f, // x방향이됨, 6, 5, 4, 3, 2, 1
    1.0f, // 현재 픽셀에 대한 값, 0
    0.9231f, 0.7261f, 0.4868f, 0.2780f, 0.1353f, 0.0561f // y방향이됨
};

// 위에서는 한번에 다했지만, 원래는 x방향 한번 먹이고, y방향 한번먹이는 방식 사용
float4 PS_GaussianBlurX(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++)
    {
        // 픽셀의 크기만큼 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 
{
    // x,y 결과를 위해 2개 RTV
    float4 Color0 : SV_Target0;
    float4 Color1 : SV_Target1;
};

// GaussianX,Y가 합쳐진 함수(MRT로 이용가능)
// 결과를 동시에 내보내기 위해 MRT를 사용
// 결과가 2개의 RTV로 한번에 나옴
PixelOutput_GaussianBlur2 PS_GaussianBlurMrt(VertexOutput input)
{
    PixelOutput_GaussianBlur2 output;
    
    // X
    float2 uv = input.Uv;
    float u = PixelSize.x;
    
    float sum = 0;
    float4 color = 0;
    for (int i = -GaussBlurCount; i <= GaussBlurCount; i++)
    {
        // 픽셀의 크기만큼 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.0f);
    
    // Y
    float v = PixelSize.y;
    
    sum = 0;
    color = 0;
    for (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;
    
    output.Color1 = float4(color.rgb, 1);
    
    return output;
}

// Combine : 합쳐져 있다는 뜻
// Combined : MRT로 부터 나온 두개의 타깃(BlurX, BlurY)을 합치는 픽셀 셰이더
// 2개의 SRV 결과를 합쳐줌

Texture2D GaussianMrt[2];
float4 PS_GaussianBlurCombined(VertexOutput input) : SV_Target
{
    float4 color = GaussianMrt[0].Sample(LinearSampler, input.Uv);
    float4 color2 = GaussianMrt[1].Sample(LinearSampler, input.Uv);

    // 두 픽셀을 합쳐서 평균을 냄(두 개의 RTV의 픽셀이 합쳐진다.)
    return float4((color.rgb + color2.rgb) * 0.5f, 1.0f);
}

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

 

 

 

 

 

 

 

 

 

 

 

결과


GaussianBlurDemo2 사용(MRT 활용)