From 075d18b4b879bbf499ee7292ffc3736f01ff1f36 Mon Sep 17 00:00:00 2001 From: Hartmut Seichter Date: Wed, 16 Jan 2019 18:52:39 +0100 Subject: [PATCH] proper blitting without texture attachment added - need to redo and refactor the stuff in pipeline --- src/core/include/pw/core/debug.hpp | 120 ++++++++++++------------ src/scripting/src/script_system.cpp | 3 +- src/scripts/demos/simple_000.lua | 14 +-- src/system/include/pw/system/window.hpp | 1 + src/system/src/window.cpp | 28 ++++-- src/visual/src/pipeline.cpp | 80 ++++++++++++---- src/visual/src/shader.cpp | 4 +- 7 files changed, 153 insertions(+), 97 deletions(-) diff --git a/src/core/include/pw/core/debug.hpp b/src/core/include/pw/core/debug.hpp index 899c133..e0923cb 100644 --- a/src/core/include/pw/core/debug.hpp +++ b/src/core/include/pw/core/debug.hpp @@ -37,90 +37,88 @@ namespace pw { class debug { public: - enum level { - none, //!< nothing will be logged, even no errors - error, //!< only errors will be logged - warning, //!< log warnings (non-critical errors) - message, //!< log messages (something to note but not an error) - notification, //!< log some more information - info, //!< log verbose information - all = 0xFF //!< log absolutely everything - }; + enum level { + none, //!< nothing will be logged, even no errors + error, //!< only errors will be logged + warning, //!< log warnings (non-critical errors) + message, //!< log messages (something to note but not an error) + notification, //!< log some more information + info, //!< log verbose information + all = 0xFF //!< log absolutely everything + }; - /** - * @brief the streaming interface for the logger - */ - class stream { - public: + /** + * @brief the streaming interface for the logger + */ + class stream { + public: - stream(debug* log = nullptr); - ~stream(); - stream(const stream& other); + stream(debug* log = nullptr); + ~stream(); + stream(const stream& other); - stream &operator << (const bool &value); - stream &operator << (const char *value); - stream& operator << (const std::string& value); ///! log a string + stream& operator << (const bool &value); + stream& operator << (const char *value); + stream& operator << (const std::string& value); ///! log a string - stream& operator << (const float &value); ///! log a float value - stream& operator << (const double &value); ///! log a double value + stream& operator << (const float &value); ///! log a float value + stream& operator << (const double &value); ///! log a double value - stream& operator << (const int &value); ///! log a int value - stream& operator << (const unsigned int &value); ///! log a int value + stream& operator << (const int &value); ///! log a int value + stream& operator << (const unsigned int &value); ///! log a int value - stream& operator << (const long &value); ///! log a long value - stream& operator << (const unsigned long &value); ///! log a int value + stream& operator << (const long &value); ///! log a long value + stream& operator << (const unsigned long &value); ///! log a int value - stream& operator << (const void *value); ///! pointer + stream& operator << (const void *value); ///! pointer - protected: + protected: - debug* _log; - std::string _line; - }; + debug* _log; + std::string _line; + }; + /** sets the logging level */ + void set_level(level level) {_level = level;} + /** gets the logging level */ + level level() const { return _level; } - /** sets the logging level */ - void set_level(level level) {_level = level;} + /** + * @brief get the stream interface of the logger + * @return return a temporary object that will write and flush the logger + */ + static stream s(enum level level = info); - /** gets the logging level */ - level level() const { return _level; } + inline static stream d() { return s(debug::info); } + inline static stream e() { return s(debug::error); } + inline static stream w() { return s(debug::warning); } - /** - * @brief get the stream interface of the logger - * @return return a temporary object that will write and flush the logger - */ - static stream s(enum level level = info); + /** + * @brief returns the instance of the logger + * @return + */ + static debug& get(); - inline static stream d() { return s(debug::info); } - inline static stream e() { return s(debug::error); } - inline static stream w() { return s(debug::warning); } + /** + * @brief write a message to the log + * @param message string + */ + void write(const std::string &message); - /** - * @brief returns the instance of the logger - * @return - */ - static debug& get(); + typedef std::function Callback; + typedef std::vector CallbackList; - /** - * @brief write a message to the log - * @param message string - */ - void write(const std::string &message); - - typedef std::function Callback; - typedef std::vector CallbackList; - - ~debug(); + ~debug(); protected: - debug(); + debug(); - CallbackList _callbacks; - enum level _level; + CallbackList _callbacks; + enum level _level; }; ///** diff --git a/src/scripting/src/script_system.cpp b/src/scripting/src/script_system.cpp index b82089c..96d81b8 100644 --- a/src/scripting/src/script_system.cpp +++ b/src/scripting/src/script_system.cpp @@ -10,13 +10,12 @@ namespace pw { void script_system::load(sol::table &ns) { - - ns.new_usertype("window", "update",&window::update, "on_update",sol::writeonly_property(&window::set_on_update), "title",sol::writeonly_property(&window::set_title), "size",sol::property(&window::size,&window::set_size), + "client_size",sol::readonly_property(&window::client_size), "position",sol::property(&window::position,&window::set_position), "fullscreen",sol::property(&window::fullscreen,&window::set_fullscreen) ); diff --git a/src/scripts/demos/simple_000.lua b/src/scripts/demos/simple_000.lua index 42c5ed3..8fea86d 100644 --- a/src/scripts/demos/simple_000.lua +++ b/src/scripts/demos/simple_000.lua @@ -70,13 +70,20 @@ local w = pw.window.new() -- set title w.title = "pixwerx 0.1" +-- set size +w.size = pw.size.new(800,600) +-- move window +w.position = pw.point.new(100,100) + + local pl = pw.pipeline.new() -if pl:create(pw.size.new(800,600)) then +if pl:create(w.client_size) then print("pipeline ok") else print("pipeline failed") end + -- setup a lua callback function w.on_update = function(self) @@ -84,11 +91,6 @@ w.on_update = function(self) -- print("test on update",w.position.x,w.position.y,pw.timer.now) end --- set size -w.size = pw.size.new(800,600) --- move window -w.position = pw.point.new(100,100) - local ds = pw.display:all() for i = 1,#ds do print("display ",i,ds[i].name) diff --git a/src/system/include/pw/system/window.hpp b/src/system/include/pw/system/window.hpp index 176bcc2..1c20213 100644 --- a/src/system/include/pw/system/window.hpp +++ b/src/system/include/pw/system/window.hpp @@ -23,6 +23,7 @@ public: void set_size(const size& s); pw::size size() const; + pw::size client_size() const; void set_position(const point& p); point position() const; diff --git a/src/system/src/window.cpp b/src/system/src/window.cpp index 4125d67..e9fea3e 100644 --- a/src/system/src/window.cpp +++ b/src/system/src/window.cpp @@ -95,6 +95,9 @@ struct window::impl { static void framebuffer_size_callback(GLFWwindow* window, int width, int height) { window::impl* impl = static_cast(glfwGetWindowUserPointer(window)); + + debug::d() << "window::frame_buffer_size_callback " << width << "x" << height; + // impl->on_resize(width,height); // std::cout << "framebuffer " << width << "x" << height << std::endl; @@ -218,9 +221,9 @@ struct window::impl { glfwSetWindowTitle(_window,title.c_str()); } - void set_size(int w,int h) + void set_size(const ::pw::sizei& s) { - glfwSetWindowSize(_window,w,h); + glfwSetWindowSize(_window,s.width,s.height); } ::pw::size size() const @@ -230,6 +233,14 @@ struct window::impl { return ::pw::size(w,h); } + + ::pw::size client_size() const + { + int w,h; + glfwGetFramebufferSize(_window,&w,&h); + return ::pw::size(w,h); + } + ::pw::point position() const { int x,y; @@ -237,9 +248,9 @@ struct window::impl { return ::pw::point(x,y); } - void set_position(int x,int y) + void set_position(const pointi& p) { - glfwSetWindowPos(_window,x,y); + glfwSetWindowPos(_window,p.x,p.y); } void set_fullscreen(bool use_fullscreen) @@ -299,7 +310,7 @@ void window::set_title(const std::string& title) void window::set_size(const ::pw::size& s) { - _impl->set_size(static_cast(std::round(s.width)),static_cast(std::round(s.height))); + _impl->set_size(s.cast()); } size window::size() const @@ -307,9 +318,14 @@ size window::size() const return _impl->size(); } +size window::client_size() const +{ + return _impl->client_size(); +} + void window::set_position(const point &p) { - _impl->set_position(p.x,p.y); + _impl->set_position(p.cast()); } point window::position() const diff --git a/src/visual/src/pipeline.cpp b/src/visual/src/pipeline.cpp index d985562..1ba3956 100644 --- a/src/visual/src/pipeline.cpp +++ b/src/visual/src/pipeline.cpp @@ -83,9 +83,6 @@ struct triangle_renderer void draw() { -// glUseProgram(shader_programme); - - shader_p.use(); glBindVertexArray(vao); // draw points 0-3 from the currently bound VAO with current in-use shader @@ -101,8 +98,8 @@ struct pipeline::impl { GLuint _fbo_draw; GLuint _fbo_msaa; - GLuint rboColorId; - GLuint rboDepthId; + GLuint _rbo_color; + GLuint _rbo_depth; //testing triangle_renderer tr; @@ -116,6 +113,18 @@ struct pipeline::impl { }; +GLuint generate_multisample_texture(const sizei& s,int samples) +{ + 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); + + return texture; +} + bool pipeline::impl::create(sizei size) { @@ -133,16 +142,14 @@ bool pipeline::impl::create(sizei size) debug::d() << "OpenGL multisampling: " << max_msaa << " choosen:" << msaa; - // msaa = std::clamp(msaa,max_msaa); - - glGenRenderbuffers(1, &rboColorId); - glBindRenderbuffer(GL_RENDERBUFFER, rboColorId); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGB8, _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 - glGenRenderbuffers(1, &rboDepthId); - glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId); + 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 @@ -153,32 +160,32 @@ bool pipeline::impl::create(sizei size) glFramebufferRenderbuffer(GL_FRAMEBUFFER, // 1. fbo target: GL_FRAMEBUFFER GL_COLOR_ATTACHMENT0, // 2. color attachment point GL_RENDERBUFFER, // 3. rbo target: GL_RENDERBUFFER - rboColorId); // 4. rbo ID + _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 - rboDepthId); // 4. rbo ID + _rbo_depth); // 4. rbo ID // check FBO status if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) return false; + // reset + glBindFramebuffer(GL_FRAMEBUFFER, 0); tr.setup(); - - return true; } void pipeline::impl::draw() { - glBindBuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo_msaa); glClearColor(1,0,0,1); glClear(GL_COLOR_BUFFER_BIT); @@ -186,11 +193,13 @@ void pipeline::impl::draw() tr.draw(); // reset - glBindBuffer(GL_DRAW_FRAMEBUFFER, 0); + // 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. */ @@ -203,7 +212,40 @@ void pipeline::impl::draw() glBlitFramebuffer (0,0, _size.width, _size.height, 0,0, _size.width, _size.height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, - GL_LINEAR); + GL_NEAREST); + +#else + + + 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 + + debug::d() << _size.width << "x" << _size.height; + +#endif + + + 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; + } + } diff --git a/src/visual/src/shader.cpp b/src/visual/src/shader.cpp index ce74226..25bed82 100644 --- a/src/visual/src/shader.cpp +++ b/src/visual/src/shader.cpp @@ -1,8 +1,6 @@ #include "pw/visual/shader.hpp" #include "pw/core/debug.hpp" - - #include "glad/glad.h" namespace pw { @@ -91,7 +89,7 @@ struct shader::impl glAttachShader(_shader_program,s); - // attribute binding ... + // TODO attribute binding ... /* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */ /* Attribute locations must be setup before calling glLinkProgram. */