[DirectX11] 106 Bloom
Bloom은 카메라 렌즈에서 빛이 작동하는 방식을 시뮬레이션하기 위해 그래픽 및 게임에서 사용되는 시각 효과다. 밝은 물체 주위에 빛나는 효과를 만든다.
목차
Bloom
다음의 과정을 거쳐 Bloom을 구현한다.
- 장면을 텍스처로 렌더링: 첫 번째 단계는 장면을 BackBuffer 대신 텍스처로 렌더링하는 것이다. 이를 통해 원래 렌더링된 이미지에 영향을 주지 않고 장면에 후처리 효과를 적용할 수 있다.
- 임계값 적용: 다음으로 텍스처에 임계값을 적용하여 장면에서 밝은 픽셀을 식별한다. 이는 각 픽셀의 색상 값을 임계값과 비교하여 수행된다. 픽셀의 색상 값이 임계값보다 크면 밝은 픽셀로 간주되어 추가 처리된다.
- 밝은 픽셀 추출: 픽셀 셰이더를 사용하여 다른 텍스처로 렌더링하여 장면에서 밝은 픽셀을 추출한다. 이 쉐이더는 블러링 또는 글로우 효과 추가와 같은 원하는 효과를 밝은 픽셀에 적용하는 데 사용할 수 있다.
- 밝은 픽셀을 원본 장면과 결합: 밝은 픽셀을 원본 텍스처 위에 렌더링하여 원본 장면과 결합한다. 이것은 두 텍스처를 함께 혼합하여 최종 블룸 효과를 생성하는 또 다른 픽셀 셰이더를 사용하여 수행된다.
- BackBuffer로 렌더링: 마지막으로 결합된 텍스처를 백 버퍼로 렌더링하여 표시합니다.
DirectX에서 Bloom을 구현하려면 Post Effect 기술을 사용하여 장면에서 밝은 픽셀을 식별하고 추출한 다음 원본 장면과 결합하여 빛나거나 후광 효과를 만든다.
Bloom.fx
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 input) : SV_Target { return DiffuseMap.Sample(LinearSampler, input.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) }
float Threshold = 0.6f; float4 PS_Luminosity(VertexOutput input) : SV_Target { float4 color = DiffuseMap.Sample(LinearSampler, input.Uv); return saturate((color - Threshold) / (1 - Threshold)); }
threshold보다
- 작은 값은 어두워진다.
- 큰 값은 밝아진다.
threshold보다 큰 값을 추출한다. 이렇게해서 밝은면을 추출한다.
Bloom Demo
BloomDemo.h
더보기
#pragma once #include "Systems/IExecute.h" class BloomDemo : 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: void SetBlur(); void GetBlurParameter(vector<float>& weights, vector<Vector2>& offsets, float x, float y); float GetGaussFunction(float val); private: bool bOrigin = false; float threshold = 0.05f; UINT blurCount = 15; //가중치 계산 vector<float> weightX; vector<Vector2> offsetX; vector<float> weightY; vector<Vector2> offsetY; private: Shader* shader; RenderTarget* renderTarget[5]; DepthStencil* depthStencil; Viewport* viewport; Render2D* render2D; PostEffect* postEffect; Billboard* 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; };
가중치 계산
- vector<float> weightX;
- vector<Vector2> offsetX;
- vector<float> weightY;
- vector<Vector2> offsetY;
BloomDemo.cpp
더보기
#include "stdafx.h" #include "BloomDemo.h" void BloomDemo::Initialize() { Context::Get()->GetCamera()->RotationDegree(20, 0, 0); Context::Get()->GetCamera()->Position(1, 36, -85); ((Freedom *)Context::Get()->GetCamera())->Speed(50, 2); shader = new Shader(L"96_Billboard.fxo"); float width = D3D::Width(), height = D3D::Height(); width = height = 4096; renderTarget[0] = new RenderTarget((UINT)width, (UINT)height); //Diffuse renderTarget[1] = new RenderTarget((UINT)width, (UINT)height); //Luminosity renderTarget[2] = new RenderTarget((UINT)width, (UINT)height); //BlurX renderTarget[3] = new RenderTarget((UINT)width, (UINT)height); //BlurY renderTarget[4] = new RenderTarget((UINT)width, (UINT)height); //Composite 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"106_Bloom.fxo"); sky = new CubeSky(L"Environment/GrassCube1024.dds"); Billboards(); Mesh(); Airplane(); Kachujin(); KachujinCollider(); KachujinWeapon(); PointLighting(); SpotLighting(); } void BloomDemo::Update() { static bool bOrigin = false; ImGui::Checkbox("Origin", &bOrigin); ImGui::InputFloat("Threshold", &threshold, 0.01f); postEffect->GetShader()->AsScalar("Threshold")->SetFloat(threshold); ImGui::InputInt("BlurCount", (int *)&blurCount, 2); blurCount %= 33; if (blurCount < 1) blurCount = 1; postEffect->GetShader()->AsScalar("BlurCount")->SetInt(blurCount); 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 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); //Luminosity { renderTarget[1]->PreRender(depthStencil); postEffect->Pass(1); postEffect->SRV(renderTarget[0]->SRV()); postEffect->Render(); } SetBlur(); //Blur값을 계산하고 넘겨준다. //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(); } //Comsite { 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::Billboards() { billboard = new Billboard(shader); //billboard->Pass(3); 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); 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 BloomDemo::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(0.15f, 0.15f, 0.15f, 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(0.15f, 0.15f, 0.15f, 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(0.15f, 0.15f, 0.15f, 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 BloomDemo::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 BloomDemo::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 BloomDemo::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 BloomDemo::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 BloomDemo::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 BloomDemo::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 BloomDemo::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); } 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))); }
실행화면

'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 111-112 Projector (0) | 2023.05.10 |
---|---|
[DirectX11] 107-110 Dynamic Cube Map (0) | 2023.05.05 |
[DirectX11] 104-105 Blur, Gaussian Blur (0) | 2023.04.28 |
[DirectX11] 103 MRT(Multiple Render Targets) (0) | 2023.04.27 |
[DirectX11] 099~102 Render Target, Post Effect(Color Tone) (0) | 2023.04.18 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 111-112 Projector
[DirectX11] 111-112 Projector
2023.05.10투영은 3D 공간에서의 객체를 2D 화면에 어떻게 표현할 것인지를 결정하는 과정이다. 이 과정에서 VS 단계에서 WVP(World, View, Projection) 변환된 결과가 SV_Position을 기준으로 2D 좌표로 레스터라이징되어 화면에 표현된다. 하지만, 이렇게 레스터라이징된 2D 좌표는 쉐이더로부터 바로 리턴받을 수 없기 때문에, CPU를 통해 VS, RS에서 사용된 같은 수식을 통해 2D 변환된 위치를 계산하고, 그 위치에 UI 요소를 배치하기 위해 사용된다. 목차 Projector Shaders Light.fxProjector.fx 생성Framework Objects Projector.h .cpp 생성 Viewer Fixity.h .cpp 생성UnitTest Objects Pro… -
[DirectX11] 107-110 Dynamic Cube Map
[DirectX11] 107-110 Dynamic Cube Map
2023.05.05큐브맵은 3D 그래픽스에서 환경 맵핑(environment mapping)에 주로 사용되며, 사실적인 조명 효과와 반사 효과를 구현하는 데 필수적이다. 큐브맵 UV는 큐브맵을 효율적으로 활용하는 기술로, 3D 공간에서의 객체와 환경 사이의 상호작용을 정교하게 표현하게 해준다. 목차 Dynamic Cube Map Shaders Global.fxDynamicCubMap.fx 생성Framework Objects DynamicCubeMap.h .cpp 생성UnitTest Objects DynamicCubeMapDemo.h .cpp 생성 Dynamic Cube Map 매핑 원리 View[6] - GS에서 생성 Projection 큐브맵(CubeMap)큐브맵은 하나의 텍스처가 아닌 6개의 면으로… -
[DirectX11] 104-105 Blur, Gaussian Blur
[DirectX11] 104-105 Blur, Gaussian Blur
2023.04.28DirectX 11에서 Blur는 이미지를 초점이 맞지 않거나 흐릿하게 보이게 하는 시각적 효과를 말한다. 이 효과는 종종 그래픽과 게임에서 필드 깊이를 시뮬레이션하거나 이미지의 가장자리를 부드럽게 하는 데 사용된다. Blur 효과를 생성하기 위한 다양한 기법이 있으며, 가장 일반적으로 사용되는 기법 중 하나는 Gaussian Blur다. 목차 Blur Gaussian blur는 가우스 함수로 이미지를 합성하여 작동하는 블러의 일종이다. 이 기능은 각 픽셀에 적용되는 흐림의 양을 결정하는 종 모양의 곡선을 가지고 있다. 픽셀이 주변 영역에 더 많은 픽셀을 가질수록 픽셀은 더 흐려진다. 가우스 블러 효과는 부드럽고 자연스럽게 보이는 흐림을 생성하기 때문에 종종 사용되며, 다양한 수준의 흐림을 달성하기 위해… -
[DirectX11] 103 MRT(Multiple Render Targets)
[DirectX11] 103 MRT(Multiple Render Targets)
2023.04.27MRT(Multiple Render Targets)는 한 번의 추첨 통화에서 둘 이상의 렌더 대상에 렌더링할 수 있는 기능을 말한다. 기존 렌더링 파이프라인에서는 하나의 렌더링 대상(백 버퍼)만 사용하여 화면에 최종 결과를 표시한다. 그러나 복잡한 후 처리 효과를 구현하거나 지연된 렌더링 기법을 구현하거나 섀도 매핑을 수행하는 경우와 같이 여러 렌더 대상에 동시에 렌더링해야 하는 상황이 있다. 목차 MRT(Multiple Render Targets) MRT(Multiple Render Targets)는 한 번의 추첨 통화에서 둘 이상의 렌더 대상에 렌더링할 수 있는 기능을 말한다. 기존 렌더링 파이프라인에서는 하나의 렌더링 대상(백 버퍼)만 사용하여 화면에 최종 결과를 표시한다. 그러나 복잡한 후 처리 …
댓글을 사용할 수 없습니다.