Source: Graphics/WebGL/DynamicShading/AxDynamicShaderWriter.js

/**
 * Creates a new dynamic shader writer object
 * The dynamic shader writer is used to generate the graphics device's shading program code in compliance with Axis' shading layers architecture
 * @param {Boolean} animated Denotes whether the shader should provide skeletal animation (skinning)
 * @param {Integer} maxBones The maximum number of bones in case the shader is animated
 * @constructor
 */
function AxDynamicShaderWriter(animated, maxBones)
{
    this.vsInputType = new AxDynamicShaderBlockDefinitions();
    this.vsParams = new AxDynamicShaderBlockDefinitions();
    this.vsCode = new AxDynamicShaderBlockDefinitions();
    this.sIOType = new AxDynamicShaderBlockDefinitions();
    this.psParams = new AxDynamicShaderBlockDefinitions();
    this.psCode = new AxDynamicShaderBlockDefinitions();
    this.psOutputType = new AxDynamicShaderBlockDefinitions();

    this.animated = animated;
    this.maxBones = maxBones;

    this.numLights = 0;
    this.textureSlots = 0;
    this.texCoordSlots = 0;
    
    this.shadingOps = new AxList();
    

    if (this.animated)
    {
        this.vsParams.ProvideDefinition('bones', 'uniform mat4 worldMatrix[' + this.maxBones + '];\r\n');
    }
    else
    {
        this.vsParams.ProvideDefinition('worldMatrix', 'uniform mat4 worldMatrix;\r\n');
    }

    this.vsParams.ProvideDefinition('', 'precision mediump float;');
    this.vsParams.ProvideDefinition('viewProjectionMatrix', 'uniform mat4 viewProjectionMatrix;');//
    this.vsParams.ProvideDefinition('ambientLight', 'uniform vec4 ambientLight;');
    this.vsParams.ProvideDefinition('viewPosition', 'uniform vec3 viewPosition;');
    
    this.psParams.ProvideDefinition('', 'precision mediump float;');
    this.psParams.ProvideDefinition('viewPosition', 'uniform vec3 viewPosition;');

    this.vsInputType.ProvideDefinition('input_pos', 'attribute vec3 input_pos;');
    if (this.animated)
    {
        this.vsInputType.ProvideDefinition('input_boneIndices', 'attribute vec4 input_boneIndices;');
        this.vsInputType.ProvideDefinition('input_boneWeights', 'attribute vec4 input_boneWeights;');
    }

    this.sIOType.ProvideDefinition('pos', 'varying vec4 sio_pos;');

    this.psParams.ProvideDefinition('', 'precision mediump float;');
    this.psParams.ProvideDefinition('ambientLight', 'uniform vec4 ambientLight;');
    
    this.psOutputType.ProvideDefinition('PSOutput', 'struct PSOutput\r\n{');
    this.psOutputType.ProvideDefinition('color', '\tvec4 color;');

    this.vsCode.ProvideDefinition('', 'void main()\r\n{');
    if (this.animated)
    {
        this.vsCode.ProvideDefinition('bonesMatrix', '\tmat4 bonesMatrix;');
        this.vsCode.ProvideDefinition('', '\tbonesMatrix = \r\n' +
            '\t\tworldMatrix[int(input_boneIndices.x)] * input_boneWeights.x +\r\n' +
            '\t\tworldMatrix[int(input_boneIndices.y)] * input_boneWeights.y +\r\n' +
            '\t\tworldMatrix[int(input_boneIndices.z)] * input_boneWeights.z +\r\n' +
            '\t\tworldMatrix[int(input_boneIndices.w)] * input_boneWeights.w;');

        this.vsCode.ProvideDefinition('worldPos', '\tvec4 worldPos = bonesMatrix * vec4(input_pos, 1.0);\r\n');
    }
    else
    {
        this.vsCode.ProvideDefinition('worldPos', '\tvec4 worldPos = worldMatrix * vec4(input_pos, 1.0);\r\n');
    }
    this.vsCode.ProvideDefinition('.pos', '\tsio_pos = viewProjectionMatrix * worldPos;\r\n');

    this.psCode.ProvideDefinition('', 'void main()\r\n{');
    this.psCode.ProvideDefinition('result', '\tPSOutput result;\r\n');
}


AxDynamicShaderWriter.prototype.Dispose = function()
{
};

/**
 * Adds a shading layer to the shader writer
 * @param {AxShadingOperation} shadingOp Shading operation for the layer to add
 * @param {AxColorOperation} colorOp Color operation for the layer
 */
AxDynamicShaderWriter.prototype.AddShadingLayer = function(shadingOp, colorOp)
{
    
    switch (shadingOp)
    {
    //*
        case AxShadingOperation.BasicShading:
        {
            this.vsInputType.ProvideDefinition('normal', 'attribute vec3 input_normal;');

            this.sIOType.ProvideDefinition('color', 'varying vec4 sio_color;');

            if (this.animated)
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(bonesMatrix * vec4(input_normal, 0.0)).xyz;');
            else
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(worldMatrix * vec4(input_normal, 0.0)).xyz;');

            this.vsCode.ProvideDefinition('', '\tfloat intensity = clamp(-normal.z, 0.0, 1.0);\r\n');
            this.vsCode.ProvideDefinition('', '\tsio_color = vec4(intensity, intensity, intensity, 1.0);\r\n');

            this.psCode.ProvideDefinition('', '\tresult.color = sio_color;\r\n');
            //this.ProvideColorOperationCode(shadingOp, colorOp, "basicShadingAmount", this.psCode, "\t", "result.color", 'sio_color');
            break;
        }

        case AxShadingOperation.FlatColor:
        {
            var pFlatColor = this.ProvideParameterDefinition(this.psParams, shadingOp, "flatColor", AxParameterType.Color);
            
            this.ProvideColorOperationCode(shadingOp, colorOp, "flatColorAmount", this.psCode, "\t", "result.color", pFlatColor);
            
            break;
        }

        case AxShadingOperation.Tint:
        {
            var pTintColor = this.ProvideParameterDefinition(this.psParams, shadingOp, "tintColor", AxParameterType.Color);

            this.psCode.ProvideDefinition("tintFactor", "float tintFactor;");
            this.psCode.ProvideDefinition("", "\ttintFactor = (result.color.x + result.color.y + result.color.z) / 3.0;");

            this.ProvideColorOperationCode(shadingOp, colorOp, "tintAmount", this.psCode, "\t", "result.color", pTintColor + " * vec4(tintFactor, tintFactor, tintFactor, 1.0)");

            break;
        }

        case AxShadingOperation.AmbientLighting:
        {
            this.ProvideColorOperationCode(shadingOp, colorOp, "ambientAmount", this.psCode, "\t", "result.color", "ambient * ambientLight");
            
            break;
        }

        case AxShadingOperation.LightSource:
        {
            this.numLights++;
            break;
        }

        case AxShadingOperation.VertexLighting:
        {
            if (this.numLights === 0)
                break;

            if (this.shadingOps.Count(AxShadingOperation.VertexLighting) > 0)
                break;

            this.ProvideParameterDefinition(this.vsParams, shadingOp, "activeLightsCount", AxParameterType.Float);

            
            this.vsInputType.ProvideDefinition('normal', 'attribute vec3 input_normal;');

            this.sIOType.ProvideDefinition('color', 'varying vec4 sio_color;');

            if (this.animated)
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(bonesMatrix * vec4(input_normal, 0.0)).xyz;');
            else
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(worldMatrix * vec4(input_normal, 0.0)).xyz;');
            
            this.vsCode.ProvideDefinition('viewVector', '\tvec3 viewVector = normalize(viewPosition - worldPos.xyz);');
            this.vsCode.ProvideDefinition('lightVector', '\tvec3 lightVector;');
            this.vsCode.ProvideDefinition('lightReflectionVector', '\tvec3 lightReflectionVector;');
            this.vsCode.ProvideDefinition('lightAttenuation', '\tfloat lightAttenuation;');
            this.vsCode.ProvideDefinition('lightDiffuse', '\tfloat lightDiffuse;');
            this.vsCode.ProvideDefinition('lightSpecular', '\tfloat lightSpecular;');
            this.vsCode.ProvideDefinition('color', '\tvec4 color;');
            this.vsCode.ProvideDefinition('', 
                '\tcolor = vec4(0.0, 0.0, 0.0, 0.0);\r\n' +
                '\tint iActiveLightsCount = int(activeLightsCount);\r\n' +
                '\tfor (int lightIndex = 0; lightIndex < maxLights; lightIndex++)\r\n' +
                '\t{\r\n' +
                '\t\tlightVector = lightsPosIntensity[lightIndex].xyz - worldPos.xyz;\r\n' +
                '\t\tlightAttenuation = 1.0 / length(lightVector);\r\n' +
                '\t\tlightVector *= lightAttenuation;\r\n' +
                '\t\tlightAttenuation *= lightAttenuation;\r\n' +
                '\t\tlightDiffuse = clamp(dot(normal, lightVector), 0.0, 1.0) * lightsPosIntensity[lightIndex].w * lightAttenuation;\r\n' +
                '\t\tlightReflectionVector = normalize(lightVector + viewVector);\r\n' +
                '\t\tlightSpecular = pow(clamp(dot(normal, lightReflectionVector), 0.0, 1.0), gloss);\r\n' +
                '\t\tcolor += lightsColor[lightIndex] * (lightDiffuse * diffuse + lightSpecular * specular);\r\n' +
                '\t\tiActiveLightsCount--;\r\n' +
                '\t\tif (iActiveLightsCount == 0)\r\n' +
                '\t\t\t break;\r\n' +
                '\t}\r\n'
                );
            this.vsCode.ProvideDefinition('', '\tsio_color = color;');

            this.ProvideColorOperationCode(shadingOp, colorOp, 'vertexLightingAmount', this.psCode, '\t', 'result.color', 'sio_color', colorOp);
            break;
        }


        case AxShadingOperation.PixelLighting:
        {
            if (this.numLights === 0)
                break;

            if (this.shadingOps.Count(AxShadingOperation.PixelLighting) > 0)
                break;

            this.ProvideParameterDefinition(this.psParams, shadingOp, "activeLightsCount", AxParameterType.Int);

            this.vsInputType.ProvideDefinition('normal', 'attribute vec3 input_normal;');

            this.sIOType.ProvideDefinition("normal", "varying vec3 sio_normal;");
            this.sIOType.ProvideDefinition("worldPos", "varying vec4 sio_worldPos;");

            if (this.animated)
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(bonesMatrix * vec4(input_normal, 0.0)).xyz;');
            else
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(worldMatrix * vec4(input_normal, 0.0)).xyz;');
            this.vsCode.ProvideDefinition(".normal", "\tsio_normal = normal;");
            this.vsCode.ProvideDefinition(".worldPos", "\tsio_worldPos = worldPos;");

            this.psCode.ProvideDefinition('sio2_normal', '\tvec3 sio2_normal = sio_normal;');

            this.psCode.ProvideDefinition('viewVector', '\tvec3 viewVector = normalize(viewPosition - sio_worldPos.xyz);');
            this.psCode.ProvideDefinition('lightVector', '\tvec3 lightVector;');
            this.psCode.ProvideDefinition('lightReflectionVector', '\tvec3 lightReflectionVector;');
            this.psCode.ProvideDefinition('lightAttenuation', '\tfloat lightAttenuation;');
            this.psCode.ProvideDefinition('lightDiffuse', '\tfloat lightDiffuse;');
            this.psCode.ProvideDefinition('lightSpecular', '\tfloat lightSpecular;');
            this.psCode.ProvideDefinition('color', '\tvec4 color;');
            this.psCode.ProvideDefinition('', 
                '\tcolor = vec4(0.0, 0.0, 0.0, 0.0);\r\n' +
                '\tint iActiveLightsCount = int(activeLightsCount);\r\n' +
                '\tfor (int lightIndex = 0; lightIndex < maxLights; lightIndex++)\r\n' +
                '\t{\r\n' +
                '\t\tlightVector = lightsPosIntensity[lightIndex].xyz - sio_worldPos.xyz;\r\n' +
                '\t\tlightAttenuation = 1.0 / length(lightVector);\r\n' +
                '\t\tlightVector *= lightAttenuation;\r\n' +
                '\t\tlightAttenuation *= lightAttenuation;\r\n' +
                '\t\tlightDiffuse = clamp(dot(sio2_normal, lightVector), 0.0, 1.0) * lightsPosIntensity[lightIndex].w * lightAttenuation;\r\n' +
                '\t\tlightReflectionVector = normalize(lightVector + viewVector);\r\n' +
                '\t\tlightSpecular = pow(clamp(dot(sio2_normal, lightReflectionVector), 0.0, 1.0), gloss);\r\n' +
                '\t\tcolor += lightsColor[lightIndex] * (lightDiffuse * diffuse + lightSpecular * specular);\r\n' +
                '\t\tiActiveLightsCount--;\r\n' +
                '\t\tif (iActiveLightsCount == 0)\r\n' +
                '\t\t\t break;\r\n' +
                '\t}\r\n'
                );

            this.ProvideColorOperationCode(shadingOp, colorOp, "pixelLightingAmount", this.psCode, "\t", "result.color", "color");
            break;
        }
                
        case AxShadingOperation.ColorMap:
        {
            var pColorMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "colorMap", AxParameterType.ReferenceTexture);

            this.vsInputType.ProvideDefinition('texCoords', 'attribute vec2 input_texCoords;');

            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');

            this.vsCode.ProvideDefinition('.texCoords', '\tsio_texCoords = input_texCoords;');

            this.psCode.ProvideDefinition('sio2_texCoords', 'vec2 sio2_texCoords = sio_texCoords;');

            this.ProvideColorOperationCode(shadingOp, colorOp, 'colorMapAmount', this.psCode, '\t', 'result.color', AxDynamicShaderWriter.TextureSampling(pColorMap, 'sio2_texCoords'), colorOp);

            break;
        }

        case AxShadingOperation.ReflectionMap:
        {
            var pReflectionMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "reflectionMap", AxParameterType.ReferenceTexture);
            var pReflectionFactor = this.ProvideParameterDefinition(this.psParams, shadingOp, "reflectionMapFactor", AxParameterType.Float);

            this.vsInputType.ProvideDefinition('normal', 'attribute vec3 input_normal;');

            this.sIOType.ProvideDefinition('normal', 'varying vec3 sio_normal;');
            this.sIOType.ProvideDefinition('screenSpaceNormal', 'varying vec3 sio_screenSpaceNormal;');
            this.sIOType.ProvideDefinition('screenSpacePos', 'varying vec3 sio_screenSpacePos;');

            if (this.animated)
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(bonesMatrix * vec4(input_normal, 0.0)).xyz;');
            else
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(worldMatrix * vec4(input_normal, 0.0)).xyz;');
            this.vsCode.ProvideDefinition("wvpNormal", "\tvec3 wvpNormal = (viewProjectionMatrix * vec4(normal, 0.0)).xyz;");
            this.vsCode.ProvideDefinition(".normal", "\tsio_normal = normal;");
            this.vsCode.ProvideDefinition(".screenSpaceNormal", "\tsio_screenSpaceNormal = wvpNormal;");
            this.vsCode.ProvideDefinition(".screenSpacePos", 
                "\tsio_screenSpacePos = ((sio_pos.xyz / sio_pos.w) - 1.0) / 2.0;\r\n");

            this.psCode.ProvideDefinition('sio2_normal', '\tvec3 sio2_normal = sio_normal;');
            this.psCode.ProvideDefinition('sampleTexCoords', '\tvec2 sampleTexCoords;');
            this.psCode.ProvideDefinition('', '\tsampleTexCoords = sio_screenSpacePos.xy - sio2_normal.xy * ' + pReflectionFactor + ';');
            
            this.ProvideColorOperationCode(shadingOp, colorOp, 'reflectionMapAmount', this.psCode, '\t', 'result.color', AxDynamicShaderWriter.TextureSampling(pReflectionMap, 'sampleTexCoords'));
            break;
        }

        case AxShadingOperation.RefractionMap:
        {
            var pRefractionMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "refractionMap", AxParameterType.ReferenceTexture);
            var pRefractionMapFactor = this.ProvideParameterDefinition(this.psParams, shadingOp, "refractionMapFactor", AxParameterType.Float);

            this.vsInputType.ProvideDefinition('normal', 'attribute vec3 input_normal;');

            this.sIOType.ProvideDefinition('normal', 'varying vec3 sio_normal;');
            this.sIOType.ProvideDefinition('screenSpaceNormal', 'varying vec3 sio_screenSpaceNormal;');
            this.sIOType.ProvideDefinition('screenSpacePos', 'varying vec3 sio_screenSpacePos;');

            if (this.animated)
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(bonesMatrix * vec4(input_normal, 0.0)).xyz;');
            else
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(worldMatrix * vec4(input_normal, 0.0)).xyz;');
            this.vsCode.ProvideDefinition("wvpNormal", "\tvec3 wvpNormal = (viewProjectionMatrix * vec4(normal, 0.0)).xyz;");
            this.vsCode.ProvideDefinition(".normal", "\tsio_normal = normal;");
            this.vsCode.ProvideDefinition(".screenSpaceNormal", "\tsio_screenSpaceNormal = wvpNormal;");
            this.vsCode.ProvideDefinition(".screenSpacePos", 
                "\tsio_screenSpacePos = ((sio_pos.xyz / sio_pos.w) - 1.0) / 2.0;\r\n");

            this.psCode.ProvideDefinition('sio2_normal', '\tvec3 sio2_normal = sio_normal;');
            this.psCode.ProvideDefinition('sampleTexCoords', '\tvec2 sampleTexCoords;');
            this.psCode.ProvideDefinition('', '\tsampleTexCoords = sio_screenSpacePos.xy - sio2_normal.xy * ' + pRefractionMapFactor + ';');

            this.ProvideColorOperationCode(shadingOp, colorOp, 'refractionMapAmount', this.psCode, '\t', 'result.color', AxDynamicShaderWriter.TextureSampling(pRefractionMap, 'sampleTexCoords'));

            break;
        }
        
        case AxShadingOperation.NormalMap:
        {
            var pNormalMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "normalMap", AxParameterType.ReferenceTexture);
            var pNormalMapFactor = this.ProvideParameterDefinition(this.psParams, shadingOp, "normalMapFactor", AxParameterType.Float);

            this.vsInputType.ProvideDefinition('texCoords', 'attribute vec2 input_texCoords;');
            this.vsInputType.ProvideDefinition('normal', 'attribute vec3 input_normal;');
            this.vsInputType.ProvideDefinition('tangent', 'attribute vec3 input_tangent;');
            this.vsInputType.ProvideDefinition('biTangent', 'attribute vec3 input_biTangent;');

            this.sIOType.ProvideDefinition('normal', 'varying vec3 sio_normal;');
            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');
            this.sIOType.ProvideDefinition('tangent', 'varying vec3 sio_tangent;');
            this.sIOType.ProvideDefinition('biTangent', 'varying vec3 sio_biTangent;');

            if (this.animated)
            {
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(bonesMatrix * vec4(input_normal, 0.0)).xyz;');
                this.vsCode.ProvideDefinition('tangent', '\tvec3 tangent = normalize(bonesMatrix * vec4(input_tangent, 0.0)).xyz;');
                this.vsCode.ProvideDefinition('biTangent', '\tvec3 biTangent = normalize(bonesMatrix * vec4(input_biTangent, 0.0)).xyz;');
            }
            else
            {
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(worldMatrix * vec4(input_normal, 0.0)).xyz;');
                this.vsCode.ProvideDefinition('tangent', '\tvec3 tangent = normalize(worldMatrix * vec4(input_tangent, 0.0)).xyz;');
                this.vsCode.ProvideDefinition('biTangent', '\tvec3 biTangent = normalize(worldMatrix * vec4(input_biTangent, 0.0)).xyz;');
            }

            this.vsCode.ProvideDefinition('.texCoords', '\tsio_texCoords = input_texCoords;');
            this.vsCode.ProvideDefinition('.normal', '\tsio_normal = normal;');
            this.vsCode.ProvideDefinition('.tangent', '\tsio_tangent = tangent;');
            this.vsCode.ProvideDefinition('.biTangent', '\tsio_biTangent = biTangent;');

            this.psCode.ProvideDefinition('sio2_texCoords', '\tvec2 sio2_texCoords = sio_texCoords;');
            this.psCode.ProvideDefinition('sio2_normal', '\tvec3 sio2_normal;');
            this.psCode.ProvideDefinition("",  
                '\tvec3 mapNormal = (' + AxDynamicShaderWriter.TextureSampling(pNormalMap, 'sio2_texCoords') + '.xyz * 2.0 - 1.0);\r\n' +
                "\tmapNormal = mapNormal.x * sio_tangent + mapNormal.y * sio_biTangent + mapNormal.z * sio_normal;\r\n" +
                "\tsio2_normal = mix(sio_normal, mapNormal, " + pNormalMapFactor + ");\r\n");

            break;
        }
            
            
            
            
        case AxShadingOperation.BumpMap:
        {
            var pBumpMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "bumpMap", AxParameterType.ReferenceTexture);
            var pBumpMapFactor = this.ProvideParameterDefinition(this.psParams, shadingOp, "bumpMapFactor", AxParameterType.Float);
            
            this.vsInputType.ProvideDefinition('texCoords', 'attribute vec2 input_texCoords;');
            this.vsInputType.ProvideDefinition('normal', 'attribute vec3 input_normal;');

            this.sIOType.ProvideDefinition('normal', 'varying vec3 sio_normal;');
            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');

            if (this.animated)
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(bonesMatrix * vec4(input_normal, 0.0)).xyz;');
            else
                this.vsCode.ProvideDefinition('normal', '\tvec3 normal = normalize(worldMatrix * vec4(input_normal, 0.0)).xyz;');
            this.vsCode.ProvideDefinition('.normal', '\tsio_normal = normal;');
            this.vsCode.ProvideDefinition('.texCoords', '\tsio_texCoords = input_texCoords;');

            this.psCode.ProvideDefinition('sio2_texCoords', '\tvec2 sio2_texCoords = sio_texCoords;');
            this.psCode.ProvideDefinition('sio2_normal', '\tvec3 sio2_normal = sio_normal;');
            this.psCode.ProvideDefinition('', 
                '\tvec3 bumpMapNormal = normalize(' + AxDynamicShaderWriter.TextureSampling(pBumpMap, 'sio2_texCoords') + ').xyz * ' + pBumpMapFactor + ' * 2.0 - 1.0;\r\n' +
                '\tsio2_normal += bumpMapNormal;\r\n');


            break;
        }

        
        case AxShadingOperation.BlurMap:
        {
            var pBlurMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "blurMap", AxParameterType.ReferenceTexture);
            var pBlurMapFactor = this.ProvideParameterDefinition(this.psParams, shadingOp, "blurMapFactor", AxParameterType.Float);

            this.vsInputType.ProvideDefinition('texCoords', 'attribute vec2 input_texCoords;');

            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');

            this.vsCode.ProvideDefinition('.texCoords', '\tsio_texCoords = input_texCoords;');

            this.psCode.ProvideDefinition('sio2_texCoords', '\tvec2 sio2_texCoords = sio_texCoords;');

            this.psCode.ProvideDefinition("blurSum", "\tvec4 blurSum;");

            this.psCode.ProvideDefinition("", 
                "\tblurSum = " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords") + ";\r\n"  +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2(-0.326212, -0.405805) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2(-0.840144, -0.073580) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2(-0.695914,  0.457137) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2(-0.203345,  0.620716) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2( 0.962340, -0.194983) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2( 0.473434, -0.480026) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2( 0.519456,  0.767022) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2( 0.185461, -0.893124) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2( 0.507431,  0.064425) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2( 0.896420,  0.412458) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2(-0.321940, -0.932615) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pBlurMap, "sio2_texCoords + vec2(-0.791559, -0.597705) * " + pBlurMapFactor) + ";\r\n" +
                "\tblurSum /= 13.0;\r\n");
           
            this.ProvideColorOperationCode(shadingOp, colorOp, "blurMapAmount", this.psCode, "\t", "result.color", "blurSum");
            break;
        }

        case AxShadingOperation.HBlur:
        {
            var pHBlurMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "hBlurMap", AxParameterType.ReferenceTexture);
            var pHBlurMapFactor = this.ProvideParameterDefinition(this.psParams, shadingOp, "hBlurMapFactor", AxParameterType.Float);

            this.vsInputType.ProvideDefinition('texCoords', 'attribute vec2 input_texCoords;');

            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');

            this.vsCode.ProvideDefinition('.texCoords', '\tsio_texCoords = input_texCoords;');

            this.psCode.ProvideDefinition('sio2_texCoords', '\tvec2 sio2_texCoords = sio_texCoords;');

            this.psCode.ProvideDefinition("blurSum", "\tvec4 blurSum;");

            this.psCode.ProvideDefinition("", 
                "\tblurSum = " + AxDynamicShaderWriter.TextureSampling(pHBlurMap, "sio2_texCoords") + ";\r\n"  +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pHBlurMap, "sio2_texCoords + vec2(-0.33, 0.0) * " + pHBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pHBlurMap, "sio2_texCoords + vec2(-0.66, 0.0) * " + pHBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pHBlurMap, "sio2_texCoords + vec2(-0.99, 0.0) * " + pHBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pHBlurMap, "sio2_texCoords + vec2(0.33, 0.0) * " + pHBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pHBlurMap, "sio2_texCoords + vec2(0.66, 0.0) * " + pHBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pHBlurMap, "sio2_texCoords + vec2(0.99, 0.0) * " + pHBlurMapFactor) + ";\r\n" +
                "\tblurSum /= 7.0;");

            this.ProvideColorOperationCode(shadingOp, colorOp, "hBlurMapAmount", this.psCode, "\t", "result.color", "blurSum");
            break;
        }

        case AxShadingOperation.VBlur:
        {
            var pVBlurMap = this.ProvideParameterDefinition(this.psParams, shadingOp, "vBlurMap", AxParameterType.ReferenceTexture);
            var pVBlurMapFactor = this.ProvideParameterDefinition(this.psParams, shadingOp, "vBlurMapFactor", AxParameterType.Float);

            this.vsInputType.ProvideDefinition('texCoords', 'attribute vec2 input_texCoords;');

            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');

            this.vsCode.ProvideDefinition('.texCoords', '\tsio_texCoords = input_texCoords;');

            this.psCode.ProvideDefinition('sio2_texCoords', '\tvec2 sio2_texCoords = sio_texCoords;');

            this.psCode.ProvideDefinition("blurSum", "\tvec4 blurSum;");

            this.psCode.ProvideDefinition("", 
                "\tblurSum = " + AxDynamicShaderWriter.TextureSampling(pVBlurMap, "sio2_texCoords") + ";\r\n"  +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pVBlurMap, "sio2_texCoords + vec2(0.0, -0.33) * " + pVBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pVBlurMap, "sio2_texCoords + vec2(0.0, -0.66) * " + pVBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pVBlurMap, "sio2_texCoords + vec2(0.0, -0.99) * " + pVBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pVBlurMap, "sio2_texCoords + vec2(0.0, 0.33) * " + pVBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pVBlurMap, "sio2_texCoords + vec2(0.0, 0.66) * " + pVBlurMapFactor) + ";\r\n" +
                "\tblurSum += " + AxDynamicShaderWriter.TextureSampling(pVBlurMap, "sio2_texCoords + vec2(0.0, 0.99) * " + pVBlurMapFactor) + ";\r\n" +
                "\tblurSum /= 7.0;");

            this.ProvideColorOperationCode(shadingOp, colorOp, "vBlurMapAmount", this.psCode, "\t", "result.color", "blurSum");
            break;
        }

        case AxShadingOperation.AlignScreenQuad:
        {
            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');

            this.vsCode.ProvideDefinition('screenPos', '\tvec2 screenPos;');
            this.vsCode.ProvideDefinition('',
                    '\tscreenPos = sign(input_pos.xy);\r\n' +
                    '\tsio_pos = vec4(screenPos, 0.999, 1.0);\r\n');// + // 0.999 for zbuffer
                    //'\tsio_pos = vec4(screenPos, 0.001, 1.0);\r\n' +
                    //'\tsio_pos.y = -sio_pos.y; // remove this, instead change vertex order');

            this.vsCode.ProvideDefinition('.texCoords', '\tsio_texCoords = (screenPos + 1.0) / 2.0;');

            break;
        }
        /*



        case AxShadingOperation.ProjectTexture:
        {
                if (this.various.ProvideDefinition('projectionMap', 
                        AxString('Texture2D tProjectionMap: register(t') + AxString(this.textureBuffersInfo.count) + ');\r\n'
                        'sampler sProjectionMap: register(s' + AxString(this.textureBuffersInfo.count) + ');\r\n'))
                {
                        this.textureBuffersInfo.Add('projectionMap');
                }

                if (this.parameters.ProvideDefinition('projectionCamera', '\tmat4 projectionCamera;'))
                {
                        this.constantBuffersInfo.Get(0).Add('projectionCamera', 64);
                }

                if (this.sIOType.ProvideDefinition('projectionTexCoords', AxString('\tvec2 projectionTexCoords: TEXCOORD') + AxString(this.texCoordSlots) + ';'))
                        this.texCoordSlots++;

                this.vsCode.ProvideDefinition('projectionCoords', '\tvec4 projectionCoords;');
                this.vsCode.ProvideDefinition('', '\tprojectionCoords = mul(projectionCamera, worldPos);');
                this.vsCode.ProvideDefinition('.projectionTexCoords', '\toutput.projectionTexCoords = ((projectionCoords.xy / projectionCoords.w) + 1.0) / 2.0;');

                this.psCode.ProvideDefinition('', AxString('\t') + this.GetColorOperationCode('output.color', 'tProjectionMap.Sample(sProjectionMap, input_projectionTexCoords)', colorOp));

                break;
        }

        case AxShadingOperation.ProjectPicture:
        {
                if (this.various.ProvideDefinition('projectionMap', 
                        AxString('Texture2D tProjectionMap: register(t') + AxString(this.textureBuffersInfo.count) + ');\r\n'
                        'sampler sProjectionMap: register(s' + AxString(this.textureBuffersInfo.count) + ');\r\n'))
                {
                        this.textureBuffersInfo.Add('projectionMap');
                }

                if (this.parameters.ProvideDefinition('projectionCamera', '\tmat4 projectionCamera;'))
                {
                        this.constantBuffersInfo.Get(0).Add('projectionCamera', 64);
                }

                if (this.sIOType.ProvideDefinition('projectionTexCoords', AxString('\tvec2 projectionTexCoords: TEXCOORD') + AxString(this.texCoordSlots) + ';'))
                        this.texCoordSlots++;

                this.vsCode.ProvideDefinition('projectionCoords', '\tvec4 projectionCoords;');
                this.vsCode.ProvideDefinition('', '\tprojectionCoords = mul(projectionCamera, worldPos);');
                this.vsCode.ProvideDefinition('.projectionTexCoords', '\toutput.projectionTexCoords = ((projectionCoords.xy / projectionCoords.w) + 1.0) / 2.0;');

                this.psCode.ProvideDefinition('', 
                        AxString('\tif ((input_projectionTexCoords.x > 0.0) && (input_projectionTexCoords.x < 1.0) && (input_projectionTexCoords.y > 0.0) && (input_projectionTexCoords.y < 1.0))\r\n') +
                        '\t\t' + this.GetColorOperationCode('output.color', 'tProjectionMap.Sample(sProjectionMap, input_projectionTexCoords)', colorOp));

                break;
        }

    //*/

        case AxShadingOperation.TextureTransform:
        {
            var pTextureTransform = this.ProvideParameterDefinition(this.psParams, shadingOp, "textureTransform", AxParameterType.ReferenceTransform);

            this.vsInputType.ProvideDefinition('texCoords', 'attribute vec2 input_texCoords;');

            this.sIOType.ProvideDefinition('texCoords', 'varying vec2 sio_texCoords;');
            
            this.psCode.ProvideDefinition('sio2_texCoords', 'vec2 sio2_texCoords;');
            this.psCode.ProvideDefinition('', '\tsio2_texCoords = (' + pTextureTransform + ' * vec4(sio_texCoords, 0, 1)).xy;');
            break;
        }
        
        case AxShadingOperation.Skinning:
        {
            break;
        }

        case AxShadingOperation.Material:
        {
            this.ProvideParameterDefinition(this.vsParams, shadingOp, "ambient", AxParameterType.Color);
            this.ProvideParameterDefinition(this.vsParams, shadingOp, "diffuse", AxParameterType.Color);
            this.ProvideParameterDefinition(this.vsParams, shadingOp, "specular", AxParameterType.Color);
            this.ProvideParameterDefinition(this.vsParams, shadingOp, "gloss", AxParameterType.Float);

            this.ProvideParameterDefinition(this.psParams, shadingOp, "ambient", AxParameterType.Color);
            this.ProvideParameterDefinition(this.psParams, shadingOp, "diffuse", AxParameterType.Color);
            this.ProvideParameterDefinition(this.psParams, shadingOp, "specular", AxParameterType.Color);
            this.ProvideParameterDefinition(this.psParams, shadingOp, "gloss", AxParameterType.Float);
        }
        case AxShadingOperation.Fog:
        {
            var pFogColor = this.ProvideParameterDefinition(this.psParams, shadingOp, "fogColor", AxParameterType.Color);
            var pFogStart = this.ProvideParameterDefinition(this.vsParams, shadingOp, "fogStart", AxParameterType.Float);
            var pFogDensity = this.ProvideParameterDefinition(this.vsParams, shadingOp, "fogDensity", AxParameterType.Float);

            this.sIOType.ProvideDefinition("fogImmersion", "varying float sio_fogImmersion;");

            this.vsCode.ProvideDefinition("distance", "\tfloat distance = length(viewPosition - worldPos.xyz);");
            this.vsCode.ProvideDefinition(".fogImmersion", "\tsio_fogImmersion = clamp((distance - " + pFogStart + ") / " + pFogDensity + ", 0.0, 1.0);");

            this.psCode.ProvideDefinition("fogColorAlpha", 
                "\tvec4 fogColorAlpha = " + pFogColor + ";\r\n" +
                "\tfogColorAlpha.w = sio_fogImmersion;");

            this.ProvideColorOperationCode(shadingOp, colorOp, "fogAmount", this.psCode, "\t", "result.color", "fogColorAlpha");

            break;
        }
    }

    this.shadingOps.Add(shadingOp);
};

AxDynamicShaderWriter.prototype.GetVSSourceCode = function()
{
    if (this.numLights > 0)
    {
        this.vsParams.ProvideDefinition('',
            '#define maxLights ' + this.numLights + '\r\n' +
            'uniform vec4 lightsPosIntensity[maxLights];\r\n' +
            'uniform vec4 lightsColor[maxLights];\r\n');
        this.psParams.ProvideDefinition('',
            '#define maxLights ' + this.numLights + '\r\n' +
            'uniform vec4 lightsPosIntensity[maxLights];\r\n' +
            'uniform vec4 lightsColor[maxLights];\r\n');
    }

    return '// Generated by Axis GLSL dynamic shader writer\r\n\r\n' +

        this.vsParams.GetCode().GetContents() + '\r\n\r\n' +

        this.vsInputType.GetCode().GetContents() + '\r\n\r\n' +

        this.sIOType.GetCode().GetContents() + '\r\n\r\n' +

        this.vsCode.GetCode().GetContents() + '\r\n\tgl_Position = sio_pos;\r\n}';
};

AxDynamicShaderWriter.prototype.GetPSSourceCode = function()
{
    return '// Generated by Axis GLSL dynamic shader writer\r\n\r\n' +

        this.psParams.GetCode().GetContents() + '\r\n\r\n' +

        this.sIOType.GetCode().GetContents() + '\r\n\r\n' +

        this.psOutputType.GetCode().GetContents() + '};\r\n\r\n' +

        this.psCode.GetCode().GetContents() + 
            '\r\n' +
            '\tgl_FragColor = result.color;\r\n' +
            '\tgl_FragColor.w = 0.85;\r\n}';
};


// Private methods


/*
 * Private
 * Provides a parameter definition for the shader, giving it a unique names, by adding a number, if required, to the desired name, based on the number of the already existing shading layers with the given shading operation
 * @param {AxDynamicShaderBlockDefinitions} definitions The shader block definitions for which the color operation code shoud be generated
 * @param {AxShadingOperation} shadingOp The shading operation for which to provide the parameter
 * @param {String} desiredName The desired name for the parameter. If a parameter with the given desired name exists, a unique name will be generated, by concatenating a number to the given one
 * @param {AxParameterType} type The type of the parameter which is to be provided
 * @param {!Integer} elementsCount The number of elements of the parameter. For values other than 1, the parameter is automatically assumed to be an array. If omitted, a value of 1 is assumed.
 * @param {!Boolean} isArray Denotes whether the parameter is an array. If omitted, a value of false is assumed.
 * @return {String} The name of the provided parameter
 */
AxDynamicShaderWriter.prototype.ProvideParameterDefinition = function(definitions, shadingOp, desiredName, type, elementsCount, isArray)
{
    if (AxUtils.IsUndefinedOrNull(elementsCount))
        elementsCount = 1;

    if (AxUtils.IsUndefinedOrNull(isArray))
        isArray = false;
    
    var shadingOpCount = this.shadingOps.Count(shadingOp);
    var name = shadingOpCount === 0 ? desiredName : (desiredName + shadingOpCount);
    isArray = isArray || (elementsCount > 1);
    
    var typeName;
    switch (type)
    {
        case AxParameterType.Int: 
        { 
            typeName = "int";
            break; 
        }
        case AxParameterType.Float:
        { 
            typeName = "float";
            break; 
        }
        case AxParameterType.Bool:
        { 
            typeName = "bool";
            break; 
        }
        case AxParameterType.Color:
        { 
            typeName = "vec4";
            break; 
        }
        case AxParameterType.ReferenceVector3:
        { 
            typeName = "vec3";
            break; 
        }
        case AxParameterType.ReferenceCamera:
        { 
            typeName = "mat4";
            break; 
        }
        case AxParameterType.ReferenceTransform:
        { 
            typeName = "mat4";
            break; 
        }
        case AxParameterType.ReferenceTexture:
        { 
            typeName = "sampler2D";
            break; 
        }
    }
    
    definitions.ProvideDefinition(name, 'uniform' + ' ' + typeName + ' ' + name + ';');
    
    return name;
};

/**
 * Private
 * Creates the proper source code for a color operation. According to the color operation, a "factor" shader property is generated. The code is added to the given AxDynamicShaderBlockDefinitions.
 * @param {AxShadingOperation} shadingOp The shading operation for which the color operation code is to be generated. It is used to give the proper name to the factor
 * @param {AxColorOperation} colorOp The color operation which is to be performed
 * @param {String} desiredFactorName The desired name for the factor of the operation. The factor is a value which generally detrmines the effective amount of the sourceArg onto the destArg
 * @param {AxDynamicShaderBlockDefinitions} definitions The shader block definitions for which the color operation code shoud be generated
 * @param {String} linePrefix A prefix for each line of code, generated by the method. Typically used to add tabs
 * @param {String} destArg The destination argument, which is to hold the result of the operation
 * @param {String} sourceArg The souce argument, which is to be applied on the destination
 */
AxDynamicShaderWriter.prototype.ProvideColorOperationCode = function(shadingOp, colorOp, desiredFactorName, definitions, linePrefix, destArg, sourceArg)
{
    var paramsDefinitions = definitions === this.psCode ? this.psParams : this.vsParams;
    
    switch (colorOp)
    {
        case AxColorOperation.None:
            break;

        case AxColorOperation.Set:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("", linePrefix + destArg + " = " + sourceArg + " * " + factor + ";");
            
            break;
        }

        case AxColorOperation.Blend:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("", linePrefix + destArg + " = mix(" + destArg + ", (" + sourceArg + "), " + factor + ");");
            
            break;
        }
        
        case AxColorOperation.Add:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("", linePrefix + destArg + " += (" + sourceArg + ") * " + factor + ";");
            
            break;
        }

        case AxColorOperation.Subtract:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("", linePrefix + destArg + " -= (" + sourceArg + ") * " + factor + ";");
            
            break;
        }

        case AxColorOperation.Modulate:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("", linePrefix + destArg + " *= (" + sourceArg + ") * " + factor + ";");
            
            break;
        }

        case AxColorOperation.Lighter:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("", linePrefix + destArg + " = max(" + destArg + ", " + sourceArg + " * " + factor + ");");
            
            break;
        }

        case AxColorOperation.Darker:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("", linePrefix + destArg + " = min(" + destArg + ", " + sourceArg + " * " + factor + ");");
            
            break;
        }

        case AxColorOperation.AlphaBlend:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("colorOpArg", linePrefix + "vec4 colorOpArg;\r\n");
            definitions.ProvideDefinition("", 
                linePrefix + "colorOpArg = " + sourceArg + ";\r\n" +
                linePrefix + destArg + " = mix(" + destArg + ", colorOpArg, colorOpArg.w * " + factor + ");");
            
            break;
        }

        case AxColorOperation.AlphaAdd:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("colorOpArg", linePrefix + "vec4 colorOpArg;\r\n");
            definitions.ProvideDefinition("", 
                linePrefix + "colorOpArg = " + sourceArg + ";\r\n" +
                linePrefix + destArg + " += " + sourceArg + " * " + sourceArg + ".w * " + factor + ";");
            
            break;
        }

        case AxColorOperation.AlphaSubtract:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("colorOpArg", linePrefix + "vec4 colorOpArg;\r\n");
            definitions.ProvideDefinition("", 
                linePrefix + "colorOpArg = " + sourceArg + ";\r\n" +
                linePrefix + destArg + " -= " + sourceArg + " * " + sourceArg + ".w * " + factor + ";");
            
            break;
        }

        case AxColorOperation.AlphaModulate:
        {
            var factor = this.ProvideParameterDefinition(paramsDefinitions, shadingOp, desiredFactorName, AxParameterType.Float);
            definitions.ProvideDefinition("colorOpArg", linePrefix + "vec4 colorOpArg;\r\n");
            definitions.ProvideDefinition("", 
                linePrefix + "colorOpArg = " + sourceArg + ";\r\n" +
                linePrefix + destArg + " *= " + sourceArg + " * " + sourceArg + ".w * " + factor + ";");
            
            break;
        }

        default:
        {
            definitions.ProvideDefinition("", linePrefix + destArg + " = 0;");

            break;
        }    
    }
};

/*
 * Converts from a string from a Axis property name format to GLSL parameter name (code variable) format
 * The convention for a GLSL property name is that it starts with a lower case, each next word of the name begins with an upper case and there are no spaces between words and numbers.
 * It is used to directly convert a Axis property name to a GLSL paramter name (that is, a GLSL code variable)
 * @param {AxString} propertyName Name of a axis property which is to be converted to a valid GLSL code variable name
 * @return {AxString} The propertyName in the format of a valid GLSL parameter
 */
AxDynamicShaderWriter.PropertyNameToParameterName = function(propertyName)
{
    var result = new AxString();

    var isFirstCharacter = true;
    var character;
    var lastCharacter = new AxString();
    for (var i = 0; i < propertyName.length; i++)
    {
        character = new AxString(propertyName.contents[i]);

        if (!character.Equals(' '))
        {
            if (isFirstCharacter)
            {
                result.Insert((new AxString(character)).ToLower());
                isFirstCharacter = false;
            }
            else
            {
                if (lastCharacter.Equals(' '))
                    result.Insert((new AxString(character)).ToUpper());
                else
                    result.Insert(character);
            }
        }

        lastCharacter = character;
    }

    return new AxString(result);
};

AxDynamicShaderWriter.CorrectTexCoords = function(texCoords, texCoords1)
{
    if (AxUtils.IsUndefinedOrNull(texCoords1))
    {
        return texCoords;
        //return "(" + texCoords + ") * vec2(1.0, -1.0) + vec2(0.0, 1.0)";
    }
    else
    {
        return "vec2(" + texCoords + ", " + texCoords1 + ")";
        //return "vec2(" + texCoords + ", 1.0 - " + texCoords1 + ")";
    }
};

AxDynamicShaderWriter.TextureSampling = function(texture, texCoords, texCoords1)
{
    return 'texture2D(' + texture + ', ' + AxDynamicShaderWriter.CorrectTexCoords(texCoords, texCoords1) + ')';
};

Documentation generated by JSDoc 3.5.3 on Mon Feb 19 2018 20:39:26 GMT+0200 (FLE Standard Time)