• Home
  • About
    • 게임 개발자 유정룡 photo

      게임 개발자 유정룡

      포트폴리오

    • Learn More
    • Email
    • Github
    • Bitbucket
  • Projects
    • All Projects
    • All Tags

Direct3D11 공부 22일차(Material)

25 Jun 2021

Reading time ~3 minutes

Material

모델을 그렸는데 아직 색이 없다. 이제 모델링 안에 있는 데이터로 메테리얼을 적용 시켜보자…!

Material 은 각 물체에 빛이 닿았을 때 물체의 표면으로부터 반사되는 색상을 말한다.

  • Material
    • Diffuse
      • 빛이 물체에 닿았을 경우에 반사하는 색상 설정
    • Ambient
      • 방향성이 없는 빛에 대한 반사색을 설정
      • 방햔성(Direction Light)빛에 의한 반사색에는 영향을 주지 않음
    • Specular
      • 빛에 의한 밝은 부분의 반사색보다 반짝이게 하는 색상을 설정(HightLight의 색상을 설정)
    • Emissive
      • 재질이 스스로 특정 색을 방출하는 옵션 각각의 값은 Color값으로 되어있다. 매테리얼 안에는 이런 값이 있지만, 우리가 직접 값을 만들지는 않고(우리는 플머니까! 디자이너가 잘하니까 디자이너한테 맡기자) 적용을 시킬거다.

Coverter

일단 첫번째로 있는 파일에서 데이터들을 읽어오자

void Converter::ReadMaterialData()
{
	for (UINT i = 0; i < scene->mNumMaterials; i++)
	{
		aiMaterial* srcMaterial = scene->mMaterials[i];
		asMaterial* material = new asMaterial();
		
		material->Name = srcMaterial->GetName().C_Str();

		aiColor3D color;

		srcMaterial->Get(AI_MATKEY_COLOR_AMBIENT , color);
		material->Ambient = Color(color.r, color.g, color.b, 1.0f);

		srcMaterial->Get(AI_MATKEY_COLOR_DIFFUSE, color);
		material->Diffuse = Color(color.r, color.g, color.b, 1.0f);

		srcMaterial->Get(AI_MATKEY_COLOR_SPECULAR, color);
		material->Specular = Color(color.r, color.g, color.b, 1.0f);

		srcMaterial->Get(AI_MATKEY_SHININESS, material->Specular.a);
		material->Specular = Color(color.r, color.g, color.b, 1.0f);

		srcMaterial->Get(AI_MATKEY_COLOR_EMISSIVE, color);
		material->Emissive = Color(color.r, color.g, color.b, 1.0f);

		aiString file;

		srcMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &file);
		material->DiffuseFile = file.C_Str();

		srcMaterial->GetTexture(aiTextureType_SPECULAR, 0, &file);
		material->SpecularFile = file.C_Str();

		srcMaterial->GetTexture(aiTextureType_NORMALS, 0, &file);
		material->NormalFile = file.C_Str();

		materials.push_back(material);
	}
}

매테리얼 갯수대로 읽어와서 현재 Convert에 있는 vector<asMaterial * >에 넣어주자

각 값을 넣을때 srcMaterial->Get()을 사용한데 여기에 각 부분을 맞춰서 넣어주자.

이제 읽었다. 저번에 Mesh에서 했던것 처럼 파일을 쓸건데 이 Material부분은 XML형식으로 Texture들의 이름과 각각의 값들을 저장해서 사용할것이다.

string Converter::WriteTexture(string saveFolder, string file)
{
	if (file.length() < 1) { return ""; }

	string fileName = Path::GetFileName(file);

	// 내장 텍스처가 있다면 내장 텍스처를 리턴 아니면 NULL 리턴
	const aiTexture* texture = scene->GetEmbeddedTexture(file.c_str());

	string path = "";
	if (texture != NULL)
	{
		path = saveFolder + fileName;

		if (texture->mHeight < 1)		// 데이터가 한 줄로 바이트파일 형식으로 써져있다.
		{
			BinaryWriter w;
			w.Open(String::ToWString(path));
			w.Byte(texture->pcData, texture->mWidth);
			w.Close();
		}

		else // 현재까지 이걸 사용한 적은 없다.
		{
			D3D11_TEXTURE2D_DESC destDesc;
			ZeroMemory(&destDesc, sizeof(D3D11_TEXTURE2D_DESC));
			destDesc.Width = texture->mWidth;
			destDesc.Height = texture->mHeight;
			destDesc.MipLevels = 1;
			destDesc.ArraySize = 1;
			destDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
			destDesc.SampleDesc.Count = 1;
			destDesc.SampleDesc.Quality = 0;
			destDesc.Usage = D3D11_USAGE_IMMUTABLE;

			D3D11_SUBRESOURCE_DATA subResource = { 0 };
			subResource.pSysMem = texture->pcData;


			ID3D11Texture2D* dest;

			HRESULT hr;
			hr = D3D::GetDevice()->CreateTexture2D(&destDesc, &subResource, &dest);
			assert(SUCCEEDED(hr));

			D3DX11SaveTextureToFileA(D3D::GetDC(), dest, D3DX11_IFF_PNG, saveFolder.c_str());
		}
	}

	else
	{
		string directory = Path::GetDirectoryName(String::ToString(this->file));
		string origin = directory + file;
		String::Replace(&origin, "\\", "/");

		if (Path::ExistFile(origin) == false)
			return "";

		path = saveFolder + fileName;
		CopyFileA(origin.c_str(), path.c_str(), FALSE);

		String::Replace(&path, "../../_Textures/", "");
	}

	return Path::GetFileName(path);
}

현재 file의 텍스처 데이터에 따라 텍스처를 생성해준다.

각 데이터들은 한 줄로 바이트 형식으로 되어있어서 그 텍스처의 byte를 읽어 하나씩 저장해준다.

만약 파일의 부분이 나눠져 있으면 만들어 주지만 저것을 지금까지 사용한 경우는 없다고 한다. 이론적으로는 저게 맞다고 한다.

만약 텍스처가 없다면, 읽어온 데이터를 byte형태로 저장해준다.

void Converter::WriteMaterialData(wstring savePath)
{
	string folder = String::ToString(Path::GetDirectoryName(savePath));
	string file = String::ToString(Path::GetFileName(savePath));

	Path::CreateFolders(folder);

	Xml::XMLDocument* document = new Xml::XMLDocument();

	Xml::XMLDeclaration* decl = document->NewDeclaration();
	document->LinkEndChild(decl);

	Xml::XMLElement* root = document->NewElement("Materials");
	root->SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
	root->SetAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
	document->LinkEndChild(root);

	for (asMaterial* material : materials)
	{
		Xml::XMLElement* node = document->NewElement("Material");
		root->LinkEndChild(node);

		Xml::XMLElement* element = NULL;

		element = document->NewElement("Name");
		element->SetText(material->Name.c_str());
		node->LinkEndChild(element);

		element = document->NewElement("DiffuseFile");
		element->SetText(WriteTexture(folder, material->DiffuseFile).c_str());
		node->LinkEndChild(element);

		element = document->NewElement("SpecularFile");
		element->SetText(WriteTexture(folder, material->SpecularFile).c_str());
		node->LinkEndChild(element);

		element = document->NewElement("NormalFile");
		element->SetText(WriteTexture(folder, material->NormalFile).c_str());
		node->LinkEndChild(element);

		element = document->NewElement("Ambient");
		element->SetAttribute("R", material->Ambient.r);
		element->SetAttribute("G", material->Ambient.g);
		element->SetAttribute("B", material->Ambient.b);
		element->SetAttribute("A", material->Ambient.a);
		node->LinkEndChild(element);

		element = document->NewElement("Diffuse");
		element->SetAttribute("R", material->Diffuse.r);
		element->SetAttribute("G", material->Diffuse.g);
		element->SetAttribute("B", material->Diffuse.b);
		element->SetAttribute("A", material->Diffuse.a);
		node->LinkEndChild(element);

		element = document->NewElement("Specular");
		element->SetAttribute("R", material->Specular.r);
		element->SetAttribute("G", material->Specular.g);
		element->SetAttribute("B", material->Specular.b);
		element->SetAttribute("A", material->Specular.a);
		node->LinkEndChild(element);

		element = document->NewElement("Emissive");
		element->SetAttribute("R", material->Emissive.r);
		element->SetAttribute("G", material->Emissive.g);
		element->SetAttribute("B", material->Emissive.b);
		element->SetAttribute("A", material->Emissive.a);
		node->LinkEndChild(element);

		SafeDelete(material);
	}

	document->SaveFile((folder + file).c_str());
	SafeDelete(document);
}

쓰는 부분이다 XML을 활용해서 각 부분의 경로와 각 부분의 값들을 저장해준다.



DirectX Share Tweet +1