Rearrange the wip stuff again. I think combining shaders with vaos is a good idea since they seem to work together a lot. Plus I'm pretty sure that's sorta how vulkan works.

This commit is contained in:
rexy712 2022-02-23 16:34:26 -08:00
parent 6e54ae74a7
commit 8a0947e750
20 changed files with 353 additions and 170 deletions

View File

@ -20,9 +20,12 @@
#define OUR_DICK_GRAPHICS_OGL_SHADER_STAGE_HPP
#include "gl_include.hpp"
#include "wip/shader_source.hpp"
#include <string>
namespace wip::gfx{
struct shader_source;
}
namespace gfx::ogl{
//class representing an opengl shader (NOT an opengl program)

View File

@ -43,7 +43,6 @@ public:
private:
math::vec4f m_color_filter;
wip::gfx::vertex_binding_object m_color_binding;
public:
state value = state::BLANK;

View File

@ -22,6 +22,8 @@
#include "shader_source.hpp"
#include "gfx/ogl/shader_stage.hpp"
#include "shader.hpp"
namespace wip::gfx::ogl{
class base_shader
@ -31,14 +33,16 @@ namespace wip::gfx::ogl{
{
.text =
R"glsl(
#version 430 core
#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 tex_coords;
layout (location = 3) in vec4 fcolor;
layout (std140) uniform mvp_matrix{
layout (binding = 0, std140) uniform mvp_matrix{
mat4 vp_mat;
};
layout (binding = 1, std140) uniform model_matrix{
mat4 model_mat;
};
@ -55,12 +59,12 @@ namespace wip::gfx::ogl{
}
)glsl",
.len = 0,
.type = static_cast<unsigned int>(::gfx::ogl::shader_stage::type::VERTEX)
.type = shader_type::VERTEX
},
{
.text =
R"glsl(
#version 430 core
#version 450 core
in VS_OUT{
vec2 tex_coords;
@ -69,7 +73,7 @@ namespace wip::gfx::ogl{
out vec4 frag_color;
uniform sampler2D diffuse_texture;
layout (binding = 0) uniform sampler2D diffuse_texture;
uniform vec4 diffuse;
void main(){
@ -77,7 +81,7 @@ namespace wip::gfx::ogl{
}
)glsl",
.len = 0,
.type = static_cast<unsigned int>(::gfx::ogl::shader_stage::type::FRAGMENT)
.type = shader_type::FRAGMENT
}
};
static inline constexpr const char* vertex_shader_text = sources[0].text;

77
include/wip/ogl_enums.hpp Normal file
View File

@ -0,0 +1,77 @@
/**
This file is a part of our_dick
Copyright (C) 2022 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OUR_DICK_GRAPHICS_WIP_OGL_ENUMS_HPP
#define OUR_DICK_GRAPHICS_WIP_OGL_ENUMS_HPP
#include "gfx/ogl/vbo.hpp"
#include "gfx/ogl/shader_stage.hpp"
namespace wip::gfx::ogl{
enum class attrib_type{
FLOAT,
DOUBLE,
BYTE,
UBYTE,
SHORT,
USHORT,
INT,
UINT
};
struct shader_type
{
protected:
using underlying_type = ::gfx::ogl::shader_stage::type;
underlying_type m_value;
constexpr shader_type(underlying_type t):
m_value(t){}
public:
constexpr operator underlying_type(void)const{return m_value;}
public:
static const shader_type VERTEX;
static const shader_type FRAGMENT;
static const shader_type GEOMETRY;
static const shader_type COMPUTE;
};
constexpr shader_type shader_type::VERTEX = underlying_type::VERTEX;
constexpr shader_type shader_type::FRAGMENT = underlying_type::FRAGMENT;
constexpr shader_type shader_type::GEOMETRY = underlying_type::GEOMETRY;
constexpr shader_type shader_type::COMPUTE = underlying_type::COMPUTE;
struct buffer_type
{
protected:
using underlying_type = ::gfx::ogl::buffer::usage;
underlying_type m_value;
constexpr buffer_type(underlying_type t):
m_value(t){}
public:
constexpr operator underlying_type(void)const{return m_value;}
public:
static const buffer_type STATIC;
static const buffer_type DYNAMIC;
static const buffer_type STREAM;
};
constexpr buffer_type buffer_type::STATIC = underlying_type::STATIC_DRAW;
constexpr buffer_type buffer_type::DYNAMIC = underlying_type::DYNAMIC_DRAW;
constexpr buffer_type buffer_type::STREAM = underlying_type::STREAM_DRAW;
}
#endif

View File

@ -35,7 +35,7 @@ namespace wip::gfx::ogl{
class mesh
{
private:
public:
size_t m_num_vertices;
::gfx::ogl::vbo m_buffer;
::gfx::ogl::vao m_attributes;

View File

@ -37,7 +37,8 @@ namespace wip::gfx::ogl{
using container_type = resource_manager::container_type<T>;
protected:
::gfx::ogl::ubo<math::mat4f,math::mat4f> m_camera_uniform;
::gfx::ogl::ubo<math::mat4f> m_camera_uniform;
::gfx::ogl::ubo<math::mat4f> m_model_uniform;
public:
renderer(void) = default;

View File

@ -19,79 +19,47 @@
#ifndef OUR_DICK_GRAPHICS_WIP_OGL_SHADER_HPP
#define OUR_DICK_GRAPHICS_WIP_OGL_SHADER_HPP
#include <array>
#include <cstdlib> //size_t
#include "gfx/ogl/shader_program.hpp"
#include "gfx/ogl/vao.hpp"
#include "gfx/ogl/vbo.hpp"
#include "gfx/ogl/texture.hpp"
#include "ogl_enums.hpp"
#include <cstdlib> //size_t
namespace wip::gfx{
class pipeline_setup;
}
namespace wip::gfx::ogl{
class vertex_binding_object
{
friend class shader;
public:
enum class type : int{
STATIC = static_cast<int>(::gfx::ogl::buffer::usage::STATIC_DRAW),
DYNAMIC = static_cast<int>(::gfx::ogl::buffer::usage::DYNAMIC_DRAW),
STREAM = static_cast<int>(::gfx::ogl::buffer::usage::STREAM_DRAW)
};
enum class array_type : int{
DISABLE,
FLOAT,
DOUBLE,
BYTE,
UBYTE,
SHORT,
USHORT,
INT,
UINT
};
struct attrib_info{
int offset;
int size;
array_type type;
};
protected:
::gfx::ogl::vbo m_buffer;
std::array<attrib_info,32> m_locations;
size_t m_stride = 0;
size_t m_binding_point = 0;
public:
vertex_binding_object(type t = type::STATIC);
~vertex_binding_object(void) = default;
void buffer(const void* data, size_t size, size_t offset);
void buffer(const math::vec4f& v, size_t offset);
void assign_location(int location, size_t size, size_t offset, array_type type);
void disable_location(int location);
};
using buffer = ::gfx::ogl::vbo;
using shader_stage = ::gfx::ogl::shader_stage;
class shader
{
private:
struct attrib_info{
size_t stride;
};
private:
::gfx::ogl::shader_program m_shader;
::gfx::ogl::vao m_attributes;
public:
template<class... Ts>
shader(Ts&&... ts);
shader(const pipeline_setup& s);
void init_vertex_binding(const vertex_binding_object& v);
void use_vertex_binding(const vertex_binding_object& v);
void bind_attribute(const buffer&, int binding, size_t offset, size_t stride);
void bind_uniform(const buffer&, int binding);
void bind_texture(const ::gfx::ogl::texture&, int binding);
void bind(void);
private:
static void define_array_(::gfx::ogl::vertex_attribute& attrib, vertex_binding_object::array_type type, int count, int offset);
void enable_attribs_(const pipeline_setup& s);
void attach_stages_(const pipeline_setup& s);
};
template<class... Ts>
shader::shader(Ts&&... ts):
m_shader(std::forward<Ts>(ts)...){}
}
#endif

49
include/wip/pipeline.hpp Normal file
View File

@ -0,0 +1,49 @@
/**
This file is a part of our_dick
Copyright (C) 2022 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OUR_DICK_GRAPHICS_WIP_PIPELINE_HPP
#define OUR_DICK_GRAPHICS_WIP_PIPELINE_HPP
#include "shader.hpp"
#include <vector>
namespace wip::gfx{
class pipeline_setup
{
friend shader;
protected:
std::vector<shader_stage> m_stages;
std::vector<vertex_attribute> m_attributes;
public:
pipeline_setup(void) = default;
void add_attribute(const vertex_attribute&);
void add_shader_stage(const shader_stage&);
template<class... Ts>
void emplace_shader_stage(Ts&&... ts);
};
template<class... Ts>
void pipeline_setup::emplace_shader_stage(Ts&&... ts){
m_stages.emplace_back(std::forward<Ts>(ts)...);
}
}
#endif

View File

@ -24,6 +24,7 @@
#include "mesh.hpp"
#include "surface.hpp"
#include "draw_command.hpp"
#include "shader.hpp"
#include <list>
@ -42,6 +43,7 @@ namespace wip::gfx{
container_type<material> m_materials;
container_type<mesh> m_meshs;
container_type<surface> m_surfaces;
container_type<shader> m_shaders;
std::list<draw_command> m_commands;
@ -61,6 +63,8 @@ namespace wip::gfx{
container_type<material>& materials(void);
const container_type<surface>& surfaces(void)const;
container_type<surface>& surfaces(void);
const container_type<shader>& shaders(void)const;
container_type<shader>& shaders(void);
void submit_command(const draw_command& c);
void render(void);

View File

@ -19,44 +19,31 @@
#ifndef OUR_DICK_GRAPHICS_WIP_SHADER_HPP
#define OUR_DICK_GRAPHICS_WIP_SHADER_HPP
#include <cstdlib> //size_t
#include "gfx/ogl/vbo.hpp"
#include "gfx/ogl/vao.hpp"
#include "gfx/ogl/shader_program.hpp"
#include "math/vec.hpp"
#include "ogl_shader.hpp"
#include <utility> //forward
#include <cstdlib> //size_t
namespace wip::gfx{
namespace impl = ogl;
//TODO
//An intermediary class should be used instead of using vao, vbo, ubo, etc directly.
//The idea is to have this api agnostic shader class spawn different 'binding' objects and then use those to set the
//data for uniforms, vertex attributes, and per instance attributes. This entire mechanism needs to be implemented before I can
//restore the functionality of changing the colors of the tic-tac-toe tiles...
using attrib_type = impl::attrib_type;
using shader_type = impl::shader_type;
using buffer_type = impl::buffer_type;
class vertex_binding_object : public ogl::vertex_binding_object
{
public:
using array_type = ogl::vertex_binding_object::array_type;
using buffer = impl::buffer;
using shader_stage = impl::shader_stage;
using shader = impl::shader;
protected:
ogl::vertex_binding_object m_impl;
public:
using ogl::vertex_binding_object::vertex_binding_object;
struct vertex_attribute{
int location;
int binding;
size_t offset;
size_t count;
attrib_type type;
};
class shader : public ogl::shader
{
public:
using ogl::shader::shader;
};
}
#endif

View File

@ -21,12 +21,14 @@
#include <cstdlib> //size_t
#include "shader.hpp"
namespace wip::gfx{
struct shader_source{
const char* text;
size_t len;
unsigned int type;
shader_type type;
};
}

View File

@ -55,7 +55,9 @@ namespace gfx::ogl{
}
GLuint shader_program::get_uniform_block_loc(const char* u)const{
return glGetUniformBlockIndex(m_shader_id, u);
GLuint i = glGetUniformBlockIndex(m_shader_id, u);
debug_print_info("%d\n", i);
return i;
}
GLint shader_program::get_uniform_loc(const char* u)const{
return glGetUniformLocation(m_shader_id, u);

View File

@ -17,6 +17,7 @@
*/
#include "gfx/ogl/shader_stage.hpp"
#include "wip/shader_source.hpp"
#include "config.hpp"
#include <utility> //exchange, swap

View File

@ -18,22 +18,13 @@
#include "ttt/board.hpp"
new_tile::new_tile(void):
m_color_binding(wip::gfx::vertex_binding_object::type::DYNAMIC)
{
m_color_binding.assign_location(3, sizeof(m_color_filter), 0, wip::gfx::ogl::vertex_binding_object::array_type::FLOAT);
}
new_tile::new_tile(void){}
new_tile::new_tile(state start_value):
m_color_binding(wip::gfx::vertex_binding_object::type::DYNAMIC),
value(start_value)
{
m_color_binding.assign_location(3, sizeof(m_color_filter), 0, wip::gfx::ogl::vertex_binding_object::array_type::FLOAT);
}
value(start_value){}
void new_tile::set_color(const math::vec4f& color){
m_color_filter = color;
m_color_binding.buffer(color, 0);
}
const math::vec4f& new_tile::get_color(void)const{
return m_color_filter;

View File

@ -24,18 +24,31 @@
#include "gfx/ogl/gl_include.hpp" //TODO
#include "wip/base_shader.hpp"
#include "wip/square.hpp"
#include "wip/shader.hpp"
#include "wip/pipeline.hpp"
#include "config.hpp"
#include <vector>
#include <utility> //pair
std::shared_ptr<wip::gfx::shader> create_base_shader(wip::gfx::renderer& r){
wip::gfx::pipeline_setup setup;
setup.add_attribute({0, 0, 0, 3, wip::gfx::attrib_type::FLOAT});
setup.add_attribute({1, 0, sizeof(float) * 3, 2, wip::gfx::attrib_type::FLOAT});
setup.add_attribute({2, 1, 0, 4, wip::gfx::attrib_type::FLOAT});
setup.emplace_shader_stage(wip::gfx::base_shader::sources[0]);
setup.emplace_shader_stage(wip::gfx::base_shader::sources[1]);
return r.shaders().emplace_value("base_shader", setup).first;
}
pause_state::pause_state(egn::game& owner, egn::game_state_iface* under):
game_state_iface(&owner),
m_under_state(under),
m_main_camera(10, 10, 0.1, 50),
m_elapsed_time(0)
{
auto new_shader = create_base_shader(renderer());
//TODO hide GL implementation details somewhere else
auto vert = renderer().shader_stages().emplace_value("base_vert", wip::gfx::base_shader::sources[0]).first;
auto frag = renderer().shader_stages().emplace_value("base_frag", wip::gfx::base_shader::sources[1]).first;
@ -50,6 +63,7 @@ pause_state::pause_state(egn::game& owner, egn::game_state_iface* under):
auto mesh = renderer().meshs().emplace_value("square_mesh", wip::square::mesh_vertices, 6).first;
m_square.reset(new wip::square(mesh, material));
new_shader->bind_attribute(m_square->m_mesh->m_buffer, 0, 0, sizeof(float) * 5);
m_main_camera.set_position({0, 0, 5});
}

View File

@ -30,7 +30,8 @@ namespace wip::gfx::ogl{
void material::bind(void){
if(diffuse_texture){
shader->get_uniform("diffuse_texture").set(*diffuse_texture, 0);
diffuse_texture->bind_unit(0);
//shader->get_uniform("diffuse_texture").set(*diffuse_texture, 0);
}
shader->get_uniform("diffuse").set(diffuse);
}

View File

@ -25,7 +25,7 @@ namespace wip::gfx::ogl{
glViewport(vp.x(), vp.y(), vp.z(), vp.w());
}
void renderer::set_model_matrix(const math::mat4f& mat){
m_camera_uniform.set<1>(mat);
m_model_uniform.set<0>(mat);
}
void renderer::set_camera(const math::mat4f& view, const math::mat4f& proj){
m_camera_uniform.set<0>(proj * view);
@ -53,7 +53,8 @@ namespace wip::gfx::ogl{
if(c.mat){
::gfx::ogl::shader_program& shade = *c.mat->shader;
shade.use();
shade.get_uniform_block("mvp_matrix").set_binding(0, m_camera_uniform);
m_camera_uniform.bind(0);
m_model_uniform.bind(1);
c.mat->bind();
}
//static_cast is fine; we know this is always the base class of renderer if we made it to this point

View File

@ -17,76 +17,119 @@
*/
#include "wip/ogl_shader.hpp"
#include "wip/pipeline.hpp"
#include "gfx/ogl/shader_stage.hpp"
#include "config.hpp"
namespace wip::gfx::ogl{
vertex_binding_object::vertex_binding_object(type t):
m_buffer(0, static_cast<::gfx::ogl::buffer::usage>(t)){}
void vertex_binding_object::buffer(const void* data, size_t size, size_t offset){
m_buffer.buffer(data, size, offset);
static constexpr shader_stage::type map_type(shader_type in){
using in_type = shader_type;
using out_type = shader_stage::type;
switch(in){
case in_type::VERTEX:
return out_type::VERTEX;
case in_type::FRAGMENT:
return out_type::FRAGMENT;
case in_type::GEOMETRY:
return out_type::GEOMETRY;
case in_type::COMPUTE:
return out_type::COMPUTE;
default:
return out_type::VERTEX;
};
}
static constexpr shader_type map_type(shader_stage::type in){
using in_type = shader_stage::type;
using out_type = shader_type;
switch(in){
case in_type::VERTEX:
return out_type::VERTEX;
case in_type::FRAGMENT:
return out_type::FRAGMENT;
case in_type::GEOMETRY:
return out_type::GEOMETRY;
case in_type::COMPUTE:
return out_type::COMPUTE;
default:
return out_type::VERTEX;
};
}
static constexpr ::gfx::ogl::buffer::usage map_type(buffer_type in){
using in_type = buffer_type;
using out_type = ::gfx::ogl::buffer::usage;
switch(in){
case in_type::STATIC:
return out_type::STATIC_DRAW;
case in_type::DYNAMIC:
return out_type::DYNAMIC_DRAW;
case in_type::STREAM:
return out_type::STREAM_DRAW;
default:
return out_type::STATIC_DRAW;
};
}
void vertex_binding_object::buffer(const math::vec4f& v, size_t offset){
buffer(v.raw(), sizeof(math::vec4f::value_type), offset);
}
void vertex_binding_object::assign_location(int location, size_t size, size_t offset, array_type type){
m_locations[location].offset = offset;
m_locations[location].size = size;
m_locations[location].type = type;
}
void vertex_binding_object::disable_location(int location){
m_locations[location].size = 0;
shader::shader(const pipeline_setup& s){
enable_attribs_(s);
attach_stages_(s);
}
void shader::init_vertex_binding(const vertex_binding_object& v){
use_vertex_binding(v);
for(size_t i = 0;i < v.m_locations.size();++i){
const auto offset = v.m_locations[i].offset;
const auto size = v.m_locations[i].size;
const auto type = v.m_locations[i].type;
void shader::bind_attribute(const buffer& b, int binding, size_t offset, size_t stride){
m_attributes.bind_buffer(b, binding, offset, stride);
}
void shader::bind_uniform(const buffer& b, int binding){
glBindBufferBase(GL_UNIFORM_BUFFER, binding, b.raw());
}
void shader::bind_texture(const ::gfx::ogl::texture& t, int binding){
t.bind_unit(binding);
}
if(size == 0)
continue;
auto attrib = m_attributes.get_attribute(i);
define_array_(attrib, type, size, offset);
attrib.associate_with(v.m_binding_point);
void shader::bind(void){
m_shader.use();
m_attributes.bind();
}
void shader::enable_attribs_(const pipeline_setup& s){
for(auto& a : s.m_attributes){
auto attrib = m_attributes.get_attribute(a.location);
attrib.associate_with(a.binding);
switch(a.type){
case attrib_type::FLOAT:
attrib.set_float_array(a.count, a.offset);
break;
case attrib_type::DOUBLE:
attrib.set_double_array(a.count, a.offset);
break;
case attrib_type::BYTE:
attrib.set_byte_array(a.count, a.offset);
break;
case attrib_type::UBYTE:
attrib.set_ubyte_array(a.count, a.offset);
break;
case attrib_type::SHORT:
attrib.set_short_array(a.count, a.offset);
break;
case attrib_type::USHORT:
attrib.set_ushort_array(a.count, a.offset);
break;
case attrib_type::INT:
attrib.set_int_array(a.count, a.offset);
break;
case attrib_type::UINT:
attrib.set_uint_array(a.count, a.offset);
break;
};
attrib.enable();
}
}
void shader::use_vertex_binding(const vertex_binding_object& v){
m_attributes.bind_buffer(v.m_buffer, v.m_binding_point, 0, v.m_stride);
}
void shader::define_array_(::gfx::ogl::vertex_attribute& attrib, vertex_binding_object::array_type type, int size, int offset){
using array_type = vertex_binding_object::array_type;
switch(type){
case array_type::FLOAT:
attrib.set_float_array(size / sizeof(float), offset);
break;
case array_type::DOUBLE:
attrib.set_double_array(size / sizeof(double), offset);
break;
case array_type::BYTE:
attrib.set_byte_array(size, offset);
break;
case array_type::UBYTE:
attrib.set_ubyte_array(size, offset);
break;
case array_type::SHORT:
attrib.set_short_array(size / sizeof(short), offset);
break;
case array_type::USHORT:
attrib.set_ushort_array(size / sizeof(unsigned short), offset);
break;
case array_type::INT:
attrib.set_int_array(size / sizeof(int), offset);
break;
case array_type::UINT:
attrib.set_uint_array(size / sizeof(unsigned int), offset);
break;
default:
break;
};
void shader::attach_stages_(const pipeline_setup& s){
for(auto& sh : s.m_stages){
m_shader.attach_shader(sh);
}
m_shader.link();
if(m_shader.has_link_error()){
debug_print_error("%s\n", m_shader.get_error().c_str());
}
}
}

30
src/wip/pipeline.cpp Normal file
View File

@ -0,0 +1,30 @@
/**
This file is a part of our_dick
Copyright (C) 2022 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "wip/pipeline.hpp"
namespace wip::gfx{
void pipeline_setup::add_attribute(const vertex_attribute& v){
m_attributes.push_back(v);
}
void pipeline_setup::add_shader_stage(const shader_stage& s){
m_stages.push_back(s);
}
}

View File

@ -49,6 +49,12 @@ namespace wip::gfx{
auto renderer::surfaces(void) -> container_type<surface>&{
return m_surfaces;
}
auto renderer::shaders(void)const -> const container_type<shader>&{
return m_shaders;
}
auto renderer::shaders(void) -> container_type<shader>&{
return m_shaders;
}
void renderer::render(void){
for(auto& command : m_commands){
process_command(command);