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); }
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); }
/* * Draws a trigonometric circle in 'resolution' steps, with a slope modifier */ void glBallisticCircle(const float3& center, const float radius, const CWeapon* weapon, unsigned int resolution, float slope) { int rdiv = 50; resolution *= 2; rdiv *= 1; CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(resolution, 0, VA_SIZE_0); float3* vertices = reinterpret_cast<float3*>(va->drawArray); va->drawArrayPos = va->drawArray + resolution * 3; for_mt(0, resolution, [&](const int i) { const float radians = (2.0f * PI) * (float)i / (float)resolution; float rad = radius; float sinR = fastmath::sin(radians); float cosR = fastmath::cos(radians); float3 pos; pos.x = center.x + (sinR * rad); pos.z = center.z + (cosR * rad); pos.y = CGround::GetHeightAboveWater(pos.x, pos.z, false); float heightDiff = (pos.y - center.y) * 0.5f; rad -= heightDiff * slope; float adjRadius = weapon ? weapon->GetRange2D(heightDiff * weapon->heightMod) : rad; float adjustment = rad * 0.5f; float ydiff = 0; for(int j = 0; j < rdiv && math::fabs(adjRadius - rad) + ydiff > .01 * rad; j++) { if (adjRadius > rad) { rad += adjustment; } else { rad -= adjustment; adjustment /= 2; } pos.x = center.x + (sinR * rad); pos.z = center.z + (cosR * rad); float newY = CGround::GetHeightAboveWater(pos.x, pos.z, false); ydiff = math::fabs(pos.y - newY); pos.y = newY; heightDiff = (pos.y - center.y); adjRadius = weapon ? weapon->GetRange2D(heightDiff * weapon->heightMod) : rad; } pos.x = center.x + (sinR * adjRadius); pos.z = center.z + (cosR * adjRadius); pos.y = CGround::GetHeightAboveWater(pos.x, pos.z, false) + 5.0f; vertices[i] = pos; }); va->DrawArray0(GL_LINE_LOOP); }
/** * 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); }
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 ); }
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); }
void SmoothHeightMeshDrawer::Draw(float yoffset) { if (!drawEnabled) return; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glLineWidth(1.0f); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_1D); glDisable(GL_CULL_FACE); const float quadSize = 4.0f * smoothGround->GetResolution(); const unsigned int numQuadsX = smoothGround->GetFMaxX() / quadSize; const unsigned int numQuadsZ = smoothGround->GetFMaxY() / quadSize; CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays((numQuadsX + 1) * (numQuadsZ + 1) * 4, 0, VA_SIZE_0); for (unsigned int zq = 0; zq <= numQuadsZ; zq++) { for (unsigned int xq = 0; xq <= numQuadsX; xq++) { const float x = xq * quadSize; const float z = zq * quadSize; const float h1 = smoothGround->GetHeightAboveWater(x, z ) + yoffset; const float h2 = smoothGround->GetHeightAboveWater(x + quadSize, z ) + yoffset; const float h3 = smoothGround->GetHeightAboveWater(x + quadSize, z + quadSize) + yoffset; const float h4 = smoothGround->GetHeightAboveWater(x, z + quadSize) + yoffset; va->AddVertexQ0(float3(x, h1, z )); va->AddVertexQ0(float3(x + quadSize, h2, z )); va->AddVertexQ0(float3(x + quadSize, h3, z + quadSize)); va->AddVertexQ0(float3(x, h4, z + quadSize)); } } glColor4ub(0, 255, 0, 255); va->DrawArray0(GL_QUADS); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); }
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); }
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; } }
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); } } } }
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); }
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); }
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); }
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); }
void CSelectedUnits::Draw() { glDisable(GL_TEXTURE_2D); glDepthMask(false); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); // for line smoothing glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glLineWidth(cmdColors.UnitBoxLineWidth()); GML_RECMUTEX_LOCK(grpsel); // Draw if (cmdColors.unitBox[3] > 0.0f) { glColor4fv(cmdColors.unitBox); const CUnitSet* unitSet; if (selectedGroup != -1) { unitSet = &grouphandlers[gu->myTeam]->groups[selectedGroup]->units; } else { unitSet = &selectedUnits; } CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(unitSet->size()*4, 0, VA_SIZE_0); CUnitSet::const_iterator ui; for (ui = unitSet->begin(); ui != unitSet->end(); ++ui) { const CUnit* unit = *ui; if (unit->isIcon) { continue; } va->AddVertexQ0(unit->drawPos.x + unit->xsize * 4, unit->drawPos.y, unit->drawPos.z + unit->zsize * 4); va->AddVertexQ0(unit->drawPos.x - unit->xsize * 4, unit->drawPos.y, unit->drawPos.z + unit->zsize * 4); va->AddVertexQ0(unit->drawPos.x - unit->xsize * 4, unit->drawPos.y, unit->drawPos.z - unit->zsize * 4); va->AddVertexQ0(unit->drawPos.x + unit->xsize * 4, unit->drawPos.y, unit->drawPos.z - unit->zsize * 4); } va->DrawArray0(GL_QUADS); } // highlight queued build sites if we are about to build something // (or old-style, whenever the shift key is being held down) if (cmdColors.buildBox[3] > 0.0f) { if (!selectedUnits.empty() && ((cmdColors.BuildBoxesOnShift() && keys[SDLK_LSHIFT]) || ((guihandler->inCommand >= 0) && (guihandler->inCommand < int(guihandler->commands.size())) && (guihandler->commands[guihandler->inCommand].id < 0)))) { GML_STDMUTEX_LOCK(cai); // Draw bool myColor = true; glColor4fv(cmdColors.buildBox); std::list<CBuilderCAI*>::const_iterator bi; for (bi = uh->builderCAIs.begin(); bi != uh->builderCAIs.end(); ++bi) { CBuilderCAI* builder = *bi; if (builder->owner->team == gu->myTeam) { if (!myColor) { glColor4fv(cmdColors.buildBox); myColor = true; } builder->DrawQuedBuildingSquares(); } else if (teamHandler->AlliedTeams(builder->owner->team, gu->myTeam)) { if (myColor) { glColor4fv(cmdColors.allyBuildBox); myColor = false; } builder->DrawQuedBuildingSquares(); } } } } glLineWidth(1.0f); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(true); glEnable(GL_TEXTURE_2D); }
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; }