Major push to get renderer separated and configurable.

Signed-off-by: Hartmut Seichter <hartmut@technotecture.com>
This commit is contained in:
Hartmut Seichter 2021-01-05 00:23:03 +01:00
parent 77e254872f
commit d2c8262c68
22 changed files with 542 additions and 97 deletions

View file

@ -7,6 +7,7 @@
#include "pw/core/time.hpp" #include "pw/core/time.hpp"
#include "pw/core/geometry.hpp" #include "pw/core/geometry.hpp"
#include "pw/core/image.hpp" #include "pw/core/image.hpp"
#include "pw/core/matrix_transform.hpp"
#include "runtime_lua.hpp" #include "runtime_lua.hpp"
@ -15,6 +16,7 @@
namespace sol { namespace sol {
template <> struct is_automagical<pw::matrix4x4> : std::false_type {}; template <> struct is_automagical<pw::matrix4x4> : std::false_type {};
template <> struct is_automagical<pw::vector3> : 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 {}; 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 ,"cross",&vector3::cross
,"transposed",&vector3::transposed ,"transposed",&vector3::transposed
,"lerp",&vector3::lerp ,"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" ns.new_usertype<quaternion>("quaternion"
,sol::constructors<quaternion(), quaternion(quaternion::value_type,quaternion::value_type,quaternion::value_type,quaternion::value_type)>() ,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;}) ,"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 , "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", ns.new_usertype<point>("point",
sol::constructors<point(),point(Scalar,Scalar)>(), 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) , "topology", sol::property(&geometry::topology,&geometry::set_topology)
, "vertices", sol::property(&geometry::vertices,&geometry::set_vertices) , "vertices", sol::property(&geometry::vertices,&geometry::set_vertices)
, "indices", sol::property(&geometry::indices,&geometry::set_indices) , "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 ,"points", geometry::topology_type::points
, "lines", geometry::topology_type::lines , "lines", geometry::topology_type::lines
, "line_strip", geometry::topology_type::line_strip , "line_strip", geometry::topology_type::line_strip
, "triangles", geometry::topology_type::triangles); , "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 // SOL3
// geoom_type["type"] = lua.create_table_with( // geoom_type["type"] = lua.create_table_with(
// "points", geometry::topology_type::points // "points", geometry::topology_type::points

View file

@ -2,6 +2,8 @@
#include "pw/core/debug.hpp" #include "pw/core/debug.hpp"
#include "pw/visual/pipeline.hpp" #include "pw/visual/pipeline.hpp"
#include "pw/visual/shader.hpp" #include "pw/visual/shader.hpp"
#include "pw/visual/framebuffer.hpp"
#include "pw/core/size.hpp"
#include "runtime_lua.hpp" #include "runtime_lua.hpp"
@ -25,6 +27,9 @@ void register_visual_function(sol::state&,sol::table &ns)
,"source",&shader::source ,"source",&shader::source
,"set_source",&shader::set_source ,"set_source",&shader::set_source
,"set_uniforms",&shader::set_uniforms ,"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" ).new_enum<false>("shader_type"
,"fragment",shader::code_type::fragment ,"fragment",shader::code_type::fragment
,"vertex",shader::code_type::vertex ,"vertex",shader::code_type::vertex
@ -40,7 +45,20 @@ void register_visual_function(sol::state&,sol::table &ns)
,"color",sol::property(&material::_color)); ,"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) PW_REGISTER_LUA(visual)

View file

@ -28,8 +28,18 @@
#include <pw/core/aabb.hpp> #include <pw/core/aabb.hpp>
#include <pw/core/resource.hpp> #include <pw/core/resource.hpp>
#include <variant>
#include <tuple>
namespace pw { 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 { class geometry {
public: public:
@ -51,6 +61,10 @@ public:
using vertex2array_t = std::vector<vector2> ; using vertex2array_t = std::vector<vector2> ;
using vertex3array_t = std::vector<vector3> ; 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() = default;
geometry(topology_type t); geometry(topology_type t);

View file

@ -43,9 +43,9 @@ public:
HDR 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); void release(bool release_memory = false);
@ -65,11 +65,11 @@ public:
typedef shared_ptr<image> ptr; typedef shared_ptr<image> ptr;
sizei size() const; ::pw::size size() const;
protected: protected:
sizei _size; ::pw::size _size;
pixel_layout _layout; pixel_layout _layout;
uint64_t _change_count; uint64_t _change_count;

View file

@ -32,7 +32,9 @@ class resource {
public: public:
using change_t = std::atomic_int_fast64_t; using change_t = std::atomic_int_fast64_t;
int64_t changecount() { return _changecount; } resource() = default;
int64_t changecount() const { return _changecount; }
void dirty() { ++_changecount; }; void dirty() { ++_changecount; };
protected: protected:

View file

@ -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> sizef;
typedef size_<float> sized; typedef size_<double> sized;
} }

View file

@ -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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

View file

@ -27,6 +27,10 @@
namespace pw { namespace pw {
/**
* Basic vector types used in pixwerx.
*/
template <typename T> template <typename T>
struct vector2_ : matrix_<2,1,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 constexpr 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 constexpr 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 constexpr 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 constexpr 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 constexpr 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> 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> 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) } ); } 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 xyz() const { return vector3_<T>({ x(),y(),z() } ); }
inline auto project() const { return vector3_<T>({ x()/w(),y()/w(),z()/w() } ); } inline auto project() const { return vector3_<T>({ x()/w(),y()/w(),z()/w() } ); }
}; };
// //

View file

@ -4,12 +4,12 @@
namespace pw { 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); 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(); 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 { } else {
_data.resize(n); _data.resize(n);
_size = sizei(0,0); _size = ::pw::size(0,0);
} }
return !_data.empty(); return !_data.empty();
@ -53,7 +53,7 @@ uint32_t image::bytes_per_pixel(image::pixel_layout t)
return std::numeric_limits<uint32_t>::max(); return std::numeric_limits<uint32_t>::max();
} }
sizei image::size() const ::pw::size image::size() const
{ {
return _size; return _size;
} }

View file

@ -4,7 +4,7 @@
#include <iostream> #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_A = { 3.2, 1.2 };
pw::vector2_<float> v2_B = { 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); auto AB_lerp = pw::vector2f::lerp(v2_A,v2_B,0.5);
pw::vector4_<float> v4; pw::vector4_<float> v4;
pw::vector3f v; pw::vector3f v = pw::vector3f::backward();
v4.fill(1.5); v4.fill(1.5);

View file

@ -24,7 +24,7 @@ struct image_io::impl
image r; 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); stbi_image_free(data);

View 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

View 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

View file

@ -43,7 +43,7 @@ struct window::impl {
GLFWwindow *_window = nullptr; GLFWwindow *_window = nullptr;
sizei _old_size; ::pw::size _old_size;
pointi _old_pos; pointi _old_pos;
// window_context _context; // window_context _context;
@ -233,7 +233,7 @@ struct window::impl {
glfwSetWindowTitle(_window,title.c_str()); 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); glfwSetWindowSize(_window,s.width,s.height);
} }

View file

@ -1,5 +1,6 @@
set(hdrs set(hdrs
include/pw/visual/framebuffer.hpp
include/pw/visual/shader.hpp include/pw/visual/shader.hpp
include/pw/visual/pipeline.hpp include/pw/visual/pipeline.hpp
include/pw/visual/texture.hpp include/pw/visual/texture.hpp
@ -8,6 +9,7 @@ set(hdrs
) )
set(srcs set(srcs
src/framebuffer.cpp
src/shader.cpp src/shader.cpp
src/context.cpp src/context.cpp
src/pass.cpp src/pass.cpp

View 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

View file

@ -19,7 +19,7 @@ public:
~mesh_renderer(); ~mesh_renderer();
void create(const geometry &m); bool create(const geometry &m);
void release(); void release();
void draw(); void draw();

View file

@ -24,26 +24,36 @@ public:
compute 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]; } std::string source(code_type t) { return _source[t]; }
bool ready() const; bool ready() const;
shader& set(int location,float v); shader& set_uniform_at_location(int location,float v);
shader& set(int location,matrix4x4f const & v); shader& set_uniform_at_location(int location,matrix4x4f const &v);
shader& set(int location,vector4f 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; 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> 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); return set_uniform_at_location( uniform_location(name), std::forward<T>(value) );
if (location >= 0)
return set(location, std::forward<T>(value));
else
debug::w() << "missing uniform: '" << name << "'";
return *this;
} }
bool build(); bool build();

View 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();
}
}

View file

@ -28,10 +28,10 @@ struct mesh_renderer::impl {
bool ready() const 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 // reset if the renderer already in use
if (ready()) { if (ready()) {
@ -81,6 +81,8 @@ struct mesh_renderer::impl {
if (error != GL_NO_ERROR) { if (error != GL_NO_ERROR) {
debug::e() << "GL error: " << error; debug::e() << "GL error: " << error;
} }
return ready();
} }
@ -135,9 +137,9 @@ bool mesh_renderer::ready() const
return _impl->ready(); 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() void mesh_renderer::release()

View file

@ -132,8 +132,8 @@ struct triangle_renderer
frag_colour = input_color; frag_colour = input_color;
})"; })";
shader_p.set_source(vertex_shader_2,shader::code_type::vertex); shader_p.set_source(shader::code_type::vertex,vertex_shader_2);
shader_p.set_source(fragment_shader_2,shader::code_type::fragment); shader_p.set_source(shader::code_type::fragment,fragment_shader_2);
if (!shader_p.build()) if (!shader_p.build())
exit(-1); exit(-1);
@ -220,7 +220,7 @@ struct triangle_renderer
struct pipeline::impl { struct pipeline::impl {
sizei _size; size _size;
GLuint _fbo_draw; GLuint _fbo_draw;
GLuint _fbo_msaa; GLuint _fbo_msaa;
@ -231,7 +231,7 @@ struct pipeline::impl {
//testing //testing
triangle_renderer tr; triangle_renderer tr;
bool create(sizei size); bool create(size s);
void draw(); 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; GLuint texture;
glGenTextures(1, &texture); glGenTextures(1, &texture);
@ -252,10 +252,10 @@ GLuint generate_multisample_texture(const sizei& s,int samples)
return texture; return texture;
} }
bool pipeline::impl::create(sizei size) bool pipeline::impl::create(::pw::size s)
{ {
_size = size; _size = s;
int max_msaa; int max_msaa;
@ -309,10 +309,12 @@ bool pipeline::impl::create(sizei size)
return true; return true;
} }
void pipeline::impl::draw() void pipeline::impl::draw()
{ {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_msaa);
// glClearColor(1.0,0,0,1); // glClearColor(1.0,0,0,1);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

View file

@ -31,7 +31,7 @@ struct shader::impl
bool build() bool build()
{ {
if (!is_valid()) return false; // if (!is_valid()) return false;
for (const auto & [type,code] : _shader._source) for (const auto & [type,code] : _shader._source)
{ {
@ -180,6 +180,7 @@ shader::shader()
shader::~shader() shader::~shader()
{ {
} }
bool shader::ready() const bool shader::ready() const
@ -187,17 +188,17 @@ bool shader::ready() const
return _impl->is_valid(); 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; _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; _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; _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>) || if constexpr ((std::is_same_v<T, vector4f>) ||
(std::is_same_v<T, matrix4x4f>) || (std::is_same_v<T, matrix4x4f>) ||
(std::is_same_v<T, float>) ) { (std::is_same_v<T, float>) ) {
set(loc, std::forward<T>(arg)); set_uniform_at_location( loc, std::forward<T>(arg));
} else { } else {
debug::e() << "unknown uniform type"; debug::e() << "unknown uniform type";
} }