Browse Source

Replace point light with sphere area light

master
C. J. Howard 11 months ago
parent
commit
c0af8b7155
10 changed files with 134 additions and 44 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +4
    -0
      src/engine/math/numbers.hpp
  3. +68
    -20
      src/engine/render/passes/material-pass.cpp
  4. +5
    -0
      src/engine/render/passes/material-pass.hpp
  5. +4
    -4
      src/engine/scene/light-type.hpp
  6. +1
    -1
      src/engine/scene/sphere-light.cpp
  7. +26
    -9
      src/engine/scene/sphere-light.hpp
  8. +2
    -2
      src/game/game.hpp
  9. +21
    -6
      src/game/states/nest-view-state.cpp
  10. +2
    -2
      src/game/states/nest-view-state.hpp

+ 1
- 0
CMakeLists.txt View File

@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.25)
option(APPLICATION_NAME "Application name" "Antkeeper")
option(APPLICATION_VERSION "Application version string" "0.0.0")
option(APPLICATION_AUTHOR "Application author" "C. J. Howard")

+ 4
- 0
src/engine/math/numbers.hpp View File

@ -68,6 +68,10 @@ inline constexpr T inv_pi = std::numbers::inv_pi_v;
template <class T>
inline constexpr T inv_sqrt_pi = std::numbers::inv_sqrtpi_v<T>;
/// Pi^2.
template <class T>
inline constexpr T sqr_pi = std::numbers::pi_v<T> * std::numbers::pi_v<T>;
/// ln(2).
template <class T>
inline constexpr T ln_2 = std::numbers::ln2_v<T>;

+ 68
- 20
src/engine/render/passes/material-pass.cpp View File

@ -40,8 +40,8 @@
#include <engine/scene/collection.hpp>
#include <engine/scene/ambient-light.hpp>
#include <engine/scene/directional-light.hpp>
#include <engine/scene/point-light.hpp>
#include <engine/scene/spot-light.hpp>
#include <engine/scene/sphere-light.hpp>
#include <engine/config.hpp>
#include <engine/math/quaternion.hpp>
#include <engine/math/projection.hpp>
@ -315,6 +315,7 @@ void material_pass::evaluate_lighting(const render::context& ctx)
directional_light_count = 0;
directional_shadow_count = 0;
spot_light_count = 0;
sphere_light_count = 0;
const auto& lights = ctx.collection->get_objects(scene::light::object_type_id);
for (const scene::object_base* object: lights)
@ -340,25 +341,6 @@ void material_pass::evaluate_lighting(const render::context& ctx)
break;
}
// Add point light
case scene::light_type::point:
{
const scene::point_light& point_light = static_cast<const scene::point_light&>(light);
const std::size_t index = point_light_count;
++point_light_count;
if (point_light_count > point_light_colors.size())
{
point_light_colors.resize(point_light_count);
point_light_positions.resize(point_light_count);
}
point_light_colors[index] = point_light.get_luminous_flux() * ctx.camera->get_exposure_normalization();
point_light_positions[index] = point_light.get_translation();
break;
}
// Add directional light
case scene::light_type::directional:
{
@ -421,6 +403,49 @@ void material_pass::evaluate_lighting(const render::context& ctx)
break;
}
// Add sphere light
case scene::light_type::sphere:
{
const scene::sphere_light& sphere_light = static_cast<const scene::sphere_light&>(light);
if (sphere_light.get_radius() == 0.0f)
{
const std::size_t index = point_light_count;
++point_light_count;
if (point_light_count > point_light_colors.size())
{
point_light_colors.resize(point_light_count);
point_light_positions.resize(point_light_count);
}
point_light_colors[index] = sphere_light.get_luminous_flux() * ctx.camera->get_exposure_normalization();
point_light_positions[index] = sphere_light.get_translation();
}
else
{
const std::size_t index = sphere_light_count;
++sphere_light_count;
if (sphere_light_count > sphere_light_colors.size())
{
sphere_light_colors.resize(sphere_light_count);
sphere_light_positions_radii.resize(sphere_light_count);
}
sphere_light_colors[index] = sphere_light.get_luminous_flux() * ctx.camera->get_exposure_normalization();
const auto& position = sphere_light.get_translation();
auto& position_radius = sphere_light_positions_radii[index];
position_radius[0] = position.x();
position_radius[1] = position.y();
position_radius[2] = position.z();
position_radius[3] = sphere_light.get_radius();
}
break;
}
default:
break;
}
@ -432,6 +457,7 @@ void material_pass::evaluate_lighting(const render::context& ctx)
lighting_state_hash = hash::combine(lighting_state_hash, std::hash<std::size_t>{}(directional_shadow_count));
lighting_state_hash = hash::combine(lighting_state_hash, std::hash<std::size_t>{}(point_light_count));
lighting_state_hash = hash::combine(lighting_state_hash, std::hash<std::size_t>{}(spot_light_count));
lighting_state_hash = hash::combine(lighting_state_hash, std::hash<std::size_t>{}(sphere_light_count));
}
void material_pass::evaluate_misc(const render::context& ctx)
@ -471,6 +497,7 @@ std::unique_ptr material_pass::generate_shader_program(const
definitions["DIRECTIONAL_SHADOW_COUNT"] = std::to_string(directional_shadow_count);
definitions["POINT_LIGHT_COUNT"] = std::to_string(point_light_count);
definitions["SPOT_LIGHT_COUNT"] = std::to_string(spot_light_count);
definitions["SPHERE_LIGHT_COUNT"] = std::to_string(sphere_light_count);
auto shader_program = shader_template.build(definitions);
@ -619,6 +646,27 @@ void material_pass::build_shader_command_buffer(std::vector
}
}
// Update sphere light variables
if (sphere_light_count)
{
if (auto sphere_light_colors_var = shader_program.variable("sphere_light_colors"))
{
auto sphere_light_positions_radii_var = shader_program.variable("sphere_light_positions_radii");
if (sphere_light_positions_radii_var)
{
command_buffer.emplace_back
(
[&, sphere_light_colors_var, sphere_light_positions_radii_var]()
{
sphere_light_colors_var->update(std::span<const float3>{sphere_light_colors.data(), sphere_light_count});
sphere_light_positions_radii_var->update(std::span<const float4>{sphere_light_positions_radii.data(), sphere_light_count});
}
);
}
}
}
// Update time variable
if (auto time_var = shader_program.variable("time"))
{

+ 5
- 0
src/engine/render/passes/material-pass.hpp View File

@ -120,6 +120,11 @@ private:
std::vector<float2> spot_light_cutoffs;
std::size_t spot_light_count;
// Sphere lights
std::vector<float3> sphere_light_colors;
std::vector<float4> sphere_light_positions_radii;
std::size_t sphere_light_count;
// Misc
float time;
float timestep;

+ 4
- 4
src/engine/scene/light-type.hpp View File

@ -33,11 +33,11 @@ enum class light_type: std::uint8_t
/// Directional light.
directional,
/// Point light.
point,
/// Spot light.
spot
spot,
/// Sphere light.
sphere
};
} // namespace scene

src/engine/scene/point-light.cpp → src/engine/scene/sphere-light.cpp View File

@ -17,7 +17,7 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include <engine/scene/point-light.hpp>
#include <engine/scene/sphere-light.hpp>
namespace scene {

src/engine/scene/point-light.hpp → src/engine/scene/sphere-light.hpp View File

@ -17,8 +17,8 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_SCENE_POINT_LIGHT_HPP
#define ANTKEEPER_SCENE_POINT_LIGHT_HPP
#ifndef ANTKEEPER_SCENE_SPHERE_LIGHT_HPP
#define ANTKEEPER_SCENE_SPHERE_LIGHT_HPP
#include <engine/scene/light.hpp>
#include <engine/math/vector.hpp>
@ -26,19 +26,19 @@
namespace scene {
/**
* Light source that radiates outward from a point.
* Light source that radiates outward from a sphere.
*/
class point_light: public light
class sphere_light: public light
{
public:
/// Returns light_type::point
/// Returns light_type::sphere.
[[nodiscard]] inline light_type get_light_type() const noexcept override
{
return light_type::point;
return light_type::sphere;
}
/**
* Sets the luminous flux of the point light.
* Sets the luminous flux of the sphere light.
*
* @param luminous_flux Luminous flux, in *lm*.
*/
@ -47,16 +47,33 @@ public:
m_luminous_flux = luminous_flux;
}
/// Returns the luminous flux of the point light, in *lm*.
/**
* Sets the radius of the sphere light.
*
* @param radius Radius of the sphere light.
*/
inline void set_radius(float radius) noexcept
{
m_radius = radius;
}
/// Returns the luminous flux of the sphere light, in *lm*.
[[nodiscard]] inline const math::vector<float, 3>& get_luminous_flux() const noexcept
{
return m_luminous_flux;
}
/// Returns the radius of the sphere light.
[[nodiscard]] inline float get_radius() const noexcept
{
return m_radius;
}
private:
math::vector<float, 3> m_luminous_flux{0.0f, 0.0f, 0.0f};
float m_radius{0.0f};
};
} // namespace scene
#endif // ANTKEEPER_SCENE_POINT_LIGHT_HPP
#endif // ANTKEEPER_SCENE_SPHERE_LIGHT_HPP

+ 2
- 2
src/game/game.hpp View File

@ -49,7 +49,7 @@
#include <engine/utility/frame-scheduler.hpp>
#include <engine/scene/text.hpp>
#include <engine/scene/directional-light.hpp>
#include <engine/scene/point-light.hpp>
#include <engine/scene/sphere-light.hpp>
#include <engine/scene/spot-light.hpp>
#include <engine/scene/ambient-light.hpp>
#include <engine/scene/camera.hpp>
@ -338,7 +338,7 @@ public:
std::shared_ptr<scene::camera> underground_camera;
std::unique_ptr<scene::directional_light> underground_directional_light;
std::unique_ptr<scene::ambient_light> underground_ambient_light;
std::unique_ptr<scene::point_light> underground_point_light;
std::unique_ptr<scene::sphere_light> underground_sphere_light;
scene::collection* active_scene;
// Animation

+ 21
- 6
src/game/states/nest-view-state.cpp View File

@ -75,6 +75,7 @@
#include <engine/utility/state-machine.hpp>
#include <engine/scene/static-mesh.hpp>
#include <engine/scene/skeletal-mesh.hpp>
#include <engine/scene/sphere-light.hpp>
#include <engine/geom/intersection.hpp>
#include <engine/animation/ease.hpp>
@ -122,14 +123,15 @@ nest_view_state::nest_view_state(::game& ctx):
// Create ambient light
ctx.underground_ambient_light = std::make_unique<scene::ambient_light>();
ctx.underground_ambient_light->set_illuminance(float3{1.0f, 1.0f, 1.0f} * 0.025f);
ctx.underground_ambient_light->set_illuminance(float3{1.0f, 1.0f, 1.0f} * 0.075f);
ctx.underground_scene->add_object(*ctx.underground_ambient_light);
// Create point light
ctx.underground_point_light = std::make_unique<scene::point_light>();
ctx.underground_point_light->set_luminous_flux(float3{1.0f, 1.0f, 1.0f} * 200.0f);
ctx.underground_point_light->set_translation(float3{-13.0f, 7.0f, -6.0f});
ctx.underground_scene->add_object(*ctx.underground_point_light);
// Create sphere light
ctx.underground_sphere_light = std::make_unique<scene::sphere_light>();
ctx.underground_sphere_light->set_luminous_flux(float3{0.8f, 0.88f, 1.0f} * 250.0f);
ctx.underground_sphere_light->set_radius(3.0f);
ctx.underground_sphere_light->set_translation(float3{-13.0f, 7.0f, -6.0f});
ctx.underground_scene->add_object(*ctx.underground_sphere_light);
// Create chamber
auto chamber_eid = ctx.entity_registry->create();
@ -165,6 +167,19 @@ nest_view_state::nest_view_state(::game& ctx):
}
);
// Create suzanne
auto suzanne_eid = ctx.entity_registry->create();
auto suzanne_static_mesh = std::make_shared<scene::static_mesh>(ctx.resource_manager->load<render::model>("suzanne.mdl"));
ctx.entity_registry->emplace<scene_component>(suzanne_eid, std::move(suzanne_static_mesh), std::uint8_t{2});
ctx.entity_registry->patch<scene_component>
(
suzanne_eid,
[&](auto& component)
{
component.object->set_translation({-13.0f, -1.0f, -6.0f});
}
);
// Disable UI color clear
ctx.ui_clear_pass->set_cleared_buffers(false, true, false);

+ 2
- 2
src/game/states/nest-view-state.hpp View File

@ -79,8 +79,8 @@ private:
double third_person_camera_near_focal_plane_height{2.0f};
double third_person_camera_far_focal_plane_height{50.0f};
double third_person_camera_near_hfov{math::radians(45.0)};
double third_person_camera_far_hfov{math::radians(90.0)};
double third_person_camera_near_hfov{math::radians(90.0)};
double third_person_camera_far_hfov{math::radians(45.0)};
/// In focal plane heights per second.
double third_person_camera_speed{1.0f};

Loading…
Cancel
Save