Added CParticleRenderer and reimplemented particle rendering code to use it

dev
Tomasz Kapuściński 2022-01-20 21:38:58 +01:00
parent 710f448477
commit 048393f448
12 changed files with 613 additions and 103 deletions

View File

@ -147,6 +147,8 @@ add_library(colobotbase STATIC
graphics/opengl/gl33renderers.h
graphics/opengl/gl33objectrenderer.cpp
graphics/opengl/gl33objectrenderer.h
graphics/opengl/gl33particlerenderer.cpp
graphics/opengl/gl33particlerenderer.h
graphics/opengl/glframebuffer.cpp
graphics/opengl/glframebuffer.h
graphics/opengl/glutil.cpp

View File

@ -48,6 +48,8 @@ class CUIRenderer;
class CTerrainRenderer;
class CShadowRenderer;
class CObjectRenderer;
class CParticleRenderer;
struct FramebufferParams;
struct Light;
struct Material;
@ -442,6 +444,8 @@ public:
virtual CTerrainRenderer* GetTerrainRenderer() = 0;
//! Returns object renderer
virtual CObjectRenderer* GetObjectRenderer() = 0;
//! Returns particle renderer
virtual CParticleRenderer* GetParticleRenderer() = 0;
//! Returns shadow renderer
virtual CShadowRenderer* GetShadowRenderer() = 0;

View File

@ -182,6 +182,38 @@ public:
virtual void DrawObject(const CVertexBuffer* buffer) = 0;
};
/**
* \class CParticleRenderer
* \brief Abstract interface for particle renderers
*/
class CParticleRenderer : public CRenderer
{
public:
virtual ~CParticleRenderer() { }
virtual void Begin() = 0;
virtual void End() = 0;
//! Sets projection matrix
virtual void SetProjectionMatrix(const glm::mat4& matrix) = 0;
//! Sets view matrix
virtual void SetViewMatrix(const glm::mat4& matrix) = 0;
//! Sets model matrix
virtual void SetModelMatrix(const glm::mat4& matrix) = 0;
//! Sets color
virtual void SetColor(const glm::vec4& color) = 0;
//! Sets texture
virtual void SetTexture(const Texture& texture) = 0;
//! Sets transparency mode
virtual void SetTransparency(TransparencyMode mode) = 0;
//! Draws particles
virtual void DrawParticle(PrimitiveType type, int count, const Vertex3D* vertices) = 0;
};
/**
* \class CShadowRenderer
* \brief Abstract interface for shadow renderers

View File

@ -3672,10 +3672,17 @@ void CEngine::Draw3DScene()
}
m_displayGoto.clear();
auto particleRenderer = m_device->GetParticleRenderer();
particleRenderer->Begin();
particleRenderer->SetProjectionMatrix(m_matProj);
particleRenderer->SetViewMatrix(m_matView);
CProfiler::StartPerformanceCounter(PCNT_RENDER_PARTICLE_WORLD);
m_particle->DrawParticle(SH_WORLD); // draws the particles of the 3D world
CProfiler::StopPerformanceCounter(PCNT_RENDER_PARTICLE_WORLD);
particleRenderer->End();
m_device->SetRenderState(RENDER_STATE_LIGHTING, true);
m_lightning->Draw(); // draws lightning
@ -4293,9 +4300,17 @@ void CEngine::DrawInterface()
if (!m_screenshotMode && m_renderInterface)
{
auto particleRenderer = m_device->GetParticleRenderer();
particleRenderer->Begin();
particleRenderer->SetProjectionMatrix(m_matProjInterface);
particleRenderer->SetViewMatrix(m_matViewInterface);
particleRenderer->SetModelMatrix(m_matWorldInterface);
CProfiler::StartPerformanceCounter(PCNT_RENDER_PARTICLE_IFACE);
m_particle->DrawParticle(SH_INTERFACE); // draws the particles of the interface
CProfiler::StopPerformanceCounter(PCNT_RENDER_PARTICLE_IFACE);
particleRenderer->End();
}
// 3D objects drawn in front of interface
@ -4376,8 +4391,15 @@ void CEngine::DrawInterface()
renderer->End();
auto particleRenderer = m_device->GetParticleRenderer();
particleRenderer->Begin();
particleRenderer->SetProjectionMatrix(m_matProj);
particleRenderer->SetViewMatrix(m_matView);
m_particle->DrawParticle(SH_FRONT); // draws the particles of the 3D world
particleRenderer->End();
m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false);
m_device->SetRenderState(RENDER_STATE_LIGHTING, false);
m_device->SetRenderState(RENDER_STATE_FOG, false);

View File

@ -25,6 +25,7 @@
#include "common/logger.h"
#include "graphics/core/device.h"
#include "graphics/core/renderers.h"
#include "graphics/engine/engine.h"
#include "graphics/engine/terrain.h"
@ -84,6 +85,7 @@ CParticle::~CParticle()
void CParticle::SetDevice(CDevice* device)
{
m_device = device;
m_renderer = device->GetParticleRenderer();
}
void CParticle::FlushParticle()
@ -2505,7 +2507,7 @@ void CParticle::TrackDraw(int i, ParticleType type)
}
glm::mat4 mat = glm::mat4(1.0f);
m_device->SetTransform(TRANSFORM_WORLD, mat);
m_renderer->SetModelMatrix(mat);
glm::vec2 texInf{ 0, 0 }, texSup{ 0, 0 };
@ -2601,7 +2603,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);
Vertex vertex[4];
Vertex3D vertex[4];
glm::vec3 corner[4];
for (int counter = 0; counter < m_track[i].posUsed-1; counter++)
@ -2640,22 +2642,24 @@ void CParticle::TrackDraw(int i, ParticleType type)
corner[3].y = p2.y;
corner[3].z = rot.y;
glm::u8vec4 white(255);
if (p2.y < p1.y)
{
vertex[0] = { corner[1], n, { texSup.x, texSup.y } };
vertex[1] = { corner[0], n, { texInf.x, texSup.y } };
vertex[2] = { corner[3], n, { texSup.x, texInf.y } };
vertex[3] = { corner[2], n, { texInf.x, texInf.y } };
vertex[0] = { corner[1], white, { texSup.x, texSup.y } };
vertex[1] = { corner[0], white, { texInf.x, texSup.y } };
vertex[2] = { corner[3], white, { texSup.x, texInf.y } };
vertex[3] = { corner[2], white, { texInf.x, texInf.y } };
}
else
{
vertex[0] = { corner[0], n, { texSup.x, texSup.y } };
vertex[1] = { corner[1], n, { texInf.x, texSup.y } };
vertex[2] = { corner[2], n, { texSup.x, texInf.y } };
vertex[3] = { corner[3], n, { texInf.x, texInf.y } };
vertex[0] = { corner[0], white, { texSup.x, texSup.y } };
vertex[1] = { corner[1], white, { texInf.x, texSup.y } };
vertex[2] = { corner[2], white, { texSup.x, texInf.y } };
vertex[3] = { corner[3], white, { texInf.x, texInf.y } };
}
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, 4);
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
if (f2 < 0.0f) break;
@ -2685,9 +2689,9 @@ void CParticle::DrawParticleTriangle(int i)
mat[3][0] = pos.x;
mat[3][1] = pos.y;
mat[3][2] = pos.z;
m_device->SetTransform(TRANSFORM_WORLD, mat);
m_renderer->SetModelMatrix(mat);
m_device->DrawPrimitive(PrimitiveType::TRIANGLES, m_triangle[i].triangle, 3);
m_renderer->DrawParticle(PrimitiveType::TRIANGLES, 3, m_triangle[i].triangle);
m_engine->AddStatisticTriangle(1);
}
@ -2700,7 +2704,7 @@ void CParticle::DrawParticleNorm(int i)
glm::vec3 corner[4];
Vertex vertex[4];
Vertex3D vertex[4];
if (m_particle[i].sheet == SH_INTERFACE)
{
@ -2728,12 +2732,14 @@ void CParticle::DrawParticleNorm(int i)
corner[3].y = pos.y-dim.y;
corner[3].z = 0.0f;
vertex[0] = { corner[1], n, { m_particle[i].texSup.x, m_particle[i].texSup.y } };
vertex[1] = { corner[0], n, { m_particle[i].texInf.x, m_particle[i].texSup.y } };
vertex[2] = { corner[3], n, { m_particle[i].texSup.x, m_particle[i].texInf.y } };
vertex[3] = { corner[2], n, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
glm::u8vec4 white(255);
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, 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 } };
vertex[3] = { corner[2], white, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
}
else
@ -2755,7 +2761,7 @@ void CParticle::DrawParticleNorm(int i)
mat[3][0] = pos.x;
mat[3][1] = pos.y;
mat[3][2] = pos.z;
m_device->SetTransform(TRANSFORM_WORLD, mat);
m_renderer->SetModelMatrix(mat);
glm::vec3 n(0.0f, 0.0f, -1.0f);
@ -2779,12 +2785,14 @@ void CParticle::DrawParticleNorm(int i)
corner[3].y = -dim.y;
corner[3].z = 0.0f;
vertex[0] = { corner[1], n, { m_particle[i].texSup.x, m_particle[i].texSup.y } };
vertex[1] = { corner[0], n, { m_particle[i].texInf.x, m_particle[i].texSup.y } };
vertex[2] = { corner[3], n, { m_particle[i].texSup.x, m_particle[i].texInf.y } };
vertex[3] = { corner[2], n, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
glm::u8vec4 color = ColorToIntColor(m_particle[i].color);
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, 4, m_particle[i].color);
vertex[0] = { corner[1], color, { m_particle[i].texSup.x, m_particle[i].texSup.y } };
vertex[1] = { corner[0], color, { m_particle[i].texInf.x, m_particle[i].texSup.y } };
vertex[2] = { corner[3], color, { m_particle[i].texSup.x, m_particle[i].texInf.y } };
vertex[3] = { corner[2], color, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
}
}
@ -2817,7 +2825,7 @@ void CParticle::DrawParticleFlat(int i)
mat[3][0] = pos.x;
mat[3][1] = pos.y;
mat[3][2] = pos.z;
m_device->SetTransform(TRANSFORM_WORLD, mat);
m_renderer->SetModelMatrix(mat);
glm::vec3 n(0.0f, 0.0f, -1.0f);
@ -2842,13 +2850,15 @@ void CParticle::DrawParticleFlat(int i)
corner[3].y = -dim.y;
corner[3].z = 0.0f;
Vertex vertex[4];
vertex[0] = { corner[1], n, { m_particle[i].texSup.x, m_particle[i].texSup.y } };
vertex[1] = { corner[0], n, { m_particle[i].texInf.x, m_particle[i].texSup.y } };
vertex[2] = { corner[3], n, { m_particle[i].texSup.x, m_particle[i].texInf.y } };
vertex[3] = { corner[2], n, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
glm::u8vec4 white(255);
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, 4);
Vertex3D 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 } };
vertex[3] = { corner[2], white, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
}
@ -2906,9 +2916,7 @@ void CParticle::DrawParticleFog(int i)
mat[3][0] = pos.x;
mat[3][1] = pos.y;
mat[3][2] = pos.z;
m_device->SetTransform(TRANSFORM_WORLD, mat);
glm::vec3 n(0.0f, 0.0f, -1.0f);
m_renderer->SetModelMatrix(mat);
glm::vec3 corner[4];
@ -2928,14 +2936,16 @@ void CParticle::DrawParticleFog(int i)
corner[3].y = -dim.y;
corner[3].z = 0.0f;
Vertex vertex[4];
glm::u8vec4 white(255);
vertex[0] = { corner[1], n, { m_particle[i].texSup.x, m_particle[i].texSup.y } };
vertex[1] = { corner[0], n, { m_particle[i].texInf.x, m_particle[i].texSup.y } };
vertex[2] = { corner[3], n, { m_particle[i].texSup.x, m_particle[i].texInf.y } };
vertex[3] = { corner[2], n, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
Vertex3D vertex[4];
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, 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 } };
vertex[3] = { corner[2], white, { m_particle[i].texInf.x, m_particle[i].texInf.y } };
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
}
@ -2967,7 +2977,7 @@ void CParticle::DrawParticleRay(int i)
mat[3][0] = pos.x;
mat[3][1] = pos.y;
mat[3][2] = pos.z;
m_device->SetTransform(TRANSFORM_WORLD, mat);
m_renderer->SetModelMatrix(mat);
glm::vec3 n(0.0f, 0.0f, left ? 1.0f : -1.0f);
@ -3056,7 +3066,9 @@ void CParticle::DrawParticleRay(int i)
corner[2].z = (Math::Rand()-0.5f)*vario1;
corner[3].z = (Math::Rand()-0.5f)*vario1;
Vertex vertex[4];
Vertex3D vertex[4];
glm::u8vec4 white(255);
for (int rank = 0; rank < step; rank++)
{
@ -3084,12 +3096,12 @@ void CParticle::DrawParticleRay(int i)
if (r % 4 < 2)
Math::Swap(texInf.y, texSup.y);
vertex[0] = { corner[1], n, { texSup.x, texSup.y } };
vertex[1] = { corner[0], n, { texInf.x, texSup.y } };
vertex[2] = { corner[3], n, { texSup.x, texInf.y } };
vertex[3] = { corner[2], n, { texInf.x, texInf.y } };
vertex[0] = { corner[1], white, { texSup.x, texSup.y } };
vertex[1] = { corner[0], white, { texInf.x, texSup.y } };
vertex[2] = { corner[3], white, { texSup.x, texInf.y } };
vertex[3] = { corner[2], white, { texInf.x, texInf.y } };
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, 4);
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
}
adv += dim.x*2.0f;
@ -3102,8 +3114,8 @@ void CParticle::DrawParticleSphere(int i)
if (zoom == 0.0f) return;
m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE | ENG_RSTATE_WRAP,
IntensityToColor(m_particle[i].intensity));
m_renderer->SetTransparency(TransparencyMode::BLACK);
m_renderer->SetColor(IntensityToColor(m_particle[i].intensity));
glm::mat4 mat = glm::mat4(1.0f);
mat[0][0] = zoom;
@ -3124,7 +3136,7 @@ void CParticle::DrawParticleSphere(int i)
mat = mat * rot;
}
m_device->SetTransform(TRANSFORM_WORLD, mat);
m_renderer->SetModelMatrix(mat);
glm::vec2 ts, ti;
ts.x = m_particle[i].texSup.x;
@ -3151,7 +3163,9 @@ void CParticle::DrawParticleSphere(int i)
float deltaRingAngle = Math::PI/numRings;
float deltaSegAngle = 2.0f*Math::PI/numSegments;
Vertex vertex[2*16*(16+1)];
std::vector<Vertex3D> vertex(2*16*(16+1));
glm::u8vec4 white(255);
// Generate the group of rings for the sphere.
int j = 0;
@ -3183,15 +3197,16 @@ void CParticle::DrawParticleSphere(int i)
tu0 = ts.x+(ti.x-ts.x)*tu0;
float tu1 = tu0;
vertex[j++] = { v0, v0, { tu0, tv0 } };
vertex[j++] = { v1, v1, { tu1, tv1 } };
vertex[j++] = { v0, white, { tu0, tv0 } };
vertex[j++] = { v1, white, { tu1, tv1 } };
}
}
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, j);
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, j, vertex.data());
m_engine->AddStatisticTriangle(j);
m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK, IntensityToColor(m_particle[i].intensity));
m_renderer->SetColor(IntensityToColor(m_particle[i].intensity));
m_renderer->SetTransparency(TransparencyMode::BLACK);
}
//! Returns the height depending on the progress
@ -3210,8 +3225,8 @@ void CParticle::DrawParticleCylinder(int i)
float diam = m_particle[i].dim.y;
if (progress >= 1.0f || zoom == 0.0f) return;
m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE | ENG_RSTATE_WRAP,
IntensityToColor(m_particle[i].intensity));
m_renderer->SetColor(IntensityToColor(m_particle[i].intensity));
m_renderer->SetTransparency(TransparencyMode::BLACK);
glm::mat4 mat = glm::mat4(1.0f);
mat[0][0] = zoom;
@ -3221,7 +3236,7 @@ void CParticle::DrawParticleCylinder(int i)
mat[3][1] = m_particle[i].pos.y;
mat[3][2] = m_particle[i].pos.z;
m_device->SetTransform(TRANSFORM_WORLD, mat);
m_renderer->SetModelMatrix(mat);
glm::vec2 ts, ti;
ts.x = m_particle[i].texSup.x;
@ -3249,7 +3264,9 @@ void CParticle::DrawParticleCylinder(int i)
}
}
Vertex vertex[2*5*(10+1)];
std::vector<Vertex3D> vertex(2*5*(10+1));
glm::u8vec4 white(255);
int j = 0;
for (int ring = 0; ring < numRings; ring++)
@ -3278,15 +3295,16 @@ void CParticle::DrawParticleCylinder(int i)
tu0 = ts.x+(ti.x-ts.x)*tu0;
float tu1 = tu0;
vertex[j++] = { v0, v0, { tu0, tv0 } };
vertex[j++] = { v1, v1, { tu1, tv1 } };
vertex[j++] = { v0, white, { tu0, tv0 } };
vertex[j++] = { v1, white, { tu1, tv1 } };
}
}
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, j);
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, j, vertex.data());
m_engine->AddStatisticTriangle(j);
m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK, IntensityToColor(m_particle[i].intensity));
m_renderer->SetColor(IntensityToColor(m_particle[i].intensity));
m_renderer->SetTransparency(TransparencyMode::BLACK);
}
void CParticle::DrawParticleText(int i)
@ -3294,8 +3312,9 @@ void CParticle::DrawParticleText(int i)
CharTexture tex = m_engine->GetText()->GetCharTexture(static_cast<UTF8Char>(m_particle[i].text), FONT_STUDIO, FONT_SIZE_BIG*2.0f);
if (tex.id == 0) return;
m_device->SetTexture(0, tex.id);
m_engine->SetState(ENG_RSTATE_TTEXTURE_ALPHA, IntensityToColor(m_particle[i].intensity));
m_renderer->SetTexture({ tex.id });
m_renderer->SetColor(IntensityToColor(m_particle[i].intensity));
m_renderer->SetTransparency(TransparencyMode::ALPHA);
glm::ivec2 fontTextureSize = m_engine->GetText()->GetFontTextureSize();
m_particle[i].texSup.x = static_cast<float>(tex.charPos.x) / fontTextureSize.x;
@ -3312,10 +3331,14 @@ void CParticle::DrawParticleWheel(int i)
float dist = Math::DistanceProjected(m_engine->GetEyePt(), m_wheelTrace[i].pos[0]);
if (dist > 300.0f) return;
glm::u8vec4 white(255);
if (m_wheelTrace[i].color == TraceColor::BlackArrow || m_wheelTrace[i].color == TraceColor::RedArrow)
{
m_engine->SetTexture("textures/effect03.png");
m_engine->SetState(ENG_RSTATE_ALPHA);
auto texture = m_engine->LoadTexture("textures/effect03.png");
m_renderer->SetTexture(texture);
m_renderer->SetTransparency(TransparencyMode::ALPHA);
m_renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });
glm::vec3 pos[4];
pos[0] = m_wheelTrace[i].pos[0];
@ -3334,16 +3357,16 @@ void CParticle::DrawParticleWheel(int i)
ti.x = ti.x-dp;
ti.y = ti.y-dp;
Vertex vertex[4];
vertex[0] = { pos[0], n, { ts.x, ts.y } };
vertex[1] = { pos[1], n, { ti.x, ts.y } };
vertex[2] = { pos[2], n, { ts.x, ti.y } };
vertex[3] = { pos[3], n, { ti.x, ti.y } };
auto color = ColorToIntColor(TraceColorColor(m_wheelTrace[i].color));
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, 4, TraceColorColor(m_wheelTrace[i].color));
Vertex3D 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 } };
vertex[3] = { pos[3], color, { ti.x, ti.y } };
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
m_engine->SetState(ENG_RSTATE_OPAQUE_COLOR);
}
else
{
@ -3353,30 +3376,21 @@ void CParticle::DrawParticleWheel(int i)
pos[2] = m_wheelTrace[i].pos[2];
pos[3] = m_wheelTrace[i].pos[3];
glm::vec3 n(0.0f, 1.0f, 0.0f);
auto color = ColorToIntColor(TraceColorColor(m_wheelTrace[i].color));
Vertex vertex[4];
vertex[0] = { pos[0], n };
vertex[1] = { pos[1], n };
vertex[2] = { pos[2], n };
vertex[3] = { pos[3], n };
Vertex3D vertex[4];
vertex[0] = { pos[0], color };
vertex[1] = { pos[1], color };
vertex[2] = { pos[2], color };
vertex[3] = { pos[3], color };
m_device->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, vertex, 4, TraceColorColor(m_wheelTrace[i].color));
m_renderer->DrawParticle(PrimitiveType::TRIANGLE_STRIP, 4, vertex);
m_engine->AddStatisticTriangle(2);
}
}
void CParticle::DrawParticle(int sheet)
{
Material mat;
mat.diffuse.r = 1.0f;
mat.diffuse.g = 1.0f;
mat.diffuse.b = 1.0f; // white
mat.ambient.r = 0.5f;
mat.ambient.g = 0.5f;
mat.ambient.b = 0.5f;
m_engine->SetMaterial(mat);
// Draw the basic particles of triangles.
if (m_totalInterface[0][sheet] > 0)
{
@ -3386,8 +3400,11 @@ void CParticle::DrawParticle(int sheet)
if (m_particle[i].sheet != sheet) continue;
if (m_particle[i].type == PARTIPART) continue;
m_engine->SetTexture(!m_triangle[i].tex1Name.empty() ? "textures/"+m_triangle[i].tex1Name : "");
m_engine->SetState(m_triangle[i].state);
auto texture = m_engine->LoadTexture(!m_triangle[i].tex1Name.empty()
? "textures/" + m_triangle[i].tex1Name : "");
m_renderer->SetTexture(texture);
//m_engine->SetState(m_triangle[i].state);
DrawParticleTriangle(i);
}
}
@ -3395,9 +3412,10 @@ void CParticle::DrawParticle(int sheet)
// Draw tire marks.
if (m_wheelTraceTotal > 0 && sheet == SH_WORLD)
{
m_engine->SetState(ENG_RSTATE_OPAQUE_COLOR);
glm::mat4 matrix = glm::mat4(1.0f);
m_device->SetTransform(TRANSFORM_WORLD, matrix);
m_renderer->SetModelMatrix(matrix);
m_renderer->SetTransparency(TransparencyMode::NONE);
m_renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });
for (int i = 0; i < m_wheelTraceTotal; i++)
DrawParticleWheel(i);
@ -3409,10 +3427,15 @@ void CParticle::DrawParticle(int sheet)
bool loadTexture = false;
int state;
if (t == 4) state = ENG_RSTATE_TTEXTURE_WHITE; // effect03.png
else state = ENG_RSTATE_TTEXTURE_BLACK; // effect[00..02].png
m_engine->SetState(state);
TransparencyMode mode = TransparencyMode::ALPHA;
if (t == 4)
mode = TransparencyMode::WHITE;
else
mode = TransparencyMode::BLACK;
m_renderer->SetTransparency(mode);
m_renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });
for (int j = 0; j < MAXPARTICULE; j++)
{
@ -3424,19 +3447,23 @@ void CParticle::DrawParticle(int sheet)
{
std::string name;
NameParticle(name, t);
m_engine->SetTexture("textures/"+name);
auto texture = m_engine->LoadTexture("textures/" + name);
m_renderer->SetTexture(texture);
loadTexture = true;
}
int r = m_particle[i].trackRank;
if (r != -1)
{
m_engine->SetState(state);
m_renderer->SetTransparency(mode);
m_renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });
//m_engine->SetState(state);
TrackDraw(r, m_particle[i].type); // draws the drag
if (!m_track[r].drawParticle) continue;
}
m_engine->SetState(state, IntensityToColor(m_particle[i].intensity));
m_renderer->SetTransparency(mode);
m_renderer->SetColor(IntensityToColor(m_particle[i].intensity));
if (m_particle[i].ray) // ray?
{

View File

@ -41,6 +41,8 @@ class CSoundInterface;
namespace Gfx
{
class CParticleRenderer;
const short MAXPARTICULE = 500;
const short MAXPARTITYPE = 6;
const short MAXTRACK = 100;
@ -339,6 +341,7 @@ protected:
CWater* m_water = nullptr;
CRobotMain* m_main = nullptr;
CSoundInterface* m_sound = nullptr;
CParticleRenderer* m_renderer = nullptr;
Particle m_particle[MAXPARTICULE*MAXPARTITYPE];
EngineTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0

View File

@ -33,6 +33,7 @@
#include "graphics/opengl/glframebuffer.h"
#include "graphics/opengl/gl33renderers.h"
#include "graphics/opengl/gl33objectrenderer.h"
#include "graphics/opengl/gl33particlerenderer.h"
#include "math/geometry.h"
@ -434,6 +435,7 @@ bool CGL33Device::Create()
m_uiRenderer = std::make_unique<CGL33UIRenderer>(this);
m_terrainRenderer = std::make_unique<CGL33TerrainRenderer>(this);
m_objectRenderer = std::make_unique<CGL33ObjectRenderer>(this);
m_particleRenderer = std::make_unique<CGL33ParticleRenderer>(this);
m_shadowRenderer = std::make_unique<CGL33ShadowRenderer>(this);
glUseProgram(m_normalProgram);
@ -501,6 +503,9 @@ void CGL33Device::Destroy()
m_uiRenderer = nullptr;
m_terrainRenderer = nullptr;
m_objectRenderer = nullptr;
m_particleRenderer = nullptr;
m_shadowRenderer = nullptr;
}
void CGL33Device::ConfigChanged(const DeviceConfig& newConfig)
@ -561,6 +566,11 @@ CObjectRenderer* CGL33Device::GetObjectRenderer()
return m_objectRenderer.get();
}
CParticleRenderer* CGL33Device::GetParticleRenderer()
{
return m_particleRenderer.get();
}
CShadowRenderer* CGL33Device::GetShadowRenderer()
{
return m_shadowRenderer.get();

View File

@ -81,6 +81,7 @@ public:
class CGL33UIRenderer;
class CGL33TerrainRenderer;
class CGL33ObjectRenderer;
class CGL33ParticleRenderer;
class CGL33ShadowRenderer;
/**
@ -118,6 +119,7 @@ public:
CUIRenderer* GetUIRenderer() override;
CTerrainRenderer* GetTerrainRenderer() override;
CObjectRenderer* GetObjectRenderer() override;
CParticleRenderer* GetParticleRenderer() override;
CShadowRenderer* GetShadowRenderer() override;
void Restore() override;
@ -300,6 +302,8 @@ private:
std::unique_ptr<CGL33TerrainRenderer> m_terrainRenderer;
//! Object renderer
std::unique_ptr<CGL33ObjectRenderer> m_objectRenderer;
//! Particle renderer
std::unique_ptr<CGL33ParticleRenderer> m_particleRenderer;
//! Shadow renderer
std::unique_ptr<CGL33ShadowRenderer> m_shadowRenderer;
};

View File

@ -0,0 +1,227 @@
#include "graphics/opengl/gl33particlerenderer.h"
#include "graphics/opengl/gl33device.h"
#include "graphics/opengl/glutil.h"
#include "graphics/core/vertex.h"
#include "common/logger.h"
#include <GL/glew.h>
#include <glm/ext.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace Gfx;
CGL33ParticleRenderer::CGL33ParticleRenderer(CGL33Device* device)
: m_device(device)
{
GetLogger()->Info("Creating CGL33ParticleRenderer\n");
std::string preamble = LoadSource("shaders/gl33/preamble.glsl");
std::string shadowSource = LoadSource("shaders/gl33/shadow.glsl");
std::string vsSource = LoadSource("shaders/gl33/particle_vs.glsl");
std::string fsSource = LoadSource("shaders/gl33/particle_fs.glsl");
GLint vsShader = CreateShader(GL_VERTEX_SHADER, { preamble, shadowSource, vsSource });
if (vsShader == 0)
{
GetLogger()->Error("Cound not create vertex shader from file 'particle_vs.glsl'\n");
return;
}
GLint fsShader = CreateShader(GL_FRAGMENT_SHADER, { preamble, shadowSource, fsSource });
if (fsShader == 0)
{
GetLogger()->Error("Cound not create fragment shader from file 'particle_fs.glsl'\n");
return;
}
m_program = LinkProgram({ vsShader, fsShader });
glDeleteShader(vsShader);
glDeleteShader(fsShader);
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");
m_fogRange = glGetUniformLocation(m_program, "uni_FogRange");
m_fogColor = glGetUniformLocation(m_program, "uni_FogColor");
m_color = glGetUniformLocation(m_program, "uni_Color");
m_alphaScissor = glGetUniformLocation(m_program, "uni_AlphaScissor");
// Set texture units
auto texture = glGetUniformLocation(m_program, "uni_Texture");
glUniform1i(texture, 10);
glUniform1f(m_alphaScissor, 0.5f);
// White texture
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &m_whiteTexture);
glBindTexture(GL_TEXTURE_2D, m_whiteTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
glUseProgram(0);
// Generic buffer
glGenBuffers(1, &m_bufferVBO);
glBindBuffer(GL_COPY_WRITE_BUFFER, m_bufferVBO);
glBufferData(GL_COPY_WRITE_BUFFER, m_bufferCapacity, nullptr, GL_STREAM_DRAW);
glGenVertexArrays(1, &m_bufferVAO);
glBindVertexArray(m_bufferVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
GetLogger()->Info("CGL33ParticleRenderer created successfully\n");
}
CGL33ParticleRenderer::~CGL33ParticleRenderer()
{
glDeleteProgram(m_program);
glDeleteTextures(1, &m_whiteTexture);
}
void CGL33ParticleRenderer::Begin()
{
glUseProgram(m_program);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, m_whiteTexture);
m_texture = 0;
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glUniform4f(m_color, 1.0f, 1.0f, 1.0f, 1.0f);
glBindVertexArray(m_bufferVAO);
glBindBuffer(GL_ARRAY_BUFFER, m_bufferVBO);
}
void CGL33ParticleRenderer::End()
{
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, 0);
m_texture = 0;
glDepthMask(GL_TRUE);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
m_device->Restore();
}
void CGL33ParticleRenderer::SetProjectionMatrix(const glm::mat4& matrix)
{
glUniformMatrix4fv(m_projectionMatrix, 1, GL_FALSE, value_ptr(matrix));
}
void CGL33ParticleRenderer::SetViewMatrix(const glm::mat4& matrix)
{
glm::mat4 scale(1.0f);
scale[2][2] = -1.0f;
auto viewMatrix = scale * matrix;
glUniformMatrix4fv(m_viewMatrix, 1, GL_FALSE, value_ptr(viewMatrix));
}
void CGL33ParticleRenderer::SetModelMatrix(const glm::mat4& matrix)
{
glUniformMatrix4fv(m_modelMatrix, 1, GL_FALSE, value_ptr(matrix));
}
void CGL33ParticleRenderer::SetColor(const glm::vec4& color)
{
glUniform4f(m_color, color.r, color.g, color.b, color.a);
}
void CGL33ParticleRenderer::SetTexture(const Texture& texture)
{
if (m_texture == texture.id) return;
m_texture = texture.id;
glActiveTexture(GL_TEXTURE10);
if (texture.id == 0)
glBindTexture(GL_TEXTURE_2D, m_whiteTexture);
else
glBindTexture(GL_TEXTURE_2D, texture.id);
}
void CGL33ParticleRenderer::SetTransparency(TransparencyMode mode)
{
switch (mode)
{
case TransparencyMode::NONE:
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
break;
case TransparencyMode::ALPHA:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
glDepthMask(GL_TRUE);
break;
case TransparencyMode::BLACK:
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
glBlendEquation(GL_FUNC_ADD);
glDepthMask(GL_FALSE);
break;
case TransparencyMode::WHITE:
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
glDepthMask(GL_FALSE);
break;
}
}
void CGL33ParticleRenderer::DrawParticle(PrimitiveType type, int count, const Vertex3D* vertices)
{
size_t size = count * sizeof(Vertex3D);
if (m_bufferCapacity < size)
m_bufferCapacity = size;
// 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);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
reinterpret_cast<void*>(offsetof(Vertex3D, position)));
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex3D),
reinterpret_cast<void*>(offsetof(Vertex3D, color)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D),
reinterpret_cast<void*>(offsetof(Vertex3D, uv)));
glDrawArrays(TranslateGfxPrimitive(type), 0, count);
}

View File

@ -0,0 +1,96 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
/**
* \file graphics/opengl/gl33objectrenderer.h
* \brief OpenGL 3.3 object renderer
*/
#pragma once
#include "graphics/core/renderers.h"
#include <GL/glew.h>
#include <array>
#include <vector>
// Graphics module namespace
namespace Gfx
{
class CGL33Device;
class CGL33ParticleRenderer : public CParticleRenderer
{
public:
CGL33ParticleRenderer(CGL33Device* device);
virtual ~CGL33ParticleRenderer();
virtual void Begin() override;
virtual void End() override;
//! Sets projection matrix
virtual void SetProjectionMatrix(const glm::mat4& matrix) override;
//! Sets view matrix
virtual void SetViewMatrix(const glm::mat4& matrix) override;
//! Sets model matrix
virtual void SetModelMatrix(const glm::mat4& matrix) override;
//! Sets color
virtual void SetColor(const glm::vec4& color) override;
//! Sets texture
virtual void SetTexture(const Texture& texture) override;
//! Sets transparency mode
virtual void SetTransparency(TransparencyMode mode) override;
//! Draws particles
virtual void DrawParticle(PrimitiveType type, int count, const Vertex3D* vertices) override;
private:
CGL33Device* const m_device;
// Uniform data
GLint m_projectionMatrix = -1;
GLint m_viewMatrix = -1;
GLint m_modelMatrix = -1;
GLint m_fogRange = -1;
GLint m_fogColor = -1;
GLint m_color = -1;
GLint m_alphaScissor = -1;
// Shader program
GLuint m_program = 0;
// 1x1 white texture
GLuint m_whiteTexture = 0;
// Currently bound primary texture
GLuint m_texture = 0;
// Vertex buffer object
GLuint m_bufferVBO = 0;
// Vertex array object
GLuint m_bufferVAO = 0;
// VBO capacity
GLsizei m_bufferCapacity = 8 * sizeof(Vertex3D);
};
}

View File

@ -0,0 +1,41 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
// FRAGMENT SHADER - PARTICLE RENDERER
uniform sampler2D uni_Texture;
uniform float uni_AlphaScissor;
in VertexData
{
vec4 Color;
vec2 TexCoord;
} data;
out vec4 out_FragColor;
void main()
{
vec4 color = texture(uni_Texture, data.TexCoord);
if (color.a < uni_AlphaScissor) discard;
out_FragColor = data.Color * color;
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
// VERTEX SHADER - PARTICLE RENDERER
layout(location = 0) in vec4 in_VertexCoord;
layout(location = 1) in vec4 in_Color;
layout(location = 2) in vec2 in_TexCoord;
uniform mat4 uni_ProjectionMatrix;
uniform mat4 uni_ViewMatrix;
uniform mat4 uni_ModelMatrix;
out VertexData
{
vec4 Color;
vec2 TexCoord;
} data;
void main()
{
gl_Position = uni_ProjectionMatrix * uni_ViewMatrix * uni_ModelMatrix * in_VertexCoord;
data.Color = in_Color;
data.TexCoord = in_TexCoord;
}