diff --git a/src/binding/src/script_visual.cpp b/src/binding/src/script_visual.cpp index 2caf618..b21d261 100644 --- a/src/binding/src/script_visual.cpp +++ b/src/binding/src/script_visual.cpp @@ -45,12 +45,12 @@ void register_visual_function(sol::state&,sol::table &ns) ,"color",sol::property(&material::_color)); - 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("mesh_renderer" + ,sol::constructors() + ,"create",&renderer::create + ,"ready",sol::readonly_property(&renderer::ready) + ,"release",&renderer::release + ,"draw",&renderer::draw ); ns.new_usertype("framebuffer" diff --git a/src/scene/src/scene.cpp b/src/scene/src/scene.cpp index eeed05d..d572f14 100644 --- a/src/scene/src/scene.cpp +++ b/src/scene/src/scene.cpp @@ -14,7 +14,7 @@ struct mesh { geometry geom; }; -struct mesh_renderer { +struct renderer { std::unique_ptr state; // std::vector mat; }; diff --git a/src/scripts/demos/simple_000.lua b/src/scripts/demos/simple_000.lua index 0e5c9da..98af6cf 100644 --- a/src/scripts/demos/simple_000.lua +++ b/src/scripts/demos/simple_000.lua @@ -66,10 +66,6 @@ while w:update() do t:reset() print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y,w.client_size.width,w.client_size.height) end --- print("update") - - end ---local scene = pw:scene.new() diff --git a/src/scripts/demos/simple_002.lua b/src/scripts/demos/simple_002.lua index 6abc829..99794ca 100644 --- a/src/scripts/demos/simple_002.lua +++ b/src/scripts/demos/simple_002.lua @@ -1,16 +1,14 @@ -- --- small demonstrator for Lua binding on pixwerx +-- 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" +w.title = "My Cool 3D Content" -- set size w.size = pw.size.new(640,480) @@ -18,26 +16,24 @@ w.size = pw.size.new(640,480) -- move window w.position = pw.point.new(100,100) - +-- create a new geometry 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 +z = 1.0 +g.vertices:add(pw.vector3:new(-1, 1, z)) -- 0 +g.vertices:add(pw.vector3:new(-1,-1, z)) -- 1 +g.vertices:add(pw.vector3:new( 1,-1, z)) -- 2 +g.vertices:add(pw.vector3:new( 1, 1, z)) -- 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) @@ -46,32 +42,15 @@ 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 @@ -95,24 +74,41 @@ void main() { } ]]) -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 +-- setup a lua callback function as callback +w.on_update = function(self) + + 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, 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) + + renderer:draw() + +end + +w.visible = true while w:update() do - -- somehow works if (pw.input.get().input_string == 'f') then w.fullscreen = not w.fullscreen @@ -131,36 +127,4 @@ while w:update() do 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/include/pw/system/window.hpp b/src/system/include/pw/system/window.hpp index 1d4c0a6..926ec53 100644 --- a/src/system/include/pw/system/window.hpp +++ b/src/system/include/pw/system/window.hpp @@ -44,6 +44,7 @@ protected: on_update_t _on_update; + }; } diff --git a/src/system/src/window.cpp b/src/system/src/window.cpp index 0df6e04..89230ac 100644 --- a/src/system/src/window.cpp +++ b/src/system/src/window.cpp @@ -152,11 +152,15 @@ struct window::impl { glfwGetVersion(&glfw_major,&glfx_minor,&glfw_rev); - debug::d() << "GLFW " << glfw_major << "." << glfx_minor << "." << glfw_rev; - debug::d() << "GLFW header " << GLFW_VERSION_MAJOR << "." << GLFW_VERSION_MINOR << "." << GLFW_VERSION_REVISION; +// debug::d() << "GLFW " << glfw_major << "." << glfx_minor << "." << glfw_rev; +// debug::d() << "GLFW header " << GLFW_VERSION_MAJOR << "." << GLFW_VERSION_MINOR << "." << GLFW_VERSION_REVISION; update_display_list(); + // we default to window invisible by default + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + + // OpenGL // request specific version 3.3 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); @@ -182,7 +186,7 @@ struct window::impl { rev = glfwGetWindowAttrib(_window, GLFW_CONTEXT_REVISION); // maybe something to pass to the outside - debug::d() << "OpenGL " << major << "." << minor << "." << rev; +// debug::d() << "OpenGL " << major << "." << minor << "." << rev; glfwSetWindowUserPointer(_window,this); @@ -213,6 +217,7 @@ struct window::impl { { if (_window && !glfwWindowShouldClose(_window)) { + // TODO lock an unlock the current input system to allow for late events coming in input::get().reset(); // get new events diff --git a/src/visual/CMakeLists.txt b/src/visual/CMakeLists.txt index e82f97e..f4c98af 100644 --- a/src/visual/CMakeLists.txt +++ b/src/visual/CMakeLists.txt @@ -4,7 +4,7 @@ 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/renderer.hpp include/pw/visual/material.hpp ) @@ -16,7 +16,7 @@ set(srcs src/pipeline.cpp src/target.cpp src/texture.cpp - src/mesh_renderer.cpp + src/renderer.cpp src/material.cpp ) diff --git a/src/visual/include/pw/visual/pipeline.hpp b/src/visual/include/pw/visual/pipeline.hpp index 3a5f17f..2069d5d 100644 --- a/src/visual/include/pw/visual/pipeline.hpp +++ b/src/visual/include/pw/visual/pipeline.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include @@ -45,7 +45,7 @@ struct render_pass { const material& mat); shader _shader; - mesh_renderer _renderer; + renderer _renderer; }; diff --git a/src/visual/include/pw/visual/mesh_renderer.hpp b/src/visual/include/pw/visual/renderer.hpp similarity index 78% rename from src/visual/include/pw/visual/mesh_renderer.hpp rename to src/visual/include/pw/visual/renderer.hpp index 751b4d3..acf7282 100644 --- a/src/visual/include/pw/visual/mesh_renderer.hpp +++ b/src/visual/include/pw/visual/renderer.hpp @@ -12,12 +12,12 @@ class geometry; /** * @brief Connects mesh data with the render backend */ -class mesh_renderer { +class renderer { public: - mesh_renderer(); - mesh_renderer(const geometry& m); + renderer(); + renderer(const geometry& m); - ~mesh_renderer(); + ~renderer(); bool create(const geometry &m); void release(); diff --git a/src/visual/src/framebuffer.cpp b/src/visual/src/framebuffer.cpp index fe929fa..878bd00 100644 --- a/src/visual/src/framebuffer.cpp +++ b/src/visual/src/framebuffer.cpp @@ -7,27 +7,28 @@ namespace pw { +// TODO stencil buffer? + struct framebuffer::impl { size _size; - GLuint _fbo_draw; - GLuint _fbo_msaa; + GLuint _fbo_draw { std::numeric_limits::max() }; + GLuint _fbo_msaa { std::numeric_limits::max() }; - GLuint _rbo_color; - GLuint _rbo_depth; + GLuint _rbo_color { std::numeric_limits::max() }; + GLuint _rbo_depth { std::numeric_limits::max() }; bool create(const size &s) { - + // TODO mak color resolution and _size = s; - int max_msaa; + int max_msaa { 0 }; // 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); @@ -39,13 +40,13 @@ struct framebuffer::impl { glBindRenderbuffer(GL_RENDERBUFFER, _rbo_color); glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGBA8, _size.width, _size.height); - // create a 4x MSAA renderbuffer object for depthbuffer + // create a 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 + // create a MSAA framebuffer object glGenFramebuffers(1, &_fbo_msaa); glBindFramebuffer(GL_FRAMEBUFFER, _fbo_msaa); @@ -71,16 +72,16 @@ struct framebuffer::impl { } - void bind() { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_msaa); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw); } void blit() { - glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo_msaa); // src FBO (multi-sample) - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw); // dst FBO (single-sample) +// 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 @@ -91,10 +92,7 @@ struct framebuffer::impl { void unbind() { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - } }; diff --git a/src/visual/src/mesh_renderer.cpp b/src/visual/src/mesh_renderer.cpp deleted file mode 100644 index 8b138e4..0000000 --- a/src/visual/src/mesh_renderer.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include "pw/visual/mesh_renderer.hpp" - -#include "pw/core/geometry.hpp" -#include "pw/core/size.hpp" -#include "pw/core/debug.hpp" - -#include "glad/glad.h" - -#include - - -namespace pw { - -struct mesh_renderer::impl { - - GLuint _vao = 0; - std::vector _vbos; - GLint _mesh_elements = {0}; - - impl() - { - } - - ~impl() - { - release(); - } - - bool ready() const - { - return glIsVertexArray != nullptr && GL_TRUE == glIsVertexArray(_vao); - } - - bool create(const geometry& m) - { - // reset if the renderer already in use - if (ready()) { - release(); - } - - glGenVertexArrays(1,&_vao); - - - glBindVertexArray(_vao); - - size_t arrays_needed = 0; - - // should bail out here - if (!m.vertices().empty()) arrays_needed++; - if (!m.indices().empty()) arrays_needed++; - - - _mesh_elements = m.indices().size(); - - // TODO: implement the other arrays - - _vbos.resize(arrays_needed); - - glGenBuffers(_vbos.size(), _vbos.data()); - - // vertices - glBindBuffer(GL_ARRAY_BUFFER, _vbos[0]); - glBufferData(GL_ARRAY_BUFFER, - sizeof(m.vertices().front()) * m.vertices().size(), - m.vertices().data(), - GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - // indices - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbos[1]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, - sizeof(m.indices().front()) * m.indices().size(), m.indices().data(), - GL_STATIC_DRAW); - - // stop binding - glBindVertexArray(0); - - auto error = glGetError(); - if (error != GL_NO_ERROR) { - debug::e() << "GL error: " << error; - } - - return ready(); - } - - - void release() - { - glDeleteVertexArrays(1,&_vao); - for (auto vbo : _vbos) - glDeleteBuffers(1,&vbo); - - _vbos.clear(); - } - - void draw() - { - if (glIsVertexArray(_vao)) { - glBindVertexArray(_vao); - glDrawElements(GL_TRIANGLES, _mesh_elements, GL_UNSIGNED_INT, nullptr); - glBindVertexArray(0); - - auto error = glGetError(); - if (error != GL_NO_ERROR) { - debug::e() << "GL error: " << error; - } - } - } - -// GLint get_mode(vertex_array::) - -}; - -// -// -// - -mesh_renderer::mesh_renderer() - : _impl(std::make_unique()) -{ -} - -mesh_renderer::mesh_renderer(const geometry &m) -{ - mesh_renderer(); - _impl->create(m); -} - -mesh_renderer::~mesh_renderer() -{ -} - -bool mesh_renderer::ready() const -{ - return _impl->ready(); -} - -bool mesh_renderer::create(const geometry &m) -{ - return _impl->create(m); -} - -void mesh_renderer::release() -{ - _impl->release(); -} - -void mesh_renderer::draw() -{ - _impl->draw(); -} - - -} diff --git a/src/visual/src/pass.cpp b/src/visual/src/pass.cpp index 098ca25..fdc0096 100644 --- a/src/visual/src/pass.cpp +++ b/src/visual/src/pass.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include namespace pw { diff --git a/src/visual/src/pipeline.cpp b/src/visual/src/pipeline.cpp index 977db1b..8c8174c 100644 --- a/src/visual/src/pipeline.cpp +++ b/src/visual/src/pipeline.cpp @@ -9,38 +9,20 @@ #include "pw/core/debug.hpp" #include "pw/visual/pipeline.hpp" #include "pw/visual/shader.hpp" -#include "pw/visual/mesh_renderer.hpp" +#include "pw/visual/renderer.hpp" #include "pw/visual/material.hpp" +#include "pw/visual/framebuffer.hpp" #include "glad/glad.h" namespace pw { -class command { - -}; - - -class mesh_command : command { - - // shader - // vertexarray - -}; - -class queue { - - // vector ... -}; - - - void render_pass::submit(const geometry &g, - const matrix4x4 &model_mat, - const matrix4x4 &view_mat, - const matrix4x4 &projection_mat, - const material &mat) + const matrix4x4 &model_mat, + const matrix4x4 &view_mat, + const matrix4x4 &projection_mat, + const material &mat) { if (!_shader.ready()) { // @@ -71,46 +53,46 @@ struct triangle_renderer { - shader shader_p; - geometry amesh; - mesh_renderer renderer; - time::tick_t tick; + shader shader_p; + geometry amesh; + renderer r; + time::tick_t tick; - triangle_renderer() - { - } + triangle_renderer() + { + } - void setup() - { + void setup() + { - const float z_val = -5.f; - const float s = 1.0f; + const float z_val = -5.f; + const float s = 1.0f; - // - // 0 -- 1 - // | / | - // 2 -- 3 + // + // 0 -- 1 + // | / | + // 2 -- 3 - // geometry - geometry::vertex3array_t vertices = { - {-s, s, z_val} // 0 - ,{ s, s, z_val} // 1 - ,{-s, -s, z_val} // 2 - ,{ s, -s, z_val} // 3 - }; + // geometry + geometry::vertex3array_t vertices = { + {-s, s, z_val} // 0 + ,{ s, s, z_val} // 1 + ,{-s, -s, z_val} // 2 + ,{ s, -s, z_val} // 3 + }; - // topology / indices - geometry::indexarray_t indices = { 2, 1, 0, - 2, 3, 1}; + // topology / indices + geometry::indexarray_t indices = { 2, 1, 0, + 2, 3, 1}; - amesh.set_indices(indices); - amesh.set_vertices(vertices); + amesh.set_indices(indices); + amesh.set_vertices(vertices); - amesh.compute_normals(); + amesh.compute_normals(); - const char* vertex_shader_2 = R"( + const char* vertex_shader_2 = R"( #version 400 uniform mat4 model; uniform mat4 view; @@ -124,7 +106,7 @@ struct triangle_renderer } )"; - const char *fragment_shader_2 = R"( + const char *fragment_shader_2 = R"( #version 400 uniform vec4 input_color = vec4(1.0, 0.0, 0.0, 1.0); out vec4 frag_colour; @@ -135,178 +117,188 @@ struct triangle_renderer 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); - } + if (!shader_p.build()) + exit(-1); + } - void draw() - { - if (!renderer.ready()) - renderer.create(amesh); + void draw() + { + if (!r.ready()) + r.create(amesh); - // input needed here - - // model view projection + // input needed here - + // model view projection - shader_p.use(); + shader_p.use(); - auto v_col = ping_pong(static_cast(time::now()),1.0f); + auto v_col = ping_pong(static_cast(time::now()),1.0f); - vector4f col({0.5f,1-v_col,v_col,1.0f}); + vector4f col = {0.5f,1-v_col,v_col,1.0f}; - matrix4x4f model_mat; model_mat.set_identity(); + matrix4x4f model_mat; model_mat.set_identity(); - auto v_angle = ping_pong(static_cast(time::now()),2 * ::pw::pi()); + auto v_angle = ping_pong(static_cast(time::now()),2 * ::pw::pi()); - axisangle rot(vector3::forward(),v_angle); - model_mat = rot.to_matrix(); + axisangle rot(vector3::forward(),v_angle); + model_mat = rot.to_matrix(); - matrix4x4f view_mat = matrix_transform::look_at(vector3({0,0,0}), - vector3::forward(), - vector3::up()); + matrix4x4f view_mat = matrix_transform::look_at(vector3({0,0,0}), + vector3::forward(), + vector3::up()); - // materials should carry this + // materials should carry this #if 1 - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); #endif - // now bind textures + // now bind textures #if 1 - auto proj_mat = matrix_transform::orthographic_projection(1.3,1.0, - 0.2f,100.f); + auto proj_mat = matrix_transform::orthographic_projection(1.3,1.0, + 0.2f,100.f); #else - auto proj_mat = matrix_transform::perspective_projection(deg_to_rad(60.f), - 1.3f, - 0.2f,1000.f); + auto proj_mat = matrix_transform::perspective_projection(deg_to_rad(60.f), + 1.3f, + 0.2f,1000.f); #endif -#if 0 - // highly inefficient - should be cached - - shader_p.set("input_color",col); - shader_p.set("model",model_mat); - shader_p.set("view",view_mat); - shader_p.set("projection",proj_mat); +#if 1 + // highly inefficient - should be cached - + shader_p.set_uniform("input_color",col); + shader_p.set_uniform("model",model_mat); + shader_p.set_uniform("view",view_mat); + shader_p.set_uniform("projection",proj_mat); #else - // new version with ... - shader::uniform_cache_t us; - us.push_back(std::make_tuple("input_color",col,-1)); - us.push_back(std::make_tuple("model",model_mat,-1)); - us.push_back(std::make_tuple("view",view_mat,-1)); - us.push_back(std::make_tuple("projection",proj_mat,-1)); + // new version with ... + shader::uniform_cache_t us; + us.push_back(std::make_tuple("input_color",col,-1)); + us.push_back(std::make_tuple("model",model_mat,-1)); + us.push_back(std::make_tuple("view",view_mat,-1)); + us.push_back(std::make_tuple("projection",proj_mat,-1)); - shader_p.set_uniforms(us); + shader_p.set_uniforms(us); #endif - renderer.draw(); + r.draw(); auto error = glGetError(); if (error != GL_NO_ERROR){ debug::e() << "GL error " << error; } - // debug::d() << 100 * (timer::now() - t0) << "ms"; - } + // debug::d() << 100 * (timer::now() - t0) << "ms"; + } }; struct pipeline::impl { +#if 0 size _size; - GLuint _fbo_draw; - GLuint _fbo_msaa; + GLuint _fbo_draw; + GLuint _fbo_msaa; - GLuint _rbo_color; - GLuint _rbo_depth; + GLuint _rbo_color; + GLuint _rbo_depth; +#endif - //testing - triangle_renderer tr; + framebuffer fb; + + + //testing + triangle_renderer tr; bool create(size s); - void draw(); + void draw(); - impl() = default; - ~impl() = default; + + + impl() = default; + ~impl() = default; }; GLuint generate_multisample_texture(const size& s,int samples) { - GLuint texture; - glGenTextures(1, &texture); + GLuint texture; + glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture); - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB8, s.width, s.height, GL_TRUE); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB8, s.width, s.height, GL_TRUE); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - return texture; + return texture; } bool pipeline::impl::create(::pw::size s) { +#if 0 _size = s; - int max_msaa; + int max_msaa; - // query actual maximum MSAA - glGetIntegerv(GL_MAX_SAMPLES,&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); + // 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() << "OpenGL multisampling: " << max_msaa << " choosen:" << msaa; - glGenRenderbuffers(1, &_rbo_color); - glBindRenderbuffer(GL_RENDERBUFFER, _rbo_color); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGBA8, _size.width, _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 + // 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); + 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); + // 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 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 + // 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; + // check FBO status + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + return false; - // reset - glBindFramebuffer(GL_FRAMEBUFFER, 0); + // reset + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif - tr.setup(); + + tr.setup(); - return true; + return true; } @@ -316,75 +308,84 @@ void pipeline::impl::draw() { -// glClearColor(1.0,0,0,1); -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -// glViewport(0,0,800,600); + glClearColor(1.0,0,0,1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // - // draw pass - // + // glViewport(0,0,800,600); - tr.draw(); + // + // draw pass + // + + tr.draw(); - // reset + // reset - // actuall blitting + // actuall blitting #if 0 - /* We are going to blit into the window (default framebuffer) */ - glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); - glDrawBuffer (GL_BACK); /* Use backbuffer as color dst. */ + /* We are going to blit into the window (default framebuffer) */ + glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); + glDrawBuffer (GL_BACK); /* Use backbuffer as color dst. */ - /* Read from your FBO */ - glBindFramebuffer (GL_READ_FRAMEBUFFER, _fbo_draw ); - glReadBuffer (GL_COLOR_ATTACHMENT0); /* Use Color Attachment 0 as color src. */ + /* Read from your FBO */ + glBindFramebuffer (GL_READ_FRAMEBUFFER, _fbo_draw ); + glReadBuffer (GL_COLOR_ATTACHMENT0); /* Use Color Attachment 0 as color src. */ - /* Copy the color and depth buffer from your FBO to the default framebuffer */ - glBlitFramebuffer (0,0, _size.width, _size.height, - 0,0, _size.width, _size.height, - GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, - GL_NEAREST); + /* Copy the color and depth buffer from your FBO to the default framebuffer */ + glBlitFramebuffer (0,0, _size.width, _size.height, + 0,0, _size.width, _size.height, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, + GL_NEAREST); #else - glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo_msaa); // src FBO (multi-sample) - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw); // dst FBO (single-sample) +#if 0 - 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 + glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo_msaa); // src FBO (multi-sample) + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw); // dst FBO (single-sample) - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + 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 - // debug::d() << _size.width << "x" << _size.height; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + // debug::d() << _size.width << "x" << _size.height; +#endif #endif + // fb.bind(); - GLenum err; - while((err = glGetError()) != GL_NO_ERROR) - { - std::string error; + // fb.blit(); - switch(err) { - case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break; - case GL_INVALID_ENUM: error="INVALID_ENUM"; break; - case GL_INVALID_VALUE: error="INVALID_VALUE"; break; - case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break; - case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break; - } + // fb.unbind(); - debug::e() << "OpenGL error:" << err << " " << error; - } + GLenum err; + while((err = glGetError()) != GL_NO_ERROR) + { + std::string error; + + switch(err) { + case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break; + case GL_INVALID_ENUM: error="INVALID_ENUM"; break; + case GL_INVALID_VALUE: error="INVALID_VALUE"; break; + case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break; + case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break; + } + + debug::e() << "OpenGL error:" << err << " " << error; + } } @@ -394,23 +395,23 @@ void pipeline::impl::draw() // pipeline::pipeline() - : _impl(std::make_unique()) + : _impl(std::make_unique()) { } pipeline::~pipeline() { - // + // } void pipeline::draw() { - _impl->draw(); + _impl->draw(); } bool pipeline::create(size s) { - return _impl->create(s.cast()); + return _impl->create(s.cast()); } } diff --git a/src/visual/src/renderer.cpp b/src/visual/src/renderer.cpp new file mode 100644 index 0000000..49403e8 --- /dev/null +++ b/src/visual/src/renderer.cpp @@ -0,0 +1,165 @@ +#include "pw/visual/renderer.hpp" + +#include "pw/core/geometry.hpp" +#include "pw/core/size.hpp" +#include "pw/core/debug.hpp" + +#include "glad/glad.h" + +#include + + +namespace pw { + +struct renderer::impl { + + GLuint _vao = 0; + std::vector _vbos; + GLint _mesh_elements = { 0 }; + + impl() = default; + + ~impl() + { + release(); + } + + bool ready() const + { + return glIsVertexArray != nullptr && GL_TRUE == glIsVertexArray(_vao); + } + + bool create(const geometry& m) + { + // reset if the renderer already in use + if (ready()) { + release(); + } + + glGenVertexArrays(1,&_vao); + // TODO check if valid? + glBindVertexArray(_vao); + + size_t arrays_needed = 0; + + // should bail out here + if (!m.vertices().empty()) arrays_needed++; + if (!m.indices().empty()) arrays_needed++; + + + _mesh_elements = m.indices().size(); + + // TODO: implement the other arrays + + _vbos.resize(arrays_needed); + + glGenBuffers(_vbos.size(), _vbos.data()); + + // vertices + glBindBuffer(GL_ARRAY_BUFFER, _vbos[0]); + glBufferData(GL_ARRAY_BUFFER, + sizeof(m.vertices().front()) * m.vertices().size(), + m.vertices().data(), + GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + + // indices + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbos[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + sizeof(m.indices().front()) * m.indices().size(), m.indices().data(), + GL_STATIC_DRAW); + + // stop binding + glBindVertexArray(0); + + auto error = glGetError(); + if (error != GL_NO_ERROR) { + debug::e() << "GL error: " << error; + } + + return ready(); + } + + + void release() + { + glDeleteVertexArrays(1,&_vao); + for (auto vbo : _vbos) + glDeleteBuffers(1,&vbo); + + _vbos.clear(); + } + + void draw() + { +#if 1 + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glFrontFace(GL_CCW); +#endif + + glClearColor(0.0,1.0,0,1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (glIsVertexArray(_vao)) + { + + glBindVertexArray(_vao); + glDrawElements(GL_TRIANGLES, _mesh_elements, GL_UNSIGNED_INT, nullptr); + glBindVertexArray(0); + + auto error = glGetError(); + if (error != GL_NO_ERROR) + { + debug::e() << "GL error: " << error; + } + } + } + + // GLint get_mode(vertex_array::) + +}; + +// +// +// + +renderer::renderer() + : _impl(std::make_unique()) +{ +} + +renderer::renderer(const geometry &m) +{ + renderer(); + _impl->create(m); +} + +renderer::~renderer() +{ +} + +bool renderer::ready() const +{ + return _impl->ready(); +} + +bool renderer::create(const geometry &m) +{ + return _impl->create(m); +} + +void renderer::release() +{ + _impl->release(); +} + +void renderer::draw() +{ + _impl->draw(); +} + + +}