internal override void WriteSourceCode( System.IO.StreamWriter stream, Program program ) { var functionList = program.Functions; var parameterList = program.Parameters; //Generate source code header WriteProgramTitle( stream, program ); stream.WriteLine(); WriteProgramDependencies( stream, program ); stream.WriteLine(); WriteUniformParametersTitle( stream, program ); stream.WriteLine(); foreach ( var itUniformParam in parameterList ) { WriteUniformParameter( stream, itUniformParam ); stream.WriteLine( ";" ); } stream.WriteLine(); foreach ( var curFunction in functionList ) { bool needToTranslateHlsl4Color = false; Parameter colorParameter; WriteFunctionTitle( stream, curFunction ); WriteFunctionDeclaration( stream, curFunction, out needToTranslateHlsl4Color, out colorParameter ); stream.WriteLine( "{" ); var localParams = curFunction.LocalParameters; foreach ( var itParam in localParams ) { stream.Write( "\t" ); WriteLocalParameter( stream, itParam ); stream.WriteLine( ";" ); } if ( needToTranslateHlsl4Color ) { stream.WriteLine( "\t" ); WriteLocalParameter( stream, colorParameter ); stream.WriteLine( ";" ); stream.WriteLine(); stream.WriteLine( "\tFFP_Assign(iHlsl4Color_0, " + colorParameter.Name + ");" ); } curFunction.SortAtomInstances(); var atomInstances = curFunction.AtomInstances; foreach ( var itAtom in atomInstances ) { WriteAtomInstance( stream, itAtom ); } stream.WriteLine( "}" ); } stream.WriteLine(); }
internal override void WriteSourceCode( System.IO.StreamWriter stream, Program program ) { var functionList = program.Functions; var parameterList = program.Parameters; //Generate source code header WriteProgramTitle( stream, program ); stream.WriteLine(); //Generate dependencies WriteProgramDependencies( stream, program ); stream.WriteLine(); //Generate global variable code. WriteUniformParametersTitle( stream, program ); stream.WriteLine(); foreach ( var itUniformParam in parameterList ) { WriteUniformParameter( stream, itUniformParam ); stream.Write( ";\n" ); } stream.WriteLine(); //Write program function(s) foreach ( var curFunction in functionList ) { Parameter colorParameter; WriteFunctionTitle( stream, curFunction ); WriteFunctionDeclaration( stream, curFunction, out colorParameter ); stream.Write( "{\n" ); //Write local parameters var localParams = curFunction.LocalParameters; foreach ( var itParam in localParams ) { stream.Write( "\t" ); WriteLocalParameter( stream, itParam ); stream.Write( ";\n" ); } //Sort and write function atoms curFunction.SortAtomInstances(); var atomInstances = curFunction.AtomInstances; foreach ( var itAtom in atomInstances ) { WriteAtomInstance( stream, itAtom ); } stream.Write( "}\n" ); } stream.WriteLine(); }
private void BindTextureSampler( Program cpuProgram, GpuProgram gpuProgram ) { var gpuParams = gpuProgram.DefaultParameters; var progParams = cpuProgram.Parameters; //Bind the samplers foreach ( var curParam in progParams ) { if ( curParam.IsSampler ) { gpuParams.SetNamedConstant( curParam.Name, curParam.Index ); } } }
private void BindTextureSamplers( Program cpuProgram, GpuProgram gpuProgram ) { var gpuParams = gpuProgram.DefaultParameters; var progParams = cpuProgram.Parameters; //bind the samplers foreach ( var curParam in progParams ) { if ( curParam.IsSampler ) { // The optimizer may remove some unnecessary parameters, so we should ignore them gpuParams.IgnoreMissingParameters = true; gpuParams.SetNamedConstant( curParam.Name, curParam.Index ); } } }
private void WriteProgramDependencies( StreamWriter stream, Program program ) { stream.WriteLine( "//-----------------------------------------------------------------------------" ); stream.WriteLine( "// PROGRAM DEPENDENCIES" ); stream.WriteLine( "//-----------------------------------------------------------------------------" ); for ( int i = 0; i < program.DependencyCount; i++ ) { string curDependency = program.GetDependency( i ); stream.WriteLine( "#include " + '\"' + curDependency + "." + TargetLanguage + '\"' ); } }
private bool AddPSInvocation( Program psProgram, int groupOrder, ref int internalCounter ) { Function psMain = psProgram.EntryPointFunction; FunctionInvocation curFuncInvocation = null; ShadowTextureParams splitParams0 = this.shadowTextureParamsList[ 0 ]; ShadowTextureParams splitParams1 = this.shadowTextureParamsList[ 1 ]; ShadowTextureParams splitParams2 = this.shadowTextureParamsList[ 2 ]; //Compute shadow factor curFuncInvocation = new FunctionInvocation( SGXFuncComputeShadowColor3, groupOrder, internalCounter++ ); curFuncInvocation.PushOperand( this.psInDepth, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psSplitPoints, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams0.PSInLightPosition, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams1.PSInLightPosition, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams2.PSInLightPosition, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams0.TextureSampler, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams1.TextureSampler, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams2.TextureSampler, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams0.InvTextureSize, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams1.InvTextureSize, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( splitParams2.InvTextureSize, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.Out ); psMain.AddAtomInstance( curFuncInvocation ); //Apply shadow factor on diffuse color curFuncInvocation = new FunctionInvocation( SGXFuncApplyShadowFactorDiffuse, groupOrder, internalCounter++ ); curFuncInvocation.PushOperand( this.psDerivedSceneColor, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psDiffuse, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.Out ); psMain.AddAtomInstance( curFuncInvocation ); //Apply shadow factor on specular color curFuncInvocation = new FunctionInvocation( SGXFuncModulateScalar, groupOrder, internalCounter++ ); curFuncInvocation.PushOperand( this.psLocalShadowFactor, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psSpecular, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psSpecular, Operand.OpSemantic.Out ); psMain.AddAtomInstance( curFuncInvocation ); //Assign the local diffuse to output diffuse curFuncInvocation = new FunctionInvocation( FFPRenderState.FFPFuncAssign, groupOrder, internalCounter++ ); curFuncInvocation.PushOperand( this.psDiffuse, Operand.OpSemantic.In ); curFuncInvocation.PushOperand( this.psOutDiffuse, Operand.OpSemantic.Out ); psMain.AddAtomInstance( curFuncInvocation ); return true; }
private void BindSubShaders( Program program, GpuProgram gpuProgram ) { if ( program.DependencyCount > 0 ) { // Get all attached shaders so we do not attach shaders twice. // maybe GLSLProgram should take care of that ( prevent add duplicate shaders ) string attachedShaders = string.Empty; //TODO: gpuProgram.GetParameter("attach"); string subSharedDef = string.Empty; for ( int i = 0; i < program.DependencyCount; i++ ) { // Here we append _VS and _FS to the library shaders (so max each lib shader // is compiled twice once as vertex and once as fragment shader) string subShaderName = program.GetDependency( i ); if ( program.Type == GpuProgramType.Vertex ) { subShaderName += "_VS"; } else { subShaderName += "_FS"; } //Check if the library shader already compiled if ( !HighLevelGpuProgramManager.Instance.ResourceExists( subShaderName ) ) { //Create the library shader HighLevelGpuProgram subGpuProgram = HighLevelGpuProgramManager.Instance.CreateProgram( subShaderName, ResourceGroupManager. DefaultResourceGroupName, TargetLanguage, program.Type ); //Set the source name string sourceName = program.GetDependency( i ) + "." + TargetLanguage; subGpuProgram.SourceFile = sourceName; //If we have compiler errors than stop processing if ( subGpuProgram.HasCompileError ) { throw new AxiomException( "Could not compile shader library from the source file: " + sourceName ); } this.libraryPrograms.Add( subShaderName ); } //Check if the lib shader already attached to this shader if ( attachedShaders.Contains( subShaderName ) ) { subSharedDef += subShaderName + " "; } } //Check if we have something to attach if ( subSharedDef.Length > 0 ) { var nvpl = new Axiom.Collections.NameValuePairList(); nvpl.Add( "attach", subSharedDef ); gpuProgram.SetParameters( nvpl ); } } }
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(); }
private void WriteProgramDependencies( StreamWriter stream, Program program ) { for ( int i = 0; i < program.DependencyCount; i++ ) { string curDependency = program.GetDependency( i ); CacheDependencyFunctions( curDependency ); } stream.WriteLine( "//-----------------------------------------------------------------------------" ); stream.WriteLine( "// PROGRAM DEPENDENCIES" ); stream.WriteLine(); var forwardDecl = new List<FunctionInvocation>(); var functionList = program.Functions; int itFunction = 0; Function curFunction = functionList[ 0 ]; var atomInstances = curFunction.AtomInstances; int itAtom = 0; int itAtomEnd = atomInstances.Count; //Now iterate over all function atoms for ( ; itAtom != itAtomEnd; itAtom++ ) { //Skip non function invocation atom if ( atomInstances[ itAtom ] is FunctionInvocation == false ) { continue; } var funcInvoc = atomInstances[ itAtom ] as FunctionInvocation; forwardDecl.Add( funcInvoc ); // Now look into that function for other non-builtin functions and add them to the declaration list // Look for non-builtin functions // Do so by assuming that these functions do not have several variations. // Also, because GLSL is C based, functions must be defined before they are used // so we can make the assumption that we already have this function cached. // // If we find a function, look it up in the map and write it out DiscoverFunctionDependencies( funcInvoc, forwardDecl ); } //Now remove duplicate declarations forwardDecl.Sort(); forwardDecl = forwardDecl.Distinct( new FunctionInvocation.FunctionInvocationComparer() ).ToList(); for ( int i = 0; i < program.DependencyCount; i++ ) { string curDependency = program.GetDependency( i ); foreach ( var key in this.definesMap.Keys ) { if ( this.definesMap[ key ] == curDependency ) { stream.Write( this.definesMap[ key ] ); stream.Write( "\n" ); } } } // Parse the source shader and write out only the needed functions foreach ( var it in forwardDecl ) { var invoc = new FunctionInvocation( string.Empty, 0, 0, string.Empty ); string body = string.Empty; //find the function in the cache foreach ( var key in this.functionCacheMap.Keys ) { if ( !( it == key ) ) { continue; } invoc = key; body = this.functionCacheMap[ key ]; break; } if ( invoc.FunctionName.Length > 0 ) { //Write out the funciton name from the cached FunctionInvocation stream.Write( invoc.ReturnType ); stream.Write( " " ); stream.Write( invoc.FunctionName ); stream.Write( "(" ); int itOperand = 0; int itOperandEnd = invoc.OperandList.Count; while ( itOperand != itOperandEnd ) { Operand op = invoc.OperandList[ itOperand ]; Operand.OpSemantic opSemantic = op.Semantic; string paramName = op.Parameter.Name; int opMask = op.Mask; GpuProgramParameters.GpuConstantType gpuType = GpuProgramParameters.GpuConstantType.Unknown; switch ( opSemantic ) { case Operand.OpSemantic.In: stream.Write( "in " ); break; case Operand.OpSemantic.Out: stream.Write( "out " ); break; case Operand.OpSemantic.InOut: stream.Write( "inout " ); break; default: break; } //Swizzle masks are onluy defined for types like vec2, vec3, vec4 if ( opMask == (int)Operand.OpMask.All ) { gpuType = op.Parameter.Type; } else { gpuType = Operand.GetGpuConstantType( opMask ); } //We need a valid type otherwise glsl compilation will not work if ( gpuType == GpuProgramParameters.GpuConstantType.Unknown ) { throw new Core.AxiomException( "Cannot convert Operand.OpMask to GpuConstantType" ); } stream.Write( this.gpuConstTypeMap[ gpuType ] + " " + paramName ); itOperand++; //Prepare for the next operand if ( itOperand != itOperandEnd ) { stream.Write( ", " ); } } stream.WriteLine(); stream.WriteLine( "{" ); stream.WriteLine( body ); stream.WriteLine( "}" ); stream.WriteLine(); } } }
private void WriteForwardDeclarations( StreamWriter stream, Program program ) { stream.WriteLine( "//-----------------------------------------------------------------------------" ); stream.WriteLine( "// FORWARD DECLARATIONS" ); stream.WriteLine( "//-----------------------------------------------------------------------------" ); var forwardDecl = new List<string>(); // hold all generated function declarations var functionList = program.Functions; foreach ( var curFunction in functionList ) { var atomInstances = curFunction.AtomInstances; for ( int i = 0; i < atomInstances.Count; i++ ) { var itAtom = atomInstances[ i ]; //Skip non function invocation atoms if ( !( itAtom is FunctionInvocation ) ) { continue; } var funcInvoc = itAtom as FunctionInvocation; int itOperator = 0; int itOperatorEnd = funcInvoc.OperandList.Count; //Start with function declaration string funcDecl = funcInvoc.ReturnType + " " + funcInvoc.FunctionName + "("; //Now iterate overall operands while ( itOperator != itOperatorEnd ) { Parameter param = funcInvoc.OperandList[ itOperator ].Parameter; Operand.OpSemantic opSemantic = funcInvoc.OperandList[ itOperator ].Semantic; int opMask = funcInvoc.OperandList[ itOperator ].Mask; Axiom.Graphics.GpuProgramParameters.GpuConstantType gpuType = GpuProgramParameters.GpuConstantType.Unknown; //Write the semantic in, out, inout switch ( opSemantic ) { case Operand.OpSemantic.In: funcDecl += "in "; break; case Operand.OpSemantic.Out: funcDecl += "out "; break; case Operand.OpSemantic.InOut: funcDecl += "inout "; break; default: break; } //Swizzle masks are only defined fro types like vec2, vec3, vec4 if ( opMask == (int)Operand.OpMask.All ) { gpuType = param.Type; } else { //Now we have to conver the mask to operator gpuType = Operand.GetGpuConstantType( opMask ); } //We need a valid type otherwise glsl compilation will not work if ( gpuType == GpuProgramParameters.GpuConstantType.Unknown ) { throw new Core.AxiomException( "Cannot convert Operand.OpMask to GpuConstantType" ); } //Write the operand type. funcDecl += this.gpuConstTypeMap[ gpuType ]; itOperator++; //move over all operators with indirection while ( ( itOperator != itOperatorEnd ) && ( funcInvoc.OperandList[ itOperator ].IndirectionLevel != 0 ) ) { itOperator++; } //Prepare for the next operand if ( itOperator != itOperatorEnd ) { funcDecl += ", "; } } //Write function call closer. funcDecl += ");\n"; //Push the generated declaration into the vector //duplicate declarations will be removed later. forwardDecl.Add( funcDecl ); } } //Now remove duplicate declaration, first we have to sort the vector. forwardDecl.Sort(); forwardDecl = forwardDecl.Distinct().ToList(); foreach ( var it in forwardDecl ) { stream.Write( it ); } }
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(); }