응애맘마조
230814 강의 본문
저번주에 했던 환경매핑에 이어서 라이트 버퍼를 추가하고 포인트 라이트와, 스포트 라이트를 했습니다.
#pragma once
struct DirLight
{
Vector4 direction;
Color color;
DirLight()
{
direction = Vector4(1, -1, 0, 0);
color = Vector4(1, 1, 1, 1);
};
};
enum class LightType
{
POINT,
SPOT,
};
struct LightBuffer
{
int isActive;
int lightType;
float inner;
float outer;
//
int size;
Vector3 direction;
//4
Vector3 position;
float radius;
//4
Color color;
LightBuffer() :isActive(false), lightType((int)LightType::POINT), color(1, 1, 1),
radius(100), size(0)
, inner(84.0f), outer(44.0f), direction(0, -1, 0)
{
}
};
class Light : public Actor
{
public:
LightBuffer* light;
static Light* Create(string name = "Light");
virtual void Release();
virtual void Update() override;
virtual void RenderDetail();
};
#define MAX_LIGHT 16
class LightManager : public Singleton<LightManager>
{
ID3D11Buffer* dirLightBuffer;
ID3D11Buffer* lightBuffer;
public:
LightManager();
~LightManager();
DirLight dirLight;
LightBuffer light[MAX_LIGHT];
void Set();
void RenderDetail();
void SetSize();
};
조명 효과도 한 가지만 사용해서 나타내기 때문에 싱글톤을 사용하고 포인트와 스포트를 설정했습니다. 스포트에서는 inner와 outer를 사용합니다.
#include "framework.h"
LightManager::LightManager()
{
{
D3D11_BUFFER_DESC desc = { 0 };
desc.ByteWidth = sizeof(DirLight);
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, &dirLightBuffer);
assert(SUCCEEDED(hr));
D3D->GetDC()->PSSetConstantBuffers(2, 1, &dirLightBuffer);
}
{
D3D11_BUFFER_DESC desc = { 0 };
desc.ByteWidth = sizeof(LightBuffer) * MAX_LIGHT;
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, &lightBuffer);
assert(SUCCEEDED(hr));
D3D->GetDC()->PSSetConstantBuffers(3, 1, &lightBuffer);
}
light[0].size = 0;
}
LightManager::~LightManager()
{
SafeRelease(dirLightBuffer);
SafeRelease(lightBuffer);
}
void LightManager::Set()
{
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
D3D->GetDC()->Map(dirLightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy_s(mappedResource.pData, sizeof(DirLight), &dirLight, sizeof(DirLight));
D3D->GetDC()->Unmap(dirLightBuffer, 0);
}
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
D3D->GetDC()->Map(lightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy_s(mappedResource.pData, sizeof(LightBuffer) * MAX_LIGHT, light, sizeof(LightBuffer) * MAX_LIGHT);
D3D->GetDC()->Unmap(lightBuffer, 0);
}
}
void LightManager::RenderDetail()
{
ImGui::SliderFloat3("dirLight", (float*)(&dirLight.direction), -1, 1);
ImGui::ColorEdit3("dirColor", (float*)(&dirLight.color));
}
void LightManager::SetSize()
{
int max = -1;
for (int i = 0; i < MAX_LIGHT; i++)
{
if (LIGHT->light[i].isActive)
{
if (i > max)
{
max = i;
}
}
}
light[0].size = max + 1;
}
Light* Light::Create(string name)
{
Light* temp = nullptr;
for (int i = 0; i < MAX_LIGHT; i++)
{
if (not LIGHT->light[i].isActive)
{
temp = new Light();
temp->name = name;
LIGHT->light[i].isActive = true;
temp->light = &LIGHT->light[i];
LIGHT->SetSize();
temp->mesh = RESOURCE->meshes.Load("1.SphereCollider.mesh");
temp->shader = RESOURCE->shaders.Load("1.Collider.hlsl");
temp->type = ObType::Light;
break;
}
}
return temp;
}
void Light::Release()
{
light->isActive = false;
LIGHT->SetSize();
Actor::Release();
}
void Light::Update()
{
scale.z = scale.y = scale.x = light->radius;
Actor::Update();
light->position = GetWorldPos();
}
void Light::RenderDetail()
{
Actor::RenderDetail();
if (ImGui::BeginTabBar("MyTabBar3"))
{
if (ImGui::BeginTabItem("Light"))
{
ImGui::SliderInt("Type", &light->lightType, 0, 1);
ImGui::ColorEdit3("Color", (float*)(&light->color));
ImGui::SliderFloat("Range", &light->radius, 0, 200);
if (light->lightType == (int)LightType::SPOT)
{
ImGui::SliderFloat3("Dir", (float*)(&light->direction), -1, 1);
ImGui::SliderFloat("Outer", &light->outer, 0.0f, 90.0f);
ImGui::SliderFloat("Inner", &light->inner, 0.0f, 90.0f);
}
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
위와 아래는 Light 클래스입니다. 최대 16개를 사용하지만 그 이상은 사용할 수 없고 16개가 되지 않아도 for문에서 전부 반복하지 않고 사용되는 개수만큼만 for문이 반복되도록 했습니다.
먼저 포인트 라이트입니다. 어떤 한 점. 즉, 회색 원이 가까이 있을 때만 밝게 빛나고 나머지는 모든 방향으로 똑같게 비춰주는 조명 효과입니다.
다음은 스포트 라이트입니다. 어떤 특정한 위치에서 광원을 발사하여 특정 부분만 비춰주는 효과를 나타냅니다.
읽어주셔서 감사합니다.