From d9bbef876e5a8d2fe8918326f130ceb7147188ac Mon Sep 17 00:00:00 2001 From: Hartmut Seichter Date: Wed, 30 Jan 2019 23:52:38 +0100 Subject: [PATCH] working mesh rendering and shader uniforms --- TODO.md | 3 +- src/core/CMakeLists.txt | 3 +- src/core/include/pw/core/color.hpp | 55 ++++++++++++++++++ src/core/include/pw/core/quaternion.hpp | 1 + .../pw/core/{rect.hpp => rectangle.hpp} | 19 +++--- src/core/tests/pwcore_test_vector.cpp | 2 +- src/scene/CMakeLists.txt | 2 - src/scene/src/component.cpp | 13 +++++ src/scene/tests/pwscene_test_node.cpp | 3 +- src/scripting/src/script_core.cpp | 54 +++++++++-------- src/system/include/pw/system/display.hpp | 1 + src/visual/CMakeLists.txt | 7 +++ .../include/pw/visual/mesh_renderer.hpp | 22 +++++-- src/visual/include/pw/visual/shader.hpp | 12 ++-- src/visual/src/mesh_renderer.cpp | 58 ++++++++++++++++--- src/visual/src/pipeline.cpp | 47 +++++++++------ src/visual/src/shader.cpp | 33 ++++++++--- src/visual/src/shader/unlit_fs.glsl | 5 ++ src/visual/src/shader/unlit_vs.glsl | 5 ++ 19 files changed, 262 insertions(+), 83 deletions(-) create mode 100644 src/core/include/pw/core/color.hpp rename src/core/include/pw/core/{rect.hpp => rectangle.hpp} (76%) create mode 100644 src/visual/src/shader/unlit_fs.glsl create mode 100644 src/visual/src/shader/unlit_vs.glsl diff --git a/TODO.md b/TODO.md index 7ea5779..1b491d1 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ * rename rect to rectangle * fields - maybe std::variant? +* add more tests for linear algebra # scripting @@ -14,7 +15,7 @@ # system -* filesystem walker with C++17 +* filesystem walker with C++17 (or inotify, FindFirstChangeNotification or FSEvents) # visual diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 84a6fd8..aa0ea86 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,6 +1,7 @@ set(hdrs include/pw/core/axisangle.hpp + include/pw/core/color.hpp include/pw/core/core.hpp include/pw/core/debug.hpp include/pw/core/globals.hpp @@ -10,7 +11,7 @@ set(hdrs include/pw/core/quaternion.hpp include/pw/core/image.hpp include/pw/core/point.hpp - include/pw/core/rect.hpp + include/pw/core/rectangle.hpp include/pw/core/serialize.hpp include/pw/core/size.hpp include/pw/core/timer.hpp diff --git a/src/core/include/pw/core/color.hpp b/src/core/include/pw/core/color.hpp new file mode 100644 index 0000000..4d9857f --- /dev/null +++ b/src/core/include/pw/core/color.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1999-2019 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 + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#ifndef PW_CORE_COLOR_HPP +#define PW_CORE_COLOR_HPP + +#include +#include + +namespace pw { + +struct color { + vector4 components; + + color(uint8_t r8,uint8_t g8,uint8_t b8,uint8_t a8) + : color(static_cast(r8 / std::numeric_limits::max()), + static_cast(g8 / std::numeric_limits::max()), + static_cast(b8 / std::numeric_limits::max()), + static_cast(a8 / std::numeric_limits::max())) + { + } + + color(real_t r,real_t g,real_t b,real_t a) + : components({r,g,b,a}) + { + } + + uint32_t to_rgb8888() const { + return 0; + } +}; + +} + + +#endif diff --git a/src/core/include/pw/core/quaternion.hpp b/src/core/include/pw/core/quaternion.hpp index b2bb56c..08c4fbc 100644 --- a/src/core/include/pw/core/quaternion.hpp +++ b/src/core/include/pw/core/quaternion.hpp @@ -43,6 +43,7 @@ struct quaternion_ : vector4_ { using base_type::z; using base_type::w; using base_type::lerp; + using base_type::xyz; // using base_type::operator*; // using base_type::operator/; diff --git a/src/core/include/pw/core/rect.hpp b/src/core/include/pw/core/rectangle.hpp similarity index 76% rename from src/core/include/pw/core/rect.hpp rename to src/core/include/pw/core/rectangle.hpp index 779626f..4926842 100644 --- a/src/core/include/pw/core/rect.hpp +++ b/src/core/include/pw/core/rectangle.hpp @@ -29,32 +29,31 @@ namespace pw { template -struct rect_ { +struct rectangle_ { size_ size; point_ position; - rect_() = default; + rectangle_() = default; - rect_(point_ const & p,size_ const & s) : size(s), position(p) {} + rectangle_(point_ const & p,size_ const & s) : size(s), position(p) {} bool contains(const point_& p) const { return p.x >= position.x && p.x <= position.x + size.width && - p.y >= position.y && p.y <= position.y + size.height; + p.y >= position.y && p.y <= position.y + size.height; } template - rect_ cast() const { return rect_(position.template cast(),size.template cast()); } - + rectangle_ cast() const { return rectangle_(position.template cast(),size.template cast()); } }; -typedef rect_ rect; +typedef rectangle_ rectangle; -typedef rect_ recti; -typedef rect_ rectf; -typedef rect_ rectd; +typedef rectangle_ rectanglei; +typedef rectangle_ rectanglef; +typedef rectangle_ rectangled; } diff --git a/src/core/tests/pwcore_test_vector.cpp b/src/core/tests/pwcore_test_vector.cpp index 6403f58..586beff 100644 --- a/src/core/tests/pwcore_test_vector.cpp +++ b/src/core/tests/pwcore_test_vector.cpp @@ -30,7 +30,7 @@ int main(int argc,char **argv) { auto v3_h = v.homogenous(); -// auto v3_lerp = vector4f::lerp() +// auto v3_lerp = vector4f:: std::cout << "v3 = " << pw::serialize::matrix(v3) << std::endl; diff --git a/src/scene/CMakeLists.txt b/src/scene/CMakeLists.txt index d5d7950..797376f 100644 --- a/src/scene/CMakeLists.txt +++ b/src/scene/CMakeLists.txt @@ -3,7 +3,6 @@ set(hdrs include/pw/scene/camera.hpp include/pw/scene/component.hpp include/pw/scene/node.hpp -# include/pw/scene/mesh.hpp include/pw/scene/scene.hpp include/pw/scene/transform.hpp include/pw/scene/traverser.hpp @@ -13,7 +12,6 @@ set(srcs src/node.cpp src/camera.cpp src/component.cpp -# src/mesh.cpp src/scene.cpp src/transform.cpp src/traverser.cpp diff --git a/src/scene/src/component.cpp b/src/scene/src/component.cpp index 520a095..ab711d8 100644 --- a/src/scene/src/component.cpp +++ b/src/scene/src/component.cpp @@ -47,6 +47,19 @@ void component::set_weight(const uint32_t &weight) } +class material_component { + + enum shading_input { + albedo, + specular + }; + +// std::map _colors; + + +// std::shared_ptr _albedo; +}; + //class trs : public transform { diff --git a/src/scene/tests/pwscene_test_node.cpp b/src/scene/tests/pwscene_test_node.cpp index d865302..a3e247f 100644 --- a/src/scene/tests/pwscene_test_node.cpp +++ b/src/scene/tests/pwscene_test_node.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include void print_node_path(pw::node::ref node) { @@ -49,7 +51,6 @@ int main(int argc,char **argv) { print_node_path((n)); - // auto t = n->transform(); // if (t) diff --git a/src/scripting/src/script_core.cpp b/src/scripting/src/script_core.cpp index f733fea..1c27982 100644 --- a/src/scripting/src/script_core.cpp +++ b/src/scripting/src/script_core.cpp @@ -27,20 +27,23 @@ void register_core_function(sol::state& lua,sol::table& ns) ns.set("pi",pw::pi()); - ns.new_usertype("matrix4x4" - , sol::constructors() - , "row",&matrix4x4::row - ); + ns.new_usertype("matrix4x4" + , sol::constructors() + , "row",&matrix4x4::row + , "column",&matrix4x4::column + , "set_identity",&matrix4x4::set_identity + , "inverse",&matrix4x4::inverse + ); - ns.new_usertype("vector3" - ,sol::constructors() - ,"x", sol::property(sol::resolve(&vector3::x), [](vector3& v,vector3::value_type val){ v.x() = val;}) - ,"y", sol::property(sol::resolve(&vector3::y), [](vector3& v,vector3::value_type val){ v.y() = val;}) - ,"z", sol::property(sol::resolve(&vector3::z), [](vector3& v,vector3::value_type val){ v.z() = val;}) - ,"cross",&vector3::cross - ,"transposed",&vector3::transposed - ,"lerp",&vector3::lerp - ); + ns.new_usertype("vector3" + ,sol::constructors() + ,"x", sol::property(sol::resolve(&vector3::x), [](vector3& v,vector3::value_type val){ v.x() = val;}) + ,"y", sol::property(sol::resolve(&vector3::y), [](vector3& v,vector3::value_type val){ v.y() = val;}) + ,"z", sol::property(sol::resolve(&vector3::z), [](vector3& v,vector3::value_type val){ v.z() = val;}) + ,"cross",&vector3::cross + ,"transposed",&vector3::transposed + ,"lerp",&vector3::lerp + ); ns.new_usertype("quaternion" , sol::constructors() @@ -50,25 +53,26 @@ void register_core_function(sol::state& lua,sol::table& ns) ,"w", sol::property(sol::resolve(&quaternion::w), [](quaternion& v,quaternion::value_type val){ v.w() = val;}) ,"identity",sol::readonly_property(&quaternion::identity) ,"dot",&quaternion::dot - ,"inverse",sol::readonly_property(&quaternion::inverse) - ,"normalized",&quaternion::normalized - ,"lerp",&quaternion::lerp - ,"slerp",&quaternion::slerp - ); + ,"inverse",sol::readonly_property(&quaternion::inverse) + ,"normalized",&quaternion::normalized + ,"lerp",&quaternion::lerp + ,"slerp",&quaternion::slerp + ); ns.new_usertype ("axisangle", sol::constructors(), - "axis",&axisangle::axis, - "angle",&axisangle::angle + "axis",&axisangle::axis, + "angle",&axisangle::angle, + "from_matrix",&axisangle::from_matrix, + "to_matrix",&axisangle::to_matrix ); - ns.new_usertype("size", - sol::constructors(), - "width",&size::width, - "height",&size::height - // "none",sol::debug::level::none + ns.new_usertype("size" + , sol::constructors() + , "width",&size::width + , "height",&size::height ); ns.new_usertype("point", diff --git a/src/system/include/pw/system/display.hpp b/src/system/include/pw/system/display.hpp index e85fafc..d6f494d 100644 --- a/src/system/include/pw/system/display.hpp +++ b/src/system/include/pw/system/display.hpp @@ -16,6 +16,7 @@ public: std::string name() const { return _name; } protected: + friend class window; std::string _name; diff --git a/src/visual/CMakeLists.txt b/src/visual/CMakeLists.txt index 6d48f62..8a5d623 100644 --- a/src/visual/CMakeLists.txt +++ b/src/visual/CMakeLists.txt @@ -12,10 +12,17 @@ set(srcs src/pipeline.cpp ) + +set(srcs_shader + src/shader/unlit_vs.glsl + src/shader/unlit_fs.glsl + ) + add_library(pwvisual STATIC ${hdrs} ${srcs} + ${srcs_shader} ) target_include_directories( diff --git a/src/visual/include/pw/visual/mesh_renderer.hpp b/src/visual/include/pw/visual/mesh_renderer.hpp index 76ba99d..2c67cbc 100644 --- a/src/visual/include/pw/visual/mesh_renderer.hpp +++ b/src/visual/include/pw/visual/mesh_renderer.hpp @@ -11,11 +11,23 @@ namespace pw { class mesh_renderer { public: - void render(const mesh& mesh, - const matrix4x4& model_matrix, - const matrix4x4& view_matrix, - const matrix4x4& projection_matrix - ); + + mesh_renderer(); + ~mesh_renderer(); + + bool ready() const; + + void create(const mesh &m); + void destroy(); + + void draw(); + + +// void render(const mesh& mesh, +// const matrix4x4& model_matrix, +// const matrix4x4& view_matrix, +// const matrix4x4& projection_matrix +// ); protected: diff --git a/src/visual/include/pw/visual/shader.hpp b/src/visual/include/pw/visual/shader.hpp index a32f5d4..b1876ea 100644 --- a/src/visual/include/pw/visual/shader.hpp +++ b/src/visual/include/pw/visual/shader.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -31,18 +32,21 @@ public: shader& bind(int location,float v); shader& bind(int location,matrix4x4f const & v); + shader& bind(int location,vector4f const & v); - int uniform_location(std::string const & name); + int uniform_location(std::string const & name) const; template shader & bind(std::string const & name, T&& value) { int location = uniform_location(name); - if (location == -1) debug::e() << "missing uniform: "<< name; - else bind(location, std::forward(value)); + if (location >= 0) + return bind(location, std::forward(value)); + else + debug::e() << "missing uniform: "<< name; return *this; } - void build(); + bool build(); void use(); diff --git a/src/visual/src/mesh_renderer.cpp b/src/visual/src/mesh_renderer.cpp index fff5c06..4a5730d 100644 --- a/src/visual/src/mesh_renderer.cpp +++ b/src/visual/src/mesh_renderer.cpp @@ -15,11 +15,21 @@ struct mesh_renderer::impl { GLuint _vao = 0; std::vector _vbos; - impl(mesh_renderer& ) + impl() { } - void create(std::shared_ptr mesh) + ~impl() + { + destroy(); + } + + bool ready() const + { + return GL_TRUE == glIsVertexArray(_vao); + } + + void create(const mesh& m) { glGenVertexArrays(1,&_vao); glBindVertexArray(_vao); @@ -27,8 +37,8 @@ struct mesh_renderer::impl { size_t arrays_needed = 0; // should bail out here - if (!mesh->vertices().empty()) arrays_needed++; - if (!mesh->indices().empty()) arrays_needed++; + if (!m.vertices().empty()) arrays_needed++; + if (!m.indices().empty()) arrays_needed++; // TODO: implement the other arrays @@ -38,22 +48,22 @@ struct mesh_renderer::impl { // vertices glBindBuffer(GL_ARRAY_BUFFER, _vbos[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(mesh->vertices().front()) * mesh->vertices().size(), mesh->vertices().data(), + 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(mesh->indices().front()) * mesh->indices().size(), mesh->indices().data(), + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m.indices().front()) * m.indices().size(), m.indices().data(), GL_STATIC_DRAW); - // stop binding glBindVertexArray(0); } + void destroy() { glDeleteVertexArrays(1,&_vao); @@ -65,12 +75,44 @@ struct mesh_renderer::impl { void draw() { - + glBindVertexArray(_vao); + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr); } }; +// +// +// +mesh_renderer::mesh_renderer() + : _impl(std::make_unique()) +{ +} + +mesh_renderer::~mesh_renderer() +{ +} + +bool mesh_renderer::ready() const +{ + return _impl->ready(); +} + +void mesh_renderer::create(const mesh &m) +{ + _impl->create(m); +} + +void mesh_renderer::destroy() +{ + _impl->destroy(); +} + +void mesh_renderer::draw() +{ + _impl->draw(); +} } diff --git a/src/visual/src/pipeline.cpp b/src/visual/src/pipeline.cpp index 6132f5f..aaa58f8 100644 --- a/src/visual/src/pipeline.cpp +++ b/src/visual/src/pipeline.cpp @@ -7,6 +7,7 @@ #include "pw/core/debug.hpp" #include "pw/visual/pipeline.hpp" #include "pw/visual/shader.hpp" +#include "pw/visual/mesh_renderer.hpp" #include "glad/glad.h" @@ -22,6 +23,7 @@ struct triangle_renderer shader shader_p; mesh amesh; + mesh_renderer amesh_renderer; triangle_renderer() { @@ -48,6 +50,10 @@ struct triangle_renderer amesh.set_indices(indices); amesh.set_vertices(vertices); + + amesh_renderer.create(amesh); + + size_t vertex_size_bytes = amesh.vertices().size() * sizeof(mesh::vertex3array_t::value_type); size_t vertex_stride = amesh.vertices().front().size(); @@ -72,24 +78,19 @@ struct triangle_renderer glVertexAttribPointer(0, vertex_stride, GL_FLOAT, GL_FALSE, 0, nullptr); const char* vertex_shader = R"( - #version 400 - in vec3 vp; - void main() { + #version 400 + in vec3 vp; + void main() { gl_Position = vec4(vp, 1.0); } )"; -// "#version 400\n" -// "in vec3 vp;" -// "void main() {" -// " gl_Position = vec4(vp, 1.0);" -// "}"; - - - const char *fragment_shader = R"(#version 400 - out vec4 frag_colour; + const char *fragment_shader = R"( + #version 400 + uniform vec4 input_color = vec4(1.0, 0.0, 0.0, 1.0); + out vec4 frag_colour; void main() { - frag_colour = vec4(0.5, 0.5, 0.5, 1.0); + frag_colour = input_color; })"; #if 0 @@ -110,17 +111,29 @@ struct triangle_renderer shader_p.set_source(fragment_shader,shader::fragment); shader_p.set_source(vertex_shader,shader::vertex); - shader_p.build(); + if (!shader_p.build()) + exit(-1); } void draw() { - shader_p.use(); - glBindVertexArray(vao); + shader_p.use(); + + + static float v = 0.0f; + v+= 0.01f; + if (v>1.0f) v = 0.0f; + vector4f test({0.5f,1-v,v,1.0f}); + + shader_p.bind("input_color",test); + + amesh_renderer.draw(); + +// glBindVertexArray(vao); // draw points 0-3 from the currently bound VAO with current in-use shader - glDrawArrays(GL_TRIANGLES, 0, 3); +// glDrawArrays(GL_TRIANGLES, 0, 3); } }; diff --git a/src/visual/src/shader.cpp b/src/visual/src/shader.cpp index 690fd3a..d412293 100644 --- a/src/visual/src/shader.cpp +++ b/src/visual/src/shader.cpp @@ -29,7 +29,7 @@ struct shader::impl return glIsProgram(_shader_program); } - void build() + bool build() { for (auto s : _shader._source) @@ -75,7 +75,7 @@ struct shader::impl // TODO - handle errors! debug::e() << log_buffer.get(); - break; + return false; } _shader_stages.push_back(shaderId); @@ -120,8 +120,10 @@ struct shader::impl /* Handle the error in an appropriate way such as displaying a message or writing to a log file. */ /* In this simple program, we'll just leave */ - return; + return false; } + + return true; } @@ -142,14 +144,24 @@ struct shader::impl } } - int uniform_location(std::string const& name) + int uniform_location(std::string const& name) const { return glGetUniformLocation(_shader_program,name.c_str()); } void bind(int location,const matrix4x4f& m) { - glUniformMatrix4fv(location,1,GL_FALSE,m.data); // TODO transpose? + glUniformMatrix4fv(location,1,GL_FALSE,m.data); + } + + void bind(int location,const vector4f& v) + { + glUniform4fv(location,1,v.data); + } + + void bind(int location,const float& v) + { + glUniform1f(location,v); } }; @@ -169,9 +181,14 @@ bool shader::ready() const return _impl->is_valid(); } -void shader::build() +shader &shader::bind(int location, const vector4f &v) { - _impl->build(); + _impl->bind(location,v); return *this; +} + +bool shader::build() +{ + return _impl->build(); } void shader::use() @@ -179,7 +196,7 @@ void shader::use() _impl->use(); } -int shader::uniform_location(const std::string &name) +int shader::uniform_location(const std::string &name) const { return _impl->uniform_location(name); } diff --git a/src/visual/src/shader/unlit_fs.glsl b/src/visual/src/shader/unlit_fs.glsl new file mode 100644 index 0000000..ae57fe3 --- /dev/null +++ b/src/visual/src/shader/unlit_fs.glsl @@ -0,0 +1,5 @@ +#version 400 +out vec4 frag_colour; +void main() { + frag_colour = vec4(0.5, 0.5, 0.5, 1.0); +} diff --git a/src/visual/src/shader/unlit_vs.glsl b/src/visual/src/shader/unlit_vs.glsl new file mode 100644 index 0000000..d67c8bb --- /dev/null +++ b/src/visual/src/shader/unlit_vs.glsl @@ -0,0 +1,5 @@ +#version 400 +in vec3 vp; +void main() { + gl_Position = vec4(vp, 1.0); +}