| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- #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_shaderCache(shaderCache) {}
- PrimitiveBatchPipeline::~PrimitiveBatchPipeline() { shutdown(); }
- auto PrimitiveBatchPipeline::initialize() -> bool {
- initializeOpenGLFunctions();
- if (m_shaderCache == nullptr) {
- return false;
- }
- m_shader = m_shaderCache->get(QStringLiteral("primitive_instanced"));
- if (m_shader == nullptr) {
- return false;
- }
- initializeSphereVao();
- initializeCylinderVao();
- initializeConeVao();
- cacheUniforms();
- m_initialized = true;
- return true;
- }
- void PrimitiveBatchPipeline::shutdown() {
- shutdownVaos();
- m_initialized = false;
- }
- void PrimitiveBatchPipeline::cacheUniforms() {
- if (m_shader != nullptr) {
- m_uniforms.viewProj = m_shader->uniformHandle("u_viewProj");
- m_uniforms.lightDir = m_shader->uniformHandle("u_lightDir");
- m_uniforms.ambientStrength = m_shader->uniformHandle("u_ambientStrength");
- }
- }
- void PrimitiveBatchPipeline::beginFrame() {}
- void PrimitiveBatchPipeline::setupInstanceAttributes(GLuint vao,
- GLuint instanceBuffer) {
- glBindVertexArray(vao);
- glBindBuffer(GL_ARRAY_BUFFER, instanceBuffer);
- 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, modelCol0)));
- glVertexAttribDivisor(3, 1);
- glEnableVertexAttribArray(4);
- glVertexAttribPointer(
- 4, Vec4, GL_FLOAT, GL_FALSE, stride,
- reinterpret_cast<void *>(offsetof(GL::PrimitiveInstanceGpu, modelCol1)));
- glVertexAttribDivisor(4, 1);
- glEnableVertexAttribArray(5);
- glVertexAttribPointer(
- 5, Vec4, GL_FLOAT, GL_FALSE, stride,
- reinterpret_cast<void *>(offsetof(GL::PrimitiveInstanceGpu, modelCol2)));
- glVertexAttribDivisor(5, 1);
- glEnableVertexAttribArray(6);
- glVertexAttribPointer(
- 6, Vec4, GL_FLOAT, GL_FALSE, stride,
- reinterpret_cast<void *>(offsetof(GL::PrimitiveInstanceGpu, colorAlpha)));
- glVertexAttribDivisor(6, 1);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::initializeSphereVao() {
- 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_sphereVao);
- glBindVertexArray(m_sphereVao);
- glGenBuffers(1, &m_sphereVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_sphereVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
- vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(1, &m_sphereIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_sphereIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
- indices.data(), GL_STATIC_DRAW);
- m_sphereIndexCount = 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_sphereInstanceBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_sphereInstanceBuffer);
- m_sphereInstanceCapacity = kDefaultInstanceCapacity;
- glBufferData(GL_ARRAY_BUFFER,
- m_sphereInstanceCapacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- setupInstanceAttributes(m_sphereVao, m_sphereInstanceBuffer);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::initializeCylinderVao() {
- 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_cylinderVao);
- glBindVertexArray(m_cylinderVao);
- glGenBuffers(1, &m_cylinderVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_cylinderVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
- vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(1, &m_cylinderIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_cylinderIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
- indices.data(), GL_STATIC_DRAW);
- m_cylinderIndexCount = 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_cylinderInstanceBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_cylinderInstanceBuffer);
- m_cylinderInstanceCapacity = kDefaultInstanceCapacity;
- glBufferData(GL_ARRAY_BUFFER,
- m_cylinderInstanceCapacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- setupInstanceAttributes(m_cylinderVao, m_cylinderInstanceBuffer);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::initializeConeVao() {
- 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_coneVao);
- glBindVertexArray(m_coneVao);
- glGenBuffers(1, &m_coneVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_coneVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
- vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(1, &m_coneIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_coneIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int),
- indices.data(), GL_STATIC_DRAW);
- m_coneIndexCount = 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_coneInstanceBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_coneInstanceBuffer);
- m_coneInstanceCapacity = kDefaultInstanceCapacity;
- glBufferData(GL_ARRAY_BUFFER,
- m_coneInstanceCapacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- setupInstanceAttributes(m_coneVao, m_coneInstanceBuffer);
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::shutdownVaos() {
- if (m_sphereVao != 0) {
- glDeleteVertexArrays(1, &m_sphereVao);
- m_sphereVao = 0;
- }
- if (m_sphereVertexBuffer != 0) {
- glDeleteBuffers(1, &m_sphereVertexBuffer);
- m_sphereVertexBuffer = 0;
- }
- if (m_sphereIndexBuffer != 0) {
- glDeleteBuffers(1, &m_sphereIndexBuffer);
- m_sphereIndexBuffer = 0;
- }
- if (m_sphereInstanceBuffer != 0) {
- glDeleteBuffers(1, &m_sphereInstanceBuffer);
- m_sphereInstanceBuffer = 0;
- }
- if (m_cylinderVao != 0) {
- glDeleteVertexArrays(1, &m_cylinderVao);
- m_cylinderVao = 0;
- }
- if (m_cylinderVertexBuffer != 0) {
- glDeleteBuffers(1, &m_cylinderVertexBuffer);
- m_cylinderVertexBuffer = 0;
- }
- if (m_cylinderIndexBuffer != 0) {
- glDeleteBuffers(1, &m_cylinderIndexBuffer);
- m_cylinderIndexBuffer = 0;
- }
- if (m_cylinderInstanceBuffer != 0) {
- glDeleteBuffers(1, &m_cylinderInstanceBuffer);
- m_cylinderInstanceBuffer = 0;
- }
- if (m_coneVao != 0) {
- glDeleteVertexArrays(1, &m_coneVao);
- m_coneVao = 0;
- }
- if (m_coneVertexBuffer != 0) {
- glDeleteBuffers(1, &m_coneVertexBuffer);
- m_coneVertexBuffer = 0;
- }
- if (m_coneIndexBuffer != 0) {
- glDeleteBuffers(1, &m_coneIndexBuffer);
- m_coneIndexBuffer = 0;
- }
- if (m_coneInstanceBuffer != 0) {
- glDeleteBuffers(1, &m_coneInstanceBuffer);
- m_coneInstanceBuffer = 0;
- }
- }
- void PrimitiveBatchPipeline::uploadSphereInstances(
- const GL::PrimitiveInstanceGpu *data, std::size_t count) {
- if (count == 0 || data == nullptr) {
- return;
- }
- glBindBuffer(GL_ARRAY_BUFFER, m_sphereInstanceBuffer);
- if (count > m_sphereInstanceCapacity) {
- m_sphereInstanceCapacity = static_cast<std::size_t>(count * kGrowthFactor);
- glBufferData(GL_ARRAY_BUFFER,
- m_sphereInstanceCapacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- }
- glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(GL::PrimitiveInstanceGpu),
- data);
- }
- void PrimitiveBatchPipeline::uploadCylinderInstances(
- const GL::PrimitiveInstanceGpu *data, std::size_t count) {
- if (count == 0 || data == nullptr) {
- return;
- }
- glBindBuffer(GL_ARRAY_BUFFER, m_cylinderInstanceBuffer);
- if (count > m_cylinderInstanceCapacity) {
- m_cylinderInstanceCapacity =
- static_cast<std::size_t>(count * kGrowthFactor);
- glBufferData(GL_ARRAY_BUFFER,
- m_cylinderInstanceCapacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- }
- glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(GL::PrimitiveInstanceGpu),
- data);
- }
- void PrimitiveBatchPipeline::uploadConeInstances(
- const GL::PrimitiveInstanceGpu *data, std::size_t count) {
- if (count == 0 || data == nullptr) {
- return;
- }
- glBindBuffer(GL_ARRAY_BUFFER, m_coneInstanceBuffer);
- if (count > m_coneInstanceCapacity) {
- m_coneInstanceCapacity = static_cast<std::size_t>(count * kGrowthFactor);
- glBufferData(GL_ARRAY_BUFFER,
- m_coneInstanceCapacity * sizeof(GL::PrimitiveInstanceGpu),
- nullptr, GL_DYNAMIC_DRAW);
- }
- glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(GL::PrimitiveInstanceGpu),
- data);
- }
- void PrimitiveBatchPipeline::drawSpheres(std::size_t count,
- const QMatrix4x4 &viewProj) {
- if (count == 0 || m_sphereVao == 0 || m_shader == nullptr) {
- return;
- }
- m_shader->use();
- m_shader->setUniform(m_uniforms.viewProj, viewProj);
- m_shader->setUniform(m_uniforms.lightDir, QVector3D(0.35F, 0.8F, 0.45F));
- m_shader->setUniform(m_uniforms.ambientStrength, 0.3F);
- glBindVertexArray(m_sphereVao);
- glDrawElementsInstanced(GL_TRIANGLES, m_sphereIndexCount, GL_UNSIGNED_INT,
- nullptr, static_cast<GLsizei>(count));
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::drawCylinders(std::size_t count,
- const QMatrix4x4 &viewProj) {
- if (count == 0 || m_cylinderVao == 0 || m_shader == nullptr) {
- return;
- }
- m_shader->use();
- m_shader->setUniform(m_uniforms.viewProj, viewProj);
- m_shader->setUniform(m_uniforms.lightDir, QVector3D(0.35F, 0.8F, 0.45F));
- m_shader->setUniform(m_uniforms.ambientStrength, 0.3F);
- glBindVertexArray(m_cylinderVao);
- glDrawElementsInstanced(GL_TRIANGLES, m_cylinderIndexCount, GL_UNSIGNED_INT,
- nullptr, static_cast<GLsizei>(count));
- glBindVertexArray(0);
- }
- void PrimitiveBatchPipeline::drawCones(std::size_t count,
- const QMatrix4x4 &viewProj) {
- if (count == 0 || m_coneVao == 0 || m_shader == nullptr) {
- return;
- }
- m_shader->use();
- m_shader->setUniform(m_uniforms.viewProj, viewProj);
- m_shader->setUniform(m_uniforms.lightDir, QVector3D(0.35F, 0.8F, 0.45F));
- m_shader->setUniform(m_uniforms.ambientStrength, 0.3F);
- glBindVertexArray(m_coneVao);
- glDrawElementsInstanced(GL_TRIANGLES, m_coneIndexCount, GL_UNSIGNED_INT,
- nullptr, static_cast<GLsizei>(count));
- glBindVertexArray(0);
- }
- } // namespace Render::GL::BackendPipelines
|