Beispiel #1
0
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;
}