internal override void WriteSourceCode(System.IO.StreamWriter stream, Program program)
        {
            var gpuType = program.Type;

            if (gpuType == GpuProgramType.Geometry)
            {
                throw new Core.AxiomException("Geometry Programs not supported in GLSL ES writer");
            }

            this.fragInputParams.Clear();
            var functionList  = program.Functions;
            var parameterList = program.Parameters;

            // Write the current version (this forces the driver to fulfill the glsl es standard)
            stream.WriteLine("#version" + this.glslVersion.ToString());

            //Default precision declaration is required in fragment and vertex shaders.
            stream.WriteLine("precision highp float");
            stream.WriteLine("precision highp int");

            //Generate source code header
            WriteProgramTitle(stream, program);
            stream.WriteLine();

            //Embed depndencies.
            WriteProgramDependencies(stream, program);
            stream.WriteLine();

            //Generate global variable code.
            WriteUniformParametersTitle(stream, program);
            stream.WriteLine();

            //Write the uniforms
            foreach (var uniformParams in parameterList)
            {
                stream.Write("uniform\t");
                stream.Write(this.gpuConstTypeMap[uniformParams.Type]);
                stream.Write("\t");
                stream.Write(uniformParams.Name);
                if (uniformParams.IsArray)
                {
                    stream.Write("[" + uniformParams.Size.ToString() + "]");
                }
                stream.WriteLine(";");
            }
            stream.WriteLine();

            //Write program function(s)
            foreach (var curFunction in functionList)
            {
                WriteFunctionTitle(stream, curFunction);

                this.inputToGLStatesMap.Clear();

                WriteInputParameters(stream, curFunction, gpuType);
                WriteOutParameters(stream, curFunction, gpuType);

                stream.WriteLine("void main() {");

                if (gpuType == GpuProgramType.Fragment)
                {
                    stream.WriteLine("\tvec4 outputColor;");
                }
                else if (gpuType == GpuProgramType.Vertex)
                {
                    stream.WriteLine("\tvec4 outputPosition;");
                }

                //Write local paraemters
                var localParam = curFunction.LocalParameters;

                foreach (var itParam in localParam)
                {
                    stream.Write("\t");
                    WriteLocalParameter(stream, itParam);
                    stream.WriteLine(";");
                }
                stream.WriteLine();

                //sort function atoms
                curFunction.SortAtomInstances();

                var atomInstances = curFunction.AtomInstances;
                foreach (var itAtom in atomInstances)
                {
                    var funcInvoc    = (FunctionInvocation)itAtom;
                    int itOperand    = 0;
                    int itOperandEnd = funcInvoc.OperandList.Count;

                    var localOs = new StringBuilder();
                    localOs.Append("\t" + funcInvoc.FunctionName + "(");

                    int curIndLevel = 0;
                    while (itOperand != itOperandEnd)
                    {
                        Operand               op         = funcInvoc.OperandList[itOperand];
                        Operand.OpSemantic    opSemantic = op.Semantic;
                        string                paramName  = op.Parameter.Name;
                        Parameter.ContentType content    = op.Parameter.Content;

                        // Check if we write to a varying because the are only readable in fragment programs
                        if (opSemantic == Operand.OpSemantic.Out || opSemantic == Operand.OpSemantic.InOut)
                        {
                            bool isVarying = false;

                            if (gpuType == GpuProgramType.Fragment)
                            {
                                if (this.fragInputParams.Contains(paramName))
                                {
                                    //Declare the copy variable
                                    string newVar  = "local_" + paramName;
                                    string tempVar = paramName;
                                    isVarying = true;

                                    // We stored the original values in the mFragInputParams thats why we have to replace the first var with o
                                    // because all vertex output vars are prefixed with o in glsl the name has to match in the fragment program.
                                    tempVar.Remove(0);
                                    tempVar.Insert(0, "o");

                                    //Declare the copy variable and assign the original
                                    stream.WriteLine("\t" + this.gpuConstTypeMap[op.Parameter.Type] + " " + newVar + " = " +
                                                     tempVar + ";\n");

                                    //Fromnow on we replace it automatic
                                    this.inputToGLStatesMap.Add(paramName, newVar);

                                    this.fragInputParams.Remove(paramName);
                                }
                            }

                            if (!isVarying)
                            {
                                foreach (var param in parameterList)
                                {
                                    if (CompareUniformByName(param, paramName))
                                    {
                                        string newVar = "local_" + paramName;

                                        if (this.inputToGLStatesMap.ContainsKey(newVar) == false)
                                        {
                                            //Declare the copy variable and assign the original

                                            stream.WriteLine("\t" + this.gpuConstTypeMap[param.Type] + " " + newVar +
                                                             " = " + paramName + ";\n");

                                            //From now on we replace it automatic
                                            this.inputToGLStatesMap.Add(paramName, newVar);
                                        }
                                    }
                                }
                            }

                            string newParam;
                            if (this.inputToGLStatesMap.ContainsKey(paramName))
                            {
                                int mask = op.Mask;                                 //our swizzle mask

                                //Here we insert the renamed param name
                                newParam = this.inputToGLStatesMap[paramName];

                                if (mask != (int)Operand.OpMask.All)
                                {
                                    newParam += "." + Operand.GetMaskAsString(mask);
                                }
                                // Now that every texcoord is a vec4 (passed as vertex attributes) we
                                // have to swizzle them according the desired type.
                                else if (gpuType == GpuProgramType.Vertex &&
                                         content == Parameter.ContentType.TextureCoordinate0 ||
                                         content == Parameter.ContentType.TextureCoordinate1 ||
                                         content == Parameter.ContentType.TextureCoordinate2 ||
                                         content == Parameter.ContentType.TextureCoordinate3 ||
                                         content == Parameter.ContentType.TextureCoordinate4 ||
                                         content == Parameter.ContentType.TextureCoordinate5 ||
                                         content == Parameter.ContentType.TextureCoordinate6 ||
                                         content == Parameter.ContentType.TextureCoordinate7)
                                {
                                    //Now generate the swizzle mask according
                                    // the type.
                                    switch (op.Parameter.Type)
                                    {
                                    case GpuProgramParameters.GpuConstantType.Float1:
                                        newParam += ".x";
                                        break;

                                    case GpuProgramParameters.GpuConstantType.Float2:
                                        newParam += ".xy";
                                        break;

                                    case GpuProgramParameters.GpuConstantType.Float3:
                                        newParam += ".xyz";
                                        break;

                                    case GpuProgramParameters.GpuConstantType.Float4:
                                        newParam += ".xyzw";
                                        break;

                                    default:
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                newParam = op.ToString();
                            }

                            itOperand++;

                            //Prepare for the next operand
                            localOs.Append(newParam);

                            int opIndLevel = 0;
                            if (itOperand != itOperandEnd)
                            {
                                opIndLevel = funcInvoc.OperandList[itOperand].IndirectionLevel;
                            }

                            if (curIndLevel != 0)
                            {
                                localOs.Append(")");
                            }
                            if (curIndLevel < opIndLevel)
                            {
                                while (curIndLevel < opIndLevel)
                                {
                                    curIndLevel++;
                                    localOs.Append("[");
                                }
                            }
                            else
                            {
                                while (curIndLevel > opIndLevel)
                                {
                                    curIndLevel--;
                                    localOs.Append("]");
                                }
                                if (opIndLevel != 0)
                                {
                                    localOs.Append("][");
                                }
                                else if (itOperand != itOperandEnd)
                                {
                                    localOs.Append(", ");
                                }
                            }
                            if (curIndLevel != 0)
                            {
                                localOs.Append("int(");
                            }
                        }
                        //Write function call closer
                        localOs.AppendLine(");");
                        localOs.AppendLine();
                        stream.Write(localOs.ToString());
                    }
                }

                if (gpuType == GpuProgramType.Fragment)
                {
                    stream.WriteLine("\tgl_FragColor = outputColor;");
                }
                else if (gpuType == GpuProgramType.Vertex)
                {
                    stream.WriteLine("\tgl_Position = outputPosition;");
                }

                stream.WriteLine("}");
            }

            stream.WriteLine();
        }
Exemple #2
0
        internal override void WriteSourceCode(System.IO.StreamWriter stream, Program program)
        {
            var gpuType = program.Type;

            if (gpuType == GpuProgramType.Geometry)
            {
                throw new Core.AxiomException("Geometry Program not supported iin GLSL writer");
            }

            this.fragInputParams.Clear();
            var functionList  = program.Functions;
            var parameterList = program.Parameters;

            // Write the current version (this force the driver to more fulfill the glsl standard)
            stream.WriteLine("#version " + this.glslVersion.ToString());

            //Generate source code header
            WriteProgramTitle(stream, program);
            stream.WriteLine();

            //Write forward declarations
            WriteForwardDeclarations(stream, program);
            stream.WriteLine();

            //Generate global variable code
            WriteUniformParametersTitle(stream, program);
            stream.WriteLine();

            //Write the uniforms
            foreach (var uniformParam in parameterList)
            {
                stream.Write("uniform\t");
                stream.Write(this.gpuConstTypeMap[uniformParam.Type]);
                stream.Write("\t");
                stream.Write(uniformParam.Name);
                if (uniformParam.IsArray)
                {
                    stream.Write("[" + uniformParam.Size.ToString() + "]");
                }
                stream.Write(";");
                stream.WriteLine();
            }
            stream.WriteLine();

            //Write program function(s)
            foreach (var curFunction in functionList)
            {
                WriteFunctionTitle(stream, curFunction);

                //Clear output mapping this map is used when we use
                //glsl built in types like gl_Color for example
                this.inputToGLStatesMap.Clear();

                //Write inout params and fill inputToGLStatesMap
                WriteInputParameters(stream, curFunction, gpuType);
                WriteOutParameters(stream, curFunction, gpuType);

                stream.Write("void main() {");
                stream.WriteLine();
                //Write local parameters
                var localParams = curFunction.LocalParameters;

                foreach (var itParam in localParams)
                {
                    stream.Write("\t");
                    WriteLocalParameter(stream, itParam);
                    stream.Write(";");
                    stream.WriteLine();
                }

                stream.WriteLine();
                //Sort function atoms
                curFunction.SortAtomInstances();
                var atomInstances = curFunction.AtomInstances;

                foreach (var itAtom in atomInstances)
                {
                    var funcInvoc = itAtom as FunctionInvocation;

                    var localOs = new StringBuilder();

                    //Write function name
                    localOs.Append("\t" + funcInvoc.FunctionAtomType + "(");
                    int curIndLevel = 0;

                    int itOperand    = 0;
                    int itOperandEnd = funcInvoc.OperandList.Count;

                    while (itOperand != itOperandEnd)
                    {
                        Operand               op         = funcInvoc.OperandList[itOperand];
                        Operand.OpSemantic    opSemantic = op.Semantic;
                        string                paramName  = op.Parameter.Name;
                        Parameter.ContentType content    = op.Parameter.Content;

                        if (opSemantic == Operand.OpSemantic.Out || opSemantic == Operand.OpSemantic.InOut)
                        {
                            bool isVarying = false;

                            // Check if we write to an varying because the are only readable in fragment programs
                            if (gpuType == GpuProgramType.Fragment)
                            {
                                if (this.fragInputParams.Contains(paramName))
                                {
                                    //Declare the copy variable
                                    string newVar  = "local_" + paramName;
                                    string tempVar = paramName;
                                    isVarying = true;

                                    // We stored the original values in the mFragInputParams thats why we have to replace the first var with o
                                    // because all vertex output vars are prefixed with o in glsl the name has to match in the fragment program.
                                    tempVar = tempVar.Remove(0);
                                    tempVar = tempVar.Insert(0, "o");

                                    //Declare the copy variable and assign the original
                                    stream.WriteLine("\t" + this.gpuConstTypeMap[op.Parameter.Type] + " " + newVar + " = " +
                                                     tempVar);

                                    //From now on we replace it automatic
                                    this.inputToGLStatesMap[paramName] = newVar;

                                    //Remove the param because now it is replaced automatic with the local variable
                                    //(which could be written).
                                    this.fragInputParams.Remove(paramName);
                                }
                            }

                            //If its not varying param check if a uniform is written
                            if (!isVarying)
                            {
                                foreach (var param in parameterList)
                                {
                                    if (GLSLProgramWriter.CompareUniformByName(param, paramName))
                                    {
                                        //Declare the copy variable
                                        string newVar = "local_" + paramName;

                                        //now we check if we already declared a uniform redirector var
                                        if (this.inputToGLStatesMap.ContainsKey(newVar) == false)
                                        {
                                            //Declare the copy variable and assign the original
                                            stream.WriteLine("\t" + this.gpuConstTypeMap[param.Type] + " " + newVar +
                                                             paramName + ";\n");

                                            //From now on we replace it automatic
                                            this.inputToGLStatesMap.Add(paramName, newVar);
                                        }
                                    }
                                }
                            }
                        }
                        if (this.inputToGLStatesMap.ContainsKey(paramName))
                        {
                            int mask = op.Mask; // our swizzle mask

                            //Here we insert the renamed param name
                            localOs.Append("." + Operand.GetMaskAsString(mask));

                            if (mask != (int)Operand.OpMask.All)
                            {
                                localOs.Append("." + Operand.GetMaskAsString(mask));
                            }

                            //Now that every texcoord is a vec4 (passed as vertex attributes)
                            //we have to swizzle them aoccording the desired type.
                            else if (gpuType == GpuProgramType.Vertex &&
                                     content == Parameter.ContentType.TextureCoordinate0 ||
                                     content == Parameter.ContentType.TextureCoordinate1 ||
                                     content == Parameter.ContentType.TextureCoordinate2 ||
                                     content == Parameter.ContentType.TextureCoordinate3 ||
                                     content == Parameter.ContentType.TextureCoordinate4 ||
                                     content == Parameter.ContentType.TextureCoordinate5 ||
                                     content == Parameter.ContentType.TextureCoordinate6 ||
                                     content == Parameter.ContentType.TextureCoordinate7)
                            {
                                //Now generate the swizzel mask according
                                //the type.
                                switch (op.Parameter.Type)
                                {
                                case GpuProgramParameters.GpuConstantType.Float1:
                                    localOs.Append(".x");
                                    break;

                                case GpuProgramParameters.GpuConstantType.Float2:
                                    localOs.Append(".xy");
                                    break;

                                case GpuProgramParameters.GpuConstantType.Float3:
                                    localOs.Append(".xyz");
                                    break;

                                case GpuProgramParameters.GpuConstantType.Float4:
                                    localOs.Append(".xyzw");
                                    break;

                                default:
                                    break;
                                }
                            }
                        }
                        else
                        {
                            localOs.Append(op.ToString());
                        }
                        itOperand++;

                        //Prepare for the next operand
                        int opIndLevel = 0;
                        if (itOperand != itOperandEnd)
                        {
                            opIndLevel = funcInvoc.OperandList[itOperand].IndirectionLevel;
                        }

                        if (curIndLevel < opIndLevel)
                        {
                            while (curIndLevel < opIndLevel)
                            {
                                curIndLevel++;
                                localOs.Append("[");
                            }
                        }
                        else
                        {
                            while (curIndLevel > opIndLevel)
                            {
                                curIndLevel--;
                                localOs.Append("]");
                            }
                            if (opIndLevel != 0)
                            {
                                localOs.Append("][");
                            }
                            else if (itOperand != itOperandEnd)
                            {
                                localOs.Append(", ");
                            }
                        }
                        if (curIndLevel != 0)
                        {
                            localOs.Append("int(");
                        }
                    }

                    //Write function call closer
                    localOs.AppendLine(");");
                    localOs.AppendLine();
                    stream.Write(localOs.ToString());
                }
                stream.WriteLine("}");
            }
            stream.WriteLine();
        }