| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- #include "primitive_batch_pipeline.h"
- #include "../backend.h"
- #include "../mesh.h"
- #include "../primitives.h"
- #include "../render_constants.h"
- #include <GL/gl.h>
- #include <QOpenGLContext>
- #include <algorithm>
- #include <cstddef>
- namespace Render::GL::BackendPipelines {
- using namespace Render::GL::VertexAttrib;
- using namespace Render::GL::ComponentCount;
- PrimitiveBatchPipeline::PrimitiveBatchPipeline(ShaderCache *shaderCache)
- : m_shader_cache(shaderCache) {}
- PrimitiveBatchPipeline::~PrimitiveBatchPipeline() { shutdown(); }
- auto PrimitiveBatchPipeline::initialize() -> bool {
- initializeOpenGLFunctions();
- if (m_shader_cache == nullptr) {
- return false;
- }
- m_shader = m_shader_cache->get(QStringLiteral("primitive_instanced"));
- if (m_shader == nullptr) {
- return false;
- }
- initialize_sphere_vao();
- initialize_cylinder_vao();
- initialize_cone_vao();
- cacheUniforms();
- m_initialized = true;
- return true;
- }
- void PrimitiveBatchPipeline::shutdown() {
- shutdown_vaos();
- m_initialized = false;
- }
- void PrimitiveBatchPipeline::cacheUniforms() {
- if (m_shader != nullptr) {
- m_uniforms.view_proj = m_shader->uniformHandle("u_viewProj");
- m_uniforms.light_dir = m_shader->uniformHandle("u_lightDir");
- m_uniforms.ambient_strength = m_shader->uniformHandle("u_ambientStrength");
- }
- }
- void PrimitiveBatchPipeline::begin_frame() {}
- void PrimitiveBatchPipeline::setup_instance_attributes(GLuint vao,
- GLuint instance_buffer) {
- glBindVertexArray(vao);
- glBindBuffer(GL_ARRAY_BUFFER, instance_buffer);
- const auto stride = static_cast<GLsizei>(sizeof(GL::PrimitiveInstanceGpu));
- glEnableVertexAttribArray(3);
- glVertexAttribPointer(
- 3, Vec4, GL_FLOAT, GL_FALSE, stride,
- reinterpret_cast<void *>(offsetof(GL::PrimitiveInstanceGpu, model_col0)));
- glVertexAttribDivisor(3, 1);
- glEnableVertexAttribArray(4);
- glVertexAttribPointer(
- 4, Vec4, GL_FLOAT, GL_FALSE, stride,
- reinterpret_cast<void *>(offsetof(GL::PrimitiveInstanceGpu, model_col1)));
- glVertexAttribDivisor(4, 1);
- glEnableVertexAttribArray(5);
- glVertexAttribPointer(
- 5, Vec4, GL_FLOAT, GL_FALSE, stride,
- reinterpret_cast<void *>(offsetof(GL::PrimitiveInstanceGpu, model_col2)));
- glVertexAttribDivisor(5, 1);
- glEnableVertexAttribArray(6);
- glVertexAttribPointer(6, Vec4, GL_FLOAT, GL_FALSE, stride,
- reinterpret_cast<void *>(
- offsetof(GL::PrimitiveInstanceGpu, color_alpha)));
- glVertexAttribDivisor(6, 1);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::initialize_sphere_vao() {
- Mesh *unit = getUnitSphere();
- if (unit == nullptr) {
- return;
- }
- const auto &vertices = unit->getVertices();
- const auto &indices = unit->getIndices();
- if (vertices.empty() || indices.empty()) {
- return;
- }
- glGenVertexArrays(1, &m_sphere_vao);
- glBindVertexArray(m_sphere_vao);
- glGenBuffers(1, &m_sphere_vertex_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_sphere_vertex_buffer);
- glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
- vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(1, &m_sphere_index_buffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphere_index_buffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
- indices.data(), GL_STATIC_DRAW);
- m_sphere_index_count = static_cast<GLsizei>(indices.size());
- glEnableVertexAttribArray(Position);
- glVertexAttribPointer(Position, Vec3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, position)));
- glEnableVertexAttribArray(Normal);
- glVertexAttribPointer(Normal, Vec3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, normal)));
- glEnableVertexAttribArray(TexCoord);
- glVertexAttribPointer(TexCoord, Vec2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, tex_coord)));
- glGenBuffers(1, &m_sphere_instance_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_sphere_instance_buffer);
- m_sphere_instance_capacity = k_default_instance_capacity;
- glBufferData(GL_ARRAY_BUFFER,
- m_sphere_instance_capacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- setup_instance_attributes(m_sphere_vao, m_sphere_instance_buffer);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::initialize_cylinder_vao() {
- Mesh *unit = getUnitCylinder();
- if (unit == nullptr) {
- return;
- }
- const auto &vertices = unit->getVertices();
- const auto &indices = unit->getIndices();
- if (vertices.empty() || indices.empty()) {
- return;
- }
- glGenVertexArrays(1, &m_cylinder_vao);
- glBindVertexArray(m_cylinder_vao);
- glGenBuffers(1, &m_cylinder_vertex_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_cylinder_vertex_buffer);
- glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
- vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(1, &m_cylinder_index_buffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_cylinder_index_buffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
- indices.data(), GL_STATIC_DRAW);
- m_cylinder_index_count = static_cast<GLsizei>(indices.size());
- glEnableVertexAttribArray(Position);
- glVertexAttribPointer(Position, Vec3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, position)));
- glEnableVertexAttribArray(Normal);
- glVertexAttribPointer(Normal, Vec3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, normal)));
- glEnableVertexAttribArray(TexCoord);
- glVertexAttribPointer(TexCoord, Vec2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, tex_coord)));
- glGenBuffers(1, &m_cylinder_instance_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_cylinder_instance_buffer);
- m_cylinder_instance_capacity = k_default_instance_capacity;
- glBufferData(GL_ARRAY_BUFFER,
- m_cylinder_instance_capacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- setup_instance_attributes(m_cylinder_vao, m_cylinder_instance_buffer);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::initialize_cone_vao() {
- Mesh *unit = getUnitCone();
- if (unit == nullptr) {
- return;
- }
- const auto &vertices = unit->getVertices();
- const auto &indices = unit->getIndices();
- if (vertices.empty() || indices.empty()) {
- return;
- }
- glGenVertexArrays(1, &m_cone_vao);
- glBindVertexArray(m_cone_vao);
- glGenBuffers(1, &m_cone_vertex_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_cone_vertex_buffer);
- glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
- vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(1, &m_cone_index_buffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_cone_index_buffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
- indices.data(), GL_STATIC_DRAW);
- m_cone_index_count = static_cast<GLsizei>(indices.size());
- glEnableVertexAttribArray(Position);
- glVertexAttribPointer(Position, Vec3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, position)));
- glEnableVertexAttribArray(Normal);
- glVertexAttribPointer(Normal, Vec3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, normal)));
- glEnableVertexAttribArray(TexCoord);
- glVertexAttribPointer(TexCoord, Vec2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
- reinterpret_cast<void *>(offsetof(Vertex, tex_coord)));
- glGenBuffers(1, &m_cone_instance_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_cone_instance_buffer);
- m_cone_instance_capacity = k_default_instance_capacity;
- glBufferData(GL_ARRAY_BUFFER,
- m_cone_instance_capacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- setup_instance_attributes(m_cone_vao, m_cone_instance_buffer);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::shutdown_vaos() {
- if (m_sphere_vao != 0) {
- glDeleteVertexArrays(1, &m_sphere_vao);
- m_sphere_vao = 0;
- }
- if (m_sphere_vertex_buffer != 0) {
- glDeleteBuffers(1, &m_sphere_vertex_buffer);
- m_sphere_vertex_buffer = 0;
- }
- if (m_sphere_index_buffer != 0) {
- glDeleteBuffers(1, &m_sphere_index_buffer);
- m_sphere_index_buffer = 0;
- }
- if (m_sphere_instance_buffer != 0) {
- glDeleteBuffers(1, &m_sphere_instance_buffer);
- m_sphere_instance_buffer = 0;
- }
- if (m_cylinder_vao != 0) {
- glDeleteVertexArrays(1, &m_cylinder_vao);
- m_cylinder_vao = 0;
- }
- if (m_cylinder_vertex_buffer != 0) {
- glDeleteBuffers(1, &m_cylinder_vertex_buffer);
- m_cylinder_vertex_buffer = 0;
- }
- if (m_cylinder_index_buffer != 0) {
- glDeleteBuffers(1, &m_cylinder_index_buffer);
- m_cylinder_index_buffer = 0;
- }
- if (m_cylinder_instance_buffer != 0) {
- glDeleteBuffers(1, &m_cylinder_instance_buffer);
- m_cylinder_instance_buffer = 0;
- }
- if (m_cone_vao != 0) {
- glDeleteVertexArrays(1, &m_cone_vao);
- m_cone_vao = 0;
- }
- if (m_cone_vertex_buffer != 0) {
- glDeleteBuffers(1, &m_cone_vertex_buffer);
- m_cone_vertex_buffer = 0;
- }
- if (m_cone_index_buffer != 0) {
- glDeleteBuffers(1, &m_cone_index_buffer);
- m_cone_index_buffer = 0;
- }
- if (m_cone_instance_buffer != 0) {
- glDeleteBuffers(1, &m_cone_instance_buffer);
- m_cone_instance_buffer = 0;
- }
- }
- void PrimitiveBatchPipeline::upload_sphere_instances(
- const GL::PrimitiveInstanceGpu *data, std::size_t count) {
- if (count == 0 || data == nullptr) {
- return;
- }
- glBindBuffer(GL_ARRAY_BUFFER, m_sphere_instance_buffer);
- if (count > m_sphere_instance_capacity) {
- m_sphere_instance_capacity =
- static_cast<std::size_t>(count * k_growth_factor);
- glBufferData(GL_ARRAY_BUFFER,
- m_sphere_instance_capacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- }
- glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(GL::PrimitiveInstanceGpu),
- data);
- }
- void PrimitiveBatchPipeline::upload_cylinder_instances(
- const GL::PrimitiveInstanceGpu *data, std::size_t count) {
- if (count == 0 || data == nullptr) {
- return;
- }
- glBindBuffer(GL_ARRAY_BUFFER, m_cylinder_instance_buffer);
- if (count > m_cylinder_instance_capacity) {
- m_cylinder_instance_capacity =
- static_cast<std::size_t>(count * k_growth_factor);
- glBufferData(GL_ARRAY_BUFFER,
- m_cylinder_instance_capacity *
- sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- }
- glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(GL::PrimitiveInstanceGpu),
- data);
- }
- void PrimitiveBatchPipeline::upload_cone_instances(
- const GL::PrimitiveInstanceGpu *data, std::size_t count) {
- if (count == 0 || data == nullptr) {
- return;
- }
- glBindBuffer(GL_ARRAY_BUFFER, m_cone_instance_buffer);
- if (count > m_cone_instance_capacity) {
- m_cone_instance_capacity =
- static_cast<std::size_t>(count * k_growth_factor);
- glBufferData(GL_ARRAY_BUFFER,
- m_cone_instance_capacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- }
- glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(GL::PrimitiveInstanceGpu),
- data);
- }
- void PrimitiveBatchPipeline::draw_spheres(std::size_t count,
- const QMatrix4x4 &view_proj) {
- if (count == 0 || m_sphere_vao == 0 || m_shader == nullptr) {
- return;
- }
- m_shader->use();
- m_shader->setUniform(m_uniforms.view_proj, view_proj);
- m_shader->setUniform(m_uniforms.light_dir, QVector3D(0.35F, 0.8F, 0.45F));
- m_shader->setUniform(m_uniforms.ambient_strength, 0.3F);
- glBindVertexArray(m_sphere_vao);
- glDrawElementsInstanced(GL_TRIANGLES, m_sphere_index_count, GL_UNSIGNED_INT,
- nullptr, static_cast<GLsizei>(count));
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::draw_cylinders(std::size_t count,
- const QMatrix4x4 &view_proj) {
- if (count == 0 || m_cylinder_vao == 0 || m_shader == nullptr) {
- return;
- }
- m_shader->use();
- m_shader->setUniform(m_uniforms.view_proj, view_proj);
- m_shader->setUniform(m_uniforms.light_dir, QVector3D(0.35F, 0.8F, 0.45F));
- m_shader->setUniform(m_uniforms.ambient_strength, 0.3F);
- glBindVertexArray(m_cylinder_vao);
- glDrawElementsInstanced(GL_TRIANGLES, m_cylinder_index_count, GL_UNSIGNED_INT,
- nullptr, static_cast<GLsizei>(count));
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::draw_cones(std::size_t count,
- const QMatrix4x4 &view_proj) {
- if (count == 0 || m_cone_vao == 0 || m_shader == nullptr) {
- return;
- }
- m_shader->use();
- m_shader->setUniform(m_uniforms.view_proj, view_proj);
- m_shader->setUniform(m_uniforms.light_dir, QVector3D(0.35F, 0.8F, 0.45F));
- m_shader->setUniform(m_uniforms.ambient_strength, 0.3F);
- glBindVertexArray(m_cone_vao);
- glDrawElementsInstanced(GL_TRIANGLES, m_cone_index_count, GL_UNSIGNED_INT,
- nullptr, static_cast<GLsizei>(count));
- glBindVertexArray(0);
- }
- } // namespace Render::GL::BackendPipelines
|