inching slowly towards a renderer

This commit is contained in:
Hartmut Seichter 2019-01-11 23:21:09 +01:00
parent 4b695ecaf6
commit c7c7d5af77
28 changed files with 613 additions and 59 deletions

View file

@ -1,11 +1,13 @@
set(hdrs
include/pw/visual/renderer.hpp
include/pw/visual/shader.hpp
include/pw/visual/context.hpp
)
set(srcs
src/renderer.cpp
src/shader.cpp
src/context.cpp
)
@ -21,6 +23,6 @@ target_include_directories(
include
)
target_link_libraries(pwvisual pwscene)
target_link_libraries(pwvisual pwscene glad)
#add_subdirectory(tests)

View file

@ -1,15 +1,29 @@
#ifndef PW_VISUAL_RENDERER_HPP
#define PW_VISUAL_RENDERER_HPP
#include <pw/scene/component.hpp>
//#include <pw/scene/component.hpp>
//#include <pw/scene/camera.hpp>
#include <pw/core/matrix.hpp>
#include <pw/core/mesh.hpp>
#include <map>
namespace pw {
class context;
class renderer {
public:
void render(context& context);
void render(const mesh& mesh,
const matrix4x4& model_matrix,
const matrix4x4& view_matrix,
const matrix4x4& projection_matrix
);
protected:
struct impl;
std::unique_ptr<impl> _impl;
};

View file

@ -0,0 +1,41 @@
#ifndef PW_VISUAL_SHADER_HPP
#define PW_VISUAL_SHADER_HPP
#include <pw/core/globals.hpp>
#include <pw/core/matrix.hpp>
#include <map>
namespace pw {
class shader {
public:
shader();
enum code_type {
vertex, //<
fragment,
geometry,
compute
};
void set_source(const std::string& c,code_type t);
std::string source(code_type t) { return _source[t]; }
// void set_attributes(const std::vector<std::string> > &attributes);
bool ready() const;
protected:
std::map<code_type,std::string> _source;
struct impl;
std::unique_ptr<impl> _impl;
};
}
#endif

View file

@ -1,9 +1,69 @@
#include "pw/visual/renderer.hpp"
#include "pw/core/mesh.hpp"
#include "glad/glad.h"
namespace pw {
void renderer::render(pw::context &context)
{
}
struct renderer::impl {
GLuint _vao = 0;
std::vector<GLuint> _vbos;
impl(renderer& )
{
}
void create(std::shared_ptr<mesh> mesh)
{
glGenVertexArrays(1,&_vao);
glBindVertexArray(_vao);
size_t arrays_needed = 0;
// should bail out here
if (!mesh->vertices().empty()) arrays_needed++;
if (!mesh->indices().empty()) arrays_needed++;
// 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(mesh->vertices().front()) * mesh->vertices().size(), mesh->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(),
GL_STATIC_DRAW);
// stop binding
glBindVertexArray(0);
}
void destroy()
{
glDeleteVertexArrays(1,&_vao);
for (auto vbo : _vbos)
glDeleteBuffers(1,&vbo);
_vbos.clear();
}
};
//pipeline > n*pass
//compositor
// render to fbo >
}

177
src/visual/src/shader.cpp Normal file
View file

@ -0,0 +1,177 @@
#include "pw/visual/shader.hpp"
#include "pw/core/debug.hpp"
#include "glad/glad.h"
namespace pw {
// TODO: move this to a separate implementation
struct shader::impl
{
shader& _shader;
GLuint _shader_program;
std::vector<GLuint> _shader_stages;
impl(shader& s)
: _shader(s)
{
}
~impl()
{
clear();
}
bool is_valid()
{
return glIsProgram(_shader_program);
}
void build()
{
for (auto s : _shader._source)
{
GLuint shader_type = 0;
switch (s.first) {
case shader::vertex:
shader_type = GL_VERTEX_SHADER;
break;
case shader::compute:
shader_type = GL_COMPUTE_SHADER;
break;
case shader::geometry:
shader_type = GL_GEOMETRY_SHADER;
break;
case shader::fragment:
shader_type = GL_FRAGMENT_SHADER;
break;
}
GLuint shaderId = glCreateShader(shader_type);
char* src = const_cast<char*>(s.second.c_str());
GLint size = static_cast<GLint>(s.second.length());
glShaderSource(shaderId , 1, &src, &size);
glCompileShader(shaderId);
GLint is_compiled = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &is_compiled);
if(is_compiled == GL_FALSE)
{
GLint log_length;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &log_length);
char* log_buffer = new char[log_length];
glGetShaderInfoLog(shaderId, log_length, &log_length, log_buffer);
// TODO - handle errors!
std::string info_log_string(log_buffer);
delete [] log_buffer;
debug::e() << info_log_string;
break;
}
_shader_stages.push_back(shaderId);
}
_shader_program = glCreateProgram();
for (auto s : _shader_stages)
glAttachShader(_shader_program,s);
// 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. */
// glBindAttribLocation(shaderprogram, 0, "in_Position");
// glBindAttribLocation(shaderprogram, 1, "in_Color");
glLinkProgram(_shader_program);
GLint is_linked = 0;
glGetProgramiv(_shader_program, GL_LINK_STATUS, &is_linked);
if(is_linked == GL_FALSE)
{
GLint log_length;
/* Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. */
glGetProgramiv(_shader_program, GL_INFO_LOG_LENGTH, &log_length);
/* The maxLength includes the NULL character */
char* info_log = new char[log_length];
/* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */
glGetProgramInfoLog(_shader_program, log_length, &log_length, info_log);
std::string info_log_string;
debug::e() << info_log_string;
/* 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 */
delete [] info_log;
return;
}
}
void use()
{
glUseProgram(_shader_program);
}
void clear()
{
if (is_valid()) {
glDeleteProgram(_shader_program);
for (auto s : _shader_stages)
{
glDeleteShader(s);
}
}
}
void set_uniform(const std::string& name,const matrix4x4f& m)
{
GLint l = glGetUniformLocation(_shader_program,name.c_str());
glUniformMatrix4fv(l,1,GL_FALSE,m.data()); // TODO transpose?
}
};
shader::shader()
{
_impl = make_unique<impl>(*this);
}
bool shader::ready() const
{
return _impl->is_valid();
}
}