1
0
forked from 0ad/0ad

Add support for texture-based terrain overlays.

Fix GLES compatibility.

This was SVN commit r11663.
This commit is contained in:
Ykkrosh 2012-04-24 16:46:32 +00:00
parent e6cb5fade6
commit 0bd649294f
12 changed files with 311 additions and 126 deletions

View File

@ -334,7 +334,7 @@ bool CShaderManager::EffectCacheKey::operator==(const EffectCacheKey& b) const
CShaderTechniquePtr CShaderManager::LoadEffect(const char* name)
{
return LoadEffect(CStrIntern(name), CShaderDefines(), CShaderDefines());
return LoadEffect(CStrIntern(name), g_Renderer.GetSystemShaderDefines(), CShaderDefines());
}
CShaderTechniquePtr CShaderManager::LoadEffect(CStrIntern name, const CShaderDefines& defines1, const CShaderDefines& defines2)

View File

@ -35,6 +35,9 @@
/**
* Shader manager: loads and caches shader programs.
*
* For a high-level overview of shaders and materials, see
* http://trac.wildfiregames.com/wiki/MaterialSystem
*/
class CShaderManager
{
@ -60,7 +63,7 @@ public:
CShaderTechniquePtr LoadEffect(CStrIntern name, const CShaderDefines& defines1, const CShaderDefines& defines2);
/**
* Load a shader effect, with no defines.
* Load a shader effect, with default system defines (from CRenderer::GetSystemShaderDefines).
*/
CShaderTechniquePtr LoadEffect(const char* name);

View File

@ -438,7 +438,7 @@ public:
// GLES defines the macro "GL_ES" in its GLSL preprocessor,
// but since we run our own preprocessor first, we need to explicitly
// define it here
preprocessor.Define("GL_ES", "1");
preprocessor.AddDefine("GL_ES", "1");
#endif
CStr vertexCode = preprocessor.Preprocess(vertexFile.GetAsString());
@ -638,7 +638,11 @@ public:
std::map<CStrIntern, int>::iterator it = m_VertexAttribs.find(CStrIntern(id));
if (it != m_VertexAttribs.end())
{
#if CONFIG2_GLES
debug_warn(L"glVertexAttribIPointer not supported on GLES");
#else
pglVertexAttribIPointerEXT(it->second, size, type, stride, pointer);
#endif
}
}
@ -771,9 +775,27 @@ void CShaderProgram::Uniform(uniform_id_t id, size_t count, const CMatrix3D* v)
Uniform(GetUniformBinding(id), count, v);
}
// These should all be overridden by CShaderProgramGLSL, and not used
// if a non-GLSL shader was loaded instead:
void CShaderProgram::VertexAttribPointer(const char* UNUSED(id), GLint UNUSED(size), GLenum UNUSED(type),
GLboolean UNUSED(normalized), GLsizei UNUSED(stride), void* UNUSED(pointer))
{
debug_warn("Shader type doesn't support VertexAttribPointer");
}
void CShaderProgram::VertexAttribIPointer(const char* UNUSED(id), GLint UNUSED(size), GLenum UNUSED(type),
GLsizei UNUSED(stride), void* UNUSED(pointer))
{
debug_warn("Shader type doesn't support VertexAttribIPointer");
}
#if CONFIG2_GLES
// These should all be overridden by CShaderProgramGLSL
// (GLES doesn't support any other types of shader program):
void CShaderProgram::VertexPointer(GLint UNUSED(size), GLenum UNUSED(type), GLsizei UNUSED(stride), void* UNUSED(pointer))
{
debug_warn("CShaderProgram::VertexPointer should be overridden");
@ -794,7 +816,8 @@ void CShaderProgram::TexCoordPointer(GLenum UNUSED(texture), GLint UNUSED(size),
#else
// These are overridden by CShaderProgramGLSL, but fixed-function and ARB shaders
// both use the fixed-function vertex attribute pointers:
// both use the fixed-function vertex attribute pointers so we'll share their
// definitions here:
void CShaderProgram::VertexPointer(GLint size, GLenum type, GLsizei stride, void* pointer)
{
@ -822,18 +845,6 @@ void CShaderProgram::TexCoordPointer(GLenum texture, GLint size, GLenum type, GL
m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0);
}
void CShaderProgram::VertexAttribPointer(const char* UNUSED(id), GLint UNUSED(size), GLenum UNUSED(type),
GLboolean UNUSED(normalized), GLsizei UNUSED(stride), void* UNUSED(pointer))
{
debug_warn("Shader type doesn't support VertexAttribPointer");
}
void CShaderProgram::VertexAttribIPointer(const char* UNUSED(id), GLint UNUSED(size), GLenum UNUSED(type),
GLsizei UNUSED(stride), void* UNUSED(pointer))
{
debug_warn("Shader type doesn't support VertexAttribIPointer");
}
void CShaderProgram::BindClientStates()
{
ENSURE(m_StreamFlags == (m_StreamFlags & (STREAM_POS|STREAM_NORMAL|STREAM_COLOR|STREAM_UV0|STREAM_UV1)));

View File

@ -58,6 +58,9 @@ enum
* the shader .xml file. Alternatively (and more efficiently, if used very frequently),
* call GetTextureBinding/GetUniformBinding and pass its return value as the ID.
* Setting uniforms that the shader .xml doesn't support is harmless.
*
* For a high-level overview of shaders and materials, see
* http://trac.wildfiregames.com/wiki/MaterialSystem
*/
class CShaderProgram
{

View File

@ -409,6 +409,10 @@ void OverlayRenderer::RenderOverlaysBeforeWater()
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];
@ -427,6 +431,7 @@ void OverlayRenderer::RenderOverlaysBeforeWater()
glDisableClientState(GL_VERTEX_ARRAY);
glLineWidth(1.f);
glDepthFunc(GL_LEQUAL);
glDisable(GL_BLEND);
#endif
}

View File

@ -1032,7 +1032,7 @@ void CPatchRData::RenderStreams(const std::vector<CPatchRData*>& patches, const
PROFILE_END("compute batches");
ENSURE(!(streamflags & ~(STREAM_POS|STREAM_COLOR|STREAM_POSTOUV1)));
ENSURE(!(streamflags & ~(STREAM_POS|STREAM_COLOR|STREAM_POSTOUV0|STREAM_POSTOUV1)));
// Render each batch
for (VertexBufferBatches::iterator itv = batches.begin(); itv != batches.end(); ++itv)

View File

@ -521,11 +521,27 @@ void CRenderer::EnumCaps()
#endif
}
CShaderDefines CRenderer::GetSystemShaderDefines()
{
CShaderDefines defines;
if (GetRenderPath() == RP_SHADER && m_Caps.m_ARBProgram)
defines.Add("SYS_HAS_ARB", "1");
if (GetRenderPath() == RP_SHADER && m_Caps.m_VertexShader && m_Caps.m_FragmentShader)
defines.Add("SYS_HAS_GLSL", "1");
if (m_Options.m_PreferGLSL)
defines.Add("SYS_PREFER_GLSL", "1");
return defines;
}
void CRenderer::ReloadShaders()
{
ENSURE(m->IsOpen);
m->globalContext = CShaderDefines();
m->globalContext = GetSystemShaderDefines();
if (m_Caps.m_Shadows && m_Options.m_Shadows)
{
@ -542,15 +558,6 @@ void CRenderer::ReloadShaders()
if (m_LightEnv)
m->globalContext.Add(("LIGHTING_MODEL_" + m_LightEnv->GetLightingModel()).c_str(), "1");
if (GetRenderPath() == RP_SHADER && m_Caps.m_ARBProgram)
m->globalContext.Add("SYS_HAS_ARB", "1");
if (GetRenderPath() == RP_SHADER && m_Caps.m_VertexShader && m_Caps.m_FragmentShader)
m->globalContext.Add("SYS_HAS_GLSL", "1");
if (m_Options.m_PreferGLSL)
m->globalContext.Add("SYS_PREFER_GLSL", "1");
m->Model.ModShader = LitRenderModifierPtr(new ShaderRenderModifier());
bool cpuLighting = (GetRenderPath() == RP_FIXED);
@ -1407,7 +1414,7 @@ void CRenderer::RenderSubmissions()
ogl_WarnIfError();
// render debug-related terrain overlays
TerrainOverlay::RenderOverlays();
ITerrainOverlay::RenderOverlaysBeforeWater();
ogl_WarnIfError();
// render other debug-related overlays before water (so they can be seen when underwater)
@ -1438,6 +1445,10 @@ void CRenderer::RenderSubmissions()
ogl_WarnIfError();
}
// render debug-related terrain overlays
ITerrainOverlay::RenderOverlaysAfterWater();
ogl_WarnIfError();
// render some other overlays after water (so they can be displayed on top of water)
m->overlayRenderer.RenderOverlaysAfterWater();
ogl_WarnIfError();
@ -1949,6 +1960,11 @@ CParticleManager& CRenderer::GetParticleManager()
return m->particleManager;
}
TerrainRenderer& CRenderer::GetTerrainRenderer()
{
return m->terrainRenderer;
}
CMaterialManager& CRenderer::GetMaterialManager()
{
return m->materialManager;

View File

@ -45,6 +45,7 @@ class SkyManager;
class CTextureManager;
class CShaderManager;
class CParticleManager;
class TerrainRenderer;
class CMaterialManager;
// rendering modes
@ -268,8 +269,12 @@ public:
CParticleManager& GetParticleManager();
TerrainRenderer& GetTerrainRenderer();
CMaterialManager& GetMaterialManager();
CShaderDefines GetSystemShaderDefines();
/**
* GetCapabilities: Return which OpenGL capabilities are available and enabled.
*

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -20,13 +20,16 @@
#include "TerrainOverlay.h"
#include "graphics/Terrain.h"
#include "simulation2/system/SimContext.h"
#include "lib/bits.h"
#include "lib/ogl.h"
#include "maths/MathUtil.h"
#include "ps/Game.h"
#include "ps/Overlay.h"
#include "ps/Profile.h"
#include "ps/World.h"
#include "renderer/Renderer.h"
#include "renderer/TerrainRenderer.h"
#include "simulation2/system/SimContext.h"
#include <algorithm>
@ -54,23 +57,13 @@ private:
const equal1st& operator=(const equal1st& rhs);
};
/// Functor for calling ->Render on pairs' firsts.
struct render1st
{
template<typename S, typename T> void operator()(const std::pair<S, T>& a) const
{
a.first->Render();
}
};
//////////////////////////////////////////////////////////////////////////
// Global overlay list management:
static std::vector<std::pair<TerrainOverlay*, int> > g_TerrainOverlayList;
static std::vector<std::pair<ITerrainOverlay*, int> > g_TerrainOverlayList;
TerrainOverlay::TerrainOverlay(const CSimContext& simContext, int priority /* = 100 */)
: m_Terrain(&simContext.GetTerrain())
ITerrainOverlay::ITerrainOverlay(int priority)
{
// Add to global list of overlays
g_TerrainOverlayList.push_back(std::make_pair(this, priority));
@ -81,53 +74,44 @@ TerrainOverlay::TerrainOverlay(const CSimContext& simContext, int priority /* =
compare2nd());
}
TerrainOverlay::~TerrainOverlay()
ITerrainOverlay::~ITerrainOverlay()
{
std::vector<std::pair<TerrainOverlay*, int> >::iterator newEnd =
std::vector<std::pair<ITerrainOverlay*, int> >::iterator newEnd =
std::remove_if(g_TerrainOverlayList.begin(), g_TerrainOverlayList.end(),
equal1st<TerrainOverlay*>(this));
equal1st<ITerrainOverlay*>(this));
g_TerrainOverlayList.erase(newEnd, g_TerrainOverlayList.end());
}
void TerrainOverlay::RenderOverlays()
void ITerrainOverlay::RenderOverlaysBeforeWater()
{
if (g_TerrainOverlayList.size() == 0)
if (g_TerrainOverlayList.empty())
return;
PROFILE3_GPU("terrain overlays");
PROFILE3_GPU("terrain overlays (before)");
#if CONFIG2_GLES
#warning TODO: implement TerrainOverlay::RenderOverlays for GLES
#else
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);
for (size_t i = 0; i < g_TerrainOverlayList.size(); ++i)
g_TerrainOverlayList[i].first->RenderBeforeWater();
}
pglActiveTextureARB(GL_TEXTURE0);
glDisable(GL_TEXTURE_2D);
void ITerrainOverlay::RenderOverlaysAfterWater()
{
if (g_TerrainOverlayList.empty())
return;
std::for_each(g_TerrainOverlayList.begin(), g_TerrainOverlayList.end(),
render1st());
PROFILE3_GPU("terrain overlays (after)");
// 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);
#endif
for (size_t i = 0; i < g_TerrainOverlayList.size(); ++i)
g_TerrainOverlayList[i].first->RenderAfterWater();
}
//////////////////////////////////////////////////////////////////////////
TerrainOverlay::TerrainOverlay(const CSimContext& simContext, int priority /* = 100 */)
: ITerrainOverlay(priority), m_Terrain(&simContext.GetTerrain())
{
}
void TerrainOverlay::StartRender()
{
}
@ -145,11 +129,27 @@ void TerrainOverlay::GetTileExtents(
max_i_inclusive = max_j_inclusive = m_Terrain->GetTilesPerSide()-1;
}
void TerrainOverlay::Render()
void TerrainOverlay::RenderBeforeWater()
{
if (!m_Terrain)
return; // should never happen, but let's play it safe
#if CONFIG2_GLES
#warning TODO: implement TerrainOverlay::RenderOverlays for GLES
#else
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);
pglActiveTextureARB(GL_TEXTURE0);
glDisable(GL_TEXTURE_2D);
StartRender();
ssize_t min_i, min_j, max_i, max_j;
@ -167,6 +167,15 @@ void TerrainOverlay::Render()
ProcessTile(m_i, m_j);
EndRender();
// 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);
#endif
}
void TerrainOverlay::RenderTile(const CColor& colour, bool draw_hidden)
@ -266,3 +275,57 @@ void TerrainOverlay::RenderTileOutline(const CColor& colour, int line_width, boo
#endif
}
//////////////////////////////////////////////////////////////////////////
TerrainTextureOverlay::TerrainTextureOverlay(float texelsPerTile, int priority) :
ITerrainOverlay(priority), m_TexelsPerTile(texelsPerTile), m_Texture(0), m_TextureW(0), m_TextureH(0)
{
glGenTextures(1, &m_Texture);
}
TerrainTextureOverlay::~TerrainTextureOverlay()
{
glDeleteTextures(1, &m_Texture);
}
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);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -23,10 +23,45 @@
#ifndef INCLUDED_TERRAINOVERLAY
#define INCLUDED_TERRAINOVERLAY
#include "lib/ogl.h"
struct CColor;
class CTerrain;
class CSimContext;
/**
* Common interface for terrain-tile-based and texture-based debug overlays.
*
* An overlay object will be rendered for as long as it is allocated
* (it is automatically registered/deregistered by constructor/destructor).
*/
class ITerrainOverlay
{
NONCOPYABLE(ITerrainOverlay);
public:
virtual ~ITerrainOverlay();
virtual void RenderBeforeWater() { }
virtual void RenderAfterWater() { }
/**
* Draw all ITerrainOverlay objects that exist
* and that should be drawn before water.
*/
static void RenderOverlaysBeforeWater();
/**
* Draw all ITerrainOverlay objects that exist
* and that should be drawn after water.
*/
static void RenderOverlaysAfterWater();
protected:
ITerrainOverlay(int priority);
};
/**
* Base class for (relatively) simple drawing of
* data onto terrain tiles, intended for debugging purposes and for the Atlas
@ -37,18 +72,9 @@ class CSimContext;
* it is drawn.
* Override ProcessTile to do your processing for each tile, which should call
* RenderTile and RenderTileOutline as appropriate.
* See the end of TerrainOverlay.h for an example.
*
* A TerrainOverlay object will be rendered for as long as it exists.
*
*/
class TerrainOverlay
class TerrainOverlay : public ITerrainOverlay
{
public:
virtual ~TerrainOverlay();
private:
TerrainOverlay(){} // private default ctor (must be subclassed)
protected:
/**
* Construct the object and register it with the global
@ -128,20 +154,9 @@ protected:
*/
void RenderTileOutline(const CColor& colour, int line_width, bool draw_hidden, ssize_t i, ssize_t j);
public:
/**
* Draw all TerrainOverlay objects that exist.
*/
static void RenderOverlays();
private:
/// Copying not allowed.
TerrainOverlay(const TerrainOverlay&);
friend struct render1st;
// Process all tiles
void Render();
virtual void RenderBeforeWater();
// Temporary storage of tile coordinates, so ProcessTile doesn't need to
// pass it to RenderTile/etc (and doesn't have a chance to get it wrong)
@ -150,40 +165,33 @@ private:
CTerrain* m_Terrain;
};
/* Example usage:
class ExampleTerrainOverlay : public TerrainOverlay
/**
* Base class for texture-based terrain overlays, with an arbitrary number of
* texels per terrain tile, intended for debugging purposes.
* Subclasses must implement BuildTextureRGBA which will be called each frame.
*/
class TerrainTextureOverlay : public ITerrainOverlay
{
public:
char random[1021];
TerrainTextureOverlay(float texelsPerTile, int priority = 100);
ExampleTerrainOverlay()
{
for (size_t i = 0; i < ARRAY_SIZE(random); ++i)
random[i] = rand(0, 5);
}
virtual ~TerrainTextureOverlay();
virtual void GetTileExtents(
ssize_t& min_i_inclusive, ssize_t& min_j_inclusive,
ssize_t& max_i_inclusive, ssize_t& max_j_inclusive)
{
min_i_inclusive = 5;
min_j_inclusive = 10;
max_i_inclusive = 70;
max_j_inclusive = 50;
}
protected:
/**
* Called each frame to generate the texture to render on the terrain.
* @p data is w*h*4 bytes, where w and h are the terrain size multiplied
* by texelsPerTile. @p data defaults to fully transparent, and should
* be filled with data in RGBA order.
*/
virtual void BuildTextureRGBA(u8* data, size_t w, size_t h) = 0;
virtual void ProcessTile(ssize_t i, ssize_t j)
{
if (!random[(i*97+j*101) % ARRAY_SIZE(random)])
return;
RenderTile(CColor(random[(i*79+j*13) % ARRAY_SIZE(random)]/4.f, 1, 0, 0.3f), false);
RenderTileOutline(CColor(1, 1, 1, 1), 1, true);
}
private:
void RenderAfterWater();
float m_TexelsPerTile;
GLuint m_Texture;
GLsizei m_TextureW, m_TextureH;
};
ExampleTerrainOverlay test; // or allocate it dynamically somewhere
*/
#endif // INCLUDED_TERRAINOVERLAY

View File

@ -387,6 +387,70 @@ void TerrainRenderer::RenderTerrain(bool filtered)
#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
}
///////////////////////////////////////////////////////////////////
/**

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2012 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -137,6 +137,13 @@ public:
*/
void RenderPriorities();
/**
* Render texture unit 0 over the terrain mesh, with UV coords calculated
* by the given texture matrix.
* Intended for use by TerrainTextureOverlay.
*/
void RenderTerrainOverlayTexture(CMatrix3D& textureMatrix);
private:
TerrainRendererInternals* m;