GLES compatibility for particles and shadows.
Fix invalid enum errors. Fix shader texture binding. This was SVN commit r11372.
This commit is contained in:
parent
8c6231f940
commit
36107cb7e1
14
binaries/data/mods/public/shaders/effects/particle.xml
Normal file
14
binaries/data/mods/public/shaders/effects/particle.xml
Normal 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>
|
14
binaries/data/mods/public/shaders/effects/particle_solid.xml
Normal file
14
binaries/data/mods/public/shaders/effects/particle_solid.xml
Normal 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>
|
@ -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;
|
||||
|
||||
|
11
binaries/data/mods/public/shaders/glsl/particle.fs
Normal file
11
binaries/data/mods/public/shaders/glsl/particle.fs
Normal 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;
|
||||
}
|
25
binaries/data/mods/public/shaders/glsl/particle.vs
Normal file
25
binaries/data/mods/public/shaders/glsl/particle.vs
Normal 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;
|
||||
}
|
17
binaries/data/mods/public/shaders/glsl/particle.xml
Normal file
17
binaries/data/mods/public/shaders/glsl/particle.xml
Normal 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>
|
17
binaries/data/mods/public/shaders/glsl/particle_solid.xml
Normal file
17
binaries/data/mods/public/shaders/glsl/particle_solid.xml
Normal 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>
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user