void CPostprocManager::ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass) { // select the other FBO for rendering if (!m_WhichBuffer) pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo); else pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); shaderTech1->BeginPass(pass); CShaderProgramPtr shader = shaderTech1->GetShader(pass); shader->Bind(); // Use the textures from the current FBO as input to the shader. // We also bind a bunch of other textures and parameters, but since // this only happens once per frame the overhead is negligible. if (m_WhichBuffer) shader->BindTexture(str_renderedTex, m_ColourTex1); else shader->BindTexture(str_renderedTex, m_ColourTex2); shader->BindTexture(str_depthTex, m_DepthTex); shader->BindTexture(str_blurTex2, m_BlurTex2a); shader->BindTexture(str_blurTex4, m_BlurTex4a); shader->BindTexture(str_blurTex8, m_BlurTex8a); shader->Uniform(str_width, m_Width); shader->Uniform(str_height, m_Height); shader->Uniform(str_zNear, g_Game->GetView()->GetNear()); shader->Uniform(str_zFar, g_Game->GetView()->GetFar()); shader->Uniform(str_brightness, g_LightEnv.m_Brightness); shader->Uniform(str_hdr, g_LightEnv.m_Contrast); shader->Uniform(str_saturation, g_LightEnv.m_Saturation); shader->Uniform(str_bloom, g_LightEnv.m_Bloom); glBegin(GL_QUADS); glColor4f(1.f, 1.f, 1.f, 1.f); glTexCoord2f(1.0, 1.0); glVertex2f(1,1); glTexCoord2f(0.0, 1.0); glVertex2f(-1,1); glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1); glTexCoord2f(1.0, 0.0); glVertex2f(1,-1); glEnd(); shader->Unbind(); shaderTech1->EndPass(pass); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); m_WhichBuffer = !m_WhichBuffer; }
void CLOSTexture::InterpolateLOS() { if (CRenderer::IsInitialised() && !g_Renderer.m_Options.m_SmoothLOS) return; if (m_Dirty) { RecomputeTexture(0); m_Dirty = false; } GLint originalFBO; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originalFBO); pglBindFramebufferEXT(GL_FRAMEBUFFER, m_smoothFbo); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, whichTex ? m_TextureSmooth2 : m_TextureSmooth1, 0); GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { LOGWARNING(L"LOS framebuffer object incomplete: 0x%04X", status); } m_smoothShader->BeginPass(); CShaderProgramPtr shader = m_smoothShader->GetShader(); shader->Bind(); shader->BindTexture("losTex1", m_Texture); shader->BindTexture("losTex2", whichTex ? m_TextureSmooth1 : m_TextureSmooth2); shader->Uniform("delta", (float)g_Renderer.GetTimeManager().GetFrameDelta() * 4.0f, 0.0f, 0.0f, 0.0f); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0, 0, m_TextureSize, m_TextureSize); glBegin(GL_QUADS); glColor4f(1.f, 1.f, 1.f, 1.f); glTexCoord2f(1.0, 1.0); glVertex2f(1,1); glTexCoord2f(0.0, 1.0); glVertex2f(-1,1); glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1); glTexCoord2f(1.0, 0.0); glVertex2f(1,-1); glEnd(); glPopAttrib(); shader->Unbind(); m_smoothShader->EndPass(); pglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, originalFBO); whichTex = !whichTex; }
void ParticleRenderer::RenderParticles(bool solidColor) { CShaderProgramPtr shader = solidColor ? m->shaderSolid : m->shader; shader->Bind(); if (!solidColor) glEnable(GL_BLEND); glDepthMask(0); glEnableClientState(GL_VERTEX_ARRAY); if (!solidColor) glEnableClientState(GL_COLOR_ARRAY); pglClientActiveTextureARB(GL_TEXTURE1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); pglClientActiveTextureARB(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); for (size_t i = 0; i < m->emitters.size(); ++i) { CParticleEmitter* emitter = m->emitters[i]; emitter->Bind(); emitter->RenderArray(); } CVertexBuffer::Unbind(); pglBlendEquationEXT(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); pglClientActiveTextureARB(GL_TEXTURE1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); pglClientActiveTextureARB(GL_TEXTURE0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_BLEND); glDepthMask(1); shader->Unbind(); }
/////////////////////////////////////////////////////////////////// // Render un-textured patches as polygons void TerrainRenderer::RenderPatches(bool filtered) { ENSURE(m->phase == Phase_Render); std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches; if (visiblePatches.empty()) return; #if CONFIG2_GLES #warning TODO: implement TerrainRenderer::RenderPatches for GLES #else CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy"); dummyShader->Bind(); glEnableClientState(GL_VERTEX_ARRAY); CPatchRData::RenderStreams(visiblePatches, dummyShader, STREAM_POS); glDisableClientState(GL_VERTEX_ARRAY); dummyShader->Unbind(); #endif }
void WaterManager::RenderWaves(const CFrustum& frustrum) { #if CONFIG2_GLES #warning Fix WaterManager::RenderWaves on GLES #else if (g_Renderer.m_SkipSubmit || !m_WaterFancyEffects) return; pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FancyEffectsFBO); GLuint attachments[2] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT }; pglDrawBuffers(2, attachments); glClearColor(0.0f,0.0f, 0.0f,0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); CShaderDefines none; CShaderProgramPtr shad = g_Renderer.GetShaderManager().LoadProgram("glsl/waves", none); shad->Bind(); shad->BindTexture(str_waveTex, m_WaveTex); shad->BindTexture(str_foamTex, m_FoamTex); shad->Uniform(str_time, (float)m_WaterTexTimer); shad->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection()); for (size_t a = 0; a < m_ShoreWaves.size(); ++a) { if (!frustrum.IsBoxVisible(m_ShoreWaves[a]->m_AABB)) continue; CVertexBuffer::VBChunk* VBchunk = m_ShoreWaves[a]->m_VBvertices; SWavesVertex* base = (SWavesVertex*)VBchunk->m_Owner->Bind(); // setup data pointers GLsizei stride = sizeof(SWavesVertex); shad->VertexPointer(3, GL_FLOAT, stride, &base[VBchunk->m_Index].m_BasePosition); shad->TexCoordPointer(GL_TEXTURE0, 2, GL_UNSIGNED_BYTE, stride, &base[VBchunk->m_Index].m_UV); // NormalPointer(gl_FLOAT, stride, &base[m_VBWater->m_Index].m_UV) pglVertexAttribPointerARB(2, 2, GL_FLOAT, GL_TRUE, stride, &base[VBchunk->m_Index].m_PerpVect); // replaces commented above because my normal is vec2 shad->VertexAttribPointer(str_a_apexPosition, 3, GL_FLOAT, false, stride, &base[VBchunk->m_Index].m_ApexPosition); shad->VertexAttribPointer(str_a_splashPosition, 3, GL_FLOAT, false, stride, &base[VBchunk->m_Index].m_SplashPosition); shad->VertexAttribPointer(str_a_retreatPosition, 3, GL_FLOAT, false, stride, &base[VBchunk->m_Index].m_RetreatPosition); shad->AssertPointersBound(); shad->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff); shad->Uniform(str_width, (int)m_ShoreWaves[a]->m_Width); u8* indexBase = m_ShoreWaves_VBIndices->m_Owner->Bind(); glDrawElements(GL_TRIANGLES, (GLsizei) (m_ShoreWaves[a]->m_Width-1)*(7*6), GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*(m_ShoreWaves_VBIndices->m_Index)); shad->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff + 6.0f); // TODO: figure out why this doesn't work. //g_Renderer.m_Stats.m_DrawCalls++; //g_Renderer.m_Stats.m_WaterTris += m_ShoreWaves_VBIndices->m_Count / 3; CVertexBuffer::Unbind(); } shad->Unbind(); pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); #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 }
/////////////////////////////////////////////////////////////////// // Full-featured terrain rendering with blending and everything void TerrainRenderer::RenderTerrain(bool filtered) { #if CONFIG2_GLES UNUSED2(filtered); #else ENSURE(m->phase == Phase_Render); std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches; std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals; if (visiblePatches.empty() && visibleDecals.empty()) return; CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy"); dummyShader->Bind(); // render the solid black sides of the map first g_Renderer.BindTexture(0, 0); glEnableClientState(GL_VERTEX_ARRAY); glColor3f(0, 0, 0); PROFILE_START("render terrain sides"); for (size_t i = 0; i < visiblePatches.size(); ++i) visiblePatches[i]->RenderSides(dummyShader); PROFILE_END("render terrain sides"); // switch on required client states glEnableClientState(GL_TEXTURE_COORD_ARRAY); // render everything fullbright // set up texture environment for base pass pglActiveTextureARB(GL_TEXTURE0); pglClientActiveTextureARB(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); // Set alpha to 1.0 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); static const float one[4] = { 1.f, 1.f, 1.f, 1.f }; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, one); PROFILE_START("render terrain base"); CPatchRData::RenderBases(visiblePatches, dummyShader, true); PROFILE_END("render terrain base"); // render blends // switch on the composite alpha map texture (void)ogl_tex_bind(g_Renderer.m_hCompositeAlphaMap, 1); // switch on second uv set pglClientActiveTextureARB(GL_TEXTURE1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // setup additional texenv required by blend pass pglActiveTextureARB(GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); 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_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA); // switch on blending glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // no need to write to the depth buffer a second time glDepthMask(0); // The decal color array contains lighting data, which we don't want in this non-shader mode glDisableClientState(GL_COLOR_ARRAY); // render blend passes for each patch PROFILE_START("render terrain blends"); CPatchRData::RenderBlends(visiblePatches, dummyShader, true); PROFILE_END("render terrain blends"); // Disable second texcoord array pglClientActiveTextureARB(GL_TEXTURE1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Render terrain decals g_Renderer.BindTexture(1, 0); pglActiveTextureARB(GL_TEXTURE0); pglClientActiveTextureARB(GL_TEXTURE0); 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_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); PROFILE_START("render terrain decals"); for (size_t i = 0; i < visibleDecals.size(); ++i) visibleDecals[i]->Render(dummyShader, true); PROFILE_END("render terrain decals"); // Now apply lighting const CLightEnv& lightEnv = g_Renderer.GetLightEnv(); pglClientActiveTextureARB(GL_TEXTURE0); glEnableClientState(GL_COLOR_ARRAY); // diffuse lighting colours glBlendFunc(GL_DST_COLOR, GL_ZERO); // GL_TEXTURE_ENV_COLOR requires four floats, so we shouldn't use the RGBColor directly float terrainAmbientColor[4] = { lightEnv.m_TerrainAmbientColor.X, lightEnv.m_TerrainAmbientColor.Y, lightEnv.m_TerrainAmbientColor.Z, 1.f }; CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture(); int streamflags = STREAM_POS|STREAM_COLOR; pglActiveTextureARB(GL_TEXTURE0); // We're not going to use a texture here, but we have to have a valid texture // bound else the texture unit will be disabled. // We should still have a bound splat texture from some earlier rendering, // so assume that's still valid to use. // (TODO: That's a bit of an ugly hack.) // No shadows: (Ambient + Diffuse) * LOS glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD); 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_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_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, terrainAmbientColor); losTexture.BindTexture(1); pglClientActiveTextureARB(GL_TEXTURE1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); streamflags |= STREAM_POSTOUV1; glMatrixMode(GL_TEXTURE); glLoadMatrixf(&losTexture.GetTextureMatrix()._11); glMatrixMode(GL_MODELVIEW); 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); pglActiveTextureARB(GL_TEXTURE0); pglClientActiveTextureARB(GL_TEXTURE0); PROFILE_START("render terrain streams"); CPatchRData::RenderStreams(visiblePatches, dummyShader, streamflags); PROFILE_END("render terrain streams"); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); // restore OpenGL state g_Renderer.BindTexture(1, 0); pglClientActiveTextureARB(GL_TEXTURE1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); pglClientActiveTextureARB(GL_TEXTURE0); pglActiveTextureARB(GL_TEXTURE0); glDepthMask(1); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); dummyShader->Unbind(); #endif }
void CMiniMap::Draw() { PROFILE3("render minimap"); // The terrain isn't actually initialized until the map is loaded, which // happens when the game is started, so abort until then. if(!(GetGUI() && g_Game && g_Game->IsGameStarted())) return; CSimulation2* sim = g_Game->GetSimulation2(); CmpPtr<ICmpRangeManager> cmpRangeManager(*sim, SYSTEM_ENTITY); ENSURE(cmpRangeManager); // Set our globals in case they hadn't been set before m_Camera = g_Game->GetView()->GetCamera(); m_Terrain = g_Game->GetWorld()->GetTerrain(); m_Width = (u32)(m_CachedActualSize.right - m_CachedActualSize.left); m_Height = (u32)(m_CachedActualSize.bottom - m_CachedActualSize.top); m_MapSize = m_Terrain->GetVerticesPerSide(); m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize); m_MapScale = (cmpRangeManager->GetLosCircular() ? 1.f : 1.414f); if(!m_TerrainTexture || g_GameRestarted) CreateTextures(); // only update 2x / second // (note: since units only move a few pixels per second on the minimap, // we can get away with infrequent updates; this is slow) static double last_time; const double cur_time = timer_Time(); if(cur_time - last_time > 0.5) { last_time = cur_time; if(m_TerrainDirty) RebuildTerrainTexture(); } glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); CMatrix3D matrix = GetDefaultGuiMatrix(); glLoadMatrixf(&matrix._11); // Disable depth updates to prevent apparent z-fighting-related issues // with some drivers causing units to get drawn behind the texture glDepthMask(0); CShaderProgramPtr shader; CShaderTechniquePtr tech; if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) { CShaderDefines defines; defines.Add("MINIMAP_BASE", "1"); tech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("minimap"), g_Renderer.GetSystemShaderDefines(), defines); tech->BeginPass(); shader = tech->GetShader(); } else { shader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy", CShaderDefines()); shader->Bind(); } const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom; const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top; const float z = GetBufferedZ(); const float texCoordMax = (float)(m_MapSize - 1) / (float)m_TextureSize; const float angle = GetAngle(); // Draw the main textured quad //g_Renderer.BindTexture(0, m_TerrainTexture); shader->BindTexture("baseTex", m_TerrainTexture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); DrawTexture(texCoordMax, angle, x, y, x2, y2, z); // Draw territory boundaries CTerritoryTexture& territoryTexture = g_Game->GetView()->GetTerritoryTexture(); shader->BindTexture("baseTex", territoryTexture.GetTexture()); //territoryTexture.BindTexture(0); glEnable(GL_BLEND); glMatrixMode(GL_TEXTURE); glLoadMatrixf(territoryTexture.GetMinimapTextureMatrix()); glMatrixMode(GL_MODELVIEW); DrawTexture(1.0f, angle, x, y, x2, y2, z); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glDisable(GL_BLEND); // Draw the LOS quad in black, using alpha values from the LOS texture CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) { tech->EndPass(); CShaderDefines defines; defines.Add("MINIMAP_LOS", "1"); tech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("minimap"), g_Renderer.GetSystemShaderDefines(), defines); tech->BeginPass(); shader = tech->GetShader(); } shader->BindTexture("baseTex", losTexture.GetTexture()); //losTexture.BindTexture(0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor3f(0.0f, 0.0f, 0.0f); glMatrixMode(GL_TEXTURE); glLoadMatrixf(losTexture.GetMinimapTextureMatrix()); glMatrixMode(GL_MODELVIEW); DrawTexture(1.0f, angle, x, y, x2, y2, z); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glDisable(GL_BLEND); if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) { tech->EndPass(); CShaderDefines defines; defines.Add("MINIMAP_POINT", "1"); tech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("minimap"), g_Renderer.GetSystemShaderDefines(), defines); tech->BeginPass(); shader = tech->GetShader(); } // Set up the matrix for drawing points and lines glPushMatrix(); glTranslatef(x, y, z); // Rotate around the center of the map glTranslatef((x2-x)/2.f, (y2-y)/2.f, 0.f); // Scale square maps to fit in circular minimap area float unitScale = (cmpRangeManager->GetLosCircular() ? 1.f : m_MapScale/2.f); glScalef(unitScale, unitScale, 1.f); glRotatef(angle * 180.f/M_PI, 0.f, 0.f, 1.f); glTranslatef(-(x2-x)/2.f, -(y2-y)/2.f, 0.f); PROFILE_START("minimap units"); // Don't enable GL_POINT_SMOOTH because it's far too slow // (~70msec/frame on a GF4 rendering a thousand points) glPointSize(3.f); float sx = (float)m_Width / ((m_MapSize - 1) * TERRAIN_TILE_SIZE); float sy = (float)m_Height / ((m_MapSize - 1) * TERRAIN_TILE_SIZE); CSimulation2::InterfaceList ents = sim->GetEntitiesWithInterface(IID_Minimap); std::vector<MinimapUnitVertex> vertexArray; vertexArray.reserve(ents.size()); for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it) { MinimapUnitVertex v; ICmpMinimap* cmpMinimap = static_cast<ICmpMinimap*>(it->second); entity_pos_t posX, posZ; if (cmpMinimap->GetRenderData(v.r, v.g, v.b, posX, posZ)) { ICmpRangeManager::ELosVisibility vis = cmpRangeManager->GetLosVisibility(it->first, g_Game->GetPlayerID()); if (vis != ICmpRangeManager::VIS_HIDDEN) { v.a = 255; v.x = posX.ToFloat()*sx; v.y = -posZ.ToFloat()*sy; vertexArray.push_back(v); } } } if (!vertexArray.empty()) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); shader->VertexPointer(2, GL_FLOAT, sizeof(MinimapUnitVertex), &vertexArray[0].x); shader->ColorPointer(4, GL_UNSIGNED_BYTE, sizeof(MinimapUnitVertex), &vertexArray[0].r); glDrawArrays(GL_POINTS, 0, (GLsizei)vertexArray.size()); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } PROFILE_END("minimap units"); if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) { tech->EndPass(); CShaderDefines defines; defines.Add("MINIMAP_LINE", "1"); tech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("minimap"), g_Renderer.GetSystemShaderDefines(), defines); tech->BeginPass(); shader = tech->GetShader(); } DrawViewRect(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER) { tech->EndPass(); } else { shader->Unbind(); } // Reset everything back to normal glPointSize(1.0f); glEnable(GL_TEXTURE_2D); glDepthMask(1); }
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 }
void TerrainRenderer::RenderTerrainOverlayTexture(CMatrix3D& textureMatrix) { #if CONFIG2_GLES #warning TODO: implement TerrainRenderer::RenderTerrainOverlayTexture for GLES UNUSED2(textureMatrix); #else ENSURE(m->phase == Phase_Render); std::vector<CPatchRData*>& visiblePatches = m->visiblePatches; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glMatrixMode(GL_TEXTURE); glLoadMatrixf(&textureMatrix._11); glMatrixMode(GL_MODELVIEW); CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy", CShaderDefines()); dummyShader->Bind(); CPatchRData::RenderStreams(visiblePatches, dummyShader, STREAM_POS|STREAM_POSTOUV0); dummyShader->Unbind(); // To make the overlay visible over water, render an additional map-sized // water-height patch CBoundingBoxAligned waterBounds; for (size_t i = 0; i < m->visiblePatches.size(); ++i) { CPatchRData* data = m->visiblePatches[i]; waterBounds += data->GetWaterBounds(); } if (!waterBounds.IsEmpty()) { float h = g_Renderer.GetWaterManager()->m_WaterHeight + 0.05f; // add a delta to avoid z-fighting float waterPos[] = { waterBounds[0].X, h, waterBounds[0].Z, waterBounds[1].X, h, waterBounds[0].Z, waterBounds[0].X, h, waterBounds[1].Z, waterBounds[1].X, h, waterBounds[1].Z }; glVertexPointer(3, GL_FLOAT, 3*sizeof(float), waterPos); glTexCoordPointer(3, GL_FLOAT, 3*sizeof(float), waterPos); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glDepthMask(1); glDisable(GL_BLEND); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif }