응애맘마조

230814 강의 본문

공부/3D강의

230814 강의

TH.Wert 2023. 8. 14. 21:21

저번주에 했던 환경매핑에 이어서 라이트 버퍼를 추가하고 포인트 라이트와, 스포트 라이트를 했습니다.

#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문이 반복되도록 했습니다.

포인트 라이트 영상

먼저 포인트 라이트입니다. 어떤 한 점. 즉, 회색 원이 가까이 있을 때만 밝게 빛나고 나머지는 모든 방향으로 똑같게 비춰주는 조명 효과입니다.

스포트 라이트 영상

다음은 스포트 라이트입니다. 어떤 특정한 위치에서 광원을 발사하여 특정 부분만 비춰주는 효과를 나타냅니다.

 

읽어주셔서 감사합니다.

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

230817 강의  (0) 2023.08.17
230816 강의  (0) 2023.08.16
230807 강의  (0) 2023.08.07
230801 강의  (0) 2023.08.01
230731 강의  (0) 2023.07.31