renamed classes in model.h to be more descriptive
- vbo is now vertex_array - ebo is now element_array etcmain
parent
e25dad380c
commit
23f069e9b0
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
|
|
||||||
set(BLT_GRAPHICS_VERSION 0.13.0)
|
set(BLT_GRAPHICS_VERSION 0.13.1)
|
||||||
set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
|
set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
|
||||||
|
|
||||||
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})
|
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})
|
||||||
|
|
|
@ -32,12 +32,13 @@ namespace blt::gfx
|
||||||
|
|
||||||
class static_dynamic_array;
|
class static_dynamic_array;
|
||||||
|
|
||||||
class vertex_array;
|
class vertex_array_t;
|
||||||
|
|
||||||
struct vbo_t
|
// vbo
|
||||||
|
struct vertex_buffer_t
|
||||||
{
|
{
|
||||||
friend vbo_t_owner;
|
friend vbo_t_owner;
|
||||||
friend vertex_array;
|
friend vertex_array_t;
|
||||||
friend static_dynamic_array;
|
friend static_dynamic_array;
|
||||||
private:
|
private:
|
||||||
GLuint bufferID_ = 0;
|
GLuint bufferID_ = 0;
|
||||||
|
@ -67,34 +68,36 @@ namespace blt::gfx
|
||||||
void destroy();
|
void destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssbo_t : public vbo_t
|
// ssbo
|
||||||
|
struct shader_buffer_t : public vertex_buffer_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline void create()
|
inline void create()
|
||||||
{
|
{
|
||||||
vbo_t::create(GL_SHADER_STORAGE_BUFFER);
|
vertex_buffer_t::create(GL_SHADER_STORAGE_BUFFER);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ebo_t : public vbo_t
|
// ebo
|
||||||
|
struct element_buffer_t : public vertex_buffer_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline void create()
|
inline void create()
|
||||||
{
|
{
|
||||||
vbo_t::create(GL_ELEMENT_ARRAY_BUFFER);
|
vertex_buffer_t::create(GL_ELEMENT_ARRAY_BUFFER);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vbo_t_owner
|
struct vbo_t_owner
|
||||||
{
|
{
|
||||||
vbo_t vbo;
|
vertex_buffer_t vbo;
|
||||||
|
|
||||||
vbo_t_owner() = default;
|
vbo_t_owner() = default;
|
||||||
|
|
||||||
explicit vbo_t_owner(vbo_t vbo): vbo(vbo)
|
explicit vbo_t_owner(vertex_buffer_t vbo): vbo(vbo)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
vbo_t* operator->()
|
vertex_buffer_t* operator->()
|
||||||
{
|
{
|
||||||
return &vbo;
|
return &vbo;
|
||||||
}
|
}
|
||||||
|
@ -153,26 +156,26 @@ namespace blt::gfx
|
||||||
/**
|
/**
|
||||||
* basic VAO class.
|
* basic VAO class.
|
||||||
*/
|
*/
|
||||||
class vertex_array
|
class vertex_array_t
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
GLuint vaoID;
|
GLuint vaoID;
|
||||||
static_dynamic_array VBOs;
|
static_dynamic_array VBOs;
|
||||||
blt::hashset_t<GLuint> used_attributes;
|
blt::hashset_t<GLuint> used_attributes;
|
||||||
vbo_t element;
|
vertex_buffer_t element;
|
||||||
|
|
||||||
void handle_vbo(const vbo_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset);
|
void handle_vbo(const vertex_buffer_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
vertex_array();
|
vertex_array_t();
|
||||||
|
|
||||||
vertex_array(const vertex_array&) = delete;
|
vertex_array_t(const vertex_array_t&) = delete;
|
||||||
|
|
||||||
vertex_array(vertex_array&&) = delete;
|
vertex_array_t(vertex_array_t&&) = delete;
|
||||||
|
|
||||||
vertex_array& operator=(const vertex_array&) = delete;
|
vertex_array_t& operator=(const vertex_array_t&) = delete;
|
||||||
|
|
||||||
vertex_array& operator=(vertex_array&&) = delete;
|
vertex_array_t& operator=(vertex_array_t&&) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function takes ownership of the underlying VBO (GPU side). It will be freed when the basic vertex array is deleted
|
* This function takes ownership of the underlying VBO (GPU side). It will be freed when the basic vertex array is deleted
|
||||||
|
@ -185,12 +188,12 @@ namespace blt::gfx
|
||||||
* @param offset offset into the data structure to where the data is stored
|
* @param offset offset into the data structure to where the data is stored
|
||||||
* @return a shared pointer to the stored vbo. used for chaining VAOs with multiple shared VBOs
|
* @return a shared pointer to the stored vbo. used for chaining VAOs with multiple shared VBOs
|
||||||
*/
|
*/
|
||||||
static_dynamic_array::vbo_type bindVBO(const vbo_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset);
|
static_dynamic_array::vbo_type bindVBO(const vertex_buffer_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset);
|
||||||
|
|
||||||
// same as the other bind method except you provide the shared reference.
|
// same as the other bind method except you provide the shared reference.
|
||||||
void bindVBO(const static_dynamic_array::vbo_type& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset);
|
void bindVBO(const static_dynamic_array::vbo_type& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset);
|
||||||
|
|
||||||
inline void bindElement(const vbo_t& vbo)
|
inline void bindElement(const vertex_buffer_t& vbo)
|
||||||
{
|
{
|
||||||
bind();
|
bind();
|
||||||
element = vbo;
|
element = vbo;
|
||||||
|
@ -198,7 +201,7 @@ namespace blt::gfx
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline vbo_t& getElement()
|
inline vertex_buffer_t& getElement()
|
||||||
{
|
{
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
@ -207,12 +210,12 @@ namespace blt::gfx
|
||||||
* Returns a non-owning reference to a vbo allowing for updating the VBO
|
* Returns a non-owning reference to a vbo allowing for updating the VBO
|
||||||
* The VBO is considered invalid if its ID is 0
|
* The VBO is considered invalid if its ID is 0
|
||||||
*/
|
*/
|
||||||
inline vbo_t& operator[](size_t index)
|
inline vertex_buffer_t& operator[](size_t index)
|
||||||
{
|
{
|
||||||
return getBuffer(index);
|
return getBuffer(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline vbo_t& getBuffer(size_t index)
|
inline vertex_buffer_t& getBuffer(size_t index)
|
||||||
{
|
{
|
||||||
return VBOs[index]->vbo;
|
return VBOs[index]->vbo;
|
||||||
}
|
}
|
||||||
|
@ -227,12 +230,12 @@ namespace blt::gfx
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline static_dynamic_array::vbo_type createSharedVBO(const vbo_t& vbo)
|
static inline static_dynamic_array::vbo_type createSharedVBO(const vertex_buffer_t& vbo)
|
||||||
{
|
{
|
||||||
return std::make_shared<vbo_t_owner>(vbo);
|
return std::make_shared<vbo_t_owner>(vbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
~vertex_array();
|
~vertex_array_t();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "blt/gfx/model.h"
|
#include "blt/gfx/model.h"
|
||||||
#include "blt/gfx/shader.h"
|
#include "blt/gfx/shader.h"
|
||||||
|
#include "blt/gfx/framebuffer.h"
|
||||||
#include "blt/gfx/renderer/resource_manager.h"
|
#include "blt/gfx/renderer/resource_manager.h"
|
||||||
#include <blt/std/hashmap.h>
|
#include <blt/std/hashmap.h>
|
||||||
#include <blt/std/memory_util.h>
|
#include <blt/std/memory_util.h>
|
||||||
|
@ -147,14 +148,7 @@ namespace blt::gfx
|
||||||
class batch_renderer_2d
|
class batch_renderer_2d
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct vec_hash
|
fbo_t draw_buffer;
|
||||||
{
|
|
||||||
std::size_t operator()(const vec4& key) const
|
|
||||||
{
|
|
||||||
using namespace blt::mem;
|
|
||||||
return type_cast<i32>(key.x()) ^ type_cast<i32>(key.y()) ^ type_cast<i32>(key.y()) ^ type_cast<i32>(key.z());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct render_object_t
|
struct render_object_t
|
||||||
|
@ -174,8 +168,8 @@ namespace blt::gfx
|
||||||
using object_container = hashmap_t<std::string, std::vector<std::pair<render_info_t, T>>>;
|
using object_container = hashmap_t<std::string, std::vector<std::pair<render_info_t, T>>>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vertex_array* square_vao = nullptr;
|
vertex_array_t* square_vao = nullptr;
|
||||||
vertex_array* line_vao = nullptr;
|
vertex_array_t* line_vao = nullptr;
|
||||||
shader_t* square_shader = nullptr;
|
shader_t* square_shader = nullptr;
|
||||||
shader_t* point_shader = nullptr;
|
shader_t* point_shader = nullptr;
|
||||||
resource_manager& resources;
|
resource_manager& resources;
|
||||||
|
@ -261,7 +255,7 @@ namespace blt::gfx
|
||||||
void drawLine(const T& render_info, f32 z_index, P... p)
|
void drawLine(const T& render_info, f32 z_index, P... p)
|
||||||
{ drawLineInternal(render_info, {p...}, z_index); }
|
{ drawLineInternal(render_info, {p...}, z_index); }
|
||||||
|
|
||||||
void render(bool transparency = true);
|
void render(i32 width, i32 height, bool transparency = true);
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLT_GRAPHICS_POST_PROCESS_H
|
||||||
|
#define BLT_GRAPHICS_POST_PROCESS_H
|
||||||
|
|
||||||
|
#include <blt/std/types.h>
|
||||||
|
#include <blt/gfx/framebuffer.h>
|
||||||
|
#include <blt/gfx/shader.h>
|
||||||
|
#include <blt/gfx/model.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace blt::gfx
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
class pp_link;
|
||||||
|
|
||||||
|
class pp_iterator;
|
||||||
|
|
||||||
|
class pp_link
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class pp_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class pp_step
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void create(i32 width, i32 height) = 0;
|
||||||
|
|
||||||
|
virtual void draw(i32 width, i32 height) = 0;
|
||||||
|
|
||||||
|
fbo_t& getBuffer()
|
||||||
|
{
|
||||||
|
return draw_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
fbo_t draw_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class pp_engine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void create();
|
||||||
|
|
||||||
|
void render(i32 width, i32 height);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<pp_step>> steps;
|
||||||
|
shader_t screen_shader;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //BLT_GRAPHICS_POST_PROCESS_H
|
|
@ -394,7 +394,7 @@ static void particle_engine(double t, float dt)
|
||||||
static void draw_particles(GLFWwindow* window, double t, float dt)
|
static void draw_particles(GLFWwindow* window, double t, float dt)
|
||||||
{
|
{
|
||||||
int i, particle_count;
|
int i, particle_count;
|
||||||
Vertex vertex_array[BATCH_PARTICLES * PARTICLE_VERTS];
|
Vertex vertex_array_t[BATCH_PARTICLES * PARTICLE_VERTS];
|
||||||
Vertex* vptr;
|
Vertex* vptr;
|
||||||
float alpha;
|
float alpha;
|
||||||
GLuint rgba;
|
GLuint rgba;
|
||||||
|
@ -449,7 +449,7 @@ static void draw_particles(GLFWwindow* window, double t, float dt)
|
||||||
// situations). GL_T2F_C4UB_V3F means: 2 floats for texture coords,
|
// situations). GL_T2F_C4UB_V3F means: 2 floats for texture coords,
|
||||||
// 4 ubytes for color and 3 floats for vertex coord (in that order).
|
// 4 ubytes for color and 3 floats for vertex coord (in that order).
|
||||||
// Most OpenGL cards / drivers are optimized for this format.
|
// Most OpenGL cards / drivers are optimized for this format.
|
||||||
glInterleavedArrays(GL_T2F_C4UB_V3F, 0, vertex_array);
|
glInterleavedArrays(GL_T2F_C4UB_V3F, 0, vertex_array_t);
|
||||||
|
|
||||||
// Wait for particle physics thread to be done
|
// Wait for particle physics thread to be done
|
||||||
mtx_lock(&thread_sync.particles_lock);
|
mtx_lock(&thread_sync.particles_lock);
|
||||||
|
@ -473,7 +473,7 @@ static void draw_particles(GLFWwindow* window, double t, float dt)
|
||||||
|
|
||||||
// Loop through all particles and build vertex arrays.
|
// Loop through all particles and build vertex arrays.
|
||||||
particle_count = 0;
|
particle_count = 0;
|
||||||
vptr = vertex_array;
|
vptr = vertex_array_t;
|
||||||
pptr = particles;
|
pptr = particles;
|
||||||
|
|
||||||
for (i = 0; i < MAX_PARTICLES; i++)
|
for (i = 0; i < MAX_PARTICLES; i++)
|
||||||
|
@ -546,7 +546,7 @@ static void draw_particles(GLFWwindow* window, double t, float dt)
|
||||||
// The last argument is the vertex count
|
// The last argument is the vertex count
|
||||||
glDrawArrays(GL_QUADS, 0, PARTICLE_VERTS * particle_count);
|
glDrawArrays(GL_QUADS, 0, PARTICLE_VERTS * particle_count);
|
||||||
particle_count = 0;
|
particle_count = 0;
|
||||||
vptr = vertex_array;
|
vptr = vertex_array_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next particle
|
// Next particle
|
||||||
|
|
|
@ -152,6 +152,9 @@ namespace blt::gfx
|
||||||
|
|
||||||
void fbo_t::updateBuffersStorage(blt::i32 width, blt::i32 height)
|
void fbo_t::updateBuffersStorage(blt::i32 width, blt::i32 height)
|
||||||
{
|
{
|
||||||
|
if (width == width_ && height == height_)
|
||||||
|
return;
|
||||||
|
|
||||||
width_ = width;
|
width_ = width;
|
||||||
height_ = height;
|
height_ = height;
|
||||||
for (auto& rbo : render_buffers)
|
for (auto& rbo : render_buffers)
|
||||||
|
@ -162,6 +165,9 @@ namespace blt::gfx
|
||||||
|
|
||||||
for (auto& texture : texture_buffers)
|
for (auto& texture : texture_buffers)
|
||||||
texture->updateSize(width, height);
|
texture->updateSize(width, height);
|
||||||
|
|
||||||
|
if (!fbo_t::validate())
|
||||||
|
BLT_ERROR("Failed to update framebuffer storage size!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void fbo_t::blitTexture(const fbo_t& draw, blt::i32 srcX, blt::i32 srcY, blt::i32 destX, blt::i32 destY, GLuint filter,
|
void fbo_t::blitTexture(const fbo_t& draw, blt::i32 srcX, blt::i32 srcY, blt::i32 destX, blt::i32 destY, GLuint filter,
|
||||||
|
|
|
@ -61,13 +61,13 @@ namespace blt::gfx
|
||||||
* vbo_t
|
* vbo_t
|
||||||
* -----------------------------------
|
* -----------------------------------
|
||||||
*/
|
*/
|
||||||
void vbo_t::create(GLint type)
|
void vertex_buffer_t::create(GLint type)
|
||||||
{
|
{
|
||||||
glGenBuffers(1, &bufferID_);
|
glGenBuffers(1, &bufferID_);
|
||||||
buffer_type = type;
|
buffer_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vbo_t::destroy()
|
void vertex_buffer_t::destroy()
|
||||||
{
|
{
|
||||||
// prevent multiple destroys of the same object, in cases of multi attribute binds
|
// prevent multiple destroys of the same object, in cases of multi attribute binds
|
||||||
if (bufferID_ == 0)
|
if (bufferID_ == 0)
|
||||||
|
@ -76,7 +76,7 @@ namespace blt::gfx
|
||||||
bufferID_ = 0;
|
bufferID_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vbo_t::allocate(GLsizeiptr size, GLint mem_type, const void* data)
|
void vertex_buffer_t::allocate(GLsizeiptr size, GLint mem_type, const void* data)
|
||||||
{
|
{
|
||||||
bind();
|
bind();
|
||||||
size_ = size;
|
size_ = size;
|
||||||
|
@ -84,7 +84,7 @@ namespace blt::gfx
|
||||||
memory_type = mem_type;
|
memory_type = mem_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vbo_t::update(GLsizeiptr size, void* data)
|
void vertex_buffer_t::update(GLsizeiptr size, void* data)
|
||||||
{
|
{
|
||||||
if (size <= size_)
|
if (size <= size_)
|
||||||
sub_update(0, size, data);
|
sub_update(0, size, data);
|
||||||
|
@ -93,18 +93,18 @@ namespace blt::gfx
|
||||||
size_ = size;
|
size_ = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vbo_t::sub_update(GLsizeiptr offset, GLsizeiptr size, void* data) const
|
void vertex_buffer_t::sub_update(GLsizeiptr offset, GLsizeiptr size, void* data) const
|
||||||
{
|
{
|
||||||
bind();
|
bind();
|
||||||
glBufferSubData(buffer_type, offset, size, data);
|
glBufferSubData(buffer_type, offset, size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vbo_t::bind() const
|
void vertex_buffer_t::bind() const
|
||||||
{
|
{
|
||||||
glBindBuffer(buffer_type, bufferID_);
|
glBindBuffer(buffer_type, bufferID_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vbo_t::unbind() const
|
void vertex_buffer_t::unbind() const
|
||||||
{
|
{
|
||||||
glBindBuffer(buffer_type, 0);
|
glBindBuffer(buffer_type, 0);
|
||||||
}
|
}
|
||||||
|
@ -115,12 +115,12 @@ namespace blt::gfx
|
||||||
* ----------------------------
|
* ----------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
vertex_array::vertex_array(): vaoID(0)
|
vertex_array_t::vertex_array_t(): vaoID(0)
|
||||||
{
|
{
|
||||||
glGenVertexArrays(1, &vaoID);
|
glGenVertexArrays(1, &vaoID);
|
||||||
}
|
}
|
||||||
|
|
||||||
vertex_array::~vertex_array()
|
vertex_array_t::~vertex_array_t()
|
||||||
{
|
{
|
||||||
// free all VBOs
|
// free all VBOs
|
||||||
for (size_t i = 0; i < VBOs.used(); i++)
|
for (size_t i = 0; i < VBOs.used(); i++)
|
||||||
|
@ -130,21 +130,21 @@ namespace blt::gfx
|
||||||
glDeleteVertexArrays(1, &vaoID);
|
glDeleteVertexArrays(1, &vaoID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_dynamic_array::vbo_type vertex_array::bindVBO(const vbo_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride,
|
static_dynamic_array::vbo_type vertex_array_t::bindVBO(const vertex_buffer_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride,
|
||||||
long offset)
|
long offset)
|
||||||
{
|
{
|
||||||
handle_vbo(vbo, attribute_number, coordinate_size, type, stride, offset);
|
handle_vbo(vbo, attribute_number, coordinate_size, type, stride, offset);
|
||||||
VBOs[attribute_number] = createSharedVBO(vbo);
|
VBOs[attribute_number] = createSharedVBO(vbo);
|
||||||
return VBOs[attribute_number];
|
return VBOs[attribute_number];
|
||||||
}
|
}
|
||||||
|
|
||||||
void vertex_array::bindVBO(const static_dynamic_array::vbo_type& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset)
|
void vertex_array_t::bindVBO(const static_dynamic_array::vbo_type& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset)
|
||||||
{
|
{
|
||||||
handle_vbo(vbo->vbo, attribute_number, coordinate_size, type, stride, offset);
|
handle_vbo(vbo->vbo, attribute_number, coordinate_size, type, stride, offset);
|
||||||
VBOs[attribute_number] = vbo;
|
VBOs[attribute_number] = vbo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vertex_array::handle_vbo(const vbo_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset)
|
void vertex_array_t::handle_vbo(const vertex_buffer_t& vbo, int attribute_number, int coordinate_size, GLenum type, int stride, long offset)
|
||||||
{
|
{
|
||||||
used_attributes.insert(attribute_number);
|
used_attributes.insert(attribute_number);
|
||||||
bind();
|
bind();
|
||||||
|
|
|
@ -51,8 +51,8 @@ namespace blt::gfx
|
||||||
void batch_renderer_2d::create()
|
void batch_renderer_2d::create()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
vbo_t vertices_vbo;
|
vertex_buffer_t vertices_vbo;
|
||||||
ebo_t indices_vbo;
|
element_buffer_t indices_vbo;
|
||||||
|
|
||||||
vertices_vbo.create();
|
vertices_vbo.create();
|
||||||
indices_vbo.create();
|
indices_vbo.create();
|
||||||
|
@ -60,14 +60,14 @@ namespace blt::gfx
|
||||||
vertices_vbo.allocate(sizeof(square_vertices), square_vertices);
|
vertices_vbo.allocate(sizeof(square_vertices), square_vertices);
|
||||||
indices_vbo.allocate(sizeof(square_indices), square_indices);
|
indices_vbo.allocate(sizeof(square_indices), square_indices);
|
||||||
|
|
||||||
square_vao = new vertex_array();
|
square_vao = new vertex_array_t();
|
||||||
const auto tb = square_vao->bindVBO(vertices_vbo, 0, 3, GL_FLOAT, 5 * sizeof(float), 0);
|
const auto tb = square_vao->bindVBO(vertices_vbo, 0, 3, GL_FLOAT, 5 * sizeof(float), 0);
|
||||||
square_vao->bindVBO(tb, 1, 2, GL_FLOAT, 5 * sizeof(float), 3 * sizeof(float));
|
square_vao->bindVBO(tb, 1, 2, GL_FLOAT, 5 * sizeof(float), 3 * sizeof(float));
|
||||||
square_vao->bindElement(indices_vbo);
|
square_vao->bindElement(indices_vbo);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
vbo_t vertices_vbo;
|
vertex_buffer_t vertices_vbo;
|
||||||
ebo_t indices_vbo;
|
element_buffer_t indices_vbo;
|
||||||
|
|
||||||
vertices_vbo.create();
|
vertices_vbo.create();
|
||||||
indices_vbo.create();
|
indices_vbo.create();
|
||||||
|
@ -75,7 +75,7 @@ namespace blt::gfx
|
||||||
vertices_vbo.allocate(sizeof(line_vertices), line_vertices);
|
vertices_vbo.allocate(sizeof(line_vertices), line_vertices);
|
||||||
indices_vbo.allocate(sizeof(square_indices), square_indices);
|
indices_vbo.allocate(sizeof(square_indices), square_indices);
|
||||||
|
|
||||||
line_vao = new vertex_array();
|
line_vao = new vertex_array_t();
|
||||||
auto tb = line_vao->bindVBO(vertices_vbo, 0, 3, GL_FLOAT, 5 * sizeof(float), 0);
|
auto tb = line_vao->bindVBO(vertices_vbo, 0, 3, GL_FLOAT, 5 * sizeof(float), 0);
|
||||||
line_vao->bindVBO(tb, 1, 2, GL_FLOAT, 5 * sizeof(float), 3 * sizeof(float));
|
line_vao->bindVBO(tb, 1, 2, GL_FLOAT, 5 * sizeof(float), 3 * sizeof(float));
|
||||||
line_vao->bindElement(indices_vbo);
|
line_vao->bindElement(indices_vbo);
|
||||||
|
@ -88,6 +88,21 @@ namespace blt::gfx
|
||||||
point_shader = new shader_t(shader_2d_textured_vert, shader_2d_textured_cirlce_frag);
|
point_shader = new shader_t(shader_2d_textured_vert, shader_2d_textured_cirlce_frag);
|
||||||
point_shader->bindAttribute(0, "vertex");
|
point_shader->bindAttribute(0, "vertex");
|
||||||
point_shader->bindAttribute(1, "uv_in");
|
point_shader->bindAttribute(1, "uv_in");
|
||||||
|
|
||||||
|
draw_buffer.create();
|
||||||
|
draw_buffer.bind();
|
||||||
|
|
||||||
|
auto* texture = new texture_gl2D(1440, 720);
|
||||||
|
draw_buffer.attachTexture(texture, fbo_t::attachment_t::COLOR0);
|
||||||
|
auto* mask = new texture_gl2D(1440, 720);
|
||||||
|
draw_buffer.attachTexture(mask, fbo_t::attachment_t::COLOR1);
|
||||||
|
|
||||||
|
rbo_t depth_rbo = rbo_t::make_render_buffer(GL_DEPTH24_STENCIL8, 1440, 720);
|
||||||
|
draw_buffer.attachRenderBuffer(depth_rbo, fbo_t::attachment_t::DEPTH_STENCIL);
|
||||||
|
|
||||||
|
if (!fbo_t::validate())
|
||||||
|
BLT_ERROR("Failed to create render framebuffer!");
|
||||||
|
fbo_t::unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void batch_renderer_2d::drawRectangleInternal(const std::string_view texture, const rectangle2d_t& rectangle, const f32 z_index)
|
void batch_renderer_2d::drawRectangleInternal(const std::string_view texture, const rectangle2d_t& rectangle, const f32 z_index)
|
||||||
|
@ -151,27 +166,11 @@ namespace blt::gfx
|
||||||
delete point_shader;
|
delete point_shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
void batch_renderer_2d::render(i32 width, i32 height, const bool transparency)
|
||||||
void find_min_and_max(T& container, f32& min, f32& max)
|
|
||||||
{
|
|
||||||
for (auto& textures : container)
|
|
||||||
{
|
|
||||||
for (auto& colors : textures.second)
|
|
||||||
{
|
|
||||||
for (auto& blend_factors : colors.second)
|
|
||||||
{
|
|
||||||
for (auto& obj : blend_factors.second)
|
|
||||||
{
|
|
||||||
min = std::min(min, obj.z_index);
|
|
||||||
max = std::max(max, obj.z_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void batch_renderer_2d::render(const bool transparency)
|
|
||||||
{
|
{
|
||||||
|
draw_buffer.bind();
|
||||||
|
draw_buffer.updateBuffersStorage(width, height);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
if (transparency)
|
if (transparency)
|
||||||
{
|
{
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
@ -187,6 +186,8 @@ namespace blt::gfx
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
render_reset();
|
render_reset();
|
||||||
|
draw_buffer.blitToScreen(width, height);
|
||||||
|
fbo_t::unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void batch_renderer_2d::draw_objects()
|
void batch_renderer_2d::draw_objects()
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* <Short Description>
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <blt/gfx/renderer/post_process.h>
|
||||||
|
|
||||||
|
namespace blt::gfx
|
||||||
|
{
|
||||||
|
void pp_engine::create()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void pp_engine::render(i32 width, i32 height)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,78 @@
|
||||||
#include <blt/gfx/stb/stb_image.h>
|
#include <blt/gfx/stb/stb_image.h>
|
||||||
#include <blt/gfx/stb/stb_perlin.h>
|
#include <blt/gfx/stb/stb_perlin.h>
|
||||||
#include <blt/gfx/texture.h>
|
#include <blt/gfx/texture.h>
|
||||||
|
#include <blt/std/hashmap.h>
|
||||||
|
|
||||||
|
struct format_t
|
||||||
|
{
|
||||||
|
GLenum format;
|
||||||
|
GLenum type;
|
||||||
|
};
|
||||||
|
|
||||||
|
blt::hashmap_t<GLint, format_t> make_format_table()
|
||||||
|
{
|
||||||
|
blt::hashmap_t<GLint, format_t> map;
|
||||||
|
|
||||||
|
map[GL_R8] = {GL_RED, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_R8_SNORM] = {GL_RED, GL_BYTE};
|
||||||
|
map[GL_R16F] = {GL_RED, GL_FLOAT};
|
||||||
|
map[GL_R32F] = {GL_RED, GL_FLOAT};
|
||||||
|
map[GL_R8UI] = {GL_RED_INTEGER, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_R8I] = {GL_RED_INTEGER, GL_BYTE};
|
||||||
|
map[GL_R16UI] = {GL_RED_INTEGER, GL_UNSIGNED_SHORT};
|
||||||
|
map[GL_R16I] = {GL_RED_INTEGER, GL_SHORT};
|
||||||
|
map[GL_R32UI] = {GL_RED_INTEGER, GL_UNSIGNED_INT};
|
||||||
|
map[GL_R32I] = {GL_RED_INTEGER, GL_INT};
|
||||||
|
map[GL_RG8] = {GL_RG, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RG8_SNORM] = {GL_RG, GL_BYTE};
|
||||||
|
map[GL_RG16F] = {GL_RG, GL_FLOAT};
|
||||||
|
map[GL_RG32F] = {GL_RG, GL_FLOAT};
|
||||||
|
map[GL_RG8UI] = {GL_RG_INTEGER, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RG8I] = {GL_RG_INTEGER, GL_BYTE};
|
||||||
|
map[GL_RG16UI] = {GL_RG_INTEGER, GL_UNSIGNED_SHORT};
|
||||||
|
map[GL_RG16I] = {GL_RG_INTEGER, GL_SHORT};
|
||||||
|
map[GL_RG32UI] = {GL_RG_INTEGER, GL_UNSIGNED_INT};
|
||||||
|
map[GL_RG32I] = {GL_RG_INTEGER, GL_INT};
|
||||||
|
map[GL_RGB8] = {GL_RGB, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_SRGB8] = {GL_RGB, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RGB565] = {GL_RGB, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RGB8_SNORM] = {GL_RGB, GL_BYTE};
|
||||||
|
map[GL_R11F_G11F_B10F] = {GL_RGB, GL_FLOAT};
|
||||||
|
map[GL_RGB9_E5] = {GL_RGB, GL_FLOAT};
|
||||||
|
map[GL_RGB16F] = {GL_RGB, GL_FLOAT};
|
||||||
|
map[GL_RGB32F] = {GL_RGB, GL_FLOAT};
|
||||||
|
map[GL_RGB8UI] = {GL_RGB_INTEGER, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RGB8I] = {GL_RGB_INTEGER, GL_BYTE};
|
||||||
|
map[GL_RGB16UI] = {GL_RGB_INTEGER, GL_UNSIGNED_SHORT};
|
||||||
|
map[GL_RGB16I] = {GL_RGB_INTEGER, GL_RGB16I};
|
||||||
|
map[GL_RGB32UI] = {GL_RGB_INTEGER, GL_UNSIGNED_INT};
|
||||||
|
map[GL_RGB32I] = {GL_RGB_INTEGER, GL_INT};
|
||||||
|
map[GL_RGBA8] = {GL_RGBA, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_SRGB8_ALPHA8] = {GL_RGBA, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RGBA8_SNORM] = {GL_RGBA, GL_BYTE};
|
||||||
|
map[GL_RGB5_A1] = {GL_RGBA, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RGBA4] = {GL_RGBA, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RGB10_A2] = {GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV};
|
||||||
|
map[GL_RGBA16F] = {GL_RGBA, GL_FLOAT};
|
||||||
|
map[GL_RGBA32F] = {GL_RGBA, GL_FLOAT};
|
||||||
|
map[GL_RGBA8UI] = {GL_RGBA_INTEGER, GL_UNSIGNED_BYTE};
|
||||||
|
map[GL_RGBA8I] = {GL_RGBA_INTEGER, GL_BYTE};
|
||||||
|
map[GL_RGB10_A2UI] = {GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV};
|
||||||
|
map[GL_RGBA16UI] = {GL_RGBA_INTEGER, GL_UNSIGNED_SHORT};
|
||||||
|
map[GL_RGBA16I] = {GL_RGBA_INTEGER, GL_SHORT};
|
||||||
|
map[GL_RGBA32I] = {GL_RGBA_INTEGER, GL_INT};
|
||||||
|
map[GL_RGBA32UI] = {GL_RGBA_INTEGER, GL_UNSIGNED_INT};
|
||||||
|
map[GL_DEPTH_COMPONENT16] = {GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
|
||||||
|
map[GL_DEPTH_COMPONENT24] = {GL_DEPTH_COMPONENT, GL_UNSIGNED_INT};
|
||||||
|
map[GL_DEPTH_COMPONENT32F] = {GL_DEPTH_COMPONENT, GL_FLOAT};
|
||||||
|
map[GL_DEPTH24_STENCIL8] = {GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8};
|
||||||
|
map[GL_DEPTH32F_STENCIL8] = {GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV};
|
||||||
|
map[GL_STENCIL_INDEX8] = {GL_STENCIL_INDEX, GL_UNSIGNED_BYTE};
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
blt::hashmap_t<GLint, format_t> internal_to_texture = make_format_table();
|
||||||
|
|
||||||
blt::gfx::texture_file::texture_file(const std::string& path, const std::string& name): m_name(name.empty() ? path : name), m_path(path)
|
blt::gfx::texture_file::texture_file(const std::string& path, const std::string& name): m_name(name.empty() ? path : name), m_path(path)
|
||||||
{
|
{
|
||||||
|
@ -45,7 +117,7 @@ blt::gfx::texture_file::texture_file(const std::string& path, const std::string&
|
||||||
reinterpret_cast<int*>(&m_texture.m_width), reinterpret_cast<int*>(&m_texture.m_height),
|
reinterpret_cast<int*>(&m_texture.m_width), reinterpret_cast<int*>(&m_texture.m_height),
|
||||||
reinterpret_cast<int*>(&m_texture.m_channels),
|
reinterpret_cast<int*>(&m_texture.m_channels),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
blt::gfx::texture_file& blt::gfx::texture_file::resize(int target_width, int target_height)
|
blt::gfx::texture_file& blt::gfx::texture_file::resize(int target_width, int target_height)
|
||||||
|
@ -56,7 +128,7 @@ blt::gfx::texture_file& blt::gfx::texture_file::resize(int target_width, int tar
|
||||||
// that matches with what stb image uses, which is malloc, since we unload with stbi_image_free -> (free)
|
// that matches with what stb image uses, which is malloc, since we unload with stbi_image_free -> (free)
|
||||||
auto* output_Data = (unsigned char*) malloc(
|
auto* output_Data = (unsigned char*) malloc(
|
||||||
target_width * target_height * m_texture.channels()
|
target_width * target_height * m_texture.channels()
|
||||||
);
|
);
|
||||||
|
|
||||||
// resize the texture
|
// resize the texture
|
||||||
if (stbir_resize_uint8_linear(
|
if (stbir_resize_uint8_linear(
|
||||||
|
@ -66,7 +138,7 @@ blt::gfx::texture_file& blt::gfx::texture_file::resize(int target_width, int tar
|
||||||
output_Data, target_width, target_height, 0,
|
output_Data, target_width, target_height, 0,
|
||||||
// channels
|
// channels
|
||||||
static_cast<stbir_pixel_layout>(m_texture.channels())
|
static_cast<stbir_pixel_layout>(m_texture.channels())
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
BLT_WARN("Error resizing block texture image!");
|
BLT_WARN("Error resizing block texture image!");
|
||||||
}
|
}
|
||||||
|
@ -132,7 +204,9 @@ void blt::gfx::texture_gl2D::resize(int width, int height)
|
||||||
m_width = width;
|
m_width = width;
|
||||||
m_height = height;
|
m_height = height;
|
||||||
bind();
|
bind();
|
||||||
glTexStorage2D(textureBindType, 0, textureColorMode, m_width, m_height);
|
//glTexStorage2D(textureBindType, 4, textureColorMode, m_width, m_height);
|
||||||
|
auto format = internal_to_texture[textureColorMode];
|
||||||
|
glTexImage2D(textureBindType, 0, textureColorMode, m_width, m_height, 0, format.format, format.type, nullptr);
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +214,8 @@ blt::gfx::texture_gl2D::texture_gl2D(int width, int height, GLint colorMode): te
|
||||||
{
|
{
|
||||||
bind();
|
bind();
|
||||||
setDefaults();
|
setDefaults();
|
||||||
// TODO:
|
resize(width, height);
|
||||||
const int MIPMAP_LEVELS = 4;
|
//glTexStorage2D(textureBindType, 4, colorMode, width, height);
|
||||||
glTexStorage2D(textureBindType, MIPMAP_LEVELS, colorMode, width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blt::gfx::texture_gl2D::texture_gl2D(const blt::gfx::texture_data& data):
|
blt::gfx::texture_gl2D::texture_gl2D(const blt::gfx::texture_data& data):
|
||||||
|
@ -165,10 +238,7 @@ void blt::gfx::gl_texture2D_array::upload(void* data, int index, GLint dataColor
|
||||||
if (sub_height < 0)
|
if (sub_height < 0)
|
||||||
sub_height = m_height;
|
sub_height = m_height;
|
||||||
bind();
|
bind();
|
||||||
glTexSubImage3D(
|
glTexSubImage3D(textureBindType, level, x_offset, y_offset, index, sub_width, sub_height, 1, dataColorMode, GL_UNSIGNED_BYTE, data);
|
||||||
textureBindType, level, x_offset, y_offset, index, sub_width, sub_height, 1,
|
|
||||||
dataColorMode, GL_UNSIGNED_BYTE, data
|
|
||||||
);
|
|
||||||
generateMipmaps();
|
generateMipmaps();
|
||||||
unbind();
|
unbind();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ blt::gfx::resource_manager resources;
|
||||||
blt::gfx::batch_renderer_2d renderer_2d(resources);
|
blt::gfx::batch_renderer_2d renderer_2d(resources);
|
||||||
blt::gfx::first_person_camera camera;
|
blt::gfx::first_person_camera camera;
|
||||||
|
|
||||||
std::vector<std::pair<blt::gfx::vertex_array*, size_t>> vaos;
|
std::vector<std::pair<blt::gfx::vertex_array_t*, size_t>> vaos;
|
||||||
blt::gfx::shader_t* shader;
|
blt::gfx::shader_t* shader;
|
||||||
|
|
||||||
float x = 0, y = 0, z = 0;
|
float x = 0, y = 0, z = 0;
|
||||||
|
@ -60,18 +60,18 @@ void init()
|
||||||
|
|
||||||
auto object = blt::parse::quick_load("../resources/models/many_objects.obj");
|
auto object = blt::parse::quick_load("../resources/models/many_objects.obj");
|
||||||
|
|
||||||
vbo_t vertices_vbo;
|
vertex_buffer_t vertices_vbo;
|
||||||
vertices_vbo.create();
|
vertices_vbo.create();
|
||||||
vertices_vbo.allocate(static_cast<long>(object.vertex_data().size() * sizeof(blt::parse::constructed_vertex_t)), object.vertex_data().data());
|
vertices_vbo.allocate(static_cast<long>(object.vertex_data().size() * sizeof(blt::parse::constructed_vertex_t)), object.vertex_data().data());
|
||||||
auto ptr = vertex_array::createSharedVBO(vertices_vbo);
|
auto ptr = vertex_array_t::createSharedVBO(vertices_vbo);
|
||||||
|
|
||||||
for (auto obj : object.objects())
|
for (auto obj : object.objects())
|
||||||
{
|
{
|
||||||
vbo_t indices_vbo;
|
vertex_buffer_t indices_vbo;
|
||||||
indices_vbo.create(GL_ELEMENT_ARRAY_BUFFER);
|
indices_vbo.create(GL_ELEMENT_ARRAY_BUFFER);
|
||||||
indices_vbo.allocate(static_cast<long>(obj.indices.size() * sizeof(blt::parse::triangle_t)), obj.indices.data());
|
indices_vbo.allocate(static_cast<long>(obj.indices.size() * sizeof(blt::parse::triangle_t)), obj.indices.data());
|
||||||
|
|
||||||
auto* vao = new vertex_array();
|
auto* vao = new vertex_array_t();
|
||||||
vao->bindVBO(ptr, 0, 3, GL_FLOAT, sizeof(float) * (3 + 3 + 2), 0);
|
vao->bindVBO(ptr, 0, 3, GL_FLOAT, sizeof(float) * (3 + 3 + 2), 0);
|
||||||
vao->bindVBO(ptr, 1, 2, GL_FLOAT, sizeof(float) * (3 + 3 + 2), sizeof(float) * 3);
|
vao->bindVBO(ptr, 1, 2, GL_FLOAT, sizeof(float) * (3 + 3 + 2), sizeof(float) * 3);
|
||||||
vao->bindVBO(ptr, 2, 3, GL_FLOAT, sizeof(float) * (3 + 3 + 2), sizeof(float) * (3 + 2));
|
vao->bindVBO(ptr, 2, 3, GL_FLOAT, sizeof(float) * (3 + 3 + 2), sizeof(float) * (3 + 2));
|
||||||
|
|
Loading…
Reference in New Issue