void TerrainTextureOverlay::RenderAfterWater() { CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); ssize_t w = (ssize_t)(terrain->GetTilesPerSide() * m_TexelsPerTile); ssize_t h = (ssize_t)(terrain->GetTilesPerSide() * m_TexelsPerTile); pglActiveTextureARB(GL_TEXTURE0); // Recreate the texture with new size if necessary if (round_up_to_pow2(w) != m_TextureW || round_up_to_pow2(h) != m_TextureH) { m_TextureW = round_up_to_pow2(w); m_TextureH = round_up_to_pow2(h); glBindTexture(GL_TEXTURE_2D, m_Texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureW, m_TextureH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } u8* data = (u8*)calloc(w * h, 4); BuildTextureRGBA(data, w, h); glBindTexture(GL_TEXTURE_2D, m_Texture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data); free(data); CMatrix3D matrix; matrix.SetZero(); matrix._11 = m_TexelsPerTile / (m_TextureW * TERRAIN_TILE_SIZE); matrix._23 = m_TexelsPerTile / (m_TextureH * TERRAIN_TILE_SIZE); matrix._44 = 1; g_Renderer.GetTerrainRenderer().RenderTerrainOverlayTexture(matrix); }
/////////////////////////////////////////////////////////////////////////////////////////////////// // CalcShadowMatrices: calculate required matrices for shadow map generation - the light's // projection and transformation matrices void ShadowMapInternals::CalcShadowMatrices() { CRenderer& renderer = g_Renderer; float minZ = ShadowBound[0].Z; ShadowBound.IntersectFrustumConservative(LightspaceCamera.GetFrustum()); // round off the shadow boundaries to sane increments to help reduce swim effect float boundInc = 16.0f; ShadowBound[0].X = floor(ShadowBound[0].X / boundInc) * boundInc; ShadowBound[0].Y = floor(ShadowBound[0].Y / boundInc) * boundInc; ShadowBound[1].X = ceil(ShadowBound[1].X / boundInc) * boundInc; ShadowBound[1].Y = ceil(ShadowBound[1].Y / boundInc) * boundInc; // minimum Z bound must not be clipped too much, because objects that lie outside // the shadow bounds cannot cast shadows either // the 2.0 is rather arbitrary: it should be big enough so that we won't accidently miss // a shadow generator, and small enough not to affect Z precision ShadowBound[0].Z = minZ - 2.0; // Setup orthogonal projection (lightspace -> clip space) for shadowmap rendering CVector3D scale = ShadowBound[1] - ShadowBound[0]; CVector3D shift = (ShadowBound[1] + ShadowBound[0]) * -0.5; if (scale.X < 1.0) scale.X = 1.0; if (scale.Y < 1.0) scale.Y = 1.0; if (scale.Z < 1.0) scale.Z = 1.0; scale.X = 2.0 / scale.X; scale.Y = 2.0 / scale.Y; scale.Z = 2.0 / scale.Z; // make sure a given world position falls on a consistent shadowmap texel fractional offset float offsetX = fmod(ShadowBound[0].X - LightTransform._14, 2.0f/(scale.X*EffectiveWidth)); float offsetY = fmod(ShadowBound[0].Y - LightTransform._24, 2.0f/(scale.Y*EffectiveHeight)); LightProjection.SetZero(); LightProjection._11 = scale.X; LightProjection._14 = (shift.X + offsetX) * scale.X; LightProjection._22 = scale.Y; LightProjection._24 = (shift.Y + offsetY) * scale.Y; LightProjection._33 = scale.Z; LightProjection._34 = shift.Z * scale.Z + renderer.m_ShadowZBias; LightProjection._44 = 1.0; // Calculate texture matrix by creating the clip space to texture coordinate matrix // and then concatenating all matrices that have been calculated so far CMatrix3D lightToTex; float texscalex = scale.X * 0.5f * (float)EffectiveWidth / (float)Width; float texscaley = scale.Y * 0.5f * (float)EffectiveHeight / (float)Height; float texscalez = scale.Z * 0.5f; lightToTex.SetZero(); lightToTex._11 = texscalex; lightToTex._14 = (offsetX - ShadowBound[0].X) * texscalex; lightToTex._22 = texscaley; lightToTex._24 = (offsetY - ShadowBound[0].Y) * texscaley; lightToTex._33 = texscalez; lightToTex._34 = -ShadowBound[0].Z * texscalez; lightToTex._44 = 1.0; TextureMatrix = lightToTex * LightTransform; }