[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