<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fshShader SYSTEM "fshShadingBlock.dtd">
<codeblocks label="root" type="std" class="STATIC_BLOCK">
<codeblock label="declarations" type="std" class="STATIC_BLOCK">
//
//  vsh.xml
//
//  Copyright 2011-2012 Apple Inc. All rights reserved.
//

#ifndef GL_ES
#define lowp
#define mediump
#define highp

#define IN_VERT  in
#define OUT_VERT out
#define IN_FRAG  in
#define OUT_FRAG out

#define texture2D   texture
#define textureCube texture
#else
#define IN_VERT  attribute
#define OUT_VERT varying
#define IN_FRAG  varying
#define OUT_FRAG

precision highp float;
#endif

#define MAX_LIGHTS   3

/////////////////////////////////////////////////////////////////////////////////////
// VERTEX ATTRIBUTES
/////////////////////////////////////////////////////////////////////////////////////
IN_VERT         vec4 a_position;
<codeblock label="use tex coord attrib" type="cond" class="EFFECT">
IN_VERT         vec3 a_texCoord0;
IN_VERT         vec3 a_texCoord1;
</codeblock>
IN_VERT         vec3 a_normal;
IN_VERT lowp    vec4 a_color;

/////////////////////////////////////////////////////////////////////////////////////
// Global State
/////////////////////////////////////////////////////////////////////////////////////
uniform bool        perPixelLightingEnabled;
uniform lowp vec4   lightModelAmbientColor;

/////////////////////////////////////////////////////////////////////////////////////
// TRANSFORM
/////////////////////////////////////////////////////////////////////////////////////
uniform mat4    modelviewMatrix;
uniform mat3    normalMatrix;
uniform mat4    mvpMatrix;

/////////////////////////////////////////////////////////////////////////////////////
// TEXTURE
/////////////////////////////////////////////////////////////////////////////////////
#define MAX_TEXTURES    3
#define MAX_TEX_COORDS  3
#define S               0
#define T               1
#define R               2
#define STR             3

#define GLKTexGenModeObjectLinear      0
#define GLKTexGenModeEyeLinear         1
#define GLKTexGenModeSphereMap         2
#define GLKTexGenModeReflectionMap     3

struct texGen_s
{
    lowp int        mode;
    highp vec4      plane;
    highp vec4      eyePlaneByInvModelview;
};

struct texture_s
{
    mat4                matrix;
    lowp vec4           envColor;
    texGen_s            texGen[STR];
};

uniform texture_s       textures[MAX_TEXTURES];
uniform sampler2D       unit2d[3];
uniform samplerCube     unitCube[3];


/////////////////////////////////////////////////////////////////////////////////////
// LIGHT
/////////////////////////////////////////////////////////////////////////////////////
uniform bool        light_enabled[MAX_LIGHTS];
uniform vec4        light_position[MAX_LIGHTS];
uniform vec4        light_positionEye[MAX_LIGHTS];
uniform lowp vec4   light_ambientColor[MAX_LIGHTS];
uniform lowp vec4   light_diffuseColor[MAX_LIGHTS];
uniform lowp vec4   light_specularColor[MAX_LIGHTS];
uniform vec3        light_normalizedSpotDirectionEye[MAX_LIGHTS];
uniform float       light_spotExponent[MAX_LIGHTS];
uniform float       light_spotCutoffAngle[MAX_LIGHTS];
uniform float       light_constantAttenuation[MAX_LIGHTS];
uniform float       light_linearAttenuation[MAX_LIGHTS];
uniform float       light_quadraticAttenuation[MAX_LIGHTS];

/////////////////////////////////////////////////////////////////////////////////////
// MATERIAL
/////////////////////////////////////////////////////////////////////////////////////
struct material_s
{
    lowp vec4 ambientColor;
    lowp vec4 diffuseColor;
    lowp vec4 specularColor;
    lowp vec4 emissiveColor;
    float shininess;
};

uniform material_s  material;

/////////////////////////////////////////////////////////////////////////////////////
// FOG
/////////////////////////////////////////////////////////////////////////////////////
#define GLKFogModeExp           0
#define GLKFogModeExp2          1
#define GLKFogModeLinear     2

struct fog_s
{
    lowp int     mode;
    lowp vec4    color;
    float   density;
    float   start;
    float   end;
};

uniform fog_s fog;


/////////////////////////////////////////////////////////////////////////////////////
// Varyings
/////////////////////////////////////////////////////////////////////////////////////

OUT_VERT lowp vec4  v_color;

<codeblock label="v_position" type="cond" class="TEXTURE">
OUT_VERT highp vec4    v_position;
</codeblock>
<codeblock label="v_positionEye" type="cond" class="EFFECT">
OUT_VERT highp vec4    v_positionEye;
</codeblock>
<codeblock label="v_normalEye" type="cond" class="EFFECT">
OUT_VERT highp vec3    v_normalEye;
</codeblock>
<codeblock label="texturing enabled" type="cond" class="EFFECT">
OUT_VERT highp vec3    v_texCoord[MAX_TEX_COORDS];
</codeblock>
<codeblock label="light model two-sided per-vertex enabled" type="cond" class="EFFECT">
OUT_VERT lowp vec4     v_backColor;
</codeblock>
<codeblock label="fog enabled" type="cond" class="FOG">
OUT_VERT float         v_fog;
</codeblock>

/////////////////////////////////////////////////////////////////////////////////////
// Temps
/////////////////////////////////////////////////////////////////////////////////////
highp vec3 normalEye;
<codeblock label="modelview matrix" type="cond" class="EFFECT">
highp vec4 positionEye;
</codeblock>

<codeblock label="color material enabled" type="cond" class="EFFECT">
#define materialAmbientColor (a_color)
#define materialDiffuseColor (a_color)
lowp vec4 baseLightingColor;
vec4 ambientTerm[3];
</codeblock>

<codeblock label="color material disabled" type="cond" class="EFFECT">
#define materialAmbientColor (material.ambientColor)
#define materialDiffuseColor (material.diffuseColor)
uniform lowp vec4 baseLightingColor;
uniform vec4 ambientTerm[3];
</codeblock>

</codeblock>

<codeblock label="main prolog" type="std" class="STATIC_BLOCK">
void main(void)
{
    // int currLight;
    lowp vec4 tmpFrontColor, tmpBackColor;
    vec3 normalizedNormal;
</codeblock>

<codeblock label="main epilog" type="std" class="STATIC_BLOCK">
    // Default value for eye space normal
    normalEye = vec3(0.0, 0.0, 1.0);
    <codeblock label="modelview matrix" type="cond" class="EFFECT">
    positionEye = modelviewMatrix * a_position;
    </codeblock>
    
    <codeblock label="normalized normals" type="cond" class="EFFECT">
<![CDATA[
    /* if( perVertexLightingEnabled == true ||
        perPixelLightingEnabled == true ||
        (textures[0].texGen[S].enabled == true && textures[0].texGen[S].mode == GLKTexGenModeSphereMap) ||
        (textures[0].texGen[T].enabled == true && textures[0].texGen[T].mode == GLKTexGenModeSphereMap) ||
        (textures[0].texGen[S].enabled == true && textures[0].texGen[S].mode == GLKTexGenModeReflectionMap) ||
        (textures[0].texGen[T].enabled == true && textures[0].texGen[T].mode == GLKTexGenModeReflectionMap) ||
        (textures[0].texGen[R].enabled == true && textures[0].texGen[R].mode == GLKTexGenModeReflectionMap) ||

        (textures[1].texGen[S].enabled == true && textures[1].texGen[S].mode == GLKTexGenModeSphereMap) ||
        (textures[1].texGen[T].enabled == true && textures[1].texGen[T].mode == GLKTexGenModeSphereMap) ||
        (textures[1].texGen[S].enabled == true && textures[1].texGen[S].mode == GLKTexGenModeReflectionMap) ||
        (textures[1].texGen[T].enabled == true && textures[1].texGen[T].mode == GLKTexGenModeReflectionMap) ||
        (textures[1].texGen[R].enabled == true && textures[1].texGen[R].mode == GLKTexGenModeReflectionMap)) */
]]>
    {
        normalEye = normalize((normalMatrix * a_normal));
    }
    </codeblock>
        
    <codeblock label="per-vertex lighting enabled" type="cond" class="EFFECT">
    vec4 specularTerm, diffuseTerm;
    vec3 vertexToLightVec;
    highp float attenuationFactor, spotFactor, nDotL;

    // if(perVertexLightingEnabled == true)
    {
        <codeblock label="color material enabled" type="cond" class="EFFECT">
            // if(colorMaterialEnabled == true)
            {
            // materialAmbientColor = materialDiffuseColor = a_color;  
            baseLightingColor = material.emissiveColor + (materialAmbientColor * lightModelAmbientColor);
            ambientTerm[0] = materialAmbientColor * light_ambientColor[0];
            ambientTerm[1] = materialAmbientColor * light_ambientColor[1];
            ambientTerm[2] = materialAmbientColor * light_ambientColor[2];
            }
        </codeblock>
        <codeblock label="color material disabled" type="cond" class="EFFECT">
            // else
            {
            // materialAmbientColor = material.ambientColor;
            // materialDiffuseColor = material.diffuseColor;  
            // baseLightingColor = material.emissiveColor + (materialAmbientColor * lightModelAmbientColor);
            }
        </codeblock>

        tmpFrontColor = baseLightingColor;

        <codeblock label="light model two-sided per-vertex enabled" type="cond" class="EFFECT">
        tmpBackColor = baseLightingColor;
        </codeblock>

        <codeblock label="lighting" type="loop" unrollCt="3" loopVar="currLight" class="LIGHT">
        <![CDATA[ // for(currLight = 0; currLight < numLights; currLight++) ]]>
        {
            // if(light_enabled[currLight] == false) continue;

            <codeblock label="directional light" type="cond" class="LIGHT">
            // For directional lights light_positionEye[currLight].xyz is normalized on the CPU side
            vertexToLightVec = light_positionEye[currLight].xyz;
            </codeblock>

            <codeblock label="positional light" type="cond" class="LIGHT">
            vertexToLightVec = normalize(light_positionEye[currLight].xyz - positionEye.xyz);
            </codeblock>

            <codeblock label="attenuate lighting enabled" type="cond" class="LIGHT">
            {
                float vertexToLightVecMagnitude = distance(light_positionEye[currLight].xyz, positionEye.xyz);

                attenuationFactor = (1.0 /
                    (light_constantAttenuation[currLight] +
                    light_linearAttenuation[currLight] * vertexToLightVecMagnitude +
                    light_quadraticAttenuation[currLight] * vertexToLightVecMagnitude * vertexToLightVecMagnitude));
            }
            </codeblock>

            <codeblock label="attenuate lighting disabled" type="cond" class="LIGHT">
            attenuationFactor = 1.0;
            </codeblock>

            // Calculate diffuse and specular terms
            nDotL = max(dot(normalEye, vertexToLightVec), 0.0);
    
            diffuseTerm = nDotL * materialDiffuseColor * light_diffuseColor[currLight];
    
            <codeblock label="specular not default" type="cond" indexedMask="no" class="MATERIAL">
            if(nDotL != 0.0)
            {
                highp float nDotH = max(dot(normalEye, normalize(vertexToLightVec + vec3(0.0, 0.0, 1.0))), 0.0);
                specularTerm = (pow(nDotH, material.shininess) * material.specularColor * light_specularColor[currLight]);
            }
            else
            {
                specularTerm = vec4(0.0);
            }
            </codeblock>
            <codeblock label="specular is default" type="cond" indexedMask="no" class="MATERIAL">
            specularTerm = vec4(0.0);
            </codeblock>


            <codeblock label="spot lighting enabled" type="cond" class="LIGHT">
            <![CDATA[
            // if(light_spotCutoffAngle[currLight] != 180.0)
            {
                vec3 vertexDir = -vertexToLightVec;
                float cosCutoff = cos(light_spotCutoffAngle[currLight]);
                float vertexDirDotSpotDir = max(dot(vertexDir, light_normalizedSpotDirectionEye[currLight]), 0.0);
    
                if(vertexDirDotSpotDir >= cosCutoff)
                {
                    spotFactor = pow(vertexDirDotSpotDir, light_spotExponent[currLight]);
                }
                else
                    spotFactor = 0.0;
            }
            ]]>
            </codeblock>
    
            <codeblock label="spot lighting disabled" type="cond" class="LIGHT">
            spotFactor = 1.0;
            </codeblock>
    
            tmpFrontColor += attenuationFactor * spotFactor * (ambientTerm[currLight] + diffuseTerm + specularTerm);

            <codeblock label="light model two-sided per-vertex enabled" type="cond" class="EFFECT">
            // if(lightModelTwoSided)
            {
                // Re-calculate diffuse and specular terms with negated normals
                nDotL = max(dot(-normalEye, vertexToLightVec), 0.0);
    
                diffuseTerm = nDotL * materialDiffuseColor * light_diffuseColor[currLight];
    
                <codeblock label="specular not default" type="cond" indexedMask="no" class="MATERIAL">
                if(nDotL != 0.0)
                {
                    highp float nDotH = max(dot(-normalEye, normalize(vertexToLightVec + vec3(0.0, 0.0, 1.0))), 0.0);
                    specularTerm = (pow(nDotH, material.shininess) * material.specularColor * light_specularColor[currLight]);
                }
                else
                {
                    specularTerm = vec4(0.0);
                }
                </codeblock>
                <codeblock label="specular is default" type="cond" indexedMask="no" class="MATERIAL">
                specularTerm = vec4(0.0);
                </codeblock>
    
                tmpBackColor += attenuationFactor * spotFactor * (ambientTerm[currLight] + diffuseTerm + specularTerm);
            }
            </codeblock>
        }
        </codeblock>
    }
    </codeblock>

    v_color = a_color;

    <codeblock label="per-vertex lighting enabled" type="cond" class="EFFECT">
    v_color = tmpFrontColor;
    v_color.a = materialDiffuseColor.a;

    <codeblock label="light model two-sided per-vertex enabled" type="cond" class="EFFECT">
    v_backColor = tmpBackColor;
    v_backColor.a = materialDiffuseColor.a;
    v_backColor = clamp(v_backColor, 0.0, 1.0);
    </codeblock>
    </codeblock>

    v_color = clamp(v_color, 0.0, 1.0);

    <codeblock label="use tex coord attrib" type="cond" class="EFFECT">
    v_texCoord[0] = a_texCoord0;
    v_texCoord[1] = a_texCoord1;
    </codeblock>

    <codeblock label="v_position" type="cond" class="TEXTURE">
    v_position = a_position;
    </codeblock>
    
    <codeblock label="v_positionEye" type="cond" class="EFFECT">
    v_positionEye = positionEye;
    </codeblock>
    
    <codeblock label="v_normalEye" type="cond" class="EFFECT">
    v_normalEye = normalEye;
    </codeblock>

    <codeblock label="fog enabled" type="cond" class="FOG">
        // if(GLKFogModeExp == fog.mode)
        <codeblock label="fog mode exp" type="cond" class="FOG">
        v_fog = exp(-1.0 * (abs(positionEye.z) * fog.density));
        </codeblock>

        <codeblock label="fog mode exp2" type="cond" class="FOG">
        // else if(GLKFogModeExp2 == fog.mode)
        {
            v_fog = (abs(positionEye.z) * fog.density);
            v_fog = exp(-(v_fog * v_fog));
        }
        </codeblock>

        <codeblock label="fog mode linear" type="cond" class="FOG">
        // else if(GLKFogModeLinear == fog.mode)
        v_fog = (fog.end - abs(positionEye.z)) / (fog.end - fog.start);
        </codeblock>

        v_fog = clamp(v_fog, 0.0, 1.0);
    </codeblock>
    
    gl_Position = mvpMatrix * a_position;

}
</codeblock>
</codeblocks>
