public void Compile()
{
DualityApp.GuardSingleThreadState();
if (this.compiled) return;
var source = this.source;
if (String.IsNullOrEmpty(source)) return;
#if __ANDROID__
source = ExtractPlatformShader(source, "__ANDROID__");
#else
source = ExtractPlatformShader(source, "__PC__");
#endif
if (this.glShaderId == 0) this.glShaderId = GL.CreateShader(this.OglShaderType);
GL.ShaderSource(this.glShaderId, source);
GL.CompileShader(this.glShaderId);
int result;
GL.GetShader(this.glShaderId, ShaderParameter.CompileStatus, out result);
if (result == 0)
{
string infoLog = GL.GetShaderInfoLog(this.glShaderId);
Log.Core.WriteError("Error compiling {0}. InfoLog:\n{1}", this.OglShaderType, infoLog);
return;
}
this.compiled = true;
// Remove comments from source code before extracting variables
string sourceWithoutComments;
{
const string blockComments = @"/\*(.*?)\*/";
const string lineComments = @"//(.*?)\r?\n";
const string strings = @"""((\\[^\n]|[^""\n])*)""";
const string verbatimStrings = @"@(""[^""]*"")+";
sourceWithoutComments = Regex.Replace(source,
blockComments + "|" + lineComments + "|" + strings + "|" + verbatimStrings,
me => {
if (me.Value.StartsWith("/*") || me.Value.StartsWith("//"))
return me.Value.StartsWith("//") ? Environment.NewLine : "";
// Keep the literal strings
return me.Value;
},
RegexOptions.Singleline);
}
// Scan remaining code chunk for variable declarations
List<ShaderVarInfo> varInfoList = new List<ShaderVarInfo>();
string[] lines = sourceWithoutComments.Split(new[] {';','\n'}, StringSplitOptions.RemoveEmptyEntries);
ShaderVarInfo varInfo = new ShaderVarInfo();
foreach (string t in lines)
{
string curLine = t.TrimStart();
if (curLine.StartsWith("uniform"))
varInfo.scope = ShaderVarScope.Uniform;
else if (curLine.StartsWith("attribute"))
varInfo.scope = ShaderVarScope.Attribute;
else continue;
string[] curLineSplit = curLine.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
switch (curLineSplit[1].ToUpper())
{
case "FLOAT": varInfo.type = ShaderVarType.Float; break;
case "VEC2": varInfo.type = ShaderVarType.Vec2; break;
case "VEC3": varInfo.type = ShaderVarType.Vec3; break;
case "VEC4": varInfo.type = ShaderVarType.Vec4; break;
case "MAT2": varInfo.type = ShaderVarType.Mat2; break;
case "MAT3": varInfo.type = ShaderVarType.Mat3; break;
case "MAT4": varInfo.type = ShaderVarType.Mat4; break;
case "INT": varInfo.type = ShaderVarType.Int; break;
case "SAMPLER2D": varInfo.type = ShaderVarType.Sampler2D; break;
}
curLineSplit = curLineSplit[2].Split(new char[] {'[', ']'}, StringSplitOptions.RemoveEmptyEntries);
varInfo.name = curLineSplit[0];
varInfo.arraySize = (curLineSplit.Length > 1) ? int.Parse(curLineSplit[1]) : 1;
varInfo.glVarLoc = -1;
varInfoList.Add(varInfo);
}
this.varInfo = varInfoList.ToArray();
}