728x90
🪄 3D Model Render Shader

Model이 그려지는 위치인 Transform이 SRT로 존재하고,
Model의 Mesh마다 BoneIndex가 존재할 때, BoneIndex를 참조해서 Bone에 있는 Transform을 그리게 된다.
Model이 움직이거나 크기가 변화할 때 바뀌는 값이 바로 Model의 Transform SRT 인 것이다.
따라서 3D Model을 출력한 후, SRT 변화에도 정상적인 Mesh를 출력하기 위해 아래와 같은 연산을 거쳐야 한다.
먼저, Bone이 기준이므로 먼저 움직이므로 자신이 가지고있는 BoneTransforms의 BoneIndex 요소를 가져와서,
mul (BoneTransforms[BoneIndex])
World에 곱하고
mul (BoneTransforms[BoneIndex], World)
해당 공간이 최종 공간이므로 World에 저장한다.
World = mul (BoneTransforms[BoneIndex], World)
이후, 쉐이더로 들어오는 input.Position을 World에 곱해서 Model Rendering을 구현할 수 있다.
mul (input.Position, World) --> (WorldPosition 으로 Typedef 해놓음)
📄 Main 출력 파일 - ModelDemo.cpp
더보기
#include "stdafx.h"
#include "ModelDemo.h"
#include "Converter.h"
void ModelDemo::Initialize()
{
Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
Context::Get()->GetCamera()->Position(1, 36, -85);
shader = new Shader(L"38_Model.fx");
Airplane();
Tower();
Tank();
sky = new CubeSky(L"Environment/GrassCube1024.dds");
gridShader = new Shader(L"25_Mesh.fx");
grid = new MeshGrid(gridShader, 6, 6);
grid->GetTransform()->Scale(12, 1, 12);
grid->DiffuseMap(L"Floor.png");
}
void ModelDemo::Update()
{
sky->Update();
grid->Update();
if (airplane != NULL)
airplane->Update();
if (tower != NULL)
tower->Update();
if (tank != NULL)
tank->Update();
}
void ModelDemo::Render()
{
ImGui::SliderFloat3("Direction", direction, -1, +1);
shader->AsVector("Direction")->SetFloatVector(direction);
gridShader->AsVector("Direction")->SetFloatVector(direction);
static int pass = 0;
ImGui::InputInt("Pass", &pass);
pass %= 2;
sky->Render();
grid->Render();
if (airplane != NULL)
{
airplane->Pass(pass);
airplane->Render();
}
if (tower != NULL)
{
tower->Pass(pass);
tower->Render();
}
if (tank != NULL)
{
tank->Pass(pass);
tank->Render();
}
}
void ModelDemo::Airplane()
{
airplane = new ModelRender(shader);
airplane->ReadMesh(L"B787/Airplane");
airplane->GetTransform()->Scale(0.005f, 0.005f, 0.005f);
}
void ModelDemo::Tower()
{
tower = new ModelRender(shader);
tower->ReadMesh(L"Tower/Tower");
tower->GetTransform()->Position(-20, 0, 0);
tower->GetTransform()->Scale(0.01f, 0.01f, 0.01f);
}
void ModelDemo::Tank()
{
tank = new ModelRender(shader);
tank->ReadMesh(L"Tank/Tank");
tank->GetTransform()->Position(20, 0, 0);
}
📄 ModelRender.h
더보기
#pragma once
class ModelRender
{
public:
ModelRender(Shader* shader);
~ModelRender();
void Update();
void Render();
public:
void ReadMesh(wstring file);
Transform* GetTransform() { return transform; }
Model* GetModel() { return model; }
void Pass(UINT pass);
void UpdateTransform(ModelBone* bone = NULL, Matrix& matrix = Matrix());
private:
void UpdateBones(ModelBone* bone, Matrix& matrix);
private:
bool bRead = false;
Shader* shader;
Model* model;
Transform* transform;
Matrix transforms[MAX_MODEL_TRANSFORMS];
};
📄 ModelRender.cpp
더보기
#include "Framework.h"
#include "ModelRender.h"
ModelRender::ModelRender(Shader * shader)
: shader(shader)
{
model = new Model();
transform = new Transform(shader);
}
ModelRender::~ModelRender()
{
SafeDelete(model);
SafeDelete(transform);
}
void ModelRender::Update()
{
if(bRead == true)
{
bRead = false;
// 전체 Mesh 돌아가면서 Shader Setting
for (ModelMesh* mesh : model->Meshes())
mesh->SetShader(shader);
UpdateTransform();
}
for (ModelMesh* mesh : model->Meshes())
mesh->Update();
}
void ModelRender::Render()
{
for (ModelMesh* mesh : model->Meshes())
{
mesh->SetTransform(transform);
mesh->Render();
}
}
void ModelRender::ReadMesh(wstring file)
{
model->ReadMesh(file);
bRead = true;
}
void ModelRender::Pass(UINT pass)
{
for (ModelMesh* mesh : model->Meshes())
mesh->Pass(pass);
}
void ModelRender::UpdateTransform(ModelBone* bone, Matrix& matrix)
{
if (bone != NULL)
UpdateBones(bone, matrix);
// Bone 에 있는 Transform을 transforms 배열에 복사
for(UINT i = 0; i < model->BoneCount(); i++)
{
ModelBone* bone = model->BoneByIndex(i);
transforms[i] = bone->Transform();
}
for (ModelMesh* mesh : model->Meshes())
mesh->Transforms(transforms);
}
void ModelRender::UpdateBones(ModelBone* bone, Matrix& matrix)
{
}
📄 Shader (38_Model.fx)
더보기
#include "00_Global.fx"
float3 Direction = float3(-1, -1, +1);
struct VertexModel
{
float4 Position : Position;
float2 Uv : Uv;
float3 Normal : Normal;
float3 Tangent : Tangent;
float4 BlendIndices : BlendIndices;
float4 BlendWeights : BlendWeights;
};
#define MAX_MODEL_TRANSFORMS 250
cbuffer CB_Bone
{
matrix BoneTransforms[MAX_MODEL_TRANSFORMS];
uint BoneIndex;
};
struct VertexOutput
{
float4 Position : SV_Position;
float3 Normal : Normal;
float2 Uv : Uv;
};
VertexOutput VS(VertexModel input)
{
VertexOutput output;
World = mul(BoneTransforms[BoneIndex], World);
output.Position = WorldPosition(input.Position);
output.Position = ViewProjection(output.Position);
output.Normal = WorldNormal(input.Normal);
output.Uv = input.Uv;
return output;
}
float4 PS(VertexOutput input) : SV_Target
{
float NdotL = dot(normalize(input.Normal), -Direction); // 음영 넣기
return float4(1, 1, 1, 1) * NdotL;
}
technique11 T0
{
P_VP(P0, VS, PS)
P_RS_VP(P1, FillMode_WireFrame, VS, PS)
}
[ 실행 결과 ]


728x90
'🎨DirectX' 카테고리의 다른 글
[DX] Model Material Render (DiffuseMap) (0) | 2023.05.08 |
---|---|
[DX] Model Material Export (.material, TINYXML) (0) | 2023.05.03 |
[DX] 3D Model Render -1 (0) | 2023.04.25 |
[DX] ExportMesh, BinaryFile/BinaryWriter (WriteMeshData), ReadBoneData, ReadMeshData (0) | 2023.04.11 |
[DX] 3D 모델, Assimp, ReadFile (0) | 2023.03.13 |