Skip to content

Commit

Permalink
Added light casters: point, directional, spotlight
Browse files Browse the repository at this point in the history
  • Loading branch information
denyskryvytskyi committed Mar 2, 2024
1 parent b04fe80 commit 966a813
Show file tree
Hide file tree
Showing 6 changed files with 317 additions and 26 deletions.
2 changes: 2 additions & 0 deletions Engine/src/Renderer/CameraController.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class CameraController {
Camera& GetCamera() { return m_camera; }
const Camera& GetCamera() const { return m_camera; }

const lia::vec3& GetFront() const { return m_front; };

protected:
virtual void ProcessInput(float dt);
virtual void OnMouseMoved(const events::MouseMovedEvent& e);
Expand Down
62 changes: 62 additions & 0 deletions Sandbox3D/assets/shaders/textured_cube_with_dir_light_caster.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Fragment shader for the cube with texture (LightingSandbox)
#version 450 core

struct Material {
sampler2D diffuse;
sampler2D specular;
sampler2D emission;
float shininess;
bool enableEmission;
};
uniform Material u_Material;

struct Light {
vec3 direction;

vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light u_Light;

uniform vec3 u_ViewPos;

in vec3 v_FragPos;
in vec3 v_Normal;
in vec2 v_UV;

out vec4 FragColor;

void main()
{
vec3 normal = normalize(v_Normal);
vec3 lightDir = normalize(-u_Light.direction); // directional light

vec3 viewDir = normalize(u_ViewPos - v_FragPos);
vec3 reflectDir = reflect(-lightDir, normal);

// ambient
vec3 diffuseMap = texture(u_Material.diffuse, v_UV).rgb;
vec3 ambient = u_Light.ambient * diffuseMap;

// diffuse
float diff = max(dot(normal, lightDir), 0.0f);
vec3 diffuse = u_Light.diffuse * diff * texture(u_Material.diffuse, v_UV).rgb;

// specular
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.shininess);
vec3 specularMap = texture(u_Material.specular, v_UV).rgb;
vec3 specular = u_Light.specular * spec * specularMap;

// emission
vec3 emission = vec3(0.0f);

if (u_Material.enableEmission && specularMap == vec3(0.0f))
{
emission = texture(u_Material.emission, v_UV).rgb;
}

// final
vec3 result = ambient + diffuse + specular + emission;
FragColor = vec4(result, 1.0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Fragment shader for the cube with texture (LightingSandbox)
#version 450 core

struct Material {
sampler2D diffuse;
sampler2D specular;
sampler2D emission;
float shininess;
bool enableEmission;
};
uniform Material u_Material;

struct Light {
vec3 position;

vec3 ambient;
vec3 diffuse;
vec3 specular;

float constant;
float linear;
float quadratic;
};
uniform Light u_Light;

uniform vec3 u_ViewPos;

in vec3 v_FragPos;
in vec3 v_Normal;
in vec2 v_UV;

out vec4 FragColor;

void main()
{
vec3 normal = normalize(v_Normal);
vec3 lightDir = normalize(u_Light.position - v_FragPos);

vec3 viewDir = normalize(u_ViewPos - v_FragPos);
vec3 reflectDir = reflect(-lightDir, normal);

// ambient
vec3 diffuseMap = texture(u_Material.diffuse, v_UV).rgb;
vec3 ambient = u_Light.ambient * diffuseMap;

// diffuse
float diff = max(dot(normal, lightDir), 0.0f);
vec3 diffuse = u_Light.diffuse * diff * texture(u_Material.diffuse, v_UV).rgb;

// specular
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.shininess);
vec3 specularMap = texture(u_Material.specular, v_UV).rgb;
vec3 specular = u_Light.specular * spec * specularMap;

// emission
vec3 emission = vec3(0.0f);

if (u_Material.enableEmission && specularMap == vec3(0.0f))
{
emission = texture(u_Material.emission, v_UV).rgb;
}

// attenuation
float distance = length(u_Light.position - v_FragPos);
float attenuation = 1.0 / (u_Light.constant + u_Light.linear * distance + u_Light.quadratic * (distance * distance));

ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;

// final
vec3 result = ambient + diffuse + specular + emission;
FragColor = vec4(result, 1.0);
}
83 changes: 83 additions & 0 deletions Sandbox3D/assets/shaders/textured_cube_with_spotlight_caster.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Fragment shader for the cube with texture (LightingSandbox)
#version 450 core

struct Material {
sampler2D diffuse;
sampler2D specular;
sampler2D emission;
float shininess;
bool enableEmission;
};
uniform Material u_Material;

struct Light {
vec3 position;
vec3 direction;

vec3 ambient;
vec3 diffuse;
vec3 specular;

float constant;
float linear;
float quadratic;
float cutOff; // cos of the angle
float outerCutOff;
};
uniform Light u_Light;

uniform vec3 u_ViewPos;

in vec3 v_FragPos;
in vec3 v_Normal;
in vec2 v_UV;

out vec4 FragColor;

void main()
{
vec3 normal = normalize(v_Normal);
vec3 lightDir = normalize(u_Light.position - v_FragPos);

vec3 viewDir = normalize(u_ViewPos - v_FragPos);
vec3 reflectDir = reflect(-lightDir, normal);

// ambient
vec3 diffuseMap = texture(u_Material.diffuse, v_UV).rgb;
vec3 ambient = u_Light.ambient * diffuseMap;

// diffuse
float diff = max(dot(normal, lightDir), 0.0f);
vec3 diffuse = u_Light.diffuse * diff * texture(u_Material.diffuse, v_UV).rgb;

// specular
float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_Material.shininess);
vec3 specularMap = texture(u_Material.specular, v_UV).rgb;
vec3 specular = u_Light.specular * spec * specularMap;

// emission
vec3 emission = vec3(0.0f);

if (u_Material.enableEmission && specularMap == vec3(0.0f))
{
emission = texture(u_Material.emission, v_UV).rgb;
}

// spotlight with soft edges
float theta = dot(lightDir, normalize(-u_Light.direction));
float epsilon = u_Light.cutOff - u_Light.outerCutOff;
float intensity = clamp((theta - u_Light.outerCutOff) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;

// attenuation
float distance = length(u_Light.position - v_FragPos);
float attenuation = 1.0 / (u_Light.constant + u_Light.linear * distance + u_Light.quadratic * (distance * distance));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;

// final
vec3 result = ambient + diffuse + specular + emission;
FragColor = vec4(result, 1.0);
}
68 changes: 54 additions & 14 deletions Sandbox3D/src/LightingSandbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ LightingSandbox::LightingSandbox()
m_vao->SetIndexBuffer(ebo);

// m_shader = elv::ShaderManager::Load("colors_cube_shader", "colors.vert", "colors.frag"); // default colored cube
m_shader = elv::ShaderManager::Load("textured_cube_shader", "textured_cube.vert", "textured_cube.frag"); // textured cube
m_shader = elv::ShaderManager::Load("textured_cube", "textured_cube.vert", "textured_cube_with_spotlight_caster.frag"); // textured cube

const uint64_t hash = elv::string_id("wooden_container");
elv::events::Subscribe<elv::events::TextureLoadedEvent>(m_textureLoadedCallback, hash);
Expand Down Expand Up @@ -177,15 +177,49 @@ void LightingSandbox::OnRender(float dt)
m_shader->SetInteger("u_Material.enableEmission", 0);
m_shader->SetFloat("u_Material.shininess", m_cubeMaterial.shininess);

if (m_lightDemoRotationEnabled) {
/*if (m_lightDemoRotationEnabled) {
m_light.position.x = sin(m_timer.Elapsed()) * 2.0f;
m_light.position.y = sin(m_timer.Elapsed() / 2.0f) * 1.0f;
}*/

// directional light
const bool enableDirLight = false;
if (enableDirLight) {
m_shader->SetVector3f("u_Light.direction", m_dirLight.direction);
m_shader->SetVector3f("u_Light.ambient", m_dirLight.ambient);
m_shader->SetVector3f("u_Light.diffuse", m_dirLight.diffuse);
m_shader->SetVector3f("u_Light.specular", m_dirLight.specular);
}

m_shader->SetVector3f("u_Light.position", m_light.position);
m_shader->SetVector3f("u_Light.ambient", m_light.ambient);
m_shader->SetVector3f("u_Light.diffuse", m_light.diffuse);
m_shader->SetVector3f("u_Light.specular", m_light.specular);
// point light
const bool enablePoint = false;
if (enablePoint) {
m_shader->SetVector3f("u_Light.position", m_pointLight.position);
m_shader->SetVector3f("u_Light.ambient", m_pointLight.ambient);
m_shader->SetVector3f("u_Light.diffuse", m_pointLight.diffuse);
m_shader->SetVector3f("u_Light.specular", m_pointLight.specular);
m_shader->SetFloat("u_Light.constant", m_pointLight.constant);
m_shader->SetFloat("u_Light.linear", m_pointLight.linear);
m_shader->SetFloat("u_Light.quadratic", m_pointLight.quadratic);
}

const bool enableSpotlight = true;
if (enableSpotlight) {
// spotlight (flashlight in this example with camera position and view direction)
m_flashlight.position = camera.GetPosition();
m_flashlight.direction = m_cameraController.GetFront();

m_shader->SetVector3f("u_Light.position", m_flashlight.position);
m_shader->SetVector3f("u_Light.direction", m_flashlight.direction);
m_shader->SetVector3f("u_Light.ambient", m_flashlight.ambient);
m_shader->SetVector3f("u_Light.diffuse", m_flashlight.diffuse);
m_shader->SetVector3f("u_Light.specular", m_flashlight.specular);
m_shader->SetFloat("u_Light.cutOff", cos(lia::radians(m_flashlight.cutOff)));
m_shader->SetFloat("u_Light.outerCutOff", cos(lia::radians(m_flashlight.outerCutOff)));
m_shader->SetFloat("u_Light.constant", m_flashlight.constant);
m_shader->SetFloat("u_Light.linear", m_flashlight.linear);
m_shader->SetFloat("u_Light.quadratic", m_flashlight.quadratic);
}

lia::mat4 model(1.0f);
model = lia::scale(model, lia::vec3(m_cubeScale.x, m_cubeScale.y, m_cubeScale.z))
Expand All @@ -197,10 +231,10 @@ void LightingSandbox::OnRender(float dt)
m_shader->SetMatrix4("u_InversedNormalModel", lia::inverse(model));
elv::Renderer::Submit(m_shader, m_vao, model);

// render lights
// render point lights
m_lightShader->Bind();
lia::mat4 lightModel(1.0f);
lightModel = lia::scale(lightModel, lia::vec3(0.2f)) * lia::translate({ 1.0f }, m_light.position);
lightModel = lia::scale(lightModel, lia::vec3(0.2f)) * lia::translate({ 1.0f }, m_pointLight.position);

elv::Renderer::Submit(m_lightShader, m_vao, lightModel);

Expand All @@ -211,7 +245,6 @@ void LightingSandbox::OnRender(float dt)
void LightingSandbox::OnImguiRender()
{
ImGui::Begin("Scene properties");
// ImGui::SetWindowSize(ImVec2(300.0f, 300.0f));

ImGui::Text("Cube Transform");
ImGui::Separator();
Expand All @@ -227,14 +260,21 @@ void LightingSandbox::OnImguiRender()
elv::editor::DrawSliderFloat("shininess", 1.0f, 256.0f, m_cubeMaterial.shininess);
ImGui::Separator();

elv::editor::DrawVec3Control("light_pos", "Light Position", m_light.position);
elv::editor::DrawVec3Control("light_dir", "Directional Light", m_dirLight.direction);
elv::editor::DrawVec3Control("light_pos", "Point Light Position", m_pointLight.position);
ImGui::Separator();

ImGui::Text("Directional Light Material");
ImGui::Separator();
elv::editor::DrawRGBColorControl("dir light ambient", m_dirLight.ambient);
elv::editor::DrawRGBColorControl("dir light diffuse", m_dirLight.diffuse);
elv::editor::DrawRGBColorControl("dir light specular", m_dirLight.specular);

ImGui::Text("Light Material");
ImGui::Text("Position Light Material");
ImGui::Separator();
elv::editor::DrawRGBColorControl("light ambient", m_light.ambient);
elv::editor::DrawRGBColorControl("light diffuse", m_light.diffuse);
elv::editor::DrawRGBColorControl("light specular", m_light.specular);
elv::editor::DrawRGBColorControl("pos light ambient", m_pointLight.ambient);
elv::editor::DrawRGBColorControl("pos light diffuse", m_pointLight.diffuse);
elv::editor::DrawRGBColorControl("pos light specular", m_pointLight.specular);

ImGui::Separator();
ImGui::Checkbox("Light demo rotation enabled", &m_lightDemoRotationEnabled);
Expand Down
Loading

0 comments on commit 966a813

Please sign in to comment.