| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791 |
- #include "vegetation_pipeline.h"
- #include "../render_constants.h"
- #include "gl/shader_cache.h"
- #include <GL/gl.h>
- #include <QDebug>
- #include <QOpenGLContext>
- #include <cmath>
- #include <cstddef>
- #include <cstdint>
- #include <qglobal.h>
- #include <qopenglcontext.h>
- #include <qopenglext.h>
- #include <qstringliteral.h>
- #include <qvectornd.h>
- #include <vector>
- namespace Render::GL::BackendPipelines {
- using namespace Render::GL::VertexAttrib;
- using namespace Render::GL::ComponentCount;
- using namespace Render::GL::Geometry;
- VegetationPipeline::VegetationPipeline(ShaderCache *shader_cache)
- : m_shaderCache(shader_cache) {}
- VegetationPipeline::~VegetationPipeline() { shutdown(); }
- auto VegetationPipeline::initialize() -> bool {
- initializeOpenGLFunctions();
- if (m_shaderCache == nullptr) {
- return false;
- }
- m_stoneShader = m_shaderCache->get(QStringLiteral("stone_instanced"));
- m_plantShader = m_shaderCache->get(QStringLiteral("plant_instanced"));
- m_pineShader = m_shaderCache->get(QStringLiteral("pine_instanced"));
- m_oliveShader = m_shaderCache->get(QStringLiteral("olive_instanced"));
- m_firecampShader = m_shaderCache->get(QStringLiteral("firecamp"));
- if (m_stoneShader == nullptr) {
- qWarning() << "VegetationPipeline: stone shader missing";
- }
- if (m_plantShader == nullptr) {
- qWarning() << "VegetationPipeline: plant shader missing";
- }
- if (m_pineShader == nullptr) {
- qWarning() << "VegetationPipeline: pine shader missing";
- }
- if (m_oliveShader == nullptr) {
- qWarning() << "VegetationPipeline: olive shader missing";
- }
- if (m_firecampShader == nullptr) {
- qWarning() << "VegetationPipeline: firecamp shader missing";
- }
- initialize_stone_pipeline();
- initialize_plant_pipeline();
- initialize_pine_pipeline();
- initialize_olive_pipeline();
- initialize_fire_camp_pipeline();
- cache_uniforms();
- m_initialized = true;
- return true;
- }
- void VegetationPipeline::shutdown() {
- shutdown_stone_pipeline();
- shutdown_plant_pipeline();
- shutdown_pine_pipeline();
- shutdown_olive_pipeline();
- shutdown_fire_camp_pipeline();
- m_initialized = false;
- }
- void VegetationPipeline::cache_uniforms() {
- if (m_stoneShader != nullptr) {
- m_stoneUniforms.view_proj = m_stoneShader->uniform_handle("uViewProj");
- m_stoneUniforms.light_direction =
- m_stoneShader->uniform_handle("uLightDirection");
- }
- if (m_plantShader != nullptr) {
- m_plantUniforms.view_proj = m_plantShader->uniform_handle("uViewProj");
- m_plantUniforms.time = m_plantShader->uniform_handle("uTime");
- m_plantUniforms.wind_strength =
- m_plantShader->uniform_handle("uWindStrength");
- m_plantUniforms.wind_speed = m_plantShader->uniform_handle("uWindSpeed");
- m_plantUniforms.light_direction =
- m_plantShader->uniform_handle("uLightDirection");
- }
- if (m_pineShader != nullptr) {
- m_pineUniforms.view_proj = m_pineShader->uniform_handle("uViewProj");
- m_pineUniforms.time = m_pineShader->uniform_handle("uTime");
- m_pineUniforms.wind_strength =
- m_pineShader->uniform_handle("uWindStrength");
- m_pineUniforms.wind_speed = m_pineShader->uniform_handle("uWindSpeed");
- m_pineUniforms.light_direction =
- m_pineShader->uniform_handle("uLightDirection");
- }
- if (m_oliveShader != nullptr) {
- m_oliveUniforms.view_proj = m_oliveShader->uniform_handle("uViewProj");
- m_oliveUniforms.time = m_oliveShader->uniform_handle("uTime");
- m_oliveUniforms.wind_strength =
- m_oliveShader->uniform_handle("uWindStrength");
- m_oliveUniforms.wind_speed = m_oliveShader->uniform_handle("uWindSpeed");
- m_oliveUniforms.light_direction =
- m_oliveShader->uniform_handle("uLightDirection");
- }
- if (m_firecampShader != nullptr) {
- m_firecampUniforms.view_proj =
- m_firecampShader->uniform_handle("u_viewProj");
- m_firecampUniforms.time = m_firecampShader->uniform_handle("u_time");
- m_firecampUniforms.flickerSpeed =
- m_firecampShader->uniform_handle("u_flickerSpeed");
- m_firecampUniforms.flickerAmount =
- m_firecampShader->uniform_handle("u_flickerAmount");
- m_firecampUniforms.glowStrength =
- m_firecampShader->uniform_handle("u_glowStrength");
- m_firecampUniforms.fireTexture =
- m_firecampShader->uniform_handle("fireTexture");
- m_firecampUniforms.camera_right =
- m_firecampShader->uniform_handle("u_cameraRight");
- m_firecampUniforms.camera_forward =
- m_firecampShader->uniform_handle("u_cameraForward");
- }
- }
- void VegetationPipeline::initialize_stone_pipeline() {
- initializeOpenGLFunctions();
- shutdown_stone_pipeline();
- struct StoneVertex {
- QVector3D position;
- QVector3D normal;
- };
- const StoneVertex stone_vertices[] = {
- {{-0.5F, -0.5F, 0.5F}, {0.0F, 0.0F, 1.0F}},
- {{0.5F, -0.5F, 0.5F}, {0.0F, 0.0F, 1.0F}},
- {{0.5F, 0.5F, 0.5F}, {0.0F, 0.0F, 1.0F}},
- {{-0.5F, 0.5F, 0.5F}, {0.0F, 0.0F, 1.0F}},
- {{-0.5F, -0.5F, -0.5F}, {0.0F, 0.0F, -1.0F}},
- {{-0.5F, 0.5F, -0.5F}, {0.0F, 0.0F, -1.0F}},
- {{0.5F, 0.5F, -0.5F}, {0.0F, 0.0F, -1.0F}},
- {{0.5F, -0.5F, -0.5F}, {0.0F, 0.0F, -1.0F}},
- {{-0.5F, 0.5F, -0.5F}, {0.0F, 1.0F, 0.0F}},
- {{-0.5F, 0.5F, 0.5F}, {0.0F, 1.0F, 0.0F}},
- {{0.5F, 0.5F, 0.5F}, {0.0F, 1.0F, 0.0F}},
- {{0.5F, 0.5F, -0.5F}, {0.0F, 1.0F, 0.0F}},
- {{-0.5F, -0.5F, -0.5F}, {0.0F, -1.0F, 0.0F}},
- {{0.5F, -0.5F, -0.5F}, {0.0F, -1.0F, 0.0F}},
- {{0.5F, -0.5F, 0.5F}, {0.0F, -1.0F, 0.0F}},
- {{-0.5F, -0.5F, 0.5F}, {0.0F, -1.0F, 0.0F}},
- {{0.5F, -0.5F, -0.5F}, {1.0F, 0.0F, 0.0F}},
- {{0.5F, 0.5F, -0.5F}, {1.0F, 0.0F, 0.0F}},
- {{0.5F, 0.5F, 0.5F}, {1.0F, 0.0F, 0.0F}},
- {{0.5F, -0.5F, 0.5F}, {1.0F, 0.0F, 0.0F}},
- {{-0.5F, -0.5F, -0.5F}, {-1.0F, 0.0F, 0.0F}},
- {{-0.5F, -0.5F, 0.5F}, {-1.0F, 0.0F, 0.0F}},
- {{-0.5F, 0.5F, 0.5F}, {-1.0F, 0.0F, 0.0F}},
- {{-0.5F, 0.5F, -0.5F}, {-1.0F, 0.0F, 0.0F}},
- };
- const uint16_t stone_indices[] = {
- 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 9, 10, 10, 11, 8,
- 12, 13, 14, 14, 15, 12, 16, 17, 18, 18, 19, 16, 20, 21, 22, 22, 23, 20};
- glGenVertexArrays(1, &m_stoneVao);
- glBindVertexArray(m_stoneVao);
- glGenBuffers(1, &m_stoneVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_stoneVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(stone_vertices), stone_vertices,
- GL_STATIC_DRAW);
- m_stoneVertexCount = CubeVertexCount;
- glGenBuffers(1, &m_stoneIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_stoneIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(stone_indices), stone_indices,
- GL_STATIC_DRAW);
- constexpr int k_stone_index_count = 36;
- m_stoneIndexCount = k_stone_index_count;
- glEnableVertexAttribArray(Position);
- glVertexAttribPointer(
- Position, Vec3, GL_FLOAT, GL_FALSE, sizeof(StoneVertex),
- reinterpret_cast<void *>(offsetof(StoneVertex, position)));
- glEnableVertexAttribArray(Normal);
- glVertexAttribPointer(
- Normal, Vec3, GL_FLOAT, GL_FALSE, sizeof(StoneVertex),
- reinterpret_cast<void *>(offsetof(StoneVertex, normal)));
- glEnableVertexAttribArray(TexCoord);
- glVertexAttribDivisor(TexCoord, 1);
- glEnableVertexAttribArray(InstancePosition);
- glVertexAttribDivisor(InstancePosition, 1);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- void VegetationPipeline::shutdown_stone_pipeline() {
- if (QOpenGLContext::currentContext() == nullptr) {
- m_stoneVao = 0;
- m_stoneVertexBuffer = 0;
- m_stoneIndexBuffer = 0;
- m_stoneVertexCount = 0;
- m_stoneIndexCount = 0;
- return;
- }
- initializeOpenGLFunctions();
- if (m_stoneIndexBuffer != 0U) {
- glDeleteBuffers(1, &m_stoneIndexBuffer);
- m_stoneIndexBuffer = 0;
- }
- if (m_stoneVertexBuffer != 0U) {
- glDeleteBuffers(1, &m_stoneVertexBuffer);
- m_stoneVertexBuffer = 0;
- }
- if (m_stoneVao != 0U) {
- glDeleteVertexArrays(1, &m_stoneVao);
- m_stoneVao = 0;
- }
- m_stoneVertexCount = 0;
- m_stoneIndexCount = 0;
- }
- void VegetationPipeline::initialize_plant_pipeline() {
- initializeOpenGLFunctions();
- shutdown_plant_pipeline();
- struct PlantVertex {
- QVector3D position;
- QVector2D tex_coord;
- QVector3D normal;
- };
- const PlantVertex plant_vertices[] = {
- {{-0.5F, 0.0F, 0.0F}, {0.0F, 0.0F}, {0.0F, 0.0F, 1.0F}},
- {{0.5F, 0.0F, 0.0F}, {1.0F, 0.0F}, {0.0F, 0.0F, 1.0F}},
- {{0.5F, 1.0F, 0.0F}, {1.0F, 1.0F}, {0.0F, 0.0F, 1.0F}},
- {{-0.5F, 1.0F, 0.0F}, {0.0F, 1.0F}, {0.0F, 0.0F, 1.0F}},
- {{0.5F, 0.0F, 0.0F}, {0.0F, 0.0F}, {0.0F, 0.0F, -1.0F}},
- {{-0.5F, 0.0F, 0.0F}, {1.0F, 0.0F}, {0.0F, 0.0F, -1.0F}},
- {{-0.5F, 1.0F, 0.0F}, {1.0F, 1.0F}, {0.0F, 0.0F, -1.0F}},
- {{0.5F, 1.0F, 0.0F}, {0.0F, 1.0F}, {0.0F, 0.0F, -1.0F}},
- {{0.0F, 0.0F, -0.5F}, {0.0F, 0.0F}, {1.0F, 0.0F, 0.0F}},
- {{0.0F, 0.0F, 0.5F}, {1.0F, 0.0F}, {1.0F, 0.0F, 0.0F}},
- {{0.0F, 1.0F, 0.5F}, {1.0F, 1.0F}, {1.0F, 0.0F, 0.0F}},
- {{0.0F, 1.0F, -0.5F}, {0.0F, 1.0F}, {1.0F, 0.0F, 0.0F}},
- {{0.0F, 0.0F, 0.5F}, {0.0F, 0.0F}, {-1.0F, 0.0F, 0.0F}},
- {{0.0F, 0.0F, -0.5F}, {1.0F, 0.0F}, {-1.0F, 0.0F, 0.0F}},
- {{0.0F, 1.0F, -0.5F}, {1.0F, 1.0F}, {-1.0F, 0.0F, 0.0F}},
- {{0.0F, 1.0F, 0.5F}, {0.0F, 1.0F}, {-1.0F, 0.0F, 0.0F}},
- };
- const unsigned short plant_indices[] = {
- 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7,
- 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15,
- };
- glGenVertexArrays(1, &m_plantVao);
- glBindVertexArray(m_plantVao);
- glGenBuffers(1, &m_plantVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_plantVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(plant_vertices), plant_vertices,
- GL_STATIC_DRAW);
- m_plantVertexCount = PlantCrossQuadVertexCount;
- glEnableVertexAttribArray(Position);
- glVertexAttribPointer(
- Position, Vec3, GL_FLOAT, GL_FALSE, sizeof(PlantVertex),
- reinterpret_cast<void *>(offsetof(PlantVertex, position)));
- glEnableVertexAttribArray(Normal);
- glVertexAttribPointer(
- Normal, Vec2, GL_FLOAT, GL_FALSE, sizeof(PlantVertex),
- reinterpret_cast<void *>(offsetof(PlantVertex, tex_coord)));
- glEnableVertexAttribArray(TexCoord);
- glVertexAttribPointer(
- TexCoord, Vec3, GL_FLOAT, GL_FALSE, sizeof(PlantVertex),
- reinterpret_cast<void *>(offsetof(PlantVertex, normal)));
- glGenBuffers(1, &m_plantIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_plantIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(plant_indices), plant_indices,
- GL_STATIC_DRAW);
- m_plantIndexCount = PlantCrossQuadIndexCount;
- glEnableVertexAttribArray(InstancePosition);
- glVertexAttribDivisor(InstancePosition, 1);
- glEnableVertexAttribArray(InstanceScale);
- glVertexAttribDivisor(InstanceScale, 1);
- glEnableVertexAttribArray(InstanceColor);
- glVertexAttribDivisor(InstanceColor, 1);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- void VegetationPipeline::shutdown_plant_pipeline() {
- if (QOpenGLContext::currentContext() == nullptr) {
- m_plantVao = 0;
- m_plantVertexBuffer = 0;
- m_plantIndexBuffer = 0;
- m_plantVertexCount = 0;
- m_plantIndexCount = 0;
- return;
- }
- initializeOpenGLFunctions();
- if (m_plantIndexBuffer != 0U) {
- glDeleteBuffers(1, &m_plantIndexBuffer);
- m_plantIndexBuffer = 0;
- }
- if (m_plantVertexBuffer != 0U) {
- glDeleteBuffers(1, &m_plantVertexBuffer);
- m_plantVertexBuffer = 0;
- }
- if (m_plantVao != 0U) {
- glDeleteVertexArrays(1, &m_plantVao);
- m_plantVao = 0;
- }
- m_plantVertexCount = 0;
- m_plantIndexCount = 0;
- }
- void VegetationPipeline::initialize_pine_pipeline() {
- initializeOpenGLFunctions();
- shutdown_pine_pipeline();
- struct PineVertex {
- QVector3D position;
- QVector2D tex_coord;
- QVector3D normal;
- };
- constexpr int k_segments = PineTreeSegments;
- constexpr float k_two_pi = 6.28318530718F;
- std::vector<PineVertex> vertices;
- vertices.reserve(k_segments * 5 + 1);
- std::vector<unsigned short> indices;
- indices.reserve(k_segments * 6 * 4 + k_segments * 3);
- auto add_ring = [&](float radius, float y, float normalUp, float v_coord,
- const QVector2D ¢er_offset =
- QVector2D(0.0F, 0.0F)) -> int {
- const int start = static_cast<int>(vertices.size());
- for (int i = 0; i < k_segments; ++i) {
- const float t = static_cast<float>(i) / static_cast<float>(k_segments);
- const float angle = t * k_two_pi;
- const float nx = std::cos(angle);
- const float nz = std::sin(angle);
- QVector3D normal(nx, normalUp, nz);
- normal.normalize();
- QVector3D const position(radius * nx + center_offset.x(), y,
- radius * nz + center_offset.y());
- QVector2D const tex_coord(t, v_coord);
- vertices.push_back({position, tex_coord, normal});
- }
- return start;
- };
- auto connect_rings = [&](int lowerStart, int upperStart) {
- for (int i = 0; i < k_segments; ++i) {
- const int next = (i + 1) % k_segments;
- const auto lower0 = static_cast<unsigned short>(lowerStart + i);
- const auto lower1 = static_cast<unsigned short>(lowerStart + next);
- const auto upper0 = static_cast<unsigned short>(upperStart + i);
- const auto upper1 = static_cast<unsigned short>(upperStart + next);
- indices.push_back(lower0);
- indices.push_back(lower1);
- indices.push_back(upper1);
- indices.push_back(lower0);
- indices.push_back(upper1);
- indices.push_back(upper0);
- }
- };
- const int trunk_bottom = add_ring(0.12F, 0.0F, 0.0F, 0.0F);
- const int trunk_mid = add_ring(0.11F, 0.35F, 0.0F, 0.12F);
- const int trunk_top = add_ring(0.10F, 0.58F, 0.05F, 0.30F);
- const int branch_base = add_ring(0.60F, 0.64F, 0.35F, 0.46F);
- const int branch_mid = add_ring(0.42F, 0.82F, 0.6F, 0.68F);
- const int branch_upper = add_ring(0.24F, 1.00F, 0.7F, 0.88F);
- const int branch_tip = add_ring(0.12F, 1.10F, 0.85F, 0.96F);
- connect_rings(trunk_bottom, trunk_mid);
- connect_rings(trunk_mid, trunk_top);
- connect_rings(trunk_top, branch_base);
- connect_rings(branch_base, branch_mid);
- connect_rings(branch_mid, branch_upper);
- connect_rings(branch_upper, branch_tip);
- const auto trunk_cap_index = static_cast<unsigned short>(vertices.size());
- vertices.push_back({QVector3D(0.0F, 0.0F, 0.0F), QVector2D(0.5F, 0.0F),
- QVector3D(0.0F, -1.0F, 0.0F)});
- for (int i = 0; i < k_segments; ++i) {
- const int next = (i + 1) % k_segments;
- indices.push_back(static_cast<unsigned short>(trunk_bottom + next));
- indices.push_back(static_cast<unsigned short>(trunk_bottom + i));
- indices.push_back(trunk_cap_index);
- }
- const auto apex_index = static_cast<unsigned short>(vertices.size());
- vertices.push_back({QVector3D(0.0F, 1.18F, 0.0F), QVector2D(0.5F, 1.0F),
- QVector3D(0.0F, 1.0F, 0.0F)});
- for (int i = 0; i < k_segments; ++i) {
- const int next = (i + 1) % k_segments;
- indices.push_back(static_cast<unsigned short>(branch_tip + i));
- indices.push_back(static_cast<unsigned short>(branch_tip + next));
- indices.push_back(apex_index);
- }
- glGenVertexArrays(1, &m_pineVao);
- glBindVertexArray(m_pineVao);
- glGenBuffers(1, &m_pineVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_pineVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER,
- static_cast<GLsizeiptr>(vertices.size() * sizeof(PineVertex)),
- vertices.data(), GL_STATIC_DRAW);
- m_pineVertexCount = static_cast<GLsizei>(vertices.size());
- glEnableVertexAttribArray(Position);
- glVertexAttribPointer(
- Position, Vec3, GL_FLOAT, GL_FALSE, sizeof(PineVertex),
- reinterpret_cast<void *>(offsetof(PineVertex, position)));
- glEnableVertexAttribArray(Normal);
- glVertexAttribPointer(
- Normal, Vec2, GL_FLOAT, GL_FALSE, sizeof(PineVertex),
- reinterpret_cast<void *>(offsetof(PineVertex, tex_coord)));
- glEnableVertexAttribArray(TexCoord);
- glVertexAttribPointer(TexCoord, Vec3, GL_FLOAT, GL_FALSE, sizeof(PineVertex),
- reinterpret_cast<void *>(offsetof(PineVertex, normal)));
- glGenBuffers(1, &m_pineIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_pineIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,
- static_cast<GLsizeiptr>(indices.size() * sizeof(unsigned short)),
- indices.data(), GL_STATIC_DRAW);
- m_pineIndexCount = static_cast<GLsizei>(indices.size());
- glEnableVertexAttribArray(InstancePosition);
- glVertexAttribDivisor(InstancePosition, 1);
- glEnableVertexAttribArray(InstanceScale);
- glVertexAttribDivisor(InstanceScale, 1);
- glEnableVertexAttribArray(InstanceColor);
- glVertexAttribDivisor(InstanceColor, 1);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- void VegetationPipeline::shutdown_pine_pipeline() {
- if (QOpenGLContext::currentContext() == nullptr) {
- m_pineVao = 0;
- m_pineVertexBuffer = 0;
- m_pineIndexBuffer = 0;
- m_pineVertexCount = 0;
- m_pineIndexCount = 0;
- return;
- }
- initializeOpenGLFunctions();
- if (m_pineIndexBuffer != 0U) {
- glDeleteBuffers(1, &m_pineIndexBuffer);
- m_pineIndexBuffer = 0;
- }
- if (m_pineVertexBuffer != 0U) {
- glDeleteBuffers(1, &m_pineVertexBuffer);
- m_pineVertexBuffer = 0;
- }
- if (m_pineVao != 0U) {
- glDeleteVertexArrays(1, &m_pineVao);
- m_pineVao = 0;
- }
- m_pineVertexCount = 0;
- m_pineIndexCount = 0;
- }
- void VegetationPipeline::initialize_olive_pipeline() {
- initializeOpenGLFunctions();
- shutdown_olive_pipeline();
- struct OliveVertex {
- QVector3D position;
- QVector2D tex_coord;
- QVector3D normal;
- };
- constexpr int k_segments = OliveTreeSegments;
- constexpr float k_two_pi = 6.28318530718F;
- std::vector<OliveVertex> vertices;
- vertices.reserve(k_segments * 40);
- std::vector<unsigned short> indices;
- indices.reserve(k_segments * 6 * 40);
- auto add_ring = [&](float radius, float y, float normalUp, float v_coord,
- const QVector2D &offset = QVector2D(0.0F, 0.0F)) -> int {
- const int start = static_cast<int>(vertices.size());
- for (int i = 0; i < k_segments; ++i) {
- const float t = static_cast<float>(i) / static_cast<float>(k_segments);
- const float angle = t * k_two_pi;
- const float nx = std::cos(angle);
- const float nz = std::sin(angle);
- QVector3D normal(nx, normalUp, nz);
- normal.normalize();
- QVector3D const position(radius * nx + offset.x(), y,
- radius * nz + offset.y());
- vertices.push_back({position, QVector2D(t, v_coord), normal});
- }
- return start;
- };
- auto connect_rings = [&](int lower, int upper) {
- for (int i = 0; i < k_segments; ++i) {
- const int next = (i + 1) % k_segments;
- indices.push_back(static_cast<unsigned short>(lower + i));
- indices.push_back(static_cast<unsigned short>(lower + next));
- indices.push_back(static_cast<unsigned short>(upper + next));
- indices.push_back(static_cast<unsigned short>(lower + i));
- indices.push_back(static_cast<unsigned short>(upper + next));
- indices.push_back(static_cast<unsigned short>(upper + i));
- }
- };
- auto add_cap = [&](int ring, float capY, const QVector2D &offset, float v) {
- const int topIdx = static_cast<int>(vertices.size());
- vertices.push_back({QVector3D(offset.x(), capY, offset.y()),
- QVector2D(0.5F, v), QVector3D(0.0F, 1.0F, 0.0F)});
- for (int i = 0; i < k_segments; ++i) {
- const int next = (i + 1) % k_segments;
- indices.push_back(static_cast<unsigned short>(ring + i));
- indices.push_back(static_cast<unsigned short>(ring + next));
- indices.push_back(static_cast<unsigned short>(topIdx));
- }
- };
- int t0 = add_ring(0.14F, 0.00F, -0.2F, 0.00F);
- int t1 = add_ring(0.12F, 0.08F, 0.0F, 0.06F);
- int t2 = add_ring(0.09F, 0.15F, 0.1F, 0.12F);
- connect_rings(t0, t1);
- connect_rings(t1, t2);
- auto add_branch = [&](float dir_x, float dir_z, float base_y, float length,
- float branch_r, float leaf_r, float v_start) {
- float len = std::sqrt(dir_x * dir_x + dir_z * dir_z);
- dir_x /= len;
- dir_z /= len;
- float rise = 0.5F;
- float dx = dir_x * std::cos(0.5F);
- float dz = dir_z * std::cos(0.5F);
- float dy = std::sin(0.4F);
- int b0 = add_ring(branch_r, base_y, 0.0F, v_start);
- float mid_dist = length * 0.5F;
- QVector2D mid_offset(dx * mid_dist, dz * mid_dist);
- int b1 = add_ring(branch_r * 0.6F, base_y + dy * mid_dist, 0.3F,
- v_start + 0.1F, mid_offset);
- float tip_dist = length;
- QVector2D tip_offset(dx * tip_dist, dz * tip_dist);
- float tip_y = base_y + dy * tip_dist;
- int b2 = add_ring(branch_r * 0.3F, tip_y, 0.5F, v_start + 0.2F, tip_offset);
- connect_rings(b0, b1);
- connect_rings(b1, b2);
- float ly = tip_y - leaf_r * 0.2F;
- int l0 = add_ring(leaf_r * 0.6F, ly, -0.4F, 0.50F, tip_offset);
- int l1 =
- add_ring(leaf_r * 0.9F, ly + leaf_r * 0.35F, 0.0F, 0.65F, tip_offset);
- int l2 =
- add_ring(leaf_r * 0.85F, ly + leaf_r * 0.65F, 0.2F, 0.80F, tip_offset);
- int l3 =
- add_ring(leaf_r * 0.5F, ly + leaf_r * 0.90F, 0.6F, 0.92F, tip_offset);
- connect_rings(b2, l0);
- connect_rings(l0, l1);
- connect_rings(l1, l2);
- connect_rings(l2, l3);
- add_cap(l3, ly + leaf_r * 1.0F, tip_offset, 1.0F);
- };
- add_branch(0.8F, 0.3F, 0.14F, 0.30F, 0.025F, 0.18F, 0.18F);
- add_branch(-0.7F, 0.5F, 0.15F, 0.32F, 0.022F, 0.20F, 0.20F);
- add_branch(0.4F, -0.9F, 0.16F, 0.28F, 0.020F, 0.16F, 0.22F);
- add_branch(-0.5F, -0.7F, 0.14F, 0.34F, 0.024F, 0.19F, 0.19F);
- m_oliveVertexCount = static_cast<GLsizei>(vertices.size());
- m_oliveIndexCount = static_cast<GLsizei>(indices.size());
- glGenVertexArrays(1, &m_oliveVao);
- glBindVertexArray(m_oliveVao);
- glGenBuffers(1, &m_oliveVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_oliveVertexBuffer);
- glBufferData(GL_ARRAY_BUFFER,
- static_cast<GLsizeiptr>(vertices.size() * sizeof(OliveVertex)),
- vertices.data(), GL_STATIC_DRAW);
- glGenBuffers(1, &m_oliveIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_oliveIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,
- static_cast<GLsizeiptr>(indices.size() * sizeof(unsigned short)),
- indices.data(), GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(
- 0, 3, GL_FLOAT, GL_FALSE, sizeof(OliveVertex),
- reinterpret_cast<void *>(offsetof(OliveVertex, position)));
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(
- 1, 2, GL_FLOAT, GL_FALSE, sizeof(OliveVertex),
- reinterpret_cast<void *>(offsetof(OliveVertex, tex_coord)));
- glEnableVertexAttribArray(2);
- glVertexAttribPointer(
- 2, 3, GL_FLOAT, GL_FALSE, sizeof(OliveVertex),
- reinterpret_cast<void *>(offsetof(OliveVertex, normal)));
- glEnableVertexAttribArray(InstancePosition);
- glVertexAttribDivisor(InstancePosition, 1);
- glEnableVertexAttribArray(InstanceScale);
- glVertexAttribDivisor(InstanceScale, 1);
- glEnableVertexAttribArray(InstanceColor);
- glVertexAttribDivisor(InstanceColor, 1);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- void VegetationPipeline::shutdown_olive_pipeline() {
- if (QOpenGLContext::currentContext() == nullptr) {
- m_oliveVao = 0;
- m_oliveVertexBuffer = 0;
- m_oliveIndexBuffer = 0;
- m_oliveVertexCount = 0;
- m_oliveIndexCount = 0;
- return;
- }
- initializeOpenGLFunctions();
- if (m_oliveIndexBuffer != 0U) {
- glDeleteBuffers(1, &m_oliveIndexBuffer);
- m_oliveIndexBuffer = 0;
- }
- if (m_oliveVertexBuffer != 0U) {
- glDeleteBuffers(1, &m_oliveVertexBuffer);
- m_oliveVertexBuffer = 0;
- }
- if (m_oliveVao != 0U) {
- glDeleteVertexArrays(1, &m_oliveVao);
- m_oliveVao = 0;
- }
- m_oliveVertexCount = 0;
- m_oliveIndexCount = 0;
- }
- void VegetationPipeline::initialize_fire_camp_pipeline() {
- initializeOpenGLFunctions();
- shutdown_fire_camp_pipeline();
- struct FireCampVertex {
- QVector3D position;
- QVector2D tex_coord;
- };
- constexpr std::size_t k_firecamp_vertex_reserve = 12;
- constexpr std::size_t k_firecamp_index_reserve = 18;
- std::vector<FireCampVertex> vertices;
- vertices.reserve(k_firecamp_vertex_reserve);
- std::vector<unsigned short> indices;
- indices.reserve(k_firecamp_index_reserve);
- auto append_plane = [&](float planeIndex) {
- auto const base = static_cast<unsigned short>(vertices.size());
- vertices.push_back(
- {QVector3D(-1.0F, 0.0F, planeIndex), QVector2D(0.0F, 0.0F)});
- vertices.push_back(
- {QVector3D(1.0F, 0.0F, planeIndex), QVector2D(1.0F, 0.0F)});
- vertices.push_back(
- {QVector3D(1.0F, 2.0F, planeIndex), QVector2D(1.0F, 1.0F)});
- vertices.push_back(
- {QVector3D(-1.0F, 2.0F, planeIndex), QVector2D(0.0F, 1.0F)});
- indices.push_back(base + 0);
- indices.push_back(base + 1);
- indices.push_back(base + 2);
- indices.push_back(base + 0);
- indices.push_back(base + 2);
- indices.push_back(base + 3);
- };
- append_plane(0.0F);
- append_plane(1.0F);
- append_plane(2.0F);
- glGenVertexArrays(1, &m_firecampVao);
- glBindVertexArray(m_firecampVao);
- glGenBuffers(1, &m_firecampVertexBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, m_firecampVertexBuffer);
- glBufferData(
- GL_ARRAY_BUFFER,
- static_cast<GLsizeiptr>(vertices.size() * sizeof(FireCampVertex)),
- vertices.data(), GL_STATIC_DRAW);
- m_firecampVertexCount = static_cast<GLsizei>(vertices.size());
- glEnableVertexAttribArray(Position);
- glVertexAttribPointer(Position, Vec3, GL_FLOAT, GL_FALSE,
- sizeof(FireCampVertex), reinterpret_cast<void *>(0));
- glEnableVertexAttribArray(Normal);
- glVertexAttribPointer(
- Normal, Vec2, GL_FLOAT, GL_FALSE, sizeof(FireCampVertex),
- reinterpret_cast<void *>(offsetof(FireCampVertex, tex_coord)));
- glGenBuffers(1, &m_firecampIndexBuffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_firecampIndexBuffer);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,
- static_cast<GLsizeiptr>(indices.size() * sizeof(unsigned short)),
- indices.data(), GL_STATIC_DRAW);
- m_firecampIndexCount = static_cast<GLsizei>(indices.size());
- glEnableVertexAttribArray(InstancePosition);
- glVertexAttribDivisor(InstancePosition, 1);
- glEnableVertexAttribArray(InstanceScale);
- glVertexAttribDivisor(InstanceScale, 1);
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- void VegetationPipeline::shutdown_fire_camp_pipeline() {
- if (QOpenGLContext::currentContext() == nullptr) {
- m_firecampVao = 0;
- m_firecampVertexBuffer = 0;
- m_firecampIndexBuffer = 0;
- m_firecampVertexCount = 0;
- m_firecampIndexCount = 0;
- return;
- }
- initializeOpenGLFunctions();
- if (m_firecampIndexBuffer != 0U) {
- glDeleteBuffers(1, &m_firecampIndexBuffer);
- m_firecampIndexBuffer = 0;
- }
- if (m_firecampVertexBuffer != 0U) {
- glDeleteBuffers(1, &m_firecampVertexBuffer);
- m_firecampVertexBuffer = 0;
- }
- if (m_firecampVao != 0U) {
- glDeleteVertexArrays(1, &m_firecampVao);
- m_firecampVao = 0;
- }
- m_firecampVertexCount = 0;
- m_firecampIndexCount = 0;
- }
- } // namespace Render::GL::BackendPipelines
|