Add the ceasefire settings to the new simulation settings system.
[0ad.git] / source / renderer / ParticleRenderer.cpp
blob977c294b3ed886bdf27621626043f90f6a3e4a09
1 /* Copyright (C) 2011 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
20 #include "ParticleRenderer.h"
22 #include "graphics/ParticleEmitter.h"
23 #include "graphics/ShaderDefines.h"
24 #include "graphics/ShaderManager.h"
25 #include "graphics/TextureManager.h"
26 #include "ps/Profile.h"
27 #include "renderer/Renderer.h"
29 struct ParticleRendererInternals
31 int frameNumber;
32 CShaderTechniquePtr shader;
33 CShaderTechniquePtr shaderSolid;
34 std::vector<CParticleEmitter*> emitters[CRenderer::CULL_MAX];
37 ParticleRenderer::ParticleRenderer()
39 m = new ParticleRendererInternals();
40 m->frameNumber = 0;
43 ParticleRenderer::~ParticleRenderer()
45 delete m;
48 void ParticleRenderer::Submit(int cullGroup, CParticleEmitter* emitter)
50 m->emitters[cullGroup].push_back(emitter);
53 void ParticleRenderer::EndFrame()
55 for (int cullGroup = 0; cullGroup < CRenderer::CULL_MAX; ++cullGroup)
56 m->emitters[cullGroup].clear();
57 // this should leave the capacity unchanged, which is okay since it
58 // won't be very large or very variable
61 struct SortEmitterDistance
63 SortEmitterDistance(const CMatrix3D& m) : worldToCam(m) { }
65 // TODO: if this is slow, we should pre-compute the distance for each emitter
67 bool operator()(CParticleEmitter* const& a, CParticleEmitter* const& b)
69 CVector3D posa = a->GetPosition();
70 CVector3D posb = b->GetPosition();
71 if (posa == posb)
72 return false;
73 float dista = worldToCam.Transform(posa).LengthSquared();
74 float distb = worldToCam.Transform(posb).LengthSquared();
75 return distb < dista;
78 CMatrix3D worldToCam;
81 void ParticleRenderer::PrepareForRendering(const CShaderDefines& context)
83 PROFILE3("prepare particles");
85 // Can't load the shader in the constructor because it's called before the
86 // renderer initialisation is complete, so load it the first time through here
87 if (!m->shader)
89 // Only construct the shaders when shaders are supported and enabled; otherwise
90 // RenderParticles will never be called so it's safe to leave the shaders as null
91 if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
93 m->shader = g_Renderer.GetShaderManager().LoadEffect(str_particle, context, CShaderDefines());
94 m->shaderSolid = g_Renderer.GetShaderManager().LoadEffect(str_particle_solid, context, CShaderDefines());
98 ++m->frameNumber;
100 for (int cullGroup = 0; cullGroup < CRenderer::CULL_MAX; ++cullGroup)
102 PROFILE("update emitters");
103 for (size_t i = 0; i < m->emitters[cullGroup].size(); ++i)
105 CParticleEmitter* emitter = m->emitters[cullGroup][i];
106 emitter->UpdateArrayData(m->frameNumber);
107 emitter->PrepareForRendering();
111 for (int cullGroup = 0; cullGroup < CRenderer::CULL_MAX; ++cullGroup)
113 // Sort back-to-front by distance from camera
114 PROFILE("sort emitters");
115 CMatrix3D worldToCam;
116 g_Renderer.GetViewCamera().m_Orientation.GetInverse(worldToCam);
117 std::stable_sort(m->emitters[cullGroup].begin(), m->emitters[cullGroup].end(), SortEmitterDistance(worldToCam));
120 // TODO: should batch by texture here when possible, maybe
123 void ParticleRenderer::RenderParticles(int cullGroup, bool solidColor)
125 CShaderTechniquePtr shader = solidColor ? m->shaderSolid : m->shader;
127 std::vector<CParticleEmitter*>& emitters = m->emitters[cullGroup];
129 shader->BeginPass();
131 shader->GetShader()->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
132 shader->GetShader()->Uniform(str_modelViewMatrix, g_Renderer.GetViewCamera().GetOrientation().GetInverse());
134 if (!solidColor)
135 glEnable(GL_BLEND);
136 glDepthMask(0);
138 for (size_t i = 0; i < emitters.size(); ++i)
140 CParticleEmitter* emitter = emitters[i];
142 emitter->Bind(shader->GetShader());
143 emitter->RenderArray(shader->GetShader());
146 CVertexBuffer::Unbind();
148 pglBlendEquationEXT(GL_FUNC_ADD);
149 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
151 glDisable(GL_BLEND);
152 glDepthMask(1);
154 shader->EndPass();
157 void ParticleRenderer::RenderBounds(int cullGroup, CShaderProgramPtr& shader)
159 std::vector<CParticleEmitter*>& emitters = m->emitters[cullGroup];
161 for (size_t i = 0; i < emitters.size(); ++i)
163 CParticleEmitter* emitter = emitters[i];
165 CBoundingBoxAligned bounds = emitter->m_Type->CalculateBounds(emitter->GetPosition(), emitter->GetParticleBounds());
166 bounds.Render(shader);