/// <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()); }
/// <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)); }
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); }
/// <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); } } }