For me
[DirectX12] 13) Shadow 본문
1. Light와 같은 위치, 방향, 크기만큼 Camera를 Setting
2. Render 하기 전, RenderShadow를 먼저 호출
▶ 모든 물체를 그림 (바라보고 있는 깊이를 texture로 그림)
3. Shadow Render Target Map 에 그려짐
4. RenderLight 에서 함께 계산하여 그림자 생성
Shadow Shader
더보기
#ifndef _SHADOW_FX_
#define _SHADOW_FX_
#include "params.fx"
struct VS_IN
{
float3 pos : POSITION;
};
struct VS_OUT
{
float4 pos : SV_Position;
float4 clipPos : POSITION;
};
VS_OUT VS_Main(VS_IN input)
{
VS_OUT output = (VS_OUT)0.f;
output.pos = mul(float4(input.pos, 1.f), g_matWVP);
output.clipPos = output.pos;
return output;
}
float4 PS_Main(VS_OUT input) : SV_Target
{
// 투영 좌표계로 기준으로한 z값
return float4(input.clipPos.z / input.clipPos.w, 0.f, 0.f, 0.f);
}
#endif
Scene.cpp
Render Shadow 먼저 진행
더보기
void Scene::Render()
{
PushLightData();
ClearRTV();
RenderShadow();
RenderDeferred();
RenderLights();
RenderFinal();
RenderForward();
}
void Scene::ClearRTV()
{
// SwapChain Group 초기화
int8 backIndex = GEngine->GetSwapChain()->GetBackBufferIndex();
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SWAP_CHAIN)->ClearRenderTargetView(backIndex);
// Shadow Group 초기화
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SHADOW)->ClearRenderTargetView();
// Deferred Group 초기화
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::G_BUFFER)->ClearRenderTargetView();
// Lighting Group 초기화
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::LIGHTING)->ClearRenderTargetView();
}
void Scene::RenderShadow()
{
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SHADOW)->OMSetRenderTargets();
for (auto& light : _lights)
{
if (light->GetLightType() != LIGHT_TYPE::DIRECTIONAL_LIGHT)
continue;
light->RenderShadow();
}
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SHADOW)->WaitTargetToResource();
}
Light.cpp
Light 컴포넌트에 Camera를 만들어 Shadow를 생성할 수 있도록 함
더보기
#include "pch.h"
#include "pch.h"
#include "Light.h"
#include "Transform.h"
#include "Engine.h"
#include "Resources.h"
#include "Camera.h"
#include "Transform.h"
#include "Texture.h"
#include "SceneManager.h"
Light::Light() : Component(COMPONENT_TYPE::LIGHT)
{
_shadowCamera = make_shared<GameObject>();
_shadowCamera->AddComponent(make_shared<Transform>());
_shadowCamera->AddComponent(make_shared<Camera>());
uint8 layerIndex = GET_SINGLE(SceneManager)->LayerNameToIndex(L"UI");
_shadowCamera->GetCamera()->SetCullingMaskLayerOnOff(layerIndex, true); // UI는 안 찍음
}
Light::~Light()
{
}
void Light::FinalUpdate()
{
_lightInfo.position = GetTransform()->GetWorldPosition();
_shadowCamera->GetTransform()->SetLocalPosition(GetTransform()->GetLocalPosition());
_shadowCamera->GetTransform()->SetLocalRotation(GetTransform()->GetLocalRotation());
_shadowCamera->GetTransform()->SetLocalScale(GetTransform()->GetLocalScale());
_shadowCamera->FinalUpdate();
}
void Light::Render()
{
assert(_lightIndex >= 0);
GetTransform()->PushData();
if (static_cast<LIGHT_TYPE>(_lightInfo.lightType) == LIGHT_TYPE::DIRECTIONAL_LIGHT)
{
shared_ptr<Texture> shadowTex = GET_SINGLE(Resources)->Get<Texture>(L"ShadowTarget");
_lightMaterial->SetTexture(2, shadowTex);
Matrix matVP = _shadowCamera->GetCamera()->GetViewMatrix() * _shadowCamera->GetCamera()->GetProjectionMatrix();
_lightMaterial->SetMatrix(0, matVP);
}
else
{
float scale = 2 * _lightInfo.range;
GetTransform()->SetLocalScale(Vec3(scale, scale, scale));
}
_lightMaterial->SetInt(0, _lightIndex);
_lightMaterial->PushGraphicsData();
_volumeMesh->Render();
}
void Light::RenderShadow()
{
_shadowCamera->GetCamera()->SortShadowObject();
_shadowCamera->GetCamera()->Render_Shadow();
}
void Light::SetLightDirection(Vec3 direction)
{
direction.Normalize();
_lightInfo.direction = direction;
GetTransform()->LookAt(direction);
}
void Light::SetLightType(LIGHT_TYPE type)
{
_lightInfo.lightType = static_cast<int32>(type);
switch (type)
{
case LIGHT_TYPE::DIRECTIONAL_LIGHT:
_volumeMesh = GET_SINGLE(Resources)->Get<Mesh>(L"Rectangle");
_lightMaterial = GET_SINGLE(Resources)->Get<Material>(L"DirLight");
_shadowCamera->GetCamera()->SetScale(1.f);
_shadowCamera->GetCamera()->SetFar(10000.f);
_shadowCamera->GetCamera()->SetWidth(4096);
_shadowCamera->GetCamera()->SetHeight(4096);
break;
case LIGHT_TYPE::POINT_LIGHT:
_volumeMesh = GET_SINGLE(Resources)->Get<Mesh>(L"Sphere");
_lightMaterial = GET_SINGLE(Resources)->Get<Material>(L"PointLight");
break;
case LIGHT_TYPE::SPOT_LIGHT:
_volumeMesh = GET_SINGLE(Resources)->Get<Mesh>(L"Sphere");
_lightMaterial = GET_SINGLE(Resources)->Get<Material>(L"PointLight");
break;
}
}
Camera.cpp
더보기
#include "pch.h"
#include "Camera.h"
#include "Transform.h"
#include "Scene.h"
#include "SceneManager.h"
#include "GameObject.h"
#include "MeshRenderer.h"
#include "Engine.h"
#include "Material.h"
#include "Shader.h"
#include "ParticleSystem.h"
#include "InstancingManager.h"
Matrix Camera::S_MatView;
Matrix Camera::S_MatProjection;
Camera::Camera() : Component(COMPONENT_TYPE::CAMERA)
{
_width = static_cast<float>(GEngine->GetWindow().width);
_height = static_cast<float>(GEngine->GetWindow().height);
}
Camera::~Camera()
{
}
void Camera::FinalUpdate()
{
_matView = GetTransform()->GetLocalToWorldMatrix().Invert();
if (_type == PROJECTION_TYPE::PERSPECTIVE)
_matProjection = ::XMMatrixPerspectiveFovLH(_fov, _width / _height, _near, _far);
else
_matProjection = ::XMMatrixOrthographicLH(_width * _scale, _height * _scale, _near, _far);
_frustum.FinalUpdate();
}
void Camera::SortGameObject()
{
shared_ptr<Scene> scene = GET_SINGLE(SceneManager)->GetActiveScene();
const vector<shared_ptr<GameObject>>& gameObjects = scene->GetGameObjects();
_vecForward.clear();
_vecDeferred.clear();
_vecParticle.clear();
for (auto& gameObject : gameObjects)
{
if (gameObject->GetMeshRenderer() == nullptr && gameObject->GetParticleSystem() == nullptr)
continue;
if (IsCulled(gameObject->GetLayerIndex()))
continue;
if (gameObject->GetCheckFrustum())
{
if (_frustum.ContainsSphere(
gameObject->GetTransform()->GetWorldPosition(),
gameObject->GetTransform()->GetBoundingSphereRadius()) == false)
{
continue;
}
}
if (gameObject->GetMeshRenderer())
{
SHADER_TYPE shaderType = gameObject->GetMeshRenderer()->GetMaterial()->GetShader()->GetShaderType();
switch (shaderType)
{
case SHADER_TYPE::DEFERRED:
_vecDeferred.push_back(gameObject);
break;
case SHADER_TYPE::FORWARD:
_vecForward.push_back(gameObject);
break;
}
}
else
{
_vecParticle.push_back(gameObject);
}
}
}
void Camera::SortShadowObject()
{
shared_ptr<Scene> scene = GET_SINGLE(SceneManager)->GetActiveScene();
const vector<shared_ptr<GameObject>>& gameObjects = scene->GetGameObjects();
_vecShadow.clear();
for (auto& gameObject : gameObjects)
{
if (gameObject->GetMeshRenderer() == nullptr)
continue;
if (gameObject->IsStatic())
continue;
if (IsCulled(gameObject->GetLayerIndex()))
continue;
if (gameObject->GetCheckFrustum())
{
if (_frustum.ContainsSphere(
gameObject->GetTransform()->GetWorldPosition(),
gameObject->GetTransform()->GetBoundingSphereRadius()) == false)
{
continue;
}
}
_vecShadow.push_back(gameObject);
}
}
void Camera::Render_Deferred()
{
S_MatView = _matView;
S_MatProjection = _matProjection;
GET_SINGLE(InstancingManager)->Render(_vecDeferred);
}
void Camera::Render_Forward()
{
S_MatView = _matView;
S_MatProjection = _matProjection;
GET_SINGLE(InstancingManager)->Render(_vecForward);
for (auto& gameObject : _vecParticle)
{
gameObject->GetParticleSystem()->Render();
}
}
void Camera::Render_Shadow()
{
S_MatView = _matView;
S_MatProjection = _matProjection;
for (auto& gameObject : _vecShadow)
{
gameObject->GetMeshRenderer()->RenderShadow();
}
}
'DirectX12' 카테고리의 다른 글
[DirectX12] 15) SkyBox (0) | 2023.01.18 |
---|---|
[DirectX12] 14) Normal Mapping (0) | 2023.01.18 |
[DirectX12] 12) Light - 2 (0) | 2023.01.17 |
[DirectX12] 11) Light - 1 (이론) (1) | 2023.01.17 |
[DirectX12] 10) Camera (0) | 2023.01.17 |