particles! Weird EBO stuff
parent
8f3fb79f05
commit
8705a1d4e1
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
project(gpu-particles VERSION 0.0.14)
|
||||
project(gpu-particles VERSION 0.0.15)
|
||||
|
||||
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
||||
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
||||
|
|
|
@ -4,13 +4,21 @@ const std::string shader_particle_2d_frag = R"("
|
|||
#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D tex2;
|
||||
|
||||
in float silly;
|
||||
|
||||
layout (location = 0) out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(tex, gl_PointCoord);
|
||||
float x = gl_PointCoord.x;
|
||||
float y = 1.0f - gl_PointCoord.y;
|
||||
if (silly > 0.0f)
|
||||
FragColor = texture(tex1, vec2(x, y));
|
||||
else
|
||||
FragColor = texture(tex2, vec2(x, y));
|
||||
}
|
||||
|
||||
")";
|
||||
|
|
|
@ -6,6 +6,8 @@ precision mediump float;
|
|||
|
||||
layout (location = 0) in vec2 position;
|
||||
|
||||
out float silly;
|
||||
|
||||
layout (std140) uniform GlobalMatrices
|
||||
{
|
||||
mat4 projection;
|
||||
|
@ -17,6 +19,10 @@ layout (std140) uniform GlobalMatrices
|
|||
|
||||
void main()
|
||||
{
|
||||
if (mod(position.x + position.y, 32.0f) >= 16.0f)
|
||||
silly = 1.0f;
|
||||
else
|
||||
silly = 0.0f;
|
||||
gl_Position = ovm * vec4(position.x, position.y, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <vbo.h>
|
||||
#include <blt/std/hashmap.h>
|
||||
#include <blt/std/vector.h>
|
||||
|
||||
namespace blt::gfx
|
||||
|
@ -32,7 +33,7 @@ namespace blt::gfx
|
|||
struct vao_vbo_storage_t
|
||||
{
|
||||
std::unique_ptr<unique_vbo_t> vbo;
|
||||
std::optional<std::vector<u32>> attribute_numbers;
|
||||
std::optional<hashset_t<u32>> attribute_numbers;
|
||||
|
||||
[[nodiscard]] bool is_element() const
|
||||
{
|
||||
|
@ -101,7 +102,6 @@ namespace blt::gfx
|
|||
vao_context_t& unbind();
|
||||
|
||||
vao_vbo_context_t attach_vbo(unique_vbo_t&& vbo) const;
|
||||
|
||||
private:
|
||||
[[nodiscard]] bool is_bound() const;
|
||||
|
||||
|
@ -140,6 +140,39 @@ namespace blt::gfx
|
|||
|
||||
detail::vao_context_t bind();
|
||||
|
||||
[[nodiscard]] std::optional<ref<unique_vbo_t>> get_attribute(const u32 attribute) const
|
||||
{
|
||||
for (const auto& vbo_obj : vbo_list)
|
||||
{
|
||||
if (const auto attrs = vbo_obj.attribute_numbers)
|
||||
{
|
||||
if (attrs->contains(attribute))
|
||||
return *vbo_obj.vbo;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<ref<unique_vbo_t>> get_buffer_type(const GLuint buffer_type) const
|
||||
{
|
||||
for (const auto& vbo_obj : vbo_list)
|
||||
{
|
||||
if (vbo_obj.vbo->get_buffer_type() == buffer_type)
|
||||
return *vbo_obj.vbo;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<ref<unique_vbo_t>> get_element() const
|
||||
{
|
||||
for (const auto& vbo_obj : vbo_list)
|
||||
{
|
||||
if (vbo_obj.is_element())
|
||||
return *vbo_obj.vbo;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
~unique_vao_t()
|
||||
{
|
||||
if (vaoID)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
After Width: | Height: | Size: 536 KiB |
92
src/main.cpp
92
src/main.cpp
|
@ -30,7 +30,7 @@ constexpr blt::size_t PARTICLE_COUNT = 8192;
|
|||
blt::gfx::matrix_state_manager global_matrices;
|
||||
blt::gfx::resource_manager resources;
|
||||
blt::gfx::batch_renderer_2d renderer_2d(resources, global_matrices);
|
||||
blt::gfx::first_person_camera camera;
|
||||
blt::gfx::first_person_camera_2d camera;
|
||||
|
||||
// use types for state that way you are not confused about what is happening?
|
||||
|
||||
|
@ -39,43 +39,80 @@ struct particle_t
|
|||
blt::vec2 position;
|
||||
blt::vec2 velocity;
|
||||
blt::vec2 acceleration;
|
||||
float mass = 10;
|
||||
float unused;
|
||||
|
||||
static particle_t make_particle()
|
||||
{
|
||||
blt::random::random_t random{std::random_device()()};
|
||||
return {blt::vec2{random.get(0.0f, 500.0f), random.get(0.0f, 500.0f)}, blt::vec2{}, blt::vec2{}};
|
||||
static blt::random::random_t random{std::random_device()()};
|
||||
return {blt::vec2{random.get(20.0f, 1880.0f), random.get(20.0f, 1000.0f)}, blt::vec2{}, blt::vec2{}};
|
||||
}
|
||||
};
|
||||
|
||||
std::optional<blt::gfx::unique_vao_t> particle_vao;
|
||||
std::unique_ptr<blt::gfx::shader_t> particle_shader;
|
||||
class gpu_particle_renderer
|
||||
{
|
||||
public:
|
||||
gpu_particle_renderer()
|
||||
{
|
||||
using namespace blt::gfx;
|
||||
|
||||
std::vector<blt::u32> alive_particles;
|
||||
std::vector<blt::u32> dead_particles;
|
||||
std::vector<particle_t> particles;
|
||||
for (blt::size_t i = 0; i < PARTICLE_COUNT; i++)
|
||||
{
|
||||
particles.push_back(particle_t::make_particle());
|
||||
alive_particles.push_back(i);
|
||||
}
|
||||
|
||||
particle_shader = std::unique_ptr<shader_t>(shader_t::make(shader_particle_2d_vert, shader_particle_2d_frag));
|
||||
|
||||
unique_vbo_t particle_vbo(GL_ARRAY_BUFFER);
|
||||
particle_vbo.bind().upload(sizeof(particle_t) * particles.size(), particles.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
unique_ebo_t alive_particles_ebo;
|
||||
alive_particles_ebo.bind().upload(sizeof(blt::u32) * alive_particles.size(), alive_particles.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
auto vao_ctx = particle_vao.bind();
|
||||
vao_ctx.attach_vbo(std::move(particle_vbo)).attribute_ptr(0, 2, GL_FLOAT, sizeof(particle_t), 0);
|
||||
vao_ctx.attach_vbo(std::move(alive_particles_ebo));
|
||||
vao_ctx.unbind();
|
||||
}
|
||||
|
||||
void render()
|
||||
{
|
||||
glPointSize(25);
|
||||
|
||||
particle_shader->bind();
|
||||
particle_shader->setInt("tex1", 0);
|
||||
particle_shader->setInt("tex2", 1);
|
||||
particle_vao.bind();
|
||||
// particle_vao.get_element()->get().bind();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
resources.get("silly").value()->bind();
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
resources.get("happy").value()->bind();
|
||||
|
||||
glDrawElements(GL_POINTS, static_cast<int>(alive_particles.size()), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
blt::gfx::unique_vao_t particle_vao;
|
||||
std::unique_ptr<blt::gfx::shader_t> particle_shader;
|
||||
|
||||
std::vector<blt::u32> alive_particles;
|
||||
std::vector<blt::u32> dead_particles;
|
||||
std::vector<particle_t> particles;
|
||||
};
|
||||
|
||||
std::optional<gpu_particle_renderer> particle_renderer;
|
||||
|
||||
void init(const blt::gfx::window_data&)
|
||||
{
|
||||
using namespace blt::gfx;
|
||||
resources.setPrefixDirectory("../");
|
||||
|
||||
particle_shader = std::unique_ptr<shader_t>(shader_t::make(shader_particle_2d_vert, shader_particle_2d_frag));
|
||||
resources.enqueue("res/silly.png", "silly");
|
||||
resources.enqueue("res/images_4.jpeg", "happy");
|
||||
|
||||
for (blt::size_t i = 0; i < PARTICLE_COUNT; i++)
|
||||
{
|
||||
particles.push_back(particle_t::make_particle());
|
||||
alive_particles.push_back(i);
|
||||
}
|
||||
|
||||
unique_vbo_t particle_vbo(GL_ARRAY_BUFFER);
|
||||
particle_vbo.bind().upload(sizeof(particle_t) * particles.size(), particles.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
unique_ebo_t alive_particles_ebo;
|
||||
alive_particles_ebo.bind().upload(sizeof(blt::u32) * alive_particles.size(), alive_particles.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
particle_vao = unique_vao_t();
|
||||
const auto vao_ctx = particle_vao->bind();
|
||||
vao_ctx.attach_vbo(std::move(particle_vbo)).attribute_ptr(0, 2, GL_FLOAT, sizeof(particle_t), 0);
|
||||
vao_ctx.attach_vbo(std::move(alive_particles_ebo));
|
||||
particle_renderer = gpu_particle_renderer{};
|
||||
|
||||
global_matrices.create_internals();
|
||||
resources.load_resources();
|
||||
|
@ -91,12 +128,13 @@ void update(const blt::gfx::window_data& data)
|
|||
global_matrices.update();
|
||||
|
||||
renderer_2d.render(data.width, data.height);
|
||||
|
||||
particle_renderer->render();
|
||||
}
|
||||
|
||||
void destroy(const blt::gfx::window_data&)
|
||||
{
|
||||
particle_vao.reset();
|
||||
particle_shader.reset();
|
||||
particle_renderer.reset();
|
||||
global_matrices.cleanup();
|
||||
resources.cleanup();
|
||||
renderer_2d.cleanup();
|
||||
|
|
17
src/vao.cpp
17
src/vao.cpp
|
@ -25,22 +25,16 @@ namespace blt::gfx
|
|||
#define ENSURE_CONTEXT_BOUND BLT_CONTRACT(glfwGetCurrentContext() != nullptr, "Expected active OpenGL context!")
|
||||
|
||||
#if blt_debug_has_flag(BLT_DEBUG_CONTRACTS)
|
||||
GLuint bound_vao_id;
|
||||
GLuint bound_vao_id = 0;
|
||||
#endif
|
||||
|
||||
detail::vao_vbo_context_t& detail::vao_vbo_context_t::attribute_ptr(const int attribute_number, const int coordinate_size, const GLenum type,
|
||||
const int stride, const long offset)
|
||||
{
|
||||
if (auto& vec = vbo.attribute_numbers)
|
||||
{
|
||||
for (const auto& v : *vec)
|
||||
{
|
||||
if (static_cast<i32>(v) == attribute_number)
|
||||
goto use;
|
||||
}
|
||||
vec->push_back(attribute_number);
|
||||
}
|
||||
use:
|
||||
if (!vbo.attribute_numbers)
|
||||
vbo.attribute_numbers = hashset_t<u32>();
|
||||
if (!vbo.attribute_numbers->contains(attribute_number))
|
||||
vbo.attribute_numbers->insert(attribute_number);
|
||||
glEnableVertexAttribArray(attribute_number);
|
||||
glVertexAttribPointer(attribute_number, coordinate_size, type, GL_FALSE, stride < 0 ? 0 : stride, reinterpret_cast<void*>(offset));
|
||||
attributed = true;
|
||||
|
@ -69,6 +63,7 @@ namespace blt::gfx
|
|||
|
||||
detail::vao_context_t& detail::vao_context_t::unbind() // NOLINT
|
||||
{
|
||||
ENSURE_CONTEXT_BOUND;
|
||||
glBindVertexArray(0);
|
||||
bound_vao_id = 0;
|
||||
return *this;
|
||||
|
|
Loading…
Reference in New Issue