From d2c8262c68bf7b550fd1bfc1dc4117cded2b80f3 Mon Sep 17 00:00:00 2001 From: Hartmut Seichter Date: Tue, 5 Jan 2021 00:23:03 +0100 Subject: [PATCH] Major push to get renderer separated and configurable. Signed-off-by: Hartmut Seichter --- src/binding/src/script_core.cpp | 30 +++- src/binding/src/script_visual.cpp | 36 +++- src/core/include/pw/core/geometry.hpp | 14 ++ src/core/include/pw/core/image.hpp | 8 +- src/core/include/pw/core/resource.hpp | 4 +- src/core/include/pw/core/size.hpp | 5 +- src/core/include/pw/core/time.hpp | 2 +- src/core/include/pw/core/vector.hpp | 19 +- src/core/src/image.cpp | 8 +- src/core/tests/pwcore_test_vector.cpp | 4 +- src/io/src/image_io.cpp | 2 +- .../include/pw/scene/components/camera.hpp | 48 +++++ src/scripts/demos/simple_002.lua | 166 ++++++++++++++++++ src/system/src/window.cpp | 4 +- src/visual/CMakeLists.txt | 56 +++--- src/visual/include/pw/visual/framebuffer.hpp | 27 +++ .../include/pw/visual/mesh_renderer.hpp | 2 +- src/visual/include/pw/visual/shader.hpp | 34 ++-- src/visual/src/framebuffer.cpp | 131 ++++++++++++++ src/visual/src/mesh_renderer.cpp | 10 +- src/visual/src/pipeline.cpp | 18 +- src/visual/src/shader.cpp | 11 +- 22 files changed, 542 insertions(+), 97 deletions(-) create mode 100644 src/scene/include/pw/scene/components/camera.hpp create mode 100644 src/scripts/demos/simple_002.lua create mode 100644 src/visual/include/pw/visual/framebuffer.hpp create mode 100644 src/visual/src/framebuffer.cpp diff --git a/src/binding/src/script_core.cpp b/src/binding/src/script_core.cpp index 1731768..cfb4ba6 100644 --- a/src/binding/src/script_core.cpp +++ b/src/binding/src/script_core.cpp @@ -7,6 +7,7 @@ #include "pw/core/time.hpp" #include "pw/core/geometry.hpp" #include "pw/core/image.hpp" +#include "pw/core/matrix_transform.hpp" #include "runtime_lua.hpp" @@ -15,6 +16,7 @@ namespace sol { template <> struct is_automagical : std::false_type {}; template <> struct is_automagical : std::false_type {}; +template <> struct is_automagical : std::false_type {}; template <> struct is_automagical : std::false_type {}; } @@ -44,8 +46,24 @@ void register_core_function(sol::state& lua,sol::table& ns) ,"cross",&vector3::cross ,"transposed",&vector3::transposed ,"lerp",&vector3::lerp + ,"forward",&vector3::forward + ,"backward",&vector3::backward + ,"left",&vector3::left + ,"right",&vector3::right + ,"up",&vector3::up + ,"down",&vector3::down ); + ns.new_usertype("vector4" + ,sol::constructors() + ,"x", sol::property(sol::resolve(&vector4::x), [](vector4& v,vector4::value_type val){ v.x() = val;}) + ,"y", sol::property(sol::resolve(&vector4::y), [](vector4& v,vector4::value_type val){ v.y() = val;}) + ,"z", sol::property(sol::resolve(&vector4::z), [](vector4& v,vector4::value_type val){ v.z() = val;}) + ,"w", sol::property(sol::resolve(&vector4::w), [](vector4& v,vector4::value_type val){ v.w() = val;}) + ,"project",&vector4::project + ); + + ns.new_usertype("quaternion" ,sol::constructors() ,"x", sol::property(sol::resolve(&quaternion::x), [](quaternion& v,quaternion::value_type val){ v.x() = val;}) @@ -77,11 +95,6 @@ void register_core_function(sol::state& lua,sol::table& ns) , "height",&size::height ); - ns.new_usertype("sizei" - , sol::constructors() - , "width",&sizei::width - , "height",&sizei::height - ); ns.new_usertype("point", sol::constructors(), @@ -109,13 +122,18 @@ void register_core_function(sol::state& lua,sol::table& ns) , "topology", sol::property(&geometry::topology,&geometry::set_topology) , "vertices", sol::property(&geometry::vertices,&geometry::set_vertices) , "indices", sol::property(&geometry::indices,&geometry::set_indices) - ).new_enum("type" + , "", &geometry::compute_normals + ).new_enum("geometry_type" ,"points", geometry::topology_type::points , "lines", geometry::topology_type::lines , "line_strip", geometry::topology_type::line_strip , "triangles", geometry::topology_type::triangles); + ns.new_usertype>("matrixtransform" + ,"new",sol::no_constructor + ,"look_at",&matrix_transform::look_at + ,"perspective_projection",&matrix_transform::perspective_projection); // SOL3 // geoom_type["type"] = lua.create_table_with( // "points", geometry::topology_type::points diff --git a/src/binding/src/script_visual.cpp b/src/binding/src/script_visual.cpp index 1e36554..2caf618 100644 --- a/src/binding/src/script_visual.cpp +++ b/src/binding/src/script_visual.cpp @@ -2,6 +2,8 @@ #include "pw/core/debug.hpp" #include "pw/visual/pipeline.hpp" #include "pw/visual/shader.hpp" +#include "pw/visual/framebuffer.hpp" +#include "pw/core/size.hpp" #include "runtime_lua.hpp" @@ -10,26 +12,29 @@ namespace pw { void register_visual_function(sol::state&,sol::table &ns) { - ns.new_usertype("pipeline" + ns.new_usertype("pipeline" ,"create",&pipeline::create - ,"draw",&pipeline::draw + ,"draw",&pipeline::draw ); - ns.new_usertype("shader" + ns.new_usertype("shader" ,sol::constructors() - ,"ready",sol::readonly_property(&shader::ready) - ,"use",&shader::use + ,"ready",sol::readonly_property(&shader::ready) + ,"use",&shader::use ,"build",&shader::build ,"source",&shader::source ,"set_source",&shader::set_source ,"set_uniforms",&shader::set_uniforms + ,"set_uniform_float",&shader::set_uniform + ,"set_uniform_mat4",&shader::set_uniform + ,"set_uniform_vec4",&shader::set_uniform ).new_enum("shader_type" ,"fragment",shader::code_type::fragment - ,"vertex",shader::code_type::vertex - ,"geometry",shader::code_type::geometry - ,"compute",shader::code_type::compute); + ,"vertex",shader::code_type::vertex + ,"geometry",shader::code_type::geometry + ,"compute",shader::code_type::compute); ns.new_usertype("render_pass" @@ -40,7 +45,20 @@ void register_visual_function(sol::state&,sol::table &ns) ,"color",sol::property(&material::_color)); - ns.new_usertype("mesh_renderer"); + ns.new_usertype("mesh_renderer" + ,sol::constructors() + ,"create",&mesh_renderer::create + ,"ready",sol::readonly_property(&mesh_renderer::ready) + ,"release",&mesh_renderer::release + ,"draw",&mesh_renderer::draw + ); + + ns.new_usertype("framebuffer" + ,sol::constructors() + ,"create",&framebuffer::create + ,"bind",&framebuffer::bind + ,"unbind",&framebuffer::unbind + ,"blit",&framebuffer::blit); } PW_REGISTER_LUA(visual) diff --git a/src/core/include/pw/core/geometry.hpp b/src/core/include/pw/core/geometry.hpp index 0a87328..dd7a84b 100644 --- a/src/core/include/pw/core/geometry.hpp +++ b/src/core/include/pw/core/geometry.hpp @@ -28,8 +28,18 @@ #include #include +#include +#include + namespace pw { +/* + * NOTE this needs to be rewritten to take into account for *any* kind of geometry + * Some ideas are drafted down there to separate out the attribute buffers. Things to + * consider: multiple UVs, triangle soup, per-vertex-color, texture transforms, weights, + * etc. pp. + */ + class geometry { public: @@ -51,6 +61,10 @@ public: using vertex2array_t = std::vector ; using vertex3array_t = std::vector ; + using __attribute_t = std::variant; + + using __attribute_set = std::tuple; + geometry() = default; geometry(topology_type t); diff --git a/src/core/include/pw/core/image.hpp b/src/core/include/pw/core/image.hpp index f5d05b9..14ac2f4 100644 --- a/src/core/include/pw/core/image.hpp +++ b/src/core/include/pw/core/image.hpp @@ -43,9 +43,9 @@ public: HDR }; - image(const sizei& s, pixel_layout t, void *ptr = nullptr); + image(const size& s, pixel_layout t, void *ptr = nullptr); - bool create(const sizei& s, pixel_layout t, void *ptr = nullptr); + bool create(const size& s, pixel_layout t, void *ptr = nullptr); void release(bool release_memory = false); @@ -65,11 +65,11 @@ public: typedef shared_ptr ptr; - sizei size() const; + ::pw::size size() const; protected: - sizei _size; + ::pw::size _size; pixel_layout _layout; uint64_t _change_count; diff --git a/src/core/include/pw/core/resource.hpp b/src/core/include/pw/core/resource.hpp index 52007ea..42c5649 100644 --- a/src/core/include/pw/core/resource.hpp +++ b/src/core/include/pw/core/resource.hpp @@ -32,7 +32,9 @@ class resource { public: using change_t = std::atomic_int_fast64_t; - int64_t changecount() { return _changecount; } + resource() = default; + + int64_t changecount() const { return _changecount; } void dirty() { ++_changecount; }; protected: diff --git a/src/core/include/pw/core/size.hpp b/src/core/include/pw/core/size.hpp index 2c52d94..c84d305 100644 --- a/src/core/include/pw/core/size.hpp +++ b/src/core/include/pw/core/size.hpp @@ -43,11 +43,10 @@ struct size_ { }; -typedef size_ size; +typedef size_ size; -typedef size_ sizei; typedef size_ sizef; -typedef size_ sized; +typedef size_ sized; } diff --git a/src/core/include/pw/core/time.hpp b/src/core/include/pw/core/time.hpp index ec95cac..a24268b 100644 --- a/src/core/include/pw/core/time.hpp +++ b/src/core/include/pw/core/time.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2019 Hartmut Seichter + * Copyright (c) 1999-2021 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/core/include/pw/core/vector.hpp b/src/core/include/pw/core/vector.hpp index 91a6d84..4093a1e 100644 --- a/src/core/include/pw/core/vector.hpp +++ b/src/core/include/pw/core/vector.hpp @@ -27,6 +27,10 @@ namespace pw { +/** + * Basic vector types used in pixwerx. + */ + template struct vector2_ : matrix_<2,1,T> { @@ -90,12 +94,12 @@ struct vector3_ : matrix_<3,1,T> { } - inline static vector3_ forward() { return vector3_ ( { T(0), T(0),-T(1) } ); } - inline static vector3_ backward() { return vector3_( { T(0), T(0), T(1) } ); } - inline static vector3_ right() { return vector3_ ( { T(1), T(0), T(0) } ); } - inline static vector3_ left() { return vector3_ ( {-T(1), T(0), T(0) } ); } - inline static vector3_ up() { return vector3_ ( { T(0), T(1), T(0) } ); } - inline static vector3_ down() { return vector3_ ( { T(0),-T(1), T(0) } ); } + inline static constexpr vector3_ forward() { return vector3_ ( { T(0), T(0),-T(1) } ); } + inline static constexpr vector3_ backward() { return vector3_( { T(0), T(0), T(1) } ); } + inline static constexpr vector3_ right() { return vector3_ ( { T(1), T(0), T(0) } ); } + inline static constexpr vector3_ left() { return vector3_ ( {-T(1), T(0), T(0) } ); } + inline static constexpr vector3_ up() { return vector3_ ( { T(0), T(1), T(0) } ); } + inline static constexpr vector3_ down() { return vector3_ ( { T(0),-T(1), T(0) } ); } inline static vector3_ x_axis() { return vector3_ ( { T(1), T(0), T(0) } ); } inline static vector3_ y_axis() { return vector3_ ( { T(0), T(1), T(0) } ); } @@ -110,7 +114,7 @@ struct vector4_ : matrix_<4,1,T> { using base_type::base_type; using base_type::operator = ; - vector4_(T x_,T y_,T z_,T w_) : base_type({x_,y_,z_,w_}) {} + vector4_(T x_,T y_,T z_,T w_) : base_type( {x_,y_,z_,w_} ) {} vector4_(const base_type& m) : base_type(m) {} vector4_(const vector3_ &m, T w) : base_type({m(0),m(1),m(2),w}) {} @@ -129,6 +133,7 @@ struct vector4_ : matrix_<4,1,T> { inline auto xyz() const { return vector3_({ x(),y(),z() } ); } inline auto project() const { return vector3_({ x()/w(),y()/w(),z()/w() } ); } + }; // diff --git a/src/core/src/image.cpp b/src/core/src/image.cpp index 97cef24..5bb9b65 100644 --- a/src/core/src/image.cpp +++ b/src/core/src/image.cpp @@ -4,12 +4,12 @@ namespace pw { -image::image(const sizei &s, image::pixel_layout t, void *ptr) +image::image(const ::pw::size &s, image::pixel_layout t, void *ptr) { this->create(s,t,ptr); } -bool image::create(const sizei &s, image::pixel_layout t, void *ptr) +bool image::create(const ::pw::size &s, image::pixel_layout t, void *ptr) { size_t n = bytes_per_pixel(t) * s.area(); @@ -24,7 +24,7 @@ bool image::create(const sizei &s, image::pixel_layout t, void *ptr) } else { _data.resize(n); - _size = sizei(0,0); + _size = ::pw::size(0,0); } return !_data.empty(); @@ -53,7 +53,7 @@ uint32_t image::bytes_per_pixel(image::pixel_layout t) return std::numeric_limits::max(); } -sizei image::size() const +::pw::size image::size() const { return _size; } diff --git a/src/core/tests/pwcore_test_vector.cpp b/src/core/tests/pwcore_test_vector.cpp index 586beff..a5091f0 100644 --- a/src/core/tests/pwcore_test_vector.cpp +++ b/src/core/tests/pwcore_test_vector.cpp @@ -4,7 +4,7 @@ #include -int main(int argc,char **argv) { +int main(int ,char **) { pw::vector2_ v2_A = { 3.2, 1.2 }; pw::vector2_ v2_B = { 3.2, 1.2 }; @@ -12,7 +12,7 @@ int main(int argc,char **argv) { auto AB_lerp = pw::vector2f::lerp(v2_A,v2_B,0.5); pw::vector4_ v4; - pw::vector3f v; + pw::vector3f v = pw::vector3f::backward(); v4.fill(1.5); diff --git a/src/io/src/image_io.cpp b/src/io/src/image_io.cpp index f90981c..00c15cf 100644 --- a/src/io/src/image_io.cpp +++ b/src/io/src/image_io.cpp @@ -24,7 +24,7 @@ struct image_io::impl image r; - r.create(sizei(x,y),image::pixel_layout::RGBA8,data); + r.create(size(x,y),image::pixel_layout::RGBA8,data); stbi_image_free(data); diff --git a/src/scene/include/pw/scene/components/camera.hpp b/src/scene/include/pw/scene/components/camera.hpp new file mode 100644 index 0000000..4181392 --- /dev/null +++ b/src/scene/include/pw/scene/components/camera.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 1999-2020 Hartmut Seichter + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef PW_SCENE_COMPONENT_PROJECTION_HPP +#define PW_SCENE_COMPONENT_PROJECTION_HPP + +#include +#include +#include + +namespace pw { + +struct camera { + matrix4x4 view = matrix4x4::identity(); + matrix4x4 projection = matrix_transform::look_at(vector3{0,0,0}, + vector3{0,0,1}, + vector3{0,1,0}); + + rectangle viewport = pw::rectangle({0, 0, 1, 1}); + + uint32_t mask = 0xFFFFFF; +}; + +} + + +#endif diff --git a/src/scripts/demos/simple_002.lua b/src/scripts/demos/simple_002.lua new file mode 100644 index 0000000..6abc829 --- /dev/null +++ b/src/scripts/demos/simple_002.lua @@ -0,0 +1,166 @@ +-- +-- small demonstrator for Lua binding on pixwerx +-- + +pw.script:load_all() + +print("hello pixwerx!") + +local w = pw.window.new() +w.visible = false + +-- set title +w.title = "pixwerx 0.1" + +-- set size +w.size = pw.size.new(640,480) + +-- move window +w.position = pw.point.new(100,100) + + +local g = pw.geometry:new() + +g.topology = pw.geometry.triangles -- meh + + +g.vertices:clear() + +g.vertices:add(pw.vector3:new(-1, 1, 0)) -- 0 +g.vertices:add(pw.vector3:new(-1,-1, 0)) -- 1 +g.vertices:add(pw.vector3:new( 1,-1, 0)) -- 2 +g.vertices:add(pw.vector3:new( 1, 1, 0)) -- 3 + + +-- 0 --- 3 +-- | \ | +-- 1 --- 2 + +print(g.vertices,#g.vertices,g.vertices[1].x) + +g.indices:add(0) +g.indices:add(1) +g.indices:add(2) + +g.indices:add(2) +g.indices:add(3) +g.indices:add(0) + +print(g.indices) + + +local mm = pw.matrix4x4:new() +local mv = pw.matrix4x4:new() +local mp = pw.matrix4x4:new() + + +w.visible = true + + +local fb = pw.framebuffer:new() + +print(w.client_size.width,"x",w.client_size.height) + +if fb:create(w.client_size) then + print("framebuffer ok") +else + print("framebuffer failed") +end + + + +local s = pw.shader:new() + +print(s.ready) + +s:set_source(pw.shader_type.vertex,[[ +#version 400 +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +in vec3 vertex_p; + +void main() { + gl_Position = projection * view * model * vec4(vertex_p, 1.0); +} +]]) + +s:set_source(pw.shader_type.fragment,[[ +#version 400 +uniform vec4 color = vec4(1.0, 0.0, 0.0, 1.0); +out vec4 frag_colour; +void main() { + frag_colour = color; +} +]]) + +print(s.ready) + +if not s:build() then + print("Error!") +end + +print(s.ready) + +local renderer = pw.mesh_renderer:new() + +if not renderer:create(g) then + print("couldn't create renderer") +end + + +while w:update() do + + + -- somehow works + if (pw.input.get().input_string == 'f') then + w.fullscreen = not w.fullscreen + end + + -- keycode for quit + if (pw.input.get().input_string == 'q') then + break; + end + + -- just to check + if (pw.input:get().mouse_button == 1) then + + print("elapsed",t.elapsed) + t:reset() + print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y,w.client_size.width,w.client_size.height) + end + + + + mm:set_identity() + + mv = pw.matrixtransform.look_at(pw.vector3:new(0,0,0),pw.vector3.forward(),pw.vector3.up()) + mp = pw.matrixtransform.perspective_projection(1.3,1.0,0.2,100) + + local cl = pw.vector4:new( 1.0, 0, 0, 1.0) + + + + s:use() + + s:set_uniform_mat4("model",mm) + s:set_uniform_mat4("view",mv) + s:set_uniform_mat4("projection",mp) + s:set_uniform_vec4("color",cl) + + + fb:bind() + + + renderer:draw() + + fb:blit() + + fb:unbind() + + + +end + + diff --git a/src/system/src/window.cpp b/src/system/src/window.cpp index d00a895..0df6e04 100644 --- a/src/system/src/window.cpp +++ b/src/system/src/window.cpp @@ -43,7 +43,7 @@ struct window::impl { GLFWwindow *_window = nullptr; - sizei _old_size; + ::pw::size _old_size; pointi _old_pos; // window_context _context; @@ -233,7 +233,7 @@ struct window::impl { glfwSetWindowTitle(_window,title.c_str()); } - void set_size(const ::pw::sizei& s) + void set_size(const ::pw::size& s) { glfwSetWindowSize(_window,s.width,s.height); } diff --git a/src/visual/CMakeLists.txt b/src/visual/CMakeLists.txt index d3ff145..e82f97e 100644 --- a/src/visual/CMakeLists.txt +++ b/src/visual/CMakeLists.txt @@ -1,41 +1,43 @@ set(hdrs - include/pw/visual/shader.hpp - include/pw/visual/pipeline.hpp - include/pw/visual/texture.hpp - include/pw/visual/mesh_renderer.hpp - include/pw/visual/material.hpp - ) + include/pw/visual/framebuffer.hpp + include/pw/visual/shader.hpp + include/pw/visual/pipeline.hpp + include/pw/visual/texture.hpp + include/pw/visual/mesh_renderer.hpp + include/pw/visual/material.hpp + ) set(srcs - src/shader.cpp - src/context.cpp - src/pass.cpp - src/pipeline.cpp - src/target.cpp - src/texture.cpp - src/mesh_renderer.cpp - src/material.cpp - ) + src/framebuffer.cpp + src/shader.cpp + src/context.cpp + src/pass.cpp + src/pipeline.cpp + src/target.cpp + src/texture.cpp + src/mesh_renderer.cpp + src/material.cpp + ) set(srcs_shader - src/shader/unlit_vs.glsl - src/shader/unlit_fs.glsl - ) + src/shader/unlit_vs.glsl + src/shader/unlit_fs.glsl + ) add_library(pwvisual - STATIC - ${hdrs} - ${srcs} - ${srcs_shader} - ) + STATIC + ${hdrs} + ${srcs} + ${srcs_shader} + ) target_include_directories( - pwvisual - PUBLIC - include - ) + pwvisual + PUBLIC + include + ) target_link_libraries(pwvisual pwscene glad) diff --git a/src/visual/include/pw/visual/framebuffer.hpp b/src/visual/include/pw/visual/framebuffer.hpp new file mode 100644 index 0000000..2052fa9 --- /dev/null +++ b/src/visual/include/pw/visual/framebuffer.hpp @@ -0,0 +1,27 @@ +#ifndef PW_VISUAL_FRAMEBUFFER_HPP +#define PW_VISUAL_FRAMEBUFFER_HPP + +#include +#include + +namespace pw { + +class framebuffer { +public: + framebuffer(); + ~framebuffer(); + + bool create(const size& s); + + void bind(); + void blit(); + void unbind(); + +protected: + + struct impl; + std::unique_ptr _impl; +}; + +} +#endif diff --git a/src/visual/include/pw/visual/mesh_renderer.hpp b/src/visual/include/pw/visual/mesh_renderer.hpp index d648944..751b4d3 100644 --- a/src/visual/include/pw/visual/mesh_renderer.hpp +++ b/src/visual/include/pw/visual/mesh_renderer.hpp @@ -19,7 +19,7 @@ public: ~mesh_renderer(); - void create(const geometry &m); + bool create(const geometry &m); void release(); void draw(); diff --git a/src/visual/include/pw/visual/shader.hpp b/src/visual/include/pw/visual/shader.hpp index 226582f..24f2cd9 100644 --- a/src/visual/include/pw/visual/shader.hpp +++ b/src/visual/include/pw/visual/shader.hpp @@ -24,26 +24,36 @@ public: compute }; - void set_source(const std::string& c,code_type t) { _source[t] = c; } + void set_source(code_type t, const std::string& c) { _source[t] = c; } std::string source(code_type t) { return _source[t]; } bool ready() const; - shader& set(int location,float v); - shader& set(int location,matrix4x4f const & v); - shader& set(int location,vector4f const & v); + shader& set_uniform_at_location(int location,float v); + shader& set_uniform_at_location(int location,matrix4x4f const &v); + shader& set_uniform_at_location(int location,vector4f const &v); + /** + * @brief retrieves the position of a uniform + * @param name of the uniform + * @return position of the uniform or negative if it doesn't exist + */ int uniform_location(std::string const & name) const; + /** + * @brief check if a uniform with the given name exists + * @param name of the uniform + * @return true if found + */ + bool has_uniform(std::string const &name) const { return uniform_location(name) >= 0; } + + /** + * sets data of the + */ template - shader & set(std::string const & name, T&& value) - { - int location = uniform_location(name); - if (location >= 0) - return set(location, std::forward(value)); - else - debug::w() << "missing uniform: '" << name << "'"; - return *this; + shader & set_uniform(std::string const & name, T &&value) + { + return set_uniform_at_location( uniform_location(name), std::forward(value) ); } bool build(); diff --git a/src/visual/src/framebuffer.cpp b/src/visual/src/framebuffer.cpp new file mode 100644 index 0000000..fe929fa --- /dev/null +++ b/src/visual/src/framebuffer.cpp @@ -0,0 +1,131 @@ +#include "pw/visual/framebuffer.hpp" + +#include "pw/core/size.hpp" +#include "pw/core/debug.hpp" + +#include "glad/glad.h" + +namespace pw { + +struct framebuffer::impl { + + size _size; + + GLuint _fbo_draw; + GLuint _fbo_msaa; + + GLuint _rbo_color; + GLuint _rbo_depth; + + bool create(const size &s) + { + + _size = s; + + int max_msaa; + + // query actual maximum MSAA + glGetIntegerv(GL_MAX_SAMPLES,&max_msaa); + + + // create a 4x MSAA renderbuffer object for colorbuffer + int msaa = std::min(max_msaa,4); + + + debug::d() << "OpenGL multisampling: " << max_msaa << " choosen:" << msaa; + debug::d() << "Framebuffer size " << _size.width << " x " << _size.height; + + glGenRenderbuffers(1, &_rbo_color); + glBindRenderbuffer(GL_RENDERBUFFER, _rbo_color); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGBA8, _size.width, _size.height); + + // create a 4x MSAA renderbuffer object for depthbuffer + + glGenRenderbuffers(1, &_rbo_depth); + glBindRenderbuffer(GL_RENDERBUFFER, _rbo_depth); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT, _size.width, _size.height); + + // create a 4x MSAA framebuffer object + glGenFramebuffers(1, &_fbo_msaa); + glBindFramebuffer(GL_FRAMEBUFFER, _fbo_msaa); + + // attach colorbuffer image to FBO + glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER + GL_COLOR_ATTACHMENT0, // 2. color attachment point + GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER + _rbo_color); // 4. rbo ID + + // attach depthbuffer image to FBO + glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER + GL_DEPTH_ATTACHMENT, // 2. depth attachment point + GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER + _rbo_depth); // 4. rbo ID + + // check FBO status + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + return false; + + unbind(); + + return true; + + } + + + void bind() + { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_msaa); + } + + void blit() + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo_msaa); // src FBO (multi-sample) + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw); // dst FBO (single-sample) + + glBlitFramebuffer(0, 0, _size.width, _size.height, // src rect + 0, 0, _size.width, _size.height, // dst rect + GL_COLOR_BUFFER_BIT, // buffer mask + GL_LINEAR); // scale filter + + } + + void unbind() + { + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + } +}; + +framebuffer::framebuffer() +{ + _impl = std::make_unique(); +} + +framebuffer::~framebuffer() +{ +} + +bool framebuffer::create(const size &s) +{ + return _impl->create(s); +} + +void framebuffer::bind() +{ + _impl->bind(); +} + +void framebuffer::blit() +{ + _impl->blit(); +} + +void framebuffer::unbind() +{ + _impl->unbind(); +} + + +} diff --git a/src/visual/src/mesh_renderer.cpp b/src/visual/src/mesh_renderer.cpp index 2bbe01c..8b138e4 100644 --- a/src/visual/src/mesh_renderer.cpp +++ b/src/visual/src/mesh_renderer.cpp @@ -28,10 +28,10 @@ struct mesh_renderer::impl { bool ready() const { - return GL_TRUE == glIsVertexArray(_vao); + return glIsVertexArray != nullptr && GL_TRUE == glIsVertexArray(_vao); } - void create(const geometry& m) + bool create(const geometry& m) { // reset if the renderer already in use if (ready()) { @@ -81,6 +81,8 @@ struct mesh_renderer::impl { if (error != GL_NO_ERROR) { debug::e() << "GL error: " << error; } + + return ready(); } @@ -135,9 +137,9 @@ bool mesh_renderer::ready() const return _impl->ready(); } -void mesh_renderer::create(const geometry &m) +bool mesh_renderer::create(const geometry &m) { - _impl->create(m); + return _impl->create(m); } void mesh_renderer::release() diff --git a/src/visual/src/pipeline.cpp b/src/visual/src/pipeline.cpp index ce8191f..977db1b 100644 --- a/src/visual/src/pipeline.cpp +++ b/src/visual/src/pipeline.cpp @@ -132,8 +132,8 @@ struct triangle_renderer frag_colour = input_color; })"; - shader_p.set_source(vertex_shader_2,shader::code_type::vertex); - shader_p.set_source(fragment_shader_2,shader::code_type::fragment); + shader_p.set_source(shader::code_type::vertex,vertex_shader_2); + shader_p.set_source(shader::code_type::fragment,fragment_shader_2); if (!shader_p.build()) exit(-1); @@ -220,7 +220,7 @@ struct triangle_renderer struct pipeline::impl { - sizei _size; + size _size; GLuint _fbo_draw; GLuint _fbo_msaa; @@ -231,7 +231,7 @@ struct pipeline::impl { //testing triangle_renderer tr; - bool create(sizei size); + bool create(size s); void draw(); @@ -240,7 +240,7 @@ struct pipeline::impl { }; -GLuint generate_multisample_texture(const sizei& s,int samples) +GLuint generate_multisample_texture(const size& s,int samples) { GLuint texture; glGenTextures(1, &texture); @@ -252,10 +252,10 @@ GLuint generate_multisample_texture(const sizei& s,int samples) return texture; } -bool pipeline::impl::create(sizei size) +bool pipeline::impl::create(::pw::size s) { - _size = size; + _size = s; int max_msaa; @@ -309,10 +309,12 @@ bool pipeline::impl::create(sizei size) return true; } + + + void pipeline::impl::draw() { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_msaa); // glClearColor(1.0,0,0,1); // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); diff --git a/src/visual/src/shader.cpp b/src/visual/src/shader.cpp index 11d0b2b..a4d05df 100644 --- a/src/visual/src/shader.cpp +++ b/src/visual/src/shader.cpp @@ -31,7 +31,7 @@ struct shader::impl bool build() { - if (!is_valid()) return false; +// if (!is_valid()) return false; for (const auto & [type,code] : _shader._source) { @@ -180,6 +180,7 @@ shader::shader() shader::~shader() { + } bool shader::ready() const @@ -187,17 +188,17 @@ bool shader::ready() const return _impl->is_valid(); } -shader &shader::set(int location, float v) +shader &shader::set_uniform_at_location(int location, float v) { _impl->bind(location,v); return *this; } -shader &shader::set(int location, const vector4f &v) +shader &shader::set_uniform_at_location(int location, vector4f const &v) { _impl->bind(location,v); return *this; } -shader &shader::set(int location, const matrix4x4f &v) +shader &shader::set_uniform_at_location(int location, matrix4x4f const &v) { _impl->bind(location,v); return *this; } @@ -239,7 +240,7 @@ void shader::set_uniforms(uniform_cache_t c) if constexpr ((std::is_same_v) || (std::is_same_v) || (std::is_same_v) ) { - set(loc, std::forward(arg)); + set_uniform_at_location( loc, std::forward(arg)); } else { debug::e() << "unknown uniform type"; }