1
0
forked from 0ad/0ad

smooth LOS

This was SVN commit r12304.
This commit is contained in:
myconid 2012-08-06 22:38:42 +00:00
parent 4b119b9bd1
commit 648e68e49c
12 changed files with 218 additions and 12 deletions

View File

@ -62,12 +62,15 @@ force_s3tc_enable = true
renderpath = default
;;;;; EXPERIMENTAL ;;;;;
; Prefer GLSL shaders over ARB shaders (not recommended). REQUIRES gentangents=true
; Prefer GLSL shaders over ARB shaders (not recommended). REQUIRES gentangents=true.
preferglsl = false
; Generate tangents for normal and parallax mapping. REQUIRES preferglsl=true. Incompatible with gpuskinning.
gentangents = false
; Use smooth LOS interpolation; REQUIRES preferglsl=true.
smoothlos = false
; Quality level of shader effects (set to 0 for lowest)
materialmgr.quality = 9.0

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<effect>
<technique>
<require shaders="glsl"/>
<pass shader="glsl/los_interp"/>
</technique>
</effect>

View File

@ -0,0 +1,17 @@
#version 110
varying vec2 v_tex;
uniform sampler2D losTex1, losTex2;
uniform vec3 delta;
void main(void)
{
float los2 = texture2D(losTex1, v_tex).a;
float los1 = texture2D(losTex2, v_tex).a;
gl_FragColor.a = mix(los1, los2, clamp(delta.r, 0.0, 1.0));
}

View File

@ -0,0 +1,19 @@
#version 110
uniform mat4 transform;
uniform vec2 losTransform;
varying vec2 v_tex;
attribute vec3 a_vertex;
attribute vec2 a_uv0;
varying vec2 v_los;
void main()
{
gl_Position = gl_Vertex;
v_tex = vec2(gl_MultiTexCoord0);
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<program type="glsl">
<vertex file="glsl/los_interp.vs">
<stream name="pos"/>
<stream name="uv0"/>
<attrib name="a_vertex" semantics="gl_Vertex"/>
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
</vertex>
<fragment file="glsl/los_interp.fs"/>
</program>

View File

@ -19,11 +19,14 @@
#include "LOSTexture.h"
#include "graphics/ShaderManager.h"
#include "graphics/Terrain.h"
#include "lib/bits.h"
#include "ps/CLogger.h"
#include "ps/Game.h"
#include "ps/Profile.h"
#include "renderer/Renderer.h"
#include "renderer/TimeManager.h"
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpRangeManager.h"
#include "simulation2/components/ICmpTerrain.h"
@ -48,8 +51,23 @@ The blurred bitmap is then uploaded into a GL texture for use by the renderer.
static const size_t g_BlurSize = 7;
CLOSTexture::CLOSTexture(CSimulation2& simulation) :
m_Simulation(simulation), m_Dirty(true), m_Texture(0), m_MapSize(0), m_TextureSize(0)
m_Simulation(simulation), m_Dirty(true), m_Texture(0), m_smoothFbo(0), m_MapSize(0), m_TextureSize(0), whichTex(true)
{
if (g_Renderer.m_Options.m_SmoothLOS)
{
m_smoothShader = g_Renderer.GetShaderManager().LoadEffect("los_interp");
CShaderProgramPtr shader = m_smoothShader->GetShader();
if (m_smoothShader && shader)
{
pglGenFramebuffersEXT(1, &m_smoothFbo);
}
else
{
LOGERROR(L"Failed to load SmoothLOS shader, disabling.");
g_Renderer.m_Options.m_SmoothLOS = false;
}
}
}
CLOSTexture::~CLOSTexture()
@ -61,6 +79,11 @@ CLOSTexture::~CLOSTexture()
void CLOSTexture::DeleteTexture()
{
glDeleteTextures(1, &m_Texture);
if (g_Renderer.m_Options.m_SmoothLOS)
{
glDeleteTextures(1, &m_TextureSmooth1);
glDeleteTextures(1, &m_TextureSmooth2);
}
m_Texture = 0;
}
@ -80,6 +103,71 @@ void CLOSTexture::BindTexture(int unit)
g_Renderer.BindTexture(unit, m_Texture);
}
GLuint CLOSTexture::GetTextureSmooth()
{
if (!g_Renderer.m_Options.m_SmoothLOS)
return GetTexture();
else
return whichTex ? m_TextureSmooth1 : m_TextureSmooth2;
}
void CLOSTexture::InterpolateLOS()
{
if (!g_Renderer.m_Options.m_SmoothLOS)
return;
if (m_Dirty)
{
RecomputeTexture(0);
m_Dirty = false;
}
GLint originalFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &originalFBO);
pglBindFramebufferEXT(GL_FRAMEBUFFER, m_smoothFbo);
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
whichTex ? m_TextureSmooth2 : m_TextureSmooth1, 0);
GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
LOGWARNING(L"LOS framebuffer object incomplete: 0x%04X", status);
}
m_smoothShader->BeginPass();
CShaderProgramPtr shader = m_smoothShader->GetShader();
shader->Bind();
shader->BindTexture("losTex1", m_Texture);
shader->BindTexture("losTex2", whichTex ? m_TextureSmooth1 : m_TextureSmooth2);
shader->Uniform("delta", (float)g_Renderer.GetTimeManager().GetFrameDelta() * 4.0f, 0.0f, 0.0f, 0.0f);
glPushAttrib(GL_VIEWPORT_BIT);
glViewport(0, 0, m_TextureSize, m_TextureSize);
glBegin(GL_QUADS);
glColor4f(1.f, 1.f, 1.f, 1.f);
glTexCoord2f(1.0, 1.0); glVertex2f(1,1);
glTexCoord2f(0.0, 1.0); glVertex2f(-1,1);
glTexCoord2f(0.0, 0.0); glVertex2f(-1,-1);
glTexCoord2f(1.0, 0.0); glVertex2f(1,-1);
glEnd();
glPopAttrib();
shader->Unbind();
m_smoothShader->EndPass();
pglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, originalFBO);
whichTex = !whichTex;
}
GLuint CLOSTexture::GetTexture()
{
if (m_Dirty)
@ -114,20 +202,41 @@ void CLOSTexture::ConstructTexture(int unit)
m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize + g_BlurSize - 1);
glGenTextures(1, &m_Texture);
g_Renderer.BindTexture(unit, m_Texture);
// Initialise texture with SoD colour, for the areas we don't
// overwrite with glTexSubImage2D later
u8* texData = new u8[m_TextureSize * m_TextureSize];
memset(texData, 0x00, m_TextureSize * m_TextureSize);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData);
delete[] texData;
u8* texData = new u8[m_TextureSize * m_TextureSize * 4];
memset(texData, 0x00, m_TextureSize * m_TextureSize * 4);
if (g_Renderer.m_Options.m_SmoothLOS)
{
glGenTextures(1, &m_TextureSmooth1);
glGenTextures(1, &m_TextureSmooth2);
g_Renderer.BindTexture(unit, m_TextureSmooth1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData);
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);
g_Renderer.BindTexture(unit, m_TextureSmooth2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData);
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);
}
g_Renderer.BindTexture(unit, m_Texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData);
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);
delete[] texData;
{
// Texture matrix: We want to map
// world pos (0, y, 0) (i.e. first vertex)
@ -166,8 +275,12 @@ void CLOSTexture::RecomputeTexture(int unit)
DeleteTexture();
}
bool recreated = false;
if (!m_Texture)
{
ConstructTexture(unit);
recreated = true;
}
PROFILE("recompute LOS texture");
@ -182,6 +295,14 @@ void CLOSTexture::RecomputeTexture(int unit)
GenerateBitmap(los, &losData[0], m_MapSize, m_MapSize);
if (g_Renderer.m_Options.m_SmoothLOS && recreated)
{
g_Renderer.BindTexture(unit, m_TextureSmooth1);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize + g_BlurSize - 1, m_MapSize + g_BlurSize - 1, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]);
g_Renderer.BindTexture(unit, m_TextureSmooth2);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize + g_BlurSize - 1, m_MapSize + g_BlurSize - 1, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]);
}
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]);
}

View File

@ -20,6 +20,9 @@
#include "maths/Matrix3D.h"
#include "simulation2/components/ICmpRangeManager.h"
#include "graphics/ShaderManager.h"
class CSimulation2;
/**
@ -55,6 +58,9 @@ public:
* The texture is in 8-bit ALPHA format.
*/
GLuint GetTexture();
void InterpolateLOS();
GLuint GetTextureSmooth();
/**
* Returns a matrix to map (x,y,z) world coordinates onto (u,v) LOS texture
@ -83,6 +89,12 @@ private:
bool m_Dirty;
GLuint m_Texture;
GLuint m_TextureSmooth1, m_TextureSmooth2;
bool whichTex;
GLuint m_smoothFbo;
CShaderTechniquePtr m_smoothShader;
ssize_t m_MapSize; // vertexes per side
GLsizei m_TextureSize; // texels per side

View File

@ -95,7 +95,7 @@ void ShaderRenderModifier::BeginPass(const CShaderProgramPtr& shader)
if (shader->GetTextureBinding("losTex").Active())
{
CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture();
shader->BindTexture("losTex", los.GetTexture());
shader->BindTexture("losTex", los.GetTextureSmooth());
// Don't bother sending the whole matrix, we just need two floats (scale and translation)
shader->Uniform("losTransform", los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
}

View File

@ -46,6 +46,7 @@
#include "graphics/Camera.h"
#include "graphics/GameView.h"
#include "graphics/LightEnv.h"
#include "graphics/LOSTexture.h"
#include "graphics/MaterialManager.h"
#include "graphics/Model.h"
#include "graphics/ModelDef.h"
@ -435,12 +436,14 @@ CRenderer::CRenderer()
m_Options.m_ForceAlphaTest = false;
m_Options.m_GPUSkinning = false;
m_Options.m_GenTangents = false;
m_Options.m_SmoothLOS = false;
// TODO: be more consistent in use of the config system
CFG_GET_USER_VAL("preferglsl", Bool, m_Options.m_PreferGLSL);
CFG_GET_USER_VAL("forcealphatest", Bool, m_Options.m_ForceAlphaTest);
CFG_GET_USER_VAL("gpuskinning", Bool, m_Options.m_GPUSkinning);
CFG_GET_USER_VAL("gentangents", Bool, m_Options.m_GenTangents);
CFG_GET_USER_VAL("smoothlos", Bool, m_Options.m_SmoothLOS);
#if CONFIG2_GLES
// Override config option since GLES only supports GLSL
@ -1358,6 +1361,8 @@ void CRenderer::RenderParticles()
void CRenderer::RenderSubmissions()
{
PROFILE3("render submissions");
GetScene().GetLOSTexture().InterpolateLOS();
CShaderDefines context = m->globalContext;

View File

@ -132,6 +132,7 @@ public:
bool m_GPUSkinning;
bool m_Silhouettes;
bool m_GenTangents;
bool m_SmoothLOS;
} m_Options;
struct Caps {

View File

@ -477,7 +477,7 @@ void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap*
shader->Uniform("sunColor", lightEnv.m_SunColor);
CLOSTexture& los = g_Renderer.GetScene().GetLOSTexture();
shader->BindTexture("losTex", los.GetTexture());
shader->BindTexture("losTex", los.GetTextureSmooth());
shader->Uniform("losTransform", los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
shader->Uniform("ambient", lightEnv.m_TerrainAmbientColor);
@ -709,7 +709,7 @@ bool TerrainRenderer::RenderFancyWater()
m->fancyWaterShader->BindTexture("reflectionMap", WaterMgr->m_ReflectionTexture);
m->fancyWaterShader->BindTexture("refractionMap", WaterMgr->m_RefractionTexture);
m->fancyWaterShader->BindTexture("losMap", losTexture.GetTexture());
m->fancyWaterShader->BindTexture("losMap", losTexture.GetTextureSmooth());
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
m->fancyWaterShader->Uniform("ambient", lightEnv.m_TerrainAmbientColor);

View File

@ -617,7 +617,13 @@ void CCmpVisualActor::UpdateVisibility()
else
{
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY);
m_Visibility = cmpRangeManager->GetLosVisibility(GetEntityId(), GetSimContext().GetCurrentDisplayedPlayer());
// Uncomment the following lines to prevent the models from popping into existence
// near the LOS boundary. Is rather resource intensive.
//if (cmpVision->GetRetainInFog())
// m_Visibility = ICmpRangeManager::VIS_VISIBLE;
//else
m_Visibility = cmpRangeManager->GetLosVisibility(GetEntityId(),
GetSimContext().GetCurrentDisplayedPlayer());
}
}
else