CBaseWater* CBaseWater::GetWater(CBaseWater* old) { CBaseWater* water = NULL; const int configValue = configHandler.GetInt("ReflectiveWater",1); if(water==NULL && configValue==2 && GLEW_ARB_fragment_program && GLEW_ARB_texture_float && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB,"waterDyn.fp")) { try { water = SAFE_NEW CDynWater; } catch (content_error& e) { delete water; water = NULL; logOutput.Print("Loading Dynamic Water failed"); logOutput.Print("Error: %s", e.what()); } } if(water==NULL && configValue==4 && GLEW_ARB_shading_language_100) { try { water = SAFE_NEW CBumpWater; } catch (content_error& e) { delete water; water = NULL; logOutput.Print("Loading Bumpmapped Water failed"); logOutput.Print("Error: %s", e.what()); } } if(water==NULL && configValue==3 && GLEW_ARB_fragment_program && GLEW_ARB_texture_rectangle){ try { water = SAFE_NEW CRefractWater; } catch (content_error& e) { delete water; water = NULL; logOutput.Print("Loading Refractive Water failed"); logOutput.Print("Error: %s", e.what()); } } if(water==NULL && configValue!=0 && GLEW_ARB_fragment_program && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB,"water.fp")){ try { water = SAFE_NEW CAdvWater; } catch (content_error& e) { delete water; water = NULL; logOutput.Print("Loading Reflective Water failed"); logOutput.Print("Error: %s", e.what()); } } if(water==NULL) water = SAFE_NEW CBasicWater; water->oldwater=old; return water; }
CBaseWater* CBaseWater::GetWater() { if(GLEW_ARB_fragment_program && configHandler.GetInt("ReflectiveWater",3)==2 && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB,"waterDyn.fp") && GLEW_ARB_texture_float) return new CDynWater; else if(GLEW_ARB_fragment_program && configHandler.GetInt("ReflectiveWater",3)==3 && GLEW_ARB_texture_rectangle) return new CRefractWater; else if(GLEW_ARB_fragment_program && configHandler.GetInt("ReflectiveWater",3) && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB,"water.fp")) return new CAdvWater; else return new CBasicWater; }
CBaseWater* CBaseWater::GetWater() { CBaseWater* water = NULL; const int configValue = configHandler.GetInt("ReflectiveWater",1); if(configValue==2 && GLEW_ARB_fragment_program && GLEW_ARB_texture_float && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_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 (water) { return water; } } if(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()); } if (water) { return water; } } if(configValue!=0 && GLEW_ARB_fragment_program && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_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 (water) { return water; } } return new CBasicWater; }
CBaseSky* CBaseSky::GetSky() { if(!mapInfo->atmosphere.skyBox.empty()) return new CSkyBox("maps/" + mapInfo->atmosphere.skyBox); else if(GLEW_ARB_fragment_program && configHandler->Get("AdvSky",1) && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB,"clouds.fp")) return new CAdvSky(); else return new CBasicSky(); }
CBaseSky* CBaseSky::GetSky() { if(!readmap->skyBox.empty()) return new CSkyBox("maps/" + readmap->skyBox); else if(GLEW_ARB_fragment_program && configHandler.GetInt("AdvSky",1) && ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB,"clouds.fp")) return new CAdvSky(); else return new CBasicSky(); }
CShadowHandler::CShadowHandler(void) { const bool tmpFirstInstance = firstInstance; firstInstance = false; drawShadows = false; inShadowPass = false; showShadowMap = false; firstDraw = true; shadowTexture = 0; if (!tmpFirstInstance && !canUseShadows) { return; } const bool haveShadowExts = GLEW_ARB_vertex_program && GLEW_ARB_shadow && GLEW_ARB_depth_texture && GLEW_ARB_texture_env_combine; const int configValue = configHandler.Get("Shadows", 0); if (configValue < 0 || !haveShadowExts) { logOutput.Print("shadows disabled or required OpenGL extension missing"); return; } shadowMapSize = configHandler.Get("ShadowMapSize", DEFAULT_SHADOWMAPSIZE); if (tmpFirstInstance) { // this already checks for GLEW_ARB_fragment_program if (!ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB, "unit.fp")) { logOutput.Print("Your GFX card does not support the fragment programs needed for shadows"); return; } // this was previously set to true (redundantly since // it was actually never made false anywhere) if either // 1. (!GLEW_ARB_texture_env_crossbar && haveShadowExts) // 2. (!GLEW_ARB_shadow_ambient && GLEW_ARB_shadow) // but the non-FP result isn't nice anyway so just always // use the program if we are guaranteed of shadow support useFPShadows = true; if (!GLEW_ARB_shadow_ambient) { // can't use arbitrary texvals in case the depth comparison op fails (only 0) logOutput.Print("You are missing the \"ARB_shadow_ambient\" extension (this will probably make shadows darker than they should be)"); } } if (!InitDepthTarget()) { return; } if (tmpFirstInstance) { canUseShadows = true; } if (configValue == 0) { // free any resources allocated by InitDepthTarget() glDeleteTextures(1, &shadowTexture); shadowTexture = 0; return; // drawShadows is still false } drawShadows = true; }
CShadowHandler::CShadowHandler(void) { const bool tmpFirstInstance = firstInstance; firstInstance = false; drawShadows = false; inShadowPass = false; shadowTexture = 0; dummyColorTexture = 0; drawTerrainShadow = true; p17 = 0.0f; p18 = 0.0f; xmid = 0; ymid = 0; x1 = 0.0f; y1 = 0.0f; x2 = 0.0f; y2 = 0.0f; if (!tmpFirstInstance && !canUseShadows) { return; } const bool haveShadowExts = GLEW_ARB_vertex_program && GLEW_ARB_shadow && GLEW_ARB_depth_texture && GLEW_ARB_texture_env_combine; //! Shadows possible values: //! -1 : disable and don't try to initialize //! 0 : disable, but still check if the hardware is able to run them //! 1 : enable (full detail) //! 2 : enable (no terrain) const int configValue = configHandler->Get("Shadows", 0); if (configValue >= 2) drawTerrainShadow = false; if (configValue < 0 || !haveShadowExts) { logOutput.Print("shadows disabled or required OpenGL extension missing"); return; } shadowMapSize = configHandler->Get("ShadowMapSize", DEFAULT_SHADOWMAPSIZE); if (tmpFirstInstance) { // this already checks for GLEW_ARB_fragment_program if (!ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB, "ARB/units3o.fp")) { logOutput.Print("Your GFX card does not support the fragment programs needed for shadows"); return; } // this was previously set to true (redundantly since // it was actually never made false anywhere) if either // 1. (!GLEW_ARB_texture_env_crossbar && haveShadowExts) // 2. (!GLEW_ARB_shadow_ambient && GLEW_ARB_shadow) // but the non-FP result isn't nice anyway so just always // use the program if we are guaranteed of shadow support useFPShadows = true; if (!GLEW_ARB_shadow_ambient) { // can't use arbitrary texvals in case the depth comparison op fails (only 0) logOutput.Print("You are missing the \"ARB_shadow_ambient\" extension (this will probably make shadows darker than they should be)"); } } if (!InitDepthTarget()) { return; } if (tmpFirstInstance) { canUseShadows = true; } if (configValue == 0) { // free any resources allocated by InitDepthTarget() glDeleteTextures(1, &shadowTexture); shadowTexture = 0; glDeleteTextures(1, &dummyColorTexture); dummyColorTexture = 0; return; // drawShadows is still false } LoadShadowGenShaderProgs(); }
CShadowHandler::CShadowHandler(void): fb(0) { const bool tmpFirstInstance = firstInstance; firstInstance = false; drawShadows = false; inShadowPass = false; showShadowMap = false; firstDraw = true; shadowTexture = 0; if (!tmpFirstInstance && !canUseShadows) { return; } const int configValue = configHandler.GetInt("Shadows", 0); if (configValue < 0) { return; } shadowMapSize=configHandler.GetInt("ShadowMapSize",DEFAULT_SHADOWMAPSIZE); if (tmpFirstInstance) { if(!(GLEW_ARB_fragment_program && GLEW_ARB_fragment_program_shadow)){ logOutput.Print("You are missing an OpenGL extension needed to use shadowmaps (fragment_program_shadow)"); return; } if(!ProgramStringIsNative(GL_FRAGMENT_PROGRAM_ARB,"unit.fp")){ logOutput.Print("Your GFX card doesnt support the fragment programs needed to run in shadowed mode"); return; } if(!(GLEW_ARB_shadow && GLEW_ARB_depth_texture && GLEW_ARB_vertex_program && GLEW_ARB_texture_env_combine && GLEW_ARB_texture_env_crossbar)){ if(GLEW_ARB_shadow && GLEW_ARB_depth_texture && GLEW_ARB_vertex_program && GLEW_ARB_texture_env_combine && GLEW_ARB_fragment_program && GLEW_ARB_fragment_program_shadow){ //logOutput.Print("Using ARB_fragment_program_shadow"); useFPShadows=true; // FIXME -- always true } else { logOutput.Print("You are missing an OpenGL extension needed to use shadowmaps"); return; } } if(!GLEW_ARB_shadow_ambient){ if(GLEW_ARB_fragment_program && GLEW_ARB_fragment_program_shadow){ if(!useFPShadows){ //logOutput.Print("Using ARB_fragment_program_shadow"); } useFPShadows = true; // FIXME -- always true } else { logOutput.Print("You are missing the extension ARB_shadow_ambient, this will make shadows darker than they should be"); } } } if (!InitDepthTarget()) { return; } if (tmpFirstInstance) { canUseShadows = true; } if (configValue == 0) { // free any resources allocated by InitDepthTarget() delete fb; fb = NULL; glDeleteTextures(1, &shadowTexture); shadowTexture = 0; return; // drawShadows is still false } drawShadows = true; // useFPShadows = true; // FIXME -- why was this being forced? }
/* #define W_SIZE 4 #define WF_SIZE 4096 #define WH_SIZE 2048 */ CDynWater::CDynWater(void) { if (!FBO::IsSupported()) throw content_error("DynWater Error: missing FBO support"); lastWaveFrame=0; noWakeProjectiles=true; firstDraw=true; drawSolid=true; camPosBig=float3(2048,0,2048); refractSize=gu->viewSizeY>=1024 ? 1024:512; glGenTextures(1, &reflectTexture); glBindTexture(GL_TEXTURE_2D, reflectTexture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,512, 512, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0); glGenTextures(1, &refractTexture); glBindTexture(GL_TEXTURE_2D, refractTexture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,refractSize, refractSize, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0); glGenTextures(1, &detailNormalTex); glBindTexture(GL_TEXTURE_2D, detailNormalTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,256, 256, 0,GL_RGBA, GL_FLOAT, 0); glGenerateMipmapEXT(GL_TEXTURE_2D); float* temp=new float[1024*1024*4]; for(int y=0;y<64;++y){ for(int x=0;x<64;++x){ temp[(y*64+x)*4+0]=(sin(x*PI*2.0f/64.0f)) + (x<32 ? -1:1)*0.3f; temp[(y*64+x)*4+1]=temp[(y*64+x)*4+0]; temp[(y*64+x)*4+2]=(cos(x*PI*2.0f/64.0f)) + (x<32 ? 16-x:x-48)/16.0f*0.3f; temp[(y*64+x)*4+3]=0; } } glGenTextures(3, rawBumpTexture); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,64, 64, 0,GL_RGBA, GL_FLOAT, temp); CBitmap foam; if (!foam.Load(mapInfo->water.foamTexture)) throw content_error("Could not load foam from file " + mapInfo->water.foamTexture); if (count_bits_set(foam.xsize)!=1 || count_bits_set(foam.ysize)!=1) throw content_error("Foam texture not power of two!"); unsigned char* scrap=new unsigned char[foam.xsize*foam.ysize*4]; for(int a=0;a<foam.xsize*foam.ysize;++a) scrap[a]=foam.mem[a*4]; glGenTextures(1, &foamTex); glBindTexture(GL_TEXTURE_2D, foamTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); glBuildMipmaps(GL_TEXTURE_2D, GL_LUMINANCE,foam.xsize,foam.ysize, GL_LUMINANCE, GL_UNSIGNED_BYTE, scrap); delete[] scrap; if(ProgramStringIsNative(GL_VERTEX_PROGRAM_ARB,"waterDyn.vp")) waterVP=LoadVertexProgram("waterDyn.vp"); else waterVP=LoadVertexProgram("waterDynNT.vp"); waterFP=LoadFragmentProgram("waterDyn.fp"); waveFP=LoadFragmentProgram("waterDynWave.fp"); waveVP=LoadVertexProgram("waterDynWave.vp"); waveFP2=LoadFragmentProgram("waterDynWave2.fp"); waveVP2=LoadVertexProgram("waterDynWave2.vp"); waveNormalFP=LoadFragmentProgram("waterDynNormal.fp"); waveNormalVP=LoadVertexProgram("waterDynNormal.vp"); waveCopyHeightFP=LoadFragmentProgram("waterDynWave3.fp"); waveCopyHeightVP=LoadVertexProgram("waterDynWave3.vp"); dwGroundRefractVP=LoadVertexProgram("dwgroundrefract.vp"); dwGroundReflectIVP=LoadVertexProgram("dwgroundreflectinverted.vp"); dwDetailNormalFP=LoadFragmentProgram("dwDetailNormal.fp"); dwDetailNormalVP=LoadVertexProgram("dwDetailNormal.vp"); dwAddSplashFP=LoadFragmentProgram("dwAddSplash.fp"); dwAddSplashVP=LoadVertexProgram("dwAddSplash.vp"); waterSurfaceColor = mapInfo->water.surfaceColor; for(int y=0;y<1024;++y){ for(int x=0;x<1024;++x){ temp[(y*1024+x)*4+0]=0; temp[(y*1024+x)*4+1]=0; temp[(y*1024+x)*4+2]=0; temp[(y*1024+x)*4+3]=0; } } glGenTextures(1, &waveHeight32); glBindTexture(GL_TEXTURE_2D, waveHeight32); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F_ARB ,256, 256, 0,GL_RGBA, GL_FLOAT, temp); glGenTextures(1, &waveTex1); glBindTexture(GL_TEXTURE_2D, waveTex1); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp); for(int y=0;y<1024;++y){ for(int x=0;x<1024;++x){ //float dist=(x-500)*(x-500)+(y-450)*(y-450); temp[(y*1024+x)*4+0]=0;//max(0.0f,15-sqrt(dist));//sin(y*PI*2.0f/64.0f)*0.5f+0.5f; temp[(y*1024+x)*4+1]=0; temp[(y*1024+x)*4+2]=0; temp[(y*1024+x)*4+3]=0; } } glGenTextures(1, &waveTex2); glBindTexture(GL_TEXTURE_2D, waveTex2); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp); for(int y=0;y<1024;++y){ for(int x=0;x<1024;++x){ temp[(y*1024+x)*4+0]=0; temp[(y*1024+x)*4+1]=1; temp[(y*1024+x)*4+2]=0; temp[(y*1024+x)*4+3]=0; } } glGenTextures(1, &waveTex3); glBindTexture(GL_TEXTURE_2D, waveTex3); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,1024, 1024, 0,GL_RGBA, GL_FLOAT, temp); for(int y=0;y<64;++y){ float dy=y-31.5f; for(int x=0;x<64;++x){ float dx=x-31.5f; float dist=sqrt(dx*dx+dy*dy); temp[(y*64+x)*4+0]=std::max(0.0f,1-dist/30.f)*std::max(0.0f,1-dist/30.f); temp[(y*64+x)*4+1]=std::max(0.0f,1-dist/30.f); temp[(y*64+x)*4+2]=std::max(0.0f,1-dist/30.f)*std::max(0.0f,1-dist/30.f); temp[(y*64+x)*4+3]=0; } } glGenTextures(1, &splashTex); glBindTexture(GL_TEXTURE_2D, splashTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); //gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA32F_ARB ,64, 64, GL_RGBA, GL_FLOAT, temp); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,64, 64, 0,GL_RGBA, GL_FLOAT, temp); unsigned char temp2[]={0,0,0,0}; glGenTextures(1, &zeroTex); glBindTexture(GL_TEXTURE_2D, zeroTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,1, 1, 0,GL_RGBA, GL_UNSIGNED_BYTE, temp2); unsigned char temp3[]={0,255,0,0}; glGenTextures(1, &fixedUpTex); glBindTexture(GL_TEXTURE_2D, fixedUpTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,1, 1, 0,GL_RGBA, GL_UNSIGNED_BYTE, temp3); CBitmap bm; if (!bm.Load("bitmaps/boatshape.bmp")) throw content_error("Could not load boatshape from file bitmaps/boatshape.bmp"); for(int a=0;a<bm.xsize*bm.ysize;++a){ bm.mem[a*4+2]=bm.mem[a*4]; bm.mem[a*4+3]=bm.mem[a*4]; } boatShape=bm.CreateTexture(); CBitmap bm2; if (!bm.Load("bitmaps/hovershape.bmp")) throw content_error("Could not load hovershape from file bitmaps/hovershape.bmp"); for(int a=0;a<bm2.xsize*bm2.ysize;++a){ bm2.mem[a*4+2]=bm2.mem[a*4]; bm2.mem[a*4+3]=bm2.mem[a*4]; } hoverShape=bm2.CreateTexture(); delete[] temp; glGenFramebuffersEXT(1,&frameBuffer); reflectFBO.Bind(); reflectFBO.AttachTexture(reflectTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT); reflectFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT32, 512, 512); refractFBO.Bind(); refractFBO.AttachTexture(refractTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT); refractFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT32, refractSize, refractSize); FBO::Unbind(); if (!reflectFBO.IsValid() || !refractFBO.IsValid()) throw content_error("DynWater Error: Invalid FBO"); }
IWater* IWater::GetWater(IWater* currWaterRenderer, int nextWaterRendererMode) { static IWater baseWaterRenderer; IWater* nextWaterRenderer = NULL; if (currWaterRenderer != NULL) { assert(water == currWaterRenderer); if (currWaterRenderer->GetID() == nextWaterRendererMode) { if (nextWaterRendererMode == IWater::WATER_RENDERER_BASIC) { return currWaterRenderer; } } // note: rendering thread(s) can concurrently dereference the // <water> global, so they may not see destructed memory while // it is being reinstantiated through <currWaterRenderer> water = &baseWaterRenderer; // for BumpWater, this needs to happen before a new renderer // instance is created because its shaders must be recompiled // (delayed deletion will fail) delete currWaterRenderer; } if (nextWaterRendererMode < IWater::WATER_RENDERER_BASIC) { nextWaterRendererMode = configHandler->GetInt("ReflectiveWater"); } 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 (const content_error& ex) { delete nextWaterRenderer; nextWaterRenderer = NULL; LOG_L(L_ERROR, "Loading Dynamic Water failed, error: %s", ex.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 (const content_error& ex) { delete nextWaterRenderer; nextWaterRenderer = NULL; LOG_L(L_ERROR, "Loading Bumpmapped Water failed, error: %s", ex.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 (const content_error& ex) { delete nextWaterRenderer; nextWaterRenderer = NULL; LOG_L(L_ERROR, "Loading Refractive Water failed, error: %s", ex.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 (const content_error& ex) { delete nextWaterRenderer; nextWaterRenderer = NULL; LOG_L(L_ERROR, "Loading Reflective Water failed, error: %s", ex.what()); } } } break; } if (nextWaterRenderer == NULL) { nextWaterRenderer = new CBasicWater(); } configHandler->Set("ReflectiveWater", nextWaterRenderer->GetID()); return nextWaterRenderer; }