Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable World Shader Commands System #1738

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/shaders/world2d.frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ void main() {
break;
}
id = u_id;
}
}
34 changes: 34 additions & 0 deletions assets/test/shaders/demo_7_world.frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#version 330

in vec2 vert_uv;

layout(location = 0) out vec4 col;
layout(location = 1) out uint id;

uniform sampler2D tex;
uniform uint u_id;

// position (top left corner) and size: (x, y, width, height)
uniform vec4 tile_params;

vec2 uv = vec2(
vert_uv.x * tile_params.z + tile_params.x,
vert_uv.y *tile_params.w + tile_params.y);

void main() {
vec4 tex_val = texture(tex, uv);
int alpha = int(round(tex_val.a * 255));
switch (alpha) {
case 0:
col = tex_val;
discard;

// do not save the ID
return;
//@COMMAND_SWITCH@
default:
col = tex_val;
break;
}
id = u_id;
}
101 changes: 101 additions & 0 deletions assets/test/shaders/demo_7_world.vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#version 330

layout(location=0) in vec2 v_position;
layout(location=1) in vec2 uv;

out vec2 vert_uv;

// camera parameters for transforming the object position
// and scaling the subtex to the correct size
layout (std140) uniform camera {
// view matrix (world to view space)
mat4 view;
// 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;
};

// can be used to move the object position in world space _before_
// it's transformed to clip space
// this is usually unnecessary because we want to draw the
// subtex where the object is, so this can be set to the identity matrix
uniform mat4 model;

// position of the object in world space
uniform vec3 obj_world_position;

// flip the subtexture horizontally/vertically
uniform bool flip_x;
uniform bool flip_y;

// parameters for scaling and moving the subtex
// to the correct position in clip space

// animation scalefactor
// scales the vertex positions so that they
// match the subtex dimensions
//
// high animation scale = downscale subtex
// low animation scale = upscale subtex
uniform float scale;

// 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() {
// 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);

// 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 = 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 = 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
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 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);

// calculate the final vertex position
gl_Position = move * vec4(v_position, 0.0, 1.0);

// if the subtex is flipped, we also need to flip the uv tex coordinates
// essentially, we invert the coordinates for the flipped axis

// !flip_x is default because OpenGL uses bottom-left as its origin
float uv_x = float(!flip_x) * uv.x + float(flip_x) * (1.0 - uv.x);
float uv_y = float(flip_y) * uv.y + float(!flip_y) * (1.0 - uv.y);

vert_uv = vec2(uv_x, uv_y);
}
23 changes: 23 additions & 0 deletions assets/test/shaders/world_commands.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[COMMAND]
placeholder=COMMAND_SWITCH
alpha=254
description=Red tint
code={
col = vec4(1.0, 0.0, 0.0, 1.0) * tex_val;
}

[COMMAND]
placeholder=COMMAND_SWITCH
alpha=252
description=Green tint
code={
col = vec4(0.0, 1.0, 0.0, 1.0) * tex_val;
}

[COMMAND]
placeholder=COMMAND_SWITCH
alpha=250
description=Blue tint
code={
col = vec4(0.0, 0.0, 1.0, 1.0) * tex_val;
}
1 change: 1 addition & 0 deletions libopenage/renderer/demo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_sources(libopenage
demo_4.cpp
demo_5.cpp
demo_6.cpp
demo_7.cpp
stresstest_0.cpp
stresstest_1.cpp
tests.cpp
Expand Down
107 changes: 107 additions & 0 deletions libopenage/renderer/demo/demo_7.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2025-2025 the openage authors. See copying.md for legal info.

#include "demo_7.h"

#include "util/path.h"

#include <eigen3/Eigen/Dense>
#include <QKeyEvent>

#include "coord/tile.h"
#include "renderer/camera/camera.h"
#include "renderer/gui/integration/public/gui_application_with_logger.h"
#include "renderer/opengl/window.h"
#include "renderer/render_factory.h"
#include "renderer/render_pass.h"
#include "renderer/render_target.h"
#include "renderer/resources/assets/asset_manager.h"
#include "renderer/resources/shader_source.h"
#include "renderer/stages/camera/manager.h"
#include "renderer/stages/screen/render_stage.h"
#include "renderer/stages/skybox/render_stage.h"
#include "renderer/stages/terrain/render_entity.h"
#include "renderer/stages/terrain/render_stage.h"
#include "renderer/stages/world/render_entity.h"
#include "renderer/stages/world/render_stage.h"
#include "renderer/uniform_buffer.h"
#include "time/clock.h"

namespace openage::renderer::tests {

void renderer_demo_7(const util::Path &path) {
// Basic setup
auto qtapp = std::make_shared<gui::GuiApplicationWithLogger>();
window_settings settings;
settings.width = 800;
settings.height = 600;
settings.debug = true;

auto window = std::make_shared<opengl::GlWindow>("Shader Commands Demo", settings);
auto renderer = window->make_renderer();
auto camera = std::make_shared<renderer::camera::Camera>(renderer, window->get_size());
auto clock = std::make_shared<time::Clock>();
auto asset_manager = std::make_shared<renderer::resources::AssetManager>(
renderer,
path["assets"]["test"]);
auto cam_manager = std::make_shared<renderer::camera::CameraManager>(camera);

auto shaderdir = path / "assets" / "test" / "shaders";

std::vector<std::shared_ptr<RenderPass>>
render_passes{};

// Initialize world renderer with shader commands
auto world_renderer = std::make_shared<renderer::world::WorldRenderStage>(
window,
renderer,
camera,
shaderdir,
shaderdir, // Temporarily, Shader commands config has the same path with shaders for this demo
asset_manager,
clock);

render_passes.push_back(world_renderer->get_render_pass());

auto screen_renderer = std::make_shared<renderer::screen::ScreenRenderStage>(
window,
renderer,
path["assets"]["shaders"]);
std::vector<std::shared_ptr<renderer::RenderTarget>> targets{};
for (auto &pass : render_passes) {
targets.push_back(pass->get_target());
}
screen_renderer->set_render_targets(targets);

render_passes.push_back(screen_renderer->get_render_pass());

auto render_factory = std::make_shared<RenderFactory>(nullptr, world_renderer);

auto entity1 = render_factory->add_world_render_entity();
entity1->update(0, coord::phys3(0.0f, 0.0f, 0.0f), "./textures/test_gaben.sprite");

auto entity2 = render_factory->add_world_render_entity();
entity2->update(1, coord::phys3(3.0f, 0.0f, 0.0f), "./textures/test_gaben.sprite");

auto entity3 = render_factory->add_world_render_entity();
entity3->update(2, coord::phys3(-3.0f, 0.0f, 0.0f), "./textures/test_gaben.sprite");

// Main loop
while (not window->should_close()) {
qtapp->process_events();

// Update camera matrices
cam_manager->update();

world_renderer->update();

for (auto &pass : render_passes) {
renderer->render(pass);
}

renderer->check_error();

window->update();
}
}

} // namespace openage::renderer::tests
22 changes: 22 additions & 0 deletions libopenage/renderer/demo/demo_7.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2025-2025 the openage authors. See copying.md for legal info.

#pragma once

#include "util/path.h"

namespace openage::renderer::tests {

/**
* Show off the render stages in the level 2 renderer and the camera
* system.
* - Window creation
* - Creating a camera
* - Initializing the level 2 render stages: skybox, terrain, world, screen
* - Adding renderables to the render stages via the render factory
* - Moving camera with mouse/keyboard callbacks
*
* @param path Path to the project rootdir.
*/
void renderer_demo_7(const util::Path &path);

} // namespace openage::renderer::tests
7 changes: 6 additions & 1 deletion libopenage/renderer/demo/tests.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2024 the openage authors. See copying.md for legal info.
// Copyright 2015-2025 the openage authors. See copying.md for legal info.

#include "tests.h"

Expand All @@ -12,6 +12,7 @@
#include "renderer/demo/demo_4.h"
#include "renderer/demo/demo_5.h"
#include "renderer/demo/demo_6.h"
#include "renderer/demo/demo_7.h"
#include "renderer/demo/stresstest_0.h"
#include "renderer/demo/stresstest_1.h"

Expand Down Expand Up @@ -47,6 +48,10 @@ void renderer_demo(int demo_id, const util::Path &path) {
renderer_demo_6(path);
break;

case 7:
renderer_demo_7(path);
break;

default:
log::log(MSG(err) << "Unknown renderer demo requested: " << demo_id << ".");
break;
Expand Down
1 change: 1 addition & 0 deletions libopenage/renderer/stages/world/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ add_sources(libopenage
object.cpp
render_entity.cpp
render_stage.cpp
world_shader_commands.cpp
)
Loading
Loading