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
#include "graphics/core/vertex.h"
#include <glm/glm.hpp>
// 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;
};
/**

View File

@ -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

View File

@ -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++)
{

View File

@ -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<Vertex3D> vertex(2*16*(16+1));
std::vector<VertexParticle> vertex(2*16*(16+1));
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);
@ -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 };

View File

@ -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<void*>(offsetof(Vertex3D, position)));
// Respecify vertex attributes
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),
reinterpret_cast<void*>(offsetof(Vertex3D, color)));
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VertexParticle),
reinterpret_cast<void*>(offsetof(VertexParticle, color)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
reinterpret_cast<void*>(offsetof(Vertex3D, uv)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexParticle),
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;
//! 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;
};
}

View File

@ -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;
}