working mesh rendering and shader uniforms

This commit is contained in:
Hartmut Seichter 2019-01-30 23:52:38 +01:00
parent ad13cea0ca
commit d9bbef876e
19 changed files with 262 additions and 83 deletions

View file

@ -2,6 +2,7 @@
* rename rect to rectangle * rename rect to rectangle
* fields - maybe std::variant? * fields - maybe std::variant?
* add more tests for linear algebra
# scripting # scripting
@ -14,7 +15,7 @@
# system # system
* filesystem walker with C++17 * filesystem walker with C++17 (or inotify, FindFirstChangeNotification or FSEvents)
# visual # visual

View file

@ -1,6 +1,7 @@
set(hdrs set(hdrs
include/pw/core/axisangle.hpp include/pw/core/axisangle.hpp
include/pw/core/color.hpp
include/pw/core/core.hpp include/pw/core/core.hpp
include/pw/core/debug.hpp include/pw/core/debug.hpp
include/pw/core/globals.hpp include/pw/core/globals.hpp
@ -10,7 +11,7 @@ set(hdrs
include/pw/core/quaternion.hpp include/pw/core/quaternion.hpp
include/pw/core/image.hpp include/pw/core/image.hpp
include/pw/core/point.hpp include/pw/core/point.hpp
include/pw/core/rect.hpp include/pw/core/rectangle.hpp
include/pw/core/serialize.hpp include/pw/core/serialize.hpp
include/pw/core/size.hpp include/pw/core/size.hpp
include/pw/core/timer.hpp include/pw/core/timer.hpp

View file

@ -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 <pw/core/vector.hpp>
#include <limits>
namespace pw {
struct color {
vector4 components;
color(uint8_t r8,uint8_t g8,uint8_t b8,uint8_t a8)
: color(static_cast<real_t>(r8 / std::numeric_limits<uint8_t>::max()),
static_cast<real_t>(g8 / std::numeric_limits<uint8_t>::max()),
static_cast<real_t>(b8 / std::numeric_limits<uint8_t>::max()),
static_cast<real_t>(a8 / std::numeric_limits<uint8_t>::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

View file

@ -43,6 +43,7 @@ struct quaternion_ : vector4_<T> {
using base_type::z; using base_type::z;
using base_type::w; using base_type::w;
using base_type::lerp; using base_type::lerp;
using base_type::xyz;
// using base_type::operator*; // using base_type::operator*;
// using base_type::operator/; // using base_type::operator/;

View file

@ -29,32 +29,31 @@
namespace pw { namespace pw {
template <typename T_> template <typename T_>
struct rect_ { struct rectangle_ {
size_<T_> size; size_<T_> size;
point_<T_> position; point_<T_> position;
rect_() = default; rectangle_() = default;
rect_(point_<T_> const & p,size_<T_> const & s) : size(s), position(p) {} rectangle_(point_<T_> const & p,size_<T_> const & s) : size(s), position(p) {}
bool contains(const point_<T_>& p) const bool contains(const point_<T_>& p) const
{ {
return p.x >= position.x && p.x <= position.x + size.width && 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 <typename To_> template <typename To_>
rect_<To_> cast() const { return rect_<To_>(position.template cast<To_>(),size.template cast<To_>()); } rectangle_<To_> cast() const { return rectangle_<To_>(position.template cast<To_>(),size.template cast<To_>()); }
}; };
typedef rect_<real_t> rect; typedef rectangle_<real_t> rectangle;
typedef rect_<int> recti; typedef rectangle_<int> rectanglei;
typedef rect_<float> rectf; typedef rectangle_<float> rectanglef;
typedef rect_<float> rectd; typedef rectangle_<double> rectangled;
} }

View file

@ -30,7 +30,7 @@ int main(int argc,char **argv) {
auto v3_h = v.homogenous(); auto v3_h = v.homogenous();
// auto v3_lerp = vector4f::lerp() // auto v3_lerp = vector4f::
std::cout << "v3 = " << pw::serialize::matrix(v3) << std::endl; std::cout << "v3 = " << pw::serialize::matrix(v3) << std::endl;

View file

@ -3,7 +3,6 @@ set(hdrs
include/pw/scene/camera.hpp include/pw/scene/camera.hpp
include/pw/scene/component.hpp include/pw/scene/component.hpp
include/pw/scene/node.hpp include/pw/scene/node.hpp
# include/pw/scene/mesh.hpp
include/pw/scene/scene.hpp include/pw/scene/scene.hpp
include/pw/scene/transform.hpp include/pw/scene/transform.hpp
include/pw/scene/traverser.hpp include/pw/scene/traverser.hpp
@ -13,7 +12,6 @@ set(srcs
src/node.cpp src/node.cpp
src/camera.cpp src/camera.cpp
src/component.cpp src/component.cpp
# src/mesh.cpp
src/scene.cpp src/scene.cpp
src/transform.cpp src/transform.cpp
src/traverser.cpp src/traverser.cpp

View file

@ -47,6 +47,19 @@ void component::set_weight(const uint32_t &weight)
} }
class material_component {
enum shading_input {
albedo,
specular
};
// std::map<shading_input,vector4> _colors;
// std::shared_ptr<image> _albedo;
};
//class trs : public transform { //class trs : public transform {

View file

@ -3,6 +3,8 @@
#include <pw/scene/node.hpp> #include <pw/scene/node.hpp>
#include <pw/scene/transform.hpp> #include <pw/scene/transform.hpp>
#include <pw/core/serialize.hpp>
#include <iostream> #include <iostream>
void print_node_path(pw::node::ref node) { void print_node_path(pw::node::ref node) {
@ -49,7 +51,6 @@ int main(int argc,char **argv) {
print_node_path((n)); print_node_path((n));
// auto t = n->transform(); // auto t = n->transform();
// if (t) // if (t)

View file

@ -27,20 +27,23 @@ void register_core_function(sol::state& lua,sol::table& ns)
ns.set("pi",pw::pi<Scalar>()); ns.set("pi",pw::pi<Scalar>());
ns.new_usertype<matrix4x4>("matrix4x4" ns.new_usertype<matrix4x4>("matrix4x4"
, sol::constructors<matrix4x4()>() , sol::constructors<matrix4x4()>()
, "row",&matrix4x4::row , "row",&matrix4x4::row
); , "column",&matrix4x4::column
, "set_identity",&matrix4x4::set_identity
, "inverse",&matrix4x4::inverse
);
ns.new_usertype<vector3>("vector3" ns.new_usertype<vector3>("vector3"
,sol::constructors<vector3(),vector3(Scalar,Scalar,Scalar)>() ,sol::constructors<vector3(),vector3(Scalar,Scalar,Scalar)>()
,"x", sol::property(sol::resolve<const vector3::value_type&() const>(&vector3::x), [](vector3& v,vector3::value_type val){ v.x() = val;}) ,"x", sol::property(sol::resolve<const vector3::value_type&() const>(&vector3::x), [](vector3& v,vector3::value_type val){ v.x() = val;})
,"y", sol::property(sol::resolve<const vector3::value_type&() const>(&vector3::y), [](vector3& v,vector3::value_type val){ v.y() = val;}) ,"y", sol::property(sol::resolve<const vector3::value_type&() const>(&vector3::y), [](vector3& v,vector3::value_type val){ v.y() = val;})
,"z", sol::property(sol::resolve<const vector3::value_type&() const>(&vector3::z), [](vector3& v,vector3::value_type val){ v.z() = val;}) ,"z", sol::property(sol::resolve<const vector3::value_type&() const>(&vector3::z), [](vector3& v,vector3::value_type val){ v.z() = val;})
,"cross",&vector3::cross ,"cross",&vector3::cross
,"transposed",&vector3::transposed ,"transposed",&vector3::transposed
,"lerp",&vector3::lerp ,"lerp",&vector3::lerp
); );
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)>()
@ -50,25 +53,26 @@ void register_core_function(sol::state& lua,sol::table& ns)
,"w", sol::property(sol::resolve<const quaternion::value_type&() const>(&quaternion::w), [](quaternion& v,quaternion::value_type val){ v.w() = val;}) ,"w", sol::property(sol::resolve<const quaternion::value_type&() const>(&quaternion::w), [](quaternion& v,quaternion::value_type val){ v.w() = val;})
,"identity",sol::readonly_property(&quaternion::identity) ,"identity",sol::readonly_property(&quaternion::identity)
,"dot",&quaternion::dot ,"dot",&quaternion::dot
,"inverse",sol::readonly_property(&quaternion::inverse) ,"inverse",sol::readonly_property(&quaternion::inverse)
,"normalized",&quaternion::normalized ,"normalized",&quaternion::normalized
,"lerp",&quaternion::lerp ,"lerp",&quaternion::lerp
,"slerp",&quaternion::slerp ,"slerp",&quaternion::slerp
); );
ns.new_usertype<axisangle> ns.new_usertype<axisangle>
("axisangle", ("axisangle",
sol::constructors<axisangle(), axisangle(vector3,Scalar)>(), sol::constructors<axisangle(), axisangle(vector3,Scalar)>(),
"axis",&axisangle::axis, "axis",&axisangle::axis,
"angle",&axisangle::angle "angle",&axisangle::angle,
"from_matrix",&axisangle::from_matrix,
"to_matrix",&axisangle::to_matrix
); );
ns.new_usertype<size>("size", ns.new_usertype<size>("size"
sol::constructors<size(),size(Scalar,Scalar)>(), , sol::constructors<size(),size(Scalar,Scalar)>()
"width",&size::width, , "width",&size::width
"height",&size::height , "height",&size::height
// "none",sol::debug::level::none
); );
ns.new_usertype<point>("point", ns.new_usertype<point>("point",

View file

@ -16,6 +16,7 @@ public:
std::string name() const { return _name; } std::string name() const { return _name; }
protected: protected:
friend class window; friend class window;
std::string _name; std::string _name;

View file

@ -12,10 +12,17 @@ set(srcs
src/pipeline.cpp src/pipeline.cpp
) )
set(srcs_shader
src/shader/unlit_vs.glsl
src/shader/unlit_fs.glsl
)
add_library(pwvisual add_library(pwvisual
STATIC STATIC
${hdrs} ${hdrs}
${srcs} ${srcs}
${srcs_shader}
) )
target_include_directories( target_include_directories(

View file

@ -11,11 +11,23 @@ namespace pw {
class mesh_renderer { class mesh_renderer {
public: public:
void render(const mesh& mesh,
const matrix4x4& model_matrix, mesh_renderer();
const matrix4x4& view_matrix, ~mesh_renderer();
const matrix4x4& projection_matrix
); 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: protected:

View file

@ -3,6 +3,7 @@
#include <pw/core/globals.hpp> #include <pw/core/globals.hpp>
#include <pw/core/matrix.hpp> #include <pw/core/matrix.hpp>
#include <pw/core/vector.hpp>
#include <pw/core/debug.hpp> #include <pw/core/debug.hpp>
#include <map> #include <map>
@ -31,18 +32,21 @@ public:
shader& bind(int location,float v); shader& bind(int location,float v);
shader& bind(int location,matrix4x4f const & 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<typename T> shader & bind(std::string const & name, T&& value) template<typename T> shader & bind(std::string const & name, T&& value)
{ {
int location = uniform_location(name); int location = uniform_location(name);
if (location == -1) debug::e() << "missing uniform: "<< name; if (location >= 0)
else bind(location, std::forward<T>(value)); return bind(location, std::forward<T>(value));
else
debug::e() << "missing uniform: "<< name;
return *this; return *this;
} }
void build(); bool build();
void use(); void use();

View file

@ -15,11 +15,21 @@ struct mesh_renderer::impl {
GLuint _vao = 0; GLuint _vao = 0;
std::vector<GLuint> _vbos; std::vector<GLuint> _vbos;
impl(mesh_renderer& ) impl()
{ {
} }
void create(std::shared_ptr<mesh> mesh) ~impl()
{
destroy();
}
bool ready() const
{
return GL_TRUE == glIsVertexArray(_vao);
}
void create(const mesh& m)
{ {
glGenVertexArrays(1,&_vao); glGenVertexArrays(1,&_vao);
glBindVertexArray(_vao); glBindVertexArray(_vao);
@ -27,8 +37,8 @@ struct mesh_renderer::impl {
size_t arrays_needed = 0; size_t arrays_needed = 0;
// should bail out here // should bail out here
if (!mesh->vertices().empty()) arrays_needed++; if (!m.vertices().empty()) arrays_needed++;
if (!mesh->indices().empty()) arrays_needed++; if (!m.indices().empty()) arrays_needed++;
// TODO: implement the other arrays // TODO: implement the other arrays
@ -38,22 +48,22 @@ struct mesh_renderer::impl {
// vertices // vertices
glBindBuffer(GL_ARRAY_BUFFER, _vbos[0]); 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); GL_STATIC_DRAW);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// indices // indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbos[1]); 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); GL_STATIC_DRAW);
// stop binding // stop binding
glBindVertexArray(0); glBindVertexArray(0);
} }
void destroy() void destroy()
{ {
glDeleteVertexArrays(1,&_vao); glDeleteVertexArrays(1,&_vao);
@ -65,12 +75,44 @@ struct mesh_renderer::impl {
void draw() void draw()
{ {
glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
} }
}; };
//
//
//
mesh_renderer::mesh_renderer()
: _impl(std::make_unique<mesh_renderer::impl>())
{
}
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();
}
} }

View file

@ -7,6 +7,7 @@
#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/mesh_renderer.hpp"
#include "glad/glad.h" #include "glad/glad.h"
@ -22,6 +23,7 @@ struct triangle_renderer
shader shader_p; shader shader_p;
mesh amesh; mesh amesh;
mesh_renderer amesh_renderer;
triangle_renderer() triangle_renderer()
{ {
@ -48,6 +50,10 @@ struct triangle_renderer
amesh.set_indices(indices); amesh.set_indices(indices);
amesh.set_vertices(vertices); 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_size_bytes = amesh.vertices().size() * sizeof(mesh::vertex3array_t::value_type);
size_t vertex_stride = amesh.vertices().front().size(); 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); glVertexAttribPointer(0, vertex_stride, GL_FLOAT, GL_FALSE, 0, nullptr);
const char* vertex_shader = R"( const char* vertex_shader = R"(
#version 400 #version 400
in vec3 vp; in vec3 vp;
void main() { void main() {
gl_Position = vec4(vp, 1.0); gl_Position = vec4(vp, 1.0);
} }
)"; )";
// "#version 400\n" const char *fragment_shader = R"(
// "in vec3 vp;" #version 400
// "void main() {" uniform vec4 input_color = vec4(1.0, 0.0, 0.0, 1.0);
// " gl_Position = vec4(vp, 1.0);" out vec4 frag_colour;
// "}";
const char *fragment_shader = R"(#version 400
out vec4 frag_colour;
void main() { void main() {
frag_colour = vec4(0.5, 0.5, 0.5, 1.0); frag_colour = input_color;
})"; })";
#if 0 #if 0
@ -110,17 +111,29 @@ struct triangle_renderer
shader_p.set_source(fragment_shader,shader::fragment); shader_p.set_source(fragment_shader,shader::fragment);
shader_p.set_source(vertex_shader,shader::vertex); shader_p.set_source(vertex_shader,shader::vertex);
shader_p.build(); if (!shader_p.build())
exit(-1);
} }
void draw() void draw()
{ {
shader_p.use(); shader_p.use();
glBindVertexArray(vao);
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 // draw points 0-3 from the currently bound VAO with current in-use shader
glDrawArrays(GL_TRIANGLES, 0, 3); // glDrawArrays(GL_TRIANGLES, 0, 3);
} }
}; };

View file

@ -29,7 +29,7 @@ struct shader::impl
return glIsProgram(_shader_program); return glIsProgram(_shader_program);
} }
void build() bool build()
{ {
for (auto s : _shader._source) for (auto s : _shader._source)
@ -75,7 +75,7 @@ struct shader::impl
// TODO - handle errors! // TODO - handle errors!
debug::e() << log_buffer.get(); debug::e() << log_buffer.get();
break; return false;
} }
_shader_stages.push_back(shaderId); _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. */ /* 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 */ /* 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()); return glGetUniformLocation(_shader_program,name.c_str());
} }
void bind(int location,const matrix4x4f& m) 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(); 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() void shader::use()
@ -179,7 +196,7 @@ void shader::use()
_impl->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); return _impl->uniform_location(name);
} }

View file

@ -0,0 +1,5 @@
#version 400
out vec4 frag_colour;
void main() {
frag_colour = vec4(0.5, 0.5, 0.5, 1.0);
}

View file

@ -0,0 +1,5 @@
#version 400
in vec3 vp;
void main() {
gl_Position = vec4(vp, 1.0);
}