Skip to content

Commit

Permalink
fix BumpWater shader compilation errors on view-resize events (#2051)
Browse files Browse the repository at this point in the history
(the new renderer instance was being created before the old one
had been deleted, so its shaders were already compiled and stale
==> rewrote CBaseWater::GetWater to get rid of the previous water
instance before new'ing)
  • Loading branch information
kloot committed Jan 3, 2011
1 parent 8750b23 commit d4d0ea3
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 114 deletions.
6 changes: 3 additions & 3 deletions rts/Game/Game.cpp
Expand Up @@ -544,7 +544,7 @@ void CGame::LoadRendering()

loadscreen->SetLoadMessage("Creating Sky & Water");
sky = CBaseSky::GetSky();
water = CBaseWater::GetWater(NULL);
water = CBaseWater::GetWater(NULL, -1);

glLightfv(GL_LIGHT1, GL_AMBIENT, mapInfo->light.unitAmbientColor);
glLightfv(GL_LIGHT1, GL_DIFFUSE, mapInfo->light.unitSunColor);
Expand Down Expand Up @@ -692,8 +692,8 @@ void CGame::ResizeEvent()
minimap->UpdateGeometry();
}

// Fix water renderer, they depend on screen resolution...
water = CBaseWater::GetWater(water);
// reload water renderer (it may depend on screen resolution)
water = CBaseWater::GetWater(water, water->GetID());

eventHandler.ViewResize();
}
Expand Down
14 changes: 6 additions & 8 deletions rts/Game/UnsyncedGameCommands.cpp
Expand Up @@ -142,18 +142,16 @@ bool CGame::ActionPressed(const Action& action,
shadowHandler = new CShadowHandler();
}
else if (cmd == "water") {
static char rmodes[5][32] = {"basic", "reflective", "dynamic", "reflective&refractive", "bumpmapped"};
int next = 0;
int nextWaterRendererMode = 0;

if (!action.extra.empty()) {
next = std::max(0, atoi(action.extra.c_str()) % 5);
nextWaterRendererMode = std::max(0, atoi(action.extra.c_str()) % CBaseWater::NUM_WATER_RENDERERS);
} else {
const int current = configHandler->Get("ReflectiveWater", 1);
next = (std::max(0, current) + 1) % 5;
nextWaterRendererMode = (std::max(0, water->GetID()) + 1) % CBaseWater::NUM_WATER_RENDERERS;
}
configHandler->Set("ReflectiveWater", next);
logOutput.Print("Set water rendering mode to %i (%s)", next, rmodes[next]);
water = CBaseWater::GetWater(water);

water = CBaseWater::GetWater(water, nextWaterRendererMode);
logOutput.Print("Set water rendering mode to %i (%s)", nextWaterRendererMode, water->GetName());
}
else if (cmd == "advshading") {
static bool canUse = unitDrawer->advShading;
Expand Down
11 changes: 3 additions & 8 deletions rts/Lua/LuaUnsyncedRead.cpp
Expand Up @@ -1096,15 +1096,10 @@ int LuaUnsyncedRead::GetWaterMode(lua_State* L)
if (water == NULL) {
return 0;
}

const int mode = water->GetID();
const char* modeName;
switch (mode) {
case 0: { modeName = "basic"; break; }
case 1: { modeName = "reflective"; break; }
case 2: { modeName = "dynamic"; break; }
case 3: { modeName = "refractive"; break; }
default: { modeName = "unknown"; break; }
}
const char* modeName = water->GetName();

lua_pushnumber(L, mode);
lua_pushstring(L, modeName);
return 2;
Expand Down
2 changes: 0 additions & 2 deletions rts/Rendering/Env/AdvWater.cpp
Expand Up @@ -228,8 +228,6 @@ void CAdvWater::Draw(bool useBlending)

void CAdvWater::UpdateWater(CGame* game)
{
DeleteOldWater(this);

if ((!mapInfo->water.forceRendering && readmap->currMinHeight > 1.0f) || mapInfo->map.voidWater)
return;

Expand Down
12 changes: 7 additions & 5 deletions rts/Rendering/Env/AdvWater.h
Expand Up @@ -10,12 +10,14 @@
class CAdvWater : public CBaseWater
{
public:
void UpdateWater(CGame* game);
void Draw();
void Draw(bool useBlending);
CAdvWater(bool loadShader=true);
CAdvWater(bool loadShader = true);
virtual ~CAdvWater();
virtual int GetID() const { return 1; }
virtual int GetID() const { return WATER_RENDERER_REFLECTIVE; }
virtual const char* GetName() const { return "reflective"; }

virtual void Draw();
void Draw(bool useBlending);
void UpdateWater(CGame* game);

protected:
FBO reflectFBO;
Expand Down
160 changes: 96 additions & 64 deletions rts/Rendering/Env/BaseWater.cpp
Expand Up @@ -15,82 +15,114 @@
#include "Exceptions.h"
#include "GlobalUnsynced.h"

CBaseWater* water=0;
CBaseWater* water = NULL;

CBaseWater::CBaseWater(void)
{
drawReflection=false;
drawRefraction=false;
noWakeProjectiles=false;
drawSolid=false;
oldwater=NULL;
drawReflection = false;
drawRefraction = false;
noWakeProjectiles = false;
drawSolid = false;
}

CBaseWater::~CBaseWater(void)
{
DeleteOldWater(this);
}

void CBaseWater::DeleteOldWater(CBaseWater *water) {
if(water->oldwater) {
DeleteOldWater(water->oldwater);
delete water->oldwater;
water->oldwater=NULL;
}
}

CBaseWater* CBaseWater::GetWater(CBaseWater* old)
CBaseWater* CBaseWater::GetWater(CBaseWater* currWaterRenderer, int nextWaterRendererMode)
{
CBaseWater* water = NULL;
int configValue = configHandler->Get("ReflectiveWater", 1);

if(water==NULL && configValue==2 && GLEW_ARB_fragment_program && GLEW_ARB_texture_float &&
ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB, "ARB/waterDyn.fp")) {
try {
water = new CDynWater;
} catch (content_error& e) {
delete water;
water = NULL;
logOutput.Print("Loading Dynamic Water failed");
logOutput.Print("Error: %s", e.what());
if (currWaterRenderer != NULL) {
if (currWaterRenderer->GetID() == nextWaterRendererMode) {
if (nextWaterRendererMode == CBaseWater::WATER_RENDERER_BASIC) {
return currWaterRenderer;
}
}

// for BumpWater, this needs to happen before a new renderer
// instance is created because its shaders must be recompiled
delete currWaterRenderer;
}

if(water==NULL && configValue==4 && GLEW_ARB_shading_language_100 && GL_ARB_fragment_shader && GL_ARB_vertex_shader) {
try {
water = new CBumpWater;
} catch (content_error& e) {
delete water;
water = NULL;
logOutput.Print("Loading Bumpmapped Water failed");
logOutput.Print("Error: %s", e.what());
}
if (nextWaterRendererMode < CBaseWater::WATER_RENDERER_BASIC) {
nextWaterRendererMode = configHandler->Get("ReflectiveWater", int(CBaseWater::WATER_RENDERER_REFLECTIVE));
}

if(water==NULL && configValue==3 && GLEW_ARB_fragment_program && GLEW_ARB_texture_rectangle){
try {
water = new CRefractWater;
} catch (content_error& e) {
delete water;
water = NULL;
logOutput.Print("Loading Refractive Water failed");
logOutput.Print("Error: %s", e.what());
}

CBaseWater* nextWaterRenderer = NULL;

switch (nextWaterRendererMode) {
case WATER_RENDERER_DYNAMIC: {
const bool canLoad =
GLEW_ARB_fragment_program &&
GLEW_ARB_texture_float &&
ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB, "ARB/waterDyn.fp");

if (canLoad) {
try {
nextWaterRenderer = new CDynWater();
} catch (content_error& e) {
delete nextWaterRenderer;
nextWaterRenderer = NULL;
logOutput.Print("Loading Dynamic Water failed");
logOutput.Print("Error: %s", e.what());
}
}
} break;

case WATER_RENDERER_BUMPMAPPED: {
const bool canLoad =
GLEW_ARB_shading_language_100 &&
GL_ARB_fragment_shader &&
GL_ARB_vertex_shader;

if (canLoad) {
try {
nextWaterRenderer = new CBumpWater();
} catch (content_error& e) {
delete nextWaterRenderer;
nextWaterRenderer = NULL;
logOutput.Print("Loading Bumpmapped Water failed");
logOutput.Print("Error: %s", e.what());
}
}
} break;

case WATER_RENDERER_REFL_REFR: {
const bool canLoad =
GLEW_ARB_fragment_program &&
GLEW_ARB_texture_rectangle;

if (canLoad) {
try {
nextWaterRenderer = new CRefractWater();
} catch (content_error& e) {
delete nextWaterRenderer;
nextWaterRenderer = NULL;
logOutput.Print("Loading Refractive Water failed");
logOutput.Print("Error: %s", e.what());
}
}
} break;

case WATER_RENDERER_REFLECTIVE: {
const bool canLoad =
GLEW_ARB_fragment_program &&
ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB, "ARB/water.fp");

if (canLoad) {
try {
nextWaterRenderer = new CAdvWater();
} catch (content_error& e) {
delete nextWaterRenderer;
nextWaterRenderer = NULL;
logOutput.Print("Loading Reflective Water failed");
logOutput.Print("Error: %s", e.what());
}
}
} break;
}

if(water==NULL && configValue!=0 && GLEW_ARB_fragment_program &&
ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB, "ARB/water.fp")){
try {
water = new CAdvWater;
} catch (content_error& e) {
delete water;
water = NULL;
logOutput.Print("Loading Reflective Water failed");
logOutput.Print("Error: %s", e.what());
}

if (nextWaterRenderer == NULL) {
nextWaterRenderer = new CBasicWater();
}
if(water==NULL)
water = new CBasicWater;
water->oldwater=old;
return water;

configHandler->Set("ReflectiveWater", nextWaterRenderer->GetID());
return nextWaterRenderer;
}
19 changes: 13 additions & 6 deletions rts/Rendering/Env/BaseWater.h
Expand Up @@ -9,21 +9,28 @@ class CGame;
class CBaseWater
{
public:
enum {
WATER_RENDERER_BASIC = 0,
WATER_RENDERER_REFLECTIVE = 1,
WATER_RENDERER_DYNAMIC = 2,
WATER_RENDERER_REFL_REFR = 3,
WATER_RENDERER_BUMPMAPPED = 4,
NUM_WATER_RENDERERS = 5,
};

CBaseWater(void);
virtual ~CBaseWater(void);
virtual ~CBaseWater(void) {}

virtual void Draw() = 0;
virtual void Update() {}
virtual void UpdateWater(CGame* game) = 0;
virtual void OcclusionQuery() {};
virtual void OcclusionQuery() {}
virtual void HeightmapChanged(const int x1, const int y1, const int x2, const int y2) {}
virtual void AddExplosion(const float3& pos, float strength, float size) {}
virtual int GetID() const { return -1; }
virtual const char* GetName() const { return ""; }

static CBaseWater* GetWater(CBaseWater* old);

CBaseWater* oldwater;
void DeleteOldWater(CBaseWater *water);
static CBaseWater* GetWater(CBaseWater* currWaterRenderer, int nextWaterRenderMode);

bool drawReflection;
bool drawRefraction;
Expand Down
4 changes: 1 addition & 3 deletions rts/Rendering/Env/BasicWater.cpp
Expand Up @@ -35,9 +35,7 @@ CBasicWater::~CBasicWater()
glDeleteLists(displist,1);
}

void CBasicWater::UpdateWater(CGame* game) {
DeleteOldWater(this);
}


void CBasicWater::Draw()
{
Expand Down
10 changes: 6 additions & 4 deletions rts/Rendering/Env/BasicWater.h
Expand Up @@ -9,11 +9,13 @@
class CBasicWater : public CBaseWater
{
public:
void Draw();
void UpdateWater(CGame* game);
CBasicWater();
virtual ~CBasicWater();
int GetID() const { return 0; }
~CBasicWater();

void Draw();
void UpdateWater(CGame*) {}
int GetID() const { return WATER_RENDERER_BASIC; }
const char* GetName() const { return "basic"; }

GLuint texture;
unsigned int displist;
Expand Down
2 changes: 0 additions & 2 deletions rts/Rendering/Env/BumpWater.cpp
Expand Up @@ -635,8 +635,6 @@ void CBumpWater::Update()

void CBumpWater::UpdateWater(CGame* game)
{
DeleteOldWater(this);

if ((!mapInfo->water.forceRendering && readmap->currMinHeight > 0.0f) || mapInfo->map.voidWater)
return;

Expand Down
3 changes: 2 additions & 1 deletion rts/Rendering/Env/BumpWater.h
Expand Up @@ -26,7 +26,8 @@ class CBumpWater : public CBaseWater
void DrawReflection(CGame* game);
void DrawRefraction(CGame* game);
void Draw();
int GetID() const { return 4; }
int GetID() const { return WATER_RENDERER_BUMPMAPPED; }
const char* GetName() const { return "bumpmapped"; }

private:
void SetUniforms(); //! see useUniforms
Expand Down
2 changes: 0 additions & 2 deletions rts/Rendering/Env/DynWater.cpp
Expand Up @@ -370,8 +370,6 @@ void CDynWater::Draw()

void CDynWater::UpdateWater(CGame* game)
{
DeleteOldWater(this);

if ((!mapInfo->water.forceRendering && readmap->currMinHeight > 1.0f) || mapInfo->map.voidWater)
return;

Expand Down
11 changes: 6 additions & 5 deletions rts/Rendering/Env/DynWater.h
Expand Up @@ -14,11 +14,12 @@ class CDynWater : public CBaseWater
CDynWater(void);
~CDynWater(void);

virtual void Draw();
virtual void UpdateWater(CGame* game);
virtual void Update();
virtual void AddExplosion(const float3& pos, float strength, float size);
int GetID() const { return 2; }
void Draw();
void UpdateWater(CGame* game);
void Update();
void AddExplosion(const float3& pos, float strength, float size);
int GetID() const { return WATER_RENDERER_DYNAMIC; }
const char* GetName() const { return "dynamic"; }

private:
void DrawReflection(CGame* game);
Expand Down
3 changes: 2 additions & 1 deletion rts/Rendering/Env/RefractWater.h
Expand Up @@ -14,7 +14,8 @@ class CRefractWater : public CAdvWater
void LoadGfx();

void Draw();
int GetID() const { return 3; }
int GetID() const { return WATER_RENDERER_REFL_REFR; }
const char* GetName() const { return "reflective&refractive"; }

protected:
void SetupWaterDepthTex();
Expand Down

0 comments on commit d4d0ea3

Please sign in to comment.