diff --git a/binaries/data/mods/public/shaders/water_high.fs b/binaries/data/mods/public/shaders/water_high.fs
index 404b9a9cf5..865ff685cf 100644
--- a/binaries/data/mods/public/shaders/water_high.fs
+++ b/binaries/data/mods/public/shaders/water_high.fs
@@ -5,6 +5,7 @@ uniform vec3 cameraPos;
uniform sampler2D normalMap;
uniform sampler2D reflectionMap;
uniform sampler2D refractionMap;
+uniform sampler2D losMap;
uniform float shininess; // Blinn-Phong specular strength
uniform float specularStrength; // Scaling for specular reflection (specular color is (this,this,this))
uniform float waviness; // "Wildness" of the reflections and refractions; choose based on texture
@@ -17,7 +18,6 @@ uniform float reflectionTintStrength; // Strength of reflection tint (how much o
varying vec3 worldPos;
varying float w;
varying float waterDepth;
-varying float losMod;
void main()
{
@@ -28,7 +28,8 @@ void main()
float t; // Temporary variable
vec2 reflCoords, refrCoords;
vec3 reflColor, refrColor, specular;
-
+ float losMod;
+
n = normalize(texture2D(normalMap, gl_TexCoord[0].st).xzy - vec3(0.5, 0.5, 0.5));
l = -sunDir;
v = normalize(cameraPos - worldPos);
@@ -55,7 +56,9 @@ void main()
myMurkiness);
specular = pow(max(0.0, ndoth), shininess) * sunColor * specularStrength;
-
+
+ losMod = texture2D(losMap, gl_TexCoord[3].st).a;
+
gl_FragColor.rgb = mix(refrColor + 0.3*specular, reflColor + specular, fresnel) * losMod;
// Make alpha vary based on both depth (so it blends with the shore) and view angle (make it
diff --git a/binaries/data/mods/public/shaders/water_high.vs b/binaries/data/mods/public/shaders/water_high.vs
index 8894abf39d..ec972f21c5 100644
--- a/binaries/data/mods/public/shaders/water_high.vs
+++ b/binaries/data/mods/public/shaders/water_high.vs
@@ -1,23 +1,22 @@
uniform mat4 reflectionMatrix;
uniform mat4 refractionMatrix;
+uniform mat4 losMatrix;
uniform vec4 translation;
attribute float vertexDepth;
-attribute float losMultiplier;
varying vec3 worldPos;
varying float w;
varying float waterDepth;
-varying float losMod;
void main()
{
worldPos = gl_Vertex.xyz;
waterDepth = vertexDepth;
- losMod = losMultiplier;
gl_TexCoord[0] = gl_MultiTexCoord0 + translation;
gl_TexCoord[1] = reflectionMatrix * gl_Vertex; // projective texturing
gl_TexCoord[2] = reflectionMatrix * gl_Vertex;
+ gl_TexCoord[3] = losMatrix * gl_Vertex;
w = gl_TexCoord[1].w;
gl_Position = ftransform();
}
diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp
index b59bc485fa..2ea0897fe5 100644
--- a/source/graphics/GameView.cpp
+++ b/source/graphics/GameView.cpp
@@ -24,6 +24,7 @@
#include "graphics/ColladaManager.h"
#include "graphics/HFTracer.h"
#include "graphics/LightEnv.h"
+#include "graphics/LOSTexture.h"
#include "graphics/Model.h"
#include "graphics/ObjectManager.h"
#include "graphics/Patch.h"
@@ -198,6 +199,7 @@ public:
CMeshManager MeshManager;
CSkeletonAnimManager SkeletonAnimManager;
CObjectManager ObjectManager;
+ CLOSTexture LOSTexture;
/**
* this camera controls the eye position when rendering
@@ -354,12 +356,10 @@ CCinemaManager* CGameView::GetCinema()
return &m->TrackManager;
};
-/*
-void CGameView::AttachToUnit(CEntity* target)
+CLOSTexture& CGameView::GetLOSTexture()
{
- m->UnitAttach = target;
+ return m->LOSTexture;
}
-*/
void CGameViewImpl::ScriptingInit()
diff --git a/source/graphics/GameView.h b/source/graphics/GameView.h
index 201b2cd6a3..a85a97b324 100644
--- a/source/graphics/GameView.h
+++ b/source/graphics/GameView.h
@@ -31,6 +31,7 @@ class CGame;
class CObjectManager;
class CCamera;
class CCinemaManager;
+class CLOSTexture;
class CVector3D;
struct SViewPort;
@@ -90,6 +91,7 @@ public:
CCamera *GetCamera();
CCinemaManager* GetCinema();
+ CLOSTexture& GetLOSTexture();
JSObject* GetScript();
static void ScriptingInit();
diff --git a/source/graphics/LOSTexture.cpp b/source/graphics/LOSTexture.cpp
new file mode 100644
index 0000000000..a6726ba652
--- /dev/null
+++ b/source/graphics/LOSTexture.cpp
@@ -0,0 +1,244 @@
+/* Copyright (C) 2011 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "LOSTexture.h"
+
+#include "graphics/Terrain.h"
+#include "lib/bits.h"
+#include "ps/Game.h"
+#include "ps/Profile.h"
+#include "ps/World.h"
+#include "renderer/Renderer.h"
+#include "simulation2/Simulation2.h"
+#include "simulation2/components/ICmpRangeManager.h"
+
+/*
+
+The LOS bitmap is computed with one value per map vertex, based on
+CCmpRangeManager's visibility information.
+
+The bitmap is then blurred using an NxN box filter (i.e. convolution
+with (1 1 1; 1 1 1; 1 1 1) etc). To implement the blur efficiently without
+using extra memory for a second copy of the bitmap, we generate the bitmap
+with (N-1)/2 pixels of padding on each side, then the blur shifts the
+image back into the corner.
+
+The blurred bitmap is then uploaded into a GL texture for use by the renderer.
+
+*/
+
+
+// Blur with a NxN box filter, where N = g_BlurSize must be an odd number.
+static const size_t g_BlurSize = 5;
+
+CLOSTexture::CLOSTexture() :
+ m_Dirty(true), m_Texture(0), m_MapSize(0), m_TextureSize(0)
+{
+}
+
+CLOSTexture::~CLOSTexture()
+{
+ if (m_Texture)
+ {
+ glDeleteTextures(1, &m_Texture);
+ m_Texture = 0;
+ }
+}
+
+void CLOSTexture::MakeDirty()
+{
+ m_Dirty = true;
+}
+
+void CLOSTexture::BindTexture(int unit)
+{
+ if (m_Dirty)
+ {
+ RecomputeTexture(unit);
+ m_Dirty = false;
+ }
+
+ g_Renderer.BindTexture(unit, m_Texture);
+}
+
+CMatrix3D CLOSTexture::GetTextureMatrix()
+{
+ debug_assert(m_MapSize);
+
+ // We want to map
+ // world pos (0, y, 0) (i.e. first vertex)
+ // onto texcoord (0.5/texsize, 0.5/texsize) (i.e. middle of first texel);
+ // world pos ((mapsize-1)*cellsize, y, (mapsize-1)*cellsize) (i.e. last vertex)
+ // onto texcoord ((mapsize-0.5) / texsize, (mapsize-0.5) / texsize) (i.e. middle of last texel)
+ // so construct an appropriate matrix:
+
+ float s = (m_MapSize-1) / (float)(m_TextureSize * (m_MapSize-1) * CELL_SIZE);
+ float t = 0.5f / m_TextureSize;
+ CMatrix3D m;
+ m.SetZero();
+ m._11 = s;
+ m._23 = s;
+ m._14 = t;
+ m._24 = t;
+ m._44 = 1;
+ return m;
+}
+
+CMatrix3D CLOSTexture::GetMinimapTextureMatrix()
+{
+ debug_assert(m_MapSize);
+
+ // We want to map UV (0,0)-(1,1) onto (0,0)-(mapsize/texsize, mapsize/texsize)
+
+ float s = m_MapSize / (float)m_TextureSize;
+ CMatrix3D m;
+ m.SetZero();
+ m._11 = s;
+ m._22 = s;
+ m._44 = 1;
+ return m;
+}
+
+void CLOSTexture::ConstructTexture(int unit)
+{
+ CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
+ m_MapSize = terrain->GetVerticesPerSide();
+ m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize + g_BlurSize - 1);
+
+ glGenTextures(1, &m_Texture);
+ g_Renderer.BindTexture(unit, m_Texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+ 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);
+}
+
+void CLOSTexture::RecomputeTexture(int unit)
+{
+ if (!m_Texture)
+ ConstructTexture(unit);
+
+ PROFILE("recompute LOS texture");
+
+ std::vector losData;
+ losData.resize(GetBitmapSize(m_MapSize, m_MapSize));
+
+ CmpPtr cmpRangeManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
+ if (cmpRangeManager.null())
+ return;
+
+ ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID()));
+
+ GenerateBitmap(los, &losData[0], m_MapSize, m_MapSize);
+
+ g_Renderer.BindTexture(unit, m_Texture);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize + g_BlurSize - 1, m_MapSize + g_BlurSize - 1, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]);
+}
+
+size_t CLOSTexture::GetBitmapSize(size_t w, size_t h)
+{
+ return (w + g_BlurSize - 1) * (h + g_BlurSize - 1);
+}
+
+void CLOSTexture::GenerateBitmap(ICmpRangeManager::CLosQuerier los, u8* losData, size_t w, size_t h)
+{
+ const size_t rowSize = w + g_BlurSize-1; // size of losData rows
+
+ u8 *dataPtr = losData;
+
+ // Initialise the top padding
+ for (size_t j = 0; j < g_BlurSize/2; ++j)
+ for (size_t i = 0; i < rowSize; ++i)
+ *dataPtr++ = 0;
+
+ for (size_t j = 0; j < h; ++j)
+ {
+ // Initialise the left padding
+ for (size_t i = 0; i < g_BlurSize/2; ++i)
+ *dataPtr++ = 0;
+
+ // Fill in the visibility data
+ for (size_t i = 0; i < w; ++i)
+ {
+ if (los.IsVisible(i, j))
+ *dataPtr++ = 255;
+ else if (los.IsExplored(i, j))
+ *dataPtr++ = 127;
+ else
+ *dataPtr++ = 0;
+ }
+
+ // Initialise the right padding
+ for (size_t i = 0; i < g_BlurSize/2; ++i)
+ *dataPtr++ = 0;
+ }
+
+ // Initialise the bottom padding
+ for (size_t j = 0; j < g_BlurSize/2; ++j)
+ for (size_t i = 0; i < rowSize; ++i)
+ *dataPtr++ = 0;
+
+ // Horizontal blur:
+
+ for (size_t j = g_BlurSize/2; j < h + g_BlurSize/2; ++j)
+ {
+ u32 accum = 0; // sum of values in the sliding Nx1 window
+
+ // Initialise the filter window for the first output pixel
+ // (Start i at the first of the non-padding pixels, since the
+ // padding was set to 0)
+ for (size_t i = g_BlurSize/2; i < g_BlurSize-1; ++i)
+ accum += losData[i+j*rowSize];
+
+ // For each pixel, update the sliding window and store the average
+ // of the window's sum
+ for (size_t i = 0; i < w; ++i)
+ {
+ accum += losData[i+g_BlurSize-1+j*rowSize];
+
+ u8 old = losData[i+j*rowSize];
+
+ losData[i+j*rowSize] = accum / g_BlurSize;
+
+ accum -= old;
+ }
+ }
+
+ // Vertical blur:
+
+ for (size_t i = 0; i < w; ++i)
+ {
+ u32 accum = 0;
+
+ for (size_t j = g_BlurSize/2; j < g_BlurSize-1; ++j)
+ accum += losData[i+j*rowSize];
+
+ for (size_t j = 0; j < h; ++j)
+ {
+ accum += losData[i+(j+g_BlurSize-1)*rowSize];
+
+ u8 old = losData[i+j*rowSize];
+
+ losData[i+j*rowSize] = accum / g_BlurSize;
+
+ accum -= old;
+ }
+ }
+}
diff --git a/source/graphics/LOSTexture.h b/source/graphics/LOSTexture.h
new file mode 100644
index 0000000000..43ef3cc1f4
--- /dev/null
+++ b/source/graphics/LOSTexture.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2011 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "lib/ogl.h"
+
+#include "simulation2/components/ICmpRangeManager.h"
+
+class CMatrix3D;
+
+/**
+ * Maintains the LOS (fog-of-war / shroud-of-darkness) texture, used for
+ * rendering and for the minimap.
+ */
+class CLOSTexture
+{
+ NONCOPYABLE(CLOSTexture);
+ friend class TestLOSTexture;
+
+public:
+ CLOSTexture();
+ ~CLOSTexture();
+
+ /**
+ * Marks the LOS texture as needing recomputation. Call this after each
+ * simulation update, to ensure responsive updates.
+ */
+ void MakeDirty();
+
+ /**
+ * Recomputes the LOS texture if necessary, and binds it to the requested
+ * texture unit.
+ * Also switches the current active texture unit, and enables texturing on it.
+ * The texture is in 8-bit ALPHA format.
+ */
+ void BindTexture(int unit);
+
+ /**
+ * Returns a matrix to map (x,y,z) world coordinates onto (u,v) LOS texture
+ * coordinates.
+ * This must only be called after BindTexture.
+ */
+ CMatrix3D GetTextureMatrix();
+
+ /**
+ * Returns a matrix to map (0,0)-(1,1) texture coordinates onto LOS texture
+ * coordinates.
+ * This must only be called after BindTexture.
+ */
+ CMatrix3D GetMinimapTextureMatrix();
+
+private:
+ void ConstructTexture(int unit);
+ void RecomputeTexture(int unit);
+
+ size_t GetBitmapSize(size_t w, size_t h);
+ void GenerateBitmap(ICmpRangeManager::CLosQuerier los, u8* losData, size_t w, size_t h);
+
+ bool m_Dirty;
+
+ GLuint m_Texture;
+
+ ssize_t m_MapSize; // vertexes per side
+ GLsizei m_TextureSize; // texels per side
+};
diff --git a/source/graphics/tests/test_LOSTexture.h b/source/graphics/tests/test_LOSTexture.h
new file mode 100644
index 0000000000..b2f2f245d0
--- /dev/null
+++ b/source/graphics/tests/test_LOSTexture.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2011 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "lib/self_test.h"
+
+#include "graphics/LOSTexture.h"
+#include "lib/timer.h"
+
+class TestLOSTexture : public CxxTest::TestSuite
+{
+public:
+ void test_basic()
+ {
+ CLOSTexture tex;
+
+ const ssize_t size = 8;
+ u32 inputData[size*size] = {
+ 2, 2, 2, 0, 0, 0, 0, 0,
+ 2, 2, 2, 0, 0, 0, 0, 0,
+ 2, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2
+ };
+ std::vector inputDataVec(inputData, inputData+size*size);
+
+ ICmpRangeManager::CLosQuerier los(1, inputDataVec, size);
+
+ std::vector losData;
+ losData.resize(tex.GetBitmapSize(size, size));
+
+ tex.GenerateBitmap(los, &losData[0], size, size);
+
+// for (size_t i = 0; i < losData.size(); ++i)
+// printf("%s %3d", i % (size_t)sqrt(losData.size()) ? "" : "\n", losData[i]);
+
+ TS_ASSERT_EQUALS(losData[0], 91);
+ }
+
+ void test_perf_DISABLED()
+ {
+ CLOSTexture tex;
+
+ const ssize_t size = 257;
+ std::vector inputDataVec;
+ inputDataVec.resize(size*size);
+
+ ICmpRangeManager::CLosQuerier los(1, inputDataVec, size);
+
+ size_t reps = 128;
+ double t = timer_Time();
+ for (size_t i = 0; i < reps; ++i)
+ {
+ std::vector losData;
+ losData.resize(tex.GetBitmapSize(size, size));
+
+ tex.GenerateBitmap(los, &losData[0], size, size);
+ }
+ double dt = timer_Time() - t;
+ printf("\n# %f secs\n", dt/reps);
+ }
+};
diff --git a/source/gui/MiniMap.cpp b/source/gui/MiniMap.cpp
index 03bcd9b1c6..1984198b94 100644
--- a/source/gui/MiniMap.cpp
+++ b/source/gui/MiniMap.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include "MiniMap.h"
#include "graphics/GameView.h"
+#include "graphics/LOSTexture.h"
#include "graphics/MiniPatch.h"
#include "graphics/Terrain.h"
#include "graphics/TerrainTextureEntry.h"
@@ -39,7 +40,6 @@
#include "scriptinterface/ScriptInterface.h"
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpMinimap.h"
-#include "simulation2/components/ICmpRangeManager.h"
bool g_GameRestarted = false;
@@ -51,9 +51,8 @@ static unsigned int ScaleColor(unsigned int color, float x)
return (0xff000000 | r | g<<8 | b<<16);
}
-CMiniMap::CMiniMap()
- : m_TerrainTexture(0), m_TerrainData(0), m_MapSize(0), m_Terrain(0),
- m_LOSTexture(0), m_TerrainDirty(true)
+CMiniMap::CMiniMap() :
+ m_TerrainTexture(0), m_TerrainData(0), m_MapSize(0), m_Terrain(0), m_TerrainDirty(true)
{
AddSetting(GUIST_CColor, "fov_wedge_color");
AddSetting(GUIST_bool, "circular");
@@ -61,8 +60,6 @@ CMiniMap::CMiniMap()
AddSetting(GUIST_CStr, "tooltip_style");
m_Clicking = false;
m_Hovering = false;
-
- m_LOSScale = 2;
}
CMiniMap::~CMiniMap()
@@ -279,9 +276,7 @@ void CMiniMap::Draw()
m_Width = (u32)(m_CachedActualSize.right - m_CachedActualSize.left);
m_Height = (u32)(m_CachedActualSize.bottom - m_CachedActualSize.top);
m_MapSize = m_Terrain->GetVerticesPerSide();
- m_LOSMapSize = (m_MapSize + m_LOSScale - 1) / m_LOSScale; // divide and round upwards
m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize);
- m_LOSTextureSize = (GLsizei)round_up_to_pow2((size_t)m_LOSMapSize);
if(!m_TerrainTexture || g_GameRestarted)
CreateTextures();
@@ -298,16 +293,12 @@ void CMiniMap::Draw()
if(m_TerrainDirty)
RebuildTerrainTexture();
-
- RebuildLOSTexture();
}
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 losTexCoordMax = (float)(m_LOSMapSize - 1) / (float)m_LOSTextureSize;
-
const float angle = GetAngle();
// Draw the main textured quad
@@ -371,20 +362,29 @@ void CMiniMap::Draw()
*/
// Draw the LOS quad in black, using alpha values from the LOS texture
- g_Renderer.BindTexture(0, m_LOSTexture);
+ CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
+ 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_SRC_ALPHA);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ 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);
- DrawTexture(losTexCoordMax, angle, x, y, x2, y2, z);
+
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf(&losTexture.GetMinimapTextureMatrix()._11);
+ glMatrixMode(GL_MODELVIEW);
+
+ DrawTexture(1.0f, angle, x, y, x2, y2, z);
+
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
glDisable(GL_BLEND);
// Set up the matrix for drawing points and lines
@@ -463,22 +463,11 @@ void CMiniMap::CreateTextures()
m_TerrainData = new u32[(m_MapSize - 1) * (m_MapSize - 1)];
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);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
-
- // Create LOS texture
- glGenTextures(1, &m_LOSTexture);
- g_Renderer.BindTexture(0, m_LOSTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, m_LOSTextureSize, m_LOSTextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
- m_LOSData.resize(m_LOSMapSize * m_LOSMapSize);
- 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);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_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);
// Rebuild and upload both of them
RebuildTerrainTexture();
- RebuildLOSTexture();
}
@@ -539,44 +528,6 @@ void CMiniMap::RebuildTerrainTexture()
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize - 1, m_MapSize - 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_TerrainData);
}
-
-void CMiniMap::RebuildLOSTexture()
-{
- PROFILE("rebuild minimap: los");
-
- ssize_t w = m_MapSize;
- ssize_t h = m_MapSize;
-
- CmpPtr cmpRangeManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
- if (cmpRangeManager.null() || cmpRangeManager->GetLosRevealAll(g_Game->GetPlayerID()))
- {
- memset(&m_LOSData[0], 0, m_LOSData.size());
- }
- else
- {
- ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID()));
-
- u8 *dataPtr = &m_LOSData[0];
-
- for (ssize_t j = 0; j < h; j += m_LOSScale)
- {
- for (ssize_t i = 0; i < w; i += m_LOSScale)
- {
- if (los.IsVisible(i, j))
- *dataPtr++ = 0;
- else if (los.IsExplored(i, j))
- *dataPtr++ = 76;
- else
- *dataPtr++ = 255;
- }
- }
- }
-
- // Upload the texture
- g_Renderer.BindTexture(0, m_LOSTexture);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_LOSMapSize, m_LOSMapSize, GL_ALPHA, GL_UNSIGNED_BYTE, &m_LOSData[0]);
-}
-
void CMiniMap::Destroy()
{
if(m_TerrainTexture)
@@ -585,11 +536,6 @@ void CMiniMap::Destroy()
m_TerrainTexture = 0;
}
- if(m_LOSTexture)
- {
- glDeleteTextures(1, &m_LOSTexture);
- m_LOSTexture = 0;
- }
-
- delete[] m_TerrainData; m_TerrainData = 0;
+ delete[] m_TerrainData;
+ m_TerrainData = 0;
}
diff --git a/source/gui/MiniMap.h b/source/gui/MiniMap.h
index 7683d3e68a..a915011ba6 100644
--- a/source/gui/MiniMap.h
+++ b/source/gui/MiniMap.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -40,9 +40,6 @@ protected:
// rebuild the terrain texture map
void RebuildTerrainTexture();
- // rebuild the LOS map
- void RebuildLOSTexture();
-
// destroy and free any memory and textures
void Destroy();
@@ -61,15 +58,9 @@ protected:
// minimap texture handles
GLuint m_TerrainTexture;
- GLuint m_LOSTexture;
-
- // number of vertexes per LOS-texture texel
- u8 m_LOSScale;
- ssize_t m_LOSMapSize;
// texture data
u32* m_TerrainData;
- std::vector m_LOSData;
// whether we need to regenerate the terrain texture
bool m_TerrainDirty;
@@ -81,7 +72,6 @@ protected:
// texture size
GLsizei m_TextureSize;
- GLsizei m_LOSTextureSize;
void DrawTexture(float coordMax, float angle, float x, float y, float x2, float y2, float z);
diff --git a/source/lib/glext_funcs.h b/source/lib/glext_funcs.h
index 57999af058..a37b723cc1 100644
--- a/source/lib/glext_funcs.h
+++ b/source/lib/glext_funcs.h
@@ -65,6 +65,7 @@ FUNC2(void, glDrawRangeElementsEXT, glDrawRangeElements, "1.2", (GLenum, GLuint,
// GL_ARB_multitexture / GL1.3:
FUNC2(void, glMultiTexCoord2fARB, glMultiTexCoord2f, "1.3", (int, float, float))
+FUNC2(void, glMultiTexCoord3fARB, glMultiTexCoord3f, "1.3", (int, float, float, float))
FUNC2(void, glActiveTextureARB, glActiveTexture, "1.3", (int))
FUNC2(void, glClientActiveTextureARB, glClientActiveTexture, "1.3", (int))
diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp
index 86e9255300..6c0fe974b3 100644
--- a/source/ps/Game.cpp
+++ b/source/ps/Game.cpp
@@ -20,6 +20,7 @@
#include "Game.h"
#include "graphics/GameView.h"
+#include "graphics/LOSTexture.h"
#include "graphics/UnitManager.h"
#include "lib/timer.h"
#include "network/NetClient.h"
@@ -234,7 +235,10 @@ bool CGame::Update(double deltaTime, bool doInterpolate)
PROFILE("update");
if (m_TurnManager->Update(deltaTime, maxTurns))
+ {
g_GUI->SendEventToAll("SimulationUpdate");
+ GetView()->GetLOSTexture().MakeDirty();
+ }
}
if (doInterpolate)
diff --git a/source/renderer/PatchRData.cpp b/source/renderer/PatchRData.cpp
index a75714e32f..e01cd36242 100644
--- a/source/renderer/PatchRData.cpp
+++ b/source/renderer/PatchRData.cpp
@@ -137,7 +137,6 @@ void CPatchRData::BuildBlends()
{
m_BlendSplats.clear();
m_BlendVertices.clear();
- m_BlendVertexIndices.clear();
CTerrain* terrain = m_Patch->m_Parent;
@@ -348,37 +347,29 @@ void CPatchRData::AddBlend(u16 i, u16 j, u8 shape)
CalculateUV(dst.m_UVs, gx, gz);
dst.m_AlphaUVs[0] = vtx[0].m_AlphaUVs[0];
dst.m_AlphaUVs[1] = vtx[0].m_AlphaUVs[1];
- dst.m_LOSColor = vtx0.m_LOSColor;
dst.m_Position = vtx0.m_Position;
m_BlendVertices.push_back(dst);
- m_BlendVertexIndices.push_back((j * vsize) + i);
const SBaseVertex& vtx1 = m_Vertices[(j * vsize) + i + 1];
CalculateUV(dst.m_UVs, gx + 1, gz);
dst.m_AlphaUVs[0] = vtx[1].m_AlphaUVs[0];
dst.m_AlphaUVs[1] = vtx[1].m_AlphaUVs[1];
- dst.m_LOSColor = vtx1.m_LOSColor;
dst.m_Position = vtx1.m_Position;
m_BlendVertices.push_back(dst);
- m_BlendVertexIndices.push_back((j * vsize) + i + 1);
const SBaseVertex& vtx2 = m_Vertices[((j + 1) * vsize) + i + 1];
CalculateUV(dst.m_UVs, gx + 1, gz + 1);
dst.m_AlphaUVs[0] = vtx[2].m_AlphaUVs[0];
dst.m_AlphaUVs[1] = vtx[2].m_AlphaUVs[1];
- dst.m_LOSColor = vtx2.m_LOSColor;
dst.m_Position = vtx2.m_Position;
m_BlendVertices.push_back(dst);
- m_BlendVertexIndices.push_back(((j + 1) * vsize) + i + 1);
const SBaseVertex& vtx3 = m_Vertices[((j + 1) * vsize) + i];
CalculateUV(dst.m_UVs, gx, gz + 1);
dst.m_AlphaUVs[0] = vtx[3].m_AlphaUVs[0];
dst.m_AlphaUVs[1] = vtx[3].m_AlphaUVs[1];
- dst.m_LOSColor = vtx3.m_LOSColor;
dst.m_Position = vtx3.m_Position;
m_BlendVertices.push_back(dst);
- m_BlendVertexIndices.push_back(((j + 1) * vsize) + i);
}
void CPatchRData::BuildIndices()
@@ -391,7 +382,6 @@ void CPatchRData::BuildIndices()
// release existing indices and bins
m_Indices.clear();
- m_ShadowMapIndices.clear();
m_Splats.clear();
// build grid of textures on this patch and boundaries of adjacent patches
@@ -430,16 +420,6 @@ void CPatchRData::BuildIndices()
}
splat.m_IndexCount=m_Indices.size()-splat.m_IndexStart;
}
-
- // build indices for the shadow map pass
- for (ssize_t j=0;jCalcPosition(ix,iz,vertices[v].m_Position);
- vertices[v].m_LOSColor = SColor4ub(0, 0, 0, 0); // will be set to the proper value in Update()
CalculateUV(vertices[v].m_UVs, ix, iz);
// Calculate diffuse lighting for this vertex
@@ -514,81 +493,19 @@ void CPatchRData::Update()
m_UpdateFlags=0;
}
-
- // Update vertex colors, which are affected by LOS
-
- ssize_t px=m_Patch->m_X;
- ssize_t pz=m_Patch->m_Z;
-
- CTerrain* terrain=m_Patch->m_Parent;
- ssize_t vsize=PATCH_SIZE+1;
- SColor4ub baseColour = terrain->GetBaseColour();
-
- CmpPtr cmpRangeManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
- if (cmpRangeManager.null())
- {
- for (ssize_t j = 0; j < vsize; ++j)
- {
- for (ssize_t i = 0; i < vsize; ++i)
- {
- ssize_t v = (j*vsize)+i;
- m_Vertices[v].m_LOSColor = baseColour;
- }
- }
- }
- else
- {
- ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID()));
-
- // this is very similar to BuildVertices(), but just for color
- for (ssize_t j = 0; j < vsize; j++)
- {
- for (ssize_t i = 0; i < vsize; i++)
- {
- ssize_t ix = px * PATCH_SIZE + i;
- ssize_t iz = pz * PATCH_SIZE + j;
- ssize_t v = (j * vsize) + i;
-
- SColor4ub losMod;
- if (los.IsVisible(ix, iz))
- losMod = baseColour;
- else if (los.IsExplored(ix, iz))
- losMod = SColor4ub(178, 178, 178, 255);
- else
- losMod = SColor4ub(0, 0, 0, 255);
-
- m_Vertices[v].m_LOSColor = losMod;
- }
- }
- }
-
- // upload base vertices into their vertex buffer
- m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);
-
- // update blend colors by copying them from vertex colors
- for(size_t i=0; im_Owner->UpdateChunkVertices(m_VBBlends,&m_BlendVertices[0]);
- }
}
-void CPatchRData::RenderBase(bool losColor)
+void CPatchRData::RenderBase()
{
debug_assert(m_UpdateFlags==0);
SBaseVertex *base=(SBaseVertex *)m_VBBase->m_Owner->Bind();
// setup data pointers
- GLsizei stride=sizeof(SBaseVertex);
- glVertexPointer(3,GL_FLOAT,stride,&base->m_Position[0]);
- glColorPointer(4,GL_UNSIGNED_BYTE,stride,losColor ? &base->m_LOSColor : &base->m_DiffuseColor);
- glTexCoordPointer(2,GL_FLOAT,stride,&base->m_UVs[0]);
+ GLsizei stride = sizeof(SBaseVertex);
+ glVertexPointer(3, GL_FLOAT, stride, &base->m_Position[0]);
+ glColorPointer(4, GL_UNSIGNED_BYTE, stride, &base->m_DiffuseColor);
+ glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs[0]);
// render each splat
for (size_t i=0;im_Owner->Bind();
// setup data pointers
- GLsizei stride=sizeof(SBaseVertex);
+ GLsizei stride = sizeof(SBaseVertex);
glVertexPointer(3, GL_FLOAT, stride, &base->m_Position);
- if (streamflags & STREAM_UV0) {
+ if (streamflags & STREAM_UV0)
+ {
glTexCoordPointer(2, GL_FLOAT, stride, &base->m_UVs);
- } else if (streamflags & STREAM_POSTOUV0) {
+ }
+ else if (streamflags & STREAM_POSTOUV0)
+ {
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
}
+ if (streamflags & STREAM_POSTOUV1)
+ {
+ pglClientActiveTextureARB(GL_TEXTURE1);
+ glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
+ pglClientActiveTextureARB(GL_TEXTURE0);
+ }
+ if (streamflags & STREAM_POSTOUV2)
+ {
+ pglClientActiveTextureARB(GL_TEXTURE2);
+ glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
+ pglClientActiveTextureARB(GL_TEXTURE0);
+ }
+ if (streamflags & STREAM_POSTOUV3)
+ {
+ pglClientActiveTextureARB(GL_TEXTURE3);
+ glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
+ pglClientActiveTextureARB(GL_TEXTURE0);
+ }
if (streamflags & STREAM_COLOR)
{
- glColorPointer(4,GL_UNSIGNED_BYTE,stride,losColor ? &base->m_LOSColor : &base->m_DiffuseColor);
+ glColorPointer(4, GL_UNSIGNED_BYTE, stride, &base->m_DiffuseColor);
}
// render all base splats at once
@@ -660,7 +598,6 @@ void CPatchRData::RenderBlends()
// invalid - see http://gcc.gnu.org/ml/gcc/2003-11/msg00281.html - but it
// doesn't seem to be worth changing this code since it works anyway.))
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position));
- glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_LOSColor));
pglClientActiveTextureARB(GL_TEXTURE0);
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0]));
diff --git a/source/renderer/PatchRData.h b/source/renderer/PatchRData.h
index 8f1a3ef4af..28cfa2bce5 100644
--- a/source/renderer/PatchRData.h
+++ b/source/renderer/PatchRData.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -37,10 +37,10 @@ public:
~CPatchRData();
void Update();
- void RenderBase(bool losColor);
+ void RenderBase();
void RenderBlends();
void RenderOutline();
- void RenderStreams(int streamflags, bool losColor);
+ void RenderStreams(int streamflags);
void RenderPriorities();
private:
@@ -62,15 +62,11 @@ private:
SColor4ub m_DiffuseColor;
// vertex uvs for base texture
float m_UVs[2];
- // color modulation from LOS
- SColor4ub m_LOSColor;
};
struct SBlendVertex {
// vertex position
CVector3D m_Position;
- // color modulation from LOS
- SColor4ub m_LOSColor;
// vertex uvs for base texture
float m_UVs[2];
// vertex uvs for alpha texture
@@ -108,19 +104,12 @@ private:
// indices into base vertices for the base splats
std::vector m_Indices;
- // indices into base vertices for the shadow map pass
- std::vector m_ShadowMapIndices;
-
// list of base splats to apply to this patch
std::vector m_Splats;
// vertices to use for blending transition texture passes
std::vector m_BlendVertices;
- // remembers the index in the m_Vertices array of each blend vertex, so that we can
- // properly update its color for fog of war and shroud of darkness
- std::vector m_BlendVertexIndices;
-
// splats used in blend pass
std::vector m_BlendSplats;
};
diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp
index e4e9dbefaf..917040338f 100644
--- a/source/renderer/Renderer.cpp
+++ b/source/renderer/Renderer.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -434,11 +434,12 @@ CRenderer::~CRenderer()
void CRenderer::EnumCaps()
{
// assume support for nothing
- m_Caps.m_VBO=false;
- m_Caps.m_TextureBorderClamp=false;
- m_Caps.m_GenerateMipmaps=false;
- m_Caps.m_VertexShader=false;
- m_Caps.m_FragmentShader=false;
+ m_Caps.m_VBO = false;
+ m_Caps.m_TextureBorderClamp = false;
+ m_Caps.m_GenerateMipmaps = false;
+ m_Caps.m_VertexShader = false;
+ m_Caps.m_FragmentShader = false;
+ m_Caps.m_Shadows = false;
m_Caps.m_DepthTextureShadows = false;
m_Caps.m_FramebufferObject = false;
@@ -448,12 +449,15 @@ void CRenderer::EnumCaps()
m_Caps.m_VBO=true;
}
}
+
if (ogl_HaveExtension("GL_ARB_texture_border_clamp")) {
m_Caps.m_TextureBorderClamp=true;
}
+
if (ogl_HaveExtension("GL_SGIS_generate_mipmap")) {
m_Caps.m_GenerateMipmaps=true;
}
+
if (0 == ogl_HaveExtensions(0, "GL_ARB_shader_objects", "GL_ARB_shading_language_100", NULL))
{
if (ogl_HaveExtension("GL_ARB_vertex_shader"))
@@ -462,6 +466,15 @@ void CRenderer::EnumCaps()
m_Caps.m_FragmentShader=true;
}
+ if (ogl_max_tex_units >= 3)
+ {
+ // To render shadows plus fog-of-war in a single lighting pass (see
+ // TerrainRenderer.cpp) we need >= 3 TMUs. Only really ancient hardware
+ // doesn't support that, so instead of implementing a compatible fallback
+ // we'll just disable shadows entirely unless there's enough TMUs.
+ m_Caps.m_Shadows = true;
+ }
+
if (0 == ogl_HaveExtensions(0, "GL_ARB_shadow", "GL_ARB_depth_texture", NULL)) {
// According to Delphi3d.net, all relevant graphics chips that support depth textures
// (i.e. Geforce3+, Radeon9500+, even i915) also have >= 4 TMUs, so this restriction
@@ -470,6 +483,7 @@ void CRenderer::EnumCaps()
if (ogl_max_tex_units >= 4)
m_Caps.m_DepthTextureShadows = true;
}
+
if (!m_Options.m_NoFramebufferObject)
{
if (ogl_HaveExtension("GL_EXT_framebuffer_object"))
@@ -764,7 +778,7 @@ void CRenderer::BeginFrame()
// choose model renderers for this frame
int vertexType;
- if (m_Options.m_Shadows && m->shadow->GetUseDepthTexture())
+ if (m_Caps.m_Shadows && m_Options.m_Shadows && m->shadow->GetUseDepthTexture())
{
vertexType = OnlyDiffuse;
m->Model.ModNormal = m->Model.ModPlainLit;
@@ -884,7 +898,7 @@ void CRenderer::RenderPatches()
}
// render all the patches, including blend pass
- m->terrainRenderer->RenderTerrain(m_Options.m_Shadows ? m->shadow : 0);
+ m->terrainRenderer->RenderTerrain((m_Caps.m_Shadows && m_Options.m_Shadows) ? m->shadow : 0);
if (m_TerrainRenderMode==WIREFRAME) {
// switch wireframe off again
@@ -1224,7 +1238,7 @@ void CRenderer::RenderSubmissions()
m->overlayRenderer.PrepareForRendering();
PROFILE_END("prepare overlays");
- if (m_Options.m_Shadows)
+ if (m_Caps.m_Shadows && m_Options.m_Shadows)
{
RenderShadowMap();
}
diff --git a/source/renderer/Renderer.h b/source/renderer/Renderer.h
index 54f1b78e17..eb18056701 100644
--- a/source/renderer/Renderer.h
+++ b/source/renderer/Renderer.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -47,15 +47,18 @@ class CTextureManager;
enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
// stream flags
-#define STREAM_POS 0x01
-#define STREAM_NORMAL 0x02
-#define STREAM_COLOR 0x04
-#define STREAM_UV0 0x08
-#define STREAM_UV1 0x10
-#define STREAM_UV2 0x20
-#define STREAM_UV3 0x40
-#define STREAM_POSTOUV0 0x80
-#define STREAM_TEXGENTOUV1 0x100
+#define STREAM_POS (1 << 0)
+#define STREAM_NORMAL (1 << 1)
+#define STREAM_COLOR (1 << 2)
+#define STREAM_UV0 (1 << 3)
+#define STREAM_UV1 (1 << 4)
+#define STREAM_UV2 (1 << 5)
+#define STREAM_UV3 (1 << 6)
+#define STREAM_POSTOUV0 (1 << 7)
+#define STREAM_POSTOUV1 (1 << 8)
+#define STREAM_POSTOUV2 (1 << 9)
+#define STREAM_POSTOUV3 (1 << 10)
+#define STREAM_TEXGENTOUV1 (1 << 11)
//////////////////////////////////////////////////////////////////////////////////////////
// SVertex3D: simple 3D vertex declaration
@@ -152,6 +155,7 @@ public:
bool m_GenerateMipmaps;
bool m_VertexShader;
bool m_FragmentShader;
+ bool m_Shadows;
bool m_DepthTextureShadows;
bool m_FramebufferObject;
};
diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp
index 3b18a24130..09cb39d92c 100644
--- a/source/renderer/TerrainRenderer.cpp
+++ b/source/renderer/TerrainRenderer.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010 Wildfire Games.
+/* Copyright (C) 2011 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -24,6 +24,7 @@
#include "graphics/Camera.h"
#include "graphics/LightEnv.h"
+#include "graphics/LOSTexture.h"
#include "graphics/Patch.h"
#include "graphics/Terrain.h"
#include "graphics/GameView.h"
@@ -37,9 +38,6 @@
#include "ps/Profile.h"
#include "ps/World.h"
-#include "simulation2/Simulation2.h"
-#include "simulation2/components/ICmpRangeManager.h"
-
#include "renderer/PatchRData.h"
#include "renderer/Renderer.h"
#include "renderer/ShadowMap.h"
@@ -159,7 +157,6 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
// switch on required client states
glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// render everything fullbright
@@ -167,11 +164,9 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
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_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);
- glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
- glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
// Set alpha to 1.0
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
@@ -183,7 +178,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
for(size_t i = 0; i < m->visiblePatches.size(); ++i)
{
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
- patchdata->RenderBase(true); // with LOS color
+ patchdata->RenderBase();
}
// render blends
@@ -225,6 +220,9 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
// 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
@@ -234,6 +232,10 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
lightEnv.m_TerrainAmbientColor.Z,
1.f
};
+
+ CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
+
+ int streamflags = STREAM_POS|STREAM_COLOR|STREAM_POSTOUV0;
if (!shadow)
{
@@ -244,7 +246,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
// so assume that's still valid to use.
// (TODO: That's a bit of an ugly hack.)
- // Shadow rendering disabled: Ambient + Diffuse
+ // Shadow rendering disabled: (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);
@@ -256,7 +258,25 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
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);
}
else
{
@@ -271,7 +291,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
if (shadow->GetUseDepthTexture())
{
- // Ambient + ShTranslucency * Diffuse * (1 - Shadow) + Diffuse * Shadow
+ // (Ambient + ShTranslucency * Diffuse * (1 - Shadow) + Diffuse * Shadow) * LOS
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_PRIMARY_COLOR);
@@ -313,11 +333,29 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, terrainAmbientColor);
-
+
+ losTexture.BindTexture(3);
+ pglClientActiveTextureARB(GL_TEXTURE3);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ streamflags |= STREAM_POSTOUV3;
+
+ 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);
}
else
{
- // Ambient + Diffuse * Shadow
+ // (Ambient + Diffuse * Shadow) * LOS
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);
@@ -341,6 +379,24 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, terrainAmbientColor);
+ losTexture.BindTexture(2);
+ pglClientActiveTextureARB(GL_TEXTURE2);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ streamflags |= STREAM_POSTOUV2;
+
+ 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);
}
}
@@ -350,25 +406,52 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
for (size_t i = 0; i < m->visiblePatches.size(); ++i)
{
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
- patchdata->RenderStreams(STREAM_POS|STREAM_COLOR|STREAM_POSTOUV0, false);
+ patchdata->RenderStreams(streamflags);
}
-
+
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
// restore OpenGL state
- if (shadow)
+ g_Renderer.BindTexture(1, 0);
+ if (!shadow)
+ {
+ pglClientActiveTextureARB(GL_TEXTURE1);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
+ else
{
if (shadow->GetUseDepthTexture())
- g_Renderer.BindTexture(2,0);
+ {
+ g_Renderer.BindTexture(2, 0);
+ g_Renderer.BindTexture(3, 0);
+
+ pglClientActiveTextureARB(GL_TEXTURE3);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
+ else
+ {
+ g_Renderer.BindTexture(2, 0);
+
+ pglClientActiveTextureARB(GL_TEXTURE2);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
}
- g_Renderer.BindTexture(1,0);
pglClientActiveTextureARB(GL_TEXTURE0);
pglActiveTextureARB(GL_TEXTURE0);
glDepthMask(1);
- glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
@@ -386,7 +469,7 @@ void TerrainRenderer::RenderPatches()
for(size_t i = 0; i < m->visiblePatches.size(); ++i)
{
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
- patchdata->RenderStreams(STREAM_POS, true);
+ patchdata->RenderStreams(STREAM_POS);
}
glDisableClientState(GL_VERTEX_ARRAY);
}
@@ -435,9 +518,7 @@ void TerrainRenderer::RenderWater()
}
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
- CmpPtr cmpRangeManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
- debug_assert(!cmpRangeManager.null());
- ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID()));
+ CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
@@ -479,6 +560,23 @@ void TerrainRenderer::RenderWater()
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);
+ pglClientActiveTextureARB(GL_TEXTURE1);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glLoadMatrixf(&losTexture.GetTextureMatrix()._11);
+
+ 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
@@ -488,7 +586,6 @@ void TerrainRenderer::RenderWater()
CVector3D camPos = camera.m_Orientation.GetTranslation();
GLint vertexDepth = 0; // water depth attribute, if using fancy water
- GLint losMultiplier = 0; // LOS multiplier, if using fancy water
if(fancy)
{
@@ -500,6 +597,8 @@ void TerrainRenderer::RenderWater()
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, WaterMgr->m_RefractionTexture );
+ losTexture.BindTexture(3);
+
// Bind water shader and set arguments
ogl_program_use( m->fancyWaterShader );
@@ -518,9 +617,11 @@ void TerrainRenderer::RenderWater()
GLint translation = ogl_program_get_uniform_location( m->fancyWaterShader, "translation" );
GLint reflectionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMatrix" );
GLint refractionMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMatrix" );
+ GLint losMatrix = ogl_program_get_uniform_location( m->fancyWaterShader, "losMatrix" );
GLint normalMap = ogl_program_get_uniform_location( m->fancyWaterShader, "normalMap" );
GLint reflectionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "reflectionMap" );
GLint refractionMap = ogl_program_get_uniform_location( m->fancyWaterShader, "refractionMap" );
+ GLint losMap = ogl_program_get_uniform_location( m->fancyWaterShader, "losMap" );
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
pglUniform3fvARB( ambient, 1, &lightEnv.m_TerrainAmbientColor.X );
@@ -537,13 +638,14 @@ void TerrainRenderer::RenderWater()
pglUniform4fARB( translation, tx, ty, 0, 0 );
pglUniformMatrix4fvARB( reflectionMatrix, 1, false, &WaterMgr->m_ReflectionMatrix._11 );
pglUniformMatrix4fvARB( refractionMatrix, 1, false, &WaterMgr->m_RefractionMatrix._11 );
+ pglUniformMatrix4fvARB( losMatrix, 1, false, &losTexture.GetTextureMatrix()._11 );
pglUniform1iARB( normalMap, 0 ); // texture unit 0
pglUniform1iARB( reflectionMap, 1 ); // texture unit 1
pglUniform1iARB( refractionMap, 2 ); // texture unit 2
+ pglUniform1iARB( losMap, 3 ); // texture unit 3
pglUniform3fvARB( cameraPos, 1, &camPos.X );
vertexDepth = ogl_program_get_attrib_location( m->fancyWaterShader, "vertexDepth" );
- losMultiplier = ogl_program_get_attrib_location( m->fancyWaterShader, "losMultiplier" );
}
float repeatPeriod = (fancy ? WaterMgr->m_RepeatPeriod : 16.0f);
@@ -589,18 +691,9 @@ void TerrainRenderer::RenderWater()
float terrainHeight = terrain->GetVertexGroundLevel(ix, iz);
- float losMod;
- if (los.IsVisible(ix, iz))
- losMod = 1.0f;
- else if (los.IsExplored(ix, iz))
- losMod = 0.7f;
- else
- losMod = 0.0f;
-
if (fancy)
{
pglVertexAttrib1fARB(vertexDepth, WaterMgr->m_WaterHeight - terrainHeight);
- pglVertexAttrib1fARB(losMultiplier, losMod);
pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
}
@@ -616,11 +709,12 @@ void TerrainRenderer::RenderWater()
// Invert and set boundaries
FresnelScalar = 1.f - (FresnelScalar * 0.6);
- glColor4f(WaterMgr->m_WaterColor.r*losMod,
- WaterMgr->m_WaterColor.g*losMod,
- WaterMgr->m_WaterColor.b*losMod,
+ glColor4f(WaterMgr->m_WaterColor.r,
+ WaterMgr->m_WaterColor.g,
+ WaterMgr->m_WaterColor.b,
alpha * FresnelScalar);
pglMultiTexCoord2fARB(GL_TEXTURE0, vertX/repeatPeriod, vertZ/repeatPeriod);
+ pglMultiTexCoord3fARB(GL_TEXTURE1, vertX, WaterMgr->m_WaterHeight, vertZ);
glVertex3f(vertX, WaterMgr->m_WaterHeight, vertZ);
}
@@ -630,25 +724,30 @@ void TerrainRenderer::RenderWater()
}
glEnd();
- if(fancy)
+ if (fancy)
{
- // Unbind the refraction/reflection textures and the shader
+ // Unbind the LOS/refraction/reflection textures and the shader
- pglActiveTextureARB( GL_TEXTURE1_ARB );
- glBindTexture( GL_TEXTURE_2D, 0 );
- glDisable( GL_TEXTURE_2D );
+ g_Renderer.BindTexture(3, 0);
+ g_Renderer.BindTexture(2, 0);
+ g_Renderer.BindTexture(1, 0);
- pglActiveTextureARB( GL_TEXTURE2_ARB );
- glBindTexture( GL_TEXTURE_2D, 0 );
- glDisable( GL_TEXTURE_2D );
-
- pglActiveTextureARB( GL_TEXTURE0_ARB );
+ pglActiveTextureARB(GL_TEXTURE0_ARB);
- ogl_program_use( 0 );
+ ogl_program_use(0);
}
- if(!fancy)
+ if (!fancy)
{
+ g_Renderer.BindTexture(1, 0);
+ pglClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glLoadIdentity();
+
+ pglActiveTextureARB(GL_TEXTURE0_ARB);
+ pglClientActiveTextureARB(GL_TEXTURE0_ARB);
+
// Clean up the texture matrix and blend mode
glLoadIdentity();
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp
index 55924cd51f..9c0e125795 100644
--- a/source/simulation2/components/CCmpRangeManager.cpp
+++ b/source/simulation2/components/CCmpRangeManager.cpp
@@ -882,6 +882,8 @@ public:
*/
inline bool LosIsOffWorld(ssize_t i, ssize_t j)
{
+ const ssize_t edgeSize = 3; // number of vertexes around the edge that will be off-world
+
if (m_LosCircular)
{
// With a circular map, vertex is off-world if hypot(i - size/2, j - size/2) >= size/2:
@@ -889,13 +891,19 @@ public:
ssize_t dist2 = (i - m_TerrainVerticesPerSide/2)*(i - m_TerrainVerticesPerSide/2)
+ (j - m_TerrainVerticesPerSide/2)*(j - m_TerrainVerticesPerSide/2);
- if (dist2 >= (m_TerrainVerticesPerSide/2)*(m_TerrainVerticesPerSide/2))
- return true;
+ ssize_t r = m_TerrainVerticesPerSide/2 - edgeSize + 1;
+ // subtract a bit from the radius to ensure nice
+ // SoD blurring around the edges of the map
+
+ return (dist2 >= r*r);
}
+ else
+ {
+ // With a square map, the outermost edge of the map should be off-world,
+ // so the SoD texture blends out nicely
- // With a square map, nothing is off-world
-
- return false;
+ return (i < edgeSize || j < edgeSize || i >= m_TerrainVerticesPerSide-edgeSize || j >= m_TerrainVerticesPerSide-edgeSize);
+ }
}
/**
diff --git a/source/simulation2/components/ICmpRangeManager.h b/source/simulation2/components/ICmpRangeManager.h
index dd961b03d6..9dcd569b11 100644
--- a/source/simulation2/components/ICmpRangeManager.h
+++ b/source/simulation2/components/ICmpRangeManager.h
@@ -169,9 +169,10 @@ public:
{
private:
friend class CCmpRangeManager;
+ friend class TestLOSTexture;
CLosQuerier(int player, const std::vector& data, ssize_t verticesPerSide) :
- m_Data(data), m_VerticesPerSide(verticesPerSide)
+ m_Data(&data[0]), m_VerticesPerSide(verticesPerSide)
{
if (player > 0 && player <= 16)
m_PlayerMask = LOS_MASK << (2*(player-1));
@@ -192,7 +193,7 @@ public:
debug_assert(i >= 0 && j >= 0 && i < m_VerticesPerSide && j < m_VerticesPerSide);
#endif
// Check high bit of each bit-pair
- if ((m_Data.at(j*m_VerticesPerSide + i) & m_PlayerMask) & 0xAAAAAAAAu)
+ if ((m_Data[j*m_VerticesPerSide + i] & m_PlayerMask) & 0xAAAAAAAAu)
return true;
else
return false;
@@ -208,7 +209,7 @@ public:
debug_assert(i >= 0 && j >= 0 && i < m_VerticesPerSide && j < m_VerticesPerSide);
#endif
// Check low bit of each bit-pair
- if ((m_Data.at(j*m_VerticesPerSide + i) & m_PlayerMask) & 0x55555555u)
+ if ((m_Data[j*m_VerticesPerSide + i] & m_PlayerMask) & 0x55555555u)
return true;
else
return false;
@@ -216,7 +217,7 @@ public:
private:
u32 m_PlayerMask;
- const std::vector& m_Data;
+ const u32* m_Data;
ssize_t m_VerticesPerSide;
};