forked from 0ad/0ad
Add support for texture-based terrain overlays.
Fix GLES compatibility. This was SVN commit r11663.
This commit is contained in:
parent
e6cb5fade6
commit
0bd649294f
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)));
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user