Rewritten particle rendering, now uses its own vertex type for optimization

dev
Tomasz Kapuściński 2022-05-08 16:22:20 +02:00
parent cac34e259b
commit a25ce2d5df
7 changed files with 86 additions and 35 deletions

View File

@ -24,8 +24,6 @@
#pragma once #pragma once
#include "graphics/core/vertex.h"
#include <glm/glm.hpp> #include <glm/glm.hpp>
// Graphics module namespace // Graphics module namespace
@ -35,7 +33,11 @@ namespace Gfx
class CVertexBuffer; class CVertexBuffer;
enum class CullFace : unsigned char; enum class CullFace : unsigned char;
enum class TransparencyMode : unsigned char; enum class TransparencyMode : unsigned char;
struct Color;
struct Texture; struct Texture;
struct Vertex2D;
struct Vertex3D;
struct VertexParticle;
/** /**
* \enum PrimitiveType * \enum PrimitiveType
@ -250,7 +252,7 @@ public:
virtual void SetTransparency(TransparencyMode mode) = 0; virtual void SetTransparency(TransparencyMode mode) = 0;
//! Draws particles //! Draws particles
virtual void DrawParticle(PrimitiveType type, int count, const Vertex3D* vertices) = 0; virtual void DrawParticle(PrimitiveType type, int count, const VertexParticle* vertices) = 0;
}; };
/** /**

View File

@ -61,4 +61,15 @@ struct Vertex3D
glm::vec3 normal = { 0.0f, 0.0f, 1.0f }; 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 } // namespace Gfx

View File

@ -244,7 +244,7 @@ void CLightning::Draw()
glm::vec3 n = glm::normalize(p1-eye); glm::vec3 n = glm::normalize(p1-eye);
glm::vec3 corner[4]; glm::vec3 corner[4];
Vertex3D vertex[4]; VertexParticle vertex[4];
for (std::size_t i = 0; i < m_segments.size() - 1; i++) for (std::size_t i = 0; i < m_segments.size() - 1; i++)
{ {

View File

@ -2604,7 +2604,7 @@ void CParticle::TrackDraw(int i, ParticleType type)
glm::vec3 eye = m_engine->GetEyePt(); glm::vec3 eye = m_engine->GetEyePt();
float a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z); float a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
Vertex3D vertex[4]; VertexParticle vertex[4];
glm::vec3 corner[4]; glm::vec3 corner[4];
for (int counter = 0; counter < m_track[i].posUsed-1; counter++) 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; mat[3][2] = pos.z;
m_renderer->SetModelMatrix(mat); 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); m_engine->AddStatisticTriangle(1);
} }
@ -2705,7 +2714,7 @@ void CParticle::DrawParticleNorm(int i)
glm::vec3 corner[4]; glm::vec3 corner[4];
Vertex3D vertex[4]; VertexParticle vertex[4];
if (m_particle[i].sheet == SH_INTERFACE) if (m_particle[i].sheet == SH_INTERFACE)
{ {
@ -2853,7 +2862,7 @@ void CParticle::DrawParticleFlat(int i)
glm::u8vec4 white(255); 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[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[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 } }; 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); 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[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[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[2].z = (Math::Rand()-0.5f)*vario1;
corner[3].z = (Math::Rand()-0.5f)*vario1; corner[3].z = (Math::Rand()-0.5f)*vario1;
Vertex3D vertex[4]; VertexParticle vertex[4];
glm::u8vec4 white(255); glm::u8vec4 white(255);
@ -3164,7 +3173,7 @@ void CParticle::DrawParticleSphere(int i)
float deltaRingAngle = Math::PI/numRings; float deltaRingAngle = Math::PI/numRings;
float deltaSegAngle = 2.0f*Math::PI/numSegments; float deltaSegAngle = 2.0f*Math::PI/numSegments;
std::vector<Vertex3D> vertex(2*16*(16+1)); std::vector<VertexParticle> vertex(2*16*(16+1));
glm::u8vec4 white(255); glm::u8vec4 white(255);
@ -3265,7 +3274,7 @@ void CParticle::DrawParticleCylinder(int i)
} }
} }
std::vector<Vertex3D> vertex(2*5*(10+1)); std::vector<VertexParticle> vertex(2*5*(10+1));
glm::u8vec4 white(255); glm::u8vec4 white(255);
@ -3360,7 +3369,7 @@ void CParticle::DrawParticleWheel(int i)
auto color = ColorToIntColor(TraceColorColor(m_wheelTrace[i].color)); auto color = ColorToIntColor(TraceColorColor(m_wheelTrace[i].color));
Vertex3D vertex[4]; VertexParticle vertex[4];
vertex[0] = { pos[0], color, { ts.x, ts.y } }; vertex[0] = { pos[0], color, { ts.x, ts.y } };
vertex[1] = { pos[1], color, { ti.x, ts.y } }; vertex[1] = { pos[1], color, { ti.x, ts.y } };
vertex[2] = { pos[2], color, { ts.x, ti.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)); auto color = ColorToIntColor(TraceColorColor(m_wheelTrace[i].color));
Vertex3D vertex[4]; VertexParticle vertex[4];
vertex[0] = { pos[0], color }; vertex[0] = { pos[0], color };
vertex[1] = { pos[1], color }; vertex[1] = { pos[1], color };
vertex[2] = { pos[2], color }; vertex[2] = { pos[2], color };

View File

@ -67,8 +67,6 @@ CGL33ParticleRenderer::CGL33ParticleRenderer(CGL33Device* device)
glUseProgram(m_program); glUseProgram(m_program);
// Setup uniforms // Setup uniforms
glm::mat4 identity(1.0f);
m_projectionMatrix = glGetUniformLocation(m_program, "uni_ProjectionMatrix"); m_projectionMatrix = glGetUniformLocation(m_program, "uni_ProjectionMatrix");
m_viewMatrix = glGetUniformLocation(m_program, "uni_ViewMatrix"); m_viewMatrix = glGetUniformLocation(m_program, "uni_ViewMatrix");
m_modelMatrix = glGetUniformLocation(m_program, "uni_ModelMatrix"); m_modelMatrix = glGetUniformLocation(m_program, "uni_ModelMatrix");
@ -102,7 +100,8 @@ CGL33ParticleRenderer::CGL33ParticleRenderer(CGL33Device* device)
// Generic buffer // Generic buffer
glGenBuffers(1, &m_bufferVBO); glGenBuffers(1, &m_bufferVBO);
glBindBuffer(GL_COPY_WRITE_BUFFER, 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); glGenVertexArrays(1, &m_bufferVAO);
glBindVertexArray(m_bufferVAO); glBindVertexArray(m_bufferVAO);
@ -194,26 +193,52 @@ void CGL33ParticleRenderer::SetTransparency(TransparencyMode mode)
m_device->SetTransparency(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) // Buffer full, orphan
m_bufferCapacity = size; if (total >= m_bufferCapacity)
{
glBufferData(GL_ARRAY_BUFFER, m_bufferCapacity * sizeof(VertexParticle), nullptr, GL_STREAM_DRAW);
// Send new vertices to GPU m_bufferOffset = 0;
glBindBuffer(GL_ARRAY_BUFFER, m_bufferVBO);
glBufferData(GL_ARRAY_BUFFER, m_bufferCapacity, nullptr, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), // Respecify vertex attributes
reinterpret_cast<void*>(offsetof(Vertex3D, position))); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexParticle),
reinterpret_cast<void*>(offsetof(VertexParticle, position)));
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex3D), glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VertexParticle),
reinterpret_cast<void*>(offsetof(Vertex3D, color))); reinterpret_cast<void*>(offsetof(VertexParticle, color)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexParticle),
reinterpret_cast<void*>(offsetof(Vertex3D, uv))); reinterpret_cast<void*>(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<VertexParticle*>(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;
} }

View File

@ -63,7 +63,7 @@ public:
virtual void SetTransparency(TransparencyMode mode) override; virtual void SetTransparency(TransparencyMode mode) override;
//! Draws particles //! 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: private:
CGL33Device* const m_device; CGL33Device* const m_device;
@ -90,7 +90,9 @@ private:
// Vertex array object // Vertex array object
GLuint m_bufferVAO = 0; GLuint m_bufferVAO = 0;
// VBO capacity // VBO capacity
GLsizei m_bufferCapacity = 8 * sizeof(Vertex3D); GLsizei m_bufferCapacity = 64 * 1024;
// Buffer offset
GLsizei m_bufferOffset = 0;
}; };
} }

View File

@ -27,6 +27,8 @@ uniform mat4 uni_ProjectionMatrix;
uniform mat4 uni_ViewMatrix; uniform mat4 uni_ViewMatrix;
uniform mat4 uni_ModelMatrix; uniform mat4 uni_ModelMatrix;
uniform vec4 uni_Color;
out VertexData out VertexData
{ {
vec4 Color; vec4 Color;
@ -37,6 +39,6 @@ void main()
{ {
gl_Position = uni_ProjectionMatrix * uni_ViewMatrix * uni_ModelMatrix * in_VertexCoord; gl_Position = uni_ProjectionMatrix * uni_ViewMatrix * uni_ModelMatrix * in_VertexCoord;
data.Color = in_Color; data.Color = in_Color * uni_Color;
data.TexCoord = in_TexCoord; data.TexCoord = in_TexCoord;
} }