void OverlayRenderer::RenderOverlaysAfterWater() { PROFILE3_GPU("overlays (after)"); RenderTexturedOverlayLines(); RenderQuadOverlays(); }
void CGUIManager::Draw() { PROFILE3_GPU("gui"); for (PageStackType::iterator it = m_PageStack.begin(); it != m_PageStack.end(); ++it) it->gui->Draw(); }
void TerrainOverlay::RenderOverlays() { if (g_TerrainOverlayList.size() == 0) return; PROFILE3_GPU("terrain overlays"); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(GL_FALSE); // To ensure that outlines are drawn on top of the terrain correctly (and // don't Z-fight and flicker nastily), draw them as QUADS with the LINE // PolygonMode, and use PolygonOffset to pull them towards the camera. // (See e.g. http://www.opengl.org/resources/faq/technical/polygonoffset.htm) glPolygonOffset(-1.f, -1.f); glEnable(GL_POLYGON_OFFSET_LINE); glDisable(GL_TEXTURE_2D); std::for_each(g_TerrainOverlayList.begin(), g_TerrainOverlayList.end(), render1st()); // Clean up state changes glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDisable(GL_POLYGON_OFFSET_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glDepthMask(GL_TRUE); glDisable(GL_BLEND); }
void OverlayRenderer::RenderSphereOverlays() { PROFILE3_GPU("overlays (spheres)"); #if CONFIG2_GLES #warning TODO: implement OverlayRenderer::RenderSphereOverlays for GLES #else if (g_Renderer.GetRenderPath() != CRenderer::RP_SHADER) return; if (m->spheres.empty()) return; glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glDepthMask(0); glEnableClientState(GL_VERTEX_ARRAY); CShaderProgramPtr shader; CShaderTechniquePtr tech; tech = g_Renderer.GetShaderManager().LoadEffect(str_overlay_solid); tech->BeginPass(); shader = tech->GetShader(); m->GenerateSphere(); shader->VertexPointer(3, GL_FLOAT, 0, &m->sphereVertexes[0]); for (size_t i = 0; i < m->spheres.size(); ++i) { SOverlaySphere* sphere = m->spheres[i]; CMatrix3D transform; transform.SetIdentity(); transform.Scale(sphere->m_Radius, sphere->m_Radius, sphere->m_Radius); transform.Translate(sphere->m_Center); shader->Uniform(str_transform, transform); shader->Uniform(str_color, sphere->m_Color); glDrawElements(GL_TRIANGLES, m->sphereIndexes.size(), GL_UNSIGNED_SHORT, &m->sphereIndexes[0]); g_Renderer.GetStats().m_DrawCalls++; g_Renderer.GetStats().m_OverlayTris = m->sphereIndexes.size()/3; } tech->EndPass(); glDisableClientState(GL_VERTEX_ARRAY); glDepthMask(1); glDisable(GL_BLEND); #endif }
void ITerrainOverlay::RenderOverlaysAfterWater() { if (g_TerrainOverlayList.empty()) return; PROFILE3_GPU("terrain overlays (after)"); for (size_t i = 0; i < g_TerrainOverlayList.size(); ++i) g_TerrainOverlayList[i].first->RenderAfterWater(); }
//Render Manager. void CConsole::Render() { if (! (m_bVisible || m_bToggle) ) return; PROFILE3_GPU("console"); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CShaderTechniquePtr solidTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid); solidTech->BeginPass(); CShaderProgramPtr solidShader = solidTech->GetShader(); CMatrix3D transform = GetDefaultGuiMatrix(); // animation: slide in from top of screen const float DeltaY = (1.0f - m_fVisibleFrac) * m_fHeight; transform.PostTranslate(m_fX, m_fY - DeltaY, 0.0f); // move to window position solidShader->Uniform(str_transform, transform); DrawWindow(solidShader); solidTech->EndPass(); CShaderTechniquePtr textTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text); textTech->BeginPass(); CTextRenderer textRenderer(textTech->GetShader()); textRenderer.Font(CStrIntern(CONSOLE_FONT)); textRenderer.SetTransform(transform); DrawHistory(textRenderer); DrawBuffer(textRenderer); textRenderer.Render(); textTech->EndPass(); glDisable(GL_BLEND); }
void OverlayRenderer::RenderOverlaysBeforeWater() { PROFILE3_GPU("overlays (before)"); #if CONFIG2_GLES #warning TODO: implement OverlayRenderer::RenderOverlaysBeforeWater for GLES #else pglActiveTextureARB(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); // Ignore z so that we draw behind terrain (but don't disable GL_DEPTH_TEST // since we still want to write to the z buffer) glDepthFunc(GL_ALWAYS); for (size_t i = 0; i < m->lines.size(); ++i) { SOverlayLine* line = m->lines[i]; if (line->m_Coords.empty()) continue; ENSURE(line->m_Coords.size() % 3 == 0); glColor4fv(line->m_Color.FloatArray()); glLineWidth((float)line->m_Thickness); glInterleavedArrays(GL_V3F, sizeof(float)*3, &line->m_Coords[0]); glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)line->m_Coords.size()/3); } glDisableClientState(GL_VERTEX_ARRAY); glLineWidth(1.f); glDepthFunc(GL_LEQUAL); glDisable(GL_BLEND); #endif }
void TerrainRenderer::RenderSimpleWater() { #if !CONFIG2_GLES PROFILE3_GPU("simple water"); WaterManager* WaterMgr = g_Renderer.GetWaterManager(); CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); double time = WaterMgr->m_WaterTexTimer; double period = 1.6f; int curTex = (int)(time*60/period) % 60; WaterMgr->m_WaterTexture[curTex]->Bind(); // Shift the texture coordinates by these amounts to make the water "flow" float tx = -fmod(time, 81.0)/81.0; float ty = -fmod(time, 34.0)/34.0; float repeatPeriod = 16.0f; // Perform the shifting by using texture coordinate generation GLfloat texgenS0[4] = { 1/repeatPeriod, 0, 0, tx }; GLfloat texgenT0[4] = { 0, 0, 1/repeatPeriod, ty }; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS0); glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT0); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); // Set up texture environment to multiply vertex RGB by texture RGB and use vertex alpha GLfloat waterColor[4] = { WaterMgr->m_WaterColor.r, WaterMgr->m_WaterColor.g, WaterMgr->m_WaterColor.b, 1.0f }; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, waterColor); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); // Multiply by LOS texture losTexture.BindTexture(1); CMatrix3D losMatrix = losTexture.GetTextureMatrix(); GLfloat texgenS1[4] = { losMatrix[0], losMatrix[4], losMatrix[8], losMatrix[12] }; GLfloat texgenT1[4] = { losMatrix[1], losMatrix[5], losMatrix[9], losMatrix[13] }; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, texgenS1); glTexGenfv(GL_T, GL_OBJECT_PLANE, texgenT1); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); // Set the proper LOD bias glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy"); dummyShader->Bind(); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); for (size_t i = 0; i < m->visiblePatches.size(); ++i) { CPatchRData* data = m->visiblePatches[i]; data->RenderWater(dummyShader); } glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); dummyShader->Unbind(); g_Renderer.BindTexture(1, 0); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); pglActiveTextureARB(GL_TEXTURE0_ARB); // Clean up the texture matrix and blend mode glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); #endif }
// Render fancy water bool TerrainRenderer::RenderFancyWater() { PROFILE3_GPU("fancy water"); // If we're using fancy water, make sure its shader is loaded if (!m->fancyWaterShader) { std::map<CStr, CStr> defNull; m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("water_high", defNull); if (!m->fancyWaterShader) { LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n"); g_Renderer.m_Options.m_FancyWater = false; return false; } } WaterManager* WaterMgr = g_Renderer.GetWaterManager(); CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); double time = WaterMgr->m_WaterTexTimer; double period = 1.6; int curTex = (int)(time*60/period) % 60; m->fancyWaterShader->Bind(); m->fancyWaterShader->BindTexture("normalMap", WaterMgr->m_NormalMap[curTex]); // Shift the texture coordinates by these amounts to make the water "flow" float tx = -fmod(time, 81.0)/81.0; float ty = -fmod(time, 34.0)/34.0; float repeatPeriod = WaterMgr->m_RepeatPeriod; // Set the proper LOD bias #if !CONFIG2_GLES glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); #endif const CCamera& camera = g_Renderer.GetViewCamera(); CVector3D camPos = camera.m_Orientation.GetTranslation(); // Bind reflection and refraction textures m->fancyWaterShader->BindTexture("reflectionMap", WaterMgr->m_ReflectionTexture); m->fancyWaterShader->BindTexture("refractionMap", WaterMgr->m_RefractionTexture); m->fancyWaterShader->BindTexture("losMap", losTexture.GetTexture()); const CLightEnv& lightEnv = g_Renderer.GetLightEnv(); m->fancyWaterShader->Uniform("ambient", lightEnv.m_TerrainAmbientColor); m->fancyWaterShader->Uniform("sunDir", lightEnv.GetSunDir()); m->fancyWaterShader->Uniform("sunColor", lightEnv.m_SunColor.X); m->fancyWaterShader->Uniform("shininess", WaterMgr->m_Shininess); m->fancyWaterShader->Uniform("specularStrength", WaterMgr->m_SpecularStrength); m->fancyWaterShader->Uniform("waviness", WaterMgr->m_Waviness); m->fancyWaterShader->Uniform("murkiness", WaterMgr->m_Murkiness); m->fancyWaterShader->Uniform("fullDepth", WaterMgr->m_WaterFullDepth); m->fancyWaterShader->Uniform("tint", WaterMgr->m_WaterTint); m->fancyWaterShader->Uniform("reflectionTintStrength", WaterMgr->m_ReflectionTintStrength); m->fancyWaterShader->Uniform("reflectionTint", WaterMgr->m_ReflectionTint); m->fancyWaterShader->Uniform("translation", tx, ty); m->fancyWaterShader->Uniform("repeatScale", 1.0f / repeatPeriod); m->fancyWaterShader->Uniform("reflectionMatrix", WaterMgr->m_ReflectionMatrix); m->fancyWaterShader->Uniform("refractionMatrix", WaterMgr->m_RefractionMatrix); m->fancyWaterShader->Uniform("losMatrix", losTexture.GetTextureMatrix()); m->fancyWaterShader->Uniform("cameraPos", camPos); for (size_t i = 0; i < m->visiblePatches.size(); ++i) { CPatchRData* data = m->visiblePatches[i]; data->RenderWater(m->fancyWaterShader); } m->fancyWaterShader->Unbind(); pglActiveTextureARB(GL_TEXTURE0); glDisable(GL_BLEND); return true; }
void Render() { PROFILE3("render"); if (g_SoundManager) g_SoundManager->IdleTask(); ogl_WarnIfError(); g_Profiler2.RecordGPUFrameStart(); ogl_WarnIfError(); // prepare before starting the renderer frame if (g_Game && g_Game->IsGameStarted()) g_Game->GetView()->BeginFrame(); if (g_Game) g_Renderer.SetSimulation(g_Game->GetSimulation2()); // start new frame g_Renderer.BeginFrame(); ogl_WarnIfError(); if (g_Game && g_Game->IsGameStarted()) g_Game->GetView()->Render(); ogl_WarnIfError(); g_Renderer.RenderTextOverlays(); if (g_DoRenderGui) g_GUI->Draw(); ogl_WarnIfError(); // If we're in Atlas game view, render special overlays (e.g. editor bandbox) if (g_AtlasGameLoop && g_AtlasGameLoop->view) { g_AtlasGameLoop->view->DrawOverlays(); ogl_WarnIfError(); } // Text: glDisable(GL_DEPTH_TEST); g_Console->Render(); ogl_WarnIfError(); if (g_DoRenderLogger) g_Logger->Render(); ogl_WarnIfError(); // Profile information g_ProfileViewer.RenderProfile(); ogl_WarnIfError(); // Draw the cursor (or set the Windows cursor, on Windows) if (g_DoRenderCursor) { PROFILE3_GPU("cursor"); CStrW cursorName = g_CursorName; if (cursorName.empty()) { cursor_draw(g_VFS, NULL, g_mouse_x, g_yres-g_mouse_y, false); } else { bool forceGL = false; CFG_GET_VAL("nohwcursor", forceGL); #if CONFIG2_GLES #warning TODO: implement cursors for GLES #else // set up transform for GL cursor glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); CMatrix3D transform; transform.SetOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f); glLoadMatrixf(&transform._11); #endif #if OS_ANDROID #warning TODO: cursors for Android #else if (cursor_draw(g_VFS, cursorName.c_str(), g_mouse_x, g_yres-g_mouse_y, forceGL) < 0) LOGWARNING("Failed to draw cursor '%s'", utf8_from_wstring(cursorName)); #endif #if CONFIG2_GLES #warning TODO: implement cursors for GLES #else // restore transform glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); #endif } } glEnable(GL_DEPTH_TEST); g_Renderer.EndFrame(); PROFILE2_ATTR("draw calls: %d", (int)g_Renderer.GetStats().m_DrawCalls); PROFILE2_ATTR("terrain tris: %d", (int)g_Renderer.GetStats().m_TerrainTris); PROFILE2_ATTR("water tris: %d", (int)g_Renderer.GetStats().m_WaterTris); PROFILE2_ATTR("model tris: %d", (int)g_Renderer.GetStats().m_ModelTris); PROFILE2_ATTR("overlay tris: %d", (int)g_Renderer.GetStats().m_OverlayTris); PROFILE2_ATTR("blend splats: %d", (int)g_Renderer.GetStats().m_BlendSplats); PROFILE2_ATTR("particles: %d", (int)g_Renderer.GetStats().m_Particles); ogl_WarnIfError(); g_Profiler2.RecordGPUFrameEnd(); ogl_WarnIfError(); }
// Render void CProfileViewer::RenderProfile() { if (!m->profileVisible) return; if (!m->path.size()) { m->profileVisible = false; return; } PROFILE3_GPU("profile viewer"); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); AbstractProfileTable* table = m->path[m->path.size() - 1]; const std::vector<ProfileColumn>& columns = table->GetColumns(); size_t numrows = table->GetNumberRows(); CFont font(L"mono-stroke-10"); font.Bind(); int lineSpacing = font.GetLineSpacing(); // Render background GLint estimate_height; GLint estimate_width; estimate_width = 50; for(size_t i = 0; i < columns.size(); ++i) estimate_width += (GLint)columns[i].width; estimate_height = 3 + (GLint)numrows; if (m->path.size() > 1) estimate_height += 2; estimate_height = lineSpacing*estimate_height; glDisable(GL_TEXTURE_2D); glColor4ub(0,0,0,128); glBegin(GL_QUADS); glVertex2i(estimate_width, g_yres); glVertex2i(0, g_yres); glVertex2i(0, g_yres-estimate_height); glVertex2i(estimate_width, g_yres-estimate_height); glEnd(); glEnable(GL_TEXTURE_2D); // Print table and column titles glPushMatrix(); glTranslatef(2.0f, g_yres - lineSpacing, 0.0f ); glScalef(1.0f, -1.0f, 1.0f); glColor3ub(255, 255, 255); glPushMatrix(); glwprintf(L"%hs", table->GetTitle().c_str()); glPopMatrix(); glTranslatef( 20.0f, lineSpacing, 0.0f ); glPushMatrix(); for(size_t col = 0; col < columns.size(); ++col) { CStr text = columns[col].title; int w, h; font.CalculateStringSize(text.FromUTF8(), w, h); glPushMatrix(); if (col > 0) // right-align all but the first column glTranslatef(columns[col].width - w, 0, 0); glwprintf(L"%hs", text.c_str()); glPopMatrix(); glTranslatef(columns[col].width, 0, 0); } glPopMatrix(); glTranslatef( 0.0f, lineSpacing, 0.0f ); // Print rows int currentExpandId = 1; for(size_t row = 0; row < numrows; ++row) { glPushMatrix(); glDisable(GL_TEXTURE_2D); if (row % 2) glColor4ub(255, 255, 255, 16); else glColor4ub(0, 0, 0, 16); glBegin(GL_QUADS); glVertex2i(-22.f, 2.f); glVertex2i(estimate_width-22.f, 2.f); glVertex2i(estimate_width-22.f, 2.f-lineSpacing); glVertex2i(-22.f, 2.f-lineSpacing); glEnd(); glEnable(GL_TEXTURE_2D); if (table->IsHighlightRow(row)) glColor3ub(255, 128, 128); else glColor3ub(255, 255, 255); if (table->GetChild(row)) { glPushMatrix(); glTranslatef( -15.0f, 0.0f, 0.0f ); glwprintf(L"%d", currentExpandId); glPopMatrix(); currentExpandId++; } for(size_t col = 0; col < columns.size(); ++col) { CStr text = table->GetCellText(row, col); int w, h; font.CalculateStringSize(text.FromUTF8(), w, h); glPushMatrix(); if (col > 0) // right-align all but the first column glTranslatef(columns[col].width - w, 0, 0); glwprintf(L"%hs", text.c_str()); glPopMatrix(); glTranslatef(columns[col].width, 0, 0); } glPopMatrix(); glTranslatef( 0.0f, lineSpacing, 0.0f ); } glColor3ub(255, 255, 255); if (m->path.size() > 1) { glTranslatef( 0.0f, lineSpacing, 0.0f ); glPushMatrix(); glPushMatrix(); glTranslatef( -15.0f, 0.0f, 0.0f ); glwprintf( L"0" ); glPopMatrix(); glwprintf( L"back to parent" ); glPopMatrix(); } glPopMatrix(); glDisable(GL_BLEND); }
void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera) { PROFILE3_GPU("overlays (fg)"); #if CONFIG2_GLES #warning TODO: implement OverlayRenderer::RenderForegroundOverlays for GLES #else glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); CVector3D right = -viewCamera.m_Orientation.GetLeft(); CVector3D up = viewCamera.m_Orientation.GetUp(); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); CShaderProgramPtr shader; CShaderTechniquePtr tech; if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) { tech = g_Renderer.GetShaderManager().LoadEffect("foreground_overlay"); tech->BeginPass(); shader = tech->GetShader(); } else { shader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy", CShaderDefines()); shader->Bind(); } float uvs[8] = { 0,0, 1,0, 1,1, 0,1 }; shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, sizeof(float)*2, &uvs[0]); for (size_t i = 0; i < m->sprites.size(); ++i) { SOverlaySprite* sprite = m->sprites[i]; shader->BindTexture("baseTex", sprite->m_Texture); CVector3D pos[4] = { sprite->m_Position + right*sprite->m_X0 + up*sprite->m_Y0, sprite->m_Position + right*sprite->m_X1 + up*sprite->m_Y0, sprite->m_Position + right*sprite->m_X1 + up*sprite->m_Y1, sprite->m_Position + right*sprite->m_X0 + up*sprite->m_Y1 }; shader->VertexPointer(3, GL_FLOAT, sizeof(float)*3, &pos[0].X); glDrawArrays(GL_QUADS, 0, (GLsizei)4); g_Renderer.GetStats().m_DrawCalls++; g_Renderer.GetStats().m_OverlayTris += 2; } if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) { tech->EndPass(); } else { shader->Unbind(); } glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); #endif }
// Render void CProfileViewer::RenderProfile() { if (!m->profileVisible) return; if (!m->path.size()) { m->profileVisible = false; return; } PROFILE3_GPU("profile viewer"); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); AbstractProfileTable* table = m->path[m->path.size() - 1]; const std::vector<ProfileColumn>& columns = table->GetColumns(); size_t numrows = table->GetNumberRows(); CStrIntern font_name("mono-stroke-10"); CFontMetrics font(font_name); int lineSpacing = font.GetLineSpacing(); // Render background GLint estimate_height; GLint estimate_width; estimate_width = 50; for(size_t i = 0; i < columns.size(); ++i) estimate_width += (GLint)columns[i].width; estimate_height = 3 + (GLint)numrows; if (m->path.size() > 1) estimate_height += 2; estimate_height = lineSpacing*estimate_height; CShaderTechniquePtr solidTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid); solidTech->BeginPass(); CShaderProgramPtr solidShader = solidTech->GetShader(); solidShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.5f); CMatrix3D transform = GetDefaultGuiMatrix(); solidShader->Uniform(str_transform, transform); float backgroundVerts[] = { (float)estimate_width, 0.0f, 0.0f, 0.0f, 0.0f, (float)estimate_height, 0.0f, (float)estimate_height, (float)estimate_width, (float)estimate_height, (float)estimate_width, 0.0f }; solidShader->VertexPointer(2, GL_FLOAT, 0, backgroundVerts); solidShader->AssertPointersBound(); glDrawArrays(GL_TRIANGLES, 0, 6); transform.PostTranslate(22.0f, lineSpacing*3.0f, 0.0f); solidShader->Uniform(str_transform, transform); // Draw row backgrounds for (size_t row = 0; row < numrows; ++row) { if (row % 2) solidShader->Uniform(str_color, 1.0f, 1.0f, 1.0f, 0.1f); else solidShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.1f); float rowVerts[] = { -22.f, 2.f, estimate_width-22.f, 2.f, estimate_width-22.f, 2.f-lineSpacing, estimate_width-22.f, 2.f-lineSpacing, -22.f, 2.f-lineSpacing, -22.f, 2.f }; solidShader->VertexPointer(2, GL_FLOAT, 0, rowVerts); solidShader->AssertPointersBound(); glDrawArrays(GL_TRIANGLES, 0, 6); transform.PostTranslate(0.0f, lineSpacing, 0.0f); solidShader->Uniform(str_transform, transform); } solidTech->EndPass(); // Print table and column titles CShaderTechniquePtr textTech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text); textTech->BeginPass(); CTextRenderer textRenderer(textTech->GetShader()); textRenderer.Font(font_name); textRenderer.Color(1.0f, 1.0f, 1.0f); textRenderer.PrintfAt(2.0f, lineSpacing, L"%hs", table->GetTitle().c_str()); textRenderer.Translate(22.0f, lineSpacing*2.0f, 0.0f); float colX = 0.0f; for (size_t col = 0; col < columns.size(); ++col) { CStrW text = columns[col].title.FromUTF8(); int w, h; font.CalculateStringSize(text.c_str(), w, h); float x = colX; if (col > 0) // right-align all but the first column x += columns[col].width - w; textRenderer.Put(x, 0.0f, text.c_str()); colX += columns[col].width; } textRenderer.Translate(0.0f, lineSpacing, 0.0f); // Print rows int currentExpandId = 1; for (size_t row = 0; row < numrows; ++row) { if (table->IsHighlightRow(row)) textRenderer.Color(1.0f, 0.5f, 0.5f); else textRenderer.Color(1.0f, 1.0f, 1.0f); if (table->GetChild(row)) { textRenderer.PrintfAt(-15.0f, 0.0f, L"%d", currentExpandId); currentExpandId++; } float colX = 0.0f; for (size_t col = 0; col < columns.size(); ++col) { CStrW text = table->GetCellText(row, col).FromUTF8(); int w, h; font.CalculateStringSize(text.c_str(), w, h); float x = colX; if (col > 0) // right-align all but the first column x += columns[col].width - w; textRenderer.Put(x, 0.0f, text.c_str()); colX += columns[col].width; } textRenderer.Translate(0.0f, lineSpacing, 0.0f); } textRenderer.Color(1.0f, 1.0f, 1.0f); if (m->path.size() > 1) { textRenderer.Translate(0.0f, lineSpacing, 0.0f); textRenderer.Put(-15.0f, 0.0f, L"0"); textRenderer.Put(0.0f, 0.0f, L"back to parent"); } textRenderer.Render(); textTech->EndPass(); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); }
// Render fancy water bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap* shadow) { PROFILE3_GPU("fancy water"); WaterManager* WaterMgr = g_Renderer.GetWaterManager(); CShaderDefines defines = context; WaterMgr->UpdateQuality(); // If we're using fancy water, make sure its shader is loaded if (!m->fancyWaterShader || WaterMgr->m_NeedsReloading) { if (WaterMgr->m_WaterNormal) defines.Add(str_USE_NORMALS, str_1); if (WaterMgr->m_WaterRealDepth) defines.Add(str_USE_REAL_DEPTH, str_1); if (WaterMgr->m_WaterFoam) defines.Add(str_USE_FOAM, str_1); if (WaterMgr->m_WaterCoastalWaves && false) defines.Add(str_USE_WAVES, str_1); if (WaterMgr->m_WaterRefraction) defines.Add(str_USE_REFRACTION, str_1); if (WaterMgr->m_WaterReflection) defines.Add(str_USE_REFLECTION, str_1); if (shadow && WaterMgr->m_WaterShadows) defines.Add(str_USE_SHADOWS, str_1); m->wavesShader = g_Renderer.GetShaderManager().LoadProgram("glsl/waves", defines); if (!m->wavesShader) { LOGERROR(L"Failed to load waves shader. Deactivating waves.\n"); g_Renderer.SetOptionBool(CRenderer::OPT_WATERCOASTALWAVES, false); defines.Add(str_USE_WAVES, str_0); } // haven't updated the ARB shader yet so I'll always load the GLSL /*if (!g_Renderer.m_Options.m_PreferGLSL && !superFancy) m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("arb/water_high", defines); else*/ m->fancyWaterShader = g_Renderer.GetShaderManager().LoadProgram("glsl/water_high", defines); if (!m->fancyWaterShader) { LOGERROR(L"Failed to load water shader. Falling back to non-fancy water.\n"); WaterMgr->m_RenderWater = false; return false; } WaterMgr->m_NeedsReloading = false; } CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture(); GLuint depthTex; // creating the real depth texture using the depth buffer. if (WaterMgr->m_WaterRealDepth) { if (WaterMgr->m_depthTT == 0) { glGenTextures(1, (GLuint*)&depthTex); WaterMgr->m_depthTT = depthTex; glBindTexture(GL_TEXTURE_2D, WaterMgr->m_depthTT); #if CONFIG2_GLES GLenum format = GL_DEPTH_COMPONENT; #else GLenum format = GL_DEPTH_COMPONENT32; #endif // TODO: use POT texture glTexImage2D(GL_TEXTURE_2D, 0, format, g_Renderer.GetWidth(), g_Renderer.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE,NULL); } glBindTexture(GL_TEXTURE_2D, WaterMgr->m_depthTT); #if !CONFIG2_GLES glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight(), 0); glBindTexture(GL_TEXTURE_2D, 0); } // Calculating the advanced informations about Foam and all if the quality calls for it. /*if (WaterMgr->m_NeedInfoUpdate && (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves)) { WaterMgr->m_NeedInfoUpdate = false; WaterMgr->CreateSuperfancyInfo(); }*/ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); double time = WaterMgr->m_WaterTexTimer; double period = 8; int curTex = (int)(time*60/period) % 60; int nexTex = (curTex + 1) % 60; GLuint FramebufferName = 0; // rendering waves to a framebuffer // TODO: reactivate this with something that looks good. if (false && WaterMgr->m_WaterCoastalWaves && WaterMgr->m_VBWaves && !g_AtlasGameLoop->running) { // Save the post-processing framebuffer. GLint fbo; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo); pglGenFramebuffersEXT(1, &FramebufferName); pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FramebufferName); GLuint renderedTexture; if (WaterMgr->m_waveTT == 0) { glGenTextures(1, &renderedTexture); WaterMgr->m_waveTT = renderedTexture; glBindTexture(GL_TEXTURE_2D, WaterMgr->m_waveTT); // TODO: use POT texture glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0,GL_RGBA, GL_UNSIGNED_BYTE, 0); } glBindTexture(GL_TEXTURE_2D, WaterMgr->m_waveTT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, WaterMgr->m_waveTT, 0); glClearColor(0.5f,0.5f,1.0f,0.0f); glClear(GL_COLOR_BUFFER_BIT); // rendering m->wavesShader->Bind(); m->wavesShader->BindTexture(str_waveTex, WaterMgr->m_Wave); m->wavesShader->Uniform(str_time, (float)time); m->wavesShader->Uniform(str_waviness, WaterMgr->m_Waviness); m->wavesShader->Uniform(str_mapSize, (float)(WaterMgr->m_TexSize)); SWavesVertex *base=(SWavesVertex *)WaterMgr->m_VBWaves->m_Owner->Bind(); GLsizei stride = sizeof(SWavesVertex); m->wavesShader->VertexPointer(3, GL_FLOAT, stride, &base[WaterMgr->m_VBWaves->m_Index].m_Position); m->wavesShader->TexCoordPointer(GL_TEXTURE0,2,GL_BYTE, stride,&base[WaterMgr->m_VBWaves->m_Index].m_UV); m->wavesShader->AssertPointersBound(); u8* indexBase = WaterMgr->m_VBWavesIndices->m_Owner->Bind(); glDrawElements(GL_TRIANGLES, (GLsizei) WaterMgr->m_VBWavesIndices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(WaterMgr->m_VBWavesIndices->m_Index)); g_Renderer.m_Stats.m_DrawCalls++; CVertexBuffer::Unbind(); m->wavesShader->Unbind(); // rebind post-processing frambuffer. pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); glBindTexture(GL_TEXTURE_2D, 0); } m->fancyWaterShader->Bind(); // Shift the texture coordinates by these amounts to make the water "flow" float tx = -fmod(time, 81.0 / (WaterMgr->m_Waviness/20.0 + 0.8) )/(81.0/ (WaterMgr->m_Waviness/20.0 + 0.8) ); float ty = -fmod(time, 34.0 / (WaterMgr->m_Waviness/20.0 + 0.8) )/(34.0/ (WaterMgr->m_Waviness/20.0 + 0.8) ); float repeatPeriod = WaterMgr->m_RepeatPeriod; const CCamera& camera = g_Renderer.GetViewCamera(); CVector3D camPos = camera.m_Orientation.GetTranslation(); m->fancyWaterShader->BindTexture(str_normalMap, WaterMgr->m_NormalMap[curTex]); m->fancyWaterShader->BindTexture(str_normalMap2, WaterMgr->m_NormalMap[nexTex]); if (WaterMgr->m_WaterFoam || WaterMgr->m_WaterCoastalWaves) { m->fancyWaterShader->BindTexture(str_Foam, WaterMgr->m_Foam); m->fancyWaterShader->Uniform(str_mapSize, (float)(WaterMgr->m_TexSize)); } if (WaterMgr->m_WaterRealDepth) m->fancyWaterShader->BindTexture(str_depthTex, WaterMgr->m_depthTT); if (WaterMgr->m_WaterCoastalWaves) m->fancyWaterShader->BindTexture(str_waveTex, WaterMgr->m_waveTT); if (WaterMgr->m_WaterReflection) m->fancyWaterShader->BindTexture(str_reflectionMap, WaterMgr->m_ReflectionTexture); if (WaterMgr->m_WaterRefraction) m->fancyWaterShader->BindTexture(str_refractionMap, WaterMgr->m_RefractionTexture); m->fancyWaterShader->BindTexture(str_losMap, losTexture.GetTextureSmooth()); const CLightEnv& lightEnv = g_Renderer.GetLightEnv(); // TODO: only bind what's really needed for that. m->fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir()); m->fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor.X); m->fancyWaterShader->Uniform(str_color, WaterMgr->m_WaterColor); m->fancyWaterShader->Uniform(str_specularStrength, WaterMgr->m_SpecularStrength); m->fancyWaterShader->Uniform(str_waviness, WaterMgr->m_Waviness); m->fancyWaterShader->Uniform(str_murkiness, WaterMgr->m_Murkiness); m->fancyWaterShader->Uniform(str_tint, WaterMgr->m_WaterTint); m->fancyWaterShader->Uniform(str_reflectionTintStrength, WaterMgr->m_ReflectionTintStrength); m->fancyWaterShader->Uniform(str_reflectionTint, WaterMgr->m_ReflectionTint); m->fancyWaterShader->Uniform(str_translation, tx, ty); m->fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod); m->fancyWaterShader->Uniform(str_reflectionMatrix, WaterMgr->m_ReflectionMatrix); m->fancyWaterShader->Uniform(str_refractionMatrix, WaterMgr->m_RefractionMatrix); m->fancyWaterShader->Uniform(str_losMatrix, losTexture.GetTextureMatrix()); m->fancyWaterShader->Uniform(str_cameraPos, camPos); m->fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor); m->fancyWaterShader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f); m->fancyWaterShader->Uniform(str_time, (float)time); m->fancyWaterShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f); m->fancyWaterShader->BindTexture(str_skyCube, g_Renderer.GetSkyManager()->GetSkyCube()); if (shadow && WaterMgr->m_WaterShadows) { m->fancyWaterShader->BindTexture(str_shadowTex, shadow->GetTexture()); m->fancyWaterShader->Uniform(str_shadowTransform, shadow->GetTextureMatrix()); int width = shadow->GetWidth(); int height = shadow->GetHeight(); m->fancyWaterShader->Uniform(str_shadowScale, width, height, 1.0f / width, 1.0f / height); } for (size_t i = 0; i < m->visiblePatches.size(); ++i) { CPatchRData* data = m->visiblePatches[i]; data->RenderWater(m->fancyWaterShader); } m->fancyWaterShader->Unbind(); pglActiveTextureARB(GL_TEXTURE0); pglDeleteFramebuffersEXT(1, &FramebufferName); glDisable(GL_BLEND); return true; }