필요한 개념
Blur(블러링) : 화면을 흐리게 해주는 효과
Blur는 주변 픽셀을 흐리게 해주는 효과
Blur는 주변의 픽셀을 합하고 평균을 구함
1. 기본 Blur
BlurCount를 올릴수록 더욱 흐려지지만(프레임이 박살남(샘플링해야할 픽셀이 늘어나서))
2. RadialBlur(원형 Blur)
속도를 넣을때 중앙점기준으로 바깥으로 퍼져나가는 것에 쓰임
중심점을 기준으로 밖으로 펴져나가는 효과
되게 많이 사용한다.
카메라 중심점으로 확 땡길때 사용
RadialBlurCount -> 찐해짐
RadialBlurRadius -> 거리
RadialBlurAmount-> 강도
Center x, y -> 중심점 위치
Blur : 주변의 픽셀을 합산하여 평균을 계산
BlurDemo.h
더보기
#pragma once
#include "Systems/IExecute.h"
class BlurDemo : 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;
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;
};
BlurDemo.cpp
더보기
#include "stdafx.h"
#include "BlurDemo.h"
void BlurDemo::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 = 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->SRV());
postEffect = new PostEffect(L"104_Blur.fxo");
sky = new CubeSky(L"Environment/GrassCube1024.dds");
Billboards();
Mesh();
Airplane();
Kachujin();
KachujinCollider();
KachujinWeapon();
PointLighting();
SpotLighting();
}
void BlurDemo::Update()
{
// PassCount() : pass 개수 구해옴
static UINT Pass = postEffect->GetShader()->PassCount() - 1;
ImGui::InputInt("Blur Pass", (int*)&Pass);
Pass %= postEffect->GetShader()->PassCount();
postEffect->Pass(Pass);
//Blur
{
Vector2 PixelSize = Vector2(1.0f / D3D::Width(), 1.0f / D3D::Height());
postEffect->GetShader()->AsVector("PixelSize")->SetFloatVector(PixelSize);
static UINT BlurCount = 8;
ImGui::InputInt("Blur Count", (int*)&BlurCount);
postEffect->GetShader()->AsScalar("BlurCount")->SetInt(BlurCount);
}
//RadialBlur
{
ImGui::Separator();
static UINT BlurCount = 8;
ImGui::InputInt("RadialBlurCount", (int*)&BlurCount);
BlurCount %= 32;
postEffect->GetShader()->AsScalar("RadialBlurCount")->SetInt(BlurCount);
static float Radius = 0.6f;
ImGui::InputFloat("RadialBlurRadius", &Radius, 0.01f);
postEffect->GetShader()->AsScalar("RadialBlurRadius")->SetFloat(Radius);
static float Amount = 0.04f;
ImGui::InputFloat("RadialBlurAmount", &Amount, 0.001f);
postEffect->GetShader()->AsScalar("RadialBlurAmount")->SetFloat(Amount);
static float CenterX = 0.5f;
ImGui::InputFloat("CenterX", &CenterX, 0.01f);
static float CenterY = 0.5f;
ImGui::InputFloat("CenterY", &CenterY, 0.01f);
postEffect->GetShader()->AsVector("RadialCenter")->SetFloatVector(Vector2(CenterX, CenterY));
}
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 BlurDemo::PreRender()
{
// SRV, DSV를 세팅하고 그쪽 backBuffer를 클리어함
// 다른 렌더타킷으로 교체하기까지 여기다가 계속 그려짐
renderTarget->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();
}
}
void BlurDemo::Render()
{
// 여기다가 메인 렌더링을 함
// 파일로 저장해봄, 파일 텍스쳐 포맷이 달라져서 색이 다르게 나옴(나중에 옵션 찾아서 해결하면 됨)
//if (Keyboard::Get()->Down(VK_SPACE))
// renderTarget->SaveTexture(L"../RenderTarget.png");
}
void BlurDemo::PostRender()
{
postEffect->SRV(renderTarget->SRV());
postEffect->Render();
render2D->Render();
}
void BlurDemo::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 BlurDemo::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 BlurDemo::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 BlurDemo::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 BlurDemo::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 BlurDemo::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 BlurDemo::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 BlurDemo::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 BlurDemo::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_Blur.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);
}
uint BlurCount = 8; // Blur를 몇개 픽셀로 할 건지
// 주변 픽셀을 평균을 낼 것이다.
float4 PS_Blur(VertexOutput input) : SV_Target
{
// 0번 좌상단, 1번 상단, 2번 우상단 순서로 9개의 픽셀을 만들어줌
// UV에다가 그대로 더할 것이다.
float2 arr[9] =
{
float2(-1, -1), float2(0, -1), float2(+1, -1), // 좌상단, 상단, 우상단
float2(-1, 0), float2(0, 0), float2(+1, 0), // 좌, 자기, 우
float2(-1, +1), float2(0, +1), float2(+1, +1) // 좌하단, 하단, 우하단
};
float3 color = 0;
// blur 1개 마다 9번의 픽셀을 구하고 있다.
// 0번은 자기자신이어서 필요가 없다.
for (uint blur = 1; blur < BlurCount; blur++)
{
for (int i = 0; i < 9; i++)
{
// 픽셀을 불름(좌상단, 우상단)...
// blur가 1일때 (그만큼 이동한 위치에서)
float x = arr[i].x * (float) blur * PixelSize.x;
float y = arr[i].y * (float) blur * PixelSize.y;
float2 uv = input.Uv + float2(x, y);
// 컬러에 누적
color += DiffuseMap.Sample(LinearSampler, uv).rgb;
}
}
// 평균을 냄
color /= BlurCount * 9;
return float4(color.rgb, 1.0f);
}
uint RadialBlurCount = 8;
float RadialBlurRadius = 0.0f;
float RadialBlurAmount = 0.04f; //4%
float2 RadialCenter = float2(0.5f, 0.5f);
// 중심점을 기준으로 사방을 Blur먹임
// 원형 Blur
float4 PS_RadialBlur(VertexOutput input) : SV_Target
{
// uv에서 중심점 빼고 반지름 만듬
float2 radius = input.Uv - RadialCenter;
float r = length(radius) + 1e-6f;
radius /= r;
// 지름 만듬
r = 2 * r / RadialBlurRadius;
r = saturate(r);
float2 delta = radius * r * r * RadialBlurAmount / RadialBlurCount;
delta = -delta;
float4 color = 0;
for (uint i = 0; i < RadialBlurCount; i++)
{
color += DiffuseMap.Sample(LinearSampler, input.Uv);
input.Uv += delta;
}
color /= RadialBlurCount;
return float4(color.rgb, 1);
}
technique11 T0
{
P_VP(P0, VS, PS_Diffuse)
P_VP(P1, VS, PS_Blur)
P_VP(P2, VS, PS_RadialBlur)
}
결과
'DirectX11 3D > 기본 문법' 카테고리의 다른 글
<DirectX11 3D> 106 - Bloom (0) | 2022.03.22 |
---|---|
<DirectX11 3D> 105 - GaussianBlur (0) | 2022.03.22 |
<DirectX11 3D> 103 - MRT(MultiRenderTarget) (0) | 2022.03.21 |
<DirectX11 3D> 100 - ColorTone(PostEffect) (0) | 2022.03.21 |
<DirectX11 3D> 99 - RenderTargetView (0) | 2022.03.17 |