1
0
forked from 0ad/0ad

Change the water manager so incremental updates to the water information is possible. Streamline a few things (and removes a not-really-used calculation to speed things up further). Fixes #2063 , refs #1743.

This was SVN commit r13698.
This commit is contained in:
wraitii 2013-08-18 09:27:11 +00:00
parent 557c1fc067
commit a4707bcc16
6 changed files with 105 additions and 72 deletions

View File

@ -45,10 +45,6 @@
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpWaterManager.h"
#include "tools/atlas/GameInterface/GameLoop.h"
extern GameLoopState* g_AtlasGameLoop;
const ssize_t BlendOffsets[9][2] = {
{ 0, -1 },
{ -1, -1 },
@ -1311,9 +1307,9 @@ void CPatchRData::BuildWater()
// TODO: This is not (yet) exported via the ICmp interface so... we stick to these values which can be compiled in defaults
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
if (WaterMgr->m_NeedsFullReloading && !g_AtlasGameLoop->running)
if (WaterMgr->m_NeedInfoUpdate)
{
WaterMgr->m_NeedsFullReloading = false;
WaterMgr->m_NeedInfoUpdate = false;
WaterMgr->CreateSuperfancyInfo(m_Simulation);
}
CPatch* patch = m_Patch;

View File

@ -649,7 +649,7 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
WaterManager* WaterMgr = g_Renderer.GetWaterManager();
CShaderDefines defines = context;
WaterMgr->updateQuality();
WaterMgr->UpdateQuality();
// If we're using fancy water, make sure its shader is loaded
if (!m->fancyWaterShader || WaterMgr->m_NeedsReloading)
@ -689,18 +689,9 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
WaterMgr->m_RenderWater = false;
return false;
}
// we need to actually recompute the whole map settings.
if (WaterMgr->m_NeedsFullReloading)
{
WaterMgr->m_waveTT = 0;
WaterMgr->m_depthTT = 0;
}
WaterMgr->m_NeedsReloading = false;
}
if (g_AtlasGameLoop->running)
WaterMgr->m_TerrainChangeThisTurn = false;
CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();
GLuint depthTex;
@ -728,9 +719,9 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap*
glBindTexture(GL_TEXTURE_2D, 0);
}
// Calculating the advanced informations about Foam and all if the quality calls for it.
/*if (WaterMgr->m_NeedsFullReloading && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves))
/*if (WaterMgr->m_NeedInfoUpdate && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves))
{
WaterMgr->m_NeedsFullReloading = false;
WaterMgr->m_NeedInfoUpdate = false;
WaterMgr->CreateSuperfancyInfo();
}*/

View File

@ -92,8 +92,7 @@ WaterManager::WaterManager()
m_WaterShadows = false;
m_NeedsReloading = false;
m_NeedsFullReloading = true;
m_TerrainChangeThisTurn = false;
m_NeedInfoUpdate = true;
m_VBWaves = NULL;
m_VBWavesIndices = NULL;
@ -101,6 +100,12 @@ WaterManager::WaterManager()
m_depthTT = 0;
m_waveTT = 0;
m_MapSize = 0;
m_updatei0 = 0;
m_updatej0 = 0;
m_updatei1 = 0;
m_updatej1 = 0;
}
WaterManager::~WaterManager()
@ -245,7 +250,6 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
}
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
ssize_t mapSize = terrain->GetVerticesPerSide();
CmpPtr<ICmpWaterManager> cmpWaterManager(*simulation, SYSTEM_ENTITY);
if (!cmpWaterManager)
@ -256,34 +260,38 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
if (!cmpRangeManager)
return;
bool circular = cmpRangeManager->GetLosCircular();
float mSize = mapSize*mapSize;
float halfSize = (mapSize/2.0);
float mSize = m_MapSize*m_MapSize;
float halfSize = (m_MapSize/2.0);
// Warning: this won't work with multiple water planes
m_WaterHeight = cmpWaterManager->GetExactWaterLevel(0,0);
// TODO: change this whenever we incrementally update because it's def. not too efficient
delete[] m_WaveX;
delete[] m_WaveZ;
delete[] m_DistanceToShore;
delete[] m_FoamFactor;
// Get the square we want to work on.
i32 Xstart = m_updatei0;
i32 Xend = m_updatei1;
i32 Zstart = m_updatej0;
i32 Zend = m_updatej1;
m_WaveX = new float[mapSize*mapSize];
m_WaveZ = new float[mapSize*mapSize];
m_DistanceToShore = new float[mapSize*mapSize];
m_FoamFactor = new float[mapSize*mapSize];
if (m_WaveX == NULL)
{
m_WaveX = new float[m_MapSize*m_MapSize];
m_WaveZ = new float[m_MapSize*m_MapSize];
m_DistanceToShore = new float[m_MapSize*m_MapSize];
m_FoamFactor = new float[m_MapSize*m_MapSize];
}
u16* heightmap = terrain->GetHeightMap();
// some temporary stuff for wave intensity
// not really used too much right now.
u8* waveForceHQ = new u8[mapSize*mapSize];
u16 waterHeightInu16 = m_WaterHeight/HEIGHT_SCALE;
//u8* waveForceHQ = new u8[mapSize*mapSize];
// used to cache terrain normals since otherwise we'd recalculate them a lot (I'm blurring the "normal" map).
// this might be updated to actually cache in the terrain manager but that's not for now.
CVector3D* normals = new CVector3D[mapSize*mapSize];
CVector3D* normals = new CVector3D[m_MapSize*m_MapSize];
// TODO: reactivate?
/*
// calculate wave force (not really used right now)
// and puts into "normals" the terrain normal at that point
// so as to avoid recalculating terrain normals too often.
@ -310,20 +318,21 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
waveForceHQ[j*mapSize + i] = 255 - color * 40;
}
}
*/
// this creates information for waves and stores it in float arrays. PatchRData then puts it in the vertex info for speed.
for (ssize_t i = 0; i < mapSize; ++i)
for (ssize_t i = Xstart; i < Xend; ++i)
{
for (ssize_t j = 0; j < mapSize; ++j)
for (ssize_t j = Zstart; j < Zend; ++j)
{
if (circular && (i-halfSize)*(i-halfSize)+(j-halfSize)*(j-halfSize) > mSize)
{
m_WaveX[j*mapSize + i] = 0.0f;
m_WaveZ[j*mapSize + i] = 0.0f;
m_DistanceToShore[j*mapSize + i] = 100;
m_FoamFactor[j*mapSize + i] = 0.0f;
m_WaveX[j*m_MapSize + i] = 0.0f;
m_WaveZ[j*m_MapSize + i] = 0.0f;
m_DistanceToShore[j*m_MapSize + i] = 100;
m_FoamFactor[j*m_MapSize + i] = 0.0f;
continue;
}
float depth = m_WaterHeight - heightmap[j*mapSize + i]*HEIGHT_SCALE;
float depth = m_WaterHeight - heightmap[j*m_MapSize + i]*HEIGHT_SCALE;
int distanceToShore = 10000;
// calculation of the distance to the shore.
@ -336,10 +345,10 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
{
for (int yy = -5; yy <= 5; ++yy)
{
if (i+xx >= 0 && i + xx < mapSize)
if (j + yy >= 0 && j + yy < mapSize)
if (i+xx >= 0 && i + xx < (long)m_MapSize)
if (j + yy >= 0 && j + yy < (long)m_MapSize)
{
float hereDepth = m_WaterHeight - heightmap[(j+yy)*mapSize + (i+xx)]*HEIGHT_SCALE;
float hereDepth = m_WaterHeight - heightmap[(j+yy)*m_MapSize + (i+xx)]*HEIGHT_SCALE;
if (hereDepth < 0 && xx*xx + yy*yy < distanceToShore)
distanceToShore = xx*xx + yy*yy;
}
@ -375,10 +384,10 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
// speedup with default values for land squares
if (distanceToShore == 10000)
{
m_WaveX[j*mapSize + i] = 0.0f;
m_WaveZ[j*mapSize + i] = 0.0f;
m_DistanceToShore[j*mapSize + i] = 100;
m_FoamFactor[j*mapSize + i] = 0.0f;
m_WaveX[j*m_MapSize + i] = 0.0f;
m_WaveZ[j*m_MapSize + i] = 0.0f;
m_DistanceToShore[j*m_MapSize + i] = 100;
m_FoamFactor[j*m_MapSize + i] = 0.0f;
continue;
}
// We'll compute the normals and the "water raise", to know about foam
@ -389,10 +398,10 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
{
for (int yy = -4; yy <= 4; yy += 2)
{
if (j+yy < mapSize && i+xx < mapSize && i+xx >= 0 && j+yy >= 0)
normal += normals[(j+yy)*mapSize + (i+xx)];
if (terrain->GetVertexGroundLevel(i+xx,j+yy) < heightmap[j*mapSize + i]*HEIGHT_SCALE)
waterRaise += heightmap[j*mapSize + i]*HEIGHT_SCALE - terrain->GetVertexGroundLevel(i+xx,j+yy);
if (j+yy < (long)m_MapSize && i+xx < (long)m_MapSize && i+xx >= 0 && j+yy >= 0)
normal += normals[(j+yy)*m_MapSize + (i+xx)];
if (terrain->GetVertexGroundLevel(i+xx,j+yy) < heightmap[j*m_MapSize + i]*HEIGHT_SCALE)
waterRaise += heightmap[j*m_MapSize + i]*HEIGHT_SCALE - terrain->GetVertexGroundLevel(i+xx,j+yy);
}
}
// normalizes the terrain info to avoid foam moving at too different speeds.
@ -400,25 +409,25 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
normal[1] = 0.1f;
normal = normal.Normalized();
m_WaveX[j*mapSize + i] = normal[0];
m_WaveZ[j*mapSize + i] = normal[2];
m_WaveX[j*m_MapSize + i] = normal[0];
m_WaveZ[j*m_MapSize + i] = normal[2];
// distance is /5.0 to be a [0,1] value.
m_DistanceToShore[j*mapSize + i] = sqrtf(distanceToShore)/5.0f; // TODO: this can probably be cached as I'm integer here.
m_DistanceToShore[j*m_MapSize + i] = sqrtf(distanceToShore)/5.0f; // TODO: this can probably be cached as I'm integer here.
// computing the amount of foam I want
depth = clamp(depth,0.0f,10.0f);
float foamAmount = (waterRaise/255.0f) * (1.0f - depth/10.0f) * (waveForceHQ[j*mapSize+i]/255.0f) * (m_Waviness/8.0f);
float foamAmount = (waterRaise/255.0f) * (1.0f - depth/10.0f) /** (waveForceHQ[j*m_MapSize+i]/255.0f)*/ * (m_Waviness/8.0f);
foamAmount += clamp(m_Waviness/2.0f - distanceToShore,0.0f,m_Waviness/2.0f)/(m_Waviness/2.0f) * clamp(m_Waviness/9.0f,0.3f,1.0f);
foamAmount = foamAmount > 1.0f ? 1.0f: foamAmount;
m_FoamFactor[j*mapSize + i] = foamAmount;
m_FoamFactor[j*m_MapSize + i] = foamAmount;
}
}
delete[] normals;
delete[] waveForceHQ;
//delete[] waveForceHQ;
// TODO: The rest should be cleaned up
@ -430,9 +439,9 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
std::vector<CVector2D> waveSquares;
int size = 8; // I think this is the size of the squares.
for (int i = 0; i < mapSize/size; ++i)
for (size_t i = 0; i < m_MapSize/size; ++i)
{
for (int j = 0; j < mapSize/size; ++j)
for (size_t j = 0; j < m_MapSize/size; ++j)
{
int landTexel = 0;
@ -575,9 +584,27 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation)
m_VBWavesIndices->m_Owner->UpdateChunkVertices(m_VBWavesIndices, &waves_indices[0]);
}
////////////////////////////////////////////////////////////////////////
// This will always recalculate for now
void WaterManager::SetMapSize(size_t size)
{
// TODO: Im' blindly trusting the user here.
m_MapSize = size;
m_NeedInfoUpdate = true;
m_updatei0 = 0;
m_updatei1 = size;
m_updatej0 = 0;
m_updatej1 = size;
SAFE_ARRAY_DELETE(m_WaveX);
SAFE_ARRAY_DELETE(m_WaveZ);
SAFE_ARRAY_DELETE(m_DistanceToShore);
SAFE_ARRAY_DELETE(m_FoamFactor);
}
////////////////////////////////////////////////////////////////////////
// This will set the bools properly
void WaterManager::updateQuality()
void WaterManager::UpdateQuality()
{
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERNORMAL) != m_WaterNormal) {
m_WaterNormal = g_Renderer.GetOptionBool(CRenderer::OPT_WATERNORMAL);
@ -590,12 +617,12 @@ void WaterManager::updateQuality()
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERFOAM) != m_WaterFoam) {
m_WaterFoam = g_Renderer.GetOptionBool(CRenderer::OPT_WATERFOAM);
m_NeedsReloading = true;
m_NeedsFullReloading = true;
m_NeedInfoUpdate = true;
}
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERCOASTALWAVES) != m_WaterCoastalWaves) {
m_WaterCoastalWaves = g_Renderer.GetOptionBool(CRenderer::OPT_WATERCOASTALWAVES);
m_NeedsReloading = true;
m_NeedsFullReloading = true;
m_NeedInfoUpdate = true;
}
if (g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFRACTION) != m_WaterRefraction) {
m_WaterRefraction = g_Renderer.GetOptionBool(CRenderer::OPT_WATERREFRACTION);

View File

@ -58,11 +58,17 @@ public:
float* m_DistanceToShore;
float* m_FoamFactor;
size_t m_MapSize;
ssize_t m_TexSize;
GLuint m_depthTT;
GLuint m_waveTT;
// used to know what to update when updating parts of the terrain only.
i32 m_updatei0;
i32 m_updatej0;
i32 m_updatei1;
i32 m_updatej1;
int m_WaterCurrentTex;
CColor m_WaterColor;
@ -79,9 +85,7 @@ public:
bool m_NeedsReloading;
// requires also recreating the super fancy information.
bool m_NeedsFullReloading;
// used only by Atlas to know when to update the water map.
bool m_TerrainChangeThisTurn;
bool m_NeedInfoUpdate;
bool m_WaterScroll;
float m_WaterHeight;
@ -147,10 +151,15 @@ public:
*/
void CreateSuperfancyInfo(CSimulation2* simulation);
/**
* Updates the map size. Will trigger a complete recalculation of fancy water information the next turn.
*/
void SetMapSize(size_t size);
/**
* Updates the settings to the one from the renderer, and sets m_NeedsReloading.
*/
void updateQuality();
void UpdateQuality();
/**
* Returns true if fancy water shaders will be used (i.e. the hardware is capable

View File

@ -25,6 +25,8 @@
#include "simulation2/MessageTypes.h"
#include "graphics/Terrain.h"
#include "Renderer/Renderer.h"
#include "Renderer/WaterManager.h"
#include "maths/Vector3D.h"
class CCmpTerrain : public ICmpTerrain
@ -133,6 +135,9 @@ public:
vertices);
}
if (CRenderer::IsInitialised())
g_Renderer.GetWaterManager()->SetMapSize(vertices);
MakeDirty(0, 0, tiles+1, tiles+1);
}

View File

@ -83,9 +83,14 @@ public:
// Tell the renderer to redraw the map.
if (CRenderer::IsInitialised())
{
g_Renderer.GetWaterManager()->m_NeedsFullReloading = true;
g_Renderer.GetWaterManager()->m_NeedsReloading = true;
g_Renderer.GetWaterManager()->m_TerrainChangeThisTurn = true;
const CMessageTerrainChanged& msgData = static_cast<const CMessageTerrainChanged&> (msg);
g_Renderer.GetWaterManager()->m_NeedInfoUpdate = true;
g_Renderer.GetWaterManager()->m_updatei0 = msgData.i0;
g_Renderer.GetWaterManager()->m_updatej0 = msgData.j0;
g_Renderer.GetWaterManager()->m_updatei1 = msgData.i1;
g_Renderer.GetWaterManager()->m_updatej1 = msgData.j1;
GetSimContext().GetTerrain().MakeDirty(msgData.i0,msgData.j0,msgData.i1,msgData.j1,RENDERDATA_UPDATE_VERTICES);
}
break;
}