From 40b42e60104fb8970ee7c3f65d0f419d822a3487 Mon Sep 17 00:00:00 2001 From: nadro Date: Tue, 15 Jan 2013 00:31:37 +0000 Subject: [PATCH] - First version of rewritten OpenGL ES 2.0 driver (IDE projects aren't updated, 2d drawing methods doesn't work, only basic functionality of fixed pipeline materials). This driver will be improved soon. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@4435 dfc29bdd-3216-0410-991c-e03cc46cb475 --- examples/10.Shaders/main.cpp | 14 +- media/Shaders/COGLES2FixedPipeline.fsh | 173 +--- media/Shaders/COGLES2FixedPipeline.vsh | 242 +---- media/ogles2.frag | 13 + media/ogles2.vert | 34 + source/Irrlicht/COGLES2Driver.cpp | 979 +++++++++--------- source/Irrlicht/COGLES2Driver.h | 109 +- .../Irrlicht/COGLES2FixedPipelineRenderer.cpp | 96 ++ .../Irrlicht/COGLES2FixedPipelineRenderer.h | 49 + .../Irrlicht/COGLES2FixedPipelineShader.cpp | 301 ------ source/Irrlicht/COGLES2FixedPipelineShader.h | 197 ---- source/Irrlicht/COGLES2MaterialRenderer.cpp | 464 +++++++++ source/Irrlicht/COGLES2MaterialRenderer.h | 694 +++---------- source/Irrlicht/COGLES2NormalMapRenderer.cpp | 193 +--- source/Irrlicht/COGLES2NormalMapRenderer.h | 55 +- .../Irrlicht/COGLES2ParallaxMapRenderer.cpp | 220 +--- source/Irrlicht/COGLES2ParallaxMapRenderer.h | 62 +- source/Irrlicht/COGLES2Renderer2D.cpp | 22 +- source/Irrlicht/COGLES2Renderer2D.h | 4 +- source/Irrlicht/COGLES2SLMaterialRenderer.cpp | 646 ------------ source/Irrlicht/COGLES2SLMaterialRenderer.h | 144 --- source/Irrlicht/COGLES2Texture.cpp | 20 +- source/Irrlicht/COGLES2Texture.h | 30 +- 23 files changed, 1603 insertions(+), 3158 deletions(-) create mode 100644 media/ogles2.frag create mode 100644 media/ogles2.vert create mode 100644 source/Irrlicht/COGLES2FixedPipelineRenderer.cpp create mode 100644 source/Irrlicht/COGLES2FixedPipelineRenderer.h delete mode 100644 source/Irrlicht/COGLES2FixedPipelineShader.cpp delete mode 100644 source/Irrlicht/COGLES2FixedPipelineShader.h create mode 100644 source/Irrlicht/COGLES2MaterialRenderer.cpp delete mode 100644 source/Irrlicht/COGLES2SLMaterialRenderer.cpp delete mode 100644 source/Irrlicht/COGLES2SLMaterialRenderer.h diff --git a/examples/10.Shaders/main.cpp b/examples/10.Shaders/main.cpp index e1ec1179..f1d8694e 100644 --- a/examples/10.Shaders/main.cpp +++ b/examples/10.Shaders/main.cpp @@ -180,7 +180,11 @@ int main() case video::EDT_OGLES1: case video::EDT_OGLES2: UseHighLevelShaders=true; - // fallthrough! + { + psFileName = "../../media/ogles2.frag"; + vsFileName = "../../media/ogles2.vert"; + } + break; case video::EDT_OPENGL: if (UseHighLevelShaders) { @@ -208,7 +212,7 @@ int main() least the vertex shader in action, without the pixel shader. */ - if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && + /*if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)) { device->getLogger()->log("WARNING: Pixel shaders disabled "\ @@ -222,7 +226,7 @@ int main() device->getLogger()->log("WARNING: Vertex shaders disabled "\ "because of missing driver/hardware support."); vsFileName = ""; - } + }*/ /* Now lets create the new materials. As you maybe know from previous @@ -391,8 +395,8 @@ int main() if (lastFPS != fps) { - core::stringw str = L"Irrlicht Engine - Vertex and pixel shader example ["; - str += driver->getName(); + core::stringw str = L"["; + //str += driver->getName(); str += "] FPS:"; str += fps; diff --git a/media/Shaders/COGLES2FixedPipeline.fsh b/media/Shaders/COGLES2FixedPipeline.fsh index 6e51bb36..218689ed 100644 --- a/media/Shaders/COGLES2FixedPipeline.fsh +++ b/media/Shaders/COGLES2FixedPipeline.fsh @@ -1,182 +1,23 @@ -// Copyright (C) 2009-2010 Amundis -// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h -#define MAX_TEXTURE_UNITS 4 -#define FOG_EXP 1 -#define FOG_LINEAR 2 - -#define TwoD 24 -#define Solid 0 -#define Solid2Layer 1 -#define LightMap 2 -#define DetailMap 9 -#define SphereMap 10 -#define Reflection2Layer 11 -#define TransparentAlphaChannel 13 -#define TransparentVertexAlpha 15 - precision mediump float; -vec4 red = vec4(1.0, 0.0, 0.0, 1.0); -vec4 green = vec4(0.0, 1.0, 0.0, 1.0); -vec4 blue = vec4(0.0, 0.0, 1.0, 1.0); - - -/* Varyings */ - -varying vec4 varTexCoord[MAX_TEXTURE_UNITS]; +varying vec2 varTexCoord0; +varying vec2 varTexCoord1; varying vec4 varVertexColor; varying float eyeDist; -varying float varClipDist; - -/* Uniforms */ - -uniform int uFRenderMode; - -uniform bool uAlphaTest; -uniform float uAlphaValue; - -/* Fog Uniforms */ - -uniform bool uFog; -uniform int uFogType; -uniform vec4 uFogColor; -uniform float uFogStart; -uniform float uFogEnd; -uniform float uFogDensity; - -/* Texture Uniforms */ uniform sampler2D uTextureUnit0; uniform sampler2D uTextureUnit1; -uniform bool uUseTexture [MAX_TEXTURE_UNITS]; - -vec4 render2D(void) -{ - vec4 color = varVertexColor; - vec4 texel = texture2D(uTextureUnit0, varTexCoord[0].xy); - if(uUseTexture[0]) - { - color *= texel; - } - return color; -} vec4 renderSolid(void) { - vec4 color = varVertexColor; - vec4 texel = texture2D(uTextureUnit0, varTexCoord[0].xy); - if(uUseTexture[0]) - color *= texel; - return color; -} + vec4 color = vec4(1.0);//varVertexColor; + vec4 texel = texture2D(uTextureUnit0, varTexCoord0); + color *= texel; -vec4 renderTransparentVertexAlpha(void) -{ - vec4 color = renderSolid(); - color.a = varVertexColor.a; return color; } -vec4 renderTransparentAlphaChannel(void) -{ - vec4 texel = texture2D(uTextureUnit0, varTexCoord[0].xy); - vec4 color = texel * varVertexColor; - color.a = texel.a; - return color; -} - -vec4 render2LayerSolid(void) -{ - float blendFactor = varVertexColor.a; - vec4 texel0 = texture2D(uTextureUnit0, varTexCoord[0].xy); - vec4 texel1 = texture2D(uTextureUnit1, varTexCoord[1].xy); - vec4 color = texel0 * blendFactor + texel1 * ( 1.0 - blendFactor ); - return color; -} - -vec4 renderLightMap(void) -{ - vec4 texel0 = texture2D(uTextureUnit0, varTexCoord[0].xy); - vec4 texel1 = texture2D(uTextureUnit1, varTexCoord[1].xy); - vec4 color = texel0 * texel1 * 4.0; - color.a = texel0.a * texel0.a; - return color; -} - -vec4 renderDetailMap(void) -{ - vec4 texel0 = texture2D(uTextureUnit0, varTexCoord[0].xy); - vec4 texel1 = texture2D(uTextureUnit1, varTexCoord[1].xy); - vec4 color = texel0; - color += texel1 - 0.5; - return color; -} - -vec4 renderReflection2Layer(void) -{ - vec4 color = varVertexColor; - vec4 texel0 = texture2D(uTextureUnit0, varTexCoord[0].xy); - vec4 texel1 = texture2D(uTextureUnit1, varTexCoord[1].xy); - color *= texel0 * texel1; - return color; -} - -float ComputeFog() -{ - float factor = 1.0; - if(uFogType == FOG_LINEAR) - { - factor = (uFogEnd - eyeDist) / (uFogEnd - uFogStart); - } - else if(uFogType == FOG_EXP) - { - factor = exp(-(eyeDist * uFogDensity)); - } - else //uFogType == FOG_EXP2 - { - factor = eyeDist * uFogDensity; - factor = exp(-(factor * factor)) ; - } - factor = clamp(factor, 0.0, 1.0); - return factor; -} - void main (void) { - if(varClipDist < 0.0) - discard; - - if( uFRenderMode == TwoD) - gl_FragColor = render2D(); - else if( uFRenderMode == Solid) - gl_FragColor = renderSolid(); - else if(uFRenderMode == LightMap) - gl_FragColor = renderLightMap(); - else if(uFRenderMode == DetailMap) - gl_FragColor = renderDetailMap(); - else if(uFRenderMode == SphereMap) - gl_FragColor = renderSolid(); - else if(uFRenderMode == Reflection2Layer) - gl_FragColor = renderReflection2Layer(); - else if(uFRenderMode == TransparentVertexAlpha) - gl_FragColor = renderTransparentVertexAlpha(); - else if(uFRenderMode == TransparentAlphaChannel) - gl_FragColor = renderTransparentAlphaChannel(); - else - gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0); - - //gl_FragColor = varVertexColor; - - if(uFog) - { - float fogFactor = ComputeFog(); - gl_FragColor = gl_FragColor * fogFactor + uFogColor * (1.0 - fogFactor); - } - - if(uAlphaTest && uAlphaValue > gl_FragColor.a) - discard; - -} + gl_FragColor = renderSolid(); +} \ No newline at end of file diff --git a/media/Shaders/COGLES2FixedPipeline.vsh b/media/Shaders/COGLES2FixedPipeline.vsh index 4ad0219b..0c516ce7 100644 --- a/media/Shaders/COGLES2FixedPipeline.vsh +++ b/media/Shaders/COGLES2FixedPipeline.vsh @@ -1,247 +1,21 @@ -// Copyright (C) 2009-2010 Amundis -// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h -#define MAX_TEXTURE_UNITS 4 -#define MAX_LIGHTS 8 - -#define SphereMap 10 -#define Reflection2Layer 11 - -const vec4 red = vec4(1.0, 0.0, 0.0, 1.0); -const vec4 green = vec4(0.0, 1.0, 0.0, 1.0); -const vec4 blue = vec4(0.0, 0.0, 1.0, 1.0); -const vec4 white = vec4(1.0); -const vec4 black = vec4(0.0); - -/* Vertex Attributes */ - -attribute vec4 inVertexPosition; -attribute vec4 inVertexColor; -attribute vec4 inTexCoord0; -attribute vec4 inTexCoord1; +attribute vec3 inVertexPosition; attribute vec3 inVertexNormal; -attribute vec3 inVertexTangent; -attribute vec3 inVertexBinormal; - -uniform int uVRenderMode; - -/* Matrix Uniforms */ +attribute vec4 inVertexColor; +attribute vec2 inTexCoord0; uniform mat4 uMvpMatrix; -uniform mat4 uWorldMatrix; - -uniform bool uNormalize; -uniform vec3 uEyePos; - -/* Light Uniforms */ - -uniform bool uUseLight [MAX_LIGHTS]; -uniform vec4 uLightPosition [MAX_LIGHTS]; -uniform vec4 uLightAmbient [MAX_LIGHTS]; -uniform vec4 uLightDiffuse [MAX_LIGHTS]; -#ifdef USE_SPECULAR -uniform vec4 uLightSpecular [MAX_LIGHTS]; -#endif -#ifdef USE_LIGHT_CUTOFF -uniform vec3 uLightDirection [MAX_LIGHTS]; -uniform float uLightCutoff [MAX_LIGHTS]; -uniform float uLightExponent [MAX_LIGHTS]; -#endif -uniform vec3 uLightAttenuation [MAX_LIGHTS]; -uniform vec4 uAmbientColor; -uniform bool uLighting; - -/* Material Uniforms */ -uniform vec4 uMaterialAmbient; -uniform vec4 uMaterialEmission; -uniform vec4 uMaterialDiffuse; -uniform vec4 uMaterialSpecular; -uniform float uMaterialShininess; -uniform int uColorMaterial; - -#define ECM_NONE 0 -#define ECM_DIFFUSE 1 -#define ECM_AMBIENT 2 -#define ECM_EMISSIVE 3 -#define ECM_SPECULAR 4 -#define ECM_DIFFUSE_AND_AMBIENT 5 - -/* Texture Uniforms */ -uniform bool uUseTexture [MAX_TEXTURE_UNITS]; -uniform mat4 uTextureMatrix [MAX_TEXTURE_UNITS]; -uniform bool uUseTexMatrix [MAX_TEXTURE_UNITS]; - -/* Clip Plane Uniforms */ -uniform bool uClip; -uniform vec4 uClipPlane; -varying float varClipDist; /* Varyings */ -varying vec4 varTexCoord[MAX_TEXTURE_UNITS]; +varying vec2 varTexCoord0; +varying vec2 varTexCoord1; varying vec4 varVertexColor; varying float eyeDist; -/* shader variables */ - -vec3 gNormal; -vec3 gWorldPos; -vec4 gColor; - -struct material { - vec4 Ambient; - vec4 Diffuse; - vec4 Specular; - vec4 Emission; - float Shininess; -} ; - -material gMaterial; - -vec4 lightEquation(int lidx) -{ - vec4 color = vec4(0.0); - - float att = 1.0; - vec3 lightDir; - - - if( uLightPosition[lidx].w == 0.0) // Directional light - { - lightDir = -uLightPosition[lidx].xyz; - } - else - { - lightDir = uLightPosition[lidx].xyz - inVertexPosition.xyz; - att = 1.0 / (uLightAttenuation[lidx].y * length(lightDir)); - lightDir = normalize(lightDir); - -#ifdef USE_LIGHT_CUTOFF - if(uLightCutoff[lidx] < 180.0) - { - // compute spot factor - float spotEffect = dot(-lightDir, uLightDirection[lidx]); - if( spotEffect >= cos( radians( uLightCutoff[lidx]))) - spotEffect = pow( spotEffect, uLightExponent[lidx]); - else - spotEffect = 0.0; - att *= spotEffect; - } -#endif - } - - if(att >= 0.0 ) - { - color += uLightAmbient[lidx] * gMaterial.Ambient; - - //Compute cos(Light, Normal) - float NdotL = max(dot(normalize(gNormal), lightDir), 0.0); - color += NdotL * uLightDiffuse[lidx] * gMaterial.Diffuse; - - //Compute cos(hvec, Normal) -#ifdef USE_SPECULAR - vec3 hvec = normalize(lightDir + vec3(0.0, 0.0, 1.0)); - float NdotH = dot(gNormal, hvec); - if(NdotH > 0.0) - { - color += pow(NdotH, uMaterialShininess) * uLightSpecular[lidx] * gMaterial.Specular; - } -#endif - color *= att; - } - return color; -} - -vec4 computeLighting(void) -{ - vec4 color = gMaterial.Emission + gMaterial.Ambient * uAmbientColor; - - for ( int i = 0 ; i < MAX_LIGHTS; ++i) - { - if ( uUseLight[i] ) - { - color += lightEquation(i) ; - } - } - color.a = gMaterial.Diffuse.a; - return color; -} - -void ReplaceColorMaterial(void) -{ - gMaterial.Ambient = uMaterialAmbient; - gMaterial.Diffuse = uMaterialDiffuse; - gMaterial.Emission = uMaterialEmission; - gMaterial.Specular = uMaterialSpecular; - gMaterial.Shininess = uMaterialShininess; - - if(uColorMaterial == ECM_DIFFUSE) - gMaterial.Diffuse = gColor; - else if(uColorMaterial == ECM_AMBIENT) - gMaterial.Ambient = gColor; - else if(uColorMaterial == ECM_DIFFUSE_AND_AMBIENT) - { - gMaterial.Diffuse = gColor; - gMaterial.Ambient = gColor; - } - else if(uColorMaterial == ECM_EMISSIVE) - gMaterial.Emission = gColor; - else if(uColorMaterial == ECM_SPECULAR) - gMaterial.Specular = gColor; -} - void main(void) { - gl_Position = uMvpMatrix * inVertexPosition; + gl_Position = uMvpMatrix * vec4(inVertexPosition,1.0); - gWorldPos = (uWorldMatrix * inVertexPosition).xyz; - - gColor = inVertexColor.bgra; - - gNormal = inVertexNormal.xyz; - if(uNormalize) - gNormal = normalize(gNormal); - - ReplaceColorMaterial(); - if(uLighting) - varVertexColor = computeLighting(); - else - varVertexColor = gColor; - - for(int i = 0; i < MAX_TEXTURE_UNITS; ++i) - varTexCoord[i] = vec4(0.0); - - if( uUseTexture[0]) - { - if(uVRenderMode == SphereMap || uVRenderMode == Reflection2Layer) - { - vec3 eyeDir = normalize(inVertexPosition.xyz - uEyePos); - vec3 reflection = reflect(eyeDir, gNormal); - float m = 2.0 * sqrt(reflection.x * reflection.x + - reflection.y * reflection.y + - (reflection.z + 1.0) * (reflection.z + 1.0)); - varTexCoord[0] = vec4((reflection.x / m + 0.5), (reflection.y / m + 0.5), 0.0, 0.0); - } - else - { - varTexCoord[0] = inTexCoord0; - if(uUseTexMatrix[0]) - varTexCoord[0] *= uTextureMatrix[0]; - } - } - if(uUseTexture[1]) - { - varTexCoord[1] = inTexCoord1; - if(uUseTexMatrix[1]) - varTexCoord[1] *= uTextureMatrix[1]; - } - - eyeDist = length(uEyePos); - - varClipDist = uClip ? dot(gWorldPos, uClipPlane.xyz)-uClipPlane.w : 0.0; - - varVertexColor.rgb = clamp(varVertexColor.rgb, 0.0, 1.0); - varVertexColor.a = gColor.a; + varTexCoord0 = inTexCoord0; + varTexCoord1 = inTexCoord0; } diff --git a/media/ogles2.frag b/media/ogles2.frag new file mode 100644 index 00000000..e0a03cda --- /dev/null +++ b/media/ogles2.frag @@ -0,0 +1,13 @@ +precision mediump float; + +varying vec2 v_texCoord; +varying vec4 v_color; + +uniform sampler2D myTexture; + +void main (void) +{ + vec4 col = texture2D(myTexture, v_texCoord); + col *= v_color; + gl_FragColor = col * 4.0; +} diff --git a/media/ogles2.vert b/media/ogles2.vert new file mode 100644 index 00000000..6007c83c --- /dev/null +++ b/media/ogles2.vert @@ -0,0 +1,34 @@ +attribute vec3 inVertexPosition; +attribute vec3 inVertexNormal; +attribute vec4 inVertexColor; +attribute vec2 inTexCoord0; + +uniform mat4 mWorldViewProj; +uniform mat4 mInvWorld; +uniform mat4 mTransWorld; +uniform vec3 mLightPos; +uniform vec4 mLightColor; + +varying mediump vec4 v_color; +varying mediump vec2 v_texCoord; + +void main(void) +{ + gl_Position = mWorldViewProj * vec4(inVertexPosition,1.0); + + vec4 normal = vec4(inVertexNormal, 0.0); + normal = mInvWorld * normal; + normal = normalize(normal); + + vec4 worldpos = vec4(inVertexPosition,1.0) * mTransWorld; + + vec4 lightVector = worldpos - vec4(mLightPos,1.0); + lightVector = normalize(lightVector); + + float tmp2 = dot(-lightVector, normal); + + vec4 tmp = mLightColor * tmp2; + v_color = vec4(tmp.x, tmp.y, tmp.z, 0.0); + + v_texCoord = inTexCoord0; +} diff --git a/source/Irrlicht/COGLES2Driver.cpp b/source/Irrlicht/COGLES2Driver.cpp index cee5d7e2..177fe87d 100644 --- a/source/Irrlicht/COGLES2Driver.cpp +++ b/source/Irrlicht/COGLES2Driver.cpp @@ -1,6 +1,7 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h @@ -12,6 +13,7 @@ #include "COGLES2Texture.h" #include "COGLES2MaterialRenderer.h" +#include "COGLES2FixedPipelineRenderer.h" #include "COGLES2NormalMapRenderer.h" #include "COGLES2ParallaxMapRenderer.h" #include "COGLES2Renderer2D.h" @@ -40,7 +42,7 @@ namespace video ) : CNullDriver(io, params.WindowSize), COGLES2ExtensionHandler(), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), - Transformation3DChanged(true), AntiAlias(params.AntiAlias), + Transformation3DChanged(true), AntiAlias(params.AntiAlias), BridgeCalls(0), RenderTargetTexture(0), CurrentRendertargetSize(0, 0), ColorFormat(ECF_R8G8B8) #ifdef EGL_VERSION_1_0 , EglDisplay(EGL_NO_DISPLAY) @@ -52,9 +54,6 @@ namespace video , ViewRenderbuffer(0) , ViewDepthRenderbuffer(0) #endif - , BlendEnabled(false) - , SourceFactor(EBF_ZERO) - , DestFactor(EBF_ZERO) { #ifdef _DEBUG setDebugName("COGLES2Driver"); @@ -281,6 +280,9 @@ namespace video { deleteMaterialRenders(); deleteAllTextures(); + + if (BridgeCalls) + delete BridgeCalls; #if defined(EGL_VERSION_1_0) // HACK : the following is commented because destroying the context crashes under Linux (Thibault 04-feb-10) @@ -311,8 +313,7 @@ namespace video } #endif - delete TwoDRenderer; - delete FixedPipeline; +// delete TwoDRenderer; } // ----------------------------------------------------------------------- @@ -342,6 +343,9 @@ namespace video #endif stencilBuffer); + if (!BridgeCalls) + BridgeCalls = new COGLES2CallBridge(this); + StencilBuffer = stencilBuffer; DriverAttributes->setAttribute("MaxTextures", MaxTextureUnits); @@ -357,10 +361,7 @@ namespace video DriverAttributes->setAttribute("Version", Version); DriverAttributes->setAttribute("AntiAlias", AntiAlias); - FixedPipeline = new COGLES2FixedPipelineShader(this, FileSystem); - FixedPipeline->useProgram(); //For setting the default uniforms (Alpha) - - TwoDRenderer = new COGLES2Renderer2d(this, FileSystem); +// TwoDRenderer = new COGLES2Renderer2d(this, FileSystem); glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -394,7 +395,6 @@ namespace video // This fixes problems with intermediate changes to the material during texture load. ResetRenderStates = true; - glUseProgram(0); testGLError(); return true; @@ -403,52 +403,143 @@ namespace video void COGLES2Driver::createMaterialRenderers() { - // create OGLES1 material renderers + // Load shaders from files (in future shaders will be merged with source code). - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_SOLID(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_SOLID_2_LAYER(this)); + // Fixed pipeline. - // add the same renderer for all lightmap types - COGLES2MaterialRenderer_LIGHTMAP* lmr = new COGLES2MaterialRenderer_LIGHTMAP(this); - addMaterialRenderer(lmr); // for EMT_LIGHTMAP: - addMaterialRenderer(lmr); // for EMT_LIGHTMAP_ADD: - addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M2: - addMaterialRenderer(lmr); // for EMT_LIGHTMAP_M4: - addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING: - addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M2: - addMaterialRenderer(lmr); // for EMT_LIGHTMAP_LIGHTING_M4: - lmr->drop(); + core::stringc FPVSPath = IRR_OGLES2_SHADER_PATH; + FPVSPath += "COGLES2FixedPipeline.vsh"; - // add remaining material renderer - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_DETAIL_MAP(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_SPHERE_MAP(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_REFLECTION_2_LAYER(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_TRANSPARENT_ADD_COLOR(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(this)); - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(this)); + core::stringc FPFSPath = IRR_OGLES2_SHADER_PATH; + FPFSPath += "COGLES2FixedPipeline.fsh"; - // add normal map renderers - s32 tmp = 0; - video::IMaterialRenderer* renderer = 0; - renderer = new COGLES2NormalMapRenderer(this, FileSystem, tmp, MaterialRenderers[EMT_SOLID].Renderer); - renderer->drop(); - renderer = new COGLES2NormalMapRenderer(this, FileSystem, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); - renderer->drop(); - renderer = new COGLES2NormalMapRenderer(this, FileSystem, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); - renderer->drop(); + io::IReadFile* FPVSFile = FileSystem->createAndOpenFile(FPVSPath); + io::IReadFile* FPFSFile = FileSystem->createAndOpenFile(FPFSPath); - // add parallax map renderers - renderer = new COGLES2ParallaxMapRenderer(this, FileSystem, tmp, MaterialRenderers[EMT_SOLID].Renderer); - renderer->drop(); - renderer = new COGLES2ParallaxMapRenderer(this, FileSystem, tmp, MaterialRenderers[EMT_TRANSPARENT_ADD_COLOR].Renderer); - renderer->drop(); - renderer = new COGLES2ParallaxMapRenderer(this, FileSystem, tmp, MaterialRenderers[EMT_TRANSPARENT_VERTEX_ALPHA].Renderer); - renderer->drop(); + c8* FPVSData = 0; + c8* FPFSData = 0; - // add basic 1 texture blending - addAndDropMaterialRenderer(new COGLES2MaterialRenderer_ONETEXTURE_BLEND(this)); + long Size = FPVSFile->getSize(); + + if (Size) + { + FPVSData = new c8[Size+1]; + FPVSFile->read(FPVSData, Size); + FPVSData[Size] = 0; + } + + Size = FPFSFile->getSize(); + + if (Size) + { + // if both handles are the same we must reset the file + if (FPFSFile == FPVSFile) + FPFSFile->seek(0); + + FPFSData = new c8[Size+1]; + FPFSFile->read(FPFSData, Size); + FPFSData[Size] = 0; + } + + // Normal Mapping. + + core::stringc NMVSPath = IRR_OGLES2_SHADER_PATH; + NMVSPath += "COGLES2NormalMap.vsh"; + + core::stringc NMFSPath = IRR_OGLES2_SHADER_PATH; + NMFSPath += "COGLES2NormalMap.fsh"; + + io::IReadFile* NMVSFile = FileSystem->createAndOpenFile(NMVSPath); + io::IReadFile* NMFSFile = FileSystem->createAndOpenFile(NMFSPath); + + c8* NMVSData = 0; + c8* NMFSData = 0; + + Size = NMVSFile->getSize(); + + if (Size) + { + NMVSData = new c8[Size+1]; + NMVSFile->read(NMVSData, Size); + NMVSData[Size] = 0; + } + + Size = NMFSFile->getSize(); + + if (Size) + { + // if both handles are the same we must reset the file + if (NMFSFile == NMVSFile) + NMFSFile->seek(0); + + NMFSData = new c8[Size+1]; + NMFSFile->read(NMFSData, Size); + NMFSData[Size] = 0; + } + + // Parallax Mapping. + + core::stringc PMVSPath = IRR_OGLES2_SHADER_PATH; + PMVSPath += "COGLES2ParallaxMap.vsh"; + + core::stringc PMFSPath = IRR_OGLES2_SHADER_PATH; + PMFSPath += "COGLES2ParallaxMap.fsh"; + + io::IReadFile* PMVSFile = FileSystem->createAndOpenFile(FPVSPath); + io::IReadFile* PMFSFile = FileSystem->createAndOpenFile(FPFSPath); + + c8* PMVSData = 0; + c8* PMFSData = 0; + + Size = PMVSFile->getSize(); + + if (Size) + { + PMVSData = new c8[Size+1]; + PMVSFile->read(PMVSData, Size); + PMVSData[Size] = 0; + } + + Size = PMFSFile->getSize(); + + if (Size) + { + // if both handles are the same we must reset the file + if (PMFSFile == PMVSFile) + PMFSFile->seek(0); + + PMFSData = new c8[Size+1]; + PMFSFile->read(PMFSData, Size); + PMFSData[Size] = 0; + } + + // Create materials. + + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_SOLID, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_SOLID_2_LAYER, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_ADD, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_M2, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_M4, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_LIGHTING, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_LIGHTING_M2, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_LIGHTING_M4, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_SPHERE_MAP, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_REFLECTION_2_LAYER, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_ADD_COLOR, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_ALPHA_CHANNEL, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_ALPHA_CHANNEL_REF, this)); + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_VERTEX_ALPHA, this)); + + addAndDropMaterialRenderer(new COGLES2NormalMapRenderer(NMVSData, NMFSData, EMT_NORMAL_MAP_SOLID, this)); + addAndDropMaterialRenderer(new COGLES2NormalMapRenderer(NMVSData, NMFSData, EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, this)); + addAndDropMaterialRenderer(new COGLES2NormalMapRenderer(NMVSData, NMFSData, EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, this)); + + addAndDropMaterialRenderer(new COGLES2ParallaxMapRenderer(PMVSData, PMFSData, EMT_PARALLAX_MAP_SOLID, this)); + addAndDropMaterialRenderer(new COGLES2ParallaxMapRenderer(PMVSData, PMFSData, EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, this)); + addAndDropMaterialRenderer(new COGLES2ParallaxMapRenderer(PMVSData, PMFSData, EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, this)); + + addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_ONETEXTURE_BLEND, this)); } @@ -1527,31 +1618,23 @@ namespace video bool COGLES2Driver::setActiveTexture(u32 stage, const video::ITexture* texture) { - if (stage >= MaxTextureUnits) + if (stage >= MaxSupportedTextures) return false; - if (CurrentTexture[stage] == texture) + if (CurrentTexture[stage]==texture) return true; - glActiveTexture(GL_TEXTURE0 + stage); - CurrentTexture[stage] = texture; if (!texture) - { return true; - } - else + else if (texture->getDriverType() != EDT_OGLES2) { - if (texture->getDriverType() != EDT_OGLES2) - { - os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); - return false; - } - glBindTexture(GL_TEXTURE_2D, - static_cast(texture)->getOGLES2TextureName()); + CurrentTexture[stage] = 0; + os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); + return false; } - testGLError(); + return true; } @@ -1611,12 +1694,8 @@ namespace video Material = material; OverrideMaterial.apply(Material); - for (s32 i = MaxTextureUnits - 1; i >= 0; --i) - { - setActiveTexture(i, Material.getTexture(i)); - setTransform((E_TRANSFORMATION_STATE)(ETS_TEXTURE_0 + i), - Material.getTextureMatrix(i)); - } + for (u32 i = 0; i < MaxTextureUnits; ++i) + setActiveTexture(i, material.getTexture(i)); } //! prints error if an error happened. @@ -1647,7 +1726,7 @@ namespace video #endif } - + //! prints error if an error happened. bool COGLES2Driver::testEGLError() { #if defined(EGL_VERSION_1_0) && defined(_DEBUG) @@ -1706,17 +1785,13 @@ namespace video } - //! sets the needed renderstates void COGLES2Driver::setRenderStates3DMode() { if (CurrentRenderMode != ERM_3D) { // Reset Texture Stages - if (BlendEnabled) - { - glDisable(GL_BLEND); - BlendEnabled = false; - } + BridgeCalls->setBlend(false); + BridgeCalls->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ResetRenderStates = true; } @@ -1726,7 +1801,7 @@ namespace video // unset old material if (LastMaterial.MaterialType != Material.MaterialType && - static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) + static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); // set new material. @@ -1741,333 +1816,235 @@ namespace video if (static_cast(Material.MaterialType) < MaterialRenderers.size()) MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, video::EVT_STANDARD); - testGLError(); - CurrentRenderMode = ERM_3D; } - - GLint COGLES2Driver::getTextureWrapMode(u8 clamp) const - { - switch (clamp) - { - case ETC_CLAMP: - // mode=GL_CLAMP; not supported in ogl-es - return GL_CLAMP_TO_EDGE; - case ETC_CLAMP_TO_EDGE: - return GL_CLAMP_TO_EDGE; - case ETC_CLAMP_TO_BORDER: - // mode=GL_CLAMP_TO_BORDER; not supported in ogl-es - return GL_CLAMP_TO_EDGE; - case ETC_MIRROR: -#ifdef GL_OES_texture_mirrored_repeat - if (FeatureAvailable[IRR_OES_texture_mirrored_repeat]) - return GL_MIRRORED_REPEAT_OES; - else -#endif - return GL_REPEAT; - default: - return GL_REPEAT; - } - } - - - void COGLES2Driver::setWrapMode(const SMaterial& material) - { - testGLError(); - // texture address mode - // Has to be checked always because it depends on the textures - for (u32 u = 0; u < MaxTextureUnits; ++u) - { - if (MultiTextureExtension) - glActiveTexture(GL_TEXTURE0 + u); - else if (u>0) - break; // stop loop - - // the APPLE npot restricted extension needs some care as it only supports CLAMP_TO_EDGE - if (queryFeature(EVDF_TEXTURE_NPOT) && !FeatureAvailable[IRR_OES_texture_npot] && - CurrentTexture[u] && (CurrentTexture[u]->getSize() != CurrentTexture[u]->getOriginalSize())) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[u].TextureWrapU)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[u].TextureWrapV)); - } - } - } - - //! Can be called by an IMaterialRenderer to make its work easier. - void COGLES2Driver::setBasicRenderStates(const SMaterial& material, - const SMaterial& lastmaterial, bool resetAllRenderStates) + void COGLES2Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderStates) { - testGLError(); - // Texture filter - // Has to be checked always because it depends on the textures - // Filtering has to be set for each texture layer - for (u32 i = 0; i < MaxTextureUnits; ++i) - { - if (!CurrentTexture[i]) - continue; - glActiveTexture(GL_TEXTURE0 + i); - -#ifdef GL_EXT_texture_lod_bias - if (FeatureAvailable[IRR_EXT_texture_lod_bias]) - { - if (material.TextureLayer[i].LODBias) - { - const float tmp = core::clamp(material.TextureLayer[i].LODBias * 0.125f, -MaxTextureLODBias, MaxTextureLODBias); - glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, tmp); - } - else - glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.f); - } -#endif - if (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - if (material.getTexture(i) && CurrentTexture[i]->hasMipMaps()) - { - if (material.TextureLayer[i].TrilinearFilter) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else if (material.TextureLayer[i].BilinearFilter) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - } - } - else if (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - -#ifdef GL_EXT_texture_filter_anisotropic - if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - static_cast(material.TextureLayer[i].AnisotropicFilter > 1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1)); -#endif - } - testGLError(); - - // fillmode - // for ogl-es this is emulated by other polygon primitives during rendering - - // shademode - if (resetAllRenderStates || (lastmaterial.GouraudShading != material.GouraudShading)) - { - //TODO : OpenGL ES 2.0 Port glShadeModel - //if (material.GouraudShading) - // glShadeModel(GL_SMOOTH); - //else - // glShadeModel(GL_FLAT); - } - testGLError(); - - // zbuffer + // ZBuffer if (resetAllRenderStates || lastmaterial.ZBuffer != material.ZBuffer) { switch (material.ZBuffer) { - case ECFN_NEVER: - glDisable(GL_DEPTH_TEST); + case ECFN_NEVER: // it will be ECFN_DISABLED after merge + BridgeCalls->setDepthTest(false); break; case ECFN_LESSEQUAL: - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LEQUAL); + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_LEQUAL); break; case ECFN_EQUAL: - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_EQUAL); + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_EQUAL); break; case ECFN_LESS: - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_LESS); break; case ECFN_NOTEQUAL: - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_NOTEQUAL); + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_NOTEQUAL); break; case ECFN_GREATEREQUAL: - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_GEQUAL); + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_GEQUAL); break; case ECFN_GREATER: - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_GREATER); + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_GREATER); break; case ECFN_ALWAYS: - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_ALWAYS); break; + /*case ECFN_NEVER: + BridgeCalls->setDepthTest(true); + BridgeCalls->setDepthFunc(GL_NEVER); + break;*/ } } - testGLError(); - // zwrite -// if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable) + // ZWrite + // if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable) { if (material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent())) - { - glDepthMask(GL_TRUE); - } + BridgeCalls->setDepthMask(true); else - glDepthMask(GL_FALSE); + BridgeCalls->setDepthMask(false); } - // back face culling + // Back face culling if (resetAllRenderStates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling)) { if ((material.FrontfaceCulling) && (material.BackfaceCulling)) { - glCullFace(GL_FRONT_AND_BACK); - glEnable(GL_CULL_FACE); - } - else if (material.BackfaceCulling) - { - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); - } - else if (material.FrontfaceCulling) - { - glCullFace(GL_FRONT); - glEnable(GL_CULL_FACE); + BridgeCalls->setCullFaceFunc(GL_FRONT_AND_BACK); + BridgeCalls->setCullFace(true); } else - glDisable(GL_CULL_FACE); + if (material.BackfaceCulling) + { + BridgeCalls->setCullFaceFunc(GL_BACK); + BridgeCalls->setCullFace(true); + } + else + if (material.FrontfaceCulling) + { + BridgeCalls->setCullFaceFunc(GL_FRONT); + BridgeCalls->setCullFace(true); + } + else + BridgeCalls->setCullFace(false); } - testGLError(); // Color Mask if (resetAllRenderStates || lastmaterial.ColorMask != material.ColorMask) { glColorMask( - (material.ColorMask & ECP_RED) ? GL_TRUE : GL_FALSE, - (material.ColorMask & ECP_GREEN) ? GL_TRUE : GL_FALSE, - (material.ColorMask & ECP_BLUE) ? GL_TRUE : GL_FALSE, - (material.ColorMask & ECP_ALPHA) ? GL_TRUE : GL_FALSE); + (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, + (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, + (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, + (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); } - testGLError(); + // Blend operation if (resetAllRenderStates|| lastmaterial.BlendOperation != material.BlendOperation) { - if (EBO_NONE) - glDisable(GL_BLEND); + if (material.BlendOperation==EBO_NONE) + BridgeCalls->setBlend(false); else { - glEnable(GL_BLEND); + BridgeCalls->setBlend(true); + switch (material.BlendOperation) { + case EBO_ADD: + glBlendEquation(GL_FUNC_ADD); + break; case EBO_SUBTRACT: glBlendEquation(GL_FUNC_SUBTRACT); break; case EBO_REVSUBTRACT: glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); break; - case EBO_MIN: - #if defined(GL_EXT_blend_minmax) - if (FeatureAvailable[IRR_EXT_blend_minmax]) - glBlendEquation(GL_MIN_EXT); - #endif - break; - case EBO_MAX: - #if defined(GL_EXT_blend_minmax) - if (FeatureAvailable[IRR_EXT_blend_minmax]) - glBlendEquation(GL_MAX_EXT); - #endif - break; - case EBO_MIN_FACTOR: - // fallback in case of missing extension - #if defined(GL_EXT_blend_minmax) - if (FeatureAvailable[IRR_EXT_blend_minmax]) - glBlendEquation(GL_MIN_EXT); - #endif - break; - case EBO_MAX_FACTOR: - // fallback in case of missing extension - #if defined(GL_EXT_blend_minmax) - if (FeatureAvailable[IRR_EXT_blend_minmax]) - glBlendEquation(GL_MAX_EXT); - #endif - break; - case EBO_MIN_ALPHA: - #if defined(GL_EXT_blend_minmax) - if (FeatureAvailable[IRR_EXT_blend_minmax]) - glBlendEquation(GL_MIN_EXT); - #endif - break; - case EBO_MAX_ALPHA: - #if defined(GL_EXT_blend_minmax) - if (FeatureAvailable[IRR_EXT_blend_minmax]) - glBlendEquation(GL_MAX_EXT); - #endif - break; default: - glBlendEquation(GL_FUNC_ADD); break; } } } - // Polygon Offset - if (queryFeature(EVDF_POLYGON_OFFSET) && (resetAllRenderStates || - lastmaterial.PolygonOffsetDirection != material.PolygonOffsetDirection || - lastmaterial.PolygonOffsetFactor != material.PolygonOffsetFactor)) - { - if (material.PolygonOffsetFactor) - glEnable(GL_POLYGON_OFFSET_FILL); - else - glDisable(GL_POLYGON_OFFSET_FILL); - if (material.PolygonOffsetDirection==EPO_BACK) - glPolygonOffset(1.0f, (GLfloat)material.PolygonOffsetFactor); - else - glPolygonOffset(-1.0f, (GLfloat)-material.PolygonOffsetFactor); - } - - // thickness - if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness) - { - //TODO : OpenGL ES 2.0 Port glPointSize - //glPointSize(material.Thickness); - glLineWidth(material.Thickness == 0 ? 1 : material.Thickness); - //glLineWidth with 0 generate GL_INVALID_VALUE on real hardware. - } - testGLError(); - // Anti aliasing if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing) { - { - if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) - glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); - else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) - glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - // other settings cannot be changed in ogl-es - } + if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE) + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); } - testGLError(); - setWrapMode(material); + // Texture parameters + setTextureRenderStates(material, resetAllRenderStates); + } + + //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call. + void COGLES2Driver::setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates) + { + // Set textures to TU/TIU and apply filters to them - glActiveTexture(GL_TEXTURE0); - testGLError(); + for (s32 i = MaxTextureUnits-1; i>= 0; --i) + { + const COGLES2Texture* tmpTexture = static_cast(CurrentTexture[i]); + + if (CurrentTexture[i]) + BridgeCalls->setTexture(i); + else + continue; + + if(resetAllRenderstates) + tmpTexture->getStatesCache().IsCached = false; + + if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter || + material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); + + tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter; + tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter; + } + + if (material.UseMipMaps && CurrentTexture[i]->hasMipMaps()) + { + if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter || + material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || !tmpTexture->getStatesCache().MipMapStatus) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR : + material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST : + GL_NEAREST_MIPMAP_NEAREST); + + tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter; + tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter; + tmpTexture->getStatesCache().MipMapStatus = true; + } + } + else + { + if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter || + material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || tmpTexture->getStatesCache().MipMapStatus) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST); + + tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter; + tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter; + tmpTexture->getStatesCache().MipMapStatus = false; + } + } + + #ifdef GL_EXT_texture_filter_anisotropic + if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic] && + (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].AnisotropicFilter != tmpTexture->getStatesCache().AnisotropicFilter)) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1); + + tmpTexture->getStatesCache().AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter; + } + #endif + + if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapU != tmpTexture->getStatesCache().WrapU) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[i].TextureWrapU)); + tmpTexture->getStatesCache().WrapU = material.TextureLayer[i].TextureWrapU; + } + + if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapV != tmpTexture->getStatesCache().WrapV) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[i].TextureWrapV)); + tmpTexture->getStatesCache().WrapV = material.TextureLayer[i].TextureWrapV; + } + + tmpTexture->getStatesCache().IsCached = true; + } + } + + + // Get OpenGL ES2.0 texture wrap mode from Irrlicht wrap mode. + GLint COGLES2Driver::getTextureWrapMode(u8 clamp) const + { + switch (clamp) + { + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + case ETC_CLAMP_TO_BORDER: + return GL_CLAMP_TO_EDGE; + case ETC_MIRROR: + return GL_REPEAT; + default: + return GL_REPEAT; + } } @@ -2082,25 +2059,29 @@ namespace video if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); } + + //TwoDRenderer->useProgram(); //Fixed Pipeline Shader needed to render 2D + + if (Transformation3DChanged) + { + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + core::matrix4 m(core::matrix4::EM4CONST_NOTHING); + m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0f, 1.0f); + m.setTranslation(core::vector3df(-1,1,0)); + + //TwoDRenderer->setOrthoMatrix(m); + + // Make sure we set first texture matrix + BridgeCalls->setActiveTexture(GL_TEXTURE0); + + Transformation3DChanged = false; + } if (!OverrideMaterial2DEnabled) { setBasicRenderStates(InitMaterial2D, LastMaterial, true); LastMaterial = InitMaterial2D; } - - TwoDRenderer->useProgram(); //Fixed Pipeline Shader needed to render 2D - - if (Transformation3DChanged) - { - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - core::matrix4 m; - m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); - m.setTranslation(core::vector3df(-1, 1, 0)); - - TwoDRenderer->setOrthoMatrix(m); - - Transformation3DChanged = false; - } + BridgeCalls->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } if (OverrideMaterial2DEnabled) { @@ -2108,42 +2089,37 @@ namespace video setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); LastMaterial = OverrideMaterial2D; } + + // no alphaChannel without texture + alphaChannel &= texture; + if (alphaChannel || alpha) { - if (! BlendEnabled) - { - glEnable(GL_BLEND); - BlendEnabled = true; - } - blendFunc(EBF_SRC_ALPHA, EBF_ONE_MINUS_SRC_ALPHA); - TwoDRenderer->useAlphaTest(true); - TwoDRenderer->setAlphaTestValue(0.f); + BridgeCalls->setBlend(true); + //TwoDRenderer->useAlphaTest(true); + //TwoDRenderer->setAlphaTestValue(0.f); } else { - if (BlendEnabled) - { - glDisable(GL_BLEND); - BlendEnabled = false; - } - TwoDRenderer->useAlphaTest(false); + BridgeCalls->setBlend(false); + //TwoDRenderer->useAlphaTest(false); } if (texture) { - if (!OverrideMaterial2DEnabled) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } + if (OverrideMaterial2DEnabled) + setTextureRenderStates(OverrideMaterial2D, false); + else + setTextureRenderStates(InitMaterial2D, false); + + Material.setTexture(0, const_cast(CurrentTexture[0])); + setTransform(ETS_TEXTURE_0, core::IdentityMatrix); + // Due to the transformation change, the previous line would call a reset each frame + // but we can safely reset the variable as it was false before + Transformation3DChanged=false; } - TwoDRenderer->useTexture(texture); CurrentRenderMode = ERM_2D; - testGLError(); } @@ -2332,11 +2308,6 @@ namespace video //glShadeModel(GL_FLAT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - if (! BlendEnabled) - glEnable(GL_BLEND); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_STENCIL_TEST); glStencilFunc(GL_NOTEQUAL, 0, ~0); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -2373,10 +2344,6 @@ namespace video glDepthMask(depthMask); //TODO : OpenGL ES 2.0 Port glShadeModel //glShadeModel(shadeModel); - if (!BlendEnabled) - glDisable(GL_BLEND); - glBlendFunc(getGLBlend(SourceFactor), getGLBlend(DestFactor)); - testGLError(); } @@ -2502,10 +2469,10 @@ namespace video s32 userData, E_GPU_SHADING_LANGUAGE shadingLang) { s32 nr = -1; - COGLES2SLMaterialRenderer* r = new COGLES2SLMaterialRenderer( + COGLES2MaterialRenderer* r = new COGLES2MaterialRenderer( this, nr, vertexShaderProgram, pixelShaderProgram, - callback, getMaterialRenderer(baseMaterial), userData); + callback, baseMaterial, userData); r->drop(); return nr; @@ -2787,11 +2754,6 @@ namespace video } } - void COGLES2Driver::reloadShaders() - { - FixedPipeline->reload(); - } - void COGLES2Driver::deleteFramebuffers(s32 n, const u32 *framebuffers) { glDeleteFramebuffers(n, framebuffers); @@ -2802,77 +2764,6 @@ namespace video glDeleteRenderbuffers(n, renderbuffers); } - void COGLES2Driver::enableBlend() - { - if (! BlendEnabled) - { - BlendEnabled = true; - glEnable(GL_BLEND); - } - } - - void COGLES2Driver::disableBlend() - { - if (BlendEnabled) - { - BlendEnabled = false; - glDisable(GL_BLEND); - } - } - - u32 COGLES2Driver::getGLBlend(E_BLEND_FACTOR factor) - { - u32 r = 0; - switch (factor) - { - case EBF_ZERO: - r = GL_ZERO; - break; - case EBF_ONE: - r = GL_ONE; - break; - case EBF_DST_COLOR: - r = GL_DST_COLOR; - break; - case EBF_ONE_MINUS_DST_COLOR: - r = GL_ONE_MINUS_DST_COLOR; - break; - case EBF_SRC_COLOR: - r = GL_SRC_COLOR; - break; - case EBF_ONE_MINUS_SRC_COLOR: - r = GL_ONE_MINUS_SRC_COLOR; - break; - case EBF_SRC_ALPHA: - r = GL_SRC_ALPHA; - break; - case EBF_ONE_MINUS_SRC_ALPHA: - r = GL_ONE_MINUS_SRC_ALPHA; - break; - case EBF_DST_ALPHA: - r = GL_DST_ALPHA; - break; - case EBF_ONE_MINUS_DST_ALPHA: - r = GL_ONE_MINUS_DST_ALPHA; - break; - case EBF_SRC_ALPHA_SATURATE: - r = GL_SRC_ALPHA_SATURATE; - break; - } - return r; - } - - void COGLES2Driver::blendFunc(E_BLEND_FACTOR sFactor, E_BLEND_FACTOR dFactor) - { - if (sFactor != SourceFactor || dFactor != DestFactor) - { - SourceFactor = sFactor; - DestFactor = dFactor; - glBlendFunc(getGLBlend(sFactor), getGLBlend(dFactor)); - } - } - - //! Set/unset a clipping plane. bool COGLES2Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) { @@ -2912,6 +2803,166 @@ namespace video return core::dimension2du(MaxTextureSize, MaxTextureSize); } + GLenum COGLES2Driver::getGLBlend(E_BLEND_FACTOR factor) const + { + GLenum r = 0; + switch (factor) + { + case EBF_ZERO: r = GL_ZERO; break; + case EBF_ONE: r = GL_ONE; break; + case EBF_DST_COLOR: r = GL_DST_COLOR; break; + case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break; + case EBF_SRC_COLOR: r = GL_SRC_COLOR; break; + case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break; + case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break; + case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break; + case EBF_DST_ALPHA: r = GL_DST_ALPHA; break; + case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break; + case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break; + } + return r; + } + + const SMaterial& COGLES2Driver::getCurrentMaterial() const + { + return Material; + } + + COGLES2CallBridge* COGLES2Driver::getBridgeCalls() const + { + return BridgeCalls; + } + + COGLES2CallBridge::COGLES2CallBridge(COGLES2Driver* driver) : Driver(driver), + BlendSource(GL_ONE), BlendDestination(GL_ZERO), Blend(false), + CullFaceMode(GL_BACK), CullFace(false), + DepthFunc(GL_LESS), DepthMask(true), DepthTest(false), + ActiveTexture(GL_TEXTURE0) + { + // Initial OpenGL values from specification. + + for (u32 i = 0; i < MATERIAL_MAX_TEXTURES; ++i) + Texture[i] = 0; + + glBlendFunc(GL_ONE, GL_ZERO); + glDisable(GL_BLEND); + + glCullFace(GL_BACK); + glDisable(GL_CULL_FACE); + + glDepthFunc(GL_LESS); + glDepthMask(GL_TRUE); + glDisable(GL_DEPTH_TEST); + } + + void COGLES2CallBridge::setBlendFunc(GLenum source, GLenum destination) + { + if(BlendSource != source || BlendDestination != destination) + { + glBlendFunc(source, destination); + + BlendSource = source; + BlendDestination = destination; + } + } + + void COGLES2CallBridge::setBlend(bool enable) + { + if(Blend != enable) + { + if (enable) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + Blend = enable; + } + } + + void COGLES2CallBridge::setCullFaceFunc(GLenum mode) + { + if(CullFaceMode != mode) + { + glCullFace(mode); + + CullFaceMode = mode; + } + } + + void COGLES2CallBridge::setCullFace(bool enable) + { + if(CullFace != enable) + { + if (enable) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + CullFace = enable; + } + } + + void COGLES2CallBridge::setDepthFunc(GLenum mode) + { + if(DepthFunc != mode) + { + glDepthFunc(mode); + + DepthFunc = mode; + } + } + + void COGLES2CallBridge::setDepthMask(bool enable) + { + if(DepthMask != enable) + { + if (enable) + glDepthMask(GL_TRUE); + else + glDepthMask(GL_FALSE); + + DepthMask = enable; + } + } + + void COGLES2CallBridge::setDepthTest(bool enable) + { + if(DepthTest != enable) + { + if (enable) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + + DepthTest = enable; + } + } + + void COGLES2CallBridge::setActiveTexture(GLenum texture) + { + if (ActiveTexture != texture) + { + glActiveTexture(texture); + ActiveTexture = texture; + } + } + + void COGLES2CallBridge::setTexture(u32 stage) + { + if (stage < MATERIAL_MAX_TEXTURES) + { + if(Texture[stage] != Driver->CurrentTexture[stage]) + { + setActiveTexture(GL_TEXTURE0 + stage); + + if(Driver->CurrentTexture[stage]) + glBindTexture(GL_TEXTURE_2D, static_cast(Driver->CurrentTexture[stage])->getOGLES2TextureName()); + + Texture[stage] = Driver->CurrentTexture[stage]; + } + } + } + } // end namespace } // end namespace diff --git a/source/Irrlicht/COGLES2Driver.h b/source/Irrlicht/COGLES2Driver.h index 457582fa..be3c942c 100644 --- a/source/Irrlicht/COGLES2Driver.h +++ b/source/Irrlicht/COGLES2Driver.h @@ -1,8 +1,10 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h + #ifndef __C_OGLES2_DRIVER_H_INCLUDED__ #define __C_OGLES2_DRIVER_H_INCLUDED__ @@ -46,12 +48,18 @@ namespace irr { namespace video { + class COGLES2CallBridge; class COGLES2Texture; - class COGLES2FixedPipelineShader; - class COGLES2Renderer2d; + class COGLES2FixedPipelineRenderer; + class COGLES2NormalMapRenderer; + class COGLES2ParallaxMapRenderer; + + //class COGLES2Renderer2d; class COGLES2Driver : public CNullDriver, public IMaterialRendererServices, public COGLES2ExtensionHandler { + friend class COGLES2CallBridge; + public: #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_COMPILE_WITH_SDL_DEVICE_) || defined(_IRR_WINDOWS_API_) || defined(_IRR_COMPILE_WITH_CONSOLE_DEVICE_) COGLES2Driver(const SIrrlichtCreationParameters& params, @@ -234,9 +242,10 @@ namespace video virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Can be called by an IMaterialRenderer to make its work easier. - virtual void setBasicRenderStates(const SMaterial& material, - const SMaterial& lastmaterial, - bool resetAllRenderstates); + virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates); + + //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call. + virtual void setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates); //! Sets a vertex shader constant. virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1); @@ -344,24 +353,21 @@ namespace video ITexture* createDepthTexture(ITexture* texture, bool shared = true); void removeDepthTexture(ITexture* texture); - COGLES2FixedPipelineShader* fixedPipeline() - { - return FixedPipeline; - } - - virtual void reloadShaders(); - - //native ogles2 which was ogles1 extensions. - void deleteFramebuffers(s32 n, const u32 *framebuffers); void deleteRenderbuffers(s32 n, const u32 *renderbuffers); - void enableBlend(); - void disableBlend(); - u32 getGLBlend(E_BLEND_FACTOR factor); - void blendFunc(E_BLEND_FACTOR sFactor, E_BLEND_FACTOR dFactor); + //! Convert E_BLEND_FACTOR to OpenGL equivalent + GLenum getGLBlend(E_BLEND_FACTOR factor) const; + + //! Get current material. + const SMaterial& getCurrentMaterial() const; + + //! Get bridge calls. + COGLES2CallBridge* getBridgeCalls() const; private: + // Bridge calls. + COGLES2CallBridge* BridgeCalls; void uploadClipPlane(u32 index); @@ -379,9 +385,6 @@ namespace video //! Map Irrlicht wrap mode to OpenGL enum GLint getTextureWrapMode(u8 clamp) const; - //! Set GL pipeline to desired texture wrap modes of the material - void setWrapMode(const SMaterial& material); - //! sets the needed renderstates void setRenderStates3DMode(); @@ -461,14 +464,62 @@ namespace video void* EglContext; #endif - COGLES2FixedPipelineShader* FixedPipeline; - COGLES2Renderer2d* TwoDRenderer; - - bool BlendEnabled; - E_BLEND_FACTOR SourceFactor; - E_BLEND_FACTOR DestFactor; + //COGLES2Renderer2d* TwoDRenderer; }; + //! This bridge between Irlicht pseudo OpenGL calls + //! and true OpenGL calls. + + class COGLES2CallBridge + { + public: + COGLES2CallBridge(COGLES2Driver* driver); + + // Blending calls. + + void setBlendFunc(GLenum source, GLenum destination); + + void setBlend(bool enable); + + // Cull face calls. + + void setCullFaceFunc(GLenum mode); + + void setCullFace(bool enable); + + // Depth calls. + + void setDepthFunc(GLenum mode); + + void setDepthMask(bool enable); + + void setDepthTest(bool enable); + + // Texture calls. + + void setActiveTexture(GLenum texture); + + void setTexture(u32 stage); + + private: + COGLES2Driver* Driver; + + GLenum BlendSource; + GLenum BlendDestination; + bool Blend; + + GLenum CullFaceMode; + bool CullFace; + + GLenum DepthFunc; + bool DepthMask; + bool DepthTest; + + GLenum ActiveTexture; + + const ITexture* Texture[MATERIAL_MAX_TEXTURES]; + }; + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/COGLES2FixedPipelineRenderer.cpp b/source/Irrlicht/COGLES2FixedPipelineRenderer.cpp new file mode 100644 index 00000000..887c3491 --- /dev/null +++ b/source/Irrlicht/COGLES2FixedPipelineRenderer.cpp @@ -0,0 +1,96 @@ +// Copyright (C) 2013 Patryk Nadrowski +// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in Irrlicht.h + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_OGLES2_ + +#include "COGLES2FixedPipelineRenderer.h" +#include "IGPUProgrammingServices.h" +#include "os.h" +#include "COGLES2Driver.h" + +namespace irr +{ +namespace video +{ + +//! Constructor +COGLES2FixedPipelineRenderer::COGLES2FixedPipelineRenderer(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, E_MATERIAL_TYPE baseMaterial, + COGLES2Driver* driver) + : COGLES2MaterialRenderer(driver, 0, baseMaterial) +{ + #ifdef _DEBUG + setDebugName("COGLES2FixedPipelineRenderer"); + #endif + + int Temp = 0; + + SharedRenderer = reinterpret_cast(driver->getMaterialRenderer(EMT_SOLID)); + + if (SharedRenderer) + SharedRenderer->grab(); + else + init(Temp, vertexShaderProgram, pixelShaderProgram, false); +} + + +//! Destructor +COGLES2FixedPipelineRenderer::~COGLES2FixedPipelineRenderer() +{ + if(SharedRenderer) + SharedRenderer->drop(); +} + + +void COGLES2FixedPipelineRenderer::OnSetMaterial(const video::SMaterial& material, + const video::SMaterial& lastMaterial, + bool resetAllRenderstates, + video::IMaterialRendererServices* services) +{ + if (SharedRenderer) + SharedRenderer->OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); + else + COGLES2MaterialRenderer::OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); +} + + +bool COGLES2FixedPipelineRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) +{ + if (SharedRenderer) + return SharedRenderer->OnRender(service, vtxtype); + else + { + /* Vertex Shader part */ + + /* Matrices Upload */ + core::matrix4 world = Driver->getTransform(ETS_WORLD); + setPixelShaderConstant("uWorldMatrix", world.pointer(), 16); + + core::matrix4 worldViewProj = Driver->getTransform(video::ETS_PROJECTION); + worldViewProj *= Driver->getTransform(video::ETS_VIEW); + worldViewProj *= Driver->getTransform(ETS_WORLD); + setPixelShaderConstant("uMvpMatrix", worldViewProj.pointer(), 16); + + /* Textures Upload */ + int TextureUnit0 = 0; + int TextureUnit1 = 1; + + setPixelShaderConstant("uTextureUnit0", &TextureUnit0, 1); + setPixelShaderConstant("uTextureUnit1", &TextureUnit1, 1); + + return true; + } +} + + +} // end namespace video +} // end namespace irr + + +#endif diff --git a/source/Irrlicht/COGLES2FixedPipelineRenderer.h b/source/Irrlicht/COGLES2FixedPipelineRenderer.h new file mode 100644 index 00000000..5127aa38 --- /dev/null +++ b/source/Irrlicht/COGLES2FixedPipelineRenderer.h @@ -0,0 +1,49 @@ +// Copyright (C) 2013 Patryk Nadrowski +// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in Irrlicht.h + +#ifndef __C_OGLES2_FIXED_PIPELINE_SHADER_H_INCLUDED__ +#define __C_OGLES2_FIXED_PIPELINE_SHADER_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_OGLES2_ + +#include "COGLES2MaterialRenderer.h" + +namespace irr +{ +namespace video +{ + +//! Class for rendering fixed pipeline stuff with OpenGL ES 2.0 +class COGLES2FixedPipelineRenderer : public COGLES2MaterialRenderer +{ +public: + //! Constructor + COGLES2FixedPipelineRenderer(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, E_MATERIAL_TYPE baseMaterial, + COGLES2Driver* driver); + + //! Destructor + ~COGLES2FixedPipelineRenderer(); + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services); + + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); + +protected: + + COGLES2MaterialRenderer* SharedRenderer; +}; + + +} // end namespace video +} // end namespace irr + +#endif +#endif diff --git a/source/Irrlicht/COGLES2FixedPipelineShader.cpp b/source/Irrlicht/COGLES2FixedPipelineShader.cpp deleted file mode 100644 index aa32e777..00000000 --- a/source/Irrlicht/COGLES2FixedPipelineShader.cpp +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (C) 2009-2010 Amundis -// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h - -#include "COGLES2FixedPipelineShader.h" - -#ifdef _IRR_COMPILE_WITH_OGLES2_ - -#include "COGLES2SLMaterialRenderer.h" -#include "COGLES2Utils.h" - -namespace irr -{ -namespace video -{ - - const char* const COGLES2FixedPipelineShader::sBuiltInShaderUniformNames[] = - { - "uVRenderMode", - "uFRenderMode", - "uMvpMatrix", - "uWorldMatrix", - "uNormalize", - "uEyePos", - "uUseLight", - "uLightPosition", - "uLightAmbient", - "uLightDiffuse", - "uLightSpecular", - "uLightDirection", - "uLightAttenuation", - "uLightExponent", - "uLightCutoff", - "uAmbientColor", - "uLighting", - "uMaterialAmbient", - "uMaterialEmission", - "uMaterialDiffuse", - "uMaterialSpecular", - "uMaterialShininess", - "uColorMaterial", - "uUseTexture", - "uTextureMatrix", - "uUseTexMatrix", - "uClip", - "uClipPlane", - "uAlphaTest", - "uAlphaValue", - "uFog", - "uFogType", - "uFogColor", - "uFogStart", - "uFogEnd", - "uFogDensity", - "uTextureUnit0", - "uTextureUnit1", - 0 - }; - - const c8 VertexShaderFile[] = IRR_OGLES2_SHADER_PATH "COGLES2FixedPipeline.vsh"; - const c8 FragmentShaderFile[] = IRR_OGLES2_SHADER_PATH "COGLES2FixedPipeline.fsh"; - - COGLES2FixedPipelineShader::COGLES2FixedPipelineShader(video::COGLES2Driver *driver, io::IFileSystem* fs) - : COGLES2SLMaterialRenderer(driver, fs, 0, 0, sBuiltInShaderUniformNames, UNIFORM_COUNT), Normalize(0), AlphaTest(0), AlphaValue(0.f), - AlphaFunction(ALPHA_GREATER), Lighting(0), Fog(0), FogType(0), FogStart(0.f), FogEnd(0.f), FogDensity(0.f), - ColorMaterial(0), MaterialShininess(0.f), RenderMode(EMT_SOLID) - { - s32 dummy; - initFromFiles(dummy, VertexShaderFile, FragmentShaderFile, false); - initData(); - }; - - void COGLES2FixedPipelineShader::reload() - { - reloadFromFiles(VertexShaderFile, FragmentShaderFile); - //initData(); - } - - void COGLES2FixedPipelineShader::initData() - { - for (u32 i = 0; i < MATERIAL_MAX_TEXTURES; ++i) - TextureUnits[i] = i; - memset(UseTexture, 0, sizeof(UseTexture)); - memset(UseTexMatrix, 0, sizeof(UseTexMatrix)); - memset(UseLight, 0, sizeof(UseLight)); - memset(LightPosition, 0, sizeof(LightPosition)); - memset(LightAmbient, 0, sizeof(LightAmbient)); - memset(LightDiffuse, 0, sizeof(LightDiffuse)); - memset(LightSpecular, 0, sizeof(LightSpecular)); - memset(LightDirection, 0, sizeof(LightDirection)); - memset(LightAttenuation, 0, sizeof(LightAttenuation)); - memset(LightExponent, 0, sizeof(LightExponent)); - memset(LightCutoff, 0, sizeof(LightCutoff)); - memset(&AmbientColor, 0, sizeof(AmbientColor)); - memset(FogColor, 0, sizeof(FogColor)); - memset(&ClipPlane, 0, sizeof(ClipPlane)); - memset(&MaterialAmbient, 0, sizeof(MaterialAmbient)); - memset(&MaterialEmission, 0, sizeof(MaterialEmission)); - memset(&MaterialDiffuse, 0, sizeof(MaterialDiffuse)); - memset(&MaterialSpecular, 0, sizeof(MaterialSpecular)); - } - - bool COGLES2FixedPipelineShader::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) - { - Driver->testGLError(); - bool statusOk = true; - - /* Matrices Upload */ - core::matrix4 world = Driver->getTransform(ETS_WORLD); - setUniform(WORLD_MATRIX, world.pointer()); - - core::matrix4 worldViewProj = Driver->getTransform(video::ETS_PROJECTION); - worldViewProj *= Driver->getTransform(video::ETS_VIEW); - worldViewProj *= Driver->getTransform(ETS_WORLD); - setUniform(MVP_MATRIX, worldViewProj.pointer()); - - /* Textures Upload */ - //statusOk &= setVertexShaderConstant("uTextureUnit", (f32*)TextureUnits, MAX_TEXTURE_UNITS); - setUniform(TEXTURE_UNIT0, &TextureUnits[0]); - setUniform(TEXTURE_UNIT1, &TextureUnits[1]); - - setUniform(USE_TEXTURE, UseTexture, MATERIAL_MAX_TEXTURES); - setUniform(USE_TEXTURE_MATRIX, UseTexMatrix, MATERIAL_MAX_TEXTURES); - setUniform(TEXTURE_MATRIX, TextureMatrix, MATERIAL_MAX_TEXTURES); - core::matrix4 invWorld; - - /* Lights (in Object Space) Upload */ - if (Lighting) - { - u32 cnt = Driver->getDynamicLightCount(); - Driver->getTransform(ETS_WORLD).getInverse(invWorld); - for ( size_t i = 0; i < MAX_LIGHTS; ++i ) - { - - if ( i < cnt ) - { - UseLight[i] = 1; - video::SLight light; - light = Driver->getDynamicLight( i ); - - switch ( light.Type ) - { - case ELT_DIRECTIONAL: - invWorld.rotateVect(( f32* )&LightPosition[i], light.Direction ); - LightPosition[i].data[4] = 0.0; - break; - case ELT_SPOT: - invWorld.rotateVect( LightDirection[i], light.Direction ); - LightExponent[i] = light.Falloff; - LightCutoff[i] = light.OuterCone; - //no break on purpose ! - case ELT_POINT: - invWorld.transformVect(( f32* )&LightPosition[i], light.Position ); - LightPosition[i].data[4] = 1.0; - LightAttenuation[i] = light.Attenuation; - break; - - default: - UseLight[i] = 0; - break; - } - - LightAmbient[i] = light.AmbientColor; - LightDiffuse[i] = light.DiffuseColor; - LightSpecular[i] = light.SpecularColor; - LightAttenuation[i] = light.Attenuation; - } - else - { - UseLight[i] = 0; - } - } - //statusOk &= setVertexShaderConstant( "uLighting", ( f32* ) & Lighting, 1 ); - setUniform( USE_LIGHT, UseLight, MAX_LIGHTS ); - setUniform( LIGHT_POSITION, LightPosition, MAX_LIGHTS ); - setUniform( LIGHT_DIRECTION, LightDirection, MAX_LIGHTS ); - setUniform( LIGHT_AMBIENT, LightAmbient, MAX_LIGHTS ); - setUniform( LIGHT_DIFFUSE, LightDiffuse, MAX_LIGHTS ); - setUniform( LIGHT_SPECULAR, LightSpecular, MAX_LIGHTS ); - setUniform( LIGHT_ATTENUATION, LightAttenuation, MAX_LIGHTS ); - setUniform( LIGHT_EXPONENT, LightExponent, MAX_LIGHTS ); - setUniform( LIGHT_CUTOFF, LightCutoff, MAX_LIGHTS ); - - AmbientColor = Driver->getAmbientLight(); - setUniform( LIGHT_AMBIENT, &AmbientColor ); - } - - /* Fog */ - /* statusOk &= setVertexShaderConstant("uFog", (f32*) &Fog, 1); - statusOk &= setVertexShaderConstant("uFogType", (f32*) &FogType, 1); - statusOk &= setVertexShaderConstant("uFogColor", FogColor, 4); - statusOk &= setVertexShaderConstant("uFogStart", &FogStart, 1); - statusOk &= setVertexShaderConstant("uFogEnd", &FogEnd, 1); - statusOk &= setVertexShaderConstant("uFogDensity", &FogDensity, 1);*/ - - /* Clip Plane */ - u32 cnt = Driver->getClipPlaneCount(); - if (cnt > 0) - { - Clip = 1; - ClipPlane = Driver->getClipPlane(0); - } - else - { - Clip = 0; - } - - /* Eye/Camera Position in ObjectSpace */ - if (Clip || RenderMode == EMT_SPHERE_MAP || RenderMode == EMT_REFLECTION_2_LAYER) // Need clipping or reflection - { - if (!Lighting) - Driver->getTransform(ETS_WORLD).getInverse(invWorld); - core::vector3df viewPos(0.0f, 0.0f, 0.0f); - core::matrix4 inverseView; - Driver->getTransform(video::ETS_VIEW).getInverse(inverseView); - inverseView.transformVect(viewPos); - invWorld.transformVect(viewPos); - setUniform(EYE_POSITION, &viewPos.X); - } - - setUniform(CLIP, &Clip); - setUniform(CLIP_PLANE, &ClipPlane); - setUniform(VRENDER_MODE, &RenderMode); - setUniform(FRENDER_MODE, &RenderMode); - - return statusOk ; - }; - - void COGLES2FixedPipelineShader::setMaterial(const SMaterial &material) - { - if (Fog != static_cast(material.FogEnable)) - { - Fog = material.FogEnable; - setUniform(FOG, &Fog); - } - if (Lighting != static_cast(material.Lighting)) - { - Lighting = material.Lighting; - setUniform(LIGHTING, &Lighting); - } - - if (Normalize != static_cast(material.NormalizeNormals)) - { - Normalize = material.NormalizeNormals; - setUniform(NORMALIZE, &Normalize); - } - - for (u32 i = 0; i < MATERIAL_MAX_TEXTURES; ++i) - { - UseTexture[i] = material.getTexture(i) != 0; - if (UseTexture[i]) - { - UseTexMatrix[i] = false; - const core::matrix4& texMat = material.getTextureMatrix(i); - if (!texMat.isIdentity()) - { - UseTexMatrix[i] = true; - memcpy(&TextureMatrix[i], texMat.pointer(), sizeof(mat4)); - } - } - } - - - if (ColorMaterial != material.ColorMaterial) - { - ColorMaterial = material.ColorMaterial; - setUniform(COLOR_MATERIAL, &ColorMaterial); - } - if (MaterialAmbient != material.AmbientColor) - { - MaterialAmbient = material.AmbientColor; - setUniform(MATERIAL_AMBIENT, &MaterialAmbient); - } - if (MaterialEmission != material.EmissiveColor) - { - MaterialEmission = material.EmissiveColor; - setUniform(MATERIAL_EMISSION, &MaterialEmission); - } - if (MaterialDiffuse != material.DiffuseColor) - { - MaterialDiffuse = material.DiffuseColor; - setUniform(MATERIAL_DIFFUSE, &MaterialDiffuse); - } - if (MaterialSpecular != material.SpecularColor) - { - MaterialSpecular = material.SpecularColor; - setUniform(MATERIAL_SPECULAR, &MaterialSpecular); - } - if (MaterialShininess != material.Shininess) - { - MaterialShininess = material.Shininess; - setUniform(MATERIAL_SHININESS, &MaterialShininess); - } - } - -} -} - -#endif //_IRR_COMPILE_WITH_OGLES2_ diff --git a/source/Irrlicht/COGLES2FixedPipelineShader.h b/source/Irrlicht/COGLES2FixedPipelineShader.h deleted file mode 100644 index 4756e7ea..00000000 --- a/source/Irrlicht/COGLES2FixedPipelineShader.h +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (C) 2009-2010 Amundis -// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h - -#ifndef __C_OGLES2_FIXED_PIPELINE_SHADER_H_INCLUDED__ -#define __C_OGLES2_FIXED_PIPELINE_SHADER_H_INCLUDED__ - -#include "IrrCompileConfig.h" - -#ifdef _IRR_COMPILE_WITH_OGLES2_ - -#include "COGLES2Driver.h" -#include "COGLES2SLMaterialRenderer.h" -#include "EVertexAttributes.h" - -namespace irr -{ -namespace video -{ -#define MAX_LIGHTS 8 - - enum AlphaFunc - { - ALPHA_GREATER = 0 - }; - - class COGLES2FixedPipelineShader : public COGLES2SLMaterialRenderer - { - - public: - - COGLES2FixedPipelineShader(video::COGLES2Driver* driver, io::IFileSystem* fs); - - void updateMatrices(); - void bindTexture(); - virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); - - public: - /*void enableNormalize() {Normalize = true;} - void disableNormalize() {Normalize = false;}*/ - - void enableAlphaTest() - { - AlphaTest = true; - } - void disableAlphaTest() - { - AlphaTest = false; - } - void setAlphaValue(float value) - { - AlphaValue = value; - } - - /*void enableLighting() {Lighting = true;} - void disableLighting() {Lighting = false;} - bool isLightingEnabled() {return (Lighting == 1);}*/ - void setAmbientLight(const SColorf& color); - - void enableFog() - { - Fog = true; - } - void disableFog() - { - Fog = false; - } - bool isFogEnabled() - { - return (Fog == 1); - } - void setFog(E_FOG_TYPE type, const SColor& color, f32 start, f32 end, f32 density); - - void setMaterial(const SMaterial& material); - - void setRenderMode(E_MATERIAL_TYPE mode) - { - RenderMode = mode; - } - - void reload(); - - private: - - void initData(); - - private: - - struct vec3 - { - float data[3]; - }; - struct vec4 - { - float data[4]; - }; - struct mat4 - { - float data[16]; - }; - - float Normalize; - - - int TextureUnits[MATERIAL_MAX_TEXTURES]; - int UseTexture[MATERIAL_MAX_TEXTURES]; - mat4 TextureMatrix[MATERIAL_MAX_TEXTURES]; - int UseTexMatrix[MATERIAL_MAX_TEXTURES]; - - - float AlphaTest; - float AlphaValue; - AlphaFunc AlphaFunction; - - int Lighting; - int UseLight[MAX_LIGHTS]; - vec4 LightPosition[MAX_LIGHTS]; - SColorf LightAmbient[MAX_LIGHTS]; - SColorf LightDiffuse[MAX_LIGHTS]; - SColorf LightSpecular[MAX_LIGHTS]; - core::vector3df LightDirection[MAX_LIGHTS]; - core::vector3df LightAttenuation[MAX_LIGHTS]; - float LightExponent[MAX_LIGHTS]; - float LightCutoff[MAX_LIGHTS]; - SColorf AmbientColor; - - int Fog; - int FogType; - float FogColor[4]; - float FogStart; - float FogEnd; - float FogDensity; - - int Clip; - core::plane3df ClipPlane; - - u32 ColorMaterial; - SColorf MaterialAmbient; - SColorf MaterialEmission; - SColorf MaterialDiffuse; - SColorf MaterialSpecular; - float MaterialShininess; - - E_MATERIAL_TYPE RenderMode; - private : - enum SHADER_UNIFORM - { - VRENDER_MODE = 0, - FRENDER_MODE, - MVP_MATRIX, - WORLD_MATRIX, - NORMALIZE, - EYE_POSITION, - USE_LIGHT, - LIGHT_POSITION, - LIGHT_AMBIENT, - LIGHT_DIFFUSE, - LIGHT_SPECULAR, - LIGHT_DIRECTION, - LIGHT_ATTENUATION, - LIGHT_EXPONENT, - LIGHT_CUTOFF, - AMBIENT_COLOR, - LIGHTING, - MATERIAL_AMBIENT, - MATERIAL_EMISSION, - MATERIAL_DIFFUSE, - MATERIAL_SPECULAR, - MATERIAL_SHININESS, - COLOR_MATERIAL, - USE_TEXTURE, - TEXTURE_MATRIX, - USE_TEXTURE_MATRIX, - CLIP, - CLIP_PLANE, - ALPHA_TEST, - ALPHA_VALUE, - FOG, - FOG_TYPE, - FOG_COLOR, - FOG_START, - FOG_END, - FOG_DENSITY, - TEXTURE_UNIT0, - TEXTURE_UNIT1, - UNIFORM_COUNT - }; - static const char* const sBuiltInShaderUniformNames[]; - }; -} -} - -#endif //_IRR_COMPILE_WITH_OGLES2_ - -#endif //__C_OGLES2_FIXED_PIPELINE_SHADER_H_INCLUDED__ diff --git a/source/Irrlicht/COGLES2MaterialRenderer.cpp b/source/Irrlicht/COGLES2MaterialRenderer.cpp new file mode 100644 index 00000000..f22aa59e --- /dev/null +++ b/source/Irrlicht/COGLES2MaterialRenderer.cpp @@ -0,0 +1,464 @@ +// Copyright (C) 2013 Patryk Nadrowski +// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in Irrlicht.h + +#include "IrrCompileConfig.h" +#ifdef _IRR_COMPILE_WITH_OGLES2_ + +#include "COGLES2MaterialRenderer.h" +#include "IGPUProgrammingServices.h" +#include "IShaderConstantSetCallBack.h" +#include "IMaterialRendererServices.h" +#include "IVideoDriver.h" +#include "os.h" +#include "COGLES2Driver.h" +#include "COGLES2MaterialRenderer.h" + +namespace irr +{ +namespace video +{ + + +//! Constructor +COGLES2MaterialRenderer::COGLES2MaterialRenderer(COGLES2Driver* driver, + s32& outMaterialTypeNr, + const c8* vertexShaderProgram, + const c8* pixelShaderProgram, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) + : Driver(driver), CallBack(callback), Program(0), Alpha(false), Blending(false), FixedBlending(false), UserData(userData) +{ + #ifdef _DEBUG + setDebugName("COGLES2MaterialRenderer"); + #endif + + if (baseMaterial == EMT_TRANSPARENT_VERTEX_ALPHA || baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL || + baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL_REF || baseMaterial == EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA || + baseMaterial == EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA) + { + Alpha = true; + } + else if (baseMaterial == EMT_TRANSPARENT_ADD_COLOR || baseMaterial == EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR || + baseMaterial == EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR) + { + FixedBlending = true; + } + else if (baseMaterial == EMT_ONETEXTURE_BLEND) + Blending = true; + + if (CallBack) + CallBack->grab(); + + init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram); +} + + +//! constructor only for use by derived classes who want to +//! create a fall back material for example. +COGLES2MaterialRenderer::COGLES2MaterialRenderer(COGLES2Driver* driver, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, s32 userData) +: Driver(driver), CallBack(callback), Program(0), Alpha(false), Blending(false), FixedBlending(false), UserData(userData) +{ + if (baseMaterial == EMT_TRANSPARENT_VERTEX_ALPHA || baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL || + baseMaterial == EMT_TRANSPARENT_ALPHA_CHANNEL_REF || baseMaterial == EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA || + baseMaterial == EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA) + { + Alpha = true; + } + else if (baseMaterial == EMT_TRANSPARENT_ADD_COLOR || baseMaterial == EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR || + baseMaterial == EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR) + { + FixedBlending = true; + } + else if (baseMaterial == EMT_ONETEXTURE_BLEND) + Blending = true; + + if (CallBack) + CallBack->grab(); +} + + +//! Destructor +COGLES2MaterialRenderer::~COGLES2MaterialRenderer() +{ + if (CallBack) + CallBack->drop(); + + if (Program) + { + GLuint shaders[8]; + GLint count; + glGetAttachedShaders(Program, 8, &count, shaders); + // avoid bugs in some drivers, which return larger numbers + count=core::min_(count,8); + for (GLint i=0; iaddMaterialRenderer(this); +} + + +bool COGLES2MaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) +{ + Driver->setTextureRenderStates(Driver->getCurrentMaterial(), false); + + // call callback to set shader constants + if (CallBack && Program) + CallBack->OnSetConstants(this, UserData); + + return true; +} + + +void COGLES2MaterialRenderer::OnSetMaterial(const video::SMaterial& material, + const video::SMaterial& lastMaterial, + bool resetAllRenderstates, + video::IMaterialRendererServices* services) +{ + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + + if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) + { + if (Program) + glUseProgram(Program); + + if (FixedBlending) + { + Driver->getBridgeCalls()->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); + Driver->getBridgeCalls()->setBlend(true); + } + else if (Blending) + { + E_BLEND_FACTOR srcFact,dstFact; + E_MODULATE_FUNC modulate; + u32 alphaSource; + unpack_textureBlendFunc(srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam); + + Driver->getBridgeCalls()->setBlendFunc(Driver->getGLBlend(srcFact), Driver->getGLBlend(dstFact)); + Driver->getBridgeCalls()->setBlend(true); + } + } + + if (CallBack) + CallBack->OnSetMaterial(material); +} + + +void COGLES2MaterialRenderer::OnUnsetMaterial() +{ + if (Program) + glUseProgram(0); + + if (Blending || FixedBlending) + Driver->getBridgeCalls()->setBlend(false); +} + + +//! Returns if the material is transparent. +bool COGLES2MaterialRenderer::isTransparent() const +{ + return (Alpha || Blending || FixedBlending); +} + + +bool COGLES2MaterialRenderer::createShader(GLenum shaderType, const char* shader) +{ + if (Program) + { + GLuint shaderHandle = glCreateShader(shaderType); + glShaderSource(shaderHandle, 1, &shader, NULL); + glCompileShader(shaderHandle); + + GLint status = 0; + + glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &status); + + if (status != GL_TRUE) + { + os::Printer::log("GLSL shader failed to compile", ELL_ERROR); + // check error message and log it + GLint maxLength=0; + GLint length; + + glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, + &maxLength); + + if (maxLength) + { + GLchar *infoLog = new GLchar[maxLength]; + glGetShaderInfoLog(shaderHandle, maxLength, &length, infoLog); + os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); + delete [] infoLog; + } + + return false; + } + + glAttachShader(Program, shaderHandle); + } + + return true; +} + + +bool COGLES2MaterialRenderer::linkProgram() +{ + if (Program) + { + glLinkProgram(Program); + + GLint status = 0; + + glGetProgramiv(Program, GL_LINK_STATUS, &status); + + if (!status) + { + os::Printer::log("GLSL shader program failed to link", ELL_ERROR); + // check error message and log it + GLint maxLength=0; + GLsizei length; + + glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &maxLength); + + if (maxLength) + { + GLchar *infoLog = new GLchar[maxLength]; + glGetProgramInfoLog(Program, maxLength, &length, infoLog); + os::Printer::log(reinterpret_cast(infoLog), ELL_ERROR); + delete [] infoLog; + } + + return false; + } + + // get uniforms information + + GLint num = 0; + + glGetProgramiv(Program, GL_ACTIVE_UNIFORMS, &num); + + if (num == 0) + { + // no uniforms + return true; + } + + GLint maxlen = 0; + + glGetProgramiv(Program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen); + + if (maxlen == 0) + { + os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR); + return false; + } + + // seems that some implementations use an extra null terminator + ++maxlen; + c8 *buf = new c8[maxlen]; + + UniformInfo.clear(); + UniformInfo.reallocate(num); + + for (GLint i=0; i < num; ++i) + { + SUniformInfo ui; + memset(buf, 0, maxlen); + + GLint size; + glGetActiveUniform(Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast(buf)); + ui.name = buf; + ui.location = glGetUniformLocation(Program, buf); + + UniformInfo.push_back(ui); + } + + delete [] buf; + } + + return true; +} + + +void COGLES2MaterialRenderer::setBasicRenderStates(const SMaterial& material, + const SMaterial& lastMaterial, + bool resetAllRenderstates) +{ + // forward + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); +} + +s32 COGLES2MaterialRenderer::getVertexShaderConstantID(const c8* name) +{ + return getPixelShaderConstantID(name); +} + +s32 COGLES2MaterialRenderer::getPixelShaderConstantID(const c8* name) +{ + for (u32 i = 0; i < UniformInfo.size(); ++i) + { + if (UniformInfo[i].name == name) + return i; + } + + return -1; +} + +void COGLES2MaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) +{ + os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING); +} + +void COGLES2MaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount) +{ + os::Printer::log("Cannot set constant, use high level shader call.", ELL_WARNING); +} + +bool COGLES2MaterialRenderer::setVertexShaderConstant(s32 index, const f32* floats, int count) +{ + return setPixelShaderConstant(index, floats, count); +} + +bool COGLES2MaterialRenderer::setVertexShaderConstant(s32 index, const s32* ints, int count) +{ + return setPixelShaderConstant(index, ints, count); +} + +bool COGLES2MaterialRenderer::setPixelShaderConstant(s32 index, const f32* floats, int count) +{ + if(index < 0 || UniformInfo[index].location < 0) + return false; + + bool status = true; + + switch (UniformInfo[index].type) + { + case GL_FLOAT: + glUniform1fv(UniformInfo[index].location, count, floats); + break; + case GL_FLOAT_VEC2: + glUniform2fv(UniformInfo[index].location, count/2, floats); + break; + case GL_FLOAT_VEC3: + glUniform3fv(UniformInfo[index].location, count/3, floats); + break; + case GL_FLOAT_VEC4: + glUniform4fv(UniformInfo[index].location, count/4, floats); + break; + case GL_FLOAT_MAT2: + glUniformMatrix2fv(UniformInfo[index].location, count/4, false, floats); + break; + case GL_FLOAT_MAT3: + glUniformMatrix3fv(UniformInfo[index].location, count/9, false, floats); + break; + case GL_FLOAT_MAT4: + glUniformMatrix4fv(UniformInfo[index].location, count/16, false, floats); + break; + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + { + if(floats) + { + const GLint id = *floats; + glUniform1iv(UniformInfo[index].location, 1, &id); + } + else + status = false; + } + break; + default: + status = false; + break; + } + + return status; +} + +bool COGLES2MaterialRenderer::setPixelShaderConstant(s32 index, const s32* ints, int count) +{ + if(index < 0 || UniformInfo[index].location < 0) + return false; + + bool status = true; + + switch (UniformInfo[index].type) + { + case GL_INT: + case GL_BOOL: + glUniform1iv(UniformInfo[index].location, count, ints); + break; + case GL_INT_VEC2: + case GL_BOOL_VEC2: + glUniform2iv(UniformInfo[index].location, count/2, ints); + break; + case GL_INT_VEC3: + case GL_BOOL_VEC3: + glUniform3iv(UniformInfo[index].location, count/3, ints); + break; + case GL_INT_VEC4: + case GL_BOOL_VEC4: + glUniform4iv(UniformInfo[index].location, count/4, ints); + break; + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + glUniform1iv(UniformInfo[index].location, 1, ints); + break; + default: + status = false; + break; + } + + return status; +} + +IVideoDriver* COGLES2MaterialRenderer::getVideoDriver() +{ + return Driver; +} + +} // end namespace video +} // end namespace irr + + +#endif diff --git a/source/Irrlicht/COGLES2MaterialRenderer.h b/source/Irrlicht/COGLES2MaterialRenderer.h index 7f30fc21..cc3d719e 100644 --- a/source/Irrlicht/COGLES2MaterialRenderer.h +++ b/source/Irrlicht/COGLES2MaterialRenderer.h @@ -1,600 +1,142 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h -#ifndef __C_OGLES2_MATERIAL_RENDERER_H_INCLUDED__ -#define __C_OGLES2_MATERIAL_RENDERER_H_INCLUDED__ + +#ifndef __C_OGLES2_SL_MATERIAL_RENDERER_H_INCLUDED__ +#define __C_OGLES2_SL_MATERIAL_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" + #ifdef _IRR_COMPILE_WITH_OGLES2_ -#include "COGLES2SLMaterialRenderer.h" -#include "COGLES2FixedPipelineShader.h" +#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) +#include +#include +#else +#include +#include +#endif + +#include "EMaterialTypes.h" +#include "EVertexAttributes.h" +#include "IMaterialRenderer.h" +#include "IMaterialRendererServices.h" +#include "IGPUProgrammingServices.h" +#include "IShaderConstantSetCallBack.h" +#include "irrArray.h" +#include "irrString.h" namespace irr { -namespace video +namespace video { - //! Base class for all internal OGLES2 material renderers - class COGLES2MaterialRenderer : public IMaterialRenderer +class COGLES2Driver; + +//! Class for using GLSL shaders with OpenGL ES 2.0 +//! Please note: This renderer implements its own IMaterialRendererServices +class COGLES2MaterialRenderer : public IMaterialRenderer, public IMaterialRendererServices +{ +public: + + //! Constructor + COGLES2MaterialRenderer( + COGLES2Driver* driver, + s32& outMaterialTypeNr, + const c8* vertexShaderProgram = 0, + const c8* pixelShaderProgram = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = EMT_SOLID, + s32 userData = 0); + + //! Destructor + virtual ~COGLES2MaterialRenderer(); + + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services); + + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); + + virtual void OnUnsetMaterial(); + + //! Returns if the material is transparent. + virtual bool isTransparent() const; + + // implementations for the render services + virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates); + + virtual s32 getVertexShaderConstantID(const c8* name); + virtual s32 getPixelShaderConstantID(const c8* name); + virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); + virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1); + virtual bool setVertexShaderConstant(s32 index, const f32* floats, int count); + virtual bool setVertexShaderConstant(s32 index, const s32* ints, int count); + virtual bool setPixelShaderConstant(s32 index, const f32* floats, int count); + virtual bool setPixelShaderConstant(s32 index, const s32* ints, int count); + + //! For compatybility with old irrlicht revisions. + + bool setVertexShaderConstant(const c8* name, const f32* floats, int count) { - public: + return setVertexShaderConstant(getVertexShaderConstantID(name), floats, count); + } - //! Constructor - COGLES2MaterialRenderer( video::COGLES2Driver* driver ) : - Driver( driver ), - FixedPipeline( driver->fixedPipeline() ) - { - } + bool setVertexShaderConstant(const c8* name, const s32* ints, int count) + { + return setVertexShaderConstant(getVertexShaderConstantID(name), ints, count); + } - virtual bool OnRender( IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype ) - { - return FixedPipeline->OnRender( service, vtxtype ); - } + bool setPixelShaderConstant(const c8* name, const f32* floats, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), floats, count); + } - protected: + bool setPixelShaderConstant(const c8* name, const s32* ints, int count) + { + return setPixelShaderConstant(getPixelShaderConstantID(name), ints, count); + } - video::COGLES2Driver* Driver; - COGLES2FixedPipelineShader* FixedPipeline; + virtual IVideoDriver* getVideoDriver(); + +protected: + + //! constructor only for use by derived classes who want to + //! create a fall back material for example. + COGLES2MaterialRenderer(COGLES2Driver* driver, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = EMT_SOLID, + s32 userData = 0); + + void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram, bool addMaterial = true); + + bool createShader(GLenum shaderType, const char* shader); + bool linkProgram(); + + COGLES2Driver* Driver; + IShaderConstantSetCallBack* CallBack; + + bool Alpha; + bool Blending; + bool FixedBlending; + + struct SUniformInfo + { + core::stringc name; + GLenum type; + GLint location; }; + GLuint Program; + core::array UniformInfo; + s32 UserData; +}; - //! Solid material renderer - class COGLES2MaterialRenderer_SOLID : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_SOLID(video::COGLES2Driver* d) : - COGLES2MaterialRenderer(d) - { - } - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services) - { - if (resetAllRenderstates || (material.MaterialType != lastMaterial.MaterialType)) - { - FixedPipeline->useProgram(); - FixedPipeline->setRenderMode(EMT_SOLID); - } - FixedPipeline->setMaterial(material); - Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); - } - }; - - - //! Generic Texture Blend - class COGLES2MaterialRenderer_ONETEXTURE_BLEND : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_ONETEXTURE_BLEND( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - Driver->disableTextures( 1 ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - FixedPipeline->setMaterial( material ); - FixedPipeline->useProgram(); - -// if (material.MaterialType != lastMaterial.MaterialType || -// material.MaterialTypeParam != lastMaterial.MaterialTypeParam || -// resetAllRenderstates) - { - E_BLEND_FACTOR srcFact, dstFact; - E_MODULATE_FUNC modulate; - u32 alphaSource; - unpack_textureBlendFunc( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); - - //TODO : OpenGL ES 2.0 Port glTexEnvf - //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - //glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS); - //rgbModulatePreviousTexture - - //glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, (f32) modulate ); - - //glBlendFunc( getGLBlend(srcFact), getGLBlend(dstFact) ); - FixedPipeline->enableAlphaTest(); - FixedPipeline->setAlphaValue( 0.f ); - Driver->enableBlend(); - Driver->blendFunc( srcFact, dstFact ); - if (alphaSource&EAS_TEXTURE) - FixedPipeline->setRenderMode( EMT_TRANSPARENT_ALPHA_CHANNEL ); - else - FixedPipeline->setRenderMode( EMT_TRANSPARENT_VERTEX_ALPHA ); - - if ( textureBlendFunc_hasAlpha( srcFact ) || textureBlendFunc_hasAlpha( dstFact ) ) - { - //TODO : OpenGL ES 2.0 Port glTexEnvf - //glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); - - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); - } - } - } - - virtual void OnUnsetMaterial() - { - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - //glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.f ); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS); - - Driver->disableBlend(); - FixedPipeline->disableAlphaTest(); - } - - //! Returns if the material is transparent. - /** Is not always transparent, but mostly. */ - virtual bool isTransparent() const - { - return true; - } - }; - - - //! Solid 2 layer material renderer - class COGLES2MaterialRenderer_SOLID_2_LAYER : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_SOLID_2_LAYER( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - Driver->disableTextures( 2 ); - Driver->setActiveTexture( 1, material.getTexture( 1 ) ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - if ( Driver->queryFeature( EVDF_MULTITEXTURE ) ) - { - //Driver->extGlActiveTexture(GL_TEXTURE1); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - //glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PRIMARY_COLOR); - //glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); - //glTexEnvf(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PRIMARY_COLOR); - //glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); - } - } - } - - virtual void OnUnsetMaterial() - { - if ( Driver->queryFeature( EVDF_MULTITEXTURE ) ) - { - //Driver->extGlActiveTexture(GL_TEXTURE1); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - //glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - //Driver->extGlActiveTexture(GL_TEXTURE0); - } - } - }; - - - //! Transparent add color material renderer - class COGLES2MaterialRenderer_TRANSPARENT_ADD_COLOR : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_TRANSPARENT_ADD_COLOR( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - if (( material.MaterialType != lastMaterial.MaterialType ) || resetAllRenderstates ) - { - Driver->blendFunc( EBF_ONE, EBF_ONE_MINUS_SRC_COLOR ); - Driver->enableBlend(); - FixedPipeline->useProgram(); - FixedPipeline->setRenderMode( EMT_SOLID ); - } - FixedPipeline->setMaterial( material ); - Driver->disableTextures( 1 ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - } - - virtual void OnUnsetMaterial() - { - Driver->disableBlend(); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } - }; - - - //! Transparent vertex alpha material renderer - class COGLES2MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_TRANSPARENT_VERTEX_ALPHA( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - Driver->blendFunc( EBF_ONE, EBF_ONE_MINUS_SRC_ALPHA ); - Driver->enableBlend(); - FixedPipeline->useProgram(); - FixedPipeline->setRenderMode( EMT_TRANSPARENT_VERTEX_ALPHA ); - } - FixedPipeline->setMaterial( material ); - Driver->disableTextures( 1 ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - } - - virtual void OnUnsetMaterial() - { - Driver->disableBlend(); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } - }; - - - //! Transparent alpha channel material renderer - class COGLES2MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - Driver->disableTextures( 1 ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates - || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) - { - Driver->blendFunc( EBF_SRC_ALPHA, EBF_ONE_MINUS_SRC_ALPHA ); - Driver->enableBlend(); - FixedPipeline->useProgram(); - FixedPipeline->setMaterial( material ); - FixedPipeline->enableAlphaTest(); - - FixedPipeline->setAlphaValue( material.MaterialTypeParam ); - FixedPipeline->setRenderMode( EMT_TRANSPARENT_ALPHA_CHANNEL ); - } - } - - virtual void OnUnsetMaterial() - { - FixedPipeline->disableAlphaTest(); - Driver->disableBlend(); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } - }; - - - //! Transparent alpha channel material renderer - class COGLES2MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - Driver->disableTextures( 1 ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - FixedPipeline->enableAlphaTest(); - FixedPipeline->setAlphaValue( 0.5f ); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } - } - - virtual void OnUnsetMaterial() - { - FixedPipeline->disableAlphaTest(); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return false; // this material is not really transparent because it does no blending. - } - }; - - - //! material renderer for all kinds of lightmaps - class COGLES2MaterialRenderer_LIGHTMAP : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_LIGHTMAP( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - FixedPipeline->useProgram(); - FixedPipeline->setRenderMode( EMT_LIGHTMAP ); - } - FixedPipeline->setMaterial( material ); - Driver->disableTextures( 2 ); - Driver->setActiveTexture( 1, material.getTexture( 1 ) ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - // diffuse map - - switch ( material.MaterialType ) - { - case EMT_LIGHTMAP_LIGHTING: - case EMT_LIGHTMAP_LIGHTING_M2: - case EMT_LIGHTMAP_LIGHTING_M4: - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - break; - case EMT_LIGHTMAP_ADD: - case EMT_LIGHTMAP: - case EMT_LIGHTMAP_M2: - case EMT_LIGHTMAP_M4: - default: - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - break; - } - - if ( Driver->queryFeature( EVDF_MULTITEXTURE ) ) - { - // lightmap - - //Driver->extGlActiveTexture(GL_TEXTURE1); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - - if ( material.MaterialType == EMT_LIGHTMAP_ADD ) - { - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD_SIGNED); - } - else - { - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - } - - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - //glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); - - //glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - //glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - //glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS); - - switch ( material.MaterialType ) - { - case EMT_LIGHTMAP_M4: - case EMT_LIGHTMAP_LIGHTING_M4: - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 4.0f); - break; - case EMT_LIGHTMAP_M2: - case EMT_LIGHTMAP_LIGHTING_M2: - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 2.0f); - break; - default: - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.0f); - break; - } - } - } - } - - virtual void OnUnsetMaterial() - { - if ( Driver->queryFeature( EVDF_MULTITEXTURE ) ) - { - //Driver->extGlActiveTexture(GL_TEXTURE1); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE, 1.f ); - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - //Driver->extGlActiveTexture(GL_TEXTURE0); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - } - }; - - - //! detail map material renderer - class COGLES2MaterialRenderer_DETAIL_MAP : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_DETAIL_MAP( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - FixedPipeline->useProgram(); - FixedPipeline->setRenderMode( EMT_DETAIL_MAP ); - } - FixedPipeline->setMaterial( material ); - Driver->disableTextures( 2 ); - Driver->setActiveTexture( 1, material.getTexture( 1 ) ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - } - }; - - - //! sphere map material renderer - class COGLES2MaterialRenderer_SPHERE_MAP : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_SPHERE_MAP( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - FixedPipeline->useProgram(); - FixedPipeline->setRenderMode( EMT_SPHERE_MAP ); - } - FixedPipeline->setMaterial( material ); - Driver->disableTextures( 1 ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - } - - virtual void OnUnsetMaterial() - { - } - }; - - - //! reflection 2 layer material renderer - class COGLES2MaterialRenderer_REFLECTION_2_LAYER : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_REFLECTION_2_LAYER( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - FixedPipeline->useProgram(); - FixedPipeline->setRenderMode( EMT_REFLECTION_2_LAYER ); - } - FixedPipeline->setMaterial( material ); - Driver->disableTextures( 2 ); - Driver->setActiveTexture( 0, material.getTexture( 1 ) ); - Driver->setActiveTexture( 1, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - } - }; - - - //! reflection 2 layer material renderer - class COGLES2MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public COGLES2MaterialRenderer - { - public: - - COGLES2MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER( video::COGLES2Driver* d ) - : COGLES2MaterialRenderer( d ) {} - - virtual void OnSetMaterial( const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services ) - { - Driver->disableTextures( 2 ); - Driver->setActiveTexture( 1, material.getTexture( 1 ) ); - Driver->setActiveTexture( 0, material.getTexture( 0 ) ); - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - if ( Driver->queryFeature( EVDF_MULTITEXTURE ) ) - { - //Driver->extGlActiveTexture(GL_TEXTURE1); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - //glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); - //glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); - } -// glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); -// glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); -// glEnable(GL_TEXTURE_GEN_S); -// glEnable(GL_TEXTURE_GEN_T); - - Driver->blendFunc( EBF_ONE, EBF_ONE_MINUS_SRC_ALPHA ); - Driver->enableBlend(); - } - } - - virtual void OnUnsetMaterial() - { - if ( Driver->queryFeature( EVDF_MULTITEXTURE ) ) - { - //Driver->extGlActiveTexture(GL_TEXTURE1); - //TODO : OpenGL ES 2.0 Port glTexEnv - //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } -// glDisable(GL_TEXTURE_GEN_S); -// glDisable(GL_TEXTURE_GEN_T); - if ( Driver->queryFeature( EVDF_MULTITEXTURE ) ) - { - //Driver->extGlActiveTexture(GL_TEXTURE0); - } - Driver->disableBlend(); - } - - //! Returns if the material is transparent. - virtual bool isTransparent() const - { - return true; - } - }; } // end namespace video } // end namespace irr -#endif -#endif - +#endif // compile with OpenGL ES 2.0 +#endif // if included diff --git a/source/Irrlicht/COGLES2NormalMapRenderer.cpp b/source/Irrlicht/COGLES2NormalMapRenderer.cpp index 9d393058..71db2240 100644 --- a/source/Irrlicht/COGLES2NormalMapRenderer.cpp +++ b/source/Irrlicht/COGLES2NormalMapRenderer.cpp @@ -1,160 +1,76 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h + #include "IrrCompileConfig.h" + #ifdef _IRR_COMPILE_WITH_OGLES2_ #include "COGLES2NormalMapRenderer.h" #include "IGPUProgrammingServices.h" -#include "IShaderConstantSetCallBack.h" -#include "IVideoDriver.h" #include "os.h" #include "COGLES2Driver.h" -#include "COGLES2Utils.h" - -#define MAX_LIGHTS 2 namespace irr { namespace video { - const char* const COGLES2NormalMapRenderer::sBuiltInShaderUniformNames[] = +//! Constructor +COGLES2NormalMapRenderer::COGLES2NormalMapRenderer(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, E_MATERIAL_TYPE baseMaterial, + COGLES2Driver* driver) + : COGLES2MaterialRenderer(driver, 0, baseMaterial) +{ + #ifdef _DEBUG + setDebugName("COGLES2NormalMapRenderer"); + #endif + + int Temp = 0; + + SharedRenderer = reinterpret_cast(driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID)); + + if (SharedRenderer) + SharedRenderer->grab(); + else + init(Temp, vertexShaderProgram, pixelShaderProgram, false); +} + + +//! Destructor +COGLES2NormalMapRenderer::~COGLES2NormalMapRenderer() +{ + if(SharedRenderer) + SharedRenderer->drop(); +} + + +void COGLES2NormalMapRenderer::OnSetMaterial(const video::SMaterial& material, + const video::SMaterial& lastMaterial, + bool resetAllRenderstates, + video::IMaterialRendererServices* services) +{ + if (SharedRenderer) + SharedRenderer->OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); + else + COGLES2MaterialRenderer::OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); +} + + +bool COGLES2NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) +{ + if (SharedRenderer) + return SharedRenderer->OnRender(service, vtxtype); + else { - "uMvpMatrix", - "uLightPos", - "uLightColor", - "texture0", - "texture1", - 0 - }; + /* Vertex Shader part */ - // Irrlicht Engine OGLES2 render path normal map vertex shader - const c8 VertexShaderFile[] = IRR_OGLES2_SHADER_PATH "COGLES2NormalMap.vsh"; - const c8 FragmentShaderFile[] = IRR_OGLES2_SHADER_PATH "COGLES2NormalMap.fsh"; - - - //! Constructor - COGLES2NormalMapRenderer::COGLES2NormalMapRenderer( video::COGLES2Driver* driver, - io::IFileSystem* fs, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial ) - : COGLES2SLMaterialRenderer( driver, fs, 0, baseMaterial, sBuiltInShaderUniformNames, UNIFORM_COUNT ), CompiledShaders( true ) - { - -#ifdef _DEBUG - setDebugName( "COGLES2NormalMapRenderer" ); -#endif - - // set this as callback. We could have done this in - // the initialization list, but some compilers don't like it. - - CallBack = this; - - // check if already compiled normal map shaders are there. - - video::IMaterialRenderer* renderer = driver->getMaterialRenderer( EMT_NORMAL_MAP_SOLID ); - - if ( renderer ) - { - // use the already compiled shaders - video::COGLES2NormalMapRenderer* nmr = reinterpret_cast( renderer ); - CompiledShaders = false; - - Program = nmr->Program; - - UniformInfo = nmr->UniformInfo; - AttributeInfo = nmr->AttributeInfo; - - outMaterialTypeNr = driver->addMaterialRenderer( this ); - } - else - { - // compile shaders on our own - if (initFromFiles(outMaterialTypeNr, VertexShaderFile, FragmentShaderFile)) - { - useProgram(); - int dummy = 0; - setUniform( TEXTURE_UNIT0, &dummy ); - dummy = 1; - setUniform( TEXTURE_UNIT1, &dummy ); - } - } - - // fallback if compilation has failed - if ( -1 == outMaterialTypeNr ) - outMaterialTypeNr = driver->addMaterialRenderer( this ); - } - - COGLES2NormalMapRenderer::~COGLES2NormalMapRenderer() - { - if ( CallBack == this ) - CallBack = 0; - if ( !CompiledShaders ) - { - // prevent this from deleting shaders we did not create - Program = 0; - } - } - - //! Returns the render capability of the material. - s32 COGLES2NormalMapRenderer::getRenderCapability() const - { - if ( Driver->queryFeature( video::EVDF_ARB_FRAGMENT_PROGRAM_1 ) && - Driver->queryFeature( video::EVDF_ARB_VERTEX_PROGRAM_1 ) ) - return 0; - - return 1; - } - - - //! Called by the engine when the vertex and/or pixel shader constants - //! for an material renderer should be set. - void COGLES2NormalMapRenderer::OnSetConstants( IMaterialRendererServices* services, s32 userData ) - { - video::IVideoDriver* driver = services->getVideoDriver(); - - // set transposed worldViewProj matrix - core::matrix4 worldViewProj( driver->getTransform( video::ETS_PROJECTION ) ); - worldViewProj *= driver->getTransform( video::ETS_VIEW ); - worldViewProj *= driver->getTransform( video::ETS_WORLD ); - setUniform( MVP_MATRIX, worldViewProj.pointer() ); - - // here we fetch the fixed function lights from the driver - // and set them as constants - - u32 cnt = driver->getDynamicLightCount(); - - // Load the inverse world matrix. - core::matrix4 invWorldMat; - driver->getTransform( video::ETS_WORLD ).getInverse( invWorldMat ); - - float lightPosition[4*MAX_LIGHTS]; - float lightColor[4*MAX_LIGHTS]; - - for ( u32 i = 0; i < MAX_LIGHTS; ++i ) - { - video::SLight light; - - if ( i < cnt ) - light = driver->getDynamicLight( i ); - else - { - light.DiffuseColor.set( 0, 0, 0 ); // make light dark - light.Radius = 1.0f; - } - - light.DiffuseColor.a = 1.0f / ( light.Radius * light.Radius ); // set attenuation - - // Transform the light by the inverse world matrix to get it into object space. - invWorldMat.transformVect( light.Position ); - - memcpy( lightPosition + i*4, &light.Position, sizeof( float )*4 ); - memcpy( lightColor + i*4, &light.DiffuseColor, sizeof( float )*4 ); - } - setUniform( LIGHT_POSITION, lightPosition, MAX_LIGHTS ); - setUniform( LIGHT_COLOR, lightColor, MAX_LIGHTS ); + return true; } +} } // end namespace video @@ -162,4 +78,3 @@ namespace video #endif - diff --git a/source/Irrlicht/COGLES2NormalMapRenderer.h b/source/Irrlicht/COGLES2NormalMapRenderer.h index 55299a5a..a79904d1 100644 --- a/source/Irrlicht/COGLES2NormalMapRenderer.h +++ b/source/Irrlicht/COGLES2NormalMapRenderer.h @@ -1,6 +1,7 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h @@ -8,51 +9,37 @@ #define __C_OGLES2_NORMAL_MAP_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" + #ifdef _IRR_COMPILE_WITH_OGLES2_ -#include "COGLES2SLMaterialRenderer.h" -#include "IShaderConstantSetCallBack.h" +#include "COGLES2MaterialRenderer.h" namespace irr { namespace video { - //! Class for rendering normal maps with OGLES2 - class COGLES2NormalMapRenderer : public COGLES2SLMaterialRenderer, public IShaderConstantSetCallBack - { - public: +//! Class for normal mapping in OpenGL ES 2.0 +class COGLES2NormalMapRenderer : public COGLES2MaterialRenderer +{ +public: + //! Constructor + COGLES2NormalMapRenderer(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, E_MATERIAL_TYPE baseMaterial, + COGLES2Driver* driver); - //! Constructor - COGLES2NormalMapRenderer(video::COGLES2Driver* driver, io::IFileSystem* fs, - s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial); + //! Destructor + ~COGLES2NormalMapRenderer(); - //! Destructor - virtual ~COGLES2NormalMapRenderer(); + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services); - //! Called by the engine when the vertex and/or pixel shader constants for an - //! material renderer should be set. - virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); - //! Returns the render capability of the material. - virtual s32 getRenderCapability() const; +protected: - protected: - - bool CompiledShaders; - - private: - enum SHADER_UNIFORM - { - MVP_MATRIX = 0, - LIGHT_POSITION, - LIGHT_COLOR, - TEXTURE_UNIT0, - TEXTURE_UNIT1, - UNIFORM_COUNT - }; - static const char* const sBuiltInShaderUniformNames[]; - }; + COGLES2MaterialRenderer* SharedRenderer; +}; } // end namespace video diff --git a/source/Irrlicht/COGLES2ParallaxMapRenderer.cpp b/source/Irrlicht/COGLES2ParallaxMapRenderer.cpp index d52225fb..a8bc674c 100644 --- a/source/Irrlicht/COGLES2ParallaxMapRenderer.cpp +++ b/source/Irrlicht/COGLES2ParallaxMapRenderer.cpp @@ -1,187 +1,76 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h #include "IrrCompileConfig.h" + #ifdef _IRR_COMPILE_WITH_OGLES2_ #include "COGLES2ParallaxMapRenderer.h" -#include "COGLES2Driver.h" #include "IGPUProgrammingServices.h" -#include "IShaderConstantSetCallBack.h" -#include "IVideoDriver.h" #include "os.h" - -#define MAX_LIGHTS 2 +#include "COGLES2Driver.h" namespace irr { namespace video { - const char * const COGLES2ParallaxMapRenderer::sBuiltInShaderUniformNames[] = +//! Constructor +COGLES2ParallaxMapRenderer::COGLES2ParallaxMapRenderer(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, E_MATERIAL_TYPE baseMaterial, + COGLES2Driver* driver) + : COGLES2MaterialRenderer(driver, 0, baseMaterial) +{ + #ifdef _DEBUG + setDebugName("COGLES2ParallaxMapRenderer"); + #endif + + int Temp = 0; + + SharedRenderer = reinterpret_cast(driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID)); + + if (SharedRenderer) + SharedRenderer->grab(); + else + init(Temp, vertexShaderProgram, pixelShaderProgram, false); +} + + +//! Destructor +COGLES2ParallaxMapRenderer::~COGLES2ParallaxMapRenderer() +{ + if(SharedRenderer) + SharedRenderer->drop(); +} + + +void COGLES2ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material, + const video::SMaterial& lastMaterial, + bool resetAllRenderstates, + video::IMaterialRendererServices* services) +{ + if (SharedRenderer) + SharedRenderer->OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); + else + COGLES2MaterialRenderer::OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); +} + + +bool COGLES2ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) +{ + if (SharedRenderer) + return SharedRenderer->OnRender(service, vtxtype); + else { - "uMvpMatrix", - "uLightPos", - "uLightColor", - "uEyePos", - "texture0", - "texture1", - "uLightDiffuse", - "uHeightScale", - 0 - }; + /* Vertex Shader part */ - // Irrlicht Engine OGLES2 render path normal map vertex shader - const c8 VertexShaderFile[] = IRR_OGLES2_SHADER_PATH "COGLES2ParallaxMap.vsh"; - const c8 FragmentShaderFile[] = IRR_OGLES2_SHADER_PATH "COGLES2ParallaxMap.fsh"; - - //! Constructor - COGLES2ParallaxMapRenderer::COGLES2ParallaxMapRenderer( video::COGLES2Driver* driver, - io::IFileSystem* fs, s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial ) - : COGLES2SLMaterialRenderer( driver, fs, 0, baseMaterial, sBuiltInShaderUniformNames, UNIFORM_COUNT ), CompiledShaders( true ) - { - -#ifdef _DEBUG - setDebugName( "COGLES2ParallaxMapRenderer" ); -#endif - - // set this as callback. We could have done this in - // the initialization list, but some compilers don't like it. - - CallBack = this; - - // basically, this simply compiles the hard coded shaders if the - // hardware is able to do them, otherwise it maps to the base material - - // check if already compiled normal map shaders are there. - - video::IMaterialRenderer* renderer = driver->getMaterialRenderer( EMT_PARALLAX_MAP_SOLID ); - - if ( renderer ) - { - // use the already compiled shaders - video::COGLES2ParallaxMapRenderer* pmr = reinterpret_cast( renderer ); - CompiledShaders = false; - - Program = pmr->Program; - - UniformInfo = pmr->UniformInfo; - AttributeInfo = pmr->AttributeInfo; - - outMaterialTypeNr = driver->addMaterialRenderer( this ); - } - else - { - // compile shaders on our own - if (initFromFiles( outMaterialTypeNr, VertexShaderFile, FragmentShaderFile)) - { - useProgram(); - int dummy = 0; - setUniform( TEXTURE_UNIT0, &dummy ); - dummy = 1; - setUniform( TEXTURE_UNIT1, &dummy ); - } - } - - // fallback if compilation has failed - if ( -1 == outMaterialTypeNr ) - outMaterialTypeNr = driver->addMaterialRenderer( this ); - } - - - //! Destructor - COGLES2ParallaxMapRenderer::~COGLES2ParallaxMapRenderer() - { - if ( CallBack == this ) - CallBack = 0; - - if ( !CompiledShaders ) - { - // prevent this from deleting shaders we did not create - Program = 0; - } - } - - - void COGLES2ParallaxMapRenderer::OnSetMaterial( - const video::SMaterial& material, const video::SMaterial& lastMaterial, - bool resetAllRenderstates, video::IMaterialRendererServices* services ) - { - COGLES2SLMaterialRenderer::OnSetMaterial(material, lastMaterial, - resetAllRenderstates, services); - - CurrentScale = material.MaterialTypeParam; - } - - //! Called by the engine when the vertex and/or pixel shader constants for an - //! material renderer should be set. - void COGLES2ParallaxMapRenderer::OnSetConstants( IMaterialRendererServices* services, s32 userData ) - { - video::IVideoDriver* driver = services->getVideoDriver(); - - // set transposed worldViewProj matrix - core::matrix4 worldViewProj( driver->getTransform( video::ETS_PROJECTION ) ); - worldViewProj *= driver->getTransform( video::ETS_VIEW ); - worldViewProj *= driver->getTransform( video::ETS_WORLD ); - - setUniform( MVP_MATRIX, worldViewProj.pointer() ); - - - // here we fetch the fixed function lights from the driver - // and set them as constants - - u32 cnt = driver->getDynamicLightCount(); - - // Load the inverse world matrix. - core::matrix4 invWorldMat; - driver->getTransform( video::ETS_WORLD ).getInverse( invWorldMat ); - - float lightPosition[4*MAX_LIGHTS]; - float lightColor[4*MAX_LIGHTS]; - - for ( u32 i = 0; i < 2; ++i ) - { - video::SLight light; - - if ( i < cnt ) - light = driver->getDynamicLight( i ); - else - { - light.DiffuseColor.set( 0, 0, 0 ); // make light dark - light.Radius = 1.0f; - } - - light.DiffuseColor.a = 1.0f / ( light.Radius * light.Radius ); // set attenuation - - // Transform the light by the inverse world matrix to get it into object space. - invWorldMat.transformVect( light.Position ); - - memcpy( lightPosition + i*4, &light.Position, sizeof( float )*4 ); - memcpy( lightColor + i*4, &light.DiffuseColor, sizeof( float )*4 ); - } - - setUniform( LIGHT_POSITION, lightPosition, MAX_LIGHTS ); - setUniform( LIGHT_COLOR, lightColor, MAX_LIGHTS ); - - // Obtain the view position by transforming 0,0,0 by the inverse view matrix - // and then multiply this by the inverse world matrix. - core::vector3df viewPos( 0.0f, 0.0f, 0.0f ); - core::matrix4 inverseView; - driver->getTransform( video::ETS_VIEW ).getInverse( inverseView ); - inverseView.transformVect( viewPos ); - invWorldMat.transformVect( viewPos ); - setUniform( EYE_POSITION, &viewPos.X ); - - // set scale factor - f32 factor = 0.02f; // default value - if ( CurrentScale != 0.0f ) - factor = CurrentScale; - - setUniform( HEIGHT_SCALE, &factor ); + return true; } +} } // end namespace video @@ -189,4 +78,3 @@ namespace video #endif - diff --git a/source/Irrlicht/COGLES2ParallaxMapRenderer.h b/source/Irrlicht/COGLES2ParallaxMapRenderer.h index 5a2c7972..eb1738c9 100644 --- a/source/Irrlicht/COGLES2ParallaxMapRenderer.h +++ b/source/Irrlicht/COGLES2ParallaxMapRenderer.h @@ -1,6 +1,7 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h @@ -8,57 +9,37 @@ #define __C_OGLES2_PARALLAX_MAP_RENDERER_H_INCLUDED__ #include "IrrCompileConfig.h" + #ifdef _IRR_COMPILE_WITH_OGLES2_ -#include "COGLES2SLMaterialRenderer.h" -#include "IShaderConstantSetCallBack.h" +#include "COGLES2MaterialRenderer.h" namespace irr { namespace video { - //! Class for rendering normal maps with OGLES2 - class COGLES2ParallaxMapRenderer : public COGLES2SLMaterialRenderer, public IShaderConstantSetCallBack - { - public: +//! Class for parallax mapping in OpenGL ES 2.0 +class COGLES2ParallaxMapRenderer : public COGLES2MaterialRenderer +{ +public: + //! Constructor + COGLES2ParallaxMapRenderer(const c8* vertexShaderProgram, + const c8* pixelShaderProgram, E_MATERIAL_TYPE baseMaterial, + COGLES2Driver* driver); - //! Constructor - COGLES2ParallaxMapRenderer( video::COGLES2Driver* driver, io::IFileSystem* fs, - s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial ); + //! Destructor + ~COGLES2ParallaxMapRenderer(); - //! Destructor - virtual ~COGLES2ParallaxMapRenderer(); + virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates, IMaterialRendererServices* services); - //! Called by the engine when the vertex and/or pixel shader constants for an - //! material renderer should be set. - virtual void OnSetConstants( IMaterialRendererServices* services, s32 userData ); + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); - virtual void OnSetMaterial( const SMaterial& material ) { } - virtual void OnSetMaterial( const video::SMaterial& material, - const video::SMaterial& lastMaterial, - bool resetAllRenderstates, video::IMaterialRendererServices* services ); +protected: - protected: - - bool CompiledShaders; - f32 CurrentScale; - - private: - enum SHADER_UNIFORM - { - MVP_MATRIX = 0, - LIGHT_POSITION, - LIGHT_COLOR, - EYE_POSITION, - TEXTURE_UNIT0, - TEXTURE_UNIT1, - LIGHT_DIFFUSE, - HEIGHT_SCALE, - UNIFORM_COUNT - }; - static const char* const sBuiltInShaderUniformNames[]; - }; + COGLES2MaterialRenderer* SharedRenderer; +}; } // end namespace video @@ -67,3 +48,4 @@ namespace video #endif #endif + diff --git a/source/Irrlicht/COGLES2Renderer2D.cpp b/source/Irrlicht/COGLES2Renderer2D.cpp index d3d5693b..0f3e423e 100644 --- a/source/Irrlicht/COGLES2Renderer2D.cpp +++ b/source/Irrlicht/COGLES2Renderer2D.cpp @@ -27,55 +27,55 @@ namespace video static const char* fragmentShaderFile = IRR_OGLES2_SHADER_PATH "COGLES2Renderer2D.fsh"; COGLES2Renderer2d::COGLES2Renderer2d( irr::video::COGLES2Driver *driver, irr::io::IFileSystem *fs ) - : COGLES2SLMaterialRenderer( driver, fs, 0, 0, sBuiltInShaderUniformNames, UNIFORM_COUNT ) + : COGLES2MaterialRenderer( driver ) { #ifdef _DEBUG setDebugName( "COGLES2Renderer2d" ); #endif - s32 dummy = -1; + /*s32 dummy = -1; if (!initFromFiles( dummy, vertexShaderFile, fragmentShaderFile, false)) return; useProgram(); int texUnit = 0; - setUniform( TEXTURE_UNIT, &texUnit ); + setUniform( TEXTURE_UNIT, &texUnit );*/ } void COGLES2Renderer2d::useTexture( bool param ) { - if ( param != UseTexture ) + /*if ( param != UseTexture ) { UseTexture = param; int dummy = param ? 1 : 0; setUniform( USE_TEXTURE, &dummy ); - } + }*/ } void COGLES2Renderer2d::useAlphaTest( bool param ) { - if ( param != UseAlphaTest ) + /*if ( param != UseAlphaTest ) { UseAlphaTest = param; int dummy = param ? 1 : 0; setUniform( ALPHA_TEST, &dummy ); - } + }*/ } void COGLES2Renderer2d::setAlphaTestValue( float value ) { - if ( value != AlphaTestValue ) + /*if ( value != AlphaTestValue ) { AlphaTestValue = value; setUniform( ALPHA_VALUE, &AlphaTestValue ); - } + }*/ } void COGLES2Renderer2d::setOrthoMatrix( const core::matrix4 &matrix ) { - if ( matrix != OrthoMatrix ) + /*if ( matrix != OrthoMatrix ) { OrthoMatrix = matrix; setUniform( ORTHO_MATRIX, OrthoMatrix.pointer() ); - } + }*/ } } } diff --git a/source/Irrlicht/COGLES2Renderer2D.h b/source/Irrlicht/COGLES2Renderer2D.h index ed7d98e5..907b112b 100644 --- a/source/Irrlicht/COGLES2Renderer2D.h +++ b/source/Irrlicht/COGLES2Renderer2D.h @@ -7,7 +7,7 @@ #ifndef __C_OGLES2_RENDERER_2D_H_INCLUDED__ #define __C_OGLES2_RENDERER_2D_H_INCLUDED__ -#include "COGLES2SLMaterialRenderer.h" +#include "COGLES2MaterialRenderer.h" #ifdef _IRR_COMPILE_WITH_OGLES2_ @@ -21,7 +21,7 @@ namespace video { class COGLES2Driver; - class COGLES2Renderer2d : public COGLES2SLMaterialRenderer + class COGLES2Renderer2d : public COGLES2MaterialRenderer { public: COGLES2Renderer2d( COGLES2Driver* driver, io::IFileSystem* fs ); diff --git a/source/Irrlicht/COGLES2SLMaterialRenderer.cpp b/source/Irrlicht/COGLES2SLMaterialRenderer.cpp deleted file mode 100644 index 636a7a5c..00000000 --- a/source/Irrlicht/COGLES2SLMaterialRenderer.cpp +++ /dev/null @@ -1,646 +0,0 @@ -// Copyright (C) 2009-2010 Amundis -// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h - -#include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_OGLES2_ - -#include "COGLES2SLMaterialRenderer.h" -#include "IGPUProgrammingServices.h" -#include "IShaderConstantSetCallBack.h" -#include "IMaterialRendererServices.h" -#include "IVideoDriver.h" -#include "os.h" -#include "COGLES2Driver.h" -#include "EVertexAttributes.h" -#include "COGLES2Texture.h" - -#if !defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) -#include -#endif - -namespace irr -{ -namespace video -{ - - //! Constructor - COGLES2SLMaterialRenderer::COGLES2SLMaterialRenderer( video::COGLES2Driver* driver, - s32& outMaterialTypeNr, const c8* vertexShaderProgram, - const c8* pixelShaderProgram, - IShaderConstantSetCallBack* callback, - video::IMaterialRenderer* baseMaterial, s32 userData ) - : Driver( driver ), CallBack( callback ), BaseMaterial( baseMaterial ), FileSystem( 0 ), - Program( 0 ), UserData( userData ), UniformStringTable( 0 ), UniformCount( 0 ) - { -#ifdef _DEBUG - setDebugName( "COGLES2SLMaterialRenderer" ); -#endif - - //entry points must always be main, and the compile target isn't selectable - //it is fine to ignore what has been asked for, as the compiler should spot anything wrong - //just check that GLSL is available - - if ( BaseMaterial ) - BaseMaterial->grab(); - - if ( CallBack ) - CallBack->grab(); - - init( outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram ); - } - - - //! constructor only for use by derived classes who want to - //! create a fall back material for example. - COGLES2SLMaterialRenderer::COGLES2SLMaterialRenderer( COGLES2Driver* driver, - io::IFileSystem* fs, IShaderConstantSetCallBack* callback, - IMaterialRenderer* baseMaterial, const char* const * uniformStringTable, - const u32& uniformCount, s32 userData ) - : Driver( driver ), CallBack( callback ), BaseMaterial( baseMaterial ), FileSystem( fs ), - Program( 0 ), UserData( userData ), UniformStringTable( uniformStringTable ), - UniformCount( uniformCount ) - { - if ( BaseMaterial ) - BaseMaterial->grab(); - - if ( CallBack ) - CallBack->grab(); - } - - - //! Destructor - COGLES2SLMaterialRenderer::~COGLES2SLMaterialRenderer() - { - if ( CallBack ) - CallBack->drop(); - - if ( Program ) - { - glDeleteProgram( Program ); - Program = 0; - } - - UniformInfo.clear(); - - AttributeInfo.clear(); - - if ( BaseMaterial ) - BaseMaterial->drop(); - } - - bool COGLES2SLMaterialRenderer::init(s32& outMaterialTypeNr, - const c8* vertexShaderProgram, - const c8* pixelShaderProgram, - bool registerMaterial ) - { - outMaterialTypeNr = -1; - - if ( Program == 0 && !createProgram() ) - return false; - - if ( vertexShaderProgram ) - if ( !createShader( GL_VERTEX_SHADER, vertexShaderProgram, "" ) ) - return false; - - if ( pixelShaderProgram ) - if ( !createShader( GL_FRAGMENT_SHADER, pixelShaderProgram, "" ) ) - return false; - - for ( size_t i = 0; i < EVA_COUNT; ++i ) - glBindAttribLocation( Program, i, sBuiltInVertexAttributeNames[i] ); - - if ( !linkProgram() ) - return false; - - // register myself as new material - if ( registerMaterial ) - outMaterialTypeNr = Driver->addMaterialRenderer( this ); - return true; - } - - bool COGLES2SLMaterialRenderer::initFromFiles( s32 &outMaterialTypeNr, - const c8 *vertexShaderFile, - const c8 *pixelShaderFile, - bool registerMaterial ) - { - outMaterialTypeNr = -1; - if ( !createProgram() ) - { - os::Printer::log( "Could not create shader program.", ELL_ERROR ); - return false; - } - - if ( !readVertexShader( vertexShaderFile ) ) - { - os::Printer::log( "Error reading fixed pipeline vertex shader.", ELL_ERROR ); - } - - if ( !readFragmentShader( pixelShaderFile ) ) - { - os::Printer::log( "Error reading fixed pipeline fragment shader.", ELL_ERROR ); - } - - for ( size_t i = 0; i < EVA_COUNT; ++i ) - glBindAttribLocation( Program, i, sBuiltInVertexAttributeNames[i] ); - - if ( !linkProgram() ) - { - os::Printer::log( "Error linking fixed pipeline shader program.", ELL_ERROR ); - return false; - } - - if ( registerMaterial ) - outMaterialTypeNr = Driver->addMaterialRenderer( this ); - return true; - } - - bool COGLES2SLMaterialRenderer::reloadFromFiles( const c8 *vertexShaderFile, - const c8 *pixelShaderFile ) - { - GLsizei shaderCount; - GLuint shaderHandles[2]; - glGetAttachedShaders( Program, 2, &shaderCount, shaderHandles ); - glDetachShader( Program, shaderHandles[0] ); - glDeleteShader( shaderHandles[0] ); - glDetachShader( Program, shaderHandles[1] ); - glDeleteShader( shaderHandles[1] ); - if ( !readVertexShader( vertexShaderFile ) ) - { - os::Printer::log( "Error reading fixed pipeline vertex shader.", ELL_ERROR ); - } - - if ( !readFragmentShader( pixelShaderFile ) ) - { - os::Printer::log( "Error reading fixed pipeline fragment shader.", ELL_ERROR ); - } - - if ( !linkProgram() ) - { - os::Printer::log( "Error linking fixed pipeline shader program.", ELL_ERROR ); - return false; - } - else - return true; - } - - - bool COGLES2SLMaterialRenderer::readShader( GLenum shaderType, const c8* shaderFile ) - { - io::IReadFile* file = FileSystem->createAndOpenFile(shaderFile); - if (!file) - { - os::Printer::log("Could not open shader file", shaderFile, ELL_ERROR); - return false; - } - const long size = file->getSize(); - if (!size) - { - os::Printer::log( "Shader file is empty", shaderFile, ELL_ERROR ); - file->drop(); - return false; - } - - c8* shader = new c8[size+1]; - file->read(shader, size); - shader[size] = 0; - - bool success = createShader(shaderType, shader, shaderFile); - file->drop(); - delete shader; - return success; - } - - bool COGLES2SLMaterialRenderer::readVertexShader( const c8 *vertexShaderFile ) - { - return readShader( GL_VERTEX_SHADER, vertexShaderFile ); - } - - bool COGLES2SLMaterialRenderer::readFragmentShader( const c8 *fragmentShaderFile ) - { - return readShader( GL_FRAGMENT_SHADER, fragmentShaderFile ); - } - - bool COGLES2SLMaterialRenderer::OnRender( IMaterialRendererServices* service, - E_VERTEX_TYPE vtxtype ) - { - // call callback to set shader constants and attributes - if ( CallBack && Program ) - { - CallBack->OnSetAttribute( this, UserData ); - CallBack->OnSetConstants( this, UserData ); - } - - return true; - } - - - bool COGLES2SLMaterialRenderer::PostRender( IMaterialRendererServices* service, - E_VERTEX_TYPE vtxtype ) - { - // call callback to unset shader attributes - if ( CallBack && Program ) - CallBack->OnUnSetAttribute( this, UserData ); - - return true; - } - - void COGLES2SLMaterialRenderer::OnSetMaterial( const video::SMaterial& material, - const video::SMaterial& lastMaterial, - bool resetAllRenderstates, - video::IMaterialRendererServices* services ) - { - if ( material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates ) - { - if ( Program ) - glUseProgram( Program ); - - //let callback know used material - if ( CallBack ) - CallBack->OnSetMaterial( material ); - } - - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - } - - - void COGLES2SLMaterialRenderer::OnUnsetMaterial() - { - glUseProgram( 0 ); - - //if (BaseMaterial) - // BaseMaterial->OnUnsetMaterial(); - } - - //! Returns if the material is transparent. - bool COGLES2SLMaterialRenderer::isTransparent() const - { - return BaseMaterial ? BaseMaterial->isTransparent() : false; - } - - bool COGLES2SLMaterialRenderer::createProgram() - { - Program = glCreateProgram(); - return true; - } - - bool COGLES2SLMaterialRenderer::createShader( GLenum shaderType, const char* shader, const char* shaderFile ) - { - GLuint shaderHandle = glCreateShader( shaderType ); - - os::Printer::log("Loading shader", shaderFile); - glShaderSource( shaderHandle, 1, &shader, NULL ); - glCompileShader( shaderHandle ); - - int status = 0; - - glGetShaderiv( shaderHandle, GL_COMPILE_STATUS, &status ); - - if ( !status ) - { - os::Printer::log("GLSL shader failed to compile", shaderFile, ELL_ERROR); - - // check error message and log it - int maxLength = 0; - GLsizei length; - - glGetShaderiv( shaderHandle, GL_INFO_LOG_LENGTH, &maxLength ); - - char *pInfoLog = new char[maxLength]; - glGetShaderInfoLog( shaderHandle, maxLength, &length, pInfoLog ); - os::Printer::log(pInfoLog, ELL_ERROR); - delete [] pInfoLog; - - return false; - } - - glAttachShader(Program, shaderHandle); - - return true; - } - - bool COGLES2SLMaterialRenderer::linkProgram() - { - glLinkProgram( Program ); - - int status = 0; - - glGetProgramiv( Program, GL_LINK_STATUS, &status ); - - if ( !status ) - { - os::Printer::log( "GLSL shader program failed to link", ELL_ERROR ); - // check error message and log it - int maxLength = 0; - GLsizei length; - - glGetProgramiv( Program, GL_INFO_LOG_LENGTH, &maxLength ); - - char *pInfoLog = new char[maxLength]; - glGetProgramInfoLog( Program, maxLength, &length, pInfoLog ); - os::Printer::log(pInfoLog, ELL_ERROR); - delete [] pInfoLog; - - return false; - } - - // get uniforms information - - int num = 0; - glGetProgramiv( Program, GL_ACTIVE_UNIFORMS, &num ); - - if (num == 0) - return true; - - int maxlen = 0; - glGetProgramiv( Program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen ); - - if (maxlen == 0) - { - os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR); - return false; - } - - maxlen++; - c8 *buf = new c8[maxlen]; - - UniformInfo.clear(); - UniformInfo.reallocate(num); - - for ( int i = 0; i < num; ++i ) - { - memset( buf, 0, maxlen ); - GLint size; - SUniformInfo ui; - glGetActiveUniform( Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast( buf ) ); - - ui.name = buf; - ui.location = glGetUniformLocation( Program, buf ); - - UniformInfo.push_back(ui); - } - - delete [] buf; - - return true; - } - - - void COGLES2SLMaterialRenderer::setBasicRenderStates( const SMaterial& material, - const SMaterial& lastMaterial, - bool resetAllRenderstates ) - { - // forward - Driver->setBasicRenderStates( material, lastMaterial, resetAllRenderstates ); - } - - - bool COGLES2SLMaterialRenderer::setVertexShaderConstant( const c8* name, const f32* floats, int count ) - { - return setPixelShaderConstant( name, floats, count ); - } - - bool COGLES2SLMaterialRenderer::setVertexShaderConstant( const c8* name, const s32* ints, int count ) - { - return setPixelShaderConstant( name, ints, count ); - } - - void COGLES2SLMaterialRenderer::setVertexShaderConstant( const f32* data, s32 startRegister, s32 constantAmount ) - { - os::Printer::log( "Cannot set constant, please use high level shader call instead.", ELL_WARNING ); - } - - bool COGLES2SLMaterialRenderer::setVertexShaderPointer( const c8* name, const void* pointer, - s32 size, bool normalized, u16 stride ) - { - os::Printer::log( "Cannot set constant, use high level shader call.", ELL_WARNING ); - - return false; - } - - void COGLES2SLMaterialRenderer::enableVertexShaderPointer( const c8* name ) - { - os::Printer::log( "Cannot set constant, use high level shader call.", ELL_WARNING ); - } - - void COGLES2SLMaterialRenderer::disableVertexShaderPointer( const c8* name ) - { - os::Printer::log( "Cannot set constant, use high level shader call.", ELL_WARNING ); - } - - bool COGLES2SLMaterialRenderer::setPixelShaderConstant( const c8* name, const f32* floats, int count ) - { - u32 i; - const u32 num = UniformInfo.size(); - - for (i=0; i < num; ++i) - { - if (UniformInfo[i].name == name) - break; - } - - if (i == num) - return false; - - if(UniformInfo[i].location == -1) - return false; - - bool status = true; - - switch (UniformInfo[i].type) - { - case GL_FLOAT: - glUniform1fv(UniformInfo[i].location, count, floats); - break; - case GL_FLOAT_VEC2: - glUniform2fv(UniformInfo[i].location, count/2, floats); - break; - case GL_FLOAT_VEC3: - glUniform3fv(UniformInfo[i].location, count/3, floats); - break; - case GL_FLOAT_VEC4: - glUniform4fv(UniformInfo[i].location, count/4, floats); - break; - case GL_FLOAT_MAT2: - glUniformMatrix2fv(UniformInfo[i].location, count/4, false, floats); - break; - case GL_FLOAT_MAT3: - glUniformMatrix3fv(UniformInfo[i].location, count/9, false, floats); - break; - case GL_FLOAT_MAT4: - glUniformMatrix4fv(UniformInfo[i].location, count/16, false, floats); - break; - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - { - if(floats) - { - GLint id = *floats; - glUniform1iv(UniformInfo[i].location, 1, &id); - } - } - break; - default: - status = false; - break; - } - - return status; - } - - bool COGLES2SLMaterialRenderer::setPixelShaderConstant( const c8* name, const s32* ints, int count ) - { - u32 i; - const u32 num = UniformInfo.size(); - - for (i=0; i < num; ++i) - { - if (UniformInfo[i].name == name) - break; - } - - if (i == num) - return false; - - if(UniformInfo[i].location == -1) - return false; - - bool status = true; - - switch (UniformInfo[i].type) - { - case GL_INT_VEC2: - case GL_BOOL_VEC2: - glUniform2iv(UniformInfo[i].location, count/2, ints); - break; - case GL_INT_VEC3: - case GL_BOOL_VEC3: - glUniform3iv(UniformInfo[i].location, count/3, ints); - break; - case GL_INT_VEC4: - case GL_BOOL_VEC4: - glUniform4iv(UniformInfo[i].location, count/4, ints); - break; - case GL_INT: - case GL_BOOL: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - glUniform1iv(UniformInfo[i].location, count, ints); - break; - default: - status = false; - break; - } - - return status; - } - - bool COGLES2SLMaterialRenderer::setUniform( int index, const void* data, int count ) - { - if ((u32)index>=UniformInfo.size()) - return false; - SUniformInfo& ui = UniformInfo[index]; - if ( ui.location == -1 ) - return false; - switch ( ui.type ) - { - case GL_FLOAT: - glUniform1fv( ui.location, count, static_cast( data ) ); - break; - case GL_FLOAT_VEC2: - glUniform2fv( ui.location, count, static_cast( data ) ); - break; - case GL_FLOAT_VEC3: - glUniform3fv( ui.location, count, static_cast( data ) ); - break; - case GL_FLOAT_VEC4: - glUniform4fv( ui.location, count, static_cast( data ) ); - break; - case GL_INT: - case GL_BOOL: - glUniform1iv( ui.location, count, static_cast( data ) ); - break; - case GL_INT_VEC2: - case GL_BOOL_VEC2: - glUniform2iv( ui.location, count, static_cast( data ) ); - break; - case GL_INT_VEC3: - case GL_BOOL_VEC3: - glUniform3iv( ui.location, count, static_cast( data ) ); - break; - case GL_INT_VEC4: - case GL_BOOL_VEC4: - glUniform4iv( ui.location, count, static_cast( data ) ); - break; - case GL_FLOAT_MAT2: - glUniformMatrix2fv( ui.location, count, false, static_cast( data ) ); - break; - case GL_FLOAT_MAT3: - glUniformMatrix3fv( ui.location, count, false, static_cast( data ) ); - break; - case GL_FLOAT_MAT4: - glUniformMatrix4fv( ui.location, count, false, static_cast( data ) ); - break; - default: // sampler - glUniform1iv( ui.location, count, static_cast( data ) ); - break; - } - return !Driver->testGLError(); - } - - bool COGLES2SLMaterialRenderer::setTextureUnit( const c8* name, int unit ) - { - os::Printer::log( "Cannot set constant, use high level shader call.", ELL_WARNING ); - return false; - } - - bool COGLES2SLMaterialRenderer::enableMaterialTexture( const c8* name, int materialId ) - { - ITexture * t = Driver->getTextureByIndex( materialId ); - COGLES2Texture * tex = reinterpret_cast( t ); - if ( !tex ) - return false; - const GLuint unit = tex->getOGLES2TextureName(); - - glActiveTexture( GL_TEXTURE0 + unit ); - glBindTexture( GL_TEXTURE_2D, unit ); - - return setTextureUnit( name, unit ); - } - - bool COGLES2SLMaterialRenderer::disableMaterialTexture( int materialId ) - { - COGLES2Texture * tex = reinterpret_cast( Driver->getTextureByIndex( materialId ) ); - if ( !tex ) - return false; - - const GLuint unit = tex->getOGLES2TextureName(); - - glActiveTexture( GL_TEXTURE0 + unit ); - glBindTexture( GL_TEXTURE_2D, 0 ); - - return true; - } - - void COGLES2SLMaterialRenderer::setPixelShaderConstant( const f32* data, s32 startRegister, s32 constantAmount ) - { - os::Printer::log( "Cannot set constant, use high level shader call.", ELL_WARNING ); - } - - IVideoDriver* COGLES2SLMaterialRenderer::getVideoDriver() - { - return Driver; - } - - void COGLES2SLMaterialRenderer::useProgram() - { - glUseProgram( Program ); - } - -} // end namespace video -} // end namespace irr - -#endif //_IRR_COMPILE_WITH_OPENGLES2_ - diff --git a/source/Irrlicht/COGLES2SLMaterialRenderer.h b/source/Irrlicht/COGLES2SLMaterialRenderer.h deleted file mode 100644 index 2e7b9593..00000000 --- a/source/Irrlicht/COGLES2SLMaterialRenderer.h +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (C) 2009-2010 Amundis -// Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in Irrlicht.h - -#ifndef __C_OGLES2_SL_MATERIAL_RENDERER_H_INCLUDED__ -#define __C_OGLES2_SL_MATERIAL_RENDERER_H_INCLUDED__ - -#include "IrrCompileConfig.h" -#ifdef _IRR_COMPILE_WITH_OGLES2_ - -#include "IMaterialRenderer.h" -#include "IMaterialRendererServices.h" -#include "IGPUProgrammingServices.h" -#include "irrArray.h" -#include "irrString.h" - -namespace irr -{ -namespace io -{ - class IFileSystem; -} -namespace video -{ - class COGLES2Driver; - class IShaderConstantSetCallBack; - - //! Class for using GLSL shaders with OpenGL - //! Please note: This renderer implements its own IMaterialRendererServices - class COGLES2SLMaterialRenderer : public IMaterialRenderer, public IMaterialRendererServices - { - protected: - struct SUniformInfo - { - core::stringc name; - u32 type; - s32 location; - }; - typedef SUniformInfo SAttributeInfo; - public: - - //! Constructor - COGLES2SLMaterialRenderer(COGLES2Driver* driver, - s32& outMaterialTypeNr, - const c8* vertexShaderProgram, - const c8* pixelShaderProgram, - IShaderConstantSetCallBack* callback, - IMaterialRenderer* baseMaterial, - s32 userData); - - //! Destructor - virtual ~COGLES2SLMaterialRenderer(); - - virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates, IMaterialRendererServices* services); - - virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); - virtual bool PostRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); - - virtual void OnUnsetMaterial(); - - //! Returns if the material is transparent. - virtual bool isTransparent() const; - - // implementations for the render services - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates); - virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count); - virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count); - virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1); - virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); - virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count); - virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1); - - bool setUniform(int index, const void* data, int count = 1); - - virtual bool setVertexShaderPointer(const c8* name, const void* pointer, s32 size = 3, bool normalized = false, u16 stride = 0); - virtual void enableVertexShaderPointer(const c8* name); - virtual void disableVertexShaderPointer(const c8* name); - - bool setTextureUnit(const c8* name, int unit); - - virtual bool enableMaterialTexture(const c8* name, int materialId); - virtual bool disableMaterialTexture(int materialId); - - virtual IVideoDriver* getVideoDriver(); - - void useProgram(); - - protected: - - //! constructor only for use by derived classes who want to - //! create a fall back material for example. - COGLES2SLMaterialRenderer(COGLES2Driver* driver, - io::IFileSystem* fs, - IShaderConstantSetCallBack* callback, - IMaterialRenderer* baseMaterial, - const char* const* uniformStringTable, - const u32& uniformCount, - s32 userData = 0); - - bool init(s32& outMaterialTypeNr, - const c8* vertexShaderProgram, - const c8* pixelShaderProgram, - bool registerMaterial = true); - - bool initFromFiles(s32& outMaterialTypeNr, - const c8* vertexShaderFile, - const c8* pixelShaderFile, - bool registerMaterial = true); - - bool reloadFromFiles(const c8* vertexShaderFile, - const c8* pixelShaderFile); - - bool readVertexShader(const c8* vertexShaderFile); - bool readFragmentShader(const c8* fragmentShaderFile); - bool readShader(u32 shaderType, const c8* shaderFile); - - bool createProgram(); - bool createShader(u32 shaderType, const char* shader, const char* shaderFile); - bool linkProgram(); - - COGLES2Driver* Driver; - IShaderConstantSetCallBack* CallBack; - IMaterialRenderer* BaseMaterial; - io::IFileSystem* FileSystem; - - u32 Program; - - core::array UniformInfo; - core::array AttributeInfo; - s32 UserData; - - const char* const* UniformStringTable; - const int UniformCount; - }; - -} // end namespace video -} // end namespace irr - -#endif //_IRR_COMPILE_WITH_OPENGLES2_ -#endif //__C_OPEN_GL_ES2_SL_MATERIAL_RENDERER_H_INCLUDED__ - diff --git a/source/Irrlicht/COGLES2Texture.cpp b/source/Irrlicht/COGLES2Texture.cpp index 6e52a80e..bf81e7c6 100644 --- a/source/Irrlicht/COGLES2Texture.cpp +++ b/source/Irrlicht/COGLES2Texture.cpp @@ -1,6 +1,7 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h @@ -217,6 +218,10 @@ namespace video // enable bilinear filter without mipmaps glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + StatesCache.BilinearFilter = true; + StatesCache.TrilinearFilter = false; + StatesCache.MipMapStatus = false; } void* source = 0; @@ -447,6 +452,12 @@ namespace video glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height ); } + //! Get an access to texture states cache. + COGLES2Texture::SStatesCache& COGLES2Texture::getStatesCache() const + { + return StatesCache; + } + /* FBO Textures */ // helper function for render to texture @@ -503,6 +514,11 @@ namespace video 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); + + StatesCache.BilinearFilter = true; + StatesCache.WrapU = ETC_CLAMP_TO_EDGE; + StatesCache.WrapV = ETC_CLAMP_TO_EDGE; + glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width, ImageSize.Height, 0, PixelFormat, PixelType, 0); diff --git a/source/Irrlicht/COGLES2Texture.h b/source/Irrlicht/COGLES2Texture.h index 51ba745f..178726e1 100644 --- a/source/Irrlicht/COGLES2Texture.h +++ b/source/Irrlicht/COGLES2Texture.h @@ -1,12 +1,14 @@ -// Copyright (C) 2009-2010 Amundis +// Copyright (C) 2013 Patryk Nadrowski // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt -// and OpenGL ES driver implemented by Christian Stehno +// OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0 +// driver implemented by Amundis. // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h #ifndef __C_OGLES2_TEXTURE_H_INCLUDED__ #define __C_OGLES2_TEXTURE_H_INCLUDED__ +#include "SMaterialLayer.h" #include "ITexture.h" #include "IImage.h" @@ -25,6 +27,25 @@ namespace video { public: + //! Cache structure. + struct SStatesCache + { + SStatesCache() : WrapU(ETC_REPEAT), WrapV(ETC_REPEAT), BilinearFilter(false), + TrilinearFilter(false), AnisotropicFilter(0), MipMapStatus(false), IsCached(false), LODBias(0) + { + } + + u8 WrapU; + u8 WrapV; + bool BilinearFilter; + bool TrilinearFilter; + u8 AnisotropicFilter; + bool MipMapStatus; + s8 LODBias; + + bool IsCached; + }; + //! constructor COGLES2Texture(IImage* surface, const io::path& name, COGLES2Driver* driver = 0); @@ -76,6 +97,9 @@ namespace video //! sets whether this texture is intended to be used as a render target. void setIsRenderTarget(bool isTarget); + //! Get an access to texture states cache. + SStatesCache& getStatesCache() const; + protected: //! protected constructor with basic setup, no GL texture name created, for derived classes @@ -104,6 +128,8 @@ namespace video bool AutomaticMipmapUpdate; bool UseStencil; bool ReadOnlyLock; + + mutable SStatesCache StatesCache; };