응애맘마조
230612 강의 본문
머터리얼에 대해 강의를 했었습니다. 재료나 질감 같은 느낌을 나타낼 때 사용합니다.
#pragma once
class MaterialBuffer
{
public:
Color ambient;
Color diffuse;
Color specular;
Color emissive;
float shininess;
float opacity;
float environment;
float shadow;
};
class Material : public MaterialBuffer
{
static ID3D11Buffer* materialBuffer;
public:
static void CreateStaticMember();
static void DeleteStaticMember();
public:
shared_ptr<Texture> normalMap;
shared_ptr<Texture> diffuseMap;
shared_ptr<Texture> specularMap;
shared_ptr<Texture> emissiveMap;
string file;
public:
Material();
~Material();
void RenderDetail();
virtual void Set();
void LoadFile(string file);
void SaveFile(string file);
};
#include "Framework.h"
ID3D11Buffer* Material::materialBuffer = nullptr;
Material::Material()
{
file = "defalut.mtl";
ambient = Color(0.3f, 0.3f, 0.3f, 0.0f);
diffuse = Color(1.0f, 1.0f, 1.0f, 0.0f);
specular = Color(1.0f, 1.0f, 1.0f, 0.0f);
emissive = Color(0.2f, 0.2f, 0.2f, 0.0f);
shininess = 30.0f;
opacity = 1.0f;
environment = 0.0f;
shadow = 0.0f;
normalMap = nullptr;
diffuseMap = nullptr;
emissiveMap = nullptr;
specularMap = nullptr;
}
Material::~Material()
{
SafeReset(normalMap);
SafeReset(diffuseMap);
SafeReset(specularMap);
SafeReset(emissiveMap);
}
void Material::CreateStaticMember()
{
D3D11_BUFFER_DESC desc = { 0 };
desc.ByteWidth = sizeof(MaterialBuffer);
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;//상수버퍼
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
HRESULT hr = D3D->GetDevice()->CreateBuffer(&desc, NULL, &materialBuffer);
assert(SUCCEEDED(hr));
D3D->GetDC()->PSSetConstantBuffers(1, 1, &materialBuffer);
}
void Material::DeleteStaticMember()
{
SafeRelease(materialBuffer);
}
void Material::Set()
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
D3D->GetDC()->Map(materialBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy_s(mappedResource.pData, sizeof(MaterialBuffer), (MaterialBuffer*)this, sizeof(MaterialBuffer));
D3D->GetDC()->Unmap(materialBuffer, 0);
if (normalMap)normalMap->Set(0);
if (diffuseMap)diffuseMap->Set(1);
if (specularMap)specularMap->Set(2);
if (emissiveMap)emissiveMap->Set(3);
}
void Material::RenderDetail()
{
ImGui::ColorEdit3("ambient", (float*)&ambient, ImGuiColorEditFlags_PickerHueWheel);
ImGui::ColorEdit3("diffuse", (float*)&diffuse, ImGuiColorEditFlags_PickerHueWheel);
ImGui::ColorEdit3("specular", (float*)&specular, ImGuiColorEditFlags_PickerHueWheel);
ImGui::ColorEdit3("emissive", (float*)&emissive, ImGuiColorEditFlags_PickerHueWheel);
ImGui::DragFloat("shiness", &shininess, 0.05f);
ImGui::DragFloat("opacity", &opacity, 0.05f);
ImGui::DragFloat("environment", &environment, 0.05f, 0.0f, 1.0f);
ImGui::DragFloat("shadow", &shadow, 0.05f, 0.0f, 1.0f);
if (normalMap)
normalMap->RenderDetail();
if (GUI->FileImGui("Load NormalMap", "Load NormalMap",
".dds,.jpg,.tga,.png,.bmp", "../Contents/Texture"))
{
string path = ImGuiFileDialog::Instance()->GetCurrentPath();
Util::Replace(&path, "\\", "/");
if (path.find("/Texture/") != -1)
{
size_t tok = path.find("/Texture/") + 9;
path = path.substr(tok, path.length())
+ "/" + ImGuiFileDialog::Instance()->GetCurrentFileName();
}
else
{
path = ImGuiFileDialog::Instance()->GetCurrentFileName();
}
SafeReset(normalMap);
normalMap = RESOURCE->textures.Load(path);
ambient.w = 1.0f;
}
if (diffuseMap)
diffuseMap->RenderDetail();
if (GUI->FileImGui("Load DiffuseMap", "Load DiffuseMap",
".dds,.jpg,.tga,.png,.bmp", "../Contents/Texture"))
{
string path = ImGuiFileDialog::Instance()->GetCurrentPath();
Util::Replace(&path, "\\", "/");
if (path.find("/Texture/") != -1)
{
size_t tok = path.find("/Texture/") + 9;
path = path.substr(tok, path.length())
+ "/" + ImGuiFileDialog::Instance()->GetCurrentFileName();
}
else
{
path = ImGuiFileDialog::Instance()->GetCurrentFileName();
}
SafeReset(diffuseMap);
diffuseMap = RESOURCE->textures.Load(path);
diffuse.w = 1.0f;
}
if (specularMap)
specularMap->RenderDetail();
if (GUI->FileImGui("Load SpecularMap", "Load SpecularMap",
".dds,.jpg,.tga,.png,.bmp", "../Contents/Texture"))
{
string path = ImGuiFileDialog::Instance()->GetCurrentPath();
Util::Replace(&path, "\\", "/");
if (path.find("/Texture/") != -1)
{
size_t tok = path.find("/Texture/") + 9;
path = path.substr(tok, path.length())
+ "/" + ImGuiFileDialog::Instance()->GetCurrentFileName();
}
else
{
path = ImGuiFileDialog::Instance()->GetCurrentFileName();
}
SafeReset(specularMap);
specularMap = RESOURCE->textures.Load(path);
specular.w = 1.0f;
}
if (emissiveMap)
emissiveMap->RenderDetail();
if (GUI->FileImGui("Load emissiveMap", "Load emissiveMap",
".dds,.jpg,.tga,.png,.bmp", "../Contents/Texture"))
{
string path = ImGuiFileDialog::Instance()->GetCurrentPath();
Util::Replace(&path, "\\", "/");
if (path.find("/Texture/") != -1)
{
size_t tok = path.find("/Texture/") + 9;
path = path.substr(tok, path.length())
+ "/" + ImGuiFileDialog::Instance()->GetCurrentFileName();
}
else
{
path = ImGuiFileDialog::Instance()->GetCurrentFileName();
}
SafeReset(emissiveMap);
emissiveMap = RESOURCE->textures.Load(path);
emissive.w = 1.0f;
}
}
void Material::LoadFile(string file)
{
this->file = file;
BinaryReader in;
wstring path = L"../Contents/Material/" + Util::ToWString(file);
in.Open(path);
ambient = in.color4f();
diffuse = in.color4f();
specular = in.color4f();
emissive = in.color4f();
if (in.Int())
{
normalMap = RESOURCE->textures.Load(in.String());
normalMap->SamplerDesc.Filter = (D3D11_FILTER)in.Int();
normalMap->SamplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
normalMap->SamplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
normalMap->SamplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
normalMap->CreateSampler();
}
if (in.Int())
{
diffuseMap = RESOURCE->textures.Load(in.String());
diffuseMap->SamplerDesc.Filter = (D3D11_FILTER)in.Int();
diffuseMap->SamplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
diffuseMap->SamplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
diffuseMap->SamplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
diffuseMap->CreateSampler();
}
if (in.Int())
{
specularMap = RESOURCE->textures.Load(in.String());
specularMap->SamplerDesc.Filter = (D3D11_FILTER)in.Int();
specularMap->SamplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
specularMap->SamplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
specularMap->SamplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
specularMap->CreateSampler();
}
if (in.Int())
{
emissiveMap = RESOURCE->textures.Load(in.String());
emissiveMap->SamplerDesc.Filter = (D3D11_FILTER)in.Int();
emissiveMap->SamplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
emissiveMap->SamplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
emissiveMap->SamplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)in.Int();
emissiveMap->CreateSampler();
}
shininess = in.Float();
opacity = in.Float();
environment = in.Float();
shadow = in.Float();
in.Close();
}
void Material::SaveFile(string file)
{
this->file = file;
BinaryWriter out;
wstring path = L"../Contents/Material/" + Util::ToWString(file);
out.Open(path);
out.color4f(ambient);
out.color4f(diffuse);
out.color4f(specular);
out.color4f(emissive);
if (normalMap)
{
out.Int(1);
out.String(normalMap->file);
out.Int((D3D11_FILTER)normalMap->SamplerDesc.Filter);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)normalMap->SamplerDesc.AddressU);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)normalMap->SamplerDesc.AddressV);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)normalMap->SamplerDesc.AddressW);
}
else
out.Int(0);
if (diffuseMap)
{
out.Int(1);
out.String(diffuseMap->file);
out.Int((D3D11_FILTER)diffuseMap->SamplerDesc.Filter);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)diffuseMap->SamplerDesc.AddressU);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)diffuseMap->SamplerDesc.AddressV);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)diffuseMap->SamplerDesc.AddressW);
}
else
out.Int(0);
if (specularMap)
{
out.Int(1);
out.String(specularMap->file);
out.Int((D3D11_FILTER)specularMap->SamplerDesc.Filter);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)specularMap->SamplerDesc.AddressU);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)specularMap->SamplerDesc.AddressV);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)specularMap->SamplerDesc.AddressW);
}
else
out.Int(0);
if (emissiveMap)
{
out.Int(1);
out.String(emissiveMap->file);
out.Int((D3D11_FILTER)emissiveMap->SamplerDesc.Filter);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)emissiveMap->SamplerDesc.AddressU);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)emissiveMap->SamplerDesc.AddressV);
out.Int((D3D11_TEXTURE_ADDRESS_MODE)emissiveMap->SamplerDesc.AddressW);
}
else
out.Int(0);
out.Float(shininess);
out.Float(opacity);
out.Float(environment);
out.Float(shadow);
out.Close();
}
헤더 파일과 cpp 파일입니다. 이걸로 GUI 안에서 ambient, diffuse, specular 이 세 가지를 직접 조절할 수 있게 되었습니다. 추가로 emissive가 있지만 만들기만 하고 아직 사용하지는 않습니다.
#include "Common.hlsl"
struct VertexInput
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float4 Normal : NORMAL0;
};
struct PixelInput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float4 Normal : NORMAL0;
float3 wPosition : POSITION0;
};
PixelInput VS(VertexInput input)
{
PixelInput output;
output.Color = input.Color;
//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 = input.Color;
//world space light
float3 light = 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 * float3(1, 1, 1);
return float4(lambert + specular, Opacity);
}
hlsl 파일입니다. 이전까지는 직접 상수 값을 넣었지만 이제 각각 맞는 버퍼를 생성해서 추가를 했습니다.
해당 3개 영상에서 각각 조절이 가능한 것을 확인했습니다.
읽어주셔서 감사합니다.