728x90
Material.cpp, h (머티리얼 정보 쉐이더에 넘기거나 수정)
더보기
#include "Framework.h"
#include "Material.h"
Material::Material()
{
Initialize();
}
Material::Material(Shader * shader)
{
Initialize();
SetShader(shader);
}
void Material::Initialize()
{
diffuseMap = NULL;
specularMap = NULL;
normalMap = NULL;
buffer = new ConstantBuffer(&colorDesc, sizeof(ColorDesc));
}
Material::~Material()
{
SafeDelete(diffuseMap);
SafeDelete(specularMap);
SafeDelete(normalMap);
SafeDelete(buffer);
}
void Material::SetShader(Shader * shader)
{
this->shader = shader;
sBuffer = shader->AsConstantBuffer("CB_Material");
sDiffuseMap = shader->AsSRV("DiffuseMap");
sSpecularMap = shader->AsSRV("SpecularMap");
sNormalMap = shader->AsSRV("NormalMap");
}
void Material::Ambient(Color & color)
{
colorDesc.Ambient = color;
}
void Material::Ambient(float r, float g, float b, float a)
{
Ambient(Color(r, g, b, a));
}
void Material::Diffuse(Color & color)
{
colorDesc.Diffuse = color;
}
void Material::Diffuse(float r, float g, float b, float a)
{
Diffuse(Color(r, g, b, a));
}
void Material::Specular(Color & color)
{
colorDesc.Specular = color;
}
void Material::Specular(float r, float g, float b, float a)
{
Specular(Color(r, g, b, a));
}
void Material::Emissive(Color & color)
{
colorDesc.Emissive = color;
}
void Material::Emissive(float r, float g, float b, float a)
{
Emissive(Color(r, g, b, a));
}
void Material::DiffuseMap(string file)
{
DiffuseMap(String::ToWString(file));
}
void Material::DiffuseMap(wstring file)
{
SafeDelete(diffuseMap);
diffuseMap = new Texture(file);
}
void Material::SpecularMap(string file)
{
SpecularMap(String::ToWString(file));
}
void Material::SpecularMap(wstring file)
{
SafeDelete(specularMap);
specularMap = new Texture(file);
}
void Material::NormalMap(string file)
{
NormalMap(String::ToWString(file));
}
void Material::NormalMap(wstring file)
{
SafeDelete(normalMap);
normalMap = new Texture(file);
}
void Material::Render()
{
buffer->Render();
sBuffer->SetConstantBuffer(buffer->Buffer());
if (diffuseMap != NULL)
sDiffuseMap->SetResource(diffuseMap->SRV());
else
sDiffuseMap->SetResource(NULL);
if (specularMap != NULL)
sSpecularMap->SetResource(specularMap->SRV());
else
sSpecularMap->SetResource(NULL);
if (normalMap != NULL)
sNormalMap->SetResource(normalMap->SRV());
else
sNormalMap->SetResource(NULL);
}
#pragma once
class Material
{
public:
Material();
Material(Shader* shader);
~Material();
Shader* GetShader() { return shader; }
void SetShader(Shader* shader);
void Name(wstring val) { name = val; }
wstring Name() { return name; }
Color& Ambient() { return colorDesc.Ambient; }
void Ambient(Color& color);
void Ambient(float r, float g, float b, float a = 1.0f);
Color& Diffuse() { return colorDesc.Diffuse; }
void Diffuse(Color& color);
void Diffuse(float r, float g, float b, float a = 1.0f);
Color& Specular() { return colorDesc.Specular; }
void Specular(Color& color);
void Specular(float r, float g, float b, float a = 1.0f);
Color& Emissive() { return colorDesc.Emissive; }
void Emissive(Color& color);
void Emissive(float r, float g, float b, float a = 1.0f);
Texture* DiffuseMap() { return diffuseMap; }
void DiffuseMap(string file);
void DiffuseMap(wstring file);
Texture* SpecularMap() { return specularMap; }
void SpecularMap(string file);
void SpecularMap(wstring file);
Texture* NormalMap() { return normalMap; }
void NormalMap(string file);
void NormalMap(wstring file);
void Render();
private:
void Initialize();
private:
struct ColorDesc
{
Color Ambient = Color(0, 0, 0, 1);
Color Diffuse = Color(1, 1, 1, 1);
Color Specular = Color(0, 0, 0, 1);
Color Emissive = Color(0, 0, 0, 1);
} colorDesc;
private:
Shader* shader;
wstring name;
Texture* diffuseMap;
Texture* specularMap;
Texture* normalMap;
ConstantBuffer* buffer;
ID3DX11EffectConstantBuffer* sBuffer;
ID3DX11EffectShaderResourceVariable* sDiffuseMap;
ID3DX11EffectShaderResourceVariable* sSpecularMap;
ID3DX11EffectShaderResourceVariable* sNormalMap;
};
00_Light.fx (00_Global.fx 같은 헤더 역할)
더보기
Texture2D DiffuseMap;
Texture2D SpecularMap;
Texture2D NormalMap;
struct MaterialDesc
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float4 Emissive;
};
cbuffer CB_Material
{
MaterialDesc Material;
};
Model.cpp, h (머티리얼 관련으로 수정)
더보기

cpp파일 빨강색은 생성, 주황색은 수정

헤더 파일
#include "Framework.h"
#include "Model.h"
#include "Utilities/BinaryFile.h"
#include "Utilities/Xml.h"
Model::Model()
{
}
Model::~Model()
{
for (ModelBone* bone : bones)
SafeDelete(bone);
for (ModelMesh* mesh : meshes)
SafeDelete(mesh);
for (Material* material : materials)
SafeDelete(material);
}
void Model::ReadMesh(wstring file)
{
file = L"../../_Models/" + file + L".mesh";
BinaryReader* r = new BinaryReader(file);
UINT count = 0;
count = r->UInt();
for (UINT i = 0; i < count; i++)
{
ModelBone* bone = new ModelBone();
bone->index = r->Int();
bone->name = String::ToWString(r->String());
bone->parentIndex = r->Int();
bone->transform = r->Matrix();
bones.push_back(bone);
}
count = r->UInt();
for (UINT i = 0; i < count; i++)
{
ModelMesh* mesh = new ModelMesh();
mesh->boneIndex = r->Int();
//VertexData
{
UINT count = r->UInt();
vector<Model::VertexModel> vertices;
vertices.assign(count, Model::VertexModel());
void* ptr = (void*)&(vertices[0]);
r->Byte(&ptr, sizeof(Model::VertexModel) * count);
mesh->vertices = new Model::VertexModel[count];
mesh->vertexCount = count;
copy
(
vertices.begin(), vertices.end(),
stdext::checked_array_iterator<Model::VertexModel*>(mesh->vertices, count)
);
}
//IndexData
{
UINT count = r->UInt();
vector<UINT> indices;
indices.assign(count, sizeof(UINT));
void* ptr = (void*)&(indices[0]);
r->Byte(&ptr, sizeof(UINT) * count);
mesh->indices = new UINT[count];
mesh->indexCount = count;
copy
(
indices.begin(), indices.end(),
stdext::checked_array_iterator<UINT*>(mesh->indices, count)
);
}
//MeshPart::DrawCall에 사용될 값
UINT partCount = r->UInt();
for (UINT k = 0; k < partCount; k++)
{
ModelMeshPart* meshPart = new ModelMeshPart();
meshPart->materialName = String::ToWString(r->String());
meshPart->startVertex = r->UInt();
meshPart->vertexCount = r->UInt();
meshPart->startIndex = r->UInt();
meshPart->indexCount = r->UInt();
mesh->meshParts.push_back(meshPart);
}
meshes.push_back(mesh);
}
SafeDelete(r);
BindBone();
}
void Model::ReadMaterial(wstring file)
{
file = L"../../_Textures/" + file + L".material";
//파일 불러오기
Xml::XMLDocument* document = new Xml::XMLDocument();
Xml::XMLError error = document->LoadFile(String::ToString(file).c_str());
assert(error == Xml::XML_SUCCESS);
//제일 첫번째 root 가져오기
Xml::XMLElement* root = document->FirstChildElement();
Xml::XMLElement* materialNode = root->FirstChildElement();
do
{
//반복문 안에 쓸 변수
Material* material = new Material();
Xml::XMLElement* node = NULL;
//Xml 문서에 있는 첫번쨰 (Name)
node = materialNode->FirstChildElement ();
material->Name(String::ToWString(node->GetText()));
wstring directory = Path::GetDirectoryName(file);
String::Replace(&file, L"../../_Textures/", L"");
//DiffuseFile, SpecularFile, NormalFile 이름
wstring texture = L"";
node = node->NextSiblingElement();
texture = String::ToWString(node->GetText());
if (texture.length() > 0)
material->DiffuseMap(directory + texture);
node = node->NextSiblingElement();
texture = String::ToWString(node->GetText());
if (texture.length() > 0)
material->SpecularMap(directory + texture);
node = node->NextSiblingElement();
texture = String::ToWString(node->GetText());
if (texture.length() > 0)
material->NormalMap(directory + texture);
//색상정보 Ambient, Diffuse, Specular, Emissive
Color color;
node = node->NextSiblingElement();
color.r = node->FloatAttribute("R");
color.g = node->FloatAttribute("G");
color.b = node->FloatAttribute("B");
color.a = node->FloatAttribute("A");
material->Ambient(color);
node = node->NextSiblingElement();
color.r = node->FloatAttribute("R");
color.g = node->FloatAttribute("G");
color.b = node->FloatAttribute("B");
color.a = node->FloatAttribute("A");
material->Diffuse(color);
node = node->NextSiblingElement();
color.r = node->FloatAttribute("R");
color.g = node->FloatAttribute("G");
color.b = node->FloatAttribute("B");
color.a = node->FloatAttribute("A");
material->Specular(color);
node = node->NextSiblingElement();
color.r = node->FloatAttribute("R");
color.g = node->FloatAttribute("G");
color.b = node->FloatAttribute("B");
color.a = node->FloatAttribute("A");
material->Emissive(color);
materials.push_back(material);//저장
materialNode = materialNode->NextSiblingElement(); // 증감자 역할
} while (materialNode != NULL);
//머티리얼 읽고선 매쉬에 Texture 적용
BindMesh();
}
void Model::BindBone()
{
root = bones[0]; //root Bone
for (ModelBone* bone : bones)
{
//부모가 없다면
if (bone->parentIndex > -1)
{
bone->parent = bones[bone->parentIndex];
bone->parent->childs.push_back(bone);
}
else
bone->parent = NULL;
}
}
void Model::BindMesh()
{
//모델이 보유한 Mesh(덩어리) 개수만큼 돌면서
for (ModelMesh* mesh : meshes)
{
mesh->bone = bones[mesh->boneIndex]; //이 Mesh가 참조할 뽄을 저장
mesh->Binding(this);
}
}
ModelBone * Model::BoneByName(wstring name)
{
for (ModelBone* bone : bones)
{
if (name == bone->Name())
return bone;
}
return NULL;
}
Material * Model::MaterialByName(wstring name)
{
for (Material* material : materials)
{
if (name == material->Name())
return material;
}
return NULL;
}

#pragma once
#define MAX_MODEL_TRANSFORMS 250
class ModelBone;
class ModelMesh;
class ModelMeshPart;
class Model
{
public:
friend class ModelRender;
struct VertexModel;
private:
Model();
~Model();
private:
void ReadMesh(wstring file); //.mesh 파일 불러오기
void ReadMaterial(wstring file); //.material 파일 불러오기
private:
void BindBone(); //부모, 자식 관계가 맺어진 bone을 bones에 저장
void BindMesh(); //이 모델이 가진 Mesh(덩어리)를 meshes에 저장
public:
UINT BoneCount() { return bones.size(); }
vector<ModelBone*>& Bones() { return bones; }
ModelBone* BoneByIndex(UINT index) { return bones[index]; }
ModelBone* BoneByName(wstring name);
UINT MeshCount() { return meshes.size(); }
vector<ModelMesh*>& Meshes() { return meshes; }
ModelMesh* MeshByIndex(UINT index) { return meshes[index]; }
UINT MaterialCount() { return bones.size(); }
vector<Material*>& Materials() { return materials; }
Material* MaterialByIndex(UINT index) { return materials[index]; }
Material* MaterialByName(wstring name);
public:
struct VertexModel
{
Vector3 Position;
Vector2 Uv;
Vector3 Normal;
Vector3 Tangent; //NormalMapping
Vector4 BlendIndices; //Animation Skinning
Vector4 BlendWeights;
VertexModel()
{
Position = Vector3(0, 0, 0);
Uv = Vector2(0, 0);
Normal = Vector3(0, 0, 0);
Tangent = Vector3(0, 0, 0);
BlendIndices = Vector4(0, 0, 0, 0);
BlendWeights = Vector4(0, 0, 0, 0);
}
};
private:
ModelBone* root;
vector<ModelBone*> bones;
vector<ModelMesh*> meshes;
vector<Material*> materials;
};

ModelMesh.cpp, h (ModelMeshPart, ModelMesh ModelBone 통합 정의 클래스)
더보기

헤더파일 변수 추가
ModelMeshPart::ModelMeshPart(){}
ModelMeshPart::~ModelMeshPart(){SafeDelete(material);}
void ModelMeshPart::Update()
{
}
void ModelMeshPart::Render()
{
material->Render();
shader->DrawIndexed(0, pass, indexCount, startIndex);
}
void ModelMeshPart::Binding(Model * model)
{
Material* srcMaterial = model->MaterialByName(materialName);
material = new Material();
//컬러
material->Ambient(srcMaterial->Ambient());
material->Diffuse(srcMaterial->Diffuse());
material->Specular(srcMaterial->Specular());
material->Emissive(srcMaterial->Emissive());
//Texture
if (srcMaterial->DiffuseMap() != NULL)
material->DiffuseMap(srcMaterial->DiffuseMap()->GetFile());
if (srcMaterial->SpecularMap() != NULL)
material->SpecularMap(srcMaterial->SpecularMap()->GetFile());
if (srcMaterial->NormalMap() != NULL)
material->NormalMap(srcMaterial->NormalMap()->GetFile());
}
void ModelMeshPart::SetShader(Shader* shader)
{
this->shader = shader;
material->SetShader(shader);
}

실행 결과
보충
1. 머티리얼 적용 하기전에 Mesh부터 다 읽고나서 색상 적용 시켜야함
2. Xml 읽을때
위 그림처럼 ReadMaterial 함수내에서 Xml 정보 읽을때 아래와 같이 설명 할수 있는데
간단히 정리를 하면
document : XML 파일
root : xml 경로
materialNode : Material
node : materialNode 안에 있는 Enelment 정보들
node = materialNode->FirstChildElement(); : 제일 첫번째 정보
node = node->NextSiblingElement(); : 그 다음 형제(트리) 정보
'DirectX > DirectX 3D_(구)' 카테고리의 다른 글
21_Thread (0) | 2021.07.28 |
---|---|
20_ModelAnimation (0) | 2021.07.26 |
19_ModelMaterial [1/2] (0) | 2021.07.17 |
18_ModelEditor [2/2] (0) | 2021.07.14 |
18_ModelEditor [1/2] (0) | 2021.07.13 |