Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
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.
8 : *
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.
13 : *
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/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "renderer/TerrainRenderer.h"
21 :
22 : #include "graphics/Camera.h"
23 : #include "graphics/Canvas2D.h"
24 : #include "graphics/Decal.h"
25 : #include "graphics/GameView.h"
26 : #include "graphics/LightEnv.h"
27 : #include "graphics/LOSTexture.h"
28 : #include "graphics/Patch.h"
29 : #include "graphics/Model.h"
30 : #include "graphics/ShaderManager.h"
31 : #include "graphics/TerritoryTexture.h"
32 : #include "graphics/TextRenderer.h"
33 : #include "graphics/TextureManager.h"
34 : #include "maths/MathUtil.h"
35 : #include "ps/CLogger.h"
36 : #include "ps/CStrInternStatic.h"
37 : #include "ps/Filesystem.h"
38 : #include "ps/Game.h"
39 : #include "ps/Profile.h"
40 : #include "ps/World.h"
41 : #include "renderer/backend/gl/Device.h"
42 : #include "renderer/DecalRData.h"
43 : #include "renderer/PatchRData.h"
44 : #include "renderer/Renderer.h"
45 : #include "renderer/RenderingOptions.h"
46 : #include "renderer/SceneRenderer.h"
47 : #include "renderer/ShadowMap.h"
48 : #include "renderer/SkyManager.h"
49 : #include "renderer/VertexArray.h"
50 : #include "renderer/WaterManager.h"
51 :
52 : /**
53 : * TerrainRenderer keeps track of which phase it is in, to detect
54 : * when Submit, PrepareForRendering etc. are called in the wrong order.
55 : */
56 : enum Phase
57 : {
58 : Phase_Submit,
59 : Phase_Render
60 : };
61 :
62 :
63 : /**
64 : * Struct TerrainRendererInternals: Internal variables used by the TerrainRenderer class.
65 : */
66 0 : struct TerrainRendererInternals
67 : {
68 : /// Which phase (submitting or rendering patches) are we in right now?
69 : Phase phase;
70 :
71 : /// Patches that were submitted for this frame
72 : std::vector<CPatchRData*> visiblePatches[CSceneRenderer::CULL_MAX];
73 :
74 : /// Decals that were submitted for this frame
75 : std::vector<CDecalRData*> visibleDecals[CSceneRenderer::CULL_MAX];
76 :
77 : /// Fancy water shader
78 : CShaderTechniquePtr fancyWaterTech;
79 :
80 : CSimulation2* simulation;
81 : };
82 :
83 :
84 :
85 : ///////////////////////////////////////////////////////////////////
86 : // Construction/Destruction
87 0 : TerrainRenderer::TerrainRenderer()
88 : {
89 0 : m = new TerrainRendererInternals();
90 0 : m->phase = Phase_Submit;
91 0 : }
92 :
93 0 : TerrainRenderer::~TerrainRenderer()
94 : {
95 0 : delete m;
96 0 : }
97 :
98 0 : void TerrainRenderer::SetSimulation(CSimulation2* simulation)
99 : {
100 0 : m->simulation = simulation;
101 0 : }
102 :
103 : ///////////////////////////////////////////////////////////////////
104 : // Submit a patch for rendering
105 0 : void TerrainRenderer::Submit(int cullGroup, CPatch* patch)
106 : {
107 0 : ENSURE(m->phase == Phase_Submit);
108 :
109 0 : CPatchRData* data = (CPatchRData*)patch->GetRenderData();
110 0 : if (data == 0)
111 : {
112 : // no renderdata for patch, create it now
113 0 : data = new CPatchRData(patch, m->simulation);
114 0 : patch->SetRenderData(data);
115 : }
116 0 : data->Update(m->simulation);
117 :
118 0 : m->visiblePatches[cullGroup].push_back(data);
119 0 : }
120 :
121 : ///////////////////////////////////////////////////////////////////
122 : // Submit a decal for rendering
123 0 : void TerrainRenderer::Submit(int cullGroup, CModelDecal* decal)
124 : {
125 0 : ENSURE(m->phase == Phase_Submit);
126 :
127 0 : CDecalRData* data = (CDecalRData*)decal->GetRenderData();
128 0 : if (data == 0)
129 : {
130 : // no renderdata for decal, create it now
131 0 : data = new CDecalRData(decal, m->simulation);
132 0 : decal->SetRenderData(data);
133 : }
134 0 : data->Update(m->simulation);
135 :
136 0 : m->visibleDecals[cullGroup].push_back(data);
137 0 : }
138 :
139 : ///////////////////////////////////////////////////////////////////
140 : // Prepare for rendering
141 0 : void TerrainRenderer::PrepareForRendering()
142 : {
143 0 : ENSURE(m->phase == Phase_Submit);
144 :
145 0 : m->phase = Phase_Render;
146 0 : }
147 :
148 : ///////////////////////////////////////////////////////////////////
149 : // Clear submissions lists
150 0 : void TerrainRenderer::EndFrame()
151 : {
152 0 : ENSURE(m->phase == Phase_Render || m->phase == Phase_Submit);
153 :
154 0 : for (int i = 0; i < CSceneRenderer::CULL_MAX; ++i)
155 : {
156 0 : m->visiblePatches[i].clear();
157 0 : m->visibleDecals[i].clear();
158 : }
159 :
160 0 : m->phase = Phase_Submit;
161 0 : }
162 :
163 0 : void TerrainRenderer::RenderTerrainOverlayTexture(
164 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
165 : int cullGroup, CMatrix3D& textureMatrix,
166 : Renderer::Backend::GL::CTexture* texture)
167 : {
168 : #if CONFIG2_GLES
169 : #warning TODO: implement TerrainRenderer::RenderTerrainOverlayTexture for GLES
170 : UNUSED2(deviceCommandContext);
171 : UNUSED2(cullGroup);
172 : UNUSED2(textureMatrix);
173 : UNUSED2(texture);
174 : #else
175 0 : ENSURE(m->phase == Phase_Render);
176 :
177 0 : std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
178 :
179 0 : CShaderTechniquePtr debugOverlayTech =
180 0 : g_Renderer.GetShaderManager().LoadEffect(str_debug_overlay);
181 0 : debugOverlayTech->BeginPass();
182 0 : deviceCommandContext->SetGraphicsPipelineState(
183 : debugOverlayTech->GetGraphicsPipelineStateDesc());
184 0 : const CShaderProgramPtr& debugOverlayShader = debugOverlayTech->GetShader();
185 :
186 0 : debugOverlayShader->BindTexture(str_baseTex, texture);
187 0 : debugOverlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
188 0 : debugOverlayShader->Uniform(str_textureTransform, textureMatrix);
189 0 : CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, debugOverlayShader, true);
190 :
191 : // To make the overlay visible over water, render an additional map-sized
192 : // water-height patch.
193 0 : CBoundingBoxAligned waterBounds;
194 0 : for (CPatchRData* data : visiblePatches)
195 0 : waterBounds += data->GetWaterBounds();
196 0 : if (!waterBounds.IsEmpty())
197 : {
198 : // Add a delta to avoid z-fighting.
199 0 : const float height = g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight + 0.05f;
200 0 : const float waterPos[] =
201 : {
202 0 : waterBounds[0].X, height, waterBounds[0].Z,
203 0 : waterBounds[1].X, height, waterBounds[0].Z,
204 0 : waterBounds[1].X, height, waterBounds[1].Z,
205 0 : waterBounds[0].X, height, waterBounds[0].Z,
206 0 : waterBounds[1].X, height, waterBounds[1].Z,
207 0 : waterBounds[0].X, height, waterBounds[1].Z
208 0 : };
209 :
210 0 : const GLsizei stride = sizeof(float) * 3;
211 0 : debugOverlayShader->VertexPointer(
212 0 : Renderer::Backend::Format::R32G32B32_SFLOAT, stride, waterPos);
213 0 : debugOverlayShader->TexCoordPointer(
214 0 : GL_TEXTURE0, Renderer::Backend::Format::R32G32B32_SFLOAT, stride, waterPos);
215 0 : debugOverlayShader->AssertPointersBound();
216 :
217 0 : deviceCommandContext->Draw(0, 6);
218 : }
219 :
220 0 : debugOverlayTech->EndPass();
221 : #endif
222 0 : }
223 :
224 :
225 : ///////////////////////////////////////////////////////////////////
226 :
227 : /**
228 : * Set up all the uniforms for a shader pass.
229 : */
230 0 : void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow)
231 : {
232 0 : CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
233 :
234 0 : shader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
235 0 : shader->Uniform(str_cameraPos, sceneRenderer.GetViewCamera().GetOrientation().GetTranslation());
236 :
237 0 : const CLightEnv& lightEnv = sceneRenderer.GetLightEnv();
238 :
239 0 : if (shadow)
240 0 : shadow->BindTo(shader);
241 :
242 0 : CLOSTexture& los = sceneRenderer.GetScene().GetLOSTexture();
243 0 : shader->BindTexture(str_losTex, los.GetTextureSmooth());
244 0 : shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
245 :
246 0 : shader->Uniform(str_ambient, lightEnv.m_AmbientColor);
247 0 : shader->Uniform(str_sunColor, lightEnv.m_SunColor);
248 0 : shader->Uniform(str_sunDir, lightEnv.GetSunDir());
249 :
250 0 : shader->Uniform(str_fogColor, lightEnv.m_FogColor);
251 0 : shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
252 0 : }
253 :
254 0 : void TerrainRenderer::RenderTerrainShader(
255 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
256 : const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
257 : {
258 0 : ENSURE(m->phase == Phase_Render);
259 :
260 0 : std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
261 0 : std::vector<CDecalRData*>& visibleDecals = m->visibleDecals[cullGroup];
262 0 : if (visiblePatches.empty() && visibleDecals.empty())
263 0 : return;
264 :
265 : // render the solid black sides of the map first
266 0 : CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_solid);
267 0 : techSolid->BeginPass();
268 0 : Renderer::Backend::GraphicsPipelineStateDesc solidPipelineStateDesc =
269 0 : techSolid->GetGraphicsPipelineStateDesc();
270 0 : solidPipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
271 0 : deviceCommandContext->SetGraphicsPipelineState(solidPipelineStateDesc);
272 :
273 0 : const CShaderProgramPtr& shaderSolid = techSolid->GetShader();
274 0 : shaderSolid->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
275 0 : shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
276 :
277 0 : CPatchRData::RenderSides(deviceCommandContext, visiblePatches, shaderSolid);
278 :
279 0 : techSolid->EndPass();
280 :
281 0 : CPatchRData::RenderBases(deviceCommandContext, visiblePatches, context, shadow);
282 :
283 : // render blend passes for each patch
284 0 : CPatchRData::RenderBlends(deviceCommandContext, visiblePatches, context, shadow);
285 :
286 0 : CDecalRData::RenderDecals(deviceCommandContext, visibleDecals, context, shadow);
287 :
288 : // restore OpenGL state
289 0 : deviceCommandContext->BindTexture(3, GL_TEXTURE_2D, 0);
290 0 : deviceCommandContext->BindTexture(2, GL_TEXTURE_2D, 0);
291 0 : deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0);
292 : }
293 :
294 :
295 : ///////////////////////////////////////////////////////////////////
296 : // Render un-textured patches as polygons
297 0 : void TerrainRenderer::RenderPatches(
298 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
299 : int cullGroup, const CShaderDefines& defines, const CColor& color)
300 : {
301 0 : ENSURE(m->phase == Phase_Render);
302 :
303 0 : std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
304 0 : if (visiblePatches.empty())
305 : return;
306 :
307 0 : GPU_SCOPED_LABEL(deviceCommandContext, "Render terrain patches");
308 :
309 : #if CONFIG2_GLES
310 : UNUSED2(deviceCommandContext);
311 : UNUSED2(defines);
312 : UNUSED2(color);
313 : #warning TODO: implement TerrainRenderer::RenderPatches for GLES
314 : #else
315 :
316 0 : CShaderTechniquePtr solidTech = g_Renderer.GetShaderManager().LoadEffect(str_terrain_solid, defines);
317 0 : solidTech->BeginPass();
318 0 : deviceCommandContext->SetGraphicsPipelineState(
319 : solidTech->GetGraphicsPipelineStateDesc());
320 :
321 0 : const CShaderProgramPtr& solidShader = solidTech->GetShader();
322 0 : solidShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
323 0 : solidShader->Uniform(str_color, color);
324 :
325 0 : CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, solidShader, false);
326 0 : solidTech->EndPass();
327 : #endif
328 : }
329 :
330 :
331 : ///////////////////////////////////////////////////////////////////
332 : // Render outlines of submitted patches as lines
333 0 : void TerrainRenderer::RenderOutlines(
334 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
335 : int cullGroup)
336 : {
337 0 : ENSURE(m->phase == Phase_Render);
338 :
339 0 : std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
340 0 : if (visiblePatches.empty())
341 : return;
342 :
343 0 : GPU_SCOPED_LABEL(deviceCommandContext, "Render terrain outlines");
344 :
345 0 : for (size_t i = 0; i < visiblePatches.size(); ++i)
346 0 : visiblePatches[i]->RenderOutline();
347 : }
348 :
349 :
350 : ///////////////////////////////////////////////////////////////////
351 : // Scissor rectangle of water patches
352 0 : CBoundingBoxAligned TerrainRenderer::ScissorWater(int cullGroup, const CCamera& camera)
353 : {
354 0 : CBoundingBoxAligned scissor;
355 0 : for (const CPatchRData* data : m->visiblePatches[cullGroup])
356 : {
357 0 : const CBoundingBoxAligned& waterBounds = data->GetWaterBounds();
358 0 : if (waterBounds.IsEmpty())
359 0 : continue;
360 :
361 0 : const CBoundingBoxAligned waterBoundsInViewPort =
362 0 : camera.GetBoundsInViewPort(waterBounds);
363 0 : if (!waterBoundsInViewPort.IsEmpty())
364 0 : scissor += waterBoundsInViewPort;
365 : }
366 0 : return CBoundingBoxAligned(
367 0 : CVector3D(Clamp(scissor[0].X, -1.0f, 1.0f), Clamp(scissor[0].Y, -1.0f, 1.0f), -1.0f),
368 0 : CVector3D(Clamp(scissor[1].X, -1.0f, 1.0f), Clamp(scissor[1].Y, -1.0f, 1.0f), 1.0f));
369 : }
370 :
371 : // Render fancy water
372 0 : bool TerrainRenderer::RenderFancyWater(
373 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
374 : const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
375 : {
376 0 : PROFILE3_GPU("fancy water");
377 0 : GPU_SCOPED_LABEL(deviceCommandContext, "Render fancy water");
378 :
379 0 : CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
380 :
381 0 : WaterManager& waterManager = sceneRenderer.GetWaterManager();
382 0 : CShaderDefines defines = context;
383 :
384 : // If we're using fancy water, make sure its shader is loaded
385 0 : if (!m->fancyWaterTech || waterManager.m_NeedsReloading)
386 : {
387 0 : if (waterManager.m_WaterRealDepth)
388 0 : defines.Add(str_USE_REAL_DEPTH, str_1);
389 0 : if (waterManager.m_WaterFancyEffects)
390 0 : defines.Add(str_USE_FANCY_EFFECTS, str_1);
391 0 : if (waterManager.m_WaterRefraction)
392 0 : defines.Add(str_USE_REFRACTION, str_1);
393 0 : if (waterManager.m_WaterReflection)
394 0 : defines.Add(str_USE_REFLECTION, str_1);
395 :
396 0 : m->fancyWaterTech = g_Renderer.GetShaderManager().LoadEffect(str_water_high, defines);
397 :
398 0 : if (!m->fancyWaterTech)
399 : {
400 0 : LOGERROR("Failed to load water shader. Falling back to a simple water.\n");
401 0 : waterManager.m_RenderWater = false;
402 0 : return false;
403 : }
404 0 : waterManager.m_NeedsReloading = false;
405 : }
406 :
407 0 : CLOSTexture& losTexture = sceneRenderer.GetScene().GetLOSTexture();
408 :
409 : // Calculating the advanced informations about Foam and all if the quality calls for it.
410 : /*if (WaterMgr->m_NeedInfoUpdate && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves))
411 : {
412 : WaterMgr->m_NeedInfoUpdate = false;
413 : WaterMgr->CreateSuperfancyInfo();
414 : }*/
415 :
416 0 : const double time = waterManager.m_WaterTexTimer;
417 0 : const float repeatPeriod = waterManager.m_RepeatPeriod;
418 :
419 0 : m->fancyWaterTech->BeginPass();
420 0 : deviceCommandContext->SetGraphicsPipelineState(
421 0 : m->fancyWaterTech->GetGraphicsPipelineStateDesc());
422 0 : const CShaderProgramPtr& fancyWaterShader = m->fancyWaterTech->GetShader();
423 :
424 0 : const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
425 :
426 0 : const double period = 8.0;
427 : // TODO: move uploading to a prepare function during loading.
428 0 : const CTexturePtr& currentNormalTexture = waterManager.m_NormalMap[waterManager.GetCurrentTextureIndex(period)];
429 0 : const CTexturePtr& nextNormalTexture = waterManager.m_NormalMap[waterManager.GetNextTextureIndex(period)];
430 0 : currentNormalTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
431 0 : nextNormalTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
432 0 : fancyWaterShader->BindTexture(str_normalMap, currentNormalTexture->GetBackendTexture());
433 0 : fancyWaterShader->BindTexture(str_normalMap2, nextNormalTexture->GetBackendTexture());
434 :
435 0 : if (waterManager.m_WaterFancyEffects)
436 : {
437 0 : fancyWaterShader->BindTexture(str_waterEffectsTex, waterManager.m_FancyTexture.get());
438 : }
439 :
440 0 : if (waterManager.m_WaterRefraction && waterManager.m_WaterRealDepth)
441 : {
442 0 : fancyWaterShader->BindTexture(str_depthTex, waterManager.m_RefrFboDepthTexture.get());
443 0 : fancyWaterShader->Uniform(str_projInvTransform, waterManager.m_RefractionProjInvMatrix);
444 0 : fancyWaterShader->Uniform(str_viewInvTransform, waterManager.m_RefractionViewInvMatrix);
445 : }
446 :
447 0 : if (waterManager.m_WaterRefraction)
448 0 : fancyWaterShader->BindTexture(str_refractionMap, waterManager.m_RefractionTexture.get());
449 0 : if (waterManager.m_WaterReflection)
450 0 : fancyWaterShader->BindTexture(str_reflectionMap, waterManager.m_ReflectionTexture.get());
451 0 : fancyWaterShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
452 :
453 0 : const CLightEnv& lightEnv = sceneRenderer.GetLightEnv();
454 :
455 0 : fancyWaterShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
456 :
457 0 : fancyWaterShader->BindTexture(str_skyCube, sceneRenderer.GetSkyManager().GetSkyCube());
458 : // TODO: check that this rotates in the right direction.
459 0 : CMatrix3D skyBoxRotation;
460 0 : skyBoxRotation.SetIdentity();
461 0 : skyBoxRotation.RotateY(M_PI + lightEnv.GetRotation());
462 0 : fancyWaterShader->Uniform(str_skyBoxRot, skyBoxRotation);
463 :
464 0 : if (waterManager.m_WaterRefraction)
465 0 : fancyWaterShader->Uniform(str_refractionMatrix, waterManager.m_RefractionMatrix);
466 0 : if (waterManager.m_WaterReflection)
467 0 : fancyWaterShader->Uniform(str_reflectionMatrix, waterManager.m_ReflectionMatrix);
468 :
469 0 : fancyWaterShader->Uniform(str_ambient, lightEnv.m_AmbientColor);
470 0 : fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir());
471 0 : fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor);
472 0 : fancyWaterShader->Uniform(str_color, waterManager.m_WaterColor);
473 0 : fancyWaterShader->Uniform(str_tint, waterManager.m_WaterTint);
474 0 : fancyWaterShader->Uniform(str_waviness, waterManager.m_Waviness);
475 0 : fancyWaterShader->Uniform(str_murkiness, waterManager.m_Murkiness);
476 0 : fancyWaterShader->Uniform(str_windAngle, waterManager.m_WindAngle);
477 0 : fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod);
478 0 : fancyWaterShader->Uniform(str_losTransform, losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12], 0.f, 0.f);
479 :
480 0 : fancyWaterShader->Uniform(str_cameraPos, camera.GetOrientation().GetTranslation());
481 :
482 0 : fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor);
483 0 : fancyWaterShader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
484 0 : fancyWaterShader->Uniform(str_time, (float)time);
485 0 : fancyWaterShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f);
486 :
487 0 : if (waterManager.m_WaterType == L"clap")
488 : {
489 0 : fancyWaterShader->Uniform(str_waveParams1, 30.0f,1.5f,20.0f,0.03f);
490 0 : fancyWaterShader->Uniform(str_waveParams2, 0.5f,0.0f,0.0f,0.0f);
491 : }
492 0 : else if (waterManager.m_WaterType == L"lake")
493 : {
494 0 : fancyWaterShader->Uniform(str_waveParams1, 8.5f,1.5f,15.0f,0.03f);
495 0 : fancyWaterShader->Uniform(str_waveParams2, 0.2f,0.0f,0.0f,0.07f);
496 : }
497 : else
498 : {
499 0 : fancyWaterShader->Uniform(str_waveParams1, 15.0f,0.8f,10.0f,0.1f);
500 0 : fancyWaterShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.3f);
501 : }
502 :
503 0 : if (shadow)
504 0 : shadow->BindTo(fancyWaterShader);
505 :
506 0 : for (CPatchRData* data : m->visiblePatches[cullGroup])
507 : {
508 0 : data->RenderWaterSurface(deviceCommandContext, fancyWaterShader, true);
509 0 : if (waterManager.m_WaterFancyEffects)
510 0 : data->RenderWaterShore(deviceCommandContext, fancyWaterShader);
511 : }
512 0 : m->fancyWaterTech->EndPass();
513 :
514 : return true;
515 : }
516 :
517 0 : void TerrainRenderer::RenderSimpleWater(
518 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
519 : int cullGroup)
520 : {
521 : #if CONFIG2_GLES
522 : UNUSED2(deviceCommandContext);
523 : UNUSED2(cullGroup);
524 : #else
525 0 : PROFILE3_GPU("simple water");
526 0 : GPU_SCOPED_LABEL(deviceCommandContext, "Render Simple Water");
527 :
528 0 : const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();
529 0 : CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
530 :
531 0 : const double time = waterManager.m_WaterTexTimer;
532 :
533 0 : CShaderDefines context;
534 0 : if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME)
535 0 : context.Add(str_MODE_WIREFRAME, str_1);
536 :
537 0 : CShaderTechniquePtr waterSimpleTech =
538 0 : g_Renderer.GetShaderManager().LoadEffect(str_water_simple, context);
539 0 : waterSimpleTech->BeginPass();
540 0 : deviceCommandContext->SetGraphicsPipelineState(
541 : waterSimpleTech->GetGraphicsPipelineStateDesc());
542 0 : const CShaderProgramPtr& waterSimpleShader = waterSimpleTech->GetShader();
543 :
544 0 : const CTexturePtr& waterTexture = waterManager.m_WaterTexture[waterManager.GetCurrentTextureIndex(1.6)];
545 0 : waterTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
546 0 : waterSimpleShader->BindTexture(str_baseTex, waterTexture->GetBackendTexture());
547 0 : waterSimpleShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
548 0 : waterSimpleShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
549 0 : waterSimpleShader->Uniform(str_losTransform, losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12], 0.f, 0.f);
550 0 : waterSimpleShader->Uniform(str_time, static_cast<float>(time));
551 0 : waterSimpleShader->Uniform(str_color, waterManager.m_WaterColor);
552 :
553 0 : std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
554 0 : for (size_t i = 0; i < visiblePatches.size(); ++i)
555 : {
556 0 : CPatchRData* data = visiblePatches[i];
557 0 : data->RenderWaterSurface(deviceCommandContext, waterSimpleShader, false);
558 : }
559 :
560 0 : deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0);
561 :
562 0 : waterSimpleTech->EndPass();
563 : #endif
564 0 : }
565 :
566 : ///////////////////////////////////////////////////////////////////
567 : // Render water that is part of the terrain
568 0 : void TerrainRenderer::RenderWater(
569 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
570 : const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
571 : {
572 0 : const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();
573 :
574 0 : if (!waterManager.WillRenderFancyWater())
575 0 : RenderSimpleWater(deviceCommandContext, cullGroup);
576 : else
577 0 : RenderFancyWater(deviceCommandContext, context, cullGroup, shadow);
578 0 : }
579 :
580 0 : void TerrainRenderer::RenderWaterFoamOccluders(
581 : Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
582 : int cullGroup)
583 : {
584 0 : CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
585 0 : const WaterManager& waterManager = sceneRenderer.GetWaterManager();
586 0 : if (!waterManager.WillRenderFancyWater())
587 0 : return;
588 :
589 0 : GPU_SCOPED_LABEL(deviceCommandContext, "Render water foam occluders");
590 :
591 : // Render normals and foam to a framebuffer if we're using fancy effects.
592 0 : deviceCommandContext->SetFramebuffer(waterManager.m_FancyEffectsFramebuffer.get());
593 :
594 : // Overwrite waves that would be behind the ground.
595 0 : CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
596 0 : dummyTech->BeginPass();
597 0 : Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
598 0 : dummyTech->GetGraphicsPipelineStateDesc();
599 0 : pipelineStateDesc.depthStencilState.depthTestEnabled = true;
600 0 : pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
601 0 : deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
602 0 : const CShaderProgramPtr& dummyShader = dummyTech->GetShader();
603 :
604 0 : dummyShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
605 0 : dummyShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.0f);
606 0 : for (CPatchRData* data : m->visiblePatches[cullGroup])
607 0 : data->RenderWaterShore(deviceCommandContext, dummyShader);
608 0 : dummyTech->EndPass();
609 :
610 0 : deviceCommandContext->SetFramebuffer(
611 : deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
612 : }
613 :
614 0 : void TerrainRenderer::RenderPriorities(CCanvas2D& canvas, int cullGroup)
615 : {
616 0 : PROFILE("priorities");
617 :
618 0 : ENSURE(m->phase == Phase_Render);
619 :
620 0 : CTextRenderer textRenderer;
621 0 : textRenderer.SetCurrentFont(CStrIntern("mono-stroke-10"));
622 0 : textRenderer.SetCurrentColor(CColor(1.0f, 1.0f, 0.0f, 1.0f));
623 :
624 0 : std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
625 0 : for (size_t i = 0; i < visiblePatches.size(); ++i)
626 0 : visiblePatches[i]->RenderPriorities(textRenderer);
627 :
628 0 : canvas.DrawText(textRenderer);
629 0 : }
|