Skip to content

Commit

Permalink
Added possibility to spawn multiple spotlights
Browse files Browse the repository at this point in the history
- LightSystem to enable flashlight
- "flashmode" and "debug render" flags for spotlights
- demo scene polishing
  • Loading branch information
denyskryvytskyi committed Mar 25, 2024
1 parent 2f836fd commit 0b6db57
Show file tree
Hide file tree
Showing 27 changed files with 160 additions and 78 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.obj filter=lfs diff=lfs merge=lfs -text
*.gltf filter=lfs diff=lfs merge=lfs -text
*.FBX filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
Binary file added .github/demo/Scene_demo_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions Engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ set(ENGINE_HEADERS
"src/Scene/Systems/BehaviorSystem.h"
"src/Scene/Systems/Physics2dSystem.h"
"src/Scene/Systems/RenderSystem.h"
"src/Scene/Systems/LightSystem.h"
"src/Resources/TextureManager.h"
"src/Resources/AudioManager.h"
"src/Resources/FontManager.h"
Expand Down Expand Up @@ -132,6 +133,7 @@ set(ENGINE_SOURCES
"src/Scene/Systems/BehaviorSystem.cpp"
"src/Scene/Systems/Physics2dSystem.cpp"
"src/Scene/Systems/RenderSystem.cpp"
"src/Scene/Systems/LightSystem.cpp"
"src/Resources/TextureManager.cpp"
"src/Resources/AudioManager.cpp"
"src/Resources/FontManager.cpp"
Expand Down
23 changes: 9 additions & 14 deletions Engine/res/shaders/mesh_phong.frag
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,19 @@ struct SpotLight {
float outerCutOff;
};

#define NR_POINT_LIGHTS 4
#define MAX_POINT_LIGHTS 16
#define MAX_SPOT_LIGHTS 16

uniform vec3 u_ViewPos;
uniform Material u_Material;

uniform bool u_DirLightEnabled;
uniform bool u_SpotLightEnabled;
uniform bool u_PointLightEnabled;
uniform int u_ActivePointLightsAmount;
uniform int u_ActiveSpotLightsAmount;

uniform DirLight u_DirLight;
uniform PointLight u_PointLights[NR_POINT_LIGHTS];
uniform SpotLight u_SpotLight;
uniform PointLight u_PointLights[MAX_POINT_LIGHTS];
uniform SpotLight u_SpotLights[MAX_SPOT_LIGHTS];

in vec3 v_FragPos;
in vec3 v_Normal;
Expand Down Expand Up @@ -100,16 +100,11 @@ void main()
result += CalcDirLight(u_DirLight, diffuseMap, specularMap, emissionMap, normal, viewDir);
}

if (u_PointLightEnabled)
{
for (int i = 0; i < NR_POINT_LIGHTS && i < u_ActivePointLightsAmount; ++i)
result += CalcPointLight(u_PointLights[i], diffuseMap, specularMap, emissionMap, normal, viewDir);
}
for (int i = 0; i < MAX_POINT_LIGHTS && i < u_ActivePointLightsAmount; ++i)
result += CalcPointLight(u_PointLights[i], diffuseMap, specularMap, emissionMap, normal, viewDir);

if (u_SpotLightEnabled)
{
result += CalcSpotLight(u_SpotLight, diffuseMap, specularMap, emissionMap, normal, viewDir);
}
for (int i = 0; i < MAX_SPOT_LIGHTS && i < u_ActiveSpotLightsAmount; ++i)
result += CalcSpotLight(u_SpotLights[i], diffuseMap, specularMap, emissionMap, normal, viewDir);

float alpha = texture(u_Material.texture_transparency, v_UV).r * diffuseMapWithAlpha.a;

Expand Down
8 changes: 6 additions & 2 deletions Engine/src/Editor/Panels/SceneHierarchyPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ void SceneHierarchyPanel::DrawProperties()
if (ImGui::BeginPopup("AddComponent")) {
DisplayAddComponentEntry<TransformComponent>("Transform");
DisplayAddComponentEntry<StaticMeshComponent>("Static Mesh");
DisplayAddComponentEntry<DirectionalLightComponent>("Directional Light");
DisplayAddComponentEntry<PointLightComponent>("Point Light");
DisplayAddComponentEntry<SpotLightComponent>("Spotlight");
DisplayAddComponentEntry<TextComponent>("Text");
Expand Down Expand Up @@ -253,7 +254,7 @@ void SceneHierarchyPanel::DrawProperties()
// Mesh name
const auto names = gMeshLibrary.GetMeshes();

static int currentMeshIndex = 0;
static std::uint64_t currentMeshIndex = 0;
const bool isMeshSet = component.GetMeshPtr() != nullptr;
std::string comboLabel;

Expand Down Expand Up @@ -352,7 +353,7 @@ void SceneHierarchyPanel::DrawProperties()
// Textures
if (Material* material = component.GetMaterial()) {
const auto textures = gTextureManager.GetTextureNames();
static int mapIndices[Material::TextureSlot::Count];
static std::uint64_t mapIndices[Material::TextureSlot::Count];

for (int i = 0; i < Material::TextureSlot::Count; ++i) {

Expand Down Expand Up @@ -405,6 +406,8 @@ void SceneHierarchyPanel::DrawProperties()

DrawComponent<SpotLightComponent>("Spot Light", m_selectedEntity, m_context, [](SpotLightComponent& component) {
ImGui::Checkbox("Enabled", &component.enabled);
ImGui::Checkbox("Flashlight mode", &component.flashlightMode);
ImGui::Checkbox("Debug render", &component.debugRender);

editor::DrawSliderFloat("Cut off angle", 0.0f, 180.0f, component.cutOff);
editor::DrawSliderFloat("Outer cut off angle", 0.0f, 180.0f, component.outerCutOff);
Expand All @@ -416,6 +419,7 @@ void SceneHierarchyPanel::DrawProperties()

DrawComponent<PointLightComponent>("Point Light", m_selectedEntity, m_context, [](PointLightComponent& component) {
ImGui::Checkbox("Enabled", &component.enabled);
ImGui::Checkbox("Debug render", &component.debugRender);

editor::DrawRGBColorControl("ambient", component.ambient);
editor::DrawRGBColorControl("diffuse", component.diffuse);
Expand Down
6 changes: 5 additions & 1 deletion Engine/src/Scene/Components/LightComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
namespace elv {
struct PointLightComponent {
bool enabled { false };
bool debugRender { false };

lia::vec3 ambient { 0.7f, 0.7f, 0.7f };
lia::vec3 diffuse { 0.7f, 0.7f, 0.7f };
lia::vec3 specular { 0.7f, 0.7f, 0.7f };

// distance 50
float constant { 1.0f };
float linear { 0.09f };
Expand All @@ -25,6 +26,9 @@ struct DirectionalLightComponent {

struct SpotLightComponent {
bool enabled { false };
bool flashlightMode { false }; // follow camera
bool debugRender { false };

lia::vec3 ambient { 0.7f, 0.7f, 0.7f };
lia::vec3 diffuse { 0.7f, 0.7f, 0.7f };
lia::vec3 specular { 0.7f, 0.7f, 0.7f };
Expand Down
2 changes: 2 additions & 0 deletions Engine/src/Scene/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "Components/SceneComponents.h"
#include "Components/StaticMeshComponent.h"
#include "Systems/BehaviorSystem.h"
#include "Systems/LightSystem.h"
#include "Systems/Physics2dSystem.h"
#include "Systems/Render2dSystem.h"
#include "Systems/RenderSystem.h"
Expand Down Expand Up @@ -44,6 +45,7 @@ void Scene::OnInit()
#endif
RegisterSystem<Render2dSystem>();
RegisterSystem<Physics2dSystem>();
RegisterSystem<LightSystem>();

if (gEngineSettings.enableSceneGraph) {
m_sceneGraph.OnInit(this);
Expand Down
34 changes: 34 additions & 0 deletions Engine/src/Scene/Systems/LightSystem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "LightSystem.h"

#include "Scene/Components/LightComponent.h"
#include "Scene/Components/TransformComponent.h"
#include "Scene/Scene.h"

#include "Core/Application.h"
#include "Renderer/CameraController.h"

namespace elv {
void LightSystem::OnUpdate(float dt)
{
auto spotLightsPool = m_pScene->GetComponentPool<SpotLightComponent>();
auto& spotLightComponents = spotLightsPool->GetComponents();
for (std::uint32_t i = 0; i < spotLightsPool->Size(); ++i) {
auto& spotlight = spotLightComponents[i];
if (!spotlight.enabled)
continue;

if (spotlight.flashlightMode) {
const auto entity = spotLightsPool->GetEntity(i);
if (m_pScene->HasComponent<TransformComponent>(entity)) {
auto& transform = m_pScene->GetComponent<TransformComponent>(entity);

const auto cameraController = Application::Get().GetCameraController();

transform.pos = cameraController->GetCamera().GetPosition();
transform.rotation = cameraController->GetFront();
break;
}
}
}
}
} // namespace elv
12 changes: 12 additions & 0 deletions Engine/src/Scene/Systems/LightSystem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "Scene/ComponentSystem.h"

namespace elv {

class LightSystem : public ecs::IComponentSystem {
public:
void OnUpdate(float dt) override;
};

} // namespace elv
75 changes: 46 additions & 29 deletions Engine/src/Scene/Systems/RenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ void RenderSystem::OnRender(float dt)

// point lights
{
bool isAnyPointLightActive = false;
int activePointLightsCounter = 0;

auto pointLightsPool = m_pScene->GetComponentPool<PointLightComponent>();
Expand All @@ -60,7 +59,6 @@ void RenderSystem::OnRender(float dt)
if (!pointLight.enabled)
continue;

isAnyPointLightActive = true;
const auto entity = pointLightsPool->GetEntity(i);
if (m_pScene->HasComponent<TransformComponent>(entity)) {
auto& transform = m_pScene->GetComponent<TransformComponent>(entity);
Expand All @@ -75,39 +73,38 @@ void RenderSystem::OnRender(float dt)
++activePointLightsCounter;
}
}
m_shader->SetInteger("u_PointLightEnabled", isAnyPointLightActive);
m_shader->SetInteger("u_ActivePointLightsAmount", activePointLightsCounter);
// TODO: need to pass how much point lights are activated
}

// spotlight (flashlight in this example with camera position and view direction)
bool isAnySpotlightAvailable = false;
auto spotLightsPool = m_pScene->GetComponentPool<SpotLightComponent>();
auto& spotLightComponents = spotLightsPool->GetComponents();
for (std::uint32_t i = 0; i < spotLightsPool->Size(); ++i) {
auto& spotlight = spotLightComponents[i];
if (!spotlight.enabled)
continue;

isAnySpotlightAvailable = true;
// spotlights
{
int activeSpotLightsCounter = 0;
auto spotLightsPool = m_pScene->GetComponentPool<SpotLightComponent>();
auto& spotLightComponents = spotLightsPool->GetComponents();
for (std::uint32_t i = 0; i < spotLightsPool->Size(); ++i) {
auto& spotlight = spotLightComponents[i];
if (!spotlight.enabled)
continue;

const auto entity = spotLightsPool->GetEntity(i);
if (m_pScene->HasComponent<TransformComponent>(entity)) {
auto& transform = m_pScene->GetComponent<TransformComponent>(entity);
const auto entity = spotLightsPool->GetEntity(i);
if (m_pScene->HasComponent<TransformComponent>(entity)) {
auto& transform = m_pScene->GetComponent<TransformComponent>(entity);

m_shader->SetVector3f("u_SpotLight.position", transform.pos);
m_shader->SetVector3f("u_SpotLight.direction", transform.rotation);
m_shader->SetVector3f("u_SpotLight.ambient", spotlight.ambient);
m_shader->SetVector3f("u_SpotLight.diffuse", spotlight.diffuse);
m_shader->SetVector3f("u_SpotLight.specular", spotlight.specular);
m_shader->SetFloat("u_SpotLight.cutOff", cos(lia::radians(spotlight.cutOff)));
m_shader->SetFloat("u_SpotLight.outerCutOff", cos(lia::radians(spotlight.outerCutOff)));
m_shader->SetFloat("u_SpotLight.constant", spotlight.constant);
m_shader->SetFloat("u_SpotLight.linear", spotlight.linear);
m_shader->SetFloat("u_SpotLight.quadratic", spotlight.quadratic);
m_shader->SetVector3f(fmt::format("u_SpotLights[{}].position", activeSpotLightsCounter), transform.pos);
m_shader->SetVector3f(fmt::format("u_SpotLights[{}].direction", activeSpotLightsCounter), transform.rotation);
m_shader->SetVector3f(fmt::format("u_SpotLights[{}].ambient", activeSpotLightsCounter), spotlight.ambient);
m_shader->SetVector3f(fmt::format("u_SpotLights[{}].diffuse", activeSpotLightsCounter), spotlight.diffuse);
m_shader->SetVector3f(fmt::format("u_SpotLights[{}].specular", activeSpotLightsCounter), spotlight.specular);
m_shader->SetFloat(fmt::format("u_SpotLights[{}].cutOff", activeSpotLightsCounter), cos(lia::radians(spotlight.cutOff)));
m_shader->SetFloat(fmt::format("u_SpotLights[{}].outerCutOff", activeSpotLightsCounter), cos(lia::radians(spotlight.outerCutOff)));
m_shader->SetFloat(fmt::format("u_SpotLights[{}].constant", activeSpotLightsCounter), spotlight.constant);
m_shader->SetFloat(fmt::format("u_SpotLights[{}].linear", activeSpotLightsCounter), spotlight.linear);
m_shader->SetFloat(fmt::format("u_SpotLights[{}].quadratic", activeSpotLightsCounter), spotlight.quadratic);
++activeSpotLightsCounter;
}
}
m_shader->SetInteger("u_ActiveSpotLightsAmount", activeSpotLightsCounter);
}
m_shader->SetInteger("u_SpotLightEnabled", isAnySpotlightAvailable);

// ===================================================

Expand All @@ -132,10 +129,12 @@ void RenderSystem::OnRender(float dt)
}
}

// render debug render point lights meshes
// render debug point/spot lights meshes
const bool renderDebugPointLightsMesh = true;
if (renderDebugPointLightsMesh) {
m_lightShader->Bind();

// point lights
auto pointLightsPool = m_pScene->GetComponentPool<PointLightComponent>();
auto& pointLightComponents = pointLightsPool->GetComponents();
for (std::uint32_t i = 0; i < pointLightsPool->Size(); ++i) {
Expand All @@ -154,6 +153,24 @@ void RenderSystem::OnRender(float dt)
Renderer::Submit(m_lightShader, m_debugLightMesh, transform.worldMatrix);
}
}

// spotlights
auto spotLightsPool = m_pScene->GetComponentPool<SpotLightComponent>();
auto& spotLightComponents = spotLightsPool->GetComponents();
for (std::uint32_t i = 0; i < spotLightsPool->Size(); ++i) {
auto& spotlight = spotLightComponents[i];
if (spotlight.debugRender) {
const auto entity = spotLightsPool->GetEntity(i);
if (m_pScene->HasComponent<TransformComponent>(entity)) {
auto& transform = m_pScene->GetComponent<TransformComponent>(entity);

m_lightShader->SetVector3f("u_Color.ambient", spotlight.ambient);
m_lightShader->SetVector3f("u_Color.diffuse", spotlight.diffuse);

Renderer::Submit(m_lightShader, m_debugLightMesh, transform.worldMatrix);
}
}
}
}

Renderer::EndScene();
Expand Down
25 changes: 15 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,31 @@ Elven Engine is primarily a 2D/3D game engine that is being developed from scrat
- [x] Add/Play/Pause/Stop functionality
+ [ ] In-engine editor (WIP; based on ImGui)
- [x] Editor Camera (holding RMB): WASD movement, QE up/down, ZX rotation
- [x] Scene hierarchy
- [x] Properties: Transform, Static Mesh material, Point/Directional/Spot light, UI tranform, Text
- [x] Settings: fullscreen, VSync, MSAA
- [x] Scene hierarchy panel
- [x] Context menu to add/delete entity
- [x] Properties panel:
- [x] Components: Transform, Static Mesh with material, Point/Directional/Spot light, UI transform, Text, Sprite
- [x] "Add component" button
- [x] Component settings context menu
- [x] Settings panel: fullscreen, VSync, MSAA
- [ ] Telemetry: performance panel
- [ ] Graphics stats
+ [x] Just cool stuff
- [x] Orthographic camera controller (OrthographicCameraController), that can be used if needed
- [x] Fly(FPS-like) 3D camera support (CameraController)
- [x] Editor camera controller to move on the scene in editor mode.
+ [ ] Multithreading support
- [x] async resources loading: texture, mesh
- [ ] Thread pool

## Demo
### 3D rendering
<img src=".github/demo/Scene_demo_0.png">

| Lighting environments with spotlight, directional, and point lights | Cube transformation and simple light |
| --- | --- |
| <img src=".github/demo/light_casters_demo.gif"> | <img src=".github/demo/cube_light_demo.gif"> |

### 2D Rendering
**Space Invaders full demo**

Expand All @@ -78,13 +90,6 @@ https://github.com/denyskryvytskyi/ElvenEngine/assets/25298585/f0d32c8b-1ed2-44e
| Ping Pong | Quad and texture batch rendering (20000 wizards) |
| <img src=".github/demo/pong.gif"> | <img src=".github/demo/wizards.gif"> |

### 3D rendering
<img src=".github/demo/models_1.png">

| Lighting environments with spotlight, directional, and point lights | Cube transformation and simple light |
| --- | --- |
| <img src=".github/demo/light_casters_demo.gif"> | <img src=".github/demo/cube_light_demo.gif"> |

## Getting Started

Windows platform only support for now (Linux and MacOS platforms are for future support)
Expand Down
Binary file modified Sandbox3D/assets/models/adam/adamHead.bin
Binary file not shown.
Binary file modified Sandbox3D/assets/models/backpack/scene.bin
Binary file not shown.
11 changes: 11 additions & 0 deletions Sandbox3D/assets/models/dark_knight/license.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Model Information:
* title: Dark Knight
* source: https://sketchfab.com/3d-models/dark-knight-e2208bdc46304f6faa18728778986f35
* author: Nick Scott (https://sketchfab.com/Nickjjscott)

Model License:
* license type: CC-BY-NC-4.0 (http://creativecommons.org/licenses/by-nc/4.0/)
* requirements: Author must be credited. No commercial use.

If you use this 3D model in your project be sure to copy paste this credit wherever you share it:
This work is based on "Dark Knight" (https://sketchfab.com/3d-models/dark-knight-e2208bdc46304f6faa18728778986f35) by Nick Scott (https://sketchfab.com/Nickjjscott) licensed under CC-BY-NC-4.0 (http://creativecommons.org/licenses/by-nc/4.0/)
3 changes: 3 additions & 0 deletions Sandbox3D/assets/models/dark_knight/scene.bin
Git LFS file not shown
3 changes: 3 additions & 0 deletions Sandbox3D/assets/models/dark_knight/scene.gltf
Git LFS file not shown
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0b6db57

Please sign in to comment.