Example #1
0
static void DrawRadialDisc()
{
	//! SAME ALGORITHM AS FOR WATER-PLANE IN BFGroundDrawer.cpp!
	const float xsize = (gs->mapx * SQUARE_SIZE) >> 2;
	const float ysize = (gs->mapy * SQUARE_SIZE) >> 2;

	CVertexArray* va = GetVertexArray();
	va->Initialize();

	const float alphainc = fastmath::PI2 / 32;
	float alpha, r1, r2;
	float3 p(0.0f, 0.0f, 0.0f);
	const float size = std::min(xsize, ysize);
	for (int n = 0; n < 4 ; ++n) {
		r1 = n*n * size;
		if (n == 3) {
			r2 = (n + 0.5) * (n + 0.5) * size;
		} else {
			r2 = (n + 1) * (n + 1) * size;
		}
		for (alpha = 0.0f; (alpha - fastmath::PI2) < alphainc; alpha += alphainc) {
			p.x = r1 * fastmath::sin(alpha) + 2 * xsize;
			p.z = r1 * fastmath::cos(alpha) + 2 * ysize;
			va->AddVertex0(p);
			p.x = r2 * fastmath::sin(alpha) + 2 * xsize;
			p.z = r2 * fastmath::cos(alpha) + 2 * ysize;
			va->AddVertex0(p);
		}
	}

	va->DrawArray0(GL_TRIANGLE_STRIP);
}
Example #2
0
static void DrawInfoText()
{
	// background
	CVertexArray* va = GetVertexArray();
	va->Initialize();
		va->AddVertex0(0.01f - 10 * globalRendering->pixelX, 0.02f - 10 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(0.01f - 10 * globalRendering->pixelX, 0.16f + 20 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(start_x - 0.05f + 10 * globalRendering->pixelX, 0.16f + 20 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(start_x - 0.05f + 10 * globalRendering->pixelX, 0.02f - 10 * globalRendering->pixelY, 0.0f);
	glColor4f(0.0f,0.0f,0.0f, 0.5f);
	va->DrawArray0(GL_QUADS);

	//print some infos (fps,gameframe,particles)
	font->SetTextColor(1,1,0.5f,0.8f);

	font->glFormat(0.01f, 0.02f, 1.0f, DBG_FONT_FLAGS, "FPS: %0.1f SimFPS: %0.1f SimFrame: %d Speed: %2.2f (%2.2f) Particles: %d (%d)",
	    globalRendering->FPS, gu->simFPS, gs->frameNum, gs->speedFactor, gs->wantedSpeedFactor, projectileHandler->syncedProjectiles.size() + projectileHandler->unsyncedProjectiles.size(), projectileHandler->currentParticles);

	// 16ms := 60fps := 30simFPS + 30drawFPS
	font->glFormat(0.01f, 0.07f, 0.7f, DBG_FONT_FLAGS, "avgFrame: %s%2.1fms\b avgDrawFrame: %s%2.1fms\b avgSimFrame: %s%2.1fms\b",
	   (gu->avgFrameTime     > 30) ? "\xff\xff\x01\x01" : "", gu->avgFrameTime,
	   (gu->avgDrawFrameTime > 16) ? "\xff\xff\x01\x01" : "", gu->avgDrawFrameTime,
	   (gu->avgSimFrameTime  > 16) ? "\xff\xff\x01\x01" : "", gu->avgSimFrameTime
	);

	const int2 pfsUpdates = pathManager->GetNumQueuedUpdates();
	const char* fmtString = "[%s-PFS] queued updates: %i %i";

	switch (pathManager->GetPathFinderType()) {
		case PFS_TYPE_DEFAULT: {
			font->glFormat(0.01f, 0.12f, 0.7f, DBG_FONT_FLAGS, fmtString, "DEFAULT", pfsUpdates.x, pfsUpdates.y);
		} break;
		case PFS_TYPE_QTPFS: {
			font->glFormat(0.01f, 0.12f, 0.7f, DBG_FONT_FLAGS, fmtString, "QT", pfsUpdates.x, pfsUpdates.y);
		} break;
	}

	SLuaInfo luaInfo = {0, 0, 0, 0};
	spring_lua_alloc_get_stats(&luaInfo);

	font->glFormat(
		0.01f, 0.15f, 0.7f, DBG_FONT_FLAGS,
		"Lua-allocated memory: %.1fMB (%.5uK allocs : %.5u usecs : %.1u states)",
		luaInfo.allocedBytes / 1024.0f / 1024.0f,
		luaInfo.numLuaAllocs / 1000,
		luaInfo.luaAllocTime,
		luaInfo.numLuaStates
	);
}
Example #3
0
static void defSurfaceSquare(const float3& center, float xsize, float zsize)
{
	// FIXME: terrain contouring
	const float3 p0 = center + float3(-xsize, 0.0f, -zsize);
	const float3 p1 = center + float3( xsize, 0.0f, -zsize);
	const float3 p2 = center + float3( xsize, 0.0f,  zsize);
	const float3 p3 = center + float3(-xsize, 0.0f,  zsize);

	CVertexArray* va = GetVertexArray();
	va->Initialize();
		va->AddVertex0(p0.x, CGround::GetHeightAboveWater(p0.x, p0.z, false), p0.z);
		va->AddVertex0(p1.x, CGround::GetHeightAboveWater(p1.x, p1.z, false), p1.z);
		va->AddVertex0(p2.x, CGround::GetHeightAboveWater(p2.x, p2.z, false), p2.z);
		va->AddVertex0(p3.x, CGround::GetHeightAboveWater(p3.x, p3.z, false), p3.z);
	va->DrawArray0(GL_LINE_LOOP);
}
Example #4
0
static void DrawThreadBarcode()
{
	const float maxHist_f = 4.0f;
	const spring_time curTime = spring_now();
	const spring_time maxHist = spring_secs(maxHist_f);
	auto& coreProf = profiler.profileCore;
	const auto numThreads = coreProf.size();

	const float drawArea[4] = {0.01f, 0.30f, (start_x / 2), 0.35f};

	// background
	CVertexArray* va = GetVertexArray();
	va->Initialize();
		va->AddVertex0(drawArea[0] - 10 * globalRendering->pixelX, drawArea[1] - 10 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(drawArea[0] - 10 * globalRendering->pixelX, drawArea[3] + 10 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(drawArea[2] + 10 * globalRendering->pixelX, drawArea[3] + 10 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(drawArea[2] + 10 * globalRendering->pixelX, drawArea[1] - 10 * globalRendering->pixelY, 0.0f);
	glColor4f(0.0f,0.0f,0.0f, 0.5f);
	va->DrawArray0(GL_QUADS);

	// title
	font->glFormat(drawArea[0], drawArea[3], 0.7f, FONT_TOP | DBG_FONT_FLAGS, "ThreadPool (%.0fsec)", maxHist_f);

	// bars
	glColor4f(1.0f,0.0f,0.0f, 0.6f);
	int i = 0;
	for (auto& frames: coreProf) {
		float drawArea2[4] = {drawArea[0], 0.f, drawArea[2], 0.f};
		drawArea2[1] = drawArea[1] + ((drawArea[3] - drawArea[1]) / numThreads) * i++;
		drawArea2[3] = drawArea[1] + ((drawArea[3] - drawArea[1]) / numThreads) * i - 4 * globalRendering->pixelY;
		DrawTimeSlice(frames, curTime, maxHist, drawArea2);
	}

	// feeder
	//const float y1 = 0.0f;
	//const float y2 = 0.1f * numThreads;
	//CVertexArray* va = GetVertexArray();
	va->Initialize();
		const float r = (curTime % maxHist).toSecsf() / maxHist_f;
		const float xf = drawArea[0] + r * (drawArea[2] - drawArea[0]);
		va->AddVertex0(xf, drawArea[1], 0.0f);
		va->AddVertex0(xf, drawArea[3], 0.0f);
		va->AddVertex0(xf + 5 * globalRendering->pixelX, drawArea[3], 0.0f);
		va->AddVertex0(xf + 5 * globalRendering->pixelX, drawArea[1], 0.0f);
	glColor3f(1.0f,0.0f,0.0f);
	va->DrawArray0(GL_QUADS);
}
Example #5
0
static void DrawTimeSlice(std::deque<TimeSlice>& frames, const spring_time curTime, const spring_time maxHist, const float drawArea[4])
{
	// remove old entries
	while (!frames.empty() && (curTime - frames.front().second) > maxHist) {
		frames.pop_front();
	}

	const float y1 = drawArea[1];
	const float y2 = drawArea[3];

	// render
	CVertexArray* va = GetVertexArray();
	va->Initialize();
	for (TimeSlice& ts: frames) {
		float x1 = (ts.first % maxHist).toSecsf() / maxHist.toSecsf();
		float x2 = (ts.second % maxHist).toSecsf() / maxHist.toSecsf();
		x2 = std::max(x1 + globalRendering->pixelX, x2);

		x1 = drawArea[0] + x1 * (drawArea[2] - drawArea[0]);
		x2 = drawArea[0] + x2 * (drawArea[2] - drawArea[0]);

		va->AddVertex0(x1, y1, 0.0f);
		va->AddVertex0(x1, y2, 0.0f);
		va->AddVertex0(x2, y2, 0.0f);
		va->AddVertex0(x2, y1, 0.0f);

		const float mx1 = x1 + 3 * globalRendering->pixelX;
		const float mx2 = x2 - 3 * globalRendering->pixelX;
		if (mx1 < mx2) {
			va->AddVertex0(mx1, y1 + 3 * globalRendering->pixelX, 0.0f);
			va->AddVertex0(mx1, y2 - 3 * globalRendering->pixelX, 0.0f);
			va->AddVertex0(mx2, y2 - 3 * globalRendering->pixelX, 0.0f);
			va->AddVertex0(mx2, y1 + 3 * globalRendering->pixelX, 0.0f);
		}
	}

	va->DrawArray0(GL_QUADS);
}
Example #6
0
/**
 *  Draws a trigonometric circle in 'resolution' steps.
 */
static void defSurfaceCircle(const float3& center, float radius, unsigned int res)
{
	CVertexArray* va = GetVertexArray();
	va->Initialize();
	for (unsigned int i = 0; i < res; ++i) {
		const float radians = math::TWOPI * (float)i / (float)res;
		float3 pos;
		pos.x = center.x + (fastmath::sin(radians) * radius);
		pos.z = center.z + (fastmath::cos(radians) * radius);
		pos.y = CGround::GetHeightAboveWater(pos.x, pos.z, false) + 5.0f;
		va->AddVertex0(pos);
	}
	va->DrawArray0(GL_LINE_LOOP);
}
Example #7
0
CBumpWater::CBumpWater()
	: CEventClient("[CBumpWater]", 271923, false)
{
	eventHandler.AddClient(this);

	// LOAD USER CONFIGS
	reflTexSize  = next_power_of_2(configHandler->GetInt("BumpWaterTexSizeReflection"));
	reflection   = configHandler->GetInt("BumpWaterReflection");
	refraction   = configHandler->GetInt("BumpWaterRefraction");
	anisotropy   = configHandler->GetFloat("BumpWaterAnisotropy");
	depthCopy    = configHandler->GetBool("BumpWaterUseDepthTexture");
	depthBits    = configHandler->GetInt("BumpWaterDepthBits");
	if ((depthBits == 24) && !globalRendering->support24bitDepthBuffers)
		depthBits = 16;
	blurRefl     = configHandler->GetBool("BumpWaterBlurReflection");
	shoreWaves   = (configHandler->GetBool("BumpWaterShoreWaves")) && mapInfo->water.shoreWaves;
	endlessOcean = (configHandler->GetBool("BumpWaterEndlessOcean")) && mapInfo->water.hasWaterPlane
	               && ((readmap->initMinHeight <= 0.0f) || (mapInfo->water.forceRendering));
	dynWaves     = (configHandler->GetBool("BumpWaterDynamicWaves")) && (mapInfo->water.numTiles>1);
	useUniforms  = (configHandler->GetBool("BumpWaterUseUniforms"));

	refractTexture = 0;
	reflectTexture = 0;

	// CHECK HARDWARE
	if (!globalRendering->haveGLSL) {
		throw content_error("["LOG_SECTION_BUMP_WATER"] your hardware/driver setup does not support GLSL");
	}

	shoreWaves = shoreWaves && (GLEW_EXT_framebuffer_object);
	dynWaves   = dynWaves && (GLEW_EXT_framebuffer_object && GLEW_ARB_imaging);


	// LOAD TEXTURES
	foamTexture   = LoadTexture(mapInfo->water.foamTexture);
	normalTexture = LoadTexture(mapInfo->water.normalTexture , anisotropy , &normalTextureX, &normalTextureY);

	//! caustic textures
	const vector<string>& causticNames = mapInfo->water.causticTextures;
	if (causticNames.size() <= 0) {
		throw content_error("["LOG_SECTION_BUMP_WATER"] no caustic textures");
	}
	for (int i = 0; i < (int)causticNames.size(); ++i) {
		caustTextures.push_back(LoadTexture(causticNames[i]));
	}

	// CHECK SHOREWAVES TEXTURE SIZE
	if (shoreWaves) {
		GLint maxw, maxh;
		glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA16F_ARB, 4096, 4096, 0, GL_RGBA, GL_FLOAT, NULL);
		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &maxw);
		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &maxh);
		if (gs->mapx>maxw || gs->mapy>maxh) {
			shoreWaves = false;
			LOG_L(L_WARNING, "Can not display shorewaves (map too large)!");
		}
	}


	// SHOREWAVES
	if (shoreWaves) {
		waveRandTexture = LoadTexture( "bitmaps/shorewaverand.png" );

		glGenTextures(1, &coastTexture);
		glBindTexture(GL_TEXTURE_2D, coastTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		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_MAG_FILTER, GL_LINEAR);
		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, gs->mapx, gs->mapy, 0, GL_RGBA, GL_FLOAT, NULL);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, gs->mapx, gs->mapy, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
		//glGenerateMipmapEXT(GL_TEXTURE_2D);


		{
			blurShader = shaderHandler->CreateProgramObject("[BumpWater]", "CoastBlurShader", false);
			blurShader->AttachShaderObject(shaderHandler->CreateShaderObject("GLSL/bumpWaterCoastBlurFS.glsl", "", GL_FRAGMENT_SHADER));
			blurShader->Link();

			if (!blurShader->IsValid()) {
				const char* fmt = "shorewaves-shader compilation error: %s";
				const char* log = (blurShader->GetLog()).c_str();

				LOG_L(L_ERROR, fmt, log);

				//! string size is limited with content_error()
				throw content_error(string("["LOG_SECTION_BUMP_WATER"] shorewaves-shader compilation error!"));
			}

			blurShader->SetUniformLocation("tex0"); // idx 0
			blurShader->SetUniformLocation("tex1"); // idx 1
			blurShader->Enable();
			blurShader->SetUniform1i(0, 0);
			blurShader->SetUniform1i(1, 1);
			blurShader->Disable();
			blurShader->Validate();

			if (!blurShader->IsValid()) {
				const char* fmt = "shorewaves-shader validation error: %s";
				const char* log = (blurShader->GetLog()).c_str();

				LOG_L(L_ERROR, fmt, log);
				throw content_error(string("["LOG_SECTION_BUMP_WATER"] shorewaves-shader validation error!"));
			}
		}


		coastFBO.reloadOnAltTab = true;
		coastFBO.Bind();
		coastFBO.AttachTexture(coastTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT);

		if (coastFBO.CheckStatus("BUMPWATER(Coastmap)")) {
			//! initialize texture
			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
			glClear(GL_COLOR_BUFFER_BIT);

			//! fill with current heightmap/coastmap
			UnsyncedHeightMapUpdate(SRectangle(0, 0, gs->mapx, gs->mapy));
			UploadCoastline(true);
			UpdateCoastmap();
		} else
			shoreWaves = false;

		if (shoreWaves)
			eventHandler.InsertEvent(this, "UnsyncedHeightMapUpdate");
		
		//coastFBO.Unbind(); // gets done below
	}


	// CREATE TEXTURES
	if ((refraction > 0) || depthCopy) {
		//! ATIs do not have GLSL support for texrects
		screenTextureX = globalRendering->viewSizeX;
		screenTextureY = globalRendering->viewSizeY;
		if (GLEW_ARB_texture_rectangle && !globalRendering->atiHacks) {
			target = GL_TEXTURE_RECTANGLE_ARB;
		} else {
			target = GL_TEXTURE_2D;
			if (!globalRendering->supportNPOTs) {
				screenTextureX = next_power_of_2(globalRendering->viewSizeX);
				screenTextureY = next_power_of_2(globalRendering->viewSizeY);
			}
		}
	}

	if (refraction > 0) {
		//! CREATE REFRACTION TEXTURE
		glGenTextures(1, &refractTexture);
		glBindTexture(target, refractTexture);
		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		if (GLEW_EXT_texture_edge_clamp) {
			glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		} else {
			glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP);
		}
		glTexImage2D(target, 0, GL_RGBA8, screenTextureX, screenTextureY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	}

	if (reflection > 0) {
		//! CREATE REFLECTION TEXTURE
		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);
		if (GLEW_EXT_texture_edge_clamp) {
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		} else {
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, reflTexSize, reflTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	}

	if (depthCopy) {
		//! CREATE DEPTH TEXTURE
		glGenTextures(1, &depthTexture);
		glBindTexture(target, depthTexture);
		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		GLuint depthFormat = GL_DEPTH_COMPONENT;
		switch (globalRendering->depthBufferBits) { // use same depth as screen framebuffer
			case 16: depthFormat = GL_DEPTH_COMPONENT16; break;
			case 24: if (!globalRendering->atiHacks) { depthFormat = GL_DEPTH_COMPONENT24; break; } // ATIs fall through and use 32bit!
			default: depthFormat = GL_DEPTH_COMPONENT32; break;
		}
		glTexImage2D(target, 0, depthFormat, screenTextureX, screenTextureY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	}

	if (dynWaves) {
		//! SETUP DYNAMIC WAVES
		tileOffsets = new unsigned char[mapInfo->water.numTiles * mapInfo->water.numTiles];

		normalTexture2 = normalTexture;
		glBindTexture(GL_TEXTURE_2D, normalTexture2);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0.0);

		glGenTextures(1, &normalTexture);
		glBindTexture(GL_TEXTURE_2D, normalTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		if (anisotropy > 0.0f) {
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, normalTextureX, normalTextureY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
		glGenerateMipmapEXT(GL_TEXTURE_2D);
	}

	// CREATE FBOs
	if (GLEW_EXT_framebuffer_object) {
		GLuint depthRBOFormat = GL_DEPTH_COMPONENT;
		switch (depthBits) {
			case 16: depthRBOFormat = GL_DEPTH_COMPONENT16; break;
			case 24: depthRBOFormat = GL_DEPTH_COMPONENT24; break;
			case 32: depthRBOFormat = GL_DEPTH_COMPONENT32; break;
		}

		if (reflection>0) {
			reflectFBO.Bind();
			reflectFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, depthRBOFormat, reflTexSize, reflTexSize);
			reflectFBO.AttachTexture(reflectTexture);
		}

		if (refraction>0) {
			refractFBO.Bind();
			refractFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, depthRBOFormat, screenTextureX, screenTextureY);
			refractFBO.AttachTexture(refractTexture,target);
		}

		if (!reflectFBO.CheckStatus("BUMPWATER(reflection)")) {
			reflection = 0;
		}
		if (!refractFBO.CheckStatus("BUMPWATER(refraction)")) {
			refraction = 0;
		}

		if (dynWaves) {
			dynWavesFBO.reloadOnAltTab = true;
			dynWavesFBO.Bind();
			dynWavesFBO.AttachTexture(normalTexture);
			if (dynWavesFBO.CheckStatus("BUMPWATER(DynWaves)")) {
				UpdateDynWaves(true); //! initialize
			}
		}
		FBO::Unbind();
	}


	/*
	 * DEFINE SOME SHADER RUNTIME CONSTANTS
	 * (I do not use Uniforms for that, because the GLSL compiler can not
	 * optimize those!)
	 */
	string definitions;
	if (reflection>0) definitions += "#define opt_reflection\n";
	if (refraction>0) definitions += "#define opt_refraction\n";
	if (shoreWaves)   definitions += "#define opt_shorewaves\n";
	if (depthCopy)    definitions += "#define opt_depth\n";
	if (blurRefl)     definitions += "#define opt_blurreflection\n";
	if (endlessOcean) definitions += "#define opt_endlessocean\n";
	if (target == GL_TEXTURE_RECTANGLE_ARB) definitions += "#define opt_texrect\n";

	GLSLDefineConstf3(definitions, "MapMid",                    float3(readmap->width * SQUARE_SIZE * 0.5f, 0.0f, readmap->height * SQUARE_SIZE * 0.5f) );
	GLSLDefineConstf2(definitions, "ScreenInverse",             1.0f / globalRendering->viewSizeX, 1.0f / globalRendering->viewSizeY );
	GLSLDefineConstf2(definitions, "ScreenTextureSizeInverse",  1.0f / screenTextureX, 1.0f / screenTextureY );
	GLSLDefineConstf2(definitions, "ViewPos",                   globalRendering->viewPosX, globalRendering->viewPosY );

	if (useUniforms) {
		SetupUniforms(definitions);
	} else {
		GLSLDefineConstf4(definitions, "SurfaceColor",   mapInfo->water.surfaceColor*0.4, mapInfo->water.surfaceAlpha );
		GLSLDefineConstf4(definitions, "PlaneColor",     mapInfo->water.planeColor*0.4, mapInfo->water.surfaceAlpha );
		GLSLDefineConstf3(definitions, "DiffuseColor",   mapInfo->water.diffuseColor);
		GLSLDefineConstf3(definitions, "SpecularColor",  mapInfo->water.specularColor);
		GLSLDefineConstf1(definitions, "SpecularPower",  mapInfo->water.specularPower);
		GLSLDefineConstf1(definitions, "SpecularFactor", mapInfo->water.specularFactor);
		GLSLDefineConstf1(definitions, "AmbientFactor",  mapInfo->water.ambientFactor);
		GLSLDefineConstf1(definitions, "DiffuseFactor",  mapInfo->water.diffuseFactor * 15.0f);
		GLSLDefineConstf3(definitions, "SunDir",         sky->GetLight()->GetLightDir()); // FIXME: not a constant
		GLSLDefineConstf1(definitions, "FresnelMin",     mapInfo->water.fresnelMin);
		GLSLDefineConstf1(definitions, "FresnelMax",     mapInfo->water.fresnelMax);
		GLSLDefineConstf1(definitions, "FresnelPower",   mapInfo->water.fresnelPower);
		GLSLDefineConstf1(definitions, "ReflDistortion", mapInfo->water.reflDistortion);
		GLSLDefineConstf2(definitions, "BlurBase",       0.0f, mapInfo->water.blurBase / globalRendering->viewSizeY);
		GLSLDefineConstf1(definitions, "BlurExponent",   mapInfo->water.blurExponent);
		GLSLDefineConstf1(definitions, "PerlinStartFreq",  mapInfo->water.perlinStartFreq);
		GLSLDefineConstf1(definitions, "PerlinLacunarity", mapInfo->water.perlinLacunarity);
		GLSLDefineConstf1(definitions, "PerlinAmp",        mapInfo->water.perlinAmplitude);
		GLSLDefineConstf1(definitions, "WindSpeed",        mapInfo->water.windSpeed);
	}

	{
		const int mapX = readmap->width  * SQUARE_SIZE;
		const int mapZ = readmap->height * SQUARE_SIZE;
		const float shadingX = (float)gs->mapx / gs->pwr2mapx;
		const float shadingZ = (float)gs->mapy / gs->pwr2mapy;
		const float scaleX = (mapX > mapZ) ? (readmap->height/64)/16.0f * (float)mapX/mapZ : (readmap->width/64)/16.0f;
		const float scaleZ = (mapX > mapZ) ? (readmap->height/64)/16.0f : (readmap->width/64)/16.0f * (float)mapZ/mapX;
		GLSLDefineConst4f(definitions, "TexGenPlane", 1.0f/mapX, 1.0f/mapZ, scaleX/mapX, scaleZ/mapZ);
		GLSLDefineConst4f(definitions, "ShadingPlane", shadingX/mapX, shadingZ/mapZ, shadingX, shadingZ);
	}



	// LOAD SHADERS
	{
		waterShader = shaderHandler->CreateProgramObject("[BumpWater]", "WaterShader", false);
		waterShader->AttachShaderObject(shaderHandler->CreateShaderObject("GLSL/bumpWaterVS.glsl", definitions, GL_VERTEX_SHADER));
		waterShader->AttachShaderObject(shaderHandler->CreateShaderObject("GLSL/bumpWaterFS.glsl", definitions, GL_FRAGMENT_SHADER));
		waterShader->Link();
		waterShader->SetUniformLocation("eyePos");      // idx  0
		waterShader->SetUniformLocation("frame");       // idx  1
		waterShader->SetUniformLocation("normalmap");   // idx  2
		waterShader->SetUniformLocation("heightmap");   // idx  3
		waterShader->SetUniformLocation("caustic");     // idx  4
		waterShader->SetUniformLocation("foam");        // idx  5
		waterShader->SetUniformLocation("reflection");  // idx  6
		waterShader->SetUniformLocation("refraction");  // idx  7
		waterShader->SetUniformLocation("depthmap");    // idx  8
		waterShader->SetUniformLocation("coastmap");    // idx  9
		waterShader->SetUniformLocation("waverand");    // idx 10

		if (!waterShader->IsValid()) {
			const char* fmt = "water-shader compilation error: %s";
			const char* log = (waterShader->GetLog()).c_str();
			LOG_L(L_ERROR, fmt, log);
			throw content_error(string("["LOG_SECTION_BUMP_WATER"] water-shader compilation error!"));
		}

		if (useUniforms) {
			GetUniformLocations(waterShader);
		}

		// BIND TEXTURE UNIFORMS
		// NOTE: ATI shader validation code is stricter wrt. state,
		// so postpone the call until all texture uniforms are set
		waterShader->Enable();
		waterShader->SetUniform1i( 2, 0);
		waterShader->SetUniform1i( 3, 1);
		waterShader->SetUniform1i( 4, 2);
		waterShader->SetUniform1i( 5, 3);
		waterShader->SetUniform1i( 6, 4);
		waterShader->SetUniform1i( 7, 5);
		waterShader->SetUniform1i( 8, 7);
		waterShader->SetUniform1i( 9, 6);
		waterShader->SetUniform1i(10, 8);
		waterShader->Disable();
		waterShader->Validate();

		if (!waterShader->IsValid()) {
			const char* fmt = "water-shader validation error: %s";
			const char* log = (waterShader->GetLog()).c_str();

			LOG_L(L_ERROR, fmt, log);
			throw content_error(string("["LOG_SECTION_BUMP_WATER"] water-shader validation error!"));
		}
	}


	// CREATE DISPLAYLIST
	displayList = glGenLists(1);
	glNewList(displayList, GL_COMPILE);
	if (endlessOcean) {
		DrawRadialDisc();
	} else {
		const int mapX = readmap->width  * SQUARE_SIZE;
		const int mapZ = readmap->height * SQUARE_SIZE;
		CVertexArray* va = GetVertexArray();
		va->Initialize();
		for (int z = 0; z < 9; z++) {
			for (int x = 0; x < 10; x++) {
				for (int zs = 0; zs <= 1; zs++) {
					va->AddVertex0(float3(x*(mapX/9.0f), 0.0f, (z + zs)*(mapZ/9.0f)));
				}
			}
			va->EndStrip();
		}
		va->DrawArray0(GL_TRIANGLE_STRIP);
	}
	glEndList();

/*
	windndir = wind.GetCurrentDirection();
	windStrength = (smoothstep(0.0f, 12.0f, wind.GetCurrentStrength()) * 0.5f + 4.0f);
	windVec = windndir * windStrength;
*/
	windVec = float3(20.0, 0.0, 20.0);

	occlusionQuery = 0;
	occlusionQueryResult = GL_TRUE;
	wasLastFrameVisible = true;
	bool useOcclQuery  = (configHandler->GetBool("BumpWaterOcclusionQuery"));
	if (useOcclQuery && GLEW_ARB_occlusion_query && (refraction < 2)) { //! in the case of a separate refraction pass, there isn't enough time for a occlusion query
		GLint bitsSupported;
		glGetQueryiv(GL_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS, &bitsSupported);
		if (bitsSupported > 0) {
			glGenQueries(1, &occlusionQuery);
		}
	}

	if (refraction > 1) {
		drawSolid = true;
	}
}
Example #8
0
void CEndGameBox::Draw()
{
	if (!graphTex) {
		graphTex = bm.CreateTexture();
	}

	if (!enabled) {
		return;
	}

	float mx = MouseX(mouse->lastx);
	float my = MouseY(mouse->lasty);

	glDisable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);

	// Large Box
	glColor4f(0.2f, 0.2f, 0.2f, guiAlpha);
	DrawBox(box);

	glColor4f(0.2f, 0.2f, 0.7f, guiAlpha);
	if (dispMode == 0) {
		DrawBox(box + playerBox);
	} else if (dispMode == 1) {
		DrawBox(box + sumBox);
	} else {
		DrawBox(box + difBox);
	}

	if (InBox(mx, my, box+exitBox)) {
		glColor4f(0.7f, 0.2f, 0.2f, guiAlpha);
		DrawBox(box + exitBox);
	}
	if (InBox(mx,my,box+playerBox)) {
		glColor4f(0.7f, 0.2f, 0.2f, guiAlpha);
		DrawBox(box + playerBox);
	}
	if (InBox(mx,my,box+sumBox)) {
		glColor4f(0.7f, 0.2f, 0.2f, guiAlpha);
		DrawBox(box + sumBox);
	}
	if (InBox(mx,my,box+difBox)) {
		glColor4f(0.7f, 0.2f, 0.2f, guiAlpha);
		DrawBox(box + difBox);
	}

	glEnable(GL_TEXTURE_2D);
	glColor4f(1, 1, 1, 0.8f);
	font->glPrint(box.x1 + exitBox.x1   + 0.025f, box.y1 + exitBox.y1   + 0.005f, 1.0f, FONT_SCALE | FONT_NORM, "Exit");
	font->glPrint(box.x1 + playerBox.x1 + 0.015f, box.y1 + playerBox.y1 + 0.005f, 0.7f, FONT_SCALE | FONT_NORM, "Player stats");
	font->glPrint(box.x1 + sumBox.x1    + 0.015f, box.y1 + sumBox.y1    + 0.005f, 0.7f, FONT_SCALE | FONT_NORM, "Team stats");
	font->glPrint(box.x1 + difBox.x1    + 0.015f, box.y1 + difBox.y1    + 0.005f, 0.7f, FONT_SCALE | FONT_NORM, "Team delta stats");

	if (winners.empty()) {
		font->glPrint(box.x1 + 0.25f, box.y1 + 0.65f, 1.0f, FONT_SCALE | FONT_NORM, "Game result was undecided");
	} else {
		std::stringstream winnersText;
		std::stringstream winnersList;

		// myPlayingAllyTeam is >= 0 iff we ever joined a team
		const bool neverPlayed = (gu->myPlayingAllyTeam < 0);
		      bool playedAndWon = false;

		for (unsigned int i = 0; i < winners.size(); i++) {
			const int winnerAllyTeam = winners[i];

			if (!neverPlayed && winnerAllyTeam == gu->myPlayingAllyTeam) {
				// we actually played and won!
				playedAndWon = true; break;
			}

			winnersList << (((i > 0)? ((i < (winners.size() - 1))? ", ": " and "): ""));
			winnersList << winnerAllyTeam;
		}

		if (neverPlayed) {
			winnersText << "Game Over! Ally-team(s) ";
			winnersText << winnersList.str() << " won!";

			font->glPrint(box.x1 + 0.25f, box.y1 + 0.65f, 1.0f, FONT_SCALE | FONT_NORM, (winnersText.str()).c_str());
		} else {
			winnersText.str("");
			winnersText << "Game Over! Your ally-team ";
			winnersText << (playedAndWon? "won!": "lost!");
			font->glPrint(box.x1 + 0.25f, box.y1 + 0.65f, 1.0f, FONT_SCALE | FONT_NORM, (winnersText.str()).c_str());
		}
	}

	if (gs->frameNum <= 0) {
		return;
	}

	if (dispMode == 0) {
		float xpos = 0.01f;

		std::string headers[] = {"Name", "MC/m", "MP/m", "KP/m", "Cmds/m", "ACS"};

		for (int a = 0; a < 6; ++a) {
			font->glPrint(box.x1 + xpos, box.y1 + 0.55f, 0.8f, FONT_SCALE | FONT_NORM,headers[a].c_str());
			xpos += 0.1f;
		}

		float ypos = 0.5f;
		for (int a = 0; a < playerHandler->ActivePlayers(); ++a) {
			const CPlayer* p = playerHandler->Player(a);
			const PlayerStatistics& pStats = p->currentStats;
			char values[6][100];

			SNPRINTF(values[0], 100, "%s", p->name.c_str());
			if (game->totalGameTime>0){ //prevent div zero
				SNPRINTF(values[1], 100, "%i", int(pStats.mouseClicks * 60 / game->totalGameTime));
				SNPRINTF(values[2], 100, "%i", int(pStats.mousePixels * 60 / game->totalGameTime));
				SNPRINTF(values[3], 100, "%i", int(pStats.keyPresses  * 60 / game->totalGameTime));
				SNPRINTF(values[4], 100, "%i", int(pStats.numCommands * 60 / game->totalGameTime));
			}else{
				for(int i=1; i<5; i++)
					SNPRINTF(values[i], 100, "%i", 0);
			}
			SNPRINTF(values[5], 100, "%i",
				(pStats.numCommands != 0)?
				(pStats.unitCommands / pStats.numCommands):
				(0));

			float xpos = 0.01f;
			for (int a = 0; a < 6; ++a) {
				font->glPrint(box.x1 + xpos, box.y1 + ypos, 0.8f, FONT_SCALE | FONT_NORM, values[a]);
				xpos += 0.1f;
			}

			ypos -= 0.02f;
		}
	} else {
		if (stats.empty()) {
			FillTeamStats();
		}

		glBindTexture(GL_TEXTURE_2D, graphTex);
		CVertexArray* va=GetVertexArray();
		va->Initialize();

		va->AddVertexT(float3(box.x1+0.15f, box.y1+0.08f, 0), 0, 0);
		va->AddVertexT(float3(box.x1+0.69f, box.y1+0.08f, 0), 4, 0);
		va->AddVertexT(float3(box.x1+0.69f, box.y1+0.62f, 0), 4, 4);
		va->AddVertexT(float3(box.x1+0.15f, box.y1+0.62f, 0), 0, 4);

		va->DrawArrayT(GL_QUADS);

		if ((mx > box.x1 + 0.01f) && (mx < box.x1 + 0.12f) &&
		    (my < box.y1 + 0.57f) && (my > box.y1 + 0.571f - (stats.size() * 0.02f))) {
			const int sel = (int) math::floor(50 * -(my - box.y1 - 0.57f));

			glColor4f(0.7f, 0.2f, 0.2f, guiAlpha);
			glDisable(GL_TEXTURE_2D);
			CVertexArray* va = GetVertexArray();
			va->Initialize();

			va->AddVertex0(float3(box.x1 + 0.01f, box.y1 + 0.55f - (sel * 0.02f)         , 0));
			va->AddVertex0(float3(box.x1 + 0.01f, box.y1 + 0.55f - (sel * 0.02f) + 0.02f , 0));
			va->AddVertex0(float3(box.x1 + 0.12f, box.y1 + 0.55f - (sel * 0.02f) + 0.02f , 0));
			va->AddVertex0(float3(box.x1 + 0.12f, box.y1 + 0.55f - (sel * 0.02f)         , 0));

			va->DrawArray0(GL_QUADS);
			glEnable(GL_TEXTURE_2D);
			glColor4f(1, 1, 1, 0.8f);
		}
		float ypos = 0.55f;
		for (size_t a = 0; a < stats.size(); ++a) {
			font->glPrint(box.x1 + 0.01f, box.y1 + ypos, 0.8f, FONT_SCALE | FONT_NORM, stats[a].name);
			ypos -= 0.02f;
		}
		float maxy = 1;

		if (dispMode == 1) {
			maxy = std::max(stats[stat1].max,    (stat2 != -1) ? stats[stat2].max    : 0);
		} else {
			maxy = std::max(stats[stat1].maxdif, (stat2 != -1) ? stats[stat2].maxdif : 0) / TeamStatistics::statsPeriod;
		}

		int numPoints = stats[0].values[0].size();

		for (int a = 0; a < 5; ++a) {
			font->glPrint(box.x1 + 0.12f, box.y1 + 0.07f + (a * 0.135f), 0.8f, FONT_SCALE | FONT_NORM,
			                FloatToSmallString(maxy * 0.25f * a));
			font->glFormat(box.x1 + 0.135f + (a * 0.135f), box.y1 + 0.057f, 0.8f, FONT_SCALE | FONT_NORM, "%02i:%02i",
			                (int) (a * 0.25f * numPoints * TeamStatistics::statsPeriod / 60),
			                (int) (a * 0.25f * (numPoints - 1) * TeamStatistics::statsPeriod) % 60);
		}

		font->glPrint(box.x1 + 0.55f, box.y1 + 0.65f, 0.8f, FONT_SCALE | FONT_NORM, stats[stat1].name);
		font->glPrint(box.x1 + 0.55f, box.y1 + 0.63f, 0.8f, FONT_SCALE | FONT_NORM, (stat2 != -1) ? stats[stat2].name : "");

		glDisable(GL_TEXTURE_2D);
		glBegin(GL_LINES);
				glVertex3f(box.x1+0.50f, box.y1+0.66f, 0);
				glVertex3f(box.x1+0.55f, box.y1+0.66f, 0);
		glEnd();

		glLineStipple(3, 0x5555);
		glEnable(GL_LINE_STIPPLE);
		glBegin(GL_LINES);
				glVertex3f(box.x1 + 0.50f, box.y1 + 0.64f, 0.0f);
				glVertex3f(box.x1 + 0.55f, box.y1 + 0.64f, 0.0f);
		glEnd();
		glDisable(GL_LINE_STIPPLE);

		const float scalex = 0.54f / std::max(1.0f, numPoints - 1.0f);
		const float scaley = 0.54f / maxy;

		for (int team = 0; team < teamHandler->ActiveTeams(); team++) {
			const CTeam* pteam = teamHandler->Team(team);

			if (pteam->gaia) {
				continue;
			}

			glColor4ubv(pteam->color);

			glBegin(GL_LINE_STRIP);
			for (int a = 0; a < numPoints; ++a) {
				float value = 0.0f;

				if (dispMode == 1) {
					value = stats[stat1].values[team][a];
				} else if (a > 0) {
					value = (stats[stat1].values[team][a] - stats[stat1].values[team][a - 1]) / TeamStatistics::statsPeriod;
				}

				glVertex3f(box.x1 + 0.15f + a * scalex, box.y1 + 0.08f + value * scaley, 0.0f);
			}
			glEnd();

			if (stat2 != -1) {
				glLineStipple(3, 0x5555);
				glEnable(GL_LINE_STIPPLE);

				glBegin(GL_LINE_STRIP);
				for (int a = 0; a < numPoints; ++a) {
					float value = 0;
					if (dispMode == 1) {
						value = stats[stat2].values[team][a];
					} else if (a > 0) {
						value = (stats[stat2].values[team][a]-stats[stat2].values[team][a-1]) / TeamStatistics::statsPeriod;
					}

					glVertex3f(box.x1+0.15f+a*scalex, box.y1+0.08f+value*scaley, 0);
				}
				glEnd();

				glDisable(GL_LINE_STIPPLE);
			}
		}
	}
}
Example #9
0
void ProfileDrawer::Draw()
{
	GML_STDMUTEX_LOCK_NOPROF(time); // Draw

	// draw the background of the window
	glDisable(GL_TEXTURE_2D);
	glColor4f(0.0f, 0.0f, 0.5f, 0.5f);
	if(!profiler.profile.empty()){
		glBegin(GL_TRIANGLE_STRIP);
		glVertex3f(start_x, end_y,                                      0);
		glVertex3f(end_x,   end_y,                                      0);
		glVertex3f(start_x, end_y-profiler.profile.size()*0.024f-0.01f, 0);
		glVertex3f(end_x,   end_y-profiler.profile.size()*0.024f-0.01f, 0);
		glEnd();
	}

	std::map<std::string, CTimeProfiler::TimeRecord>::iterator pi;

	// draw the textual info (total-time, short-time percentual time, timer-name)
	int y = 0;
	font->Begin();
	for (pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi, ++y) {
#if GML_MUTEX_PROFILER
		if (pi->first.size()<5 || pi->first.substr(pi->first.size()-5,5).compare("Mutex")!=0) { --y; continue; }
		const float fStartY = start_y - y * 0.020f;
#else
		const float fStartY = start_y - y * 0.024f;
#endif
		const float s = ((float)pi->second.total) / 1000.0f;
		const float p = pi->second.percent * 100;
		float fStartX = start_x + 0.005f + 0.015f + 0.005f;

		// print total-time running since application start
		fStartX += 0.09f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM | FONT_RIGHT, "%.2fs", s);

		// print percent of CPU time used within the last 500ms
		fStartX += 0.08f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM | FONT_RIGHT, "%.2f%%", p);

		// print timer name
		fStartX += 0.01f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM, "%s", pi->first.c_str());
	}
	font->End();

	// draw the Timer selection boxes
	glPushMatrix();
	glTranslatef(start_x + 0.005f, start_y, 0);
	glScalef(0.015f, 0.02f, 0.02f);
	for (pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi){
		glColorf3((float3)pi->second.color);
		glBegin(GL_QUADS);
		glVertex3f(0,0,0);
		glVertex3f(1,0,0);
		glVertex3f(1,1,0);
		glVertex3f(0,1,0);
		glEnd();
		// draw the 'graph view disabled' cross
		if (!pi->second.showGraph) {
			glColor3f(1,0,0);
			glBegin(GL_LINES);
			glVertex3f(0,0,0);
			glVertex3f(1,1,0);
			glVertex3f(1,0,0);
			glVertex3f(0,1,0);
			glEnd();
		}
		glTranslatef(0,-1.2f,0);
	}
	glPopMatrix();

	// draw the graph
	for (pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi) {
		if (!pi->second.showGraph) {
			continue;
		}
		CVertexArray* va = GetVertexArray();
		va->Initialize();
		const float steps_x = (end_x - start_x) / CTimeProfiler::TimeRecord::frames_size;
		for (size_t a=0; a < CTimeProfiler::TimeRecord::frames_size; ++a) {
			// profile runtime; eg 0.5f means: uses 50% of a CPU (during that frame)
			// This may be more then 1.0f, in case an operation
			// which ran over many frames, ended in this one.
			const float p = ((float)pi->second.frames[a]) / 1000.0f * GAME_SPEED;
			const float x = start_x + (a * steps_x);
			const float y = 0.02f + (p * 0.4f);
			va->AddVertex0(float3(x, y, 0.0f));
		}
		glColorf3((float3)pi->second.color);
		va->DrawArray0(GL_LINE_STRIP);
	}
	glEnable(GL_TEXTURE_2D);
}
Example #10
0
static void DrawProfiler()
{
	font->SetTextColor(1,1,1,1);
	CVertexArray* va  = GetVertexArray();
	CVertexArray* va2 = GetVertexArray();

	// draw the background of the window
	if(!profiler.profile.empty()){
		va->Initialize();
			va->AddVertex0(start_x, end_y,                                      0);
			va->AddVertex0(end_x,   end_y,                                      0);
			va->AddVertex0(start_x, end_y-profiler.profile.size()*0.024f-0.01f, 0);
			va->AddVertex0(end_x,   end_y-profiler.profile.size()*0.024f-0.01f, 0);
		glColor4f(0.0f, 0.0f, 0.5f, 0.5f);
		va->DrawArray0(GL_TRIANGLE_STRIP);
	}

	std::map<std::string, CTimeProfiler::TimeRecord>::iterator pi;

	// draw the textual info (total-time, short-time percentual time, timer-name)
	int y = 0;
	for (pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi, ++y) {
		const float fStartY = start_y - y * 0.024f;
		float fStartX = start_x + 0.005f + 0.015f + 0.005f;

		// print total-time running since application start
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM | FONT_RIGHT, "%.2fs", pi->second.total.toSecsf());

		// print percent of CPU time used within the last 500ms
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM | FONT_RIGHT, "%.2f%%", pi->second.percent * 100);
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM | FONT_RIGHT, "\xff\xff%c%c%.2f%%", pi->second.newPeak?1:255, pi->second.newPeak?1:255, pi->second.peak * 100);
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM | FONT_RIGHT, "\xff\xff%c%c%.0fms", pi->second.newLagPeak?1:255, pi->second.newLagPeak?1:255, pi->second.maxLag);

		// print timer name
		fStartX += 0.01f;
		font->glFormat(fStartX, fStartY, 0.7f, FONT_BASELINE | FONT_SCALE | FONT_NORM, pi->first);
	}


	// draw the Timer selection boxes
	glPushMatrix();
	glTranslatef(start_x + 0.005f, start_y, 0);
	glScalef(0.015f, 0.02f, 0.02f);
		va->Initialize();
		va2->Initialize();
			int i = 0;
			for (pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi, ++i){
				auto& fc = pi->second.color;
				SColor c(fc[0], fc[1], fc[2]);
				va->AddVertexC(float3(0, 0 - i * 1.2f, 0), c);
				va->AddVertexC(float3(1, 0 - i * 1.2f, 0), c);
				va->AddVertexC(float3(1, 1 - i * 1.2f, 0), c);
				va->AddVertexC(float3(0, 1 - i * 1.2f, 0), c);

				if (!pi->second.showGraph) {
					va2->AddVertex0(0, 0 - i * 1.2f, 0);
					va2->AddVertex0(1, 1 - i * 1.2f, 0);
					va2->AddVertex0(1, 0 - i * 1.2f, 0);
					va2->AddVertex0(0, 1 - i * 1.2f, 0);
				}
			}
		// draw the boxes
		va->DrawArrayC(GL_QUADS);
		// draw the 'graph view disabled' cross
		glColor3f(1,0,0);
		va2->DrawArray0(GL_LINES);
	glPopMatrix();

	// draw the graph
	glLineWidth(3.0f);
	for (pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi) {
		if (!pi->second.showGraph) {
			continue;
		}
		va->Initialize();
		const float steps_x = (end_x - start_x) / CTimeProfiler::TimeRecord::frames_size;
		for (size_t a=0; a < CTimeProfiler::TimeRecord::frames_size; ++a) {
			// profile runtime; eg 0.5f means: uses 50% of a CPU (during that frame)
			// This may be more then 1.0f, in case an operation
			// which ran over many frames, ended in this one.
			const float p = pi->second.frames[a].toSecsf() * GAME_SPEED;
			const float x = start_x + (a * steps_x);
			const float y = 0.02f + (p * 0.96f);
			va->AddVertex0(x, y, 0.0f);
		}

		glColorf3((float3)pi->second.color);
		va->DrawArray0(GL_LINE_STRIP);
	}
	glLineWidth(1.0f);
}
Example #11
0
static void DrawFrameBarcode()
{
	const float maxHist_f = 0.5f;
	const spring_time curTime = spring_now();
	const spring_time maxHist = spring_secs(maxHist_f);
	float drawArea[4] = {0.01f, 0.2f, start_x - 0.05f, 0.25f};

	// background
	CVertexArray* va = GetVertexArray();
	va->Initialize();
		va->AddVertex0(drawArea[0] - 10 * globalRendering->pixelX, drawArea[1] - 10 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(drawArea[0] - 10 * globalRendering->pixelX, drawArea[3] + 20 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(drawArea[2] + 10 * globalRendering->pixelX, drawArea[3] + 20 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(drawArea[2] + 10 * globalRendering->pixelX, drawArea[1] - 10 * globalRendering->pixelY, 0.0f);
	glColor4f(0.0f,0.0f,0.0f, 0.5f);
	va->DrawArray0(GL_QUADS);

	// title and legend
	font->glFormat(drawArea[0], drawArea[3] + 10 * globalRendering->pixelY, 0.7f, FONT_TOP | DBG_FONT_FLAGS,
			"Frame Grapher (%.2fsec)"
			"\xff\xff\x80\xff  GC"
			"\xff\xff\xff\x01  Unsynced"
			"\xff\x01\x01\xff  Swap"
			"\xff\x01\xff\x01  Video"
			"\xff\xff\x01\x01  Sim"
			, maxHist_f);

	// gc frames
	glColor4f(1.0f,0.5f,1.0f, 0.55f);
	DrawTimeSlice(lgcFrames, curTime, maxHist, drawArea);

	// updateunsynced frames
	glColor4f(1.0f,1.0f,0.0f, 0.9f);
	DrawTimeSlice(uusFrames, curTime, maxHist, drawArea);

	// video swap frames
	glColor4f(0.0f,0.0f,1.0f, 0.55f);
	DrawTimeSlice(swpFrames, curTime, maxHist, drawArea);

	// video frames
	glColor4f(0.0f,1.0f,0.0f, 0.55f);
	DrawTimeSlice(vidFrames, curTime, maxHist, drawArea);

	// sim frames
	glColor4f(1.0f,0.0f,0.0f, 0.55f);
	DrawTimeSlice(simFrames, curTime, maxHist, drawArea);

	// draw `feeder` indicating current time pos
	//CVertexArray* va = GetVertexArray();
	va->Initialize();
		// draw feeder
		const float r = (curTime % maxHist).toSecsf() / maxHist_f;
		const float xf = drawArea[0] + r * (drawArea[2] - drawArea[0]);
		va->AddVertex0(xf, drawArea[1], 0.0f);
		va->AddVertex0(xf, drawArea[3], 0.0f);
		va->AddVertex0(xf + 10 * globalRendering->pixelX, drawArea[3], 0.0f);
		va->AddVertex0(xf + 10 * globalRendering->pixelX, drawArea[1], 0.0f);

		// draw scale (horizontal bar that indicates 30FPS timing length)
		const float xs1 = drawArea[2] - 1.f/(30.f*maxHist_f) * (drawArea[2] - drawArea[0]);
		const float xs2 = drawArea[2] +               0.0f * (drawArea[2] - drawArea[0]);
		va->AddVertex0(xs1, drawArea[3] +  2 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(xs1, drawArea[3] + 10 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(xs2, drawArea[3] + 10 * globalRendering->pixelY, 0.0f);
		va->AddVertex0(xs2, drawArea[3] +  2 * globalRendering->pixelY, 0.0f);
	glColor4f(1.0f,0.0f,0.0f, 1.0f);
	va->DrawArray0(GL_QUADS);
}
Example #12
0
static void DrawProfiler()
{
	font->SetTextColor(1,1,1,1);

	// draw the background of the window
	{
		CVertexArray* va  = GetVertexArray();
		va->Initialize();
			va->AddVertex0(start_x, start_y + lineHeight + 0.005f,                          0);
			va->AddVertex0(end_x,   start_y + lineHeight + 0.005f,                          0);
			va->AddVertex0(start_x, start_y - profiler.profile.size() * lineHeight - 0.01f, 0);
			va->AddVertex0(end_x,   start_y - profiler.profile.size() * lineHeight - 0.01f, 0);
		glColor4f(0.0f, 0.0f, 0.5f, 0.5f);
		va->DrawArray0(GL_TRIANGLE_STRIP);
	}

	const float textSize = 0.5f;

	// table header
	{
		const float fStartY = start_y + 0.005f;
		float fStartX = start_x + 0.005f + 0.015f + 0.005f;

		// print total-time running since application start
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, textSize, FONT_SHADOW | FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "totaltime");

		// print percent of CPU time used within the last 500ms
		fStartX += 0.06f;
		font->glFormat(fStartX, fStartY, textSize, FONT_SHADOW | FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "cur-%%usage");
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, textSize, FONT_SHADOW | FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "max-%%usage");
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, textSize, FONT_SHADOW | FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "lag");

		// print timer name
		fStartX += 0.01f;
		font->glFormat(fStartX, fStartY, textSize, FONT_SHADOW | FONT_DESCENDER | FONT_SCALE | FONT_NORM, "title");
	}

	// draw the textual info (total-time, short-time percentual time, timer-name)
	int y = 1;
	for (auto pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi, ++y) {
		const auto& profileData = pi->second;

		const float fStartY = start_y - y * lineHeight;
		float fStartX = start_x + 0.005f + 0.015f + 0.005f;

		// print total-time running since application start
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, textSize, FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "%.2fs", profileData.total.toSecsf());

		// print percent of CPU time used within the last 500ms
		fStartX += 0.06f;
		font->glFormat(fStartX, fStartY, textSize, FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "%.2f%%", profileData.percent * 100);
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, textSize, FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "\xff\xff%c%c%.2f%%", profileData.newPeak?1:255, profileData.newPeak?1:255, profileData.peak * 100);
		fStartX += 0.04f;
		font->glFormat(fStartX, fStartY, textSize, FONT_DESCENDER | FONT_SCALE | FONT_NORM | FONT_RIGHT, "\xff\xff%c%c%.0fms", profileData.newLagPeak?1:255, profileData.newLagPeak?1:255, profileData.maxLag);

		// print timer name
		fStartX += 0.01f;
		font->glFormat(fStartX, fStartY, textSize, FONT_DESCENDER | FONT_SCALE | FONT_NORM, pi->first);
	}


	// draw the Timer selection boxes
	const float boxSize = lineHeight*0.9;
	const float selOffset = boxSize*0.2;
	glPushMatrix();
	glTranslatef(start_x + 0.005f, start_y + boxSize, 0); // we are now at upper left of first box
		CVertexArray* va  = GetVertexArray();
		CVertexArray* va2 = GetVertexArray();
		va->Initialize();
		va2->Initialize();
			int i = 1;
			for (auto pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi, ++i){
				auto& fc = pi->second.color;
				SColor c(fc[0], fc[1], fc[2]);
				va->AddVertexC(float3(0, -i*lineHeight, 0), c); // upper left
				va->AddVertexC(float3(0, -i*lineHeight-boxSize, 0), c); // lower left
				va->AddVertexC(float3(boxSize, -i*lineHeight-boxSize, 0), c); // lower right
				va->AddVertexC(float3(boxSize, -i*lineHeight, 0), c); // upper right

				if (pi->second.showGraph) {
					va2->AddVertex0(lineHeight+selOffset, -i*lineHeight-selOffset, 0); // upper left
					va2->AddVertex0(lineHeight+selOffset, -i*lineHeight-boxSize+selOffset, 0); // lower left
					va2->AddVertex0(lineHeight+boxSize-selOffset, -i*lineHeight-boxSize+selOffset, 0); // lower right
					va2->AddVertex0(lineHeight+boxSize-selOffset, -i*lineHeight-selOffset, 0); // upper right
				}
			}
		// draw the boxes
		va->DrawArrayC(GL_QUADS);
		// draw the 'graph view disabled' cross
		glColor3f(1,0,0);
		va2->DrawArray0(GL_QUADS);
	glPopMatrix();

	// draw the graph
	glLineWidth(3.0f);
	for (auto pi = profiler.profile.begin(); pi != profiler.profile.end(); ++pi) {
		if (!pi->second.showGraph) {
			continue;
		}
		CVertexArray* va = GetVertexArray();
		va->Initialize();
		const float steps_x = (end_x - start_x) / CTimeProfiler::TimeRecord::frames_size;
		for (size_t a=0; a < CTimeProfiler::TimeRecord::frames_size; ++a) {
			// profile runtime; eg 0.5f means: uses 50% of a CPU (during that frame)
			// This may be more then 1.0f, in case an operation
			// which ran over many frames, ended in this one.
			const float p = pi->second.frames[a].toSecsf() * GAME_SPEED;
			const float x = start_x + (a * steps_x);
			const float y = 0.02f + (p * 0.96f);
			va->AddVertex0(x, y, 0.0f);
		}

		glColorf3((float3)pi->second.color);
		va->DrawArray0(GL_LINE_STRIP);
	}
	glLineWidth(1.0f);
}
Example #13
0
CBumpWater::CBumpWater()
{
	/** LOAD USER CONFIGS **/
	reflTexSize  = next_power_of_2(configHandler->Get("BumpWaterTexSizeReflection", 512));
	reflection   = !!configHandler->Get("BumpWaterReflection", 1);
	refraction   = configHandler->Get("BumpWaterRefraction", 1);  /// 0:=off, 1:=screencopy, 2:=own rendering cycle
	anisotropy   = atof(configHandler->GetString("BumpWaterAnisotropy", "0.0").c_str());
	depthCopy    = !!configHandler->Get("BumpWaterUseDepthTexture", 1);
	depthBits    = configHandler->Get("BumpWaterDepthBits", (gu->atiHacks)?16:24);
	blurRefl     = !!configHandler->Get("BumpWaterBlurReflection", 0);
	shoreWaves   = (!!configHandler->Get("", 1)) && mapInfo->water.shoreWaves;
	endlessOcean = (!!configHandler->Get("BumpWaterEndlessOcean", 1)) && mapInfo->water.hasWaterPlane
	               && ((readmap->minheight <= 0.0f) || (mapInfo->water.forceRendering));
	dynWaves     = (!!configHandler->Get("BumpWaterDynamicWaves", 1)) && (mapInfo->water.numTiles>1);
	useUniforms  = (!!configHandler->Get("BumpWaterUseUniforms", 0));

	refractTexture = 0;
	reflectTexture = 0;

	/** CHECK HARDWARE **/
	if (!GL_ARB_shading_language_100)
		throw content_error("BumpWater: your hardware/driver setup does not support GLSL.");

	shoreWaves = shoreWaves && (GLEW_EXT_framebuffer_object);
	dynWaves   = dynWaves && (GLEW_EXT_framebuffer_object && GLEW_ARB_imaging);


	/** LOAD TEXTURES **/
	foamTexture     = LoadTexture( mapInfo->water.foamTexture );
	normalTexture   = LoadTexture( mapInfo->water.normalTexture , anisotropy , &normalTextureX, &normalTextureY);

	//! caustic textures
	const vector<string>& causticNames = mapInfo->water.causticTextures;
	if (causticNames.size() <= 0) {
		throw content_error("no caustic textures");
	}
	for (int i = 0; i < (int)causticNames.size(); ++i) {
		caustTextures.push_back(LoadTexture(causticNames[i]));
	}

	/** CHECK SHOREWAVES TEXTURE SIZE **/
	if (shoreWaves) {
		GLint maxw,maxh;
		glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA16F_ARB, 4096, 4096, 0, GL_RGBA, GL_FLOAT, NULL);
		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &maxw);
		glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &maxh);
		if (gs->mapx>maxw || gs->mapy>maxh) {
			shoreWaves = false;
			logOutput.Print("BumpWater: can't display shorewaves (map too large)!");
		}
	}


	/** SHOREWAVES **/
	if (shoreWaves) {
		waveRandTexture = LoadTexture( "bitmaps/shorewaverand.png" );

		glGenTextures(1, &coastTexture);
		glBindTexture(GL_TEXTURE_2D, coastTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		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_MAG_FILTER, GL_LINEAR);
		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, gs->mapx, gs->mapy, 0, GL_RGBA, GL_FLOAT, NULL);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, gs->mapx, gs->mapy, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
		//glGenerateMipmapEXT(GL_TEXTURE_2D);

		const string fsSource = LoadShaderSource("shaders/bumpWaterCoastBlurFS.glsl");
		const GLchar* fsSourceStr = fsSource.c_str();
		blurFP = glCreateShader(GL_FRAGMENT_SHADER);
		glShaderSource(blurFP, 1, &fsSourceStr, NULL);
		glCompileShader(blurFP);
		PrintShaderLog(blurFP, "blurFP");

		blurShader = glCreateProgram();
		glAttachShader(blurShader, blurFP);
		glLinkProgram(blurShader);
		PrintShaderLog(blurShader, "blurShader");
		glUseProgram(blurShader);
			GLuint tex0Loc = glGetUniformLocation(blurShader, "tex0");
			GLuint tex1Loc = glGetUniformLocation(blurShader, "tex1");
			glUniform1i(tex0Loc, 0);
			glUniform1i(tex1Loc, 1);
		glUseProgram(0);

		coastFBO.reloadOnAltTab = true;
		coastFBO.Bind();
		coastFBO.AttachTexture(coastTexture, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT);

		if (coastFBO.CheckStatus("BUMPWATER(Coastmap)")) {
			//! initialize texture
			glClearColor(0.0f,0.0f,0.0f,0.0f);
			glClear(GL_COLOR_BUFFER_BIT);

			//! fill with current heightmap/coastmap
			HeightmapChanged(0, 0, gs->mapx, gs->mapy);
			UploadCoastline(true);
			UpdateCoastmap();
		}else shoreWaves=false;

		//coastFBO.Unbind(); gets done below
	}


	/** CREATE TEXTURES **/
	if ((refraction>0) || depthCopy) {
		//! ati's don't have glsl support for texrects
		screenTextureX = gu->viewSizeX;
		screenTextureY = gu->viewSizeY;
		if (GLEW_ARB_texture_rectangle && !gu->atiHacks) {
			target = GL_TEXTURE_RECTANGLE_ARB;
		} else {
			target = GL_TEXTURE_2D;
			if (!gu->supportNPOTs) {
				screenTextureX = next_power_of_2(gu->viewSizeX);
				screenTextureY = next_power_of_2(gu->viewSizeY);
			}
		}
	}

	if (refraction>0) {
		//! CREATE REFRACTION TEXTURE
		glGenTextures(1, &refractTexture);
		glBindTexture(target, refractTexture);
		glTexParameteri(target,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
		glTexParameteri(target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		if (GLEW_EXT_texture_edge_clamp) {
			glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		} else {
			glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP);
		}
		glTexImage2D(target, 0, GL_RGBA8, screenTextureX, screenTextureY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	}

	if (reflection) {
		//! CREATE REFLECTION TEXTURE
		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);
		if (GLEW_EXT_texture_edge_clamp) {
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		} else {
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		}
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, reflTexSize, reflTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	}

	if (depthCopy) {
		//! CREATE DEPTH TEXTURE
		glGenTextures(1, &depthTexture);
		glBindTexture(target, depthTexture);
		glTexParameteri(target,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
		glTexParameteri(target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		GLuint depthFormat = GL_DEPTH_COMPONENT; 
		switch (gu->depthBufferBits) { /// use same depth as screen framebuffer
			case 16: depthFormat = GL_DEPTH_COMPONENT16; break;
			case 24: if (!gu->atiHacks) { depthFormat = GL_DEPTH_COMPONENT24; break; } //ATIs fall through and use 32bit!
			default: depthFormat = GL_DEPTH_COMPONENT32; break;
		}
		glTexImage2D(target, 0, depthFormat, screenTextureX, screenTextureY, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	}

	if (dynWaves) {
		//! SETUP DYNAMIC WAVES
		tileOffsets = new unsigned char[mapInfo->water.numTiles * mapInfo->water.numTiles];

		normalTexture2 = normalTexture;
		glBindTexture(GL_TEXTURE_2D, normalTexture2);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 0.0);

		glGenTextures(1, &normalTexture);
		glBindTexture(GL_TEXTURE_2D, normalTexture);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		if (anisotropy>0.0f)
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, normalTextureX, normalTextureY, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
		glGenerateMipmapEXT(GL_TEXTURE_2D);
	}

	/** CREATE FBOs **/
	if (GLEW_EXT_framebuffer_object) {
		GLuint depthRBOFormat = GL_DEPTH_COMPONENT;
		switch (depthBits) {
			case 16: depthRBOFormat = GL_DEPTH_COMPONENT16; break;
			case 24: depthRBOFormat = GL_DEPTH_COMPONENT24; break;
			case 32: depthRBOFormat = GL_DEPTH_COMPONENT32; break;
		}

		if (reflection) {
			reflectFBO.Bind();
			reflectFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, depthRBOFormat, reflTexSize, reflTexSize);
			reflectFBO.AttachTexture(reflectTexture);
		}

		if (refraction>0) {
			refractFBO.Bind();
			refractFBO.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, depthRBOFormat, screenTextureX, screenTextureY);
			refractFBO.AttachTexture(refractTexture,target);
		}

		if (!reflectFBO.CheckStatus("BUMPWATER(reflection)")) {
			reflection = false;
		}
		if (!refractFBO.CheckStatus("BUMPWATER(refraction)")) {
			refraction = 0;
		}

		if (dynWaves) {
			dynWavesFBO.reloadOnAltTab = true;
			dynWavesFBO.Bind();
			dynWavesFBO.AttachTexture(normalTexture);
			if (dynWavesFBO.CheckStatus("BUMPWATER(DynWaves)")) {
				UpdateDynWaves(true); //! initialize
			}
		}
		FBO::Unbind();
	}


	/** DEFINE SOME SHADER RUNTIME CONSTANTS (I don't use Uniforms for that, because the glsl compiler can't optimize those!) **/
	string definitions;
	if (reflection)   definitions += "#define opt_reflection\n";
	if (refraction>0) definitions += "#define opt_refraction\n";
	if (shoreWaves)   definitions += "#define opt_shorewaves\n";
	if (depthCopy)    definitions += "#define opt_depth\n";
	if (blurRefl)     definitions += "#define opt_blurreflection\n";
	if (endlessOcean) definitions += "#define opt_endlessocean\n";
	if (target==GL_TEXTURE_RECTANGLE_ARB) definitions += "#define opt_texrect\n";

	GLSLDefineConstf3(definitions, "MapMid",         float3(readmap->width*SQUARE_SIZE*0.5f,0.0f,readmap->height*SQUARE_SIZE*0.5f) );
	GLSLDefineConstf2(definitions, "ScreenInverse",  1.0f/gu->viewSizeX, 1.0f/gu->viewSizeY );
	GLSLDefineConstf2(definitions, "ScreenTextureSizeInverse",  1.0f/screenTextureX, 1.0f/screenTextureY );
	GLSLDefineConstf2(definitions, "ViewPos",        gu->viewPosX,gu->viewPosY );

	if (useUniforms) {
		SetupUniforms(definitions);
	} else {
		GLSLDefineConstf4(definitions, "SurfaceColor",   mapInfo->water.surfaceColor*0.4, mapInfo->water.surfaceAlpha );
		GLSLDefineConstf4(definitions, "PlaneColor",     mapInfo->water.planeColor*0.4, mapInfo->water.surfaceAlpha );
		GLSLDefineConstf3(definitions, "DiffuseColor",   mapInfo->water.diffuseColor);
		GLSLDefineConstf3(definitions, "SpecularColor",  mapInfo->water.specularColor);
		GLSLDefineConstf1(definitions, "SpecularPower",  mapInfo->water.specularPower);
		GLSLDefineConstf1(definitions, "SpecularFactor", mapInfo->water.specularFactor);
		GLSLDefineConstf1(definitions, "AmbientFactor",  mapInfo->water.ambientFactor);
		GLSLDefineConstf1(definitions, "DiffuseFactor",  mapInfo->water.diffuseFactor * 15.0f);
		GLSLDefineConstf3(definitions, "SunDir",         mapInfo->light.sunDir);
		GLSLDefineConstf1(definitions, "FresnelMin",     mapInfo->water.fresnelMin);
		GLSLDefineConstf1(definitions, "FresnelMax",     mapInfo->water.fresnelMax);
		GLSLDefineConstf1(definitions, "FresnelPower",   mapInfo->water.fresnelPower);
		GLSLDefineConstf1(definitions, "ReflDistortion", mapInfo->water.reflDistortion);
		GLSLDefineConstf2(definitions, "BlurBase",       0.0f,mapInfo->water.blurBase/gu->viewSizeY);
		GLSLDefineConstf1(definitions, "BlurExponent",   mapInfo->water.blurExponent);
		GLSLDefineConstf1(definitions, "PerlinStartFreq",  mapInfo->water.perlinStartFreq);
		GLSLDefineConstf1(definitions, "PerlinLacunarity", mapInfo->water.perlinLacunarity);
		GLSLDefineConstf1(definitions, "PerlinAmp",        mapInfo->water.perlinAmplitude);
		GLSLDefineConstf1(definitions, "WindSpeed",        mapInfo->water.windSpeed);
	}

	{
		const int mapX = readmap->width  * SQUARE_SIZE;
		const int mapZ = readmap->height * SQUARE_SIZE;
		const float shadingX = (float)gs->mapx / gs->pwr2mapx;
		const float shadingZ = (float)gs->mapy / gs->pwr2mapy;
		const float scaleX = (mapX > mapZ) ? (readmap->height/64)/16.0f * (float)mapX/mapZ : (readmap->width/64)/16.0f;
		const float scaleZ = (mapX > mapZ) ? (readmap->height/64)/16.0f : (readmap->width/64)/16.0f * (float)mapZ/mapX;
		GLSLDefineConst4f(definitions, "TexGenPlane", 1.0f/mapX, 1.0f/mapZ, scaleX/mapX, scaleZ/mapZ);
		GLSLDefineConst4f(definitions, "ShadingPlane", shadingX/mapX, shadingZ/mapZ, shadingX,shadingZ);
	}

	/** LOAD SHADERS **/
	string vsSource = LoadShaderSource("shaders/bumpWaterVS.glsl");
	string fsSource = LoadShaderSource("shaders/bumpWaterFS.glsl");

	vector<GLint> lengths(2);
	vector<const GLchar*> strings(2);
	lengths[0] = definitions.length();
	strings[0] = definitions.c_str();

	waterVP = glCreateShader(GL_VERTEX_SHADER);
	lengths[1] = vsSource.length();
	strings[1] = vsSource.c_str();
	glShaderSource(waterVP, strings.size(), &strings.front(), &lengths.front());
	glCompileShader(waterVP);
	PrintShaderLog(waterVP, "waterVP");

	waterFP = glCreateShader(GL_FRAGMENT_SHADER);
	lengths[1] = fsSource.length();
	strings[1] = fsSource.c_str();
	glShaderSource(waterFP, strings.size(), &strings.front(), &lengths.front());
	glCompileShader(waterFP);
	PrintShaderLog(waterFP, "waterFP");

	waterShader = glCreateProgram();
	glAttachShader(waterShader, waterVP);
	glAttachShader(waterShader, waterFP);
	glLinkProgram(waterShader);
	PrintShaderLog(waterShader, "waterShader");


	/** BIND TEXTURE UNIFORMS **/
	glUseProgram(waterShader);
		eyePosLoc     = glGetUniformLocation(waterShader, "eyePos");
		frameLoc      = glGetUniformLocation(waterShader, "frame");

		if (useUniforms)
			GetUniformLocations(waterShader);

		//! Texture Uniform Locations
		GLuint normalmapLoc  = glGetUniformLocation(waterShader, "normalmap");
		GLuint heightmapLoc  = glGetUniformLocation(waterShader, "heightmap");
		GLuint causticLoc    = glGetUniformLocation(waterShader, "caustic");
		GLuint foamLoc       = glGetUniformLocation(waterShader, "foam");
		GLuint reflectionLoc = glGetUniformLocation(waterShader, "reflection");
		GLuint refractionLoc = glGetUniformLocation(waterShader, "refraction");
		GLuint depthmapLoc   = glGetUniformLocation(waterShader, "depthmap");
		GLuint coastmapLoc   = glGetUniformLocation(waterShader, "coastmap");
		GLuint waverandLoc   = glGetUniformLocation(waterShader, "waverand");

		glUniform1i(normalmapLoc, 0);
		glUniform1i(heightmapLoc, 1);
		glUniform1i(causticLoc, 2);
		glUniform1i(foamLoc, 3);
		glUniform1i(reflectionLoc, 4);
		glUniform1i(refractionLoc, 5);
		glUniform1i(coastmapLoc, 6);
		glUniform1i(depthmapLoc, 7);
		glUniform1i(waverandLoc, 8);
	glUseProgram(0);


	/** CREATE DISPLAYLIST **/
	displayList = glGenLists(1);
	glNewList(displayList,GL_COMPILE);
	if (endlessOcean) {
		DrawRadialDisc();
	}else{
		const int mapX = readmap->width  * SQUARE_SIZE;
		const int mapZ = readmap->height * SQUARE_SIZE;
		CVertexArray *va = GetVertexArray();
		va->Initialize();
		for (int z = 0; z < 9; z++) {
			for (int x = 0; x < 10; x++) {
				for (int zs = 0; zs <= 1; zs++) {
					va->AddVertex0(float3(x*(mapX/9.0f), 0.0f, (z+zs)*(mapZ/9.0f)));
				}
			}
			va->EndStrip();
		}
		va->DrawArray0(GL_TRIANGLE_STRIP);
	}
	glEndList();

/*
	windndir = wind.GetCurrentDirection();
	windStrength = (smoothstep(0.0f, 12.0f, wind.GetCurrentStrength()) * 0.5f + 4.0f);
	windVec = windndir * windStrength;
*/
	windVec = float3(20.0,0.0,20.0);

	occlusionQuery = 0;
	occlusionQueryResult = GL_TRUE;
	wasLastFrameVisible = false;
	bool useOcclQuery  = (!!configHandler->Get("BumpWaterOcclusionQuery", 1));
	if (useOcclQuery && GLEW_ARB_occlusion_query && refraction<2) { //! in the case of a separate refraction pass, there isn't enough time for a occlusion query
		GLint bitsSupported;
		glGetQueryiv(GL_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS, &bitsSupported);
		if (bitsSupported > 0)
			glGenQueries(1,&occlusionQuery);
	}

	if (refraction>1)
		drawSolid = true;
}