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; }