From d2d9c33c7911f14395ea3b60d3c0ea9f9dcb1d01 Mon Sep 17 00:00:00 2001 From: heinezen Date: Sat, 20 Apr 2024 21:08:25 +0200 Subject: [PATCH 1/9] renderer: Compute camera scaling variables for uniform buffer, --- assets/shaders/terrain.vert.glsl | 12 ++++++++-- assets/shaders/world2d.vert.glsl | 19 ++++++++++----- libopenage/renderer/camera/camera.cpp | 23 +++++++++++-------- libopenage/renderer/camera/camera.h | 9 ++++++++ libopenage/renderer/stages/camera/manager.cpp | 20 +++++++++++++--- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/assets/shaders/terrain.vert.glsl b/assets/shaders/terrain.vert.glsl index aef9b45867..614f6f382b 100644 --- a/assets/shaders/terrain.vert.glsl +++ b/assets/shaders/terrain.vert.glsl @@ -7,9 +7,17 @@ out vec2 tex_pos; uniform mat4 model; +// camera parameters for transforming the object position +// and scaling the subtex to the correct size layout (std140) uniform camera { - mat4 view; - mat4 proj; + // view matrix (world to view space) + mat4 view; + // projection matrix (view to clip space) + mat4 proj; + // inverse zoom factor (1.0 / zoom) + float inv_zoom; + // inverse viewport size (1.0 / viewport size) + vec2 inv_viewport_size; }; void main() { diff --git a/assets/shaders/world2d.vert.glsl b/assets/shaders/world2d.vert.glsl index 76cd6db34d..edb557e4a9 100644 --- a/assets/shaders/world2d.vert.glsl +++ b/assets/shaders/world2d.vert.glsl @@ -5,10 +5,17 @@ layout(location=1) in vec2 uv; out vec2 vert_uv; -// transformation for object (not vertex!) position to clip space +// camera parameters for transforming the object position +// and scaling the subtex to the correct size layout (std140) uniform camera { - mat4 view; - mat4 proj; + // view matrix (world to view space) + mat4 view; + // projection matrix (view to clip space) + mat4 proj; + // inverse zoom factor (1.0 / zoom) + float inv_zoom; + // inverse viewport size (1.0 / viewport size) + vec2 inv_viewport_size; }; // can be used to move the object position in world space _before_ @@ -51,9 +58,9 @@ void main() { // create a move matrix for positioning the vertices // uses the scale and the transformed object position in clip space - mat4 move = mat4(scale.x, 0.0, 0.0, 0.0, - 0.0, scale.y, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, + mat4 move = mat4(scale.x, 0.0, 0.0, 0.0, + 0.0, scale.y, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, obj_clip_pos.x, obj_clip_pos.y, obj_clip_pos.z, 1.0); // calculate the final vertex position diff --git a/libopenage/renderer/camera/camera.cpp b/libopenage/renderer/camera/camera.cpp index 604ddf440f..884aceca1b 100644 --- a/libopenage/renderer/camera/camera.cpp +++ b/libopenage/renderer/camera/camera.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2023 the openage authors. See copying.md for legal info. +// Copyright 2022-2024 the openage authors. See copying.md for legal info. #include "camera.h" @@ -28,10 +28,7 @@ Camera::Camera(const std::shared_ptr &renderer, proj{Eigen::Matrix4f::Identity()} { this->look_at_scene(Eigen::Vector3f(0.0f, 0.0f, 0.0f)); - resources::UBOInput view_input{"view", resources::ubo_input_t::M4F32}; - resources::UBOInput proj_input{"proj", resources::ubo_input_t::M4F32}; - auto ubo_info = resources::UniformBufferInfo{resources::ubo_layout_t::STD140, {view_input, proj_input}}; - this->uniform_buffer = renderer->add_uniform_buffer(ubo_info); + this->init_uniform_buffer(renderer); log::log(INFO << "Created new camera at position " << "(" << this->scene_pos[0] @@ -55,10 +52,7 @@ Camera::Camera(const std::shared_ptr &renderer, viewport_changed{true}, view{Eigen::Matrix4f::Identity()}, proj{Eigen::Matrix4f::Identity()} { - resources::UBOInput view_input{"view", resources::ubo_input_t::M4F32}; - resources::UBOInput proj_input{"proj", resources::ubo_input_t::M4F32}; - auto ubo_info = resources::UniformBufferInfo{resources::ubo_layout_t::STD140, {view_input, proj_input}}; - this->uniform_buffer = renderer->add_uniform_buffer(ubo_info); + this->init_uniform_buffer(renderer); log::log(INFO << "Created new camera at position " << "(" << this->scene_pos[0] @@ -269,4 +263,15 @@ const std::shared_ptr &Camera::get_uniform_buffer() con return this->uniform_buffer; } +void Camera::init_uniform_buffer(const std::shared_ptr &renderer) { + resources::UBOInput view_input{"view", resources::ubo_input_t::M4F32}; + resources::UBOInput proj_input{"proj", resources::ubo_input_t::M4F32}; + resources::UBOInput inv_zoom_input{"inv_zoom", resources::ubo_input_t::F32}; + resources::UBOInput inv_viewport_size{"inv_viewport_size", resources::ubo_input_t::V2F32}; + auto ubo_info = resources::UniformBufferInfo{ + resources::ubo_layout_t::STD140, + {view_input, proj_input, inv_zoom_input, inv_viewport_size}}; + this->uniform_buffer = renderer->add_uniform_buffer(ubo_info); +} + } // namespace openage::renderer::camera diff --git a/libopenage/renderer/camera/camera.h b/libopenage/renderer/camera/camera.h index 9cdd559e6f..c8c5c23076 100644 --- a/libopenage/renderer/camera/camera.h +++ b/libopenage/renderer/camera/camera.h @@ -43,6 +43,7 @@ class Camera { * The camera uses default values. Its centered on the origin of the scene (0.0f, 0.0f, 0.0f) * and has a zoom level of 1.0f. * + * @param renderer openage renderer instance. * @param viewport_size Initial viewport size of the camera (width x height). */ Camera(const std::shared_ptr &renderer, @@ -51,6 +52,7 @@ class Camera { /** * Create a new camera for the renderer. * + * @param renderer openage renderer instance. * @param viewport_size Viewport size of the camera (width x height). * @param scene_pos Position of the camera in the scene. * @param zoom Zoom level of the camera (defaults to 1.0f). @@ -187,6 +189,13 @@ class Camera { const std::shared_ptr &get_uniform_buffer() const; private: + /** + * Create the uniform buffer for the camera. + * + * @param renderer openage renderer instance. + */ + void init_uniform_buffer(const std::shared_ptr &renderer); + /** * Position in the 3D scene. */ diff --git a/libopenage/renderer/stages/camera/manager.cpp b/libopenage/renderer/stages/camera/manager.cpp index 580f7db597..39eddd2b52 100644 --- a/libopenage/renderer/stages/camera/manager.cpp +++ b/libopenage/renderer/stages/camera/manager.cpp @@ -1,4 +1,4 @@ -// Copyright 2023-2023 the openage authors. See copying.md for legal info. +// Copyright 2023-2024 the openage authors. See copying.md for legal info. #include "manager.h" @@ -97,11 +97,25 @@ void CameraManager::update_motion() { } void CameraManager::update_uniforms() { + // transformation matrices this->uniforms->update( "view", - camera->get_view_matrix(), + this->camera->get_view_matrix(), "proj", - camera->get_projection_matrix()); + this->camera->get_projection_matrix()); + + // zoom scaling + this->uniforms->update( + "inv_zoom", + 1.0f / this->camera->get_zoom()); + + auto viewport_size = this->camera->get_viewport_size(); + Eigen::Vector2f viewport_size_vec{ + 1.0f / static_cast(viewport_size[0]), + 1.0f / static_cast(viewport_size[1])}; + this->uniforms->update("inv_viewport_size", viewport_size_vec); + + // update the uniform buffer this->camera->get_uniform_buffer()->update_uniforms(this->uniforms); } From f8d0f08a2c6d3a10b1ff106c658066cfe7db7094 Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 00:05:03 +0200 Subject: [PATCH 2/9] renderer: Calculate zoom scale from uniform buffer values. --- assets/shaders/world2d.vert.glsl | 28 +++++++++++++++---- libopenage/renderer/stages/world/object.cpp | 19 +++++++++++-- .../renderer/stages/world/render_stage.cpp | 4 +-- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/assets/shaders/world2d.vert.glsl b/assets/shaders/world2d.vert.glsl index edb557e4a9..3c763d4ae3 100644 --- a/assets/shaders/world2d.vert.glsl +++ b/assets/shaders/world2d.vert.glsl @@ -36,21 +36,37 @@ uniform bool flip_y; // offset from the subtex anchor // moves the subtex relative to the subtex center -uniform vec2 anchor_offset; +// uniform vec2 anchor_offset; // scales the vertex positions so that they // match the subtex dimensions -uniform vec2 scale; +// uniform vec2 scale; + +uniform float scalefactor; +uniform float zoom; +uniform vec2 screen_size; +uniform vec2 subtex_size; +uniform vec2 anchor; void main() { // translate the position of the object from world space to clip space // this is the position where we want to draw the subtex in 2D vec4 obj_clip_pos = proj * view * model * vec4(obj_world_position, 1.0); + float obj_scale = scalefactor * inv_zoom; + vec2 obj_scale_vec = vec2( + obj_scale * (subtex_size.x / screen_size.x), + obj_scale * (subtex_size.y / screen_size.y) + ); + vec2 obj_anchor_vec = vec2( + obj_scale * (anchor.x / screen_size.x), + obj_scale * (anchor.y / screen_size.y) + ); + // if the subtex is flipped, we also need to flip the anchor offset // essentially, we invert the coordinates for the flipped axis - float anchor_x = float(flip_x) * -1.0 * anchor_offset.x + float(!flip_x) * anchor_offset.x; - float anchor_y = float(flip_y) * -1.0 * anchor_offset.y + float(!flip_y) * anchor_offset.y; + float anchor_x = float(flip_x) * -1.0 * obj_anchor_vec.x + float(!flip_x) * obj_anchor_vec.x; + float anchor_y = float(flip_y) * -1.0 * obj_anchor_vec.y + float(!flip_y) * obj_anchor_vec.y; // offset the clip position by the offset of the subtex anchor // imagine this as pinning the subtex to the object position at the subtex anchor point @@ -58,8 +74,8 @@ void main() { // create a move matrix for positioning the vertices // uses the scale and the transformed object position in clip space - mat4 move = mat4(scale.x, 0.0, 0.0, 0.0, - 0.0, scale.y, 0.0, 0.0, + mat4 move = mat4(obj_scale_vec.x, 0.0, 0.0, 0.0, + 0.0, obj_scale_vec.y, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, obj_clip_pos.x, obj_clip_pos.y, obj_clip_pos.z, 1.0); diff --git a/libopenage/renderer/stages/world/object.cpp b/libopenage/renderer/stages/world/object.cpp index 23915d420f..7709d2223a 100644 --- a/libopenage/renderer/stages/world/object.cpp +++ b/libopenage/renderer/stages/world/object.cpp @@ -148,14 +148,29 @@ void WorldObject::update_uniforms(const time::time_t &time) { auto scale_vec = Eigen::Vector2f{ scale * (static_cast(subtex_size[0]) / screen_size[0]), scale * (static_cast(subtex_size[1]) / screen_size[1])}; - this->uniforms->update(this->scale, scale_vec); + // this->uniforms->update(this->scale, scale_vec); // Move subtexture in scene so that its anchor point is at the object's position auto anchor = tex_info->get_subtex_info(subtex_idx).get_anchor_params(); auto anchor_offset = Eigen::Vector2f{ scale * (static_cast(anchor[0]) / screen_size[0]), scale * (static_cast(anchor[1]) / screen_size[1])}; - this->uniforms->update(this->anchor_offset, anchor_offset); + // this->uniforms->update(this->anchor_offset, anchor_offset); + + this->uniforms->update("scalefactor", animation_info->get_scalefactor()); + // this->uniforms->update("zoom", this->camera->get_zoom()); + Eigen::Vector2f screen_size_vec{ + static_cast(screen_size[0]), + static_cast(screen_size[1])}; + this->uniforms->update("screen_size", screen_size_vec); + Eigen::Vector2f subtex_size_vec{ + static_cast(subtex_size[0]), + static_cast(subtex_size[1])}; + this->uniforms->update("subtex_size", subtex_size_vec); + Eigen::Vector2f anchor_vec{ + static_cast(anchor[0]), + static_cast(anchor[1])}; + this->uniforms->update("anchor", anchor_vec); } uint32_t WorldObject::get_id() { diff --git a/libopenage/renderer/stages/world/render_stage.cpp b/libopenage/renderer/stages/world/render_stage.cpp index 85e5da7048..e97b52cabf 100644 --- a/libopenage/renderer/stages/world/render_stage.cpp +++ b/libopenage/renderer/stages/world/render_stage.cpp @@ -135,8 +135,8 @@ void WorldRenderStage::init_uniform_ids() { WorldObject::flip_y = this->display_shader->get_uniform_id("flip_y"); WorldObject::tex = this->display_shader->get_uniform_id("tex"); WorldObject::tile_params = this->display_shader->get_uniform_id("tile_params"); - WorldObject::scale = this->display_shader->get_uniform_id("scale"); - WorldObject::anchor_offset = this->display_shader->get_uniform_id("anchor_offset"); + // WorldObject::scale = this->display_shader->get_uniform_id("scale"); + // WorldObject::anchor_offset = this->display_shader->get_uniform_id("anchor_offset"); } } // namespace openage::renderer::world From 81124bea3935d8713c99dd98b68400e83bdf6068 Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 15:17:38 +0200 Subject: [PATCH 3/9] renderer: Check if uniform buffer conforms to uniform block definition. --- libopenage/renderer/opengl/shader_program.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libopenage/renderer/opengl/shader_program.cpp b/libopenage/renderer/opengl/shader_program.cpp index 3ccd49ce80..31b0d17778 100644 --- a/libopenage/renderer/opengl/shader_program.cpp +++ b/libopenage/renderer/opengl/shader_program.cpp @@ -1,4 +1,4 @@ -// Copyright 2013-2023 the openage authors. See copying.md for legal info. +// Copyright 2013-2024 the openage authors. See copying.md for legal info. #include "shader_program.h" @@ -445,7 +445,12 @@ void GlShaderProgram::bind_uniform_buffer(const char *block_name, std::shared_pt auto gl_buffer = std::dynamic_pointer_cast(buffer); auto &block = this->uniform_blocks[block_name]; - // TODO: Check if the uniform buffer matches the block definition + // Check if the uniform buffer matches the block definition + for (auto const &pair : block.uniforms) { + auto const &unif = pair.second; + ENSURE(gl_buffer->has_uniform(pair.first.c_str()), + "Uniform buffer does not contain uniform '" << pair.first << "' required by block " << block_name); + } block.binding_point = gl_buffer->get_binding_point(); glUniformBlockBinding(*this->handle, block.index, block.binding_point); From 24da277e08bed71bdf99acecf6557c59278c43dc Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 15:19:48 +0200 Subject: [PATCH 4/9] renderer: Fix alignment of uniform buffer inputs. --- libopenage/renderer/opengl/renderer.cpp | 16 +++++++++++----- libopenage/renderer/resources/buffer_info.cpp | 10 ++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libopenage/renderer/opengl/renderer.cpp b/libopenage/renderer/opengl/renderer.cpp index a06cc16edf..d26ba7b96c 100644 --- a/libopenage/renderer/opengl/renderer.cpp +++ b/libopenage/renderer/opengl/renderer.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2023 the openage authors. See copying.md for legal info. +// Copyright 2017-2024 the openage authors. See copying.md for legal info. #include "renderer.h" @@ -33,10 +33,10 @@ GlRenderer::GlRenderer(const std::shared_ptr &ctx, // global GL alpha blending settings // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFuncSeparate( - GL_SRC_ALPHA, // source (overlaying) RGB factor + GL_SRC_ALPHA, // source (overlaying) RGB factor GL_ONE_MINUS_SRC_ALPHA, // destination (underlying) RGB factor - GL_ONE, // source (overlaying) alpha factor - GL_ONE_MINUS_SRC_ALPHA // destination (underlying) alpha factor + GL_ONE, // source (overlaying) alpha factor + GL_ONE_MINUS_SRC_ALPHA // destination (underlying) alpha factor ); // global GL depth testing settings @@ -90,6 +90,11 @@ std::shared_ptr GlRenderer::add_uniform_buffer(resources::Uniform size_t offset = 0; for (auto const &input : inputs) { auto type = GL_UBO_INPUT_TYPE.get(input.type); + auto size = resources::UniformBufferInfo::get_size(input, info.get_layout()); + + // align offset to the size of the type + offset += offset % size; + uniforms.emplace( std::make_pair(input.name, GlInBlockUniform{type, @@ -97,7 +102,8 @@ std::shared_ptr GlRenderer::add_uniform_buffer(resources::Uniform resources::UniformBufferInfo::get_size(input, info.get_layout()), resources::UniformBufferInfo::get_stride_size(input.type, info.get_layout()), input.count})); - offset += resources::UniformBufferInfo::get_size(input, info.get_layout()); + + offset += size; } return std::make_shared(this->gl_context, diff --git a/libopenage/renderer/resources/buffer_info.cpp b/libopenage/renderer/resources/buffer_info.cpp index c3215d63ba..de9a1751c8 100644 --- a/libopenage/renderer/resources/buffer_info.cpp +++ b/libopenage/renderer/resources/buffer_info.cpp @@ -1,4 +1,4 @@ -// Copyright 2023-2023 the openage authors. See copying.md for legal info. +// Copyright 2023-2024 the openage authors. See copying.md for legal info. #include "buffer_info.h" @@ -27,7 +27,13 @@ const std::vector &UniformBufferInfo::get_inputs() const { size_t UniformBufferInfo::get_size() const { size_t size = 0; for (const auto &input : this->inputs) { - size += this->get_size(input, this->layout); + // size of the input type + size_t input_size = this->get_size(input, this->layout); + + // inputs must additionally be aligned to a multiple of their size + size_t align_size = size % input_size; + + size += input_size + align_size; } return size; } From 67b0fa4b60f37c340f9cb13d1a4594985e769daa Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 15:20:36 +0200 Subject: [PATCH 5/9] renderer: Calculate subtex/anchor scale from uniform buffer values. --- assets/shaders/world2d.vert.glsl | 8 ++++---- libopenage/renderer/stages/world/object.cpp | 4 ++-- libopenage/renderer/stages/world/render_stage.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/shaders/world2d.vert.glsl b/assets/shaders/world2d.vert.glsl index 3c763d4ae3..e3a8e4a773 100644 --- a/assets/shaders/world2d.vert.glsl +++ b/assets/shaders/world2d.vert.glsl @@ -55,12 +55,12 @@ void main() { float obj_scale = scalefactor * inv_zoom; vec2 obj_scale_vec = vec2( - obj_scale * (subtex_size.x / screen_size.x), - obj_scale * (subtex_size.y / screen_size.y) + obj_scale * (subtex_size.x * inv_viewport_size.x), + obj_scale * (subtex_size.y * inv_viewport_size.y) ); vec2 obj_anchor_vec = vec2( - obj_scale * (anchor.x / screen_size.x), - obj_scale * (anchor.y / screen_size.y) + obj_scale * (anchor.x * inv_viewport_size.x), + obj_scale * (anchor.y * inv_viewport_size.y) ); // if the subtex is flipped, we also need to flip the anchor offset diff --git a/libopenage/renderer/stages/world/object.cpp b/libopenage/renderer/stages/world/object.cpp index 7709d2223a..93f7c7a8bb 100644 --- a/libopenage/renderer/stages/world/object.cpp +++ b/libopenage/renderer/stages/world/object.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2023 the openage authors. See copying.md for legal info. +// Copyright 2022-2024 the openage authors. See copying.md for legal info. #include "object.h" @@ -162,7 +162,7 @@ void WorldObject::update_uniforms(const time::time_t &time) { Eigen::Vector2f screen_size_vec{ static_cast(screen_size[0]), static_cast(screen_size[1])}; - this->uniforms->update("screen_size", screen_size_vec); + // this->uniforms->update("screen_size", screen_size_vec); Eigen::Vector2f subtex_size_vec{ static_cast(subtex_size[0]), static_cast(subtex_size[1])}; diff --git a/libopenage/renderer/stages/world/render_stage.cpp b/libopenage/renderer/stages/world/render_stage.cpp index e97b52cabf..b107f8d863 100644 --- a/libopenage/renderer/stages/world/render_stage.cpp +++ b/libopenage/renderer/stages/world/render_stage.cpp @@ -1,4 +1,4 @@ -// Copyright 2022-2023 the openage authors. See copying.md for legal info. +// Copyright 2022-2024 the openage authors. See copying.md for legal info. #include "render_stage.h" From 154a2eef7d7cead774160dea258c3cd72f44c50f Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 15:30:18 +0200 Subject: [PATCH 6/9] renderer: Use uniform IDs to set new uniforms in world stage. --- assets/shaders/world2d.vert.glsl | 14 +++++++------- libopenage/renderer/stages/world/object.cpp | 6 +++--- libopenage/renderer/stages/world/object.h | 3 +++ libopenage/renderer/stages/world/render_stage.cpp | 3 +++ 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/assets/shaders/world2d.vert.glsl b/assets/shaders/world2d.vert.glsl index e3a8e4a773..86a6565656 100644 --- a/assets/shaders/world2d.vert.glsl +++ b/assets/shaders/world2d.vert.glsl @@ -42,25 +42,25 @@ uniform bool flip_y; // match the subtex dimensions // uniform vec2 scale; -uniform float scalefactor; +uniform float scale; uniform float zoom; uniform vec2 screen_size; uniform vec2 subtex_size; -uniform vec2 anchor; +uniform vec2 anchor_offset; void main() { // translate the position of the object from world space to clip space // this is the position where we want to draw the subtex in 2D vec4 obj_clip_pos = proj * view * model * vec4(obj_world_position, 1.0); - float obj_scale = scalefactor * inv_zoom; + float obj_scale = scale * inv_zoom; vec2 obj_scale_vec = vec2( - obj_scale * (subtex_size.x * inv_viewport_size.x), - obj_scale * (subtex_size.y * inv_viewport_size.y) + obj_scale * subtex_size.x * inv_viewport_size.x, + obj_scale * subtex_size.y * inv_viewport_size.y ); vec2 obj_anchor_vec = vec2( - obj_scale * (anchor.x * inv_viewport_size.x), - obj_scale * (anchor.y * inv_viewport_size.y) + obj_scale * anchor_offset.x * inv_viewport_size.x, + obj_scale * anchor_offset.y * inv_viewport_size.y ); // if the subtex is flipped, we also need to flip the anchor offset diff --git a/libopenage/renderer/stages/world/object.cpp b/libopenage/renderer/stages/world/object.cpp index 93f7c7a8bb..e26aaab9e7 100644 --- a/libopenage/renderer/stages/world/object.cpp +++ b/libopenage/renderer/stages/world/object.cpp @@ -157,7 +157,7 @@ void WorldObject::update_uniforms(const time::time_t &time) { scale * (static_cast(anchor[1]) / screen_size[1])}; // this->uniforms->update(this->anchor_offset, anchor_offset); - this->uniforms->update("scalefactor", animation_info->get_scalefactor()); + this->uniforms->update(this->scale, animation_info->get_scalefactor()); // this->uniforms->update("zoom", this->camera->get_zoom()); Eigen::Vector2f screen_size_vec{ static_cast(screen_size[0]), @@ -166,11 +166,11 @@ void WorldObject::update_uniforms(const time::time_t &time) { Eigen::Vector2f subtex_size_vec{ static_cast(subtex_size[0]), static_cast(subtex_size[1])}; - this->uniforms->update("subtex_size", subtex_size_vec); + this->uniforms->update(this->subtex_size, subtex_size_vec); Eigen::Vector2f anchor_vec{ static_cast(anchor[0]), static_cast(anchor[1])}; - this->uniforms->update("anchor", anchor_vec); + this->uniforms->update(this->anchor_offset, anchor_vec); } uint32_t WorldObject::get_id() { diff --git a/libopenage/renderer/stages/world/object.h b/libopenage/renderer/stages/world/object.h index e2fc865dd6..eb075dd4c3 100644 --- a/libopenage/renderer/stages/world/object.h +++ b/libopenage/renderer/stages/world/object.h @@ -131,7 +131,10 @@ class WorldObject { inline static uniform_id_t flip_y; inline static uniform_id_t tex; inline static uniform_id_t tile_params; + // inline static uniform_id_t scale; + // inline static uniform_id_t anchor_offset; inline static uniform_id_t scale; + inline static uniform_id_t subtex_size; inline static uniform_id_t anchor_offset; private: diff --git a/libopenage/renderer/stages/world/render_stage.cpp b/libopenage/renderer/stages/world/render_stage.cpp index b107f8d863..c8c8770414 100644 --- a/libopenage/renderer/stages/world/render_stage.cpp +++ b/libopenage/renderer/stages/world/render_stage.cpp @@ -137,6 +137,9 @@ void WorldRenderStage::init_uniform_ids() { WorldObject::tile_params = this->display_shader->get_uniform_id("tile_params"); // WorldObject::scale = this->display_shader->get_uniform_id("scale"); // WorldObject::anchor_offset = this->display_shader->get_uniform_id("anchor_offset"); + WorldObject::scale = this->display_shader->get_uniform_id("scale"); + WorldObject::subtex_size = this->display_shader->get_uniform_id("subtex_size"); + WorldObject::anchor_offset = this->display_shader->get_uniform_id("anchor_offset"); } } // namespace openage::renderer::world From 080849f5d9689f52d07b13c13246cc296f4b68b2 Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 16:01:46 +0200 Subject: [PATCH 7/9] renderer: Remove unused uniform code from world stage. --- assets/shaders/world2d.vert.glsl | 54 ++++++++++++------- libopenage/renderer/stages/world/object.cpp | 38 +++++-------- libopenage/renderer/stages/world/object.h | 2 - .../renderer/stages/world/render_stage.cpp | 2 - 4 files changed, 46 insertions(+), 50 deletions(-) diff --git a/assets/shaders/world2d.vert.glsl b/assets/shaders/world2d.vert.glsl index 86a6565656..3b698b39c1 100644 --- a/assets/shaders/world2d.vert.glsl +++ b/assets/shaders/world2d.vert.glsl @@ -13,6 +13,8 @@ layout (std140) uniform camera { // projection matrix (view to clip space) mat4 proj; // inverse zoom factor (1.0 / zoom) + // high zoom = upscale subtex + // low zoom = downscale subtex float inv_zoom; // inverse viewport size (1.0 / viewport size) vec2 inv_viewport_size; @@ -34,18 +36,21 @@ uniform bool flip_y; // parameters for scaling and moving the subtex // to the correct position in clip space -// offset from the subtex anchor -// moves the subtex relative to the subtex center -// uniform vec2 anchor_offset; - +// animation scalefactor // scales the vertex positions so that they // match the subtex dimensions -// uniform vec2 scale; - +// +// high animation scale = downscale subtex +// low animation scale = upscale subtex uniform float scale; -uniform float zoom; -uniform vec2 screen_size; + +// size of the subtex (in pixels) uniform vec2 subtex_size; + +// offset of the subtex anchor point +// from the subtex center (in pixels) +// used to move the subtex so that the anchor point +// is at the object position uniform vec2 anchor_offset; void main() { @@ -53,29 +58,38 @@ void main() { // this is the position where we want to draw the subtex in 2D vec4 obj_clip_pos = proj * view * model * vec4(obj_world_position, 1.0); - float obj_scale = scale * inv_zoom; - vec2 obj_scale_vec = vec2( - obj_scale * subtex_size.x * inv_viewport_size.x, - obj_scale * subtex_size.y * inv_viewport_size.y + // subtex has to be scaled to account for the zoom factor + // and the animation scale factor. essentially this is (animation scale / zoom). + float zoom_scale = scale * inv_zoom; + + // Scale the subtex vertices + // we have to account for the viewport size to get the correct dimensions + // and then scale the subtex to the zoom factor to get the correct size + vec2 vert_scale = vec2( + zoom_scale * subtex_size.x * inv_viewport_size.x, + zoom_scale * subtex_size.y * inv_viewport_size.y ); - vec2 obj_anchor_vec = vec2( - obj_scale * anchor_offset.x * inv_viewport_size.x, - obj_scale * anchor_offset.y * inv_viewport_size.y + + // Scale the anchor offset with the same method as above + // to get the correct anchor position in the viewport + vec2 anchor_scale = vec2( + zoom_scale * anchor_offset.x * inv_viewport_size.x, + zoom_scale * anchor_offset.y * inv_viewport_size.y ); // if the subtex is flipped, we also need to flip the anchor offset // essentially, we invert the coordinates for the flipped axis - float anchor_x = float(flip_x) * -1.0 * obj_anchor_vec.x + float(!flip_x) * obj_anchor_vec.x; - float anchor_y = float(flip_y) * -1.0 * obj_anchor_vec.y + float(!flip_y) * obj_anchor_vec.y; + float anchor_x = float(flip_x) * -1.0 * anchor_scale.x + float(!flip_x) * anchor_scale.x; + float anchor_y = float(flip_y) * -1.0 * anchor_scale.y + float(!flip_y) * anchor_scale.y; // offset the clip position by the offset of the subtex anchor // imagine this as pinning the subtex to the object position at the subtex anchor point obj_clip_pos += vec4(anchor_x, anchor_y, 0.0, 0.0); // create a move matrix for positioning the vertices - // uses the scale and the transformed object position in clip space - mat4 move = mat4(obj_scale_vec.x, 0.0, 0.0, 0.0, - 0.0, obj_scale_vec.y, 0.0, 0.0, + // uses the vert scale and the transformed object position in clip space + mat4 move = mat4(vert_scale.x, 0.0, 0.0, 0.0, + 0.0, vert_scale.y, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, obj_clip_pos.x, obj_clip_pos.y, obj_clip_pos.z, 1.0); diff --git a/libopenage/renderer/stages/world/object.cpp b/libopenage/renderer/stages/world/object.cpp index e26aaab9e7..c58e9faa98 100644 --- a/libopenage/renderer/stages/world/object.cpp +++ b/libopenage/renderer/stages/world/object.cpp @@ -138,39 +138,25 @@ void WorldObject::update_uniforms(const time::time_t &time) { auto coords = tex_info->get_subtex_info(subtex_idx).get_tile_params(); this->uniforms->update(this->tile_params, coords); - // scale and keep width x height ratio of texture - // when the viewport size changes - auto scale = animation_info->get_scalefactor() / this->camera->get_zoom(); - auto screen_size = this->camera->get_viewport_size(); - auto subtex_size = tex_info->get_subtex_info(subtex_idx).get_size(); - - // Scaling with viewport size and zoom - auto scale_vec = Eigen::Vector2f{ - scale * (static_cast(subtex_size[0]) / screen_size[0]), - scale * (static_cast(subtex_size[1]) / screen_size[1])}; - // this->uniforms->update(this->scale, scale_vec); + // Animation scale factor + // Scales the subtex up or down in the shader + auto scale = animation_info->get_scalefactor(); + this->uniforms->update(this->scale, scale); - // Move subtexture in scene so that its anchor point is at the object's position - auto anchor = tex_info->get_subtex_info(subtex_idx).get_anchor_params(); - auto anchor_offset = Eigen::Vector2f{ - scale * (static_cast(anchor[0]) / screen_size[0]), - scale * (static_cast(anchor[1]) / screen_size[1])}; - // this->uniforms->update(this->anchor_offset, anchor_offset); - - this->uniforms->update(this->scale, animation_info->get_scalefactor()); - // this->uniforms->update("zoom", this->camera->get_zoom()); - Eigen::Vector2f screen_size_vec{ - static_cast(screen_size[0]), - static_cast(screen_size[1])}; - // this->uniforms->update("screen_size", screen_size_vec); + // Subtexture size in pixels + auto subtex_size = tex_info->get_subtex_info(subtex_idx).get_size(); Eigen::Vector2f subtex_size_vec{ static_cast(subtex_size[0]), static_cast(subtex_size[1])}; this->uniforms->update(this->subtex_size, subtex_size_vec); - Eigen::Vector2f anchor_vec{ + + // Anchor point offset (in pixels) + // moves the subtex in the shader so that the anchor point is at the object's position + auto anchor = tex_info->get_subtex_info(subtex_idx).get_anchor_params(); + Eigen::Vector2f anchor_offset{ static_cast(anchor[0]), static_cast(anchor[1])}; - this->uniforms->update(this->anchor_offset, anchor_vec); + this->uniforms->update(this->anchor_offset, anchor_offset); } uint32_t WorldObject::get_id() { diff --git a/libopenage/renderer/stages/world/object.h b/libopenage/renderer/stages/world/object.h index eb075dd4c3..a34a0c690c 100644 --- a/libopenage/renderer/stages/world/object.h +++ b/libopenage/renderer/stages/world/object.h @@ -131,8 +131,6 @@ class WorldObject { inline static uniform_id_t flip_y; inline static uniform_id_t tex; inline static uniform_id_t tile_params; - // inline static uniform_id_t scale; - // inline static uniform_id_t anchor_offset; inline static uniform_id_t scale; inline static uniform_id_t subtex_size; inline static uniform_id_t anchor_offset; diff --git a/libopenage/renderer/stages/world/render_stage.cpp b/libopenage/renderer/stages/world/render_stage.cpp index c8c8770414..d24bb5f896 100644 --- a/libopenage/renderer/stages/world/render_stage.cpp +++ b/libopenage/renderer/stages/world/render_stage.cpp @@ -135,8 +135,6 @@ void WorldRenderStage::init_uniform_ids() { WorldObject::flip_y = this->display_shader->get_uniform_id("flip_y"); WorldObject::tex = this->display_shader->get_uniform_id("tex"); WorldObject::tile_params = this->display_shader->get_uniform_id("tile_params"); - // WorldObject::scale = this->display_shader->get_uniform_id("scale"); - // WorldObject::anchor_offset = this->display_shader->get_uniform_id("anchor_offset"); WorldObject::scale = this->display_shader->get_uniform_id("scale"); WorldObject::subtex_size = this->display_shader->get_uniform_id("subtex_size"); WorldObject::anchor_offset = this->display_shader->get_uniform_id("anchor_offset"); From a19b42b4aaa98524a44856bfbfb6cdf345c2bb89 Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 16:03:57 +0200 Subject: [PATCH 8/9] renderer: Use more compact shader code. --- assets/shaders/world2d.vert.glsl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/assets/shaders/world2d.vert.glsl b/assets/shaders/world2d.vert.glsl index 3b698b39c1..7987d40ec3 100644 --- a/assets/shaders/world2d.vert.glsl +++ b/assets/shaders/world2d.vert.glsl @@ -65,17 +65,11 @@ void main() { // Scale the subtex vertices // we have to account for the viewport size to get the correct dimensions // and then scale the subtex to the zoom factor to get the correct size - vec2 vert_scale = vec2( - zoom_scale * subtex_size.x * inv_viewport_size.x, - zoom_scale * subtex_size.y * inv_viewport_size.y - ); + vec2 vert_scale = zoom_scale * subtex_size * inv_viewport_size; // Scale the anchor offset with the same method as above // to get the correct anchor position in the viewport - vec2 anchor_scale = vec2( - zoom_scale * anchor_offset.x * inv_viewport_size.x, - zoom_scale * anchor_offset.y * inv_viewport_size.y - ); + vec2 anchor_scale = zoom_scale * anchor_offset * inv_viewport_size; // if the subtex is flipped, we also need to flip the anchor offset // essentially, we invert the coordinates for the flipped axis From 185dd98ed9e01c97740e67e89a72feaa3c95a41f Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 21 Apr 2024 16:08:59 +0200 Subject: [PATCH 9/9] renderer: Add new camera uniforms in stresstest 0. --- libopenage/renderer/demo/stresstest_0.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libopenage/renderer/demo/stresstest_0.cpp b/libopenage/renderer/demo/stresstest_0.cpp index ce7da14948..01169b0849 100644 --- a/libopenage/renderer/demo/stresstest_0.cpp +++ b/libopenage/renderer/demo/stresstest_0.cpp @@ -49,7 +49,14 @@ void renderer_stresstest_0(const util::Path &path) { "view", camera->get_view_matrix(), "proj", - camera->get_projection_matrix()); + camera->get_projection_matrix(), + "inv_zoom", + 1.0f / camera->get_zoom()); + auto viewport_size = camera->get_viewport_size(); + Eigen::Vector2f viewport_size_vec{ + 1.0f / static_cast(viewport_size[0]), + 1.0f / static_cast(viewport_size[1])}; + cam_unifs->update("inv_viewport_size", viewport_size_vec); camera->get_uniform_buffer()->update_uniforms(cam_unifs); // Render stages