Example #1
0
        /// <summary>
        ///     Adds the data type precision definition to the given shader.
        /// </summary>
        /// <param name="shaderType">Type of the shader.</param>
        protected override StringBuilder SetPrecision(SLShaderType shaderType)
        {
            if (ShaderDesc.Precision[(int)shaderType] != null)
            {
                DebugLog.Warning("Using [xSLPrecision] is not supported in GLSL 1.1. Ignored");
            }

            return(new StringBuilder());
        }
Example #2
0
        /// <summary>
        ///     Adds the data type precision definition to the given shader.
        /// </summary>
        /// <param name="shaderType">Type of the shader.</param>
        protected override StringBuilder SetPrecision(SLShaderType shaderType)
        {
            var result      = new StringBuilder();
            var defaultPrec = true;

            if (ShaderDesc.Precision[(int)shaderType] != null)
            {
                var precAttr = ShaderDesc.Precision[(int)shaderType];

                var floatPrec = precAttr.Properties.FirstOrDefault(prop => prop.Name == "floatPrecision");
                var intPrec   = precAttr.Properties.FirstOrDefault(prop => prop.Name == "intPrecision");

                if (floatPrec.Name != null)
                {
                    var floatPrecVal = ((xSLShader.xSLPrecision)floatPrec.Argument.Value).ToString();
                    result.Append("precision ").Append(floatPrecVal.ToLower()).Append("p");
                    result.Append(" float;").NewLine();

                    defaultPrec = false;
                }

                if (intPrec.Name != null)
                {
                    var intPrecVal = ((xSLShader.xSLPrecision)intPrec.Argument.Value).ToString();
                    result.Append("precision ").Append(intPrecVal.ToLower()).Append("p");
                    result.Append(" int;").NewLine();
                }
            }

            if (defaultPrec && shaderType == SLShaderType.FragmentShader)
            {
                DebugLog.Warning("Target GLSLES requires [xSLPrecision] at 'FragmentShader()' to set " +
                                 "the precision of data type 'float'. Using high precision as default");

                result.Append("precision highp float;").NewLine();
            }

            if (result.Length == 0)
            {
                return(result);
            }

            result.Replace(Environment.NewLine, Environment.NewLine + "\t").Length--;
            result = new StringBuilder("#ifdef").Append(" GL_ES").NewLine().Intend().Append(result);
            return(result.Append("#endif").NewLine(2));
        }
Example #3
0
        internal static StringBuilder CreateShader(StringBuilder shader, SLShaderType type)
        {
            var result = new StringBuilder();

            var shaderObj = type == SLShaderType.VertexShader
                ? GL.CreateShader(ShaderType.VertexShader)
                : GL.CreateShader(ShaderType.FragmentShader);

            GL.ShaderSource(shaderObj, shader.ToString());
            GL.CompileShader(shaderObj);

            string info;

            GL.GetShaderInfoLog(shaderObj, out info);

            if (info.Length > 0 && info != "No errors.\n")
            {
                result.Append(info).NewLine();
            }

            return(result);
        }
Example #4
0
 /// <summary>
 ///     Adds the data type precision definition to the given shader.
 /// </summary>
 /// <param name="shaderType">Type of the shader.</param>
 protected override StringBuilder SetPrecision(SLShaderType shaderType)
 {
     // depending on target
     return(new StringBuilder());
 }
        /// <summary>
        ///     Builds the given type of shader.
        /// </summary>
        /// <param name="shaderType">Type of the shader.</param>
        /// <returns></returns>
        internal virtual StringBuilder BuildShader(SLShaderType shaderType)
        {
            var result = new StringBuilder();

            // corresponding functions
            var functions = ShaderDesc.Funcs[(int)shaderType];

            // collect all referenced variables
            var refVars = new List <VariableDesc>();

            foreach (var func in functions.Where(func => func.Variables != null))
            {
                refVars.AddRange(func.Variables);
            }

            var varDescs       = new Collection <VariableDesc>();
            var shaderDescType = ShaderDesc.Type.ToType();
            var memberVars     = refVars.Where(var => var.Definition.DeclaringType.ToType() == shaderDescType);

            foreach (var memberVar in memberVars)
            {
                var globVar = ShaderDesc.Variables.FirstOrDefault(var => var.Definition == memberVar.Definition);

                if (globVar != null)
                {
                    var globIndex = ShaderDesc.Variables.IndexOf(globVar);

                    ShaderDesc.Variables[globIndex].IsReferenced = true;

                    memberVar.Attribute    = globVar.Attribute;
                    memberVar.DataType     = globVar.DataType;
                    memberVar.IsArray      = globVar.IsArray;
                    memberVar.IsReferenced = true;

                    varDescs.Add(memberVar);
                }
            }

            // check variables
            PostVariableCheck(shaderType, varDescs, refVars);
            if (DebugLog.Abort)
            {
                return(null);
            }

            // add precision to output
            result.Append(SetPrecision(shaderType));
            if (DebugLog.Abort)
            {
                return(null);
            }

            // add variables to shader output
            foreach (var varDesc in varDescs.Distinct().OrderBy(var => var.Attribute))
            {
                var dataType = ShaderMapping.Types[varDesc.DataType];

                var varType = varDesc.Attribute.ToString().ToLower();
                varType = varType.Remove(0, 3).Remove(varType.Length - 12);

                result.Append(varType).Space().Append(dataType).Space();
                result.Append(varDesc.Definition.Name);

                if (varDesc.IsArray)
                {
                    var valStr = varDesc.Value.ToString();
                    valStr = valStr.Remove(0, valStr.IndexOf('['));
                    result.Append(valStr.Remove(valStr.IndexOf(']') + 1));
                }

                if (varDesc.Attribute == SLVariableType.xSLConstAttribute)
                {
                    result.Assign().Append(varDesc.Value);
                }

                result.Semicolon().NewLine();
            }

            if (result.Length > 2)
            {
                result.Length -= 2;
            }

            // add all functions to shader output
            foreach (var func in ShaderDesc.Funcs[(int)shaderType])
            {
                result.NewLine(2).Append(func.Signature).NewLine().Append(func.Body);
            }

            return(result);
        }
 /// <summary>
 ///     Sets the data type precision for the given shader type.
 /// </summary>
 /// <param name="shaderType">Type of the shader.</param>
 protected abstract StringBuilder SetPrecision(SLShaderType shaderType);
        /// <summary>
        ///     Checks member and referenced variables after translating the shader.
        /// </summary>
        /// <param name="shaderType">Type of the shader.</param>
        /// <param name="varDescs">The variable descs.</param>
        /// <param name="refVars">The referenced variables.</param>
        private void PostVariableCheck(SLShaderType shaderType, Collection <VariableDesc> varDescs,
                                       List <VariableDesc> refVars)
        {
            // check if varyings and attributes are used properly
            var varVars = varDescs.Where(var => var.Attribute == SLVariableType.xSLVaryingAttribute);

            if (shaderType == SLShaderType.FragmentShader)
            {
                foreach (var invalidVar in varVars.Where(var => !var.IsReferenced))
                {
                    DebugLog.Error("Varying '" + invalidVar.Definition.Name + "' is used in 'FragmentShader()'" +
                                   " but was not set in 'VertexShader()'", invalidVar.Instruction);
                }

                var attrVars = varDescs.Where(var => var.Attribute == SLVariableType.xSLAttributeAttribute).ToList();

                foreach (var invalidVar in attrVars)
                {
                    DebugLog.Error("Attribute '" + invalidVar.Definition.Name + "' cannot be " +
                                   "used in in 'FragmentShader()'" + invalidVar.Instruction);
                }
            }
            else
            {
                var fragFunc   = ShaderDesc.Funcs[(int)SLShaderType.FragmentShader];
                var mergedVars = fragFunc.SelectMany(func => func.Variables).ToList();

                foreach (var invalidVar in varVars.Where(var => !mergedVars.Contains(var)))
                {
                    DebugLog.Warning("Varying '" + invalidVar.Definition.Name + "' was set in 'VertexShader()'" +
                                     " but is not used in 'FragmentShader()'", invalidVar.Instruction);
                }
            }

            // check if constants have been set
            var constVars = varDescs.Where(var => var.Attribute == SLVariableType.xSLConstAttribute).ToList();

            foreach (var constVar in refVars.Where(constVars.Contains).Where(con => con.Value != null))
            {
                DebugLog.Error("Constant '" + constVar.Definition.Name + "' cannot be initialized " +
                               "in 'VertexShader()'", constVar.Instruction);
            }

            foreach (var constVar in constVars.Where(var => var.Value == null))
            {
                constVar.Value = ShaderDesc.Variables.First(var => var.Definition == constVar.Definition).Value;
                if (constVar.Value != null)
                {
                    continue;
                }

                DebugLog.Error("Constant '" + constVar.Definition.Name + "' was not initialized", constVar.Instruction);
            }

            // check if invalid variables are set
            var nestedTypes = typeof(xSLShader).GetNestedTypes(BindingFlags.NonPublic);

            var attrType = nestedTypes.FirstOrDefault(type => type.Name == shaderType + "Attribute");
            var mandType = nestedTypes.FirstOrDefault(type => type == typeof(xSLShader.MandatoryAttribute));

            var allProps   = typeof(xSLShader).GetProperties(BindingFlags.Instance | BindingFlags.NonPublic);
            var validProps = allProps.Where(prop => prop.CustomAttributes.Any(attr => attr.AttributeType == attrType));
            var validNames = validProps.Select(prop => prop.Name).ToList();

            var globalVars  = refVars.Where(def => def.Definition.DeclaringType.IsType <xSLShader>()).ToList();
            var globalNames = globalVars.Select(var => var.Definition.Name).ToList();

            foreach (var memberVar in globalNames.Where(var => !validNames.Contains(var)))
            {
                var instr = globalVars.First(var => var.Definition.Name == memberVar).Instruction;
                DebugLog.Error("'" + memberVar + "' cannot be used in '" + shaderType + "()'", instr);
            }

            // check if necessary variables are set
            var mandVars = allProps.Where(prop => prop.CustomAttributes.Any(attr => attr.AttributeType == mandType));

            foreach (var mandVar in mandVars)
            {
                var mandVarName = mandVar.Name;

                if (validNames.Contains(mandVarName) && !globalNames.Contains(mandVarName))
                {
                    DebugLog.Error("'" + mandVarName + "' has to be set in '" + shaderType + "()'");
                }

                if (globalNames.Count(var => var == mandVarName) > 1)
                {
                    var instr = globalVars.Last(var => var.Definition.Name == mandVarName).Instruction;
                    DebugLog.Warning("'" + mandVarName + "' has been set more than" +
                                     " once in '" + shaderType + "()'", instr);
                }
            }
        }