Skip to content

Commit

Permalink
Added basic lights (directional, point, spot) (#806)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaremieromer authored Nov 19, 2024
1 parent 53dc1c2 commit e3cc906
Show file tree
Hide file tree
Showing 58 changed files with 706 additions and 101 deletions.
16 changes: 13 additions & 3 deletions docs/EngineComponents.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ Engine Components
* [Transform](#transform)
* [Tag](#tag)
* [Collider](#collider)
* [DirectionalLight](#directionalLight)
* [ConcaveCollider](#concavecollider)
* [PhysicsBody](#physicsbody)
* [MeshRenderer](#meshrenderer)
* [ToonRenderer](#toonrenderer)
* [PointLight](#pointlight)
* [SpotLight](#spotLight)
* [AudioSource](#audiosource)
* [Camera](#camera)
* [SceneNavigationCamera](#scenenavigationcamera)
* [SceneNavigationCamera](#scenenavigationcamera)
* [ParticleEmitter](#particleemitter)
* [NetworkDispatcher](#networkdispatcher)
* [FreeComponentGroup](#freecomponentgroup)
Expand Down Expand Up @@ -131,7 +133,15 @@ Toon renderers allows a mesh to be rendered using a toon material. They rely on
### PointLight
-------------
Point lights components specify a light source at a point in space emitting light in all directions. The light's position is the position of the associated transform and will be updated if the transform moves.
Point light components specify a light source at a point in space emitting light in all directions. The light's position is the position of the associated transform and will be updated if the transform moves.
### SpotLight
-------------
Spot light components specify a light source at a point in space emitting light in a single direction. The light's position is the position of the associated transform and will be updated if the transform moves.
### DirectionalLight
-------------
Directional light components specify a light source with no position, emitting light in a single direction. Directional lights do not cast shadows at this time.
### AudioSource
--------------
Expand Down Expand Up @@ -160,4 +170,4 @@ The NetworkDispatcher relies on some old, tedious, and probably unsafe code.
### FreeComponentGroup
----------------------
A FreeComponentGroup is a collection of FreeComponents belonging to an Entity. It is automatically added to each Entity upon creation. Projects do not need to directly interact with this component.
A FreeComponentGroup is a collection of FreeComponents belonging to an Entity. It is automatically added to each Entity upon creation. Projects do not need to directly interact with this component.
1 change: 1 addition & 0 deletions include/ncengine/NcFwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace graphics
{
struct NcGraphics;
class Camera;
struct DirectionalLight;
class MeshRenderer;
class ParticleEmitter;
struct PointLight;
Expand Down
1 change: 1 addition & 0 deletions include/ncengine/config/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct MemorySettings
unsigned maxRenderers = 100000;
unsigned maxTransforms = 100000;
unsigned maxPointLights = 10;
unsigned maxDirectionalLights = 10;
unsigned maxSpotLights = 10;
unsigned maxSkeletalAnimations = 1000;
unsigned maxTextures = 1000;
Expand Down
35 changes: 35 additions & 0 deletions include/ncengine/graphics/DirectionalLight.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @file DirectionalLight.h
* @copyright Jaremie Romer and McCallister Romer 2024
*/
#pragma once

#include "ncengine/ecs/Component.h"

#include "ncmath/Vector.h"

namespace nc::graphics
{
/** @brief Component representing an infinite, directional light, like the sun.
* Not implementing shadowing currently due to this type of light's proclivity for artifacts. */
struct DirectionalLight
{
explicit DirectionalLight(const Vector3& color_ = Vector3::One()) noexcept
: color{color_}
{
}

Vector3 color;
};
} // namespace nc::graphics

namespace nc
{
template<>
struct StoragePolicy<graphics::DirectionalLight> : DefaultStoragePolicy
{
static constexpr bool EnableOnAddCallbacks = false;
static constexpr bool EnableOnCommitCallbacks = true;
static constexpr bool EnableOnRemoveCallbacks = true;
};
} // namespace nc
2 changes: 2 additions & 0 deletions include/ncengine/graphics/NcGraphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct SystemEvents;

namespace config
{
struct AssetSettings;
struct GraphicsSettings;
struct MemorySettings;
struct ProjectSettings;
Expand Down Expand Up @@ -96,6 +97,7 @@ struct NcGraphics : public Module
* @note The NcAsset, NcScene, and NcWindow modules must be registered prior to initializing NcGraphics.
*/
auto BuildGraphicsModule(const config::ProjectSettings& projectSettings,
const config::AssetSettings& assetSettings,
const config::GraphicsSettings& graphicsSettings,
const config::MemorySettings& memorySettings,
ModuleProvider modules,
Expand Down
1 change: 1 addition & 0 deletions include/ncengine/type/EngineId.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ constexpr size_t NetworkDispatcherId = 14ull;
constexpr size_t WireframeRendererId = 15ull;
constexpr size_t HierarchyId = 16ull;
constexpr size_t MeshRenderer2Id = 17ull;
constexpr size_t DirectionalLightId = 18ull;
/** @} */

/** @{ */
Expand Down
2 changes: 2 additions & 0 deletions include/ncengine/type/EngineTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ncengine/ecs/Transform.h"
#include "ncengine/ecs/detail/FreeComponentGroup.h"
#include "ncengine/graphics/Camera.h"
#include "ncengine/graphics/DirectionalLight.h"
#include "ncengine/graphics/MeshRenderer.h"
#include "ncengine/graphics/ParticleEmitter.h"
#include "ncengine/graphics/PointLight.h"
Expand All @@ -33,6 +34,7 @@ REGISTER_TYPE(Transform);
REGISTER_TYPE(audio::AudioSource);
REGISTER_TYPE(ecs::detail::FreeComponentGroup);
REGISTER_TYPE(graphics::Camera);
REGISTER_TYPE(graphics::DirectionalLight);
REGISTER_TYPE(graphics::MeshRenderer);
REGISTER_TYPE(graphics::ToonRenderer);
REGISTER_TYPE(graphics::ParticleEmitter);
Expand Down
107 changes: 107 additions & 0 deletions resources/shaders/Lighting.fxh
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
struct DirectionalLightData
{
float3 color;
float padding;
float3 direction;
float padding2;
};

struct PointLightData
{
float4x4 viewProj;
float3 position;
int castsShadows;
float3 color;
float radius;
};

struct SpotLightData
{
float4x4 viewProj;
float3 position;
int castsShadows;
float3 color;
float innerAngle;
float3 direction;
float outerAngle;
float3 padding;
float radius;
};

struct LightInfluence
{
float3 color;
float specularAmt;
float diffuseAmt;
};

LightInfluence DirectionalLightRadiance(DirectionalLightData light, float3 fragWorldPos, float3 cameraPosition, float3 normal)
{
// Diffuse
float3 lightVec = normalize(-light.direction); // Vector from light to fragment
float normalDotLightVec = saturate(dot(normal, lightVec)); // Light influence is proportional to the angle the light hits the fragment
float diffuseTotal = normalDotLightVec;

// Specular
float3 cameraVec = normalize(cameraPosition - fragWorldPos); // Vector from camera to fragment
float3 reflectVec = reflect(-lightVec, normal); // Vector of reflected light to normal
float specular = pow(saturate(dot(cameraVec, reflectVec)), 32);
float specularTotal = specular * 0.5f;

LightInfluence lightInfluence = {light.color, specularTotal, diffuseTotal};
return lightInfluence;
}

LightInfluence PointLightRadiance(PointLightData light, float3 fragWorldPos, float3 cameraPosition, float3 normal)
{
// Diffuse
float3 lightVec = normalize(light.position - fragWorldPos); // Vector from light to fragment
float normalDotLightVec = saturate(dot(normal, lightVec)); // Light influence is proportional to the angle the light hits the fragment
float diffuseTotal = normalDotLightVec;

// Specular
float3 cameraVec = normalize(cameraPosition - fragWorldPos); // Vector from camera to fragment
float3 reflectVec = reflect(-lightVec, normal); // Vector of reflected light to normal
float specular = pow(saturate(dot(cameraVec, reflectVec)), 32);
float specularTotal = specular * 0.5f;

// Attenuation
float distance = length(light.position - fragWorldPos);
float attenuation = saturate(1.0 / pow(max(distance, 0.01), 4.0f)) * pow(light.radius, 3);
diffuseTotal *= attenuation;
specularTotal *= attenuation;

LightInfluence lightInfluence = {light.color, specularTotal, diffuseTotal};
return lightInfluence;
}

LightInfluence SpotLightRadiance(SpotLightData light, float3 fragWorldPos, float3 cameraPosition, float3 normal)
{
// Diffuse
float3 lightVec = normalize(light.position - fragWorldPos); // Vector from light to fragment
float normalDotLightVec = saturate(dot(normal, lightVec)); // Light influence is proportional to the angle the light hits the fragment
float diffuseTotal = normalDotLightVec;

// Specular
float3 cameraVec = normalize(cameraPosition - fragWorldPos); // Vector from camera to fragment
float3 reflectVec = reflect(-lightVec, normal); // Vector of reflected light to normal
float specular = pow(saturate(dot(cameraVec, reflectVec)), 32);
float specularTotal = specular * 0.5f;

// Spot Light Cutoff
float theta = dot(lightVec, normalize(-light.direction));
float epsilon = light.outerAngle - light.innerAngle;
float intensity = saturate((theta - light.innerAngle) / epsilon);
diffuseTotal *= intensity;
specularTotal *= intensity;

// Attenuation
float distance = length(light.position - fragWorldPos);
float attenuation = saturate(1.0 / pow(max(distance, 0.01), 4.0f)) * pow(light.radius, 3);

diffuseTotal *= attenuation;
specularTotal *= attenuation;

LightInfluence lightInfluence = {light.color, specularTotal, diffuseTotal};
return lightInfluence;
}
4 changes: 4 additions & 0 deletions sample/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ install(DIRECTORY ${PROJECT_SOURCE_DIR}/sample/assets/font
install(DIRECTORY ${PROJECT_SOURCE_DIR}/resources/nca
DESTINATION sample
)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/resources/shaders/
DESTINATION sample/nca/shaders
FILES_MATCHING REGEX ".*\.(fxh)"
)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/resources/shaders/compiled/
DESTINATION sample/nca/shaders
FILES_MATCHING REGEX ".*\.(spv)"
Expand Down
1 change: 1 addition & 0 deletions sample/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ max_spot_lights=10
max_textures=1000
max_cubemaps=10
max_particles=100000
max_directional_lights=10
[physics_settings]
physics_enabled=1
temp_allocator_size=67108864
Expand Down
13 changes: 11 additions & 2 deletions sample/source/scenes/PhysicsTest_Diligent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1067,12 +1067,21 @@ void PhysicsTest::Load(ecs::Ecs world, ModuleProvider modules)

world.Emplace<graphics::PointLight>(
world.Emplace<Entity>({
.position = Vector3{0.0f, 40.0f, 0.0f},
.position = Vector3{4.0f, 50.0f, 35.0f},
.tag = "Point Light"
}),
Vector3{1.0f, 1.0f, 1.0f},
Vector3{0.8f, 0.8f, 0.8f},
180.0f
300.0f
);

world.Emplace<graphics::DirectionalLight>(
world.Emplace<Entity>({
.position = Vector3{0.0f, 40.0f, 0.0f},
.rotation = nc::Quaternion::FromEulerAngles(-1.892f, 0.809f, -2.661f),
.tag = "Directional Light"
}),
Vector3{1.0f, 1.0f, 1.0f}
);
}

Expand Down
3 changes: 3 additions & 0 deletions source/ncengine/config/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ constexpr auto MaxSpotLightsKey = "max_spot_lights"sv;
constexpr auto MaxTexturesKey = "max_textures"sv;
constexpr auto MaxCubeMapsKey = "max_cubemaps"sv;
constexpr auto MaxParticlesKey = "max_particles"sv;
constexpr auto MaxDirectionalLightsKey = "max_directional_lights"sv;

// physics
constexpr auto PhysicsEnabledKey = "physics_enabled"sv;
Expand Down Expand Up @@ -216,6 +217,7 @@ auto BuildFromConfigMap(const std::unordered_map<std::string, std::string>& kvPa
ParseValueIfExists(out.maxTextures, MaxTexturesKey, kvPairs);
ParseValueIfExists(out.maxCubeMaps, MaxCubeMapsKey, kvPairs);
ParseValueIfExists(out.maxParticles, MaxParticlesKey, kvPairs);
ParseValueIfExists(out.maxDirectionalLights, MaxDirectionalLightsKey, kvPairs);
}
else if constexpr (std::same_as<Struct_t, nc::config::GraphicsSettings>)
{
Expand Down Expand Up @@ -367,6 +369,7 @@ void Write(std::ostream& stream, const Config& config, bool writeSections)
::WriteKVPair(stream, MaxTexturesKey, config.memorySettings.maxTextures);
::WriteKVPair(stream, MaxCubeMapsKey, config.memorySettings.maxCubeMaps);
::WriteKVPair(stream, MaxParticlesKey, config.memorySettings.maxParticles);
::WriteKVPair(stream, MaxDirectionalLightsKey, config.memorySettings.maxDirectionalLights);

if (writeSections) stream << "[physics_settings]\n";
::WriteKVPair(stream, PhysicsEnabledKey, config.physicsSettings.enabled);
Expand Down
1 change: 1 addition & 0 deletions source/ncengine/config/default_config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ max_spot_lights=10
max_textures=1000
max_cubemaps=10
max_particles=100000
max_directional_lights=10
[physics_settings]
physics_enabled=1
temp_allocator_size=67108864
Expand Down
7 changes: 7 additions & 0 deletions source/ncengine/engine/ComponentFactories.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "ncengine/audio/AudioSource.h"
#include "ncengine/ecs/FrameLogic.h"
#include "ncengine/ecs/ComponentRegistry.h"
#include "ncengine/graphics/DirectionalLight.h"
#include "ncengine/graphics/MeshRenderer.h"
#include "ncengine/graphics/ParticleEmitter.h"
#include "ncengine/graphics/PointLight.h"
#include "ncengine/graphics/MeshRenderer.h"
Expand Down Expand Up @@ -86,4 +88,9 @@ auto CreateRigidBody(Entity entity, const std::any&) -> RigidBody
{
return RigidBody{entity};
}

auto CreateDirectionalLight(Entity, const std::any&) -> graphics::DirectionalLight
{
return graphics::DirectionalLight{};
}
} // namespace nc
1 change: 1 addition & 0 deletions source/ncengine/engine/ComponentFactories.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ auto CreateSkeletalAnimator(Entity entity, const std::any&) -> graphics::Skeleta
auto CreateSpotLight(Entity entity, const std::any&) -> graphics::SpotLight;
auto CreateNetworkDispatcher(Entity entity, const std::any&) -> net::NetworkDispatcher;
auto CreateRigidBody(Entity entity, const std::any&) -> RigidBody;
auto CreateDirectionalLight(Entity entity, const std::any&) -> graphics::DirectionalLight;
} // namespace nc
1 change: 1 addition & 0 deletions source/ncengine/engine/ModuleFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ auto BuildModuleRegistry(Registry* registry,
BuildDefaultAssetMap()));

moduleRegistry->Register(nc::graphics::BuildGraphicsModule(config.projectSettings,
config.assetSettings,
config.graphicsSettings,
config.memorySettings,
ModuleProvider{moduleRegistry.get()},
Expand Down
13 changes: 11 additions & 2 deletions source/ncengine/engine/registration/GraphicsTypes.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "GraphicsTypes.h"
#include "ncengine/graphics/Camera.h"
#include "ncengine/graphics/DirectionalLight.h"
#include "ncengine/graphics/MeshRenderer.h"
#include "ncengine/graphics/MeshRenderer2.h"
#include "ncengine/graphics/ParticleEmitter.h"
Expand Down Expand Up @@ -80,7 +81,6 @@ void RegisterGraphicsTypes(ecs::ComponentRegistry& registry, size_t maxEntities)
SerializeSpotLight,
DeserializeSpotLight
);

Register<MeshRenderer2>(
registry,
maxEntities,
Expand All @@ -91,6 +91,15 @@ void RegisterGraphicsTypes(ecs::ComponentRegistry& registry, size_t maxEntities)
nullptr,
nullptr
);

Register<graphics::DirectionalLight>(
registry,
maxEntities,
DirectionalLightId,
"DirectionalLight",
ui::editor::DirectionalLightUIWidget,
CreateDirectionalLight,
SerializeDirectionalLight,
DeserializeDirectionalLight
);
}
} // namespace nc
1 change: 1 addition & 0 deletions source/ncengine/graphics/NcGraphicsImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ namespace nc::graphics
{
#ifndef NC_USE_DILIGENT
auto BuildGraphicsModule(const config::ProjectSettings& projectSettings,
const config::AssetSettings& ,
const config::GraphicsSettings& graphicsSettings,
const config::MemorySettings& memorySettings,
ModuleProvider modules,
Expand Down
Loading

0 comments on commit e3cc906

Please sign in to comment.