Skip to content

Commit

Permalink
Directional, point and spot light rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
roeas committed Oct 30, 2024
1 parent c88609b commit c135719
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 43 deletions.
84 changes: 65 additions & 19 deletions Engine/Asset/Shader/Base_frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,82 @@ layout(location = 0) out vec4 o_color;
#include "Lib/BRDF.glsl"
#include "Lib/Light.glsl"

float GetDistanceAttenuation(vec3 uLightDir, float range)
{
float distance2 = dot(uLightDir, uLightDir);
float attenuation = 1.0 / (max(distance2, 0.01 * 0.01));

// n = 4
float factor = distance2 / (range * range);
float smoothFactor = clamp(1.0 - factor * factor, 0.0, 1.0);
float smoothDistanceAtt = smoothFactor * smoothFactor;

return attenuation * smoothDistanceAtt;
}

float GetAngleAttenuation(vec3 lightDir, vec3 lightForward, float angleScale, float angleOffset)
{
// On the CPU
// float angleScale = 1.0f / max(0.001f, (cosInner - cosOuter));
// float angleOffset =- cosOuter * angleScale;
float cd = dot(lightDir, lightForward);
float attenuation = clamp(cd * angleScale + angleOffset, 0.0, 1.0);

return attenuation * attenuation;
}

vec3 GetDirectLightContribute(vec3 worldPos, vec3 cameraPos, Material material)
{
vec3 direct = vec3(0.0);
for(uint i = 0; i < ub_lightCount; ++i)
{
Light light = ub_lights[i];

vec3 lightPos = light.position.xyz;
vec3 lightForward = normalize(light.direction.xyz);

vec3 viewDir = normalize(cameraPos - worldPos);
vec3 ulightDir = lightPos - worldPos;
vec3 lightDir = normalize(ulightDir);
vec3 harfDir = normalize(lightDir + viewDir);
float NdotV = max(dot(material.normal, viewDir), 0.0);
float NdotL = max(dot(material.normal, lightDir), 0.0);
float NdotH = max(dot(material.normal, harfDir), 0.0);
float VdotH = max(dot(viewDir, harfDir), 0.0);

float Dis = DistributionGGX(material.roughness, NdotH);
float Vis = VisibilitySchlick(material.roughness, NdotV, NdotL);
vec3 Fre = FresnelSchlick(material.F0, VdotH);
vec3 KD = mix(vec3(1.0) - Fre, vec3(0.0), material.metallic);
vec3 BRDF = vec3(Dis) * vec3(Vis) * Fre + KD * material.albedo * vec3(SL_PI_INV);

if(light.type == LIGHT_TYPE_DIRECTIONAL)
{
direct += vec3(0.0);
// L_out = f * E * cosTheta
direct += BRDF * light.intensity * max(dot(material.normal, -lightForward), 0.0);
}
else if(light.type == LIGHT_TYPE_POINT)
{
vec3 lightPos = light.position.xyz;
vec3 viewDir = normalize(cameraPos - worldPos);
vec3 lightDir = normalize(lightPos - worldPos);
vec3 harfDir = normalize(lightDir + viewDir);
float NdotV = max(dot(material.normal, viewDir), 0.0);
float NdotL = max(dot(material.normal, lightDir), 0.0);
float NdotH = max(dot(material.normal, harfDir), 0.0);
float VdotH = max(dot(viewDir, harfDir), 0.0);

float Dis = DistributionGGX(material.roughness, NdotH);
float Vis = VisibilitySchlick(material.roughness, NdotV, NdotL);
vec3 Fre = FresnelSchlick(material.F0, VdotH);
vec3 KD = mix(vec3(1.0) - Fre, vec3(0.0), material.metallic);
vec3 BRDF = vec3(Dis) * vec3(Vis) * Fre + KD * material.albedo * vec3(SL_PI_INV);

direct += BRDF;
// I = Phi / 4Pi
// L_out = f * L_in * cosTheta

float I = light.intensity * 0.25 * SL_PI_INV;
float attenuation = GetDistanceAttenuation(ulightDir, light.range);
float L = I * attenuation;

direct += BRDF * L * NdotL;
}
else if(light.type == LIGHT_TYPE_SPOT)
{
direct += vec3(0.0);
// I = Phi / Pi
// L_out = f * L_in * cosTheta

float I = light.intensity * SL_PI_INV;
float attenuation = GetDistanceAttenuation(ulightDir, light.range);
attenuation *= GetAngleAttenuation(lightDir, lightForward, light.scale, light.offset);
float L = I * attenuation;

direct += BRDF * L * NdotL;
}
}

Expand All @@ -57,8 +101,10 @@ vec3 GetDirectLightContribute(vec3 worldPos, vec3 cameraPos, Material material)

void main()
{
vec3 cameraPos = GetCameraPos();
Material material = GetMaterial(v_uv0);
vec3 directColor = GetDirectLightContribute(v_worldPos, GetCameraPos(), material);
material.normal = v_normal; // TMP
vec3 directColor = GetDirectLightContribute(v_worldPos, cameraPos, material);

vec3 environmentColor = vec3(0.01);

Expand Down
4 changes: 2 additions & 2 deletions Engine/Asset/Shader/Lib/Light.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ struct Light
uint type; // 0 4
float intensity; // 4 4
float range; // 8 4
float outer; // 12 4
float inner; // 16 4
float scale; // 12 4
float offset; // 16 4
vec4 color; // 32 16
vec4 position; // 48 16
vec4 direction; // 64 16
Expand Down
1 change: 1 addition & 0 deletions Engine/Asset/Shader/Lib/Material.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ vec3 SampleAlbedoTexture(vec2 uv)
}
vec3 SampleNormalTexture(vec2 uv)
{
// TODO: Support normal map.
return texture(s_normal, uv).xyz;
}
vec3 SampleEmissiveTexture(vec2 uv)
Expand Down
2 changes: 1 addition & 1 deletion Engine/Source/Editor/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Editor::Editor(EditorInitor initor)
sl::RenderCore::Init();
sl::RenderCore::SetDefaultState();

// Create frame buffers, Size is meaningless here.
// Create frame buffers, size is meaningless here.
sl::RenderCore::SetMainFramebuffer(sl::FrameBuffer::Create(
{
sl::Texture2D::Create(1, 1, false, sl::TextureFormat::RGBA8, SL_SAMPLER_CLAMP | SL_SAMPLER_BILINEAR),
Expand Down
7 changes: 7 additions & 0 deletions Engine/Source/Editor/Layer/ImGuiLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,10 @@ void ImGuiLayer::ShowEntityList()
auto entity = sl::ECSWorld::CreateEntity("Directional Light");
auto &light = entity.AddComponent<sl::LightComponent>();
light.type = sl::LightType::Directional;
// light.intensity = 100000.0f;

auto &transform = entity.GetComponents<sl::TransformComponent>();
transform.m_rotation = glm::vec4{ 1.0, 0.0, 0.0, 1.0 } * sl::ECSWorld::GetMainCameraTransformComponent().GetRotate();
}
if (ImGui::MenuItem("Creat Point Light"))
{
Expand All @@ -696,6 +700,9 @@ void ImGuiLayer::ShowEntityList()
auto entity = sl::ECSWorld::CreateEntity("Spot Light");
auto &light = entity.AddComponent<sl::LightComponent>();
light.type = sl::LightType::Spot;

auto &transform = entity.GetComponents<sl::TransformComponent>();
transform.m_rotation = glm::vec4{ 1.0, 0.0, 0.0, 1.0 } *sl::ECSWorld::GetMainCameraTransformComponent().GetRotate();
}
ImGui::EndPopup();
}
Expand Down
16 changes: 12 additions & 4 deletions Engine/Source/Editor/Layer/RendererLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,19 @@ void RendererLayer::OnRender()
{
SL_PROFILE;

// upload camera uniform buffer.
if (auto *pCameraUniformBuffer = sl::RenderCore::GetUniformBuffer("CameraUniformBuffer"); pCameraUniformBuffer)
{
sl::Entity mainCamera = sl::ECSWorld::GetMainCameraEntity();
pCameraUniformBuffer->Upload("ub_viewProjection", glm::value_ptr(mainCamera.GetComponents<sl::CameraComponent>().GetViewProjection()));
pCameraUniformBuffer->Upload("ub_cameraPos", glm::value_ptr(mainCamera.GetComponents<sl::TransformComponent>().m_position));
}

// Upload light uniform buffer.
auto group = sl::ECSWorld::GetRegistry().group<sl::LightComponent>(entt::get<sl::TransformComponent>);
uint32_t lightCount = (uint32_t)group.size();
std::vector<sl::LightUniformBuffer> lightGPUData;
lightGPUData.reserve(lightCount);
static std::vector<sl::LightUniformBuffer> lightGPUData(LIGHT_MAX_COUNT);
lightGPUData.clear();
for (auto entity : group)
{
auto [light, transform] = group.get<sl::LightComponent, sl::TransformComponent>(entity);
Expand All @@ -104,8 +106,14 @@ void RendererLayer::OnRender()
uniformBuffer.type = (uint32_t)light.type;
uniformBuffer.intensity = light.intensity;
uniformBuffer.range = light.range;
uniformBuffer.outer = light.outer;
uniformBuffer.inner = light.inner;

float cosInner = std::cos(light.inner);
float cosOuter = std::cos(light.outer);
float scale = 1.0f / std::max(cosInner - cosOuter, 0.001f);
float offset =- cosOuter * scale;

uniformBuffer.scale = scale;
uniformBuffer.offset = offset;
uniformBuffer.color = glm::vec4{ light.color, 0.0f };
uniformBuffer.position = glm::vec4{ transform.m_position, 0.0f };
uniformBuffer.direction = glm::vec4{ transform.m_rotation, 0.0f };
Expand Down
5 changes: 5 additions & 0 deletions Engine/Source/Engine/Scene/ECSWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ CameraComponent &ECSWorld::GetMainCameraComponent()
return GetMainCameraEntity().GetComponents<CameraComponent>();
}

TransformComponent &ECSWorld::GetMainCameraTransformComponent()
{
return GetMainCameraEntity().GetComponents<TransformComponent>();
}

void Entity::Destroy()
{
if (!IsValid())
Expand Down
1 change: 1 addition & 0 deletions Engine/Source/Engine/Scene/ECSWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class ECSWorld final

static Entity GetMainCameraEntity();
static CameraComponent &GetMainCameraComponent();
static TransformComponent &GetMainCameraTransformComponent();

private:
inline static entt::registry m_registry;
Expand Down
8 changes: 4 additions & 4 deletions Engine/Source/Engine/Scene/LightComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ struct LightComponent
glm::vec3 color{ 1.0f };
float intensity = 1024.0f;
float range = 1024.0f;
float outer = glm::radians(45.0f);
float inner = glm::radians(30.0f);
float outer = glm::radians(45.0f); // Store in radiance
float inner = glm::radians(30.0f); // Store in radiance
};

// std140
Expand All @@ -32,8 +32,8 @@ struct LightUniformBuffer
uint32_t type;
float intensity;
float range;
float outer;
float inner;
float scale;
float offset;
float padding0, padding1, padding2;
glm::vec4 color;
glm::vec4 position;
Expand Down
42 changes: 42 additions & 0 deletions Engine/Source/Engine/Scene/TransformComponent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "TransformComponent.h"

#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/quaternion.hpp>

namespace sl
{

glm::vec3 TransformComponent::GetRotationDegrees() const
{
return glm::degrees(m_rotation);
}

void TransformComponent::SetRotationDegrees(const glm::vec3 &degrees)
{
m_rotation = glm::radians(degrees);
}

glm::mat4 TransformComponent::GetTranslate() const
{
return glm::translate(glm::mat4{ 1.0f }, m_position);
}

glm::mat4 TransformComponent::GetRotate() const
{
return glm::toMat4(glm::quat(m_rotation));
}

glm::mat4 TransformComponent::GetScale() const
{
return glm::scale(glm::mat4{ 1.0f }, m_scale);
}

glm::mat4 TransformComponent::GetTransform() const
{
return glm::translate(glm::mat4{ 1.0f }, m_position) *
glm::toMat4(glm::quat(m_rotation)) *
glm::scale(glm::mat4{ 1.0f }, m_scale);
}

} // namespace sl
20 changes: 7 additions & 13 deletions Engine/Source/Engine/Scene/TransformComponent.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#pragma once

#define GLM_ENABLE_EXPERIMENTAL

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/mat4x4.hpp>
#include <glm/trigonometric.hpp>
#include <glm/vec3.hpp>
Expand All @@ -24,18 +20,16 @@ struct TransformComponent
TransformComponent(const glm::vec3 &position, const glm::vec3 &rotation, const glm::vec3 &scale) :
m_position(position), m_rotation(rotation), m_scale(scale) {}

glm::vec3 GetRotationDegrees() const { return glm::degrees(m_rotation); }
void SetRotationDegrees(const glm::vec3 &degrees) { m_rotation = glm::radians(degrees); }
glm::vec3 GetRotationDegrees() const;
void SetRotationDegrees(const glm::vec3 &degrees);

glm::mat4 GetTransform() const
{
return glm::translate(glm::mat4{ 1.0f }, m_position) *
glm::toMat4(glm::quat(m_rotation)) *
glm::scale(glm::mat4{ 1.0f }, m_scale);
}
glm::mat4 GetTranslate() const;
glm::mat4 GetRotate() const;
glm::mat4 GetScale() const;
glm::mat4 GetTransform() const;

glm::vec3 m_position{ 0.0f, 0.0f , 0.0f };
glm::vec3 m_rotation{ 0.0f, 0.0f , 0.0f }; // Stores in radians
glm::vec3 m_rotation{ 0.0f, 0.0f , 0.0f }; // Stores in radians.
glm::vec3 m_scale{ 1.0f, 1.0f , 1.0f };
};

Expand Down

0 comments on commit c135719

Please sign in to comment.