[DirectX11] 096~98 Geometry Shader
Geometry Shader는 정점 셰이더(Vertex shader) 뒤와 픽셀 셰이더(Pixel shader) 앞에서 실행되는 셰이더 유형이다. 이것은 정점 셰이더 단독보다 더 복잡한 기하학적 조작을 가능하게 하며, 새로운 꼭짓점을 생성하거나 메쉬의 위상을 변경하거나 기하학에 다른 변환을 적용하는 데 사용한다.
목차
Geometry Shader
Shaders | |
Light.fx Billboard.fx |
|
Framework | |
Viewer | |
Billboard.h .cpp | |
P | |
BillboardDemo.h .cpp | |
렌더링 순서 DirectX9 vs. DirectX10
DirectX9
- IA → VS → RS → PS → OM
DirectX10
- IA → VS → GS →SO(요즘은 잘 안 쓴다) → RS → PS → OM
Light.fx 추가코드
Light.fx 추가코드
더보기
float4 PS_AllLight(MeshOutput input) { NormalMapping(input.Uv, input.Normal, input.Tangent); Texture(Material.Diffuse, DiffuseMap, input.Uv); Texture(Material.Specular, SpecularMap, input.Uv); MaterialDesc output = MakeMaterial(); MaterialDesc result = MakeMaterial(); ComputeLight(output, input.Normal, input.wPosition); AddMaterial(result, output); ComputePointLight(output, input.Normal, input.wPosition); AddMaterial(result, output); ComputeSpotLight(output, input.Normal, input.wPosition); AddMaterial(result, output); return float4(MaterialToColor(result).rgb, 1.0f); }
Billboard.fx
Billboard.fx
더보기
#include "00_Global.fx" #include "00_Light.fx" #include "00_Render.fx" float4 PS(MeshOutput input) : SV_Target { return PS_AllLight(input); } struct VertexBillboard { float4 Position : Position; float2 Scale : Scale; uint MapIndex : MapIndex; //uint VertexIndex : SV_VertexID; }; struct VertexOutput { float4 Position : Position; float2 Scale : Scale; uint MapIndex : MapIndex; }; VertexOutput VS(VertexBillboard input) { VertexOutput output; output.Position = WorldPosition(input.Position); output.Scale = input.Scale; output.MapIndex = input.MapIndex; return output; } struct GeometryOutput { float4 Position : SV_Position; float2 Uv : Uv; uint MapIndex : MapIndex; }; [maxvertexcount(4)] void GS_Billboard(point VertexOutput input[1], inout TriangleStream<GeometryOutput> stream) { float3 up = float3(0, 1, 0); //float3 forward = float3(0, 0, 1); float3 forward = input[0].Position.xyz - ViewPosition(); float3 right = normalize(cross(up, forward));//up과 forward를 외적한 후에 정규화해준다. float2 size = input[0].Scale * 0.5f; float4 position[4]; position[0] = float4(input[0].Position.xyz - size.x * right - size.y * up, 1);//좌하단 position[1] = float4(input[0].Position.xyz - size.x * right + size.y * up, 1);//좌상단 position[2] = float4(input[0].Position.xyz + size.x * right - size.y * up, 1);//우하단 position[3] = float4(input[0].Position.xyz + size.x * right + size.y * up, 1);//우상단 float2 uv[4] = { float2(0, 1), float2(0, 0), float2(1, 1), float2(1, 0) }; GeometryOutput output; //자료형 [unroll(4)] //정점 4개 처리 for (int i = 0; i < 4; i++) { output.Position = ViewProjection(position[i]); output.Uv = uv[i]; output.MapIndex = input[0].MapIndex; stream.Append(output);//TriangleStream을 추가한다. } } [maxvertexcount(8)] void GS_Cross(point VertexOutput input[1], inout TriangleStream<GeometryOutput> stream) { float3 up = float3(0, 1, 0); float3 forward = float3(0, 0, 1); float3 right = normalize(cross(up, forward)); float2 size = input[0].Scale * 0.5f; float4 position[8]; position[0] = float4(input[0].Position.xyz - size.x * right - size.y * up, 1); position[1] = float4(input[0].Position.xyz - size.x * right + size.y * up, 1); position[2] = float4(input[0].Position.xyz + size.x * right - size.y * up, 1); position[3] = float4(input[0].Position.xyz + size.x * right + size.y * up, 1); position[4] = float4(input[0].Position.xyz - size.x * forward - size.y * up, 1); position[5] = float4(input[0].Position.xyz - size.x * forward + size.y * up, 1); position[6] = float4(input[0].Position.xyz + size.x * forward - size.y * up, 1); position[7] = float4(input[0].Position.xyz + size.x * forward + size.y * up, 1); float2 uv[4] = { float2(0, 1), float2(0, 0), float2(1, 1), float2(1, 0) }; GeometryOutput output; [unroll(8)] for (int i = 0; i < 8; i++) { output.Position = ViewProjection(position[i]); output.Uv = uv[i % 4]; output.MapIndex = input[0].MapIndex; stream.Append(output); [flatten] if(i == 3) stream.RestartStrip(); } } Texture2DArray BillboardMap; float4 PS_Billboard(GeometryOutput input) : SV_Target { return BillboardMap.Sample(LinearSampler, float3(input.Uv, input.MapIndex)) * 1.75f; } technique11 T0 { P_VP(P0, VS_Mesh, PS) P_VP(P1, VS_Model, PS) P_VP(P2, VS_Animation, PS) P_BS_VGP(P3, AlphaBlend, VS, GS_Billboard, PS_Billboard) P_RS_BS_VGP(P4, CullMode_None, AlphaBlend_AlphaToCoverageEnable, VS, GS_Cross, PS_Billboard) }
void GS_Billboard(point VertexOutput input[1], inout TriangleStream<GeometryOutput> stream)
- point VertexOutput input[1]
- point list이기 때문에 하나만 받아온다.
- inout TriangleStream stream
- Geometry Shader는 삼각형만 다룬다.(사각형으로 사용이 불가능하다). 템플릿 문법을 사용하였다.

Billboard
Billboard.h
더보기
#pragma once #define MAX_BILLBOARD_COUNT 10000 class Billboard : public Renderer { public: Billboard(Shader* shader); ~Billboard(); void Update(); void Render(); void Add(Vector3& position, Vector2& scale, UINT mapIndex); void AddTexture(wstring file); private: struct VertexBillboard { Vector3 Position; Vector2 Scale; UINT MapIndex; }; private: vector<VertexBillboard> vertices; vector<wstring> textureNames; TextureArray* textureArray = NULL; ID3DX11EffectShaderResourceVariable* sDiffuseMap; };
Billboard.cpp
더보기
#include "Framework.h" #include "Billboard.h" Billboard::Billboard(Shader* shader) : Renderer(shader) { Topology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); sDiffuseMap = shader->AsSRV("BillboardMap"); } Billboard::~Billboard() { SafeDelete(textureArray); } void Billboard::Update() { Super::Update(); } void Billboard::Render() { if (textureNames.size() > 0 && textureArray == NULL) { SafeDelete(textureArray); //textureArray가 바뀌는 경우가 발생하므로 지우고 textureArray = new TextureArray(textureNames);//textureArray를 그려준다. } if (vertexCount != vertices.size()) { vertexCount = vertices.size(); SafeDelete(vertexBuffer); vertexBuffer = new VertexBuffer(&vertices[0], vertices.size(), sizeof(VertexBillboard)); } Super::Render(); sDiffuseMap->SetResource(textureArray->SRV()); shader->Draw(0, Pass(), vertexCount); } void Billboard::AddTexture(wstring file) { textureNames.push_back(file); } void Billboard::Add(Vector3 & position, Vector2 & scale, UINT mapIndex) { VertexBillboard vertex = { position, scale, mapIndex }; vertices.push_back(vertex); }
BillboardDemo
BillboardDemo.h
더보기
#pragma once #include "Systems/IExecute.h" class BillboardDemo : 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; 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; };
BillboardDemo.cpp
더보기
#include "stdafx.h" #include "BillboardDemo.h" void BillboardDemo::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"); sky = new CubeSky(L"Environment/GrassCube1024.dds"); Billboards(); Mesh(); Airplane(); Kachujin(); KachujinCollider(); KachujinWeapon(); PointLighting(); SpotLighting(); } void BillboardDemo::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(); } void BillboardDemo::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 BillboardDemo::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 BillboardDemo::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 BillboardDemo::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 BillboardDemo::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 BillboardDemo::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 BillboardDemo::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 BillboardDemo::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 BillboardDemo::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 BillboardDemo::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); }
실행화면

'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 103 MRT(Multiple Render Targets) (0) | 2023.04.27 |
---|---|
[DirectX11] 099~102 Render Target, Post Effect(Color Tone) (0) | 2023.04.18 |
[DirectX11] 095 Particle Editor (0) | 2023.04.12 |
[DirectX11] 089~94 Particle System (0) | 2023.04.04 |
[DirectX11] 085~88 Weather (Rain, Snow) (0) | 2023.04.02 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 103 MRT(Multiple Render Targets)
[DirectX11] 103 MRT(Multiple Render Targets)
2023.04.27 -
[DirectX11] 099~102 Render Target, Post Effect(Color Tone)
[DirectX11] 099~102 Render Target, Post Effect(Color Tone)
2023.04.18 -
[DirectX11] 095 Particle Editor
[DirectX11] 095 Particle Editor
2023.04.12 -
[DirectX11] 089~94 Particle System
[DirectX11] 089~94 Particle System
2023.04.04
댓글을 사용할 수 없습니다.