Major push to get renderer separated and configurable.
Signed-off-by: Hartmut Seichter <hartmut@technotecture.com>
This commit is contained in:
parent
77e254872f
commit
d2c8262c68
22 changed files with 542 additions and 97 deletions
|
@ -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<pw::matrix4x4> : std::false_type {};
|
||||
template <> struct is_automagical<pw::vector3> : std::false_type {};
|
||||
template <> struct is_automagical<pw::vector4> : std::false_type {};
|
||||
template <> struct is_automagical<pw::quaternion> : 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>("vector4"
|
||||
,sol::constructors<vector4(),vector4(vector4::value_type,vector4::value_type,vector4::value_type,vector4::value_type)>()
|
||||
,"x", sol::property(sol::resolve<const vector4::value_type&() const>(&vector4::x), [](vector4& v,vector4::value_type val){ v.x() = val;})
|
||||
,"y", sol::property(sol::resolve<const vector4::value_type&() const>(&vector4::y), [](vector4& v,vector4::value_type val){ v.y() = val;})
|
||||
,"z", sol::property(sol::resolve<const vector4::value_type&() const>(&vector4::z), [](vector4& v,vector4::value_type val){ v.z() = val;})
|
||||
,"w", sol::property(sol::resolve<const vector4::value_type&() const>(&vector4::w), [](vector4& v,vector4::value_type val){ v.w() = val;})
|
||||
,"project",&vector4::project
|
||||
);
|
||||
|
||||
|
||||
ns.new_usertype<quaternion>("quaternion"
|
||||
,sol::constructors<quaternion(), quaternion(quaternion::value_type,quaternion::value_type,quaternion::value_type,quaternion::value_type)>()
|
||||
,"x", sol::property(sol::resolve<const quaternion::value_type&() const>(&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>("sizei"
|
||||
, sol::constructors<sizei(),sizei(int,int)>()
|
||||
, "width",&sizei::width
|
||||
, "height",&sizei::height
|
||||
);
|
||||
|
||||
ns.new_usertype<point>("point",
|
||||
sol::constructors<point(),point(Scalar,Scalar)>(),
|
||||
|
@ -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<false>("type"
|
||||
, "", &geometry::compute_normals
|
||||
).new_enum<false>("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<matrix_transform<real_t>>("matrixtransform"
|
||||
,"new",sol::no_constructor
|
||||
,"look_at",&matrix_transform<real_t>::look_at
|
||||
,"perspective_projection",&matrix_transform<real_t>::perspective_projection);
|
||||
// SOL3
|
||||
// geoom_type["type"] = lua.create_table_with(
|
||||
// "points", geometry::topology_type::points
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
@ -25,6 +27,9 @@ void register_visual_function(sol::state&,sol::table &ns)
|
|||
,"source",&shader::source
|
||||
,"set_source",&shader::set_source
|
||||
,"set_uniforms",&shader::set_uniforms
|
||||
,"set_uniform_float",&shader::set_uniform<float>
|
||||
,"set_uniform_mat4",&shader::set_uniform<matrix4x4&>
|
||||
,"set_uniform_vec4",&shader::set_uniform<vector4&>
|
||||
).new_enum<false>("shader_type"
|
||||
,"fragment",shader::code_type::fragment
|
||||
,"vertex",shader::code_type::vertex
|
||||
|
@ -40,7 +45,20 @@ void register_visual_function(sol::state&,sol::table &ns)
|
|||
,"color",sol::property(&material::_color));
|
||||
|
||||
|
||||
ns.new_usertype<mesh_renderer>("mesh_renderer");
|
||||
ns.new_usertype<mesh_renderer>("mesh_renderer"
|
||||
,sol::constructors<mesh_renderer(),mesh_renderer(const geometry&)>()
|
||||
,"create",&mesh_renderer::create
|
||||
,"ready",sol::readonly_property(&mesh_renderer::ready)
|
||||
,"release",&mesh_renderer::release
|
||||
,"draw",&mesh_renderer::draw
|
||||
);
|
||||
|
||||
ns.new_usertype<framebuffer>("framebuffer"
|
||||
,sol::constructors<framebuffer()>()
|
||||
,"create",&framebuffer::create
|
||||
,"bind",&framebuffer::bind
|
||||
,"unbind",&framebuffer::unbind
|
||||
,"blit",&framebuffer::blit);
|
||||
}
|
||||
|
||||
PW_REGISTER_LUA(visual)
|
||||
|
|
|
@ -28,8 +28,18 @@
|
|||
#include <pw/core/aabb.hpp>
|
||||
#include <pw/core/resource.hpp>
|
||||
|
||||
#include <variant>
|
||||
#include <tuple>
|
||||
|
||||
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<vector2> ;
|
||||
using vertex3array_t = std::vector<vector3> ;
|
||||
|
||||
using __attribute_t = std::variant<valuearray_t,indexarray_t,vertex2array_t,vertex3array_t>;
|
||||
|
||||
using __attribute_set = std::tuple<uint32_t,__attribute_t,int>;
|
||||
|
||||
geometry() = default;
|
||||
geometry(topology_type t);
|
||||
|
||||
|
|
|
@ -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<image> ptr;
|
||||
|
||||
sizei size() const;
|
||||
::pw::size size() const;
|
||||
|
||||
protected:
|
||||
|
||||
sizei _size;
|
||||
::pw::size _size;
|
||||
pixel_layout _layout;
|
||||
uint64_t _change_count;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -43,11 +43,10 @@ struct size_ {
|
|||
|
||||
};
|
||||
|
||||
typedef size_<real_t> size;
|
||||
typedef size_<int> size;
|
||||
|
||||
typedef size_<int> sizei;
|
||||
typedef size_<float> sizef;
|
||||
typedef size_<float> sized;
|
||||
typedef size_<double> sized;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
namespace pw {
|
||||
|
||||
/**
|
||||
* Basic vector types used in pixwerx.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
struct vector2_ : matrix_<2,1,T> {
|
||||
|
||||
|
@ -90,12 +94,12 @@ struct vector3_ : matrix_<3,1,T> {
|
|||
}
|
||||
|
||||
|
||||
inline static vector3_<T> forward() { return vector3_<T> ( { T(0), T(0),-T(1) } ); }
|
||||
inline static vector3_<T> backward() { return vector3_<T>( { T(0), T(0), T(1) } ); }
|
||||
inline static vector3_<T> right() { return vector3_<T> ( { T(1), T(0), T(0) } ); }
|
||||
inline static vector3_<T> left() { return vector3_<T> ( {-T(1), T(0), T(0) } ); }
|
||||
inline static vector3_<T> up() { return vector3_<T> ( { T(0), T(1), T(0) } ); }
|
||||
inline static vector3_<T> down() { return vector3_<T> ( { T(0),-T(1), T(0) } ); }
|
||||
inline static constexpr vector3_<T> forward() { return vector3_<T> ( { T(0), T(0),-T(1) } ); }
|
||||
inline static constexpr vector3_<T> backward() { return vector3_<T>( { T(0), T(0), T(1) } ); }
|
||||
inline static constexpr vector3_<T> right() { return vector3_<T> ( { T(1), T(0), T(0) } ); }
|
||||
inline static constexpr vector3_<T> left() { return vector3_<T> ( {-T(1), T(0), T(0) } ); }
|
||||
inline static constexpr vector3_<T> up() { return vector3_<T> ( { T(0), T(1), T(0) } ); }
|
||||
inline static constexpr vector3_<T> down() { return vector3_<T> ( { T(0),-T(1), T(0) } ); }
|
||||
|
||||
inline static vector3_<T> x_axis() { return vector3_<T> ( { T(1), T(0), T(0) } ); }
|
||||
inline static vector3_<T> y_axis() { return vector3_<T> ( { T(0), T(1), T(0) } ); }
|
||||
|
@ -129,6 +133,7 @@ struct vector4_ : matrix_<4,1,T> {
|
|||
inline auto xyz() const { return vector3_<T>({ x(),y(),z() } ); }
|
||||
|
||||
inline auto project() const { return vector3_<T>({ x()/w(),y()/w(),z()/w() } ); }
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
@ -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<uint32_t>::max();
|
||||
}
|
||||
|
||||
sizei image::size() const
|
||||
::pw::size image::size() const
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc,char **argv) {
|
||||
int main(int ,char **) {
|
||||
|
||||
pw::vector2_<float> v2_A = { 3.2, 1.2 };
|
||||
pw::vector2_<float> 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_<float> v4;
|
||||
pw::vector3f v;
|
||||
pw::vector3f v = pw::vector3f::backward();
|
||||
|
||||
v4.fill(1.5);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
48
src/scene/include/pw/scene/components/camera.hpp
Normal file
48
src/scene/include/pw/scene/components/camera.hpp
Normal file
|
@ -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 <pw/core/matrix.hpp>
|
||||
#include <pw/core/matrix_transform.hpp>
|
||||
#include <pw/core/rectangle.hpp>
|
||||
|
||||
namespace pw {
|
||||
|
||||
struct camera {
|
||||
matrix4x4 view = matrix4x4::identity();
|
||||
matrix4x4 projection = matrix_transform<float>::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
|
166
src/scripts/demos/simple_002.lua
Normal file
166
src/scripts/demos/simple_002.lua
Normal file
|
@ -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
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
set(hdrs
|
||||
include/pw/visual/framebuffer.hpp
|
||||
include/pw/visual/shader.hpp
|
||||
include/pw/visual/pipeline.hpp
|
||||
include/pw/visual/texture.hpp
|
||||
|
@ -8,6 +9,7 @@ set(hdrs
|
|||
)
|
||||
|
||||
set(srcs
|
||||
src/framebuffer.cpp
|
||||
src/shader.cpp
|
||||
src/context.cpp
|
||||
src/pass.cpp
|
||||
|
|
27
src/visual/include/pw/visual/framebuffer.hpp
Normal file
27
src/visual/include/pw/visual/framebuffer.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef PW_VISUAL_FRAMEBUFFER_HPP
|
||||
#define PW_VISUAL_FRAMEBUFFER_HPP
|
||||
|
||||
#include <pw/core/globals.hpp>
|
||||
#include <pw/core/size.hpp>
|
||||
|
||||
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> _impl;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -19,7 +19,7 @@ public:
|
|||
|
||||
~mesh_renderer();
|
||||
|
||||
void create(const geometry &m);
|
||||
bool create(const geometry &m);
|
||||
void release();
|
||||
|
||||
void draw();
|
||||
|
|
|
@ -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<typename T>
|
||||
shader & set(std::string const & name, T&& value)
|
||||
shader & set_uniform(std::string const & name, T &&value)
|
||||
{
|
||||
int location = uniform_location(name);
|
||||
if (location >= 0)
|
||||
return set(location, std::forward<T>(value));
|
||||
else
|
||||
debug::w() << "missing uniform: '" << name << "'";
|
||||
return *this;
|
||||
return set_uniform_at_location( uniform_location(name), std::forward<T>(value) );
|
||||
}
|
||||
|
||||
bool build();
|
||||
|
|
131
src/visual/src/framebuffer.cpp
Normal file
131
src/visual/src/framebuffer.cpp
Normal file
|
@ -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<impl>();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<T, vector4f>) ||
|
||||
(std::is_same_v<T, matrix4x4f>) ||
|
||||
(std::is_same_v<T, float>) ) {
|
||||
set(loc, std::forward<T>(arg));
|
||||
set_uniform_at_location( loc, std::forward<T>(arg));
|
||||
} else {
|
||||
debug::e() << "unknown uniform type";
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue