응애맘마조

230613 강의 본문

공부/3D강의

230613 강의

TH.Wert 2023. 6. 13. 23:28

먼저 코드의 변경 사항이 있었습니다.

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 파일이 생성된 것을 알 수 있습니다. 또한 위의 사진은 과제로 나왔습니다.

읽어주셔서 감사합니다.

'공부 > 3D강의' 카테고리의 다른 글

230616 강의  (0) 2023.06.20
230614 강의  (0) 2023.06.14
230612 강의  (0) 2023.06.12
230609 강의  (1) 2023.06.11
230608 강의  (0) 2023.06.08