diff --git a/binaries/data/mods/public/shaders/model_common.fs b/binaries/data/mods/public/shaders/model_common.fs index e54a551426..25b8575864 100644 --- a/binaries/data/mods/public/shaders/model_common.fs +++ b/binaries/data/mods/public/shaders/model_common.fs @@ -1,3 +1,5 @@ +#version 110 + uniform sampler2D baseTex; uniform sampler2DShadow shadowTex; uniform sampler2D losTex; @@ -26,7 +28,7 @@ void main() // Apply player-coloring based on texture alpha #ifdef USE_OBJECTCOLOR - color *= mix(objectColor, 1.0, tex.a); + color *= mix(objectColor, vec3(1.0, 1.0, 1.0), tex.a); #endif #ifdef USE_SHADOW @@ -38,7 +40,7 @@ void main() shadow2D(shadowTex, vec3(v_shadow.xy + shadowOffsets2.zw, v_shadow.z)).a ) * 0.25; #else - float shadow = shadow2D(shadowTex, v_shadow).a; + float shadow = shadow2D(shadowTex, v_shadow.xyz).a; #endif #else float shadow = 1.0; diff --git a/binaries/data/mods/public/shaders/model_common.vs b/binaries/data/mods/public/shaders/model_common.vs index 56d58a81c4..74acc7e989 100644 --- a/binaries/data/mods/public/shaders/model_common.vs +++ b/binaries/data/mods/public/shaders/model_common.vs @@ -1,3 +1,5 @@ +#version 110 + uniform vec3 sunDir; uniform vec3 sunColor; uniform vec2 losTransform; @@ -9,20 +11,24 @@ varying vec2 v_tex; varying vec4 v_shadow; varying vec2 v_los; +attribute vec3 a_vertex; +attribute vec3 a_normal; +attribute vec2 a_uv0; + void main() { #ifdef USE_INSTANCING - vec4 position = instancingTransform * gl_Vertex; - vec3 normal = instancingTransform * vec4(gl_Normal, 0.0); + vec4 position = instancingTransform * vec4(a_vertex, 1.0); + vec3 normal = (instancingTransform * vec4(a_normal, 0.0)).xyz; #else - vec4 position = gl_Vertex; - vec3 normal = gl_Normal; + vec4 position = vec4(a_vertex, 1.0); + vec3 normal = a_normal; #endif gl_Position = gl_ModelViewProjectionMatrix * position; v_lighting = max(0.0, dot(normal, -sunDir)) * sunColor; - v_tex = gl_MultiTexCoord0.xy; + v_tex = a_uv0; v_shadow = shadowTransform * position; v_los = position.xz * losTransform.x + losTransform.y; } diff --git a/binaries/data/mods/public/shaders/model_common_glsl.xml b/binaries/data/mods/public/shaders/model_common_glsl.xml index bfe49c675c..662d5c3dc8 100644 --- a/binaries/data/mods/public/shaders/model_common_glsl.xml +++ b/binaries/data/mods/public/shaders/model_common_glsl.xml @@ -5,6 +5,9 @@ + + + diff --git a/binaries/data/mods/public/shaders/model_common_instancing_glsl.xml b/binaries/data/mods/public/shaders/model_common_instancing_glsl.xml index 641ad2c213..a8ad6ba626 100644 --- a/binaries/data/mods/public/shaders/model_common_instancing_glsl.xml +++ b/binaries/data/mods/public/shaders/model_common_instancing_glsl.xml @@ -7,6 +7,9 @@ + + + diff --git a/binaries/data/mods/public/shaders/program.rng b/binaries/data/mods/public/shaders/program.rng index 30c43fcaf8..10f4bd8beb 100644 --- a/binaries/data/mods/public/shaders/program.rng +++ b/binaries/data/mods/public/shaders/program.rng @@ -48,7 +48,23 @@ - + + + gl_Vertex + gl_Normal + gl_Color + gl_SecondaryColor + gl_FogCoord + gl_MultiTexCoord0 + gl_MultiTexCoord1 + gl_MultiTexCoord2 + gl_MultiTexCoord3 + gl_MultiTexCoord4 + gl_MultiTexCoord5 + gl_MultiTexCoord6 + gl_MultiTexCoord7 + + diff --git a/binaries/data/mods/public/shaders/water_high.fs b/binaries/data/mods/public/shaders/water_high.fs index f6f2ad0fab..114f5a2c1b 100644 --- a/binaries/data/mods/public/shaders/water_high.fs +++ b/binaries/data/mods/public/shaders/water_high.fs @@ -1,3 +1,5 @@ +#version 110 + uniform vec3 ambient; uniform vec3 sunDir; uniform vec3 sunColor; diff --git a/binaries/data/mods/public/shaders/water_high.vs b/binaries/data/mods/public/shaders/water_high.vs index f510c874cb..6e846028a1 100644 --- a/binaries/data/mods/public/shaders/water_high.vs +++ b/binaries/data/mods/public/shaders/water_high.vs @@ -1,3 +1,5 @@ +#version 110 + uniform mat4 reflectionMatrix; uniform mat4 refractionMatrix; uniform mat4 losMatrix; diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp index 13b88aaa2b..5368314edf 100644 --- a/source/graphics/ShaderManager.cpp +++ b/source/graphics/ShaderManager.cpp @@ -82,6 +82,29 @@ CShaderProgramPtr CShaderManager::LoadProgram(const char* name, const std::map& baseDefines, CShaderProgramPtr& program) { PROFILE2("loading shader"); @@ -120,17 +143,18 @@ bool CShaderManager::NewProgram(const char* name, const std::map& ba // Define all the elements and attributes used in the XML file #define EL(x) int el_##x = XeroFile.GetElementID(#x) #define AT(x) int at_##x = XeroFile.GetAttributeID(#x) - EL(vertex); - EL(fragment); - EL(define); - EL(uniform); EL(attrib); + EL(define); + EL(fragment); EL(stream); - AT(type); + EL(uniform); + EL(vertex); AT(file); - AT(name); - AT(value); AT(loc); + AT(name); + AT(semantics); + AT(type); + AT(value); #undef AT #undef EL @@ -142,6 +166,7 @@ bool CShaderManager::NewProgram(const char* name, const std::map& ba std::map defines = baseDefines; std::map vertexUniforms; std::map fragmentUniforms; + std::map vertexAttribs; int streamFlags = 0; XERO_ITER_EL(Root, Child) @@ -180,7 +205,8 @@ bool CShaderManager::NewProgram(const char* name, const std::map& ba } else if (Param.GetNodeName() == el_attrib) { - // TODO: add support for vertex attributes + int attribLoc = ParseAttribSemantics(Param.GetAttributes().GetNamedItem(at_semantics)); + vertexAttribs[Param.GetAttributes().GetNamedItem(at_name)] = attribLoc; } } } @@ -199,7 +225,7 @@ bool CShaderManager::NewProgram(const char* name, const std::map& ba } if (isGLSL) - program = CShaderProgramPtr(CShaderProgram::ConstructGLSL(vertexFile, fragmentFile, defines, streamFlags)); + program = CShaderProgramPtr(CShaderProgram::ConstructGLSL(vertexFile, fragmentFile, defines, vertexAttribs, streamFlags)); else program = CShaderProgramPtr(CShaderProgram::ConstructARB(vertexFile, fragmentFile, defines, vertexUniforms, fragmentUniforms, streamFlags)); diff --git a/source/graphics/ShaderProgram.cpp b/source/graphics/ShaderProgram.cpp index 59d6c4618e..22f1ee34e0 100644 --- a/source/graphics/ShaderProgram.cpp +++ b/source/graphics/ShaderProgram.cpp @@ -121,6 +121,8 @@ public: glEnable(GL_FRAGMENT_PROGRAM_ARB); pglBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_VertexProgram); pglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_FragmentProgram); + + BindClientStates(); } virtual void Unbind() @@ -130,6 +132,8 @@ public: pglBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0); pglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); + UnbindClientStates(); + // TODO: should unbind textures, probably } @@ -229,10 +233,12 @@ class CShaderProgramGLSL : public CShaderProgram public: CShaderProgramGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile, const std::map& defines, + const std::map& vertexAttribs, int streamflags) : CShaderProgram(streamflags), m_VertexFile(vertexFile), m_FragmentFile(fragmentFile), - m_Defines(defines) + m_Defines(defines), + m_VertexAttribs(vertexAttribs) { m_Program = 0; m_VertexShader = pglCreateShaderObjectARB(GL_VERTEX_SHADER); @@ -292,6 +298,12 @@ public: pglAttachObjectARB(m_Program, m_FragmentShader); ogl_WarnIfError(); + // Set up the attribute bindings explicitly, since apparently drivers + // don't always pick the most efficient bindings automatically, + // and also this lets us hardcode indexes into VertexPointer etc + for (std::map::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) + pglBindAttribLocationARB(m_Program, it->second, it->first.c_str()); + pglLinkProgramARB(m_Program); GLint ok = 0; @@ -397,12 +409,18 @@ public: virtual void Bind() { pglUseProgramObjectARB(m_Program); + + for (std::map::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) + pglEnableVertexAttribArrayARB(it->second); } virtual void Unbind() { pglUseProgramObjectARB(0); + for (std::map::iterator it = m_VertexAttribs.begin(); it != m_VertexAttribs.end(); ++it) + pglDisableVertexAttribArrayARB(it->second); + // TODO: should unbind textures, probably } @@ -489,10 +507,32 @@ public: } } + // Map the various fixed-function Pointer functions onto generic vertex attributes + // (matching the attribute indexes from ShaderManager's ParseAttribSemantics): + + virtual void VertexPointer(GLint size, GLenum type, GLsizei stride, void* pointer) + { + pglVertexAttribPointerARB(0, size, type, GL_FALSE, stride, pointer); + m_ValidStreams |= STREAM_POS; + } + + virtual void NormalPointer(GLenum type, GLsizei stride, void* pointer) + { + pglVertexAttribPointerARB(2, 3, type, GL_FALSE, stride, pointer); + m_ValidStreams |= STREAM_NORMAL; + } + + virtual void TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, void* pointer) + { + pglVertexAttribPointerARB(8 + texture - GL_TEXTURE0, size, type, GL_FALSE, stride, pointer); + m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); + } + private: VfsPath m_VertexFile; VfsPath m_FragmentFile; std::map m_Defines; + std::map m_VertexAttribs; GLhandleARB m_Program; GLhandleARB m_VertexShader; @@ -506,7 +546,7 @@ private: CShaderProgram::CShaderProgram(int streamflags) - : m_IsValid(false), m_StreamFlags(streamflags) + : m_IsValid(false), m_StreamFlags(streamflags), m_ValidStreams(0) { } @@ -520,9 +560,10 @@ CShaderProgram::CShaderProgram(int streamflags) /*static*/ CShaderProgram* CShaderProgram::ConstructGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile, const std::map& defines, + const std::map& vertexAttribs, int streamflags) { - return new CShaderProgramGLSL(vertexFile, fragmentFile, defines, streamflags); + return new CShaderProgramGLSL(vertexFile, fragmentFile, defines, vertexAttribs, streamflags); } bool CShaderProgram::IsValid() const @@ -600,6 +641,25 @@ void CShaderProgram::Uniform(uniform_id_t id, const CMatrix3D& v) Uniform(GetUniformBinding(id), v); } +void CShaderProgram::VertexPointer(GLint size, GLenum type, GLsizei stride, void* pointer) +{ + glVertexPointer(size, type, stride, pointer); + m_ValidStreams |= STREAM_POS; +} + +void CShaderProgram::NormalPointer(GLenum type, GLsizei stride, void* pointer) +{ + glNormalPointer(type, stride, pointer); + m_ValidStreams |= STREAM_NORMAL; +} + +void CShaderProgram::TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, void* pointer) +{ + pglActiveTextureARB(texture); + glTexCoordPointer(size, type, stride, pointer); + m_ValidStreams |= STREAM_UV0 << (texture - GL_TEXTURE0); +} + CStr CShaderProgram::Preprocess(CPreprocessor& preprocessor, const CStr& input) { size_t len = 0; @@ -620,3 +680,56 @@ CStr CShaderProgram::Preprocess(CPreprocessor& preprocessor, const CStr& input) return ret; } +void CShaderProgram::BindClientStates() +{ + ENSURE(m_StreamFlags == (m_StreamFlags & (STREAM_POS|STREAM_NORMAL|STREAM_COLOR|STREAM_UV0|STREAM_UV1))); + + // Enable all the desired client states for non-GLSL rendering + + if (m_StreamFlags & STREAM_POS) glEnableClientState(GL_VERTEX_ARRAY); + if (m_StreamFlags & STREAM_NORMAL) glEnableClientState(GL_NORMAL_ARRAY); + if (m_StreamFlags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY); + + if (m_StreamFlags & STREAM_UV0) + { + pglClientActiveTextureARB(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (m_StreamFlags & STREAM_UV1) + { + pglClientActiveTextureARB(GL_TEXTURE1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglClientActiveTextureARB(GL_TEXTURE0); + } + + // Rendering code must subsequently call VertexPointer etc for all of the streams + // that were activated in this function, else AssertPointersBound will complain + // that some arrays were unspecified + m_ValidStreams = 0; +} + +void CShaderProgram::UnbindClientStates() +{ + if (m_StreamFlags & STREAM_POS) glDisableClientState(GL_VERTEX_ARRAY); + if (m_StreamFlags & STREAM_NORMAL) glDisableClientState(GL_NORMAL_ARRAY); + if (m_StreamFlags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY); + + if (m_StreamFlags & STREAM_UV0) + { + pglClientActiveTextureARB(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + if (m_StreamFlags & STREAM_UV1) + { + pglClientActiveTextureARB(GL_TEXTURE1); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglClientActiveTextureARB(GL_TEXTURE0); + } +} + +void CShaderProgram::AssertPointersBound() +{ + ENSURE(m_ValidStreams == m_StreamFlags); +} \ No newline at end of file diff --git a/source/graphics/ShaderProgram.h b/source/graphics/ShaderProgram.h index 56e12af62f..7f0312e17c 100644 --- a/source/graphics/ShaderProgram.h +++ b/source/graphics/ShaderProgram.h @@ -75,6 +75,7 @@ public: */ static CShaderProgram* ConstructGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile, const std::map& defines, + const std::map& vertexAttribs, int streamflags); /** @@ -173,6 +174,18 @@ public: void Uniform(uniform_id_t id, float v0, float v1, float v2, float v3); void Uniform(uniform_id_t id, const CMatrix3D& v); + // Vertex attribute pointers (equivalent to glVertexPointer etc): + + virtual void VertexPointer(GLint size, GLenum type, GLsizei stride, void* pointer); + virtual void NormalPointer(GLenum type, GLsizei stride, void* pointer); + virtual void TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, void* pointer); + + /** + * Checks that all the required vertex attributes have been set. + * Call this before calling glDrawArrays/glDrawElements etc to avoid potential crashes. + */ + void AssertPointersBound(); + protected: CShaderProgram(int streamflags); @@ -180,6 +193,11 @@ protected: bool m_IsValid; int m_StreamFlags; + + // Non-GLSL client state handling: + void BindClientStates(); + void UnbindClientStates(); + int m_ValidStreams; // which streams have been specified via VertexPointer etc since the last Bind }; typedef shared_ptr CShaderProgramPtr; diff --git a/source/graphics/ShaderProgramFFP.cpp b/source/graphics/ShaderProgramFFP.cpp index 0726adf486..7db732ebd0 100644 --- a/source/graphics/ShaderProgramFFP.cpp +++ b/source/graphics/ShaderProgramFFP.cpp @@ -247,11 +247,14 @@ public: glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); - + + BindClientStates(); } virtual void Unbind() { + UnbindClientStates(); + pglActiveTextureARB(GL_TEXTURE2); glDisable(GL_TEXTURE_2D); @@ -311,10 +314,14 @@ public: pglActiveTextureARB(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + BindClientStates(); } virtual void Unbind() { + UnbindClientStates(); + pglActiveTextureARB(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); @@ -361,10 +368,14 @@ public: glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); + + BindClientStates(); } virtual void Unbind() { + UnbindClientStates(); + glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); diff --git a/source/gui/GUIRenderer.cpp b/source/gui/GUIRenderer.cpp index 068161a2a7..34b92334ea 100644 --- a/source/gui/GUIRenderer.cpp +++ b/source/gui/GUIRenderer.cpp @@ -340,21 +340,20 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z) std::swap(TexCoords.bottom, TexCoords.top); } - glBegin(GL_QUADS); + std::vector data; +#define ADD(u, v, x, y, z) STMT(data.push_back(u); data.push_back(v); data.push_back(x); data.push_back(y); data.push_back(z)) + ADD(TexCoords.left, TexCoords.bottom, Verts.left, Verts.bottom, Z + cit->m_DeltaZ); + ADD(TexCoords.right, TexCoords.bottom, Verts.right, Verts.bottom, Z + cit->m_DeltaZ); + ADD(TexCoords.right, TexCoords.top, Verts.right, Verts.top, Z + cit->m_DeltaZ); - glTexCoord2f(TexCoords.left, TexCoords.bottom); - glVertex3f(Verts.left, Verts.bottom, Z + cit->m_DeltaZ); + ADD(TexCoords.right, TexCoords.top, Verts.right, Verts.top, Z + cit->m_DeltaZ); + ADD(TexCoords.left, TexCoords.top, Verts.left, Verts.top, Z + cit->m_DeltaZ); + ADD(TexCoords.left, TexCoords.bottom, Verts.left, Verts.bottom, Z + cit->m_DeltaZ); +#undef ADD - glTexCoord2f(TexCoords.right, TexCoords.bottom); - glVertex3f(Verts.right, Verts.bottom, Z + cit->m_DeltaZ); - - glTexCoord2f(TexCoords.right, TexCoords.top); - glVertex3f(Verts.right, Verts.top, Z + cit->m_DeltaZ); - - glTexCoord2f(TexCoords.left, TexCoords.top); - glVertex3f(Verts.left, Verts.top, Z + cit->m_DeltaZ); - - glEnd(); + shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, 5*sizeof(float), &data[0]); + shader->VertexPointer(3, GL_FLOAT, 5*sizeof(float), &data[2]); + glDrawArrays(GL_TRIANGLES, 0, 6); cit->m_Shader->EndPass(0); } @@ -378,23 +377,33 @@ void GUIRenderer::Draw(DrawCalls &Calls, float Z) if (Verts.bottom < Verts.top) std::swap(Verts.bottom, Verts.top); - glBegin(GL_QUADS); - glVertex3f(Verts.left, Verts.bottom, Z + cit->m_DeltaZ); - glVertex3f(Verts.right, Verts.bottom, Z + cit->m_DeltaZ); - glVertex3f(Verts.right, Verts.top, Z + cit->m_DeltaZ); - glVertex3f(Verts.left, Verts.top, Z + cit->m_DeltaZ); - glEnd(); + std::vector data; +#define ADD(x, y, z) STMT(data.push_back(x); data.push_back(y); data.push_back(z)) + ADD(Verts.left, Verts.bottom, Z + cit->m_DeltaZ); + ADD(Verts.right, Verts.bottom, Z + cit->m_DeltaZ); + ADD(Verts.right, Verts.top, Z + cit->m_DeltaZ); + + ADD(Verts.right, Verts.top, Z + cit->m_DeltaZ); + ADD(Verts.left, Verts.top, Z + cit->m_DeltaZ); + ADD(Verts.left, Verts.bottom, Z + cit->m_DeltaZ); + + shader->VertexPointer(3, GL_FLOAT, 3*sizeof(float), &data[0]); + glDrawArrays(GL_TRIANGLES, 0, 6); if (cit->m_BorderColor != CColor()) { shader->Uniform("color", cit->m_BorderColor); - glBegin(GL_LINE_LOOP); - glVertex3f(Verts.left + 0.5f, Verts.top + 0.5f, Z + cit->m_DeltaZ); - glVertex3f(Verts.right - 0.5f, Verts.top + 0.5f, Z + cit->m_DeltaZ); - glVertex3f(Verts.right - 0.5f, Verts.bottom - 0.5f, Z + cit->m_DeltaZ); - glVertex3f(Verts.left + 0.5f, Verts.bottom - 0.5f, Z + cit->m_DeltaZ); - glEnd(); + + data.clear(); + ADD(Verts.left + 0.5f, Verts.top + 0.5f, Z + cit->m_DeltaZ); + ADD(Verts.right - 0.5f, Verts.top + 0.5f, Z + cit->m_DeltaZ); + ADD(Verts.right - 0.5f, Verts.bottom - 0.5f, Z + cit->m_DeltaZ); + ADD(Verts.left + 0.5f, Verts.bottom - 0.5f, Z + cit->m_DeltaZ); + + shader->VertexPointer(3, GL_FLOAT, 3*sizeof(float), &data[0]); + glDrawArrays(GL_LINE_LOOP, 0, 4); } +#undef ADD cit->m_Shader->EndPass(0); } diff --git a/source/gui/MiniMap.cpp b/source/gui/MiniMap.cpp index ec987f3bf4..48ebf56bfd 100644 --- a/source/gui/MiniMap.cpp +++ b/source/gui/MiniMap.cpp @@ -184,6 +184,13 @@ void CMiniMap::FireWorldClickEvent(int button, int clicks) UNUSED2(clicks); } +#if CONFIG2_GLES +#warning TODO: implement minimap for GLES +void CMiniMap::Draw() +{ +} +#else + // render view rect : John M. Mena // This sets up and draws the rectangle on the mini-map // which represents the view of the camera in the world. @@ -436,6 +443,8 @@ void CMiniMap::Draw() glEnable(GL_TEXTURE_2D); } +#endif // CONFIG2_GLES + void CMiniMap::CreateTextures() { Destroy(); @@ -449,14 +458,14 @@ void CMiniMap::CreateTextures() u32* texData = new u32[m_TextureSize * m_TextureSize]; for (ssize_t i = 0; i < m_TextureSize * m_TextureSize; ++i) texData[i] = 0xFF000000; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_TextureSize, m_TextureSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, texData); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, texData); delete[] texData; m_TerrainData = new u32[(m_MapSize - 1) * (m_MapSize - 1)]; - 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); + 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); // Rebuild and upload both of them RebuildTerrainTexture(); diff --git a/source/lib/res/graphics/unifont.cpp b/source/lib/res/graphics/unifont.cpp index 726b48f9f1..847d21becd 100644 --- a/source/lib/res/graphics/unifont.cpp +++ b/source/lib/res/graphics/unifont.cpp @@ -291,7 +291,11 @@ void glvwprintf(const wchar_t* fmt, va_list args) unifont_render(buf, &advance); // Move into position for subsequent prints +#if CONFIG2_GLES +#warning TODO: implement unifont for GLES +#else glTranslatef((float)advance, 0, 0); +#endif } void unifont_render(const wchar_t* str, int* advance) diff --git a/source/renderer/FixedFunctionModelRenderer.cpp b/source/renderer/FixedFunctionModelRenderer.cpp index f653cf672f..5354d1519e 100644 --- a/source/renderer/FixedFunctionModelRenderer.cpp +++ b/source/renderer/FixedFunctionModelRenderer.cpp @@ -240,7 +240,7 @@ void FixedFunctionModelRenderer::EndPass(int streamflags) // Prepare UV coordinates for this modeldef -void FixedFunctionModelRenderer::PrepareModelDef(int streamflags, const CModelDefPtr& def) +void FixedFunctionModelRenderer::PrepareModelDef(CShaderProgramPtr& UNUSED(shader), int streamflags, const CModelDefPtr& def) { m->ffmodeldef = (FFModelDef*)def->GetRenderData(m); @@ -257,7 +257,7 @@ void FixedFunctionModelRenderer::PrepareModelDef(int streamflags, const CModelDe // Render one model -void FixedFunctionModelRenderer::RenderModel(int streamflags, CModel* model, void* data) +void FixedFunctionModelRenderer::RenderModel(CShaderProgramPtr& UNUSED(shader), int streamflags, CModel* model, void* data) { CModelDefPtr mdldef = model->GetModelDef(); FFModel* ffmodel = (FFModel*)data; diff --git a/source/renderer/FixedFunctionModelRenderer.h b/source/renderer/FixedFunctionModelRenderer.h index 79acfdd64c..d9952c9aa6 100644 --- a/source/renderer/FixedFunctionModelRenderer.h +++ b/source/renderer/FixedFunctionModelRenderer.h @@ -44,8 +44,8 @@ public: void BeginPass(int streamflags); void EndPass(int streamflags); - void PrepareModelDef(int streamflags, const CModelDefPtr& def); - void RenderModel(int streamflags, CModel* model, void* data); + void PrepareModelDef(CShaderProgramPtr& shader, int streamflags, const CModelDefPtr& def); + void RenderModel(CShaderProgramPtr& shader, int streamflags, CModel* model, void* data); private: FixedFunctionModelRendererInternals* m; diff --git a/source/renderer/HWLightingModelRenderer.cpp b/source/renderer/HWLightingModelRenderer.cpp index bd3d1adb76..dc9aeab5c9 100644 --- a/source/renderer/HWLightingModelRenderer.cpp +++ b/source/renderer/HWLightingModelRenderer.cpp @@ -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 @@ -205,7 +205,7 @@ void ShaderModelRenderer::EndPass(int streamflags) // Prepare UV coordinates for this modeldef -void ShaderModelRenderer::PrepareModelDef(int streamflags, const CModelDefPtr& def) +void ShaderModelRenderer::PrepareModelDef(CShaderProgramPtr& shader, int streamflags, const CModelDefPtr& def) { m->shadermodeldef = (ShaderModelDef*)def->GetRenderData(m); @@ -216,13 +216,13 @@ void ShaderModelRenderer::PrepareModelDef(int streamflags, const CModelDefPtr& d u8* base = m->shadermodeldef->m_Array.Bind(); GLsizei stride = (GLsizei)m->shadermodeldef->m_Array.GetStride(); - glTexCoordPointer(2, GL_FLOAT, stride, base + m->shadermodeldef->m_UV.offset); + shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, stride, base + m->shadermodeldef->m_UV.offset); } } // Render one model -void ShaderModelRenderer::RenderModel(int streamflags, CModel* model, void* data) +void ShaderModelRenderer::RenderModel(CShaderProgramPtr& shader, int streamflags, CModel* model, void* data) { CModelDefPtr mdldef = model->GetModelDef(); ShaderModel* shadermodel = (ShaderModel*)data; @@ -233,10 +233,12 @@ void ShaderModelRenderer::RenderModel(int streamflags, CModel* model, void* data u8* indexBase = m->shadermodeldef->m_IndexArray.Bind(); if (streamflags & STREAM_POS) - glVertexPointer(3, GL_FLOAT, stride, base + shadermodel->m_Position.offset); + shader->VertexPointer(3, GL_FLOAT, stride, base + shadermodel->m_Position.offset); if (streamflags & STREAM_NORMAL) - glNormalPointer(GL_FLOAT, stride, base + shadermodel->m_Normal.offset); + shader->NormalPointer(GL_FLOAT, stride, base + shadermodel->m_Normal.offset); + + shader->AssertPointersBound(); // render the lot size_t numFaces = mdldef->GetNumFaces(); diff --git a/source/renderer/HWLightingModelRenderer.h b/source/renderer/HWLightingModelRenderer.h index 7ea933ecfe..04f6a7da24 100644 --- a/source/renderer/HWLightingModelRenderer.h +++ b/source/renderer/HWLightingModelRenderer.h @@ -51,8 +51,8 @@ public: void BeginPass(int streamflags); void EndPass(int streamflags); - void PrepareModelDef(int streamflags, const CModelDefPtr& def); - void RenderModel(int streamflags, CModel* model, void* data); + void PrepareModelDef(CShaderProgramPtr& shader, int streamflags, const CModelDefPtr& def); + void RenderModel(CShaderProgramPtr& shader, int streamflags, CModel* model, void* data); protected: ShaderModelRendererInternals* m; diff --git a/source/renderer/InstancingModelRenderer.cpp b/source/renderer/InstancingModelRenderer.cpp index c667ac0e2f..945b7fcffb 100644 --- a/source/renderer/InstancingModelRenderer.cpp +++ b/source/renderer/InstancingModelRenderer.cpp @@ -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 @@ -99,9 +99,6 @@ IModelDef::IModelDef(const CModelDefPtr& mdef) struct InstancingModelRendererInternals { - /// Currently used RenderModifier - RenderModifierPtr modifier; - /// Previously prepared modeldef IModelDef* imodeldef; @@ -157,35 +154,17 @@ void InstancingModelRenderer::DestroyModelData(CModel* UNUSED(model), void* UNUS void InstancingModelRenderer::BeginPass(int streamflags) { ENSURE(streamflags == (streamflags & (STREAM_POS|STREAM_NORMAL|STREAM_UV0))); - - if (streamflags & STREAM_POS) - glEnableClientState(GL_VERTEX_ARRAY); - - if (streamflags & STREAM_NORMAL) - glEnableClientState(GL_NORMAL_ARRAY); - - if (streamflags & STREAM_UV0) - glEnableClientState(GL_TEXTURE_COORD_ARRAY); } // Cleanup rendering pass. -void InstancingModelRenderer::EndPass(int streamflags) +void InstancingModelRenderer::EndPass(int UNUSED(streamflags)) { - if (streamflags & STREAM_POS) - glDisableClientState(GL_VERTEX_ARRAY); - - if (streamflags & STREAM_NORMAL) - glDisableClientState(GL_NORMAL_ARRAY); - - if (streamflags & STREAM_UV0) - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - CVertexBuffer::Unbind(); } // Prepare UV coordinates for this modeldef -void InstancingModelRenderer::PrepareModelDef(int streamflags, const CModelDefPtr& def) +void InstancingModelRenderer::PrepareModelDef(CShaderProgramPtr& shader, int streamflags, const CModelDefPtr& def) { m->imodeldef = (IModelDef*)def->GetRenderData(m); @@ -197,18 +176,20 @@ void InstancingModelRenderer::PrepareModelDef(int streamflags, const CModelDefPt m->imodeldefIndexBase = m->imodeldef->m_IndexArray.Bind(); if (streamflags & STREAM_POS) - glVertexPointer(3, GL_FLOAT, stride, base + m->imodeldef->m_Position.offset); + shader->VertexPointer(3, GL_FLOAT, stride, base + m->imodeldef->m_Position.offset); if (streamflags & STREAM_NORMAL) - glNormalPointer(GL_FLOAT, stride, base + m->imodeldef->m_Normal.offset); + shader->NormalPointer(GL_FLOAT, stride, base + m->imodeldef->m_Normal.offset); if (streamflags & STREAM_UV0) - glTexCoordPointer(2, GL_FLOAT, stride, base + m->imodeldef->m_UV.offset); + shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, stride, base + m->imodeldef->m_UV.offset); + + shader->AssertPointersBound(); } // Render one model -void InstancingModelRenderer::RenderModel(int UNUSED(streamflags), CModel* model, void* UNUSED(data)) +void InstancingModelRenderer::RenderModel(CShaderProgramPtr& UNUSED(shader), int UNUSED(streamflags), CModel* model, void* UNUSED(data)) { CModelDefPtr mdldef = model->GetModelDef(); diff --git a/source/renderer/InstancingModelRenderer.h b/source/renderer/InstancingModelRenderer.h index cbbaf78589..35c654b1a2 100644 --- a/source/renderer/InstancingModelRenderer.h +++ b/source/renderer/InstancingModelRenderer.h @@ -45,8 +45,8 @@ public: void BeginPass(int streamflags); void EndPass(int streamflags); - void PrepareModelDef(int streamflags, const CModelDefPtr& def); - void RenderModel(int streamflags, CModel* model, void* data); + void PrepareModelDef(CShaderProgramPtr& shader, int streamflags, const CModelDefPtr& def); + void RenderModel(CShaderProgramPtr& shader, int streamflags, CModel* model, void* data); protected: InstancingModelRendererInternals* m; diff --git a/source/renderer/ModelRenderer.cpp b/source/renderer/ModelRenderer.cpp index ac0acf8543..b2fb28d0ec 100644 --- a/source/renderer/ModelRenderer.cpp +++ b/source/renderer/ModelRenderer.cpp @@ -442,9 +442,11 @@ void BatchModelRendererInternals::RenderAllModels( const RenderModifierPtr& modifier, int filterflags, int pass, int streamflags) { + CShaderProgramPtr shader = modifier->GetShader(pass); + for(BMRModelDefTracker* mdeftracker = submissions; mdeftracker; mdeftracker = mdeftracker->m_Next) { - vertexRenderer->PrepareModelDef(streamflags, mdeftracker->m_ModelDef.lock()); + vertexRenderer->PrepareModelDef(shader, streamflags, mdeftracker->m_ModelDef.lock()); for(size_t idx = 0; idx < mdeftracker->m_Slots; ++idx) { @@ -462,7 +464,7 @@ void BatchModelRendererInternals::RenderAllModels( continue; modifier->PrepareModel(pass, model); - vertexRenderer->RenderModel(streamflags, model, bmrdata->m_Data); + vertexRenderer->RenderModel(shader, streamflags, model, bmrdata->m_Data); } } } diff --git a/source/renderer/ModelVertexRenderer.h b/source/renderer/ModelVertexRenderer.h index 428e4ca8b5..2cbb011448 100644 --- a/source/renderer/ModelVertexRenderer.h +++ b/source/renderer/ModelVertexRenderer.h @@ -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 @@ -24,6 +24,7 @@ #define INCLUDED_MODELVERTEXRENDERER #include "graphics/MeshManager.h" +#include "graphics/ShaderProgram.h" class CModel; @@ -147,7 +148,7 @@ public: * BeginPass. * @param def The model definition. */ - virtual void PrepareModelDef(int streamflags, const CModelDefPtr& def) = 0; + virtual void PrepareModelDef(CShaderProgramPtr& shader, int streamflags, const CModelDefPtr& def) = 0; /** @@ -169,7 +170,7 @@ public: * that use the same CModelDef object and the same texture must * succeed. */ - virtual void RenderModel(int streamflags, CModel* model, void* data) = 0; + virtual void RenderModel(CShaderProgramPtr& shader, int streamflags, CModel* model, void* data) = 0; }; diff --git a/source/renderer/OverlayRenderer.cpp b/source/renderer/OverlayRenderer.cpp index 53d6b59ce2..2fd44d0dc5 100644 --- a/source/renderer/OverlayRenderer.cpp +++ b/source/renderer/OverlayRenderer.cpp @@ -256,21 +256,6 @@ void OverlayRenderer::RenderTexturedOverlayLines(CShaderProgramPtr shaderTexLine { int streamflags = shaderTexLine->GetStreamFlags(); - if (streamflags & STREAM_POS) - glEnableClientState(GL_VERTEX_ARRAY); - - if (streamflags & STREAM_UV0) - { - pglClientActiveTextureARB(GL_TEXTURE0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } - - if (streamflags & STREAM_UV1) - { - pglClientActiveTextureARB(GL_TEXTURE1); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } - for (size_t i = 0; i < m->texlines.size(); ++i) { SOverlayTexturedLine* line = m->texlines[i]; @@ -293,26 +278,21 @@ void OverlayRenderer::RenderTexturedOverlayLines(CShaderProgramPtr shaderTexLine CTexturedLineRData::SVertex* vertexBase = reinterpret_cast(rdata->m_VB->m_Owner->Bind()); if (streamflags & STREAM_POS) - glVertexPointer(3, GL_FLOAT, stride, &vertexBase->m_Position[0]); + shaderTexLine->VertexPointer(3, GL_FLOAT, stride, &vertexBase->m_Position[0]); if (streamflags & STREAM_UV0) - { - pglClientActiveTextureARB(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, stride, &vertexBase->m_UVs[0]); - } + shaderTexLine->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, stride, &vertexBase->m_UVs[0]); if (streamflags & STREAM_UV1) - { - pglClientActiveTextureARB(GL_TEXTURE1); - glTexCoordPointer(2, GL_FLOAT, stride, &vertexBase->m_UVs[0]); - } + shaderTexLine->TexCoordPointer(GL_TEXTURE1, 2, GL_FLOAT, stride, &vertexBase->m_UVs[0]); u8* indexBase = rdata->m_VBIndices->m_Owner->Bind(); + + shaderTexLine->AssertPointersBound(); glDrawElements(GL_TRIANGLES, rdata->m_VBIndices->m_Count, GL_UNSIGNED_SHORT, indexBase + sizeof(u16)*rdata->m_VBIndices->m_Index); + g_Renderer.GetStats().m_OverlayTris += rdata->m_VBIndices->m_Count/3; - } - } void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera) diff --git a/source/renderer/RenderModifiers.cpp b/source/renderer/RenderModifiers.cpp index d3d6e3d412..d0b34746b9 100644 --- a/source/renderer/RenderModifiers.cpp +++ b/source/renderer/RenderModifiers.cpp @@ -47,6 +47,10 @@ void RenderModifier::PrepareModel(int UNUSED(pass), CModel* UNUSED(model)) { } +CShaderProgramPtr RenderModifier::GetShader(int UNUSED(pass)) +{ + return CShaderProgramPtr(); +} /////////////////////////////////////////////////////////////////////////////////////////////// // LitRenderModifier implementation @@ -272,6 +276,11 @@ bool ShaderRenderModifier::EndPass(int pass) return (pass >= m_Technique->GetNumPasses()-1); } +CShaderProgramPtr ShaderRenderModifier::GetShader(int pass) +{ + return m_Technique->GetShader(pass); +} + void ShaderRenderModifier::PrepareTexture(int pass, CTexturePtr& texture) { CShaderProgramPtr shader = m_Technique->GetShader(pass); diff --git a/source/renderer/RenderModifiers.h b/source/renderer/RenderModifiers.h index eb911e50e6..9a184793f7 100644 --- a/source/renderer/RenderModifiers.h +++ b/source/renderer/RenderModifiers.h @@ -72,6 +72,11 @@ public: */ virtual bool EndPass(int pass) = 0; + /** + * Return the shader for the given pass, or a null pointer if none. + */ + virtual CShaderProgramPtr GetShader(int pass); + /** * PrepareTexture: Called before rendering models that use the given * texture. @@ -200,6 +205,7 @@ public: // Implementation int BeginPass(int pass); bool EndPass(int pass); + CShaderProgramPtr GetShader(int pass); void PrepareTexture(int pass, CTexturePtr& texture); void PrepareModel(int pass, CModel* model); diff --git a/source/renderer/TransparencyRenderer.cpp b/source/renderer/TransparencyRenderer.cpp index 7c5c119336..1cdd37c139 100644 --- a/source/renderer/TransparencyRenderer.cpp +++ b/source/renderer/TransparencyRenderer.cpp @@ -330,7 +330,7 @@ void PolygonSortModelRenderer::EndPass(int streamflags) // Prepare for rendering models using this CModelDef -void PolygonSortModelRenderer::PrepareModelDef(int streamflags, const CModelDefPtr& def) +void PolygonSortModelRenderer::PrepareModelDef(CShaderProgramPtr& UNUSED(shader), int streamflags, const CModelDefPtr& def) { if (streamflags & STREAM_UV0) { @@ -347,7 +347,7 @@ void PolygonSortModelRenderer::PrepareModelDef(int streamflags, const CModelDefP // Render one model -void PolygonSortModelRenderer::RenderModel(int streamflags, CModel* model, void* data) +void PolygonSortModelRenderer::RenderModel(CShaderProgramPtr& UNUSED(shader), int streamflags, CModel* model, void* data) { CModelDefPtr mdef = model->GetModelDef(); PSModel* psmdl = (PSModel*)data; @@ -529,6 +529,8 @@ void SortModelRenderer::Render(const RenderModifierPtr& modifier, int flags) CModelDefPtr lastmdef; CTexturePtr lasttex; + CShaderProgramPtr shader = modifier->GetShader(pass); + m->vertexRenderer->BeginPass(streamflags); for(std::vector::iterator it = m->models.begin(); it != m->models.end(); ++it) @@ -547,7 +549,7 @@ void SortModelRenderer::Render(const RenderModifierPtr& modifier, int flags) // Prepare per-CModelDef data if changed if (mdef != lastmdef) { - m->vertexRenderer->PrepareModelDef(streamflags, mdef); + m->vertexRenderer->PrepareModelDef(shader, streamflags, mdef); lastmdef = mdef; } @@ -561,7 +563,7 @@ void SortModelRenderer::Render(const RenderModifierPtr& modifier, int flags) modifier->PrepareModel(pass, mdl); // Render the model - m->vertexRenderer->RenderModel(streamflags, mdl, smdl->m_Data); + m->vertexRenderer->RenderModel(shader, streamflags, mdl, smdl->m_Data); } m->vertexRenderer->EndPass(streamflags); diff --git a/source/renderer/TransparencyRenderer.h b/source/renderer/TransparencyRenderer.h index ca308698f1..73d2fe2dd2 100644 --- a/source/renderer/TransparencyRenderer.h +++ b/source/renderer/TransparencyRenderer.h @@ -51,8 +51,8 @@ public: void BeginPass(int streamflags); void EndPass(int streamflags); - void PrepareModelDef(int streamflags, const CModelDefPtr& def); - void RenderModel(int streamflags, CModel* model, void* data); + void PrepareModelDef(CShaderProgramPtr& shader, int streamflags, const CModelDefPtr& def); + void RenderModel(CShaderProgramPtr& shader, int streamflags, CModel* model, void* data); private: PolygonSortModelRendererInternals* m;