From: Mikko Rasa Date: Sat, 8 May 2021 14:58:11 +0000 (+0300) Subject: Use persistent uniform blocks for Camera, Lighting and Clipping X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=a275d25eccad43716c5dcf91f8bc4af2a53c0445 Use persistent uniform blocks for Camera, Lighting and Clipping Now that the relevant calculations are done in world space, the values of these uniforms don't need to be calculated on a per-frame basis. --- diff --git a/source/core/clipping.cpp b/source/core/clipping.cpp index c286b7e5..18b706e7 100644 --- a/source/core/clipping.cpp +++ b/source/core/clipping.cpp @@ -20,7 +20,7 @@ unsigned Clipping::get_n_attach_points() void Clipping::attach(const ClipPlane &p) { - if(find(planes, &p)!=planes.end()) + if(find_member(planes, &p, &AttachedPlane::plane)!=planes.end()) return; if(planes.size()>=get_n_attach_points()) throw invalid_operation("Clipping::attach"); @@ -32,7 +32,7 @@ void Clipping::attach(const ClipPlane &p) void Clipping::detach(const ClipPlane &p) { - vector::iterator i = find(planes, &p); + vector::iterator i = find_member(planes, &p, &AttachedPlane::plane); if(i!=planes.end()) { planes.erase(i); @@ -45,14 +45,19 @@ void Clipping::detach(const ClipPlane &p) void Clipping::detach(unsigned i) { if(iupdate_shader_data(shdata, view_inverse, i); + if(planes[i].plane->get_generation()!=planes[i].generation) + { + planes[i].plane->update_shader_data(shdata, i); + planes[i].generation = planes[i].plane->get_generation(); + } + + return shdata; } void Clipping::bind() const diff --git a/source/core/clipping.h b/source/core/clipping.h index 319a8d98..d74763ab 100644 --- a/source/core/clipping.h +++ b/source/core/clipping.h @@ -4,18 +4,27 @@ #include #include #include "bindable.h" +#include "programdata.h" namespace Msp { namespace GL { class ClipPlane; class Matrix; -class ProgramData; class Clipping: public Bindable { private: - std::vector planes; + struct AttachedPlane + { + const ClipPlane *plane; + mutable unsigned generation; + + AttachedPlane(const ClipPlane *p): plane(p), generation(0) { } + }; + + std::vector planes; + mutable ProgramData shdata; public: static unsigned get_n_attach_points(); @@ -26,7 +35,7 @@ public: DEPRECATED void attach(unsigned, const ClipPlane &p) { attach(p); } DEPRECATED void detach(unsigned); - void update_shader_data(ProgramData &, const Matrix &) const; + const ProgramData &get_shader_data() const; void bind() const; diff --git a/source/core/clipplane.cpp b/source/core/clipplane.cpp index 4adf2bf5..b27464ca 100644 --- a/source/core/clipplane.cpp +++ b/source/core/clipplane.cpp @@ -9,20 +9,24 @@ namespace Msp { namespace GL { ClipPlane::ClipPlane(): - eq(0, 0, 0, 1) + eq(0, 0, 0, 1), + generation(0) { } ClipPlane::ClipPlane(const Vector4 &e): - eq(e) + eq(e), + generation(0) { } ClipPlane::ClipPlane(const Vector3 &p, const Vector3 &d): - eq(compose(d, -dot(p, d))) + eq(compose(d, -dot(p, d))), + generation(0) { } void ClipPlane::set_equation(const Vector4 &e) { eq = e; + ++generation; } void ClipPlane::set_plane(const Vector3 &p, const Vector3 &d) @@ -31,9 +35,9 @@ void ClipPlane::set_plane(const Vector3 &p, const Vector3 &d) set_equation(compose(nd, -dot(p, nd))); } -void ClipPlane::update_shader_data(ProgramData &shdata, const Matrix &view_inverse, unsigned i) const +void ClipPlane::update_shader_data(ProgramData &shdata, unsigned i) const { - shdata.uniform(format("clip_planes[%d].equation", i), eq*view_inverse); + shdata.uniform(format("clip_planes[%d].equation", i), eq); } } // namespace GL diff --git a/source/core/clipplane.h b/source/core/clipplane.h index 98c633b7..f9dca0de 100644 --- a/source/core/clipplane.h +++ b/source/core/clipplane.h @@ -13,6 +13,7 @@ class ClipPlane { private: Vector4 eq; + unsigned generation; public: ClipPlane(); @@ -21,7 +22,9 @@ public: void set_equation(const Vector4 &); void set_plane(const Vector3 &, const Vector3 &); - void update_shader_data(ProgramData &, const Matrix &, unsigned) const; + void update_shader_data(ProgramData &, unsigned) const; + + unsigned get_generation() const { return generation; } }; } // namespace GL diff --git a/source/materials/light.cpp b/source/materials/light.cpp index 2825b81e..3d3cba0a 100644 --- a/source/materials/light.cpp +++ b/source/materials/light.cpp @@ -16,7 +16,8 @@ Light::Light(): position(0, 0, 1, 0), spot_dir(0, 0, -1), spot_exp(0), - spot_cutoff(Geometry::Angle::straight()) + spot_cutoff(Geometry::Angle::straight()), + generation(0) { attenuation[0] = 1; attenuation[1] = 0; @@ -43,11 +44,13 @@ void Light::update_matrix() void Light::set_color(const Color &c) { color = c; + ++generation; } void Light::set_transmittance(const Color &t) { transmittance = t; + ++generation; } void Light::set_matrix(const Matrix &m) @@ -57,6 +60,7 @@ void Light::set_matrix(const Matrix &m) spot_dir = normalize(-matrix.column(2).slice<3>(0)); direction = (position.w ? spot_dir : normalize(-position.slice<3>(0))); update_matrix(); + ++generation; } void Light::set_position(const Vector4 &p) @@ -65,6 +69,7 @@ void Light::set_position(const Vector4 &p) if(!position.w) direction = normalize(-position.slice<3>(0)); update_matrix(); + ++generation; } void Light::set_spot_direction(const Vector3 &d) @@ -73,6 +78,7 @@ void Light::set_spot_direction(const Vector3 &d) if(position.w) direction = spot_dir; update_matrix(); + ++generation; } void Light::set_spot_exponent(float e) @@ -81,6 +87,7 @@ void Light::set_spot_exponent(float e) throw invalid_argument("Light::set_spot_exponent"); spot_exp = e; + ++generation; } void Light::set_spot_cutoff(const Geometry::Angle &c) @@ -89,11 +96,13 @@ void Light::set_spot_cutoff(const Geometry::Angle &c) throw invalid_argument("Light::set_spot_cutoff"); spot_cutoff = c; + ++generation; } void Light::disable_spot_cutoff() { set_spot_cutoff(Geometry::Angle::straight()); + ++generation; } void Light::set_attenuation(float c, float l, float q) @@ -101,13 +110,15 @@ void Light::set_attenuation(float c, float l, float q) attenuation[0] = c; attenuation[1] = l; attenuation[2] = q; + ++generation; } -void Light::update_shader_data(ProgramData &shdata, const Matrix &view_matrix, unsigned i) const +void Light::update_shader_data(ProgramData &shdata, unsigned i) const { string base = format("light_sources[%d]", i); - shdata.uniform(base+".position", view_matrix*position); + shdata.uniform(base+".position", position); shdata.uniform(base+".color", color.r*transmittance.r, color.g*transmittance.g, color.b*transmittance.b); + shdata.uniform(base+".enabled", 1); } diff --git a/source/materials/light.h b/source/materials/light.h index d4b66077..4532d0d4 100644 --- a/source/materials/light.h +++ b/source/materials/light.h @@ -51,6 +51,7 @@ private: float spot_exp; Geometry::Angle spot_cutoff; float attenuation[3]; + unsigned generation; public: Light(); @@ -107,9 +108,11 @@ public: void set_attenuation(float, float, float); const float *get_attenuation() const { return attenuation; } - /** Updates a ProgramData object with the uniforms for the Light. A view - matrix and light source index must be passed in. */ - void update_shader_data(ProgramData &, const Matrix &, unsigned) const; + unsigned get_generation() const { return generation; } + + /** Updates a ProgramData object with the uniforms for the Light. A light + source index must be passed in. Primarily used by Lighting. */ + void update_shader_data(ProgramData &, unsigned) const; }; } // namespace GL diff --git a/source/materials/lighting.cpp b/source/materials/lighting.cpp index 70b819ce..b19ebab0 100644 --- a/source/materials/lighting.cpp +++ b/source/materials/lighting.cpp @@ -13,12 +13,13 @@ namespace Msp { namespace GL { Lighting::Lighting(): - ambient(0.2), zenith_direction(0, 0, 1), - horizon_angle(Geometry::Angle::zero()), - fog_color(0.0f, 0.0f, 0.0f, 0.0f), - fog_density(0.0f) -{ } + horizon_angle(Geometry::Angle::zero()) +{ + set_ambient(0.2f); + set_fog_color(Color(0.0f, 0.0f, 0.0f, 0.0f)); + set_fog_density(0.0f); +} Lighting::~Lighting() { @@ -29,26 +30,31 @@ Lighting::~Lighting() void Lighting::set_ambient(const Color &a) { ambient = a; + shdata.uniform("ambient_color", ambient); } void Lighting::set_sky_color(const Color &s) { sky_color = s; + shdata.uniform("sky_color", sky_color); } void Lighting::set_zenith_direction(const Vector3 &d) { zenith_direction = d; + shdata.uniform("world_zenith_dir", zenith_direction); } void Lighting::set_horizon_angle(const Geometry::Angle &a) { horizon_angle = a; + shdata.uniform("horizon_limit", horizon_angle.radians()); } void Lighting::set_fog_color(const Color &c) { fog_color = c; + shdata.uniform("fog_color", fog_color); } void Lighting::set_fog_density(float d) @@ -57,6 +63,7 @@ void Lighting::set_fog_density(float d) throw invalid_argument("Lighting::set_fog_density"); fog_density = d; + shdata.uniform("fog_density", fog_density); } void Lighting::set_fog_half_distance(float d) @@ -66,13 +73,13 @@ void Lighting::set_fog_half_distance(float d) void Lighting::attach(const Light &l) { - if(find(lights, &l)==lights.end()) + if(find_member(lights, &l, &AttachedLight::light)==lights.end()) lights.push_back(&l); } void Lighting::detach(const Light &l) { - vector::iterator i = find(lights, &l); + vector::iterator i = find_member(lights, &l, &AttachedLight::light); if(i!=lights.end()) lights.erase(i); } @@ -82,26 +89,47 @@ void Lighting::detach(unsigned i) if(i>=lights.size()) return; - detach(*lights[i]); + detach(*lights[i].light); } const Light *Lighting::get_attached_light(unsigned i) const { - return iupdate_shader_data(shdata, view_matrix, i); + if(lights[i].light) + lights[i].light->update_shader_data(sd, i); +} + +const ProgramData &Lighting::get_shader_data() const +{ + for(unsigned i=0; iget_generation()!=lights[i].generation) + { + lights[i].light->update_shader_data(shdata, i); + lights[i].generation = lights[i].light->get_generation(); + } + + return shdata; +} + +void Lighting::set_debug_name(const string &name) +{ +#ifdef DEBUG + shdata.set_debug_name(name+" [UBO]"); +#else + (void)name; +#endif } @@ -137,7 +165,7 @@ void Lighting::Loader::init_actions() void Lighting::Loader::ambient(float r, float g, float b) { - obj.ambient = Color(r, g, b); + obj.set_ambient(Color(r, g, b)); } void Lighting::Loader::fog_color(float r, float g, float b) diff --git a/source/materials/lighting.h b/source/materials/lighting.h index 2a8756c3..833e7d2b 100644 --- a/source/materials/lighting.h +++ b/source/materials/lighting.h @@ -44,14 +44,23 @@ public: }; private: + struct AttachedLight + { + const Light *light; + mutable unsigned generation; + + AttachedLight(const Light *l): light(l), generation(0) { } + }; + Color ambient; Color sky_color; Vector3 zenith_direction; Geometry::Angle horizon_angle; Color fog_color; float fog_density; - std::vector lights; + std::vector lights; std::vector owned_data; + mutable ProgramData shdata; public: Lighting(); @@ -97,11 +106,13 @@ public: is returned. */ DEPRECATED const Light *get_attached_light(unsigned) const; - const std::vector &get_attached_lights() const { return lights; } - /** Updates a ProgramData object with the uniforms for the Lighting, including all attached light sources. A view matrix must be passed in. */ - void update_shader_data(ProgramData &, const Matrix &) const; + DEPRECATED void update_shader_data(ProgramData &, const Matrix &) const; + + const ProgramData &get_shader_data() const; + + void set_debug_name(const std::string &); }; } // namespace GL diff --git a/source/render/camera.cpp b/source/render/camera.cpp index 3bba0eaf..9b8b0c77 100644 --- a/source/render/camera.cpp +++ b/source/render/camera.cpp @@ -2,6 +2,8 @@ #include "camera.h" #include "matrix.h" +using namespace std; + namespace Msp { namespace GL { @@ -129,6 +131,8 @@ void Camera::update_projection_matrix() else proj_matrix = Matrix::ortho(left, right, bottom, top, clip_near, clip_far); proj_matrix = Matrix::rotation(rotate, Vector3(0, 0, 1))*proj_matrix; + + shdata.uniform("clip_eye_matrix", proj_matrix); } void Camera::update_object_matrix() @@ -141,6 +145,17 @@ void Camera::update_object_matrix() columns[3] = compose(position, 1.0f); matrix = Matrix::from_columns(columns); view_matrix = invert(matrix); + + shdata.uniform("eye_world_matrix", view_matrix); +} + +void Camera::set_debug_name(const string &name) +{ +#ifdef DEBUG + shdata.set_debug_name(name+" [UBO]"); +#else + (void)name; +#endif } diff --git a/source/render/camera.h b/source/render/camera.h index b10ccb93..844ec0d8 100644 --- a/source/render/camera.h +++ b/source/render/camera.h @@ -3,6 +3,7 @@ #include #include "placeable.h" +#include "programdata.h" namespace Msp { namespace GL { @@ -41,6 +42,7 @@ private: Vector3 up_dir; Matrix view_matrix; Matrix proj_matrix; + ProgramData shdata; public: Camera(); @@ -89,9 +91,14 @@ public: Vector4 unproject(const Vector4 &) const; Vector3 unproject(const Vector3 &) const; + const ProgramData &get_shader_data() const { return shdata; } + private: void update_projection_matrix(); void update_object_matrix(); + +public: + void set_debug_name(const std::string &); }; } // namespace GL diff --git a/source/render/renderer.cpp b/source/render/renderer.cpp index 5d0bf6b8..2da4bd78 100644 --- a/source/render/renderer.cpp +++ b/source/render/renderer.cpp @@ -43,9 +43,6 @@ void Renderer::init() state_stack.push_back(State()); shdata_stack.reserve(32); state = &state_stack.back(); - - standard_shdata.uniform("clip_eye_matrix", Matrix()); - standard_shdata.uniform("eye_world_matrix", Matrix()); } Renderer::~Renderer() @@ -56,9 +53,7 @@ Renderer::~Renderer() void Renderer::set_camera(const Camera &c) { state->camera = &c; - standard_shdata.uniform("clip_eye_matrix", state->camera->get_projection_matrix()); - standard_shdata.uniform("eye_world_matrix", state->camera->get_view_matrix()); - changed |= STANDARD_SHDATA; + changed |= CAMERA_SHDATA; set_matrix(Matrix()); } @@ -159,21 +154,13 @@ void Renderer::set_material(const Material *m) void Renderer::set_lighting(const Lighting *l) { state->lighting = l; - if(l) - { - l->update_shader_data(standard_shdata, Matrix()); - changed |= STANDARD_SHDATA; - } + changed |= LIGHTING_SHDATA; } void Renderer::set_clipping(const Clipping *c) { state->clipping = c; - if(c) - { - c->update_shader_data(standard_shdata, Matrix()); - changed |= STANDARD_SHDATA; - } + changed |= CLIPPING_SHDATA; } void Renderer::set_shader_program(const Program *p, const ProgramData *d) @@ -246,35 +233,11 @@ void Renderer::pop_state() changed |= MATRIX; bool camera_changed = (state->camera!=old_camera); if(camera_changed) - { - if(state->camera) - { - standard_shdata.uniform("clip_eye_matrix", state->camera->get_projection_matrix()); - standard_shdata.uniform("eye_world_matrix", state->camera->get_view_matrix()); - } - else - { - standard_shdata.uniform("clip_eye_matrix", Matrix()); - standard_shdata.uniform("eye_world_matrix", Matrix()); - } - changed |= STANDARD_SHDATA; - } + changed |= CAMERA_SHDATA; if(state->lighting!=old_lighting) - { - if(state->lighting) - { - state->lighting->update_shader_data(standard_shdata, Matrix()); - changed |= STANDARD_SHDATA; - } - } + changed |= LIGHTING_SHDATA; if(state->clipping!=old_clipping) - { - if(state->clipping) - { - state->clipping->update_shader_data(standard_shdata, Matrix()); - changed |= STANDARD_SHDATA; - } - } + changed |= CLIPPING_SHDATA; } void Renderer::end() @@ -285,8 +248,6 @@ void Renderer::end() *state = State(); if(default_camera) set_camera(*default_camera); - else - standard_shdata.uniform("clip_eye_matrix", Matrix()); shdata_stack.clear(); excluded.clear(); @@ -374,12 +335,30 @@ void Renderer::apply_state() changed = (changed&~MATRIX)|STANDARD_SHDATA; } + if(state->camera && ((changed&CAMERA_SHDATA) || shprog_changed)) + { + state->camera->get_shader_data().apply(); + changed &= ~CAMERA_SHDATA; + } + if(state->material && ((changed&MATERIAL_SHDATA) || shprog_changed)) { state->material->get_shader_data().apply(); changed &= ~MATERIAL_SHDATA; } + if(state->lighting && ((changed&LIGHTING_SHDATA) || shprog_changed)) + { + state->lighting->get_shader_data().apply(); + changed &= ~LIGHTING_SHDATA; + } + + if(state->clipping && ((changed&CLIPPING_SHDATA) || shprog_changed)) + { + state->clipping->get_shader_data().apply(); + changed &= ~CLIPPING_SHDATA; + } + if((changed&STANDARD_SHDATA) || shprog_changed) { standard_shdata.apply(); diff --git a/source/render/renderer.h b/source/render/renderer.h index 27087197..197cf95a 100644 --- a/source/render/renderer.h +++ b/source/render/renderer.h @@ -107,7 +107,10 @@ private: MATRIX = 2, SHADER_DATA = 16, MATERIAL_SHDATA = 32, - STANDARD_SHDATA = 64 + STANDARD_SHDATA = 64, + CAMERA_SHDATA = 128, + LIGHTING_SHDATA = 256, + CLIPPING_SHDATA = 512 }; const Camera *default_camera; diff --git a/source/resources/resources.cpp b/source/resources/resources.cpp index 79c95932..682acde2 100644 --- a/source/resources/resources.cpp +++ b/source/resources/resources.cpp @@ -44,11 +44,13 @@ Resources::Resources(bool set_as_global): { add_type().suffix(".anim").keyword("animation"); add_type().suffix(".arma").keyword("armature"); - add_type().keyword("camera"); + add_type().keyword("camera") + .notify(&Resources::set_debug_name); add_type().keyword("font"); add_type().suffix(".kframe").keyword("keyframe"); add_type().keyword("light"); - add_type().suffix(".lightn").keyword("lighting"); + add_type().suffix(".lightn").keyword("lighting") + .notify(&Resources::set_debug_name); add_type().suffix(".mat") .creator(&Resources::create_material).notify(&Resources::set_debug_name); add_type().keyword("mesh")