From a25ce2d5df07a36f395bbc8d0ccdd5adeca78c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Kapu=C5=9Bci=C5=84ski?= Date: Sun, 8 May 2022 16:22:20 +0200 Subject: [PATCH] Rewritten particle rendering, now uses its own vertex type for optimization --- src/graphics/core/renderers.h | 8 ++- src/graphics/core/vertex.h | 11 ++++ src/graphics/engine/lightning.cpp | 2 +- src/graphics/engine/particle.cpp | 29 ++++++--- .../opengl33/gl33_particle_renderer.cpp | 61 +++++++++++++------ .../opengl33/gl33_particle_renderer.h | 6 +- .../opengl33/shaders/gl33/particle_vs.glsl | 4 +- 7 files changed, 86 insertions(+), 35 deletions(-) diff --git a/src/graphics/core/renderers.h b/src/graphics/core/renderers.h index 5e5ffffa..3d0e0cbc 100644 --- a/src/graphics/core/renderers.h +++ b/src/graphics/core/renderers.h @@ -24,8 +24,6 @@ #pragma once -#include "graphics/core/vertex.h" - #include // Graphics module namespace @@ -35,7 +33,11 @@ namespace Gfx class CVertexBuffer; enum class CullFace : unsigned char; enum class TransparencyMode : unsigned char; +struct Color; struct Texture; +struct Vertex2D; +struct Vertex3D; +struct VertexParticle; /** * \enum PrimitiveType @@ -250,7 +252,7 @@ public: virtual void SetTransparency(TransparencyMode mode) = 0; //! Draws particles - virtual void DrawParticle(PrimitiveType type, int count, const Vertex3D* vertices) = 0; + virtual void DrawParticle(PrimitiveType type, int count, const VertexParticle* vertices) = 0; }; /** diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h index c398a60e..038e29a4 100644 --- a/src/graphics/core/vertex.h +++ b/src/graphics/core/vertex.h @@ -61,4 +61,15 @@ struct Vertex3D glm::vec3 normal = { 0.0f, 0.0f, 1.0f }; }; +/** + * \struct VertexParticle + * \brief 3D vertex for particle rendering, contains color and UV coordinates + */ +struct VertexParticle +{ + glm::vec3 position = { 0.0f, 0.0f, 0.0f }; + glm::u8vec4 color = { 255, 255, 255, 255 }; + glm::vec2 uv = { 0.0f, 0.0f }; +}; + } // namespace Gfx diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp index 354554ca..e1c33a2a 100644 --- a/src/graphics/engine/lightning.cpp +++ b/src/graphics/engine/lightning.cpp @@ -244,7 +244,7 @@ void CLightning::Draw() glm::vec3 n = glm::normalize(p1-eye); glm::vec3 corner[4]; - Vertex3D vertex[4]; + VertexParticle vertex[4]; for (std::size_t i = 0; i < m_segments.size() - 1; i++) { diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index b689b9e4..3ddd0243 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -2604,7 +2604,7 @@ void CParticle::TrackDraw(int i, ParticleType type) glm::vec3 eye = m_engine->GetEyePt(); float a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z); - Vertex3D vertex[4]; + VertexParticle vertex[4]; glm::vec3 corner[4]; for (int counter = 0; counter < m_track[i].posUsed-1; counter++) @@ -2692,7 +2692,16 @@ void CParticle::DrawParticleTriangle(int i) mat[3][2] = pos.z; m_renderer->SetModelMatrix(mat); - m_renderer->DrawParticle(PrimitiveType::TRIANGLES, 3, m_triangle[i].triangle); + VertexParticle vertices[3]; + + for (size_t j = 0; j < 3; j++) + { + vertices[j].position = m_triangle[i].triangle[j].position; + vertices[j].color = m_triangle[i].triangle[j].color; + vertices[j].uv = m_triangle[i].triangle[j].uv; + } + + m_renderer->DrawParticle(PrimitiveType::TRIANGLES, 3, vertices); m_engine->AddStatisticTriangle(1); } @@ -2705,7 +2714,7 @@ void CParticle::DrawParticleNorm(int i) glm::vec3 corner[4]; - Vertex3D vertex[4]; + VertexParticle vertex[4]; if (m_particle[i].sheet == SH_INTERFACE) { @@ -2853,7 +2862,7 @@ void CParticle::DrawParticleFlat(int i) glm::u8vec4 white(255); - Vertex3D vertex[4]; + VertexParticle vertex[4]; vertex[0] = { corner[1], white, { m_particle[i].texSup.x, m_particle[i].texSup.y } }; vertex[1] = { corner[0], white, { m_particle[i].texInf.x, m_particle[i].texSup.y } }; vertex[2] = { corner[3], white, { m_particle[i].texSup.x, m_particle[i].texInf.y } }; @@ -2939,7 +2948,7 @@ void CParticle::DrawParticleFog(int i) glm::u8vec4 white(255); - Vertex3D vertex[4]; + VertexParticle vertex[4]; vertex[0] = { corner[1], white, { m_particle[i].texSup.x, m_particle[i].texSup.y } }; vertex[1] = { corner[0], white, { m_particle[i].texInf.x, m_particle[i].texSup.y } }; @@ -3067,7 +3076,7 @@ void CParticle::DrawParticleRay(int i) corner[2].z = (Math::Rand()-0.5f)*vario1; corner[3].z = (Math::Rand()-0.5f)*vario1; - Vertex3D vertex[4]; + VertexParticle vertex[4]; glm::u8vec4 white(255); @@ -3164,7 +3173,7 @@ void CParticle::DrawParticleSphere(int i) float deltaRingAngle = Math::PI/numRings; float deltaSegAngle = 2.0f*Math::PI/numSegments; - std::vector vertex(2*16*(16+1)); + std::vector vertex(2*16*(16+1)); glm::u8vec4 white(255); @@ -3265,7 +3274,7 @@ void CParticle::DrawParticleCylinder(int i) } } - std::vector vertex(2*5*(10+1)); + std::vector vertex(2*5*(10+1)); glm::u8vec4 white(255); @@ -3360,7 +3369,7 @@ void CParticle::DrawParticleWheel(int i) auto color = ColorToIntColor(TraceColorColor(m_wheelTrace[i].color)); - Vertex3D vertex[4]; + VertexParticle vertex[4]; vertex[0] = { pos[0], color, { ts.x, ts.y } }; vertex[1] = { pos[1], color, { ti.x, ts.y } }; vertex[2] = { pos[2], color, { ts.x, ti.y } }; @@ -3379,7 +3388,7 @@ void CParticle::DrawParticleWheel(int i) auto color = ColorToIntColor(TraceColorColor(m_wheelTrace[i].color)); - Vertex3D vertex[4]; + VertexParticle vertex[4]; vertex[0] = { pos[0], color }; vertex[1] = { pos[1], color }; vertex[2] = { pos[2], color }; diff --git a/src/graphics/opengl33/gl33_particle_renderer.cpp b/src/graphics/opengl33/gl33_particle_renderer.cpp index 1d732df1..e09ee109 100644 --- a/src/graphics/opengl33/gl33_particle_renderer.cpp +++ b/src/graphics/opengl33/gl33_particle_renderer.cpp @@ -67,8 +67,6 @@ CGL33ParticleRenderer::CGL33ParticleRenderer(CGL33Device* device) glUseProgram(m_program); // Setup uniforms - glm::mat4 identity(1.0f); - m_projectionMatrix = glGetUniformLocation(m_program, "uni_ProjectionMatrix"); m_viewMatrix = glGetUniformLocation(m_program, "uni_ViewMatrix"); m_modelMatrix = glGetUniformLocation(m_program, "uni_ModelMatrix"); @@ -102,7 +100,8 @@ CGL33ParticleRenderer::CGL33ParticleRenderer(CGL33Device* device) // Generic buffer glGenBuffers(1, &m_bufferVBO); glBindBuffer(GL_COPY_WRITE_BUFFER, m_bufferVBO); - glBufferData(GL_COPY_WRITE_BUFFER, m_bufferCapacity, nullptr, GL_STREAM_DRAW); + glBufferData(GL_COPY_WRITE_BUFFER, m_bufferCapacity * sizeof(VertexParticle), nullptr, GL_STREAM_DRAW); + m_bufferOffset = m_bufferCapacity; glGenVertexArrays(1, &m_bufferVAO); glBindVertexArray(m_bufferVAO); @@ -194,26 +193,52 @@ void CGL33ParticleRenderer::SetTransparency(TransparencyMode mode) m_device->SetTransparency(mode); } -void CGL33ParticleRenderer::DrawParticle(PrimitiveType type, int count, const Vertex3D* vertices) +void CGL33ParticleRenderer::DrawParticle(PrimitiveType type, int count, const VertexParticle* vertices) { - size_t size = count * sizeof(Vertex3D); + GLuint total = m_bufferOffset + count; - if (m_bufferCapacity < size) - m_bufferCapacity = size; + // Buffer full, orphan + if (total >= m_bufferCapacity) + { + glBufferData(GL_ARRAY_BUFFER, m_bufferCapacity * sizeof(VertexParticle), nullptr, GL_STREAM_DRAW); - // Send new vertices to GPU - glBindBuffer(GL_ARRAY_BUFFER, m_bufferVBO); - glBufferData(GL_ARRAY_BUFFER, m_bufferCapacity, nullptr, GL_STREAM_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices); + m_bufferOffset = 0; - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), - reinterpret_cast(offsetof(Vertex3D, position))); + // Respecify vertex attributes + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexParticle), + reinterpret_cast(offsetof(VertexParticle, position))); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex3D), - reinterpret_cast(offsetof(Vertex3D, color))); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VertexParticle), + reinterpret_cast(offsetof(VertexParticle, color))); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), - reinterpret_cast(offsetof(Vertex3D, uv))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexParticle), + reinterpret_cast(offsetof(VertexParticle, uv))); + } - glDrawArrays(TranslateGfxPrimitive(type), 0, count); + void* ptr = glMapBufferRange(GL_ARRAY_BUFFER, + m_bufferOffset * sizeof(VertexParticle), + count * sizeof(VertexParticle), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + + if (ptr) + { + auto buffer = reinterpret_cast(ptr); + + std::copy_n(vertices, count, buffer); + + glUnmapBuffer(GL_ARRAY_BUFFER); + } + else + { + glBufferSubData(GL_ARRAY_BUFFER, + m_bufferOffset * sizeof(VertexParticle), + count * sizeof(VertexParticle), + vertices); + } + + glDrawArrays(TranslateGfxPrimitive(type), + m_bufferOffset, + count); + + m_bufferOffset += count; } diff --git a/src/graphics/opengl33/gl33_particle_renderer.h b/src/graphics/opengl33/gl33_particle_renderer.h index 4b222493..e1b15859 100644 --- a/src/graphics/opengl33/gl33_particle_renderer.h +++ b/src/graphics/opengl33/gl33_particle_renderer.h @@ -63,7 +63,7 @@ public: virtual void SetTransparency(TransparencyMode mode) override; //! Draws particles - virtual void DrawParticle(PrimitiveType type, int count, const Vertex3D* vertices) override; + virtual void DrawParticle(PrimitiveType type, int count, const VertexParticle* vertices) override; private: CGL33Device* const m_device; @@ -90,7 +90,9 @@ private: // Vertex array object GLuint m_bufferVAO = 0; // VBO capacity - GLsizei m_bufferCapacity = 8 * sizeof(Vertex3D); + GLsizei m_bufferCapacity = 64 * 1024; + // Buffer offset + GLsizei m_bufferOffset = 0; }; } diff --git a/src/graphics/opengl33/shaders/gl33/particle_vs.glsl b/src/graphics/opengl33/shaders/gl33/particle_vs.glsl index 30450b6c..8a2c7e19 100644 --- a/src/graphics/opengl33/shaders/gl33/particle_vs.glsl +++ b/src/graphics/opengl33/shaders/gl33/particle_vs.glsl @@ -27,6 +27,8 @@ uniform mat4 uni_ProjectionMatrix; uniform mat4 uni_ViewMatrix; uniform mat4 uni_ModelMatrix; +uniform vec4 uni_Color; + out VertexData { vec4 Color; @@ -37,6 +39,6 @@ void main() { gl_Position = uni_ProjectionMatrix * uni_ViewMatrix * uni_ModelMatrix * in_VertexCoord; - data.Color = in_Color; + data.Color = in_Color * uni_Color; data.TexCoord = in_TexCoord; }