From 351d29cd5478a633c8d15a3cfe92cd391663d71d Mon Sep 17 00:00:00 2001 From: Hartmut Seichter Date: Wed, 16 Jan 2019 16:55:37 +0100 Subject: [PATCH] the usual triangle test with the shader pipeline --- src/scripting/CMakeLists.txt | 2 +- src/scripting/src/script.cpp | 2 + src/scripting/src/script_system.cpp | 53 ++---- src/scripting/src/script_visual.cpp | 18 ++ src/scripting/src/script_visual.hpp | 17 ++ src/scripts/demos/simple_000.lua | 23 ++- src/system/src/window.cpp | 4 +- src/visual/include/pw/visual/shader.hpp | 7 +- src/visual/src/pipeline.cpp | 226 ++++++++++++++++++------ src/visual/src/shader.cpp | 16 +- 10 files changed, 263 insertions(+), 105 deletions(-) diff --git a/src/scripting/CMakeLists.txt b/src/scripting/CMakeLists.txt index 9b86114..783a2ae 100644 --- a/src/scripting/CMakeLists.txt +++ b/src/scripting/CMakeLists.txt @@ -32,4 +32,4 @@ target_include_directories( include ) -target_link_libraries(pwscripting lualib pwcore pwsystem pwscene) +target_link_libraries(pwscripting lualib pwcore pwsystem pwscene pwvisual) diff --git a/src/scripting/src/script.cpp b/src/scripting/src/script.cpp index d141164..c48ff00 100644 --- a/src/scripting/src/script.cpp +++ b/src/scripting/src/script.cpp @@ -5,6 +5,7 @@ #include "script_core.hpp" #include "script_system.hpp" #include "script_scene.hpp" +#include "script_visual.hpp" namespace pw { @@ -46,6 +47,7 @@ void lua_state::load_modules() { script_core::load(_namespace); script_system::load(_namespace); script_scene::load(_namespace); + script_visual::load(_namespace); } diff --git a/src/scripting/src/script_system.cpp b/src/scripting/src/script_system.cpp index 25a309e..b82089c 100644 --- a/src/scripting/src/script_system.cpp +++ b/src/scripting/src/script_system.cpp @@ -6,27 +6,8 @@ #include "pw/core/debug.hpp" -// hijacking -//#include "pw/visual/pipeline.hpp" - namespace pw { -#if defined(__clang) -struct window_lua : public window { - // overridable function - sol::function lua_update; - - window_lua(sol::this_state L) - // default is an empty callback - : lua_update(sol::make_reference(L.lua_state(), [](){})) - { - // set this internal callback of the window to the lua callback - _on_update = [this](window&){this->lua_update();}; - } -}; -#endif - - void script_system::load(sol::table &ns) { @@ -41,30 +22,20 @@ void script_system::load(sol::table &ns) ); - ns.new_usertype("input", - "new", sol::no_constructor, - "get",&input::get, - "mouse_position",sol::readonly_property(&input::mouse_position), - "mouse_button",sol::readonly_property(&input::mouse_button), - "mouse_pressed",sol::readonly_property(&input::mouse_pressed), - "input_string",sol::readonly_property(&input::input_string) - ); + ns.new_usertype("input", + "new", sol::no_constructor, + "get",&input::get, + "mouse_position",sol::readonly_property(&input::mouse_position), + "mouse_button",sol::readonly_property(&input::mouse_button), + "mouse_pressed",sol::readonly_property(&input::mouse_pressed), + "input_string",sol::readonly_property(&input::input_string) + ); - ns.new_usertype("display", - "all",&display::all, - "name",sol::readonly_property(&display::name) - ); + ns.new_usertype("display", + "all",&display::all, + "name",sol::readonly_property(&display::name) + ); - - // ns.set_function("my_class_func_2", &my_class::func); - - - // - // // hijack part - // // - // ns.new_usertype("pipeline", - // "create",&pipeline::create - // ); } } diff --git a/src/scripting/src/script_visual.cpp b/src/scripting/src/script_visual.cpp index e69de29..57e3ef4 100644 --- a/src/scripting/src/script_visual.cpp +++ b/src/scripting/src/script_visual.cpp @@ -0,0 +1,18 @@ +#include "script_visual.hpp" + +#include "pw/core/debug.hpp" +#include "pw/visual/pipeline.hpp" + +namespace pw { + +void script_visual::load(sol::table &ns) +{ + + ns.new_usertype("pipeline", + "create",&pipeline::create, + "draw",&pipeline::draw + ); + +} + +} diff --git a/src/scripting/src/script_visual.hpp b/src/scripting/src/script_visual.hpp index e69de29..c720209 100644 --- a/src/scripting/src/script_visual.hpp +++ b/src/scripting/src/script_visual.hpp @@ -0,0 +1,17 @@ +#ifndef PW_SCRIPTING_PRIVATE_VISUAL_HPP +#define PW_SCRIPTING_PRIVATE_VISUAL_HPP + +#include "scripting.hpp" + +namespace pw { + +struct script_visual { + + static void load(scripting::table& ns); + +}; + + +} + +#endif diff --git a/src/scripts/demos/simple_000.lua b/src/scripts/demos/simple_000.lua index 6e34031..42c5ed3 100644 --- a/src/scripts/demos/simple_000.lua +++ b/src/scripts/demos/simple_000.lua @@ -70,9 +70,18 @@ local w = pw.window.new() -- set title w.title = "pixwerx 0.1" +local pl = pw.pipeline.new() +if pl:create(pw.size.new(800,600)) then + print("pipeline ok") +else + print("pipeline failed") +end + -- setup a lua callback function w.on_update = function(self) - print("test on update",w.position.x,w.position.y,pw.timer.now) + + pl:draw() + -- print("test on update",w.position.x,w.position.y,pw.timer.now) end -- set size @@ -90,16 +99,16 @@ local t = pw.timer.new() while w:update() do -- somehow works - if (pw.input.get().input_string == 'f') then - w.fullscreen = not w.fullscreen - end + if (pw.input.get().input_string == 'f') then + w.fullscreen = not w.fullscreen + end -- just to check if (pw.input:get().mouse_button == 1) then - print("elapsed",t.elapsed) + print("elapsed",t.elapsed) t:reset() - print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y) - end + print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y) + end -- print("update") end diff --git a/src/system/src/window.cpp b/src/system/src/window.cpp index a90946f..4125d67 100644 --- a/src/system/src/window.cpp +++ b/src/system/src/window.cpp @@ -135,9 +135,9 @@ struct window::impl { update_display_list(); - // request specific version 3.2 + // request specific version 3.3 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); diff --git a/src/visual/include/pw/visual/shader.hpp b/src/visual/include/pw/visual/shader.hpp index 95c91cc..a32f5d4 100644 --- a/src/visual/include/pw/visual/shader.hpp +++ b/src/visual/include/pw/visual/shader.hpp @@ -13,6 +13,7 @@ class shader { public: shader(); + ~shader(); enum code_type { vertex, //< @@ -21,7 +22,7 @@ public: compute }; - void set_source(const std::string& c,code_type t); + void set_source(const std::string& c,code_type t) { _source[t] = c; } std::string source(code_type t) { return _source[t]; } // void set_attributes(const std::vector > &attributes); @@ -41,6 +42,10 @@ public: return *this; } + void build(); + + void use(); + protected: std::map _source; diff --git a/src/visual/src/pipeline.cpp b/src/visual/src/pipeline.cpp index 06dadae..d985562 100644 --- a/src/visual/src/pipeline.cpp +++ b/src/visual/src/pipeline.cpp @@ -2,91 +2,208 @@ #include "pw/core/size.hpp" #include "pw/core/matrix.hpp" +#include "pw/core/debug.hpp" #include "pw/visual/pipeline.hpp" +#include "pw/visual/shader.hpp" #include "glad/glad.h" namespace pw { + + +struct triangle_renderer +{ + GLuint vbo = 0; + GLuint vao = 0; + GLuint shader_programme = 0; + + shader shader_p; + + triangle_renderer() + { + } + + + + void setup() + { + float points[] = { + 0.0f, 0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, -0.5f, 0.0f + }; + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW); + + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); + + const char* vertex_shader = + "#version 400\n" + "in vec3 vp;" + "void main() {" + " gl_Position = vec4(vp, 1.0);" + "}"; + + + const char* fragment_shader = + "#version 400\n" + "out vec4 frag_colour;" + "void main() {" + " frag_colour = vec4(0.5, 0.0, 0.5, 1.0);" + "}"; +#if 0 + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vertex_shader, NULL); + glCompileShader(vs); + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, &fragment_shader, NULL); + glCompileShader(fs); + + shader_programme = glCreateProgram(); + glAttachShader(shader_programme, fs); + glAttachShader(shader_programme, vs); + glLinkProgram(shader_programme); +#endif + + + shader_p.set_source(fragment_shader,shader::fragment); + shader_p.set_source(vertex_shader,shader::vertex); + + shader_p.build(); + + + } + + void draw() + { +// glUseProgram(shader_programme); + + + shader_p.use(); + glBindVertexArray(vao); + // draw points 0-3 from the currently bound VAO with current in-use shader + glDrawArrays(GL_TRIANGLES, 0, 3); + } +}; + + struct pipeline::impl { - sizei _size; + sizei _size; - GLuint _fbo_draw; - GLuint _fbo_msaa; + GLuint _fbo_draw; + GLuint _fbo_msaa; - GLuint rboColorId; - GLuint rboDepthId; + GLuint rboColorId; + GLuint rboDepthId; - bool create(sizei size); + //testing + triangle_renderer tr; - void draw(); + bool create(sizei size); - impl() = default; - ~impl() = default; + void draw(); + + impl() = default; + ~impl() = default; }; bool pipeline::impl::create(sizei size) { - int max_msaa; - // query actual maximum MSAA - glGetIntegerv(GL_MAX_SAMPLES,&max_msaa); + _size = size; - // create a 4x MSAA renderbuffer object for colorbuffer - int msaa = 4; + int max_msaa; - // msaa = std::clamp(msaa,max_msaa); + // query actual maximum MSAA + glGetIntegerv(GL_MAX_SAMPLES,&max_msaa); - glGenRenderbuffers(1, &rboColorId); - glBindRenderbuffer(GL_RENDERBUFFER, rboColorId); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGB8, _size.width, _size.height); - // create a 4x MSAA renderbuffer object for depthbuffer + // create a 4x MSAA renderbuffer object for colorbuffer + int msaa = std::min(max_msaa,4); - glGenRenderbuffers(1, &rboDepthId); - glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId); - 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); + debug::d() << "OpenGL multisampling: " << max_msaa << " choosen:" << 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 - rboColorId); // 4. rbo ID + // msaa = std::clamp(msaa,max_msaa); - // 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 + glGenRenderbuffers(1, &rboColorId); + glBindRenderbuffer(GL_RENDERBUFFER, rboColorId); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_RGB8, _size.width, _size.height); - // check FBO status - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - return false; + // create a 4x MSAA renderbuffer object for depthbuffer - return true; + glGenRenderbuffers(1, &rboDepthId); + glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId); + 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 + rboColorId); // 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 + + // check FBO status + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + return false; + + + + tr.setup(); + + + + + return true; } void pipeline::impl::draw() { - /* 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. */ + glBindBuffer(GL_DRAW_FRAMEBUFFER, _fbo_draw); - /* 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); + glClearColor(1,0,0,1); + glClear(GL_COLOR_BUFFER_BIT); + + tr.draw(); + + // reset + glBindBuffer(GL_DRAW_FRAMEBUFFER, 0); + + + // actuall blitting + + /* 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. */ + + /* 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_LINEAR); } @@ -95,7 +212,7 @@ void pipeline::impl::draw() // pipeline::pipeline() - : _impl(std::make_unique()) + : _impl(std::make_unique()) { } @@ -104,9 +221,14 @@ pipeline::~pipeline() // } +void pipeline::draw() +{ + _impl->draw(); +} + bool pipeline::create(size s) { - return _impl->create(sizei(s.width,s.height)); + return _impl->create(s.cast()); } } diff --git a/src/visual/src/shader.cpp b/src/visual/src/shader.cpp index 0883a2a..ce74226 100644 --- a/src/visual/src/shader.cpp +++ b/src/visual/src/shader.cpp @@ -159,7 +159,11 @@ struct shader::impl shader::shader() { - _impl = make_unique(*this); + _impl = make_unique(*this); +} + +shader::~shader() +{ } bool shader::ready() const @@ -167,6 +171,16 @@ bool shader::ready() const return _impl->is_valid(); } +void shader::build() +{ + _impl->build(); +} + +void shader::use() +{ + _impl->use(); +} + int shader::uniform_location(const std::string &name) { return _impl->uniform_location(name);