응애맘마조
230613 강의 본문
먼저 코드의 변경 사항이 있었습니다.
shared_ptr<Material> material;
class Material* material;
첫 번째 줄에서 shared_ptr을 두 번째 줄인 클래스로 바꿨습니다. 재질 또한 오브젝트마다 제각각 다른데 전부 공유를 해버리면 모든 오브젝트에서 똑같아지는 이유에서 클래스로 바꾸게 되었습니다.
cbuffer VS_W : register(b0)
{
matrix World;
}
cbuffer VS_VP : register(b1)
{
matrix ViewProj;
}
cbuffer PS_ViewPos : register(b0)
{
float4 ViewPos;
}
cbuffer PS_Material : register(b1)
{
float4 Ka;
float4 Kd;
float4 Ks;
float4 Ke;
float Shininess;
float Opacity;
float environment;
float shadow;
}
Texture2D TextureN : register(t0);
SamplerState SamplerN : register(s0);
Texture2D TextureD : register(t1);
SamplerState SamplerD : register(s1);
Texture2D TextureS : register(t2);
SamplerState SamplerS : register(s2);
Texture2D TextureE : register(t3);
SamplerState SamplerE : register(s3);
float4 DiffuseMapping(float2 Uv)
{
[flatten]
if (Kd.a)
return TextureD.Sample(SamplerD, Uv);
return float4(1, 1, 1, 1);
}
float3 SpecularMapping(float2 Uv)
{
[flatten]
if (Ks.a)
return TextureS.Sample(SamplerS, Uv).rgb;
return float3(1, 1, 1);
}
기본 포함하는 hlsl 파일에도 코드의 추가가 생겼습니다. 매핑을 하기 위해서 새로운 값을 넣게 되었습니다.
#include "Common.hlsl"
struct VertexInput
{
float4 Position : POSITION0;
//float4 Color : COLOR0;
float4 Normal : NORMAL0;
float2 Uv : UV0;
};
struct PixelInput
{
float4 Position : SV_POSITION;
//float4 Color : COLOR0;
float4 Normal : NORMAL0;
float3 wPosition : POSITION0;
float2 Uv : UV0;
};
PixelInput VS(VertexInput input)
{
PixelInput output;
//output.Color = input.Color;
output.Uv = input.Uv;
//output.Color.a = 1.0f;
// o = i X W
output.Position = mul(input.Position, World);
output.wPosition = output.Position.xyz;
output.Position = mul(output.Position, ViewProj);
input.Normal.w = 0.0f;
output.Normal = mul(input.Normal, World);
return output;
}
float4 PS(PixelInput input) : SV_TARGET
{
float4 BaseColor = DiffuseMapping(input.Uv);
if (BaseColor.a == 0)
discard;
//world space light
float3 arilightel = normalize(-float3(1, -1, 1));
//world space normal
float3 normal = normalize(input.Normal);
float diffuse = saturate(dot(light, normal));
float ambient = Ka.rgb;
float3 lambert = (diffuse + ambient) * Kd.rgb * BaseColor.rgb;
//input.Color.rgb
float3 Reflect = reflect(normalize(float3(1, -1, 1)), normal);
float3 viewDir = normalize(ViewPos.xyz - input.wPosition);
float3 specular = pow(saturate(dot(Reflect, viewDir)), Shininess) * Ks.rgb * SpecularMapping(input.Uv);
return float4(lambert + specular, Opacity);
}
따라서 큐브 생성의 hlsl도 실행했을 때의 내용은 같지만 위처럼 코드의 변경 사항이 생겼습니다.
#pragma once
//메인에는 씬만 구성
class Main : public Scene
{
private:
Camera* Cam;
Grid* grid;
Actor* temp;
map <string,Material*> mtlList;
public:
Main();
~Main();
void LoadMaterial(string file);
virtual void Init() override;
virtual void Release() override; //해제
virtual void Update() override;
virtual void LateUpdate() override;//갱신
virtual void Render() override;
virtual void PreRender() override;
virtual void ResizeScreen() override;
};
#include "stdafx.h"
#include "Main.h"
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
Main::Main()
{
}
Main::~Main()
{
}
void Main::LoadMaterial(string file)
{
ifstream fin;
fin.open("../Assets/" + file);
if (fin.is_open())
{
string name;
while (!fin.eof())
{
string Input;
fin >> Input;
if (Input == "newmtl")
{
fin >> name;
mtlList[name] = new Material();
}
else if (Input == "Ka")
{
fin >> mtlList[name]->ambient.x;
fin >> mtlList[name]->ambient.y;
fin >> mtlList[name]->ambient.z;
}
else if (Input == "Kd")
{
fin >> mtlList[name]->diffuse.x;
fin >> mtlList[name]->diffuse.y;
fin >> mtlList[name]->diffuse.z;
}
else if (Input == "Ks")
{
fin >> mtlList[name]->specular.x;
fin >> mtlList[name]->specular.y;
fin >> mtlList[name]->specular.z;
}
else if (Input == "d")
{
fin >> mtlList[name]->opacity;
}
else if (Input == "Ns")
{
fin >> mtlList[name]->shininess;
}
else if (Input == "map_Kd")
{
mtlList[name]->diffuse.w = 1.0f;
string TexName;
fin >> TexName;
{
size_t tok = file.find_last_of(".");
string filename = file.substr(0, tok);
string checkPath = "../Contents/Texture/" + filename;
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
string orgin = "../Assets/" + TexName;
string copy = "../Contents/Texture/" + file.substr(0, tok) + "/" + TexName;
bool isCheck = true;
CopyFileA(orgin.c_str(), copy.c_str(), isCheck);
mtlList[name]->diffuseMap = make_shared<Texture>();
mtlList[name]->diffuseMap->LoadFile(filename + "/" + TexName);
}
{
size_t tok = file.find_last_of(".");
string filename = file.substr(0, tok);
string checkPath = "../Contents/Material/" + filename;
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
mtlList[name]->SaveFile(filename + "/" + name + ".mtl");
}
}
char c[128];
//한줄 읽어오기
fin.getline(c, 128);
}
}
}
void Main::Init()
{
Cam = Camera::Create();
Cam->LoadFile("Cam.xml");
Camera::main = Cam;
Cam->width = App.GetWidth();
Cam->height = App.GetHeight();
Cam->viewport.width = App.GetWidth();
Cam->viewport.height = App.GetHeight();
grid = Grid::Create();
temp = Actor::Create();
}
void Main::Release()
{
}
void Main::Update()
{
ImGui::Begin("Hierarchy");
Cam->RenderHierarchy();
temp->RenderHierarchy();
grid->RenderHierarchy();
ImGui::End();
if (GUI->FileImGui("Load", "Load Obj",
".obj", "../Assets"))
{
string path = ImGuiFileDialog::Instance()->GetCurrentPath();
Util::Replace(&path, "\\", "/");
if (path.find("/Assets/") != -1)
{
size_t tok = path.find("/Assets/") + 8;
path = path.substr(tok, path.length())
+ "/" + ImGuiFileDialog::Instance()->GetCurrentFileName();
}
else
{
path = ImGuiFileDialog::Instance()->GetCurrentFileName();
}
ifstream fin;
fin.open("../Assets/" + path);
if (fin.is_open())
{
int GCount = 0;
vector<VertexPTN> Vertices;
vector<UINT> Indices;
vector<Vector3> P;
vector<Vector2> T;
vector<Vector3> N;
string name;
Material* tempMtl = nullptr;
string mtlstr;
while (!fin.eof())
{
string tag;
fin >> tag;
if (tag == "mtllib")
{
string file;
fin >> file;
LoadMaterial(file.substr(2, file.size()));
}
if (tag == "v")
{
Vector3 pos;
fin >> pos.x >> pos.y >> pos.z;
P.push_back(pos);
}
else if (tag == "vt")
{
Vector2 uv;
float temp;
fin >> uv.x >> uv.y >> temp;
T.push_back(uv);
}
else if (tag == "vn")
{
Vector3 nor;
fin >> nor.x >> nor.y >> nor.z;
N.push_back(nor);
}
else if (tag == "f")
{
int idx[3]; char slash;
VertexPTN ptn;
for (int i = 0; i < 3; i++)
{
fin >> idx[0] >> slash >> idx[1] >> slash >> idx[2];
ptn.position = P[idx[0] - 1];
ptn.uv = T[idx[1] - 1];
ptn.normal = N[idx[2] - 1];
Indices.push_back(Vertices.size());
Vertices.push_back(ptn);
}
}
else if (tag == "g")
{
GCount++;
if (GCount == 2)
{
fin >> name;
}
//저장해야할시점
if (GCount == 3)
{
GameObject* child = GameObject::Create(name);
temp->AddChild(child);
child->shader = make_shared<Shader>();
child->shader->LoadFile("3.Cube.hlsl");
child->mesh = make_shared<Mesh>();
child->mesh->vertices = &Vertices[0];
child->mesh->vertexCount = Vertices.size();
child->mesh->indices = &Indices[0];
child->mesh->indexCount = Indices.size();
child->mesh->byteWidth = sizeof(VertexPTN);
child->mesh->primitiveTopology
= D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
child->mesh->vertexType = VertexType::PTN;
child->mesh->Reset();
child->material = tempMtl;
size_t tok = path.find_last_of(".");
child->material->file = path.substr(0, tok) + "/" + mtlstr +".mtl";
child->mesh->file = path.substr(0, tok) + "/" + name + ".mesh";
{
size_t tok = path.find_last_of(".");
string checkPath = "../Contents/Mesh/" + path.substr(0, tok);
if (!PathFileExistsA(checkPath.c_str()))
{
CreateDirectoryA(checkPath.c_str(), NULL);
}
child->mesh->SaveFile(path.substr(0, tok) + "/" + name + ".mesh");
}
GCount = 1;
Vertices.clear();
Indices.clear();
}
}
else if (tag == "usemtl")
{
fin >> mtlstr;
tempMtl = mtlList[mtlstr];
}
char c[128];
//한줄 읽어오기
fin.getline(c, 128);
}
}
}
Camera::ControlMainCam();
Cam->Update();
grid->Update();
temp->Update();
}
void Main::LateUpdate()
{
}
void Main::PreRender()
{
}
void Main::Render()
{
Cam->Set();
grid->Render();
temp->Render();
}
void Main::ResizeScreen()
{
}
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR param, int command)
{
App.SetAppName(L"ObjLoader");
App.SetInstance(instance);
WIN->Create();
D3D->Create();
Main * main = new Main();
main->Init();
int wParam = (int)WIN->Run(main);
main->Release();
SafeDelete(main);
D3D->DeleteSingleton();
WIN->DeleteSingleton();
return wParam;
}
main의 헤더와 cpp 파일입니다. mtl 파일을 읽어서 그 내용대로 매핑을 하는 것입니다. mtl 파일 내에 있는 값대로 매핑을 하게 되면
해당 사진의 색상 모습으로 나오게 됩니다. 그리고 Contents 파일 내에도 각각의 오브젝트에 매칭된 mtl 파일이 생성된 것을 알 수 있습니다. 또한 위의 사진은 과제로 나왔습니다.
읽어주셔서 감사합니다.