필요한 개념
주인공을 비출때 SpotLighting을 씀
SpotLighting : 위에서 밑으로 퍼지는 빛
다 동일하지만 깍아내는 부분만 다르다.
Lighting.h 추가된 내용
더보기
#define MAX_SPOT_LIGHTS 256
struct SpotLight
{
Color Ambient;
Color Diffuse;
Color Specular;
Color Emissive;
Vector3 Position;
float Range;
Vector3 Direction;
float Angle;
float Intensity;
float Padding[3];
};
class Lighting
{
public:
UINT SpotLightCount() { return spotLightCount; }
UINT SpotLights(OUT SpotLight* lights);
void AddSpotLight(SpotLight& light);
SpotLight& GetSpotLight(UINT index);
private:
UINT spotLightCount = 0;
SpotLight spotLights[MAX_SPOT_LIGHTS];
}
Lighting.cpp 추가된 내용
더보기
UINT Lighting::SpotLights(OUT SpotLight* lights)
{
memcpy(lights, spotLights, sizeof(SpotLight) * spotLightCount);
return spotLightCount;
}
void Lighting::AddSpotLight(SpotLight& light)
{
spotLights[spotLightCount] = light;
spotLightCount++;
}
SpotLight& Lighting::GetSpotLight(UINT index)
{
return spotLights[index];
}
PerFrame.h 추가된 내용
더보기
class PerFrame
{
private:
struct SpotLightDesc
{
UINT Count = 0;
float Padding[3];
SpotLight Lights[MAX_SPOT_LIGHTS];
} spotLightDesc;
private:
ConstantBuffer* spotLightBuffer;
ID3DX11EffectConstantBuffer* sSpotLightBuffer;
}
PerFrame.cpp 추가된 내용
더보기
#include "Framework.h"
#include "PerFrame.h"
PerFrame::PerFrame(Shader* shader)
: shader(shader)
{
...
spotLightBuffer = new ConstantBuffer(&spotLightDesc, sizeof(SpotLightDesc));
sSpotLightBuffer = shader->AsConstantBuffer("CB_SpotLights");
}
PerFrame::~PerFrame()
{
...
SafeDelete(spotLightBuffer);
}
void PerFrame::Update()
{
...
spotLightDesc.Count = Lighting::Get()->SpotLights(spotLightDesc.Lights);
}
void PerFrame::Render()
{
...
spotLightBuffer->Render();
sSpotLightBuffer->SetConstantBuffer(spotLightBuffer->Buffer());
}
00_Lighting.fx 추가된 내용
더보기
...
////////////////////////////////////////////////////////////////////////////
// 한 맵에 256넘어가는것은 초대형 맵을 제외해서는 없다.
#define MAX_SPOT_LIGHTS 256
struct SpotLight
{
float4 Ambient; // 주변광을 줄거고 얘에 따라 주변광을 줄일수 있도록
float4 Diffuse; // 주 빛의 색
float4 Specular; // 반사 색
float4 Emissive; // 얘에 의해 주변광이 표시될 색
// 포인트 라이팅도 물체의 색에 영향을 주므로 포인트 라이팅도 매터리얼을 가지고 있다.
float3 Position; // 위치
float Range; // 범위
float3 Direction; // 조명의 방향
float Angle; // 조명의 앵글
float Intensity; // 강도
float3 Padding;
// Padding을 채우는 이유? 배열로 버퍼의 값을 받기 위해 패딩을 사용, 만약 없으면 데이터가 당겨져 제대로 받을 수 없다.
};
cbuffer CB_SpotLights
{
uint SpotLightCount; // 라이트의 개수(들어온 갯수만)
float3 CB_SpotLights_Padding; // 16바이트로 끊기 위해
SpotLight SpotLights[MAX_SPOT_LIGHTS];
};
void ComputeSpotLight(inout MaterialDesc output, float3 normal, float3 wPosition)
{
output = MakeMaterial();
MaterialDesc result = MakeMaterial();
for (uint i = 0; i < SpotLightCount; i++)
{
float3 light = SpotLights[i].Position - wPosition;
float dist = length(light);
[flatten]
if (dist > SpotLights[i].Range)
continue;
light /= dist;
result.Ambient = SpotLights[i].Ambient * Material.Ambient;
float NdotL = dot(light, normalize(normal));
float3 E = normalize(ViewPosition() - wPosition);
[flatten]
if (NdotL > 0.0f)
{
result.Diffuse = Material.Diffuse * NdotL * SpotLights[i].Diffuse;
[flatten]
if (Material.Specular.a > 0.0f)
{
float3 R = normalize(reflect(-light, normal));
float RdotE = saturate(dot(R, E));
float specular = pow(RdotE, Material.Specular.a);
result.Specular = Material.Specular * specular * SpotLights[i].Specular;
}
}
[flatten]
if (Material.Emissive.a > 0.0f)
{
float NdotE = dot(E, normalize(normal));
float emissive = smoothstep(1.0f - Material.Emissive.a, 1.0f, 1.0f - saturate(NdotE));
result.Emissive = Material.Emissive * emissive * SpotLights[i].Emissive;
}
// 어떻게 조명을 깍어내는냐
// light가 원 모양 밑에서(wPosition) Direction으로 가는것을 반대로 뒤집는다.(위로 올라가는 것을 밑으로 내려가게끔)
// pow는 구를 형성시키기 위해 사용
float temp = pow(saturate(dot(-light, SpotLights[i].Direction)), SpotLights[i].Angle);
// 이미 pow가 정의되어 제곱이 계산되었으므로, Temp를 제곱할 필요가 없다.
// 값 뒤집음(1.0f /max(1.0f - SpotLights[i].Intensity, 1e-8f))
// 역수로 취했는데 0이면 조명이 제대로 들어 갈 수 없으니까, 1e-8f을 준다.(조명의 강도는 0이 존재하지 않음, 또한 0으로 1.0f를 나눌 수 없다.)
float att = temp * (1.0f / max(1.0f - SpotLights[i].Intensity, 1e-8f));
output.Ambient += result.Ambient * temp;
output.Diffuse += result.Diffuse * att;
output.Specular += result.Specular * att;
output.Emissive += result.Emissive * att;
}
}
80_SpotLighting.fx
더보기
#include "00_Global.fx"
#include "00_Light.fx"
#include "00_Render.fx"
float4 PS(MeshOutput input) : SV_Target
{
Texture(Material.Diffuse, DiffuseMap, input.Uv);
Texture(Material.Specular, SpecularMap, input.Uv);
MaterialDesc output = MakeMaterial();
MaterialDesc result = MakeMaterial();
ComputeLight(output, input.Normal, input.wPosition);
AddMaterial(result, output);
ComputePointLight(output, input.Normal, input.wPosition);
AddMaterial(result, output);
ComputeSpotLight(output, input.Normal, input.wPosition);
AddMaterial(result, output);
return float4(MaterialToColor(result), 1.0f);
}
technique11 T0
{
P_VP(P0, VS_Mesh, PS)
P_VP(P1, VS_Model, PS)
P_VP(P2, VS_Animation, PS)
}
결과
'DirectX11 3D > 기본 문법' 카테고리의 다른 글
<DirectX11 3D> 83 - Billboard (0) | 2022.03.14 |
---|---|
<DirectX11 3D> 82 - NormalMapping (0) | 2022.03.10 |
<DirectX11 3D> 78 - PointLighting & HLSL FlowControl (0) | 2022.03.09 |
<DirectX11 3D> 75 - Lighting(Ambient, Diffuse, Specular, Emissive) (0) | 2022.03.09 |
<DirectX11 3D> 74 - Instancing (0) | 2022.03.09 |