GLES compatibility for particles and shadows.

Fix invalid enum errors.
Fix shader texture binding.

This was SVN commit r11372.
This commit is contained in:
Ykkrosh 2012-03-19 21:10:14 +00:00
parent 8c6231f940
commit 36107cb7e1
19 changed files with 344 additions and 138 deletions

View File

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

View File

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

View File

@ -1,10 +1,16 @@
#version 110
uniform sampler2D baseTex;
#ifdef USE_SHADOW
uniform sampler2DShadow shadowTex;
#endif
uniform sampler2D losTex;
#ifdef USE_SHADOW
#ifdef USE_SHADOW_SAMPLER
uniform sampler2DShadow shadowTex;
#else
uniform sampler2D shadowTex;
#endif
#endif
uniform vec3 objectColor;
uniform vec3 shadingColor;
uniform vec3 ambient;
@ -16,6 +22,39 @@ varying vec2 v_tex;
varying vec4 v_shadow;
varying vec2 v_los;
float get_shadow()
{
#ifdef USE_SHADOW
#ifdef USE_SHADOW_SAMPLER
#ifdef USE_SHADOW_PCF
return 0.25 * (
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.zw, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.zw, v_shadow.z)).a
);
#else
return shadow2D(shadowTex, v_shadow.xyz).a;
#endif
#else
if (v_shadow.z >= 1.0)
return 1.0;
#ifdef USE_SHADOW_PCF
return (
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets1.xy).x ? 0.25 : 0.0) +
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets1.zw).x ? 0.25 : 0.0) +
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets2.xy).x ? 0.25 : 0.0) +
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets2.zw).x ? 0.25 : 0.0)
);
#else
return (v_shadow.z <= texture2D(shadowTex, v_shadow.xy).x ? 1.0 : 0.0);
#endif
#endif
#else
return 1.0;
#endif
}
void main()
{
vec4 tex = texture2D(baseTex, v_tex);
@ -38,22 +77,7 @@ void main()
color *= mix(objectColor, vec3(1.0, 1.0, 1.0), tex.a);
#endif
#ifdef USE_SHADOW
#ifdef USE_SHADOW_PCF
float shadow = (
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.zw, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.zw, v_shadow.z)).a
) * 0.25;
#else
float shadow = shadow2D(shadowTex, v_shadow.xyz).a;
#endif
#else
float shadow = 1.0;
#endif
color *= v_lighting * shadow + ambient;
color *= v_lighting * get_shadow() + ambient;
color *= texture2D(losTex, v_los).a;

View File

@ -0,0 +1,11 @@
#version 110
uniform sampler2D baseTex;
varying vec2 v_tex;
varying vec4 v_color;
void main()
{
gl_FragColor = texture2D(baseTex, v_tex) * v_color;
}

View File

@ -0,0 +1,25 @@
#version 110
uniform mat4 transform;
varying vec2 v_tex;
varying vec4 v_color;
attribute vec3 a_vertex;
attribute vec4 a_color;
attribute vec2 a_uv0;
attribute vec2 a_uv1;
void main()
{
vec3 axis1 = vec3(transform[0][0], transform[1][0], transform[2][0]);
vec3 axis2 = vec3(transform[0][1], transform[1][1], transform[2][1]);
vec2 offset = a_uv1;
vec3 position = axis1*offset.x + axis1*offset.y + axis2*offset.x + axis2*-offset.y + a_vertex;
gl_Position = transform * vec4(position, 1.0);
v_tex = a_uv0;
v_color = a_color;
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<program type="glsl">
<vertex file="glsl/particle.vs">
<stream name="pos"/>
<stream name="color"/>
<stream name="uv0"/>
<stream name="uv1"/>
<attrib name="a_vertex" semantics="gl_Vertex"/>
<attrib name="a_color" semantics="gl_Color"/>
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
<attrib name="a_uv1" semantics="gl_MultiTexCoord1"/>
</vertex>
<fragment file="glsl/particle.fs"/>
</program>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<program type="glsl">
<vertex file="glsl/particle.vs">
<stream name="pos"/>
<stream name="color"/>
<stream name="uv0"/>
<stream name="uv1"/>
<attrib name="a_vertex" semantics="gl_Vertex"/>
<attrib name="a_color" semantics="gl_Color"/>
<attrib name="a_uv0" semantics="gl_MultiTexCoord0"/>
<attrib name="a_uv1" semantics="gl_MultiTexCoord1"/>
</vertex>
<fragment file="glsl/particle.fs"/>
</program>

View File

@ -2,10 +2,16 @@
uniform sampler2D baseTex;
uniform sampler2D blendTex;
#ifdef USE_SHADOW
uniform sampler2DShadow shadowTex;
#endif
uniform sampler2D losTex;
#ifdef USE_SHADOW
#ifdef USE_SHADOW_SAMPLER
uniform sampler2DShadow shadowTex;
#else
uniform sampler2D shadowTex;
#endif
#endif
uniform vec3 shadingColor;
uniform vec3 ambient;
uniform vec4 shadowOffsets1;
@ -17,9 +23,41 @@ varying vec4 v_shadow;
varying vec2 v_los;
varying vec2 v_blend;
float get_shadow()
{
#ifdef USE_SHADOW
#ifdef USE_SHADOW_SAMPLER
#ifdef USE_SHADOW_PCF
return 0.25 * (
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.zw, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.zw, v_shadow.z)).a
);
#else
return shadow2D(shadowTex, v_shadow.xyz).a;
#endif
#else
if (v_shadow.z >= 1.0)
return 1.0;
#ifdef USE_SHADOW_PCF
return (
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets1.xy).x ? 0.25 : 0.0) +
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets1.zw).x ? 0.25 : 0.0) +
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets2.xy).x ? 0.25 : 0.0) +
(v_shadow.z <= texture2D(shadowTex, v_shadow.xy + shadowOffsets2.zw).x ? 0.25 : 0.0)
);
#else
return (v_shadow.z <= texture2D(shadowTex, v_shadow.xy).x ? 1.0 : 0.0);
#endif
#endif
#else
return 1.0;
#endif
}
void main()
{
#ifdef BLEND
// Use alpha from blend texture
gl_FragColor.a = 1.0 - texture2D(blendTex, v_blend).a;
@ -33,22 +71,7 @@ void main()
gl_FragColor.a = color.a;
#endif
#ifdef USE_SHADOW
#ifdef USE_SHADOW_PCF
float shadow = (
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets1.zw, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.xy, v_shadow.z)).a +
shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.zw, v_shadow.z)).a
) * 0.25;
#else
float shadow = shadow2D(shadowTex, v_shadow.xyz).a;
#endif
#else
float shadow = 1.0;
#endif
color.rgb *= v_lighting * shadow + ambient;
color.rgb *= v_lighting * get_shadow() + ambient;
color *= texture2D(losTex, v_los).a;

View File

@ -30,6 +30,9 @@ void main()
float c = textureTransform.x;
float s = -textureTransform.y;
v_tex = vec2(a_vertex.x * c + a_vertex.z * -s, a_vertex.x * -s + a_vertex.z * -c);
// XXX: Ugly hack to hide some precision issues in GLES
v_tex = mod(v_tex, vec2(9.0, 9.0));
#endif
#ifdef BLEND

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011 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
@ -28,6 +28,7 @@
CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
m_Type(type), m_Active(true), m_NextParticleIdx(0), m_EmissionRoundingError(0.f),
m_LastUpdateTime(type->m_Manager.GetCurrentTime()),
m_IndexArray(GL_DYNAMIC_DRAW),
m_VertexArray(GL_DYNAMIC_DRAW)
{
// If we should start with particles fully emitted, pretend that we
@ -60,6 +61,21 @@ CParticleEmitter::CParticleEmitter(const CParticleEmitterTypePtr& type) :
m_VertexArray.SetNumVertices(m_Type->m_MaxParticles * 4);
m_VertexArray.Layout();
m_IndexArray.SetNumVertices(m_Type->m_MaxParticles * 6);
m_IndexArray.Layout();
VertexArrayIterator<u16> index = m_IndexArray.GetIterator();
for (size_t i = 0; i < m_Type->m_MaxParticles; ++i)
{
*index++ = i*4 + 0;
*index++ = i*4 + 1;
*index++ = i*4 + 2;
*index++ = i*4 + 2;
*index++ = i*4 + 3;
*index++ = i*4 + 0;
}
m_IndexArray.Upload();
m_IndexArray.FreeBackingStore();
}
void CParticleEmitter::UpdateArrayData()
@ -153,13 +169,14 @@ void CParticleEmitter::Bind()
glBlendFunc(m_Type->m_BlendFuncSrc, m_Type->m_BlendFuncDst);
}
void CParticleEmitter::RenderArray(CShaderProgramPtr& shader)
void CParticleEmitter::RenderArray(const CShaderProgramPtr& shader)
{
// Some drivers apparently don't like count=0 in glDrawArrays here,
// so skip all drawing in that case
if (m_Particles.empty())
return;
u8* indexBase = m_IndexArray.Bind();
u8* base = m_VertexArray.Bind();
GLsizei stride = (GLsizei)m_VertexArray.GetStride();
@ -174,11 +191,7 @@ void CParticleEmitter::RenderArray(CShaderProgramPtr& shader)
shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, base + m_AttributeColor.offset);
shader->AssertPointersBound();
#if CONFIG2_GLES
#warning TODO: change CParticleEmitter to use (indexed?) triangles instead of quads, for GLES
#else
glDrawArrays(GL_QUADS, 0, m_Particles.size()*4);
#endif
glDrawElements(GL_TRIANGLES, (GLsizei)(m_Particles.size() * 6), GL_UNSIGNED_SHORT, indexBase);
g_Renderer.GetStats().m_DrawCalls++;
g_Renderer.GetStats().m_Particles += m_Particles.size();

View File

@ -103,7 +103,7 @@ public:
/**
* Draw the vertex array.
*/
void RenderArray(CShaderProgramPtr& shader);
void RenderArray(const CShaderProgramPtr& shader);
/**
* Stop this emitter emitting new particles, and pass responsibility for rendering
@ -135,6 +135,8 @@ private:
/// Bounding box of the current particle center points
CBoundingBoxAligned m_ParticleBounds;
VertexIndexArray m_IndexArray;
VertexArray m_VertexArray;
VertexArray::Attribute m_AttributePos;
VertexArray::Attribute m_AttributeAxis;

View File

@ -1075,7 +1075,9 @@ Status ogl_tex_bind(Handle ht, size_t unit)
// we therefore complain so this one can be ruled out.
ENSURE(ot->id != 0);
#if !CONFIG2_GLES
glEnable(GL_TEXTURE_2D);
#endif
glBindTexture(GL_TEXTURE_2D, ot->id);
return INFO::OK;
}

View File

@ -27,8 +27,8 @@
struct ParticleRendererInternals
{
CShaderProgramPtr shader;
CShaderProgramPtr shaderSolid;
CShaderTechniquePtr shader;
CShaderTechniquePtr shaderSolid;
std::vector<CParticleEmitter*> emitters;
};
@ -78,11 +78,6 @@ void ParticleRenderer::PrepareForRendering()
{
PROFILE3("prepare particles");
#if CONFIG2_GLES
#warning TODO: implement particles for GLES
return;
#endif
// Can't load the shader in the constructor because it's called before the
// renderer initialisation is complete, so load it the first time through here
if (!m->shader)
@ -91,8 +86,8 @@ void ParticleRenderer::PrepareForRendering()
// RenderParticles will never be called so it's safe to leave the shaders as null
if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
{
m->shader = g_Renderer.GetShaderManager().LoadProgram("particle");
m->shaderSolid = g_Renderer.GetShaderManager().LoadProgram("particle_solid");
m->shader = g_Renderer.GetShaderManager().LoadEffect("particle");
m->shaderSolid = g_Renderer.GetShaderManager().LoadEffect("particle_solid");
}
}
@ -118,14 +113,11 @@ void ParticleRenderer::PrepareForRendering()
void ParticleRenderer::RenderParticles(bool solidColor)
{
#if CONFIG2_GLES
#warning TODO: implement particles for GLES
return;
#endif
CShaderTechniquePtr shader = solidColor ? m->shaderSolid : m->shader;
CShaderProgramPtr shader = solidColor ? m->shaderSolid : m->shader;
shader->BeginPass();
shader->Bind();
shader->GetShader()->Uniform("transform", g_Renderer.GetViewCamera().GetViewProjection());
if (!solidColor)
glEnable(GL_BLEND);
@ -136,7 +128,7 @@ void ParticleRenderer::RenderParticles(bool solidColor)
CParticleEmitter* emitter = m->emitters[i];
emitter->Bind();
emitter->RenderArray(shader);
emitter->RenderArray(shader->GetShader());
}
CVertexBuffer::Unbind();
@ -147,7 +139,7 @@ void ParticleRenderer::RenderParticles(bool solidColor)
glDisable(GL_BLEND);
glDepthMask(1);
shader->Unbind();
shader->EndPass();
}
void ParticleRenderer::RenderBounds(CShaderProgramPtr& shader)

View File

@ -746,7 +746,7 @@ void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches, const CS
{
if (itt->first)
{
itt->first->GetTexture()->Bind();
shader->BindTexture("baseTex", itt->first->GetTexture());
#if !CONFIG2_GLES
if (isDummyShader)
@ -765,7 +765,7 @@ void CPatchRData::RenderBases(const std::vector<CPatchRData*>& patches, const CS
}
else
{
g_Renderer.GetTextureManager().GetErrorTexture()->Bind();
shader->BindTexture("baseTex", g_Renderer.GetTextureManager().GetErrorTexture());
}
for (VertexBufferBatches::iterator itv = itt->second.begin(); itv != itt->second.end(); ++itv)
@ -931,7 +931,7 @@ void CPatchRData::RenderBlends(const std::vector<CPatchRData*>& patches, const C
{
if (itt->m_Texture)
{
itt->m_Texture->GetTexture()->Bind();
shader->BindTexture("baseTex", itt->m_Texture->GetTexture());
#if !CONFIG2_GLES
if (isDummyShader)
@ -951,7 +951,7 @@ void CPatchRData::RenderBlends(const std::vector<CPatchRData*>& patches, const C
}
else
{
g_Renderer.GetTextureManager().GetErrorTexture()->Bind();
shader->BindTexture("baseTex", g_Renderer.GetTextureManager().GetErrorTexture());
}
for (VertexBufferBatches::iterator itv = itt->m_Batches.begin(); itv != itt->m_Batches.end(); ++itv)

View File

@ -541,11 +541,15 @@ void CRenderer::EnumCaps()
m_Caps.m_FragmentShader = true;
}
#if CONFIG2_GLES
m_Caps.m_Shadows = true;
#else
if (0 == ogl_HaveExtensions(0, "GL_ARB_shadow", "GL_ARB_depth_texture", "GL_EXT_framebuffer_object", NULL))
{
if (ogl_max_tex_units >= 4)
m_Caps.m_Shadows = true;
}
#endif
}
void CRenderer::ReloadShaders()
@ -562,6 +566,9 @@ void CRenderer::ReloadShaders()
defBasic["USE_FP_SHADOW"] = "1";
if (m_Options.m_ShadowPCF)
defBasic["USE_SHADOW_PCF"] = "1";
#if !CONFIG2_GLES
defBasic["USE_SHADOW_SAMPLER"] = "1";
#endif
}
if (m_LightEnv)
@ -958,6 +965,8 @@ void CRenderer::RenderShadowMap()
#endif
m->shadow->EndRender();
m->SetOpenGLCamera(m_ViewCamera);
}
void CRenderer::RenderPatches(const CFrustum* frustum)
@ -1223,7 +1232,7 @@ SScreenRect CRenderer::RenderReflections(const CBoundingBoxAligned& scissor)
glEnable(GL_SCISSOR_TEST);
glScissor(screenScissor.x1, screenScissor.y1, screenScissor.x2 - screenScissor.x1, screenScissor.y2 - screenScissor.y1);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glFrontFace(GL_CW);
@ -1608,7 +1617,8 @@ void CRenderer::RenderSubmissions()
if (m_DisplayFrustum)
{
DisplayFrustum();
m->shadow->RenderDebugDisplay();
m->shadow->RenderDebugBounds();
m->shadow->RenderDebugTexture();
ogl_WarnIfError();
}
@ -1802,16 +1812,18 @@ Scene& CRenderer::GetScene()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BindTexture: bind a GL texture object to current active unit
void CRenderer::BindTexture(int unit,GLuint tex)
void CRenderer::BindTexture(int unit, GLuint tex)
{
pglActiveTextureARB(GL_TEXTURE0+unit);
glBindTexture(GL_TEXTURE_2D,tex);
glBindTexture(GL_TEXTURE_2D, tex);
#if !CONFIG2_GLES
if (tex) {
glEnable(GL_TEXTURE_2D);
} else {
glDisable(GL_TEXTURE_2D);
}
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -239,6 +239,9 @@ public:
// return the current view camera
const CCamera& GetViewCamera() const { return m_ViewCamera; }
// replace the current view camera
void SetViewCamera(const CCamera& camera) { m_ViewCamera = camera; }
// return the current cull camera
const CCamera& GetCullCamera() const { return m_CullCamera; }

View File

@ -21,6 +21,7 @@
#include "precompiled.h"
#include "gui/GUIutil.h"
#include "lib/bits.h"
#include "lib/ogl.h"
#include "ps/CLogger.h"
@ -79,6 +80,10 @@ struct ShadowMapInternals
// alpha texture which is attached to the FBO as a workaround.
GLuint DummyTexture;
// Copy of renderer's standard view camera, saved between
// BeginRender and EndRender while we replace it with the shadow camera
CCamera SavedViewCamera;
float FilterOffsets[8];
// Helper functions
@ -233,7 +238,7 @@ void ShadowMapInternals::CalcShadowMatrices()
// minimum Z bound must not be clipped too much, because objects that lie outside
// the shadow bounds cannot cast shadows either
// the 2.0 is rather arbitrary: it should be big enough so that we won't accidently miss
// the 2.0 is rather arbitrary: it should be big enough so that we won't accidentally miss
// a shadow generator, and small enough not to affect Z precision
ShadowBound[0].Z = minZ - 2.0;
@ -317,9 +322,8 @@ void ShadowMapInternals::CreateTexture()
}
else
{
// get shadow map size as next power of two up from view width and height
Width = (int)round_up_to_pow2((unsigned)g_Renderer.GetWidth());
Height = (int)round_up_to_pow2((unsigned)g_Renderer.GetHeight());
// get shadow map size as next power of two up from view width/height
Width = Height = (int)round_up_to_pow2((unsigned)std::max(g_Renderer.GetWidth(), g_Renderer.GetHeight()));
}
// Clamp to the maximum texture size
Width = std::min(Width, (int)ogl_max_tex_size);
@ -359,31 +363,42 @@ void ShadowMapInternals::CreateTexture()
GLenum format;
switch(DepthTextureBits)
#if CONFIG2_GLES
format = GL_DEPTH_COMPONENT;
#else
switch (DepthTextureBits)
{
case 16: format = GL_DEPTH_COMPONENT16; break;
#if !CONFIG2_GLES
case 24: format = GL_DEPTH_COMPONENT24; break;
case 32: format = GL_DEPTH_COMPONENT32; break;
#endif
default: format = GL_DEPTH_COMPONENT; break;
}
glTexImage2D(GL_TEXTURE_2D, 0, format, Width, Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
#if CONFIG2_GLES
#warning TODO: implement shadows with non-depth textures and explicit comparisons in the GLSL
#else
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, format, Width, Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);
// GLES requires type == UNSIGNED_SHORT or UNSIGNED_INT
// set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#if CONFIG2_GLES
// GLES doesn't do depth comparisons, so treat it as a
// basic unfiltered depth texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
#else
// Enable automatic depth comparisons
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
// Use GL_LINEAR to trigger automatic PCF on some devices
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#endif
ogl_WarnIfError();
// bind to framebuffer object
glBindTexture(GL_TEXTURE_2D, 0);
@ -408,6 +423,8 @@ void ShadowMapInternals::CreateTexture()
glReadBuffer(GL_NONE);
#endif
ogl_WarnIfError();
GLenum status = pglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@ -452,22 +469,27 @@ void ShadowMap::BeginRender()
// clear buffers
{
PROFILE("clear depth texture");
glClear(GL_DEPTH_BUFFER_BIT);
// In case we used m_ShadowAlphaFix, we ought to clear the unused
// color buffer too, else Mali 400 drivers get confused.
// Might as well clear stencil too for completeness.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glColorMask(0,0,0,0);
}
// setup viewport
glViewport(0, 0, m->EffectiveWidth, m->EffectiveHeight);
#if CONFIG2_GLES
#warning TODO: implement ShdaowMap::BeginRender GLES
#else
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(&m->LightProjection._11);
m->SavedViewCamera = g_Renderer.GetViewCamera();
CCamera c = m->SavedViewCamera;
c.SetProjection(m->LightProjection);
c.GetOrientation() = m->InvLightTransform;
g_Renderer.SetViewCamera(c);
#if !CONFIG2_GLES
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(&m->LightProjection._11);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(&m->LightTransform._11);
#endif
@ -482,6 +504,8 @@ void ShadowMap::EndRender()
{
glDisable(GL_SCISSOR_TEST);
g_Renderer.SetViewCamera(m->SavedViewCamera);
{
PROFILE("unbind framebuffer");
pglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@ -490,14 +514,6 @@ void ShadowMap::EndRender()
glViewport(0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight());
glColorMask(1,1,1,1);
#if !CONFIG2_GLES
// restore matrix stack
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
#endif
}
@ -542,9 +558,8 @@ const float* ShadowMap::GetFilterOffsets() const
}
//////////////////////////////////////////////////////////////////////////////
// RenderDebugDisplay: debug visualizations
// - blue: objects in shadow
void ShadowMap::RenderDebugDisplay()
void ShadowMap::RenderDebugBounds()
{
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect("gui_solid");
shaderTech->BeginPass();
@ -617,36 +632,48 @@ void ShadowMap::RenderDebugDisplay()
glPopMatrix();
#endif
// Render the shadow map
#if CONFIG2_GLES
#warning TODO: implement ShadowMap::RenderDebugDisplay for GLES
#else
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glEnable(GL_CULL_FACE);
glDepthMask(1);
}
void ShadowMap::RenderDebugTexture()
{
glDepthMask(0);
glDisable(GL_DEPTH_TEST);
#if !CONFIG2_GLES
g_Renderer.BindTexture(0, m->Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f(0.2f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f(0.2f, 0.2f);
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 0.2f);
glEnd();
#endif
CShaderTechniquePtr texTech = g_Renderer.GetShaderManager().LoadEffect("gui_basic");
texTech->BeginPass();
CShaderProgramPtr texShader = texTech->GetShader();
texShader->Uniform("transform", GetDefaultGuiMatrix());
texShader->BindTexture("tex", m->Texture);
float s = 256.f;
float boxVerts[] = {
0,0, 0,s, s,0,
s,0, 0,s, s,s
};
float boxUV[] = {
0,0, 0,1, 1,0,
1,0, 0,1, 1,1
};
texShader->VertexPointer(2, GL_FLOAT, 0, boxVerts);
texShader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 0, boxUV);
texShader->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, 0, 6);
texTech->EndPass();
#if !CONFIG2_GLES
g_Renderer.BindTexture(0, m->Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glEnable(GL_CULL_FACE);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
#endif
glEnable(GL_DEPTH_TEST);

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
@ -113,10 +113,15 @@ public:
const CMatrix3D& GetTextureMatrix() const;
/**
* RenderDebugDisplay: Visualize shadow mapping calculations to help in
* Visualize shadow mapping calculations to help in
* debugging and optimal shadow map usage.
*/
void RenderDebugDisplay();
void RenderDebugBounds();
/**
* Visualize shadow map texture to help in debugging.
*/
void RenderDebugTexture();
/**
* Get offsets for PCF filtering.

View File

@ -408,6 +408,8 @@ void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap*
shader->Uniform("ambient", lightEnv.m_TerrainAmbientColor);
shader->Uniform("sunColor", lightEnv.m_SunColor);
shader->BindTexture("blendTex", g_Renderer.m_hCompositeAlphaMap);
}
void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow, bool filtered)
@ -430,6 +432,9 @@ void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow, bool filtered)
defBasic["USE_FP_SHADOW"] = "1";
if (g_Renderer.m_Options.m_ShadowPCF)
defBasic["USE_SHADOW_PCF"] = "1";
#if !CONFIG2_GLES
defBasic["USE_SHADOW_SAMPLER"] = "1";
#endif
}
defBasic["LIGHTING_MODEL_" + g_Renderer.GetLightEnv().GetLightingModel()] = "1";
@ -466,9 +471,6 @@ void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow, bool filtered)
techBlend->BeginPass();
PrepareShader(techBlend->GetShader(), shadow);
// switch on the composite alpha map texture
(void)ogl_tex_bind(g_Renderer.m_hCompositeAlphaMap, 1);
// switch on blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);