2021-01-13 00:18:29 +01:00
|
|
|
/* Copyright (C) 2021 Wildfire Games.
|
2009-04-18 19:00:33 +02:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. 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 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2009-04-18 19:51:05 +02:00
|
|
|
/*
|
|
|
|
* Terrain rendering (everything related to patches and water) is
|
|
|
|
* encapsulated in TerrainRenderer
|
2006-01-07 02:04:26 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precompiled.h"
|
|
|
|
|
|
|
|
#include "graphics/Camera.h"
|
2011-03-13 20:22:05 +01:00
|
|
|
#include "graphics/Decal.h"
|
2006-02-13 15:18:20 +01:00
|
|
|
#include "graphics/LightEnv.h"
|
2011-02-03 02:12:24 +01:00
|
|
|
#include "graphics/LOSTexture.h"
|
2006-01-07 02:04:26 +01:00
|
|
|
#include "graphics/Patch.h"
|
2006-03-21 21:55:45 +01:00
|
|
|
#include "graphics/GameView.h"
|
2011-03-13 20:22:05 +01:00
|
|
|
#include "graphics/Model.h"
|
2011-03-26 21:17:21 +01:00
|
|
|
#include "graphics/ShaderManager.h"
|
2012-10-31 19:42:17 +01:00
|
|
|
#include "renderer/ShadowMap.h"
|
2013-08-24 16:44:38 +02:00
|
|
|
#include "renderer/SkyManager.h"
|
2011-07-20 21:48:06 +02:00
|
|
|
#include "graphics/TerritoryTexture.h"
|
2012-02-12 21:45:31 +01:00
|
|
|
#include "graphics/TextRenderer.h"
|
2006-01-07 02:04:26 +01:00
|
|
|
|
|
|
|
#include "maths/MathUtil.h"
|
|
|
|
|
2010-07-04 12:15:53 +02:00
|
|
|
#include "ps/Filesystem.h"
|
2009-03-24 22:00:41 +01:00
|
|
|
#include "ps/CLogger.h"
|
2006-01-07 02:04:26 +01:00
|
|
|
#include "ps/Game.h"
|
|
|
|
#include "ps/Profile.h"
|
2007-01-13 23:44:42 +01:00
|
|
|
#include "ps/World.h"
|
2006-01-07 02:04:26 +01:00
|
|
|
|
2011-03-13 20:22:05 +01:00
|
|
|
#include "renderer/DecalRData.h"
|
2006-01-07 02:04:26 +01:00
|
|
|
#include "renderer/PatchRData.h"
|
|
|
|
#include "renderer/Renderer.h"
|
2019-08-04 10:28:30 +02:00
|
|
|
#include "renderer/RenderingOptions.h"
|
2006-02-11 19:04:32 +01:00
|
|
|
#include "renderer/ShadowMap.h"
|
2006-01-07 02:04:26 +01:00
|
|
|
#include "renderer/TerrainRenderer.h"
|
2011-03-13 20:22:05 +01:00
|
|
|
#include "renderer/VertexArray.h"
|
2006-01-07 02:04:26 +01:00
|
|
|
#include "renderer/WaterManager.h"
|
|
|
|
|
2012-10-31 19:42:17 +01:00
|
|
|
#include "tools/atlas/GameInterface/GameLoop.h"
|
|
|
|
|
|
|
|
extern GameLoopState* g_AtlasGameLoop;
|
2006-01-07 02:04:26 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// TerrainRenderer implementation
|
|
|
|
|
2020-11-03 19:59:27 +01:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
CShaderProgramPtr GetDummyShader()
|
|
|
|
{
|
|
|
|
const char* shaderName;
|
|
|
|
if (g_RenderingOptions.GetRenderPath() == RenderPath::SHADER)
|
|
|
|
{
|
|
|
|
if (g_RenderingOptions.GetPreferGLSL())
|
|
|
|
shaderName = "glsl/dummy";
|
|
|
|
else
|
|
|
|
shaderName = "arb/dummy";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
shaderName = "fixed:dummy";
|
|
|
|
return g_Renderer.GetShaderManager().LoadProgram(shaderName, CShaderDefines());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // anonymous namespace
|
2006-01-07 02:04:26 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* TerrainRenderer keeps track of which phase it is in, to detect
|
|
|
|
* when Submit, PrepareForRendering etc. are called in the wrong order.
|
|
|
|
*/
|
|
|
|
enum Phase {
|
|
|
|
Phase_Submit,
|
|
|
|
Phase_Render
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Struct TerrainRendererInternals: Internal variables used by the TerrainRenderer class.
|
|
|
|
*/
|
|
|
|
struct TerrainRendererInternals
|
|
|
|
{
|
|
|
|
/// Which phase (submitting or rendering patches) are we in right now?
|
|
|
|
Phase phase;
|
|
|
|
|
2011-03-13 20:22:05 +01:00
|
|
|
/// Patches that were submitted for this frame
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*> visiblePatches[CRenderer::CULL_MAX];
|
2011-03-13 20:22:05 +01:00
|
|
|
|
|
|
|
/// Decals that were submitted for this frame
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CDecalRData*> visibleDecals[CRenderer::CULL_MAX];
|
2006-05-25 07:46:17 +02:00
|
|
|
|
|
|
|
/// Fancy water shader
|
2012-01-29 13:04:39 +01:00
|
|
|
CShaderProgramPtr fancyWaterShader;
|
2012-09-28 20:20:36 +02:00
|
|
|
|
|
|
|
CSimulation2* simulation;
|
2006-01-07 02:04:26 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Construction/Destruction
|
|
|
|
TerrainRenderer::TerrainRenderer()
|
|
|
|
{
|
|
|
|
m = new TerrainRendererInternals();
|
|
|
|
m->phase = Phase_Submit;
|
|
|
|
}
|
|
|
|
|
|
|
|
TerrainRenderer::~TerrainRenderer()
|
|
|
|
{
|
|
|
|
delete m;
|
|
|
|
}
|
|
|
|
|
2012-09-28 20:20:36 +02:00
|
|
|
void TerrainRenderer::SetSimulation(CSimulation2* simulation)
|
|
|
|
{
|
|
|
|
m->simulation = simulation;
|
|
|
|
}
|
2006-01-07 02:04:26 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Submit a patch for rendering
|
2014-06-25 03:11:10 +02:00
|
|
|
void TerrainRenderer::Submit(int cullGroup, CPatch* patch)
|
2006-01-07 02:04:26 +01:00
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Submit);
|
2006-01-07 02:04:26 +01:00
|
|
|
|
2011-03-13 20:22:05 +01:00
|
|
|
CPatchRData* data = (CPatchRData*)patch->GetRenderData();
|
2006-01-07 02:04:26 +01:00
|
|
|
if (data == 0)
|
|
|
|
{
|
|
|
|
// no renderdata for patch, create it now
|
2012-09-28 20:20:36 +02:00
|
|
|
data = new CPatchRData(patch, m->simulation);
|
2006-01-07 02:04:26 +01:00
|
|
|
patch->SetRenderData(data);
|
|
|
|
}
|
2012-09-28 20:20:36 +02:00
|
|
|
data->Update(m->simulation);
|
2006-01-07 02:04:26 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
m->visiblePatches[cullGroup].push_back(data);
|
2006-01-07 02:04:26 +01:00
|
|
|
}
|
|
|
|
|
2011-03-13 20:22:05 +01:00
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Submit a decal for rendering
|
2014-06-25 03:11:10 +02:00
|
|
|
void TerrainRenderer::Submit(int cullGroup, CModelDecal* decal)
|
2011-03-13 20:22:05 +01:00
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Submit);
|
2011-03-13 20:22:05 +01:00
|
|
|
|
|
|
|
CDecalRData* data = (CDecalRData*)decal->GetRenderData();
|
|
|
|
if (data == 0)
|
|
|
|
{
|
|
|
|
// no renderdata for decal, create it now
|
2012-09-28 20:20:36 +02:00
|
|
|
data = new CDecalRData(decal, m->simulation);
|
2011-03-13 20:22:05 +01:00
|
|
|
decal->SetRenderData(data);
|
|
|
|
}
|
2012-09-28 20:20:36 +02:00
|
|
|
data->Update(m->simulation);
|
2011-03-13 20:22:05 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
m->visibleDecals[cullGroup].push_back(data);
|
2011-03-13 20:22:05 +01:00
|
|
|
}
|
2006-01-07 02:04:26 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Prepare for rendering
|
|
|
|
void TerrainRenderer::PrepareForRendering()
|
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Submit);
|
2006-01-07 02:04:26 +01:00
|
|
|
|
|
|
|
m->phase = Phase_Render;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Clear submissions lists
|
|
|
|
void TerrainRenderer::EndFrame()
|
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Render || m->phase == Phase_Submit);
|
2006-01-07 02:04:26 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
for (int i = 0; i < CRenderer::CULL_MAX; ++i)
|
2011-07-13 01:48:05 +02:00
|
|
|
{
|
2014-06-25 03:11:10 +02:00
|
|
|
m->visiblePatches[i].clear();
|
|
|
|
m->visibleDecals[i].clear();
|
2011-07-13 01:48:05 +02:00
|
|
|
}
|
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
m->phase = Phase_Submit;
|
2011-07-13 01:48:05 +02:00
|
|
|
}
|
|
|
|
|
2020-11-09 19:50:40 +01:00
|
|
|
void TerrainRenderer::RenderTerrainOverlayTexture(int cullGroup, CMatrix3D& textureMatrix, GLuint texture)
|
2012-04-24 18:46:32 +02:00
|
|
|
{
|
|
|
|
#if CONFIG2_GLES
|
|
|
|
#warning TODO: implement TerrainRenderer::RenderTerrainOverlayTexture for GLES
|
2014-06-25 03:11:10 +02:00
|
|
|
UNUSED2(cullGroup);
|
2012-04-24 18:46:32 +02:00
|
|
|
UNUSED2(textureMatrix);
|
2020-11-09 19:50:40 +01:00
|
|
|
UNUSED2(texture);
|
2012-04-24 18:46:32 +02:00
|
|
|
#else
|
|
|
|
ENSURE(m->phase == Phase_Render);
|
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
2012-04-24 18:46:32 +02:00
|
|
|
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glDepthMask(0);
|
New long-range pathfinder.
Based on Philip's work located at
http://git.wildfiregames.com/gitweb/?p=0ad.git;a=shortlog;h=refs/heads/projects/philip/pathfinder
Includes code by wraitii, sanderd17 and kanetaka.
An updated version of docs/pathfinder.pdf describing the changes in
detail will be committed ASAP.
Running update-workspaces is needed after this change.
Fixes #1756.
Fixes #930, #1259, #2908, #2960, #3097
Refs #1200, #1914, #1942, #2568, #2132, #2563
This was SVN commit r16751.
2015-06-12 20:58:24 +02:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
2012-04-24 18:46:32 +02:00
|
|
|
|
2020-11-09 19:50:40 +01:00
|
|
|
CShaderTechniquePtr debugOverlayTech =
|
|
|
|
g_Renderer.GetShaderManager().LoadEffect(str_debug_overlay);
|
|
|
|
debugOverlayTech->BeginPass();
|
|
|
|
CShaderProgramPtr debugOverlayShader = debugOverlayTech->GetShader();
|
2012-04-24 18:46:32 +02:00
|
|
|
|
2020-11-09 19:50:40 +01:00
|
|
|
debugOverlayShader->Bind();
|
|
|
|
debugOverlayShader->BindTexture(str_baseTex, texture);
|
|
|
|
debugOverlayShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
|
|
|
debugOverlayShader->Uniform(str_textureTransform, textureMatrix);
|
|
|
|
CPatchRData::RenderStreams(visiblePatches, debugOverlayShader, STREAM_POS | STREAM_POSTOUV0);
|
2012-04-24 18:46:32 +02:00
|
|
|
|
2020-11-09 19:50:40 +01:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
2012-04-24 18:46:32 +02:00
|
|
|
|
|
|
|
// To make the overlay visible over water, render an additional map-sized
|
2020-11-09 19:50:40 +01:00
|
|
|
// water-height patch.
|
2012-04-24 18:46:32 +02:00
|
|
|
CBoundingBoxAligned waterBounds;
|
2020-11-09 19:50:40 +01:00
|
|
|
for (CPatchRData* data : visiblePatches)
|
2012-04-24 18:46:32 +02:00
|
|
|
waterBounds += data->GetWaterBounds();
|
|
|
|
if (!waterBounds.IsEmpty())
|
|
|
|
{
|
2020-11-09 19:50:40 +01:00
|
|
|
// Add a delta to avoid z-fighting.
|
|
|
|
const float height = g_Renderer.GetWaterManager()->m_WaterHeight + 0.05f;
|
|
|
|
const float waterPos[] = {
|
|
|
|
waterBounds[0].X, height, waterBounds[0].Z,
|
|
|
|
waterBounds[1].X, height, waterBounds[0].Z,
|
|
|
|
waterBounds[0].X, height, waterBounds[1].Z,
|
|
|
|
waterBounds[1].X, height, waterBounds[1].Z
|
2012-04-24 18:46:32 +02:00
|
|
|
};
|
2020-11-09 19:50:40 +01:00
|
|
|
|
|
|
|
const GLsizei stride = sizeof(float) * 3;
|
|
|
|
debugOverlayShader->VertexPointer(3, GL_FLOAT, stride, waterPos);
|
|
|
|
debugOverlayShader->TexCoordPointer(GL_TEXTURE0, 3, GL_FLOAT, stride, waterPos);
|
|
|
|
debugOverlayShader->AssertPointersBound();
|
|
|
|
|
2012-04-24 18:46:32 +02:00
|
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
}
|
|
|
|
|
2020-11-09 19:50:40 +01:00
|
|
|
debugOverlayShader->Unbind();
|
|
|
|
debugOverlayTech->EndPass();
|
2012-04-24 18:46:32 +02:00
|
|
|
|
|
|
|
glDepthMask(1);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-26 21:17:21 +01:00
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set up all the uniforms for a shader pass.
|
|
|
|
*/
|
|
|
|
void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow)
|
|
|
|
{
|
2013-09-29 15:19:52 +02:00
|
|
|
shader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
|
|
|
shader->Uniform(str_cameraPos, g_Renderer.GetViewCamera().GetOrientation().GetTranslation());
|
2012-02-13 15:02:14 +01:00
|
|
|
|
2011-03-26 21:17:21 +01:00
|
|
|
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
|
|
|
|
|
|
|
if (shadow)
|
|
|
|
{
|
2013-09-29 15:19:52 +02:00
|
|
|
shader->BindTexture(str_shadowTex, shadow->GetTexture());
|
|
|
|
shader->Uniform(str_shadowTransform, shadow->GetTextureMatrix());
|
2012-05-21 21:23:14 +02:00
|
|
|
int width = shadow->GetWidth();
|
|
|
|
int height = shadow->GetHeight();
|
2013-09-29 15:19:52 +02:00
|
|
|
shader->Uniform(str_shadowScale, width, height, 1.0f / width, 1.0f / height);
|
2011-03-26 21:17:21 +01:00
|
|
|
}
|
|
|
|
|
2011-04-05 22:32:03 +02:00
|
|
|
CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture();
|
2013-09-29 15:19:52 +02:00
|
|
|
shader->BindTexture(str_losTex, los.GetTextureSmooth());
|
|
|
|
shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
|
2011-03-26 21:17:21 +01:00
|
|
|
|
2013-09-29 15:19:52 +02:00
|
|
|
shader->Uniform(str_ambient, lightEnv.m_TerrainAmbientColor);
|
|
|
|
shader->Uniform(str_sunColor, lightEnv.m_SunColor);
|
|
|
|
shader->Uniform(str_sunDir, lightEnv.GetSunDir());
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2013-09-29 15:19:52 +02:00
|
|
|
shader->Uniform(str_fogColor, lightEnv.m_FogColor);
|
|
|
|
shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
|
2011-03-26 21:17:21 +01:00
|
|
|
}
|
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
2011-03-26 21:17:21 +01:00
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Render);
|
2011-03-26 21:17:21 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
|
|
|
std::vector<CDecalRData*>& visibleDecals = m->visibleDecals[cullGroup];
|
2011-07-13 01:48:05 +02:00
|
|
|
if (visiblePatches.empty() && visibleDecals.empty())
|
|
|
|
return;
|
|
|
|
|
2011-03-26 21:17:21 +01:00
|
|
|
// render the solid black sides of the map first
|
2013-09-29 15:19:52 +02:00
|
|
|
CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid);
|
2012-02-13 15:02:14 +01:00
|
|
|
techSolid->BeginPass();
|
|
|
|
CShaderProgramPtr shaderSolid = techSolid->GetShader();
|
2013-09-29 15:19:52 +02:00
|
|
|
shaderSolid->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
|
|
|
shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
2012-02-13 15:02:14 +01:00
|
|
|
|
2011-03-26 21:17:21 +01:00
|
|
|
PROFILE_START("render terrain sides");
|
2011-07-13 01:48:05 +02:00
|
|
|
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
2012-02-13 15:02:14 +01:00
|
|
|
visiblePatches[i]->RenderSides(shaderSolid);
|
2011-03-26 21:17:21 +01:00
|
|
|
PROFILE_END("render terrain sides");
|
|
|
|
|
2012-02-13 15:02:14 +01:00
|
|
|
techSolid->EndPass();
|
2011-03-26 21:17:21 +01:00
|
|
|
|
|
|
|
PROFILE_START("render terrain base");
|
2012-08-07 20:21:16 +02:00
|
|
|
CPatchRData::RenderBases(visiblePatches, context, shadow);
|
2011-03-26 21:17:21 +01:00
|
|
|
PROFILE_END("render terrain base");
|
|
|
|
|
|
|
|
// no need to write to the depth buffer a second time
|
|
|
|
glDepthMask(0);
|
|
|
|
|
|
|
|
// render blend passes for each patch
|
|
|
|
PROFILE_START("render terrain blends");
|
2012-08-07 20:21:16 +02:00
|
|
|
CPatchRData::RenderBlends(visiblePatches, context, shadow, false);
|
2011-03-26 21:17:21 +01:00
|
|
|
PROFILE_END("render terrain blends");
|
|
|
|
|
|
|
|
PROFILE_START("render terrain decals");
|
2012-08-07 20:21:16 +02:00
|
|
|
CDecalRData::RenderDecals(visibleDecals, context, shadow, false);
|
2011-03-26 21:17:21 +01:00
|
|
|
PROFILE_END("render terrain decals");
|
|
|
|
|
|
|
|
// restore OpenGL state
|
|
|
|
g_Renderer.BindTexture(1, 0);
|
|
|
|
g_Renderer.BindTexture(2, 0);
|
|
|
|
g_Renderer.BindTexture(3, 0);
|
|
|
|
|
|
|
|
glDepthMask(1);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2006-02-13 15:18:20 +01:00
|
|
|
glDisable(GL_BLEND);
|
2006-01-07 02:04:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Render un-textured patches as polygons
|
2020-11-04 16:52:26 +01:00
|
|
|
void TerrainRenderer::RenderPatches(int cullGroup, const CColor& color)
|
2006-01-07 02:04:26 +01:00
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Render);
|
2006-01-07 02:04:26 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
2011-07-13 01:48:05 +02:00
|
|
|
if (visiblePatches.empty())
|
|
|
|
return;
|
|
|
|
|
2012-02-13 15:02:14 +01:00
|
|
|
#if CONFIG2_GLES
|
|
|
|
#warning TODO: implement TerrainRenderer::RenderPatches for GLES
|
|
|
|
#else
|
2020-11-03 19:59:27 +01:00
|
|
|
CShaderProgramPtr dummyShader = GetDummyShader();
|
2012-02-13 15:02:14 +01:00
|
|
|
dummyShader->Bind();
|
2020-11-04 16:52:26 +01:00
|
|
|
dummyShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
|
|
|
dummyShader->Uniform(str_color, color);
|
2012-02-13 15:02:14 +01:00
|
|
|
|
2006-01-07 02:04:26 +01:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
2012-02-13 15:02:14 +01:00
|
|
|
CPatchRData::RenderStreams(visiblePatches, dummyShader, STREAM_POS);
|
2006-01-07 02:04:26 +01:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2012-02-13 15:02:14 +01:00
|
|
|
|
|
|
|
dummyShader->Unbind();
|
|
|
|
#endif
|
2006-01-07 02:04:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Render outlines of submitted patches as lines
|
2014-06-25 03:11:10 +02:00
|
|
|
void TerrainRenderer::RenderOutlines(int cullGroup)
|
2006-01-07 02:04:26 +01:00
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Render);
|
2011-01-30 03:14:44 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
2011-07-13 01:48:05 +02:00
|
|
|
if (visiblePatches.empty())
|
|
|
|
return;
|
|
|
|
|
2012-02-13 15:02:14 +01:00
|
|
|
#if CONFIG2_GLES
|
|
|
|
#warning TODO: implement TerrainRenderer::RenderOutlines for GLES
|
|
|
|
#else
|
2006-01-07 02:04:26 +01:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
2011-07-13 01:48:05 +02:00
|
|
|
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
|
|
|
visiblePatches[i]->RenderOutline();
|
2006-01-07 02:04:26 +01:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2012-02-13 15:02:14 +01:00
|
|
|
#endif
|
2006-01-07 02:04:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
2011-07-13 01:48:05 +02:00
|
|
|
// Scissor rectangle of water patches
|
2014-06-25 03:11:10 +02:00
|
|
|
CBoundingBoxAligned TerrainRenderer::ScissorWater(int cullGroup, const CMatrix3D &viewproj)
|
2006-01-07 02:04:26 +01:00
|
|
|
{
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
|
|
|
|
2011-11-25 07:36:13 +01:00
|
|
|
CBoundingBoxAligned scissor;
|
2014-06-25 03:11:10 +02:00
|
|
|
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
2011-07-13 01:48:05 +02:00
|
|
|
{
|
2014-06-25 03:11:10 +02:00
|
|
|
CPatchRData* data = visiblePatches[i];
|
2011-11-25 07:36:13 +01:00
|
|
|
const CBoundingBoxAligned& waterBounds = data->GetWaterBounds();
|
2011-07-13 01:48:05 +02:00
|
|
|
if (waterBounds.IsEmpty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CVector4D v1 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
|
|
|
|
CVector4D v2 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[0].Z, 1.0f));
|
|
|
|
CVector4D v3 = viewproj.Transform(CVector4D(waterBounds[0].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
|
|
|
|
CVector4D v4 = viewproj.Transform(CVector4D(waterBounds[1].X, waterBounds[1].Y, waterBounds[1].Z, 1.0f));
|
2011-11-25 07:36:13 +01:00
|
|
|
CBoundingBoxAligned screenBounds;
|
2011-07-13 01:48:05 +02:00
|
|
|
#define ADDBOUND(v1, v2, v3, v4) \
|
2012-04-08 17:55:06 +02:00
|
|
|
if (v1.Z >= -v1.W) \
|
|
|
|
screenBounds += CVector3D(v1.X, v1.Y, v1.Z) * (1.0f / v1.W); \
|
2011-07-13 01:48:05 +02:00
|
|
|
else \
|
|
|
|
{ \
|
2012-04-08 17:55:06 +02:00
|
|
|
float t = v1.Z + v1.W; \
|
|
|
|
if (v2.Z > -v2.W) \
|
2011-07-13 01:48:05 +02:00
|
|
|
{ \
|
2012-04-08 17:55:06 +02:00
|
|
|
CVector4D c2 = v1 + (v2 - v1) * (t / (t - (v2.Z + v2.W))); \
|
|
|
|
screenBounds += CVector3D(c2.X, c2.Y, c2.Z) * (1.0f / c2.W); \
|
2011-07-13 01:48:05 +02:00
|
|
|
} \
|
2012-04-08 17:55:06 +02:00
|
|
|
if (v3.Z > -v3.W) \
|
2011-07-13 01:48:05 +02:00
|
|
|
{ \
|
2012-04-08 17:55:06 +02:00
|
|
|
CVector4D c3 = v1 + (v3 - v1) * (t / (t - (v3.Z + v3.W))); \
|
|
|
|
screenBounds += CVector3D(c3.X, c3.Y, c3.Z) * (1.0f / c3.W); \
|
2011-07-13 01:48:05 +02:00
|
|
|
} \
|
2012-04-08 17:55:06 +02:00
|
|
|
if (v4.Z > -v4.W) \
|
2011-07-13 01:48:05 +02:00
|
|
|
{ \
|
2012-04-08 17:55:06 +02:00
|
|
|
CVector4D c4 = v1 + (v4 - v1) * (t / (t - (v4.Z + v4.W))); \
|
|
|
|
screenBounds += CVector3D(c4.X, c4.Y, c4.Z) * (1.0f / c4.W); \
|
2011-07-13 01:48:05 +02:00
|
|
|
} \
|
|
|
|
}
|
|
|
|
ADDBOUND(v1, v2, v3, v4);
|
|
|
|
ADDBOUND(v2, v1, v3, v4);
|
|
|
|
ADDBOUND(v3, v1, v2, v4);
|
|
|
|
ADDBOUND(v4, v1, v2, v3);
|
|
|
|
#undef ADDBOUND
|
|
|
|
if (screenBounds[0].X >= 1.0f || screenBounds[1].X <= -1.0f || screenBounds[0].Y >= 1.0f || screenBounds[1].Y <= -1.0f)
|
|
|
|
continue;
|
|
|
|
scissor += screenBounds;
|
|
|
|
}
|
2019-09-18 16:44:31 +02:00
|
|
|
return CBoundingBoxAligned(CVector3D(Clamp(scissor[0].X, -1.0f, 1.0f), Clamp(scissor[0].Y, -1.0f, 1.0f), -1.0f),
|
|
|
|
CVector3D(Clamp(scissor[1].X, -1.0f, 1.0f), Clamp(scissor[1].Y, -1.0f, 1.0f), 1.0f));
|
2011-07-13 01:48:05 +02:00
|
|
|
}
|
2010-03-21 15:18:15 +01:00
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
// Render fancy water
|
2014-06-25 03:11:10 +02:00
|
|
|
bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
2011-07-13 01:48:05 +02:00
|
|
|
{
|
2011-11-09 14:09:01 +01:00
|
|
|
PROFILE3_GPU("fancy water");
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2012-10-31 19:42:17 +01:00
|
|
|
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
|
|
|
|
CShaderDefines defines = context;
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2006-05-25 07:46:17 +02:00
|
|
|
// If we're using fancy water, make sure its shader is loaded
|
2013-07-14 14:17:07 +02:00
|
|
|
if (!m->fancyWaterShader || WaterMgr->m_NeedsReloading)
|
2006-05-25 07:46:17 +02:00
|
|
|
{
|
2013-09-29 15:19:52 +02:00
|
|
|
if (WaterMgr->m_WaterRealDepth)
|
|
|
|
defines.Add(str_USE_REAL_DEPTH, str_1);
|
2014-07-01 18:05:05 +02:00
|
|
|
if (WaterMgr->m_WaterFancyEffects)
|
|
|
|
defines.Add(str_USE_FANCY_EFFECTS, str_1);
|
2013-09-29 15:19:52 +02:00
|
|
|
if (WaterMgr->m_WaterRefraction)
|
|
|
|
defines.Add(str_USE_REFRACTION, str_1);
|
|
|
|
if (WaterMgr->m_WaterReflection)
|
|
|
|
defines.Add(str_USE_REFLECTION, str_1);
|
|
|
|
if (shadow && WaterMgr->m_WaterShadows)
|
2014-07-01 18:05:05 +02:00
|
|
|
defines.Add(str_USE_SHADOWS_ON_WATER, str_1);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2012-10-31 19:42:17 +01:00
|
|
|
// haven't updated the ARB shader yet so I'll always load the GLSL
|
2019-08-04 10:28:30 +02:00
|
|
|
/*if (!g_RenderingOptions.GetPreferGLSL() && !superFancy)
|
2012-10-31 19:42:17 +01:00
|
|
|
m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("arb/water_high", defines);
|
|
|
|
else*/
|
|
|
|
m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("glsl/water_high", defines);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2012-01-29 13:04:39 +01:00
|
|
|
if (!m->fancyWaterShader)
|
2009-03-24 22:00:41 +01:00
|
|
|
{
|
2015-01-22 21:31:30 +01:00
|
|
|
LOGERROR("Failed to load water shader. Falling back to fixed pipeline water.\n");
|
2012-11-04 16:54:36 +01:00
|
|
|
WaterMgr->m_RenderWater = false;
|
2011-07-13 01:48:05 +02:00
|
|
|
return false;
|
2009-03-24 22:00:41 +01:00
|
|
|
}
|
2013-04-27 14:20:42 +02:00
|
|
|
WaterMgr->m_NeedsReloading = false;
|
2006-05-25 07:46:17 +02:00
|
|
|
}
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2012-10-31 19:42:17 +01:00
|
|
|
CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
|
|
|
|
|
2012-11-04 16:54:36 +01:00
|
|
|
// Calculating the advanced informations about Foam and all if the quality calls for it.
|
2013-08-18 11:27:11 +02:00
|
|
|
/*if (WaterMgr->m_NeedInfoUpdate && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves))
|
2013-04-27 14:20:42 +02:00
|
|
|
{
|
2013-08-18 11:27:11 +02:00
|
|
|
WaterMgr->m_NeedInfoUpdate = false;
|
2012-11-04 16:54:36 +01:00
|
|
|
WaterMgr->CreateSuperfancyInfo();
|
2013-04-27 14:20:42 +02:00
|
|
|
}*/
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2006-01-22 00:27:42 +01:00
|
|
|
double time = WaterMgr->m_WaterTexTimer;
|
2012-10-31 19:42:17 +01:00
|
|
|
double period = 8;
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
int curTex = (int)(time*60/period) % 60;
|
2012-10-31 19:42:17 +01:00
|
|
|
int nexTex = (curTex + 1) % 60;
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-01 18:05:05 +02:00
|
|
|
float repeatPeriod = WaterMgr->m_RepeatPeriod;
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-01 18:05:05 +02:00
|
|
|
// Render normals and foam to a framebuffer if we're in fancy effects
|
|
|
|
if (WaterMgr->m_WaterFancyEffects)
|
2012-10-31 19:42:17 +01:00
|
|
|
{
|
|
|
|
// Save the post-processing framebuffer.
|
|
|
|
GLint fbo;
|
|
|
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-28 12:14:00 +02:00
|
|
|
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, WaterMgr->m_FancyEffectsFBO);
|
|
|
|
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-28 12:14:00 +02:00
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
// Overwrite waves that would be behind the ground.
|
|
|
|
CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("glsl/gui_solid", CShaderDefines());
|
|
|
|
dummyShader->Bind();
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-28 12:14:00 +02:00
|
|
|
dummyShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
|
|
|
dummyShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.0f);
|
2014-07-01 18:05:05 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
|
|
|
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
|
|
|
{
|
|
|
|
CPatchRData* data = visiblePatches[i];
|
2014-08-01 12:15:29 +02:00
|
|
|
data->RenderWater(dummyShader, true, true);
|
2014-07-01 18:05:05 +02:00
|
|
|
}
|
2014-07-28 12:14:00 +02:00
|
|
|
dummyShader->Unbind();
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-28 12:14:00 +02:00
|
|
|
glEnable(GL_CULL_FACE);
|
2012-10-31 19:42:17 +01:00
|
|
|
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
|
|
|
}
|
2014-07-01 18:05:05 +02:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-01 18:05:05 +02:00
|
|
|
m->fancyWaterShader->Bind();
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2010-08-29 16:13:39 +02:00
|
|
|
const CCamera& camera = g_Renderer.GetViewCamera();
|
2006-05-25 07:46:17 +02:00
|
|
|
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->BindTexture(str_normalMap, WaterMgr->m_NormalMap[curTex]);
|
|
|
|
m->fancyWaterShader->BindTexture(str_normalMap2, WaterMgr->m_NormalMap[nexTex]);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-01 18:05:05 +02:00
|
|
|
if (WaterMgr->m_WaterFancyEffects)
|
2014-07-28 12:14:00 +02:00
|
|
|
{
|
2020-09-16 20:03:51 +02:00
|
|
|
m->fancyWaterShader->BindTexture(str_waterEffectsTex, WaterMgr->m_FancyTexture);
|
2014-07-28 12:14:00 +02:00
|
|
|
}
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2020-11-11 19:46:52 +01:00
|
|
|
if (WaterMgr->m_WaterRefraction && WaterMgr->m_WaterRealDepth)
|
|
|
|
{
|
|
|
|
m->fancyWaterShader->BindTexture(str_depthTex, WaterMgr->m_RefrFboDepthTexture);
|
|
|
|
m->fancyWaterShader->Uniform(str_projInvTransform, WaterMgr->m_RefractionProjInvMatrix);
|
|
|
|
m->fancyWaterShader->Uniform(str_viewInvTransform, WaterMgr->m_RefractionViewInvMatrix);
|
|
|
|
}
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2012-11-04 16:54:36 +01:00
|
|
|
if (WaterMgr->m_WaterRefraction)
|
2014-07-01 18:05:05 +02:00
|
|
|
m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture);
|
2019-09-22 16:56:22 +02:00
|
|
|
if (WaterMgr->m_WaterReflection)
|
|
|
|
m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture);
|
2020-11-04 23:55:34 +01:00
|
|
|
m->fancyWaterShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
|
2011-07-13 01:48:05 +02:00
|
|
|
|
|
|
|
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
2012-10-31 19:42:17 +01:00
|
|
|
|
2014-07-28 12:14:00 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
|
|
|
|
|
|
|
//TODO: bind only what's needed
|
2019-05-25 13:08:57 +02:00
|
|
|
if (WaterMgr->m_WaterRefraction || WaterMgr->m_WaterReflection)
|
2014-07-28 12:14:00 +02:00
|
|
|
{
|
2019-05-25 13:08:57 +02:00
|
|
|
m->fancyWaterShader->BindTexture(str_skyCube, g_Renderer.GetSkyManager()->GetSkyCube());
|
2014-07-28 12:14:00 +02:00
|
|
|
// TODO: check that this rotates in the right direction.
|
|
|
|
CMatrix3D skyBoxRotation;
|
|
|
|
skyBoxRotation.SetIdentity();
|
2019-01-06 22:55:30 +01:00
|
|
|
skyBoxRotation.RotateY(M_PI + lightEnv.GetRotation());
|
2014-07-28 12:14:00 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_skyBoxRot, skyBoxRotation);
|
2019-09-22 16:56:22 +02:00
|
|
|
|
|
|
|
if (WaterMgr->m_WaterRefraction)
|
|
|
|
m->fancyWaterShader->Uniform(str_refractionMatrix, WaterMgr->m_RefractionMatrix);
|
|
|
|
if (WaterMgr->m_WaterReflection)
|
|
|
|
m->fancyWaterShader->Uniform(str_reflectionMatrix, WaterMgr->m_ReflectionMatrix);
|
2014-07-28 12:14:00 +02:00
|
|
|
}
|
2020-11-08 23:17:58 +01:00
|
|
|
m->fancyWaterShader->Uniform(str_ambient, lightEnv.m_TerrainAmbientColor);
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir());
|
2014-07-28 12:14:00 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor);
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_color, WaterMgr->m_WaterColor);
|
2014-07-03 22:07:15 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_tint, WaterMgr->m_WaterTint);
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_waviness, WaterMgr->m_Waviness);
|
|
|
|
m->fancyWaterShader->Uniform(str_murkiness, WaterMgr->m_Murkiness);
|
2014-07-03 22:07:15 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_windAngle, WaterMgr->m_WindAngle);
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod);
|
|
|
|
m->fancyWaterShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix());
|
2019-12-10 22:39:09 +01:00
|
|
|
|
2019-12-14 13:56:47 +01:00
|
|
|
m->fancyWaterShader->Uniform(str_cameraPos, camera.GetOrientation().GetTranslation());
|
2019-12-10 22:39:09 +01:00
|
|
|
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor);
|
|
|
|
m->fancyWaterShader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
|
|
|
|
m->fancyWaterShader->Uniform(str_time, (float)time);
|
|
|
|
m->fancyWaterShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f);
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2014-07-28 12:14:00 +02:00
|
|
|
if (WaterMgr->m_WaterType == L"clap")
|
2014-07-03 22:07:15 +02:00
|
|
|
{
|
2014-07-28 12:14:00 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_waveParams1, 30.0f,1.5f,20.0f,0.03f);
|
|
|
|
m->fancyWaterShader->Uniform(str_waveParams2, 0.5f,0.0f,0.0f,0.0f);
|
|
|
|
}
|
|
|
|
else if (WaterMgr->m_WaterType == L"lake")
|
|
|
|
{
|
|
|
|
m->fancyWaterShader->Uniform(str_waveParams1, 8.5f,1.5f,15.0f,0.03f);
|
|
|
|
m->fancyWaterShader->Uniform(str_waveParams2, 0.2f,0.0f,0.0f,0.07f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m->fancyWaterShader->Uniform(str_waveParams1, 15.0f,0.8f,10.0f,0.1f);
|
|
|
|
m->fancyWaterShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.3f);
|
2014-07-03 22:07:15 +02:00
|
|
|
}
|
2016-11-23 15:09:58 +01:00
|
|
|
|
2012-11-04 16:54:36 +01:00
|
|
|
if (shadow && WaterMgr->m_WaterShadows)
|
2012-10-31 19:42:17 +01:00
|
|
|
{
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->BindTexture(str_shadowTex, shadow->GetTexture());
|
|
|
|
m->fancyWaterShader->Uniform(str_shadowTransform, shadow->GetTextureMatrix());
|
2012-10-31 19:42:17 +01:00
|
|
|
int width = shadow->GetWidth();
|
|
|
|
int height = shadow->GetHeight();
|
2013-09-29 15:19:52 +02:00
|
|
|
m->fancyWaterShader->Uniform(str_shadowScale, width, height, 1.0f / width, 1.0f / height);
|
2012-10-31 19:42:17 +01:00
|
|
|
}
|
2006-05-25 07:46:17 +02:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
|
|
|
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
2006-05-25 07:46:17 +02:00
|
|
|
{
|
2014-06-25 03:11:10 +02:00
|
|
|
CPatchRData* data = visiblePatches[i];
|
2012-02-13 15:02:14 +01:00
|
|
|
data->RenderWater(m->fancyWaterShader);
|
2006-05-25 07:46:17 +02:00
|
|
|
}
|
2012-01-29 13:23:16 +01:00
|
|
|
m->fancyWaterShader->Unbind();
|
2006-01-07 02:04:26 +01:00
|
|
|
|
2014-07-28 12:14:00 +02:00
|
|
|
glDepthFunc(GL_LEQUAL);
|
2011-07-13 01:48:05 +02:00
|
|
|
glDisable(GL_BLEND);
|
2006-05-28 04:13:32 +02:00
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
return true;
|
|
|
|
}
|
2006-05-28 04:13:32 +02:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
void TerrainRenderer::RenderSimpleWater(int cullGroup)
|
2011-07-13 01:48:05 +02:00
|
|
|
{
|
2014-06-25 03:11:10 +02:00
|
|
|
#if CONFIG2_GLES
|
|
|
|
UNUSED2(cullGroup);
|
|
|
|
#else
|
2011-11-09 14:09:01 +01:00
|
|
|
PROFILE3_GPU("simple water");
|
2006-05-25 07:46:17 +02:00
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
|
|
|
|
CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
|
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
|
|
|
|
double time = WaterMgr->m_WaterTexTimer;
|
|
|
|
double period = 1.6f;
|
|
|
|
int curTex = (int)(time*60/period) % 60;
|
|
|
|
|
2020-11-04 23:25:08 +01:00
|
|
|
CShaderTechniquePtr waterSimpleTech =
|
|
|
|
g_Renderer.GetShaderManager().LoadEffect(str_water_simple);
|
|
|
|
waterSimpleTech->BeginPass();
|
|
|
|
CShaderProgramPtr waterSimpleShader = waterSimpleTech->GetShader();
|
|
|
|
|
|
|
|
waterSimpleShader->Bind();
|
|
|
|
waterSimpleShader->BindTexture(str_baseTex, WaterMgr->m_WaterTexture[curTex]);
|
2020-11-04 23:55:34 +01:00
|
|
|
waterSimpleShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
|
2020-11-04 23:25:08 +01:00
|
|
|
waterSimpleShader->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
|
|
|
waterSimpleShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix());
|
|
|
|
waterSimpleShader->Uniform(str_time, static_cast<float>(time));
|
|
|
|
waterSimpleShader->Uniform(str_color, WaterMgr->m_WaterColor);
|
2012-02-13 15:02:14 +01:00
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
2011-02-03 02:12:24 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
|
|
|
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
2011-07-13 01:48:05 +02:00
|
|
|
{
|
2014-06-25 03:11:10 +02:00
|
|
|
CPatchRData* data = visiblePatches[i];
|
2020-11-04 23:25:08 +01:00
|
|
|
data->RenderWater(waterSimpleShader, false, true);
|
2006-05-28 23:58:56 +02:00
|
|
|
}
|
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
|
2020-11-04 23:25:08 +01:00
|
|
|
waterSimpleShader->Unbind();
|
2011-07-13 01:48:05 +02:00
|
|
|
g_Renderer.BindTexture(1, 0);
|
|
|
|
|
|
|
|
pglActiveTextureARB(GL_TEXTURE0_ARB);
|
2006-01-07 02:04:26 +01:00
|
|
|
glDisable(GL_TEXTURE_2D);
|
2020-11-04 23:25:08 +01:00
|
|
|
|
|
|
|
waterSimpleTech->EndPass();
|
2012-02-13 15:02:14 +01:00
|
|
|
#endif
|
2006-01-07 02:04:26 +01:00
|
|
|
}
|
2011-01-29 17:31:48 +01:00
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Render water that is part of the terrain
|
2014-06-25 03:11:10 +02:00
|
|
|
void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
2011-07-13 01:48:05 +02:00
|
|
|
{
|
|
|
|
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
|
|
|
|
|
2014-07-01 18:05:05 +02:00
|
|
|
WaterMgr->UpdateQuality();
|
|
|
|
|
2012-11-04 16:54:36 +01:00
|
|
|
if (!WaterMgr->WillRenderFancyWater())
|
2014-06-25 03:11:10 +02:00
|
|
|
RenderSimpleWater(cullGroup);
|
2012-11-04 16:54:36 +01:00
|
|
|
else
|
2014-06-25 03:11:10 +02:00
|
|
|
RenderFancyWater(context, cullGroup, shadow);
|
2011-07-13 01:48:05 +02:00
|
|
|
}
|
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
void TerrainRenderer::RenderPriorities(int cullGroup)
|
2011-01-29 17:31:48 +01:00
|
|
|
{
|
2011-11-09 14:09:01 +01:00
|
|
|
PROFILE("priorities");
|
2011-01-29 17:31:48 +01:00
|
|
|
|
2011-04-30 15:01:45 +02:00
|
|
|
ENSURE(m->phase == Phase_Render);
|
2011-01-30 03:14:44 +01:00
|
|
|
|
2013-09-29 15:19:52 +02:00
|
|
|
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
|
2012-02-12 21:45:31 +01:00
|
|
|
tech->BeginPass();
|
|
|
|
CTextRenderer textRenderer(tech->GetShader());
|
2011-01-29 17:31:48 +01:00
|
|
|
|
2013-10-18 18:15:42 +02:00
|
|
|
textRenderer.Font(CStrIntern("mono-stroke-10"));
|
2012-02-12 21:45:31 +01:00
|
|
|
textRenderer.Color(1.0f, 1.0f, 0.0f);
|
2011-01-29 17:31:48 +01:00
|
|
|
|
2014-06-25 03:11:10 +02:00
|
|
|
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
|
|
|
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
|
|
|
visiblePatches[i]->RenderPriorities(textRenderer);
|
2012-02-12 21:45:31 +01:00
|
|
|
|
|
|
|
textRenderer.Render();
|
|
|
|
tech->EndPass();
|
2011-01-29 17:31:48 +01:00
|
|
|
}
|