diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj index 781c9d15..5ee4ded3 100644 --- a/Source/Core/Builder.csproj +++ b/Source/Core/Builder.csproj @@ -200,6 +200,12 @@ + + True + True + Resources.resx + + @@ -563,11 +569,6 @@ - - True - True - Resources.resx - @@ -663,17 +664,9 @@ SettingsSingleFileGenerator Settings.Designer.cs - - - - + - - - - - - + @@ -689,21 +682,8 @@ - - - - - - - - - - - - - - - + + diff --git a/Source/Core/Properties/Resources.Designer.cs b/Source/Core/Properties/Resources.Designer.cs index 38c20ac1..dacd671f 100755 --- a/Source/Core/Properties/Resources.Designer.cs +++ b/Source/Core/Properties/Resources.Designer.cs @@ -370,46 +370,6 @@ namespace CodeImp.DoomBuilder.Properties { } } - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] display2d_fsaa { - get { - object obj = ResourceManager.GetObject("display2d_fsaa", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] display2d_fullbright { - get { - object obj = ResourceManager.GetObject("display2d_fullbright", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] display2d_normal { - get { - object obj = ResourceManager.GetObject("display2d_normal", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] display2d_vp { - get { - object obj = ResourceManager.GetObject("display2d_vp", resourceCulture); - return ((byte[])(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -1070,26 +1030,6 @@ namespace CodeImp.DoomBuilder.Properties { } } - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] plotter { - get { - object obj = ResourceManager.GetObject("plotter", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] plotter_vp { - get { - object obj = ResourceManager.GetObject("plotter_vp", resourceCulture); - return ((byte[])(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -1580,46 +1520,6 @@ namespace CodeImp.DoomBuilder.Properties { } } - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] things2d_fill { - get { - object obj = ResourceManager.GetObject("things2d_fill", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] things2d_sprite { - get { - object obj = ResourceManager.GetObject("things2d_sprite", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] things2d_thing { - get { - object obj = ResourceManager.GetObject("things2d_thing", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] things2d_vp { - get { - object obj = ResourceManager.GetObject("things2d_vp", resourceCulture); - return ((byte[])(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -1810,156 +1710,6 @@ namespace CodeImp.DoomBuilder.Properties { } } - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_constant_color { - get { - object obj = ResourceManager.GetObject("world3d_constant_color", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_customvertexcolor_fog_vp { - get { - object obj = ResourceManager.GetObject("world3d_customvertexcolor_fog_vp", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_customvertexcolor_vp { - get { - object obj = ResourceManager.GetObject("world3d_customvertexcolor_vp", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_fullbright { - get { - object obj = ResourceManager.GetObject("world3d_fullbright", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_fullbright_highlight { - get { - object obj = ResourceManager.GetObject("world3d_fullbright_highlight", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_lightpass { - get { - object obj = ResourceManager.GetObject("world3d_lightpass", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_lightpass_vp { - get { - object obj = ResourceManager.GetObject("world3d_lightpass_vp", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_main { - get { - object obj = ResourceManager.GetObject("world3d_main", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_main_fog { - get { - object obj = ResourceManager.GetObject("world3d_main_fog", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_main_highlight { - get { - object obj = ResourceManager.GetObject("world3d_main_highlight", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_main_highlight_fog { - get { - object obj = ResourceManager.GetObject("world3d_main_highlight_fog", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_main_vp { - get { - object obj = ResourceManager.GetObject("world3d_main_vp", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_skybox { - get { - object obj = ResourceManager.GetObject("world3d_skybox", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_skybox_vp { - get { - object obj = ResourceManager.GetObject("world3d_skybox_vp", resourceCulture); - return ((byte[])(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Byte[]. - /// - internal static byte[] world3d_vertex_color { - get { - object obj = ResourceManager.GetObject("world3d_vertex_color", resourceCulture); - return ((byte[])(obj)); - } - } - /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/Source/Core/Properties/Resources.resx b/Source/Core/Properties/Resources.resx index 48978a18..0af1b28f 100755 --- a/Source/Core/Properties/Resources.resx +++ b/Source/Core/Properties/Resources.resx @@ -613,81 +613,6 @@ ..\Resources\Github.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - ..\Resources\display2d.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\display2d_fsaa.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\display2d_fullbright.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\display2d_normal.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\plotter.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\plotter.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\things2d.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\things2d_fill.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\things2d_sprite.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\things2d_thing.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_constant_color.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_customvertexcolor.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_customvertexcolor_fog.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_fullbright.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_fullbright_highlight.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_lightpass.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_lightpass.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_main.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_main.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_main_fog.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_main_highlight.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_main_highlight_fog.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_skybox.vp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_skybox.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ..\Resources\world3d_vertex_color.fp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\Resources\AboutBack.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/Source/Core/Rendering/RenderDevice.cs b/Source/Core/Rendering/RenderDevice.cs index 800772c6..3154ae02 100755 --- a/Source/Core/Rendering/RenderDevice.cs +++ b/Source/Core/Rendering/RenderDevice.cs @@ -27,6 +27,7 @@ using System.Reflection; using System.IO; using System.Text; using System.Linq; +using CodeImp.DoomBuilder.Rendering.Shaders; #endregion @@ -66,27 +67,38 @@ namespace CodeImp.DoomBuilder.Rendering DeclareUniform(UniformName.fogsettings, "fogsettings", UniformType.Vec4); DeclareUniform(UniformName.fogcolor, "fogcolor", UniformType.Vec4); - DeclareShader(ShaderName.display2d_fsaa, "display2d.vp", "display2d_fsaa.fp"); - DeclareShader(ShaderName.display2d_normal, "display2d.vp", "display2d_normal.fp"); - DeclareShader(ShaderName.display2d_fullbright, "display2d.vp", "display2d_fullbright.fp"); - DeclareShader(ShaderName.things2d_thing, "things2d.vp", "things2d_thing.fp"); - DeclareShader(ShaderName.things2d_sprite, "things2d.vp", "things2d_sprite.fp"); - DeclareShader(ShaderName.things2d_fill, "things2d.vp", "things2d_fill.fp"); - DeclareShader(ShaderName.plotter, "plotter.vp", "plotter.fp"); - DeclareShader(ShaderName.world3d_main, "world3d_main.vp", "world3d_main.fp"); - DeclareShader(ShaderName.world3d_fullbright, "world3d_main.vp", "world3d_fullbright.fp"); - DeclareShader(ShaderName.world3d_main_highlight, "world3d_main.vp", "world3d_main_highlight.fp"); - DeclareShader(ShaderName.world3d_fullbright_highlight, "world3d_main.vp", "world3d_fullbright_highlight.fp"); - DeclareShader(ShaderName.world3d_main_vertexcolor, "world3d_customvertexcolor.vp", "world3d_main.fp"); - DeclareShader(ShaderName.world3d_skybox, "world3d_skybox.vp", "world3d_skybox.fp"); - DeclareShader(ShaderName.world3d_main_highlight_vertexcolor, "world3d_customvertexcolor.vp", "world3d_main_highlight.fp"); - DeclareShader(ShaderName.world3d_main_fog, "world3d_lightpass.vp", "world3d_main_fog.fp"); - DeclareShader(ShaderName.world3d_main_highlight_fog, "world3d_lightpass.vp", "world3d_main_highlight_fog.fp"); - DeclareShader(ShaderName.world3d_main_fog_vertexcolor, "world3d_customvertexcolor_fog.vp", "world3d_main_fog.fp"); - DeclareShader(ShaderName.world3d_main_highlight_fog_vertexcolor, "world3d_customvertexcolor_fog.vp", "world3d_main_highlight_fog.fp"); - DeclareShader(ShaderName.world3d_vertex_color, "world3d_main.vp", "world3d_vertex_color.fp"); - DeclareShader(ShaderName.world3d_constant_color, "world3d_customvertexcolor.vp", "world3d_constant_color.fp"); - DeclareShader(ShaderName.world3d_lightpass, "world3d_lightpass.vp", "world3d_lightpass.fp"); + // 2d fsaa + CompileShader(ShaderName.display2d_fsaa, "display2d.shader", "display2d_fsaa"); + + // 2d normal + CompileShader(ShaderName.display2d_normal, "display2d.shader", "display2d_normal"); + CompileShader(ShaderName.display2d_fullbright, "display2d.shader", "display2d_fullbright"); + + // 2d things + CompileShader(ShaderName.things2d_thing, "things2d.shader", "things2d_thing"); + CompileShader(ShaderName.things2d_sprite, "things2d.shader", "things2d_sprite"); + CompileShader(ShaderName.things2d_fill, "things2d.shader", "things2d_fill"); + + // non-fog 3d shaders + CompileShader(ShaderName.world3d_main, "world3d.shader", "world3d_main"); + CompileShader(ShaderName.world3d_fullbright, "world3d.shader", "world3d_fullbright"); + CompileShader(ShaderName.world3d_main_highlight, "world3d.shader", "world3d_main_highlight"); + CompileShader(ShaderName.world3d_fullbright_highlight, "world3d.shader", "world3d_fullbright_highlight"); + CompileShader(ShaderName.world3d_vertex_color, "world3d.shader", "world3d_vertex_color"); + CompileShader(ShaderName.world3d_main_vertexcolor, "world3d.shader", "world3d_main_vertexcolor"); + CompileShader(ShaderName.world3d_constant_color, "world3d.shader", "world3d_constant_color"); + + // skybox shader + CompileShader(ShaderName.world3d_skybox, "world3d_skybox.shader", "world3d_skybox"); + + // fog 3d shaders + CompileShader(ShaderName.world3d_main_fog, "world3d.shader", "world3d_main_fog"); + CompileShader(ShaderName.world3d_main_highlight_fog, "world3d.shader", "world3d_main_highlight_fog"); + CompileShader(ShaderName.world3d_main_fog_vertexcolor, "world3d.shader", "world3d_main_fog_vertexcolor"); + CompileShader(ShaderName.world3d_main_highlight_fog_vertexcolor, "world3d.shader", "world3d_main_highlight_fog_vertexcolor"); + + // pure light shader + CompileShader(ShaderName.world3d_lightpass, "world3d.shader", "world3d_lightpass"); SetupSettings(); } @@ -139,6 +151,26 @@ namespace CodeImp.DoomBuilder.Rendering RenderDevice_DeclareShader(Handle, name, name.ToString(), GetResourceText(vertResourceName), GetResourceText(fragResourceName)); } + // save precompiled shaders -- don't build from scratch every time + private static Dictionary precompiledGroups = new Dictionary(); + public void CompileShader(ShaderName internalName, string groupName, string shaderName) + { + ShaderGroup sg; + + if (precompiledGroups.ContainsKey(groupName)) + sg = precompiledGroups[groupName]; + else sg = ShaderCompiler.Compile(GetResourceText(groupName)); + + Shader s = sg.GetShader(shaderName); + + if (s == null) + throw new RenderDeviceException(string.Format("Shader {0}::{1} not found", groupName, shaderName)); + + General.WriteLogLine(string.Format("===========================================\nDBG: loading shader {0} / {1}\n\nVertex source: {2}\n\nFragment source: {3}\n\n===========================================", + groupName, shaderName, s.GetVertexSource(), s.GetFragmentSource())); + RenderDevice_DeclareShader(Handle, internalName, internalName.ToString(), s.GetVertexSource(), s.GetFragmentSource()); + } + static string GetResourceText(string name) { string fullname = string.Format("CodeImp.DoomBuilder.Resources.{0}", name); @@ -617,7 +649,6 @@ namespace CodeImp.DoomBuilder.Rendering things2d_thing, things2d_sprite, things2d_fill, - plotter, world3d_main, world3d_fullbright, world3d_main_highlight, diff --git a/Source/Core/Rendering/Shaders/ShaderCompiler.cs b/Source/Core/Rendering/Shaders/ShaderCompiler.cs new file mode 100755 index 00000000..e1c5c3a5 --- /dev/null +++ b/Source/Core/Rendering/Shaders/ShaderCompiler.cs @@ -0,0 +1,853 @@ +using CodeImp.DoomBuilder.ZDoom; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CodeImp.DoomBuilder.Rendering.Shaders +{ + internal class ShaderField + { + public int Line; + public List> ArrayDimensions; + public string TypeName; + public List Initializer; + public string Name; + } + + internal class ShaderFunction + { + public int Line; + public int CodeLine; + public string ReturnValue; + public string Name; + public List Arguments; + public List Code; + } + + class Shader + { + private ShaderGroup Group; + internal string ParentName; + public int CodeLine; + public string Name; + // data input for vertex shader + public List In; + // data between vertex and fragment shader + public List V2F; + // data output for fragment shader + public List Out; + // source for main() of vertex shader + public int SourceVertexLine; + public List SourceVertex; + // source for main() of fragment shader + public int SourceFragmentLine; + public List SourceFragment; + + private const string GLSLInternalSeparator = "_"; + + public Shader(ShaderGroup group) + { + Group = group; + } + + // dumps all uniforms into a string + private string GetTokenListSource(List tokens) + { + string ss = ""; + foreach (ZScriptToken tok in tokens) + { + bool isBlock = false; + switch (tok.Type) + { + case ZScriptTokenType.LineComment: + ss += "//"; + break; + case ZScriptTokenType.BlockComment: + ss += "/*"; + isBlock = true; + break; + } + ss += tok.Value; + if (isBlock) ss += "*/"; + } + return ss; + } + + private string GetUniformSource() + { + + string output = ""; + foreach (ShaderField field in Group.Uniforms) + { + + output += string.Format("#line {0}\n", field.Line); + + output += "uniform "; + output += field.TypeName; + + if (field.ArrayDimensions != null) + { + foreach (List arrayDim in field.ArrayDimensions) + output += "[" + GetTokenListSource(arrayDim) + "]"; + } + + output += " " + field.Name; + + if (field.Initializer != null) + output += GetTokenListSource(field.Initializer); + + output += ";\n"; + + } + + return output; + + } + + private string GetDataIOInternalName(string block, string name) + { + return string.Format("{2}SC{2}B{0}{2}F{1}", block, name, GLSLInternalSeparator); + } + + private string GetDataIOSource(string prefix, string blockid, List block, bool vertexInput) + { + + string output = ""; + foreach (ShaderField field in block) + { + + output += string.Format("#line {0}\n", field.Line); + + if (vertexInput) + { + int location; + switch (field.Name) + { + case "Position": + location = 0; + break; + case "Color": + location = 1; + break; + case "TextureCoordinate": + location = 2; + break; + case "Normal": + location = 3; + break; + default: + throw new ShaderCompileException("Invalid input field {0} (not supported)", field.Name); + } + + output += string.Format("layout(location = {0}) ", location); + } + + output += prefix + " "; + output += field.TypeName; + + if (field.ArrayDimensions != null) + { + foreach (List arrayDim in field.ArrayDimensions) + output += "[" + GetTokenListSource(arrayDim) + "]"; + } + + output += " " + GetDataIOInternalName(blockid, field.Name); + + if (field.Initializer != null) + output += GetTokenListSource(field.Initializer); + + output += ";\n"; + + } + + return output; + + } + + private void GetReferencedFunctions(List source, List functions) + { + + for (int i = 0; i < source.Count; i++) + { + + ZScriptToken token = source[i]; + if (token.Type != ZScriptTokenType.Identifier) + continue; + + if (functions.Contains(token.Value)) + continue; + + // check token to the left - needs to not be identifier. + // check token to the right - needs to be open parenthesis + // --- + // the idea is that we can differentiate pixel = desaturate(...) from vec4 desaturate(1,1,1,1) + // + ZScriptTokenType leftToken = ZScriptTokenType.Invalid; + ZScriptTokenType rightToken = ZScriptTokenType.Invalid; + + for (int j = i-1; j >= 0; j--) + { + ZScriptTokenType tt = source[j].Type; + if (!IsWhitespace(tt)) + { + leftToken = tt; + break; + } + } + + for (int j = i+1; j < source.Count; j++) + { + ZScriptTokenType tt = source[j].Type; + if (!IsWhitespace(tt)) + { + rightToken = tt; + break; + } + } + + if (leftToken != ZScriptTokenType.Identifier && rightToken == ZScriptTokenType.OpenParen) + { + + // find function + functions.Add(token.Value); + // if function was found, recurse and find functions it may depend on. + ShaderFunction func = Group.GetFunction(token.Value); + if (func != null) + GetReferencedFunctions(func.Code, functions); + + } + + } + + } + + private string GetFunctionSource(List shaderSource) + { + + List functionNames = new List(); + GetReferencedFunctions(shaderSource, functionNames); + + string preOutput = ""; + string output = ""; + + foreach (string functionName in functionNames) + { + ShaderFunction func = Group.GetFunction(functionName); + if (func == null) + continue; + + string funcOutput = string.Format("#line {0}\n", func.Line) + func.ReturnValue + " " + func.Name + " (" + GetTokenListSource(func.Arguments) + ")"; + preOutput += funcOutput + ";\n"; + + funcOutput += " {\n" + string.Format("#line {0}\n", func.CodeLine) +GetTokenListSource(func.Code) + "}\n"; + output += funcOutput; + + } + + return preOutput + "\n" + output; + + } + + private static bool IsWhitespace(ZScriptTokenType t) + { + switch (t) + { + case ZScriptTokenType.Whitespace: + case ZScriptTokenType.LineComment: + case ZScriptTokenType.BlockComment: + case ZScriptTokenType.Newline: + return true; + } + return false; + } + + public List ReplaceIO(List tokens) + { + + List output = new List(tokens); + + // we replace all . with GetDataBlockInternalName(, ) + // thus, "in" and "out" are reserved keywords and may not be found out of such context + for (int i = 0; i < output.Count; i++) + { + + ZScriptToken token = output[i]; + if (token.Type != ZScriptTokenType.Identifier) + continue; + if (token.Value != "in" && token.Value != "out" && token.Value != "v2f") + continue; + + string structPrefix = token.Value; + + int startIndex = i; + + i++; + // skip whitespace... + for (; i < output.Count; i++) + if (!IsWhitespace(output[i].Type)) break; + + if (i >= output.Count || output[i].Type != ZScriptTokenType.Dot) + continue; + + i++; + // skip whitespace again... + for (; i < output.Count; i++) + if (!IsWhitespace(output[i].Type)) break; + + if (i >= output.Count || output[i].Type != ZScriptTokenType.Identifier) + continue; + + // + string fieldName = output[i].Value; + string realName = GetDataIOInternalName(structPrefix, fieldName); + // now, remove all tokens between prefix and current + output.RemoveRange(startIndex + 1, i - startIndex); + ZScriptToken realToken = new ZScriptToken(output[startIndex]); + realToken.Value = realName; + output[startIndex] = realToken; + i = startIndex - 1; + + // check if this field exists, just in case. and produce an error + List searchIn = null; + switch (structPrefix) + { + case "in": + searchIn = In; + break; + case "out": + searchIn = Out; + break; + case "v2f": + searchIn = V2F; + break; + } + if (searchIn != null) + { + bool found = false; + foreach (ShaderField field in searchIn) + { + if (field.Name == fieldName) + { + found = true; + break; + } + } + if (!found) + throw new ShaderCompileException("Referenced non-existent {0} field {1}", structPrefix, fieldName); + } + + } + + return output; + + } + + public string GetVertexSource() + { + if (In == null || V2F == null || SourceVertex == null) + throw new ShaderCompileException("Tried to compile incomplete shader {0}", Name); + + string src = ""; + src += GetDataIOSource("in", "in", In, true) + "\n\n"; + src += GetDataIOSource("out", "v2f", V2F, false) + "\n\n"; + src += GetUniformSource() + "\n"; + src += GetFunctionSource(SourceVertex) + "\n\n"; + src += "void main() {\n" + string.Format("#line {0}\n", SourceVertexLine) + GetTokenListSource(ReplaceIO(SourceVertex)) + "\n}\n\n"; + + return src; + } + + public string GetFragmentSource() + { + if (Out == null || V2F == null || SourceFragment == null) + throw new ShaderCompileException("Tried to compile incomplete shader {0}", Name); + + string src = ""; + src += GetDataIOSource("in", "v2f", V2F, false) + "\n\n"; + src += GetDataIOSource("out", "out", Out, false) + "\n\n"; + src += GetUniformSource() + "\n"; + src += GetFunctionSource(SourceFragment) + "\n\n"; + src += "void main() {\n" + string.Format("#line {0}\n", SourceFragmentLine) + GetTokenListSource(ReplaceIO(SourceFragment)) + "\n}\n\n"; + + return src; + } + } + + class ShaderGroup + { + internal List Uniforms = new List(); + internal List Shaders = new List(); + internal List Functions = new List(); + + public Shader GetShader(string identifier) + { + foreach (Shader s in Shaders) + if (s.Name == identifier) return s; + return null; + } + + public ShaderFunction GetFunction(string identifier) + { + foreach (ShaderFunction f in Functions) + if (f.Name == identifier) return f; + return null; + } + } + + class ShaderCompileException : Exception + { + public ShaderCompileException(string fmt, params object[] v) : base(string.Format(fmt, v)) { } + } + + class ShaderCompiler + { + // this is to implement partial parsing. it counts {}, (), and []. it stops parsing at the specified type, if outside of nesting. + // also if last block token equals to the type, it will stop at the outer level. (i.e. last }) + private static List ReadEverythingUntil(ZScriptTokenizer t, ZScriptTokenType type, bool eofIsOk, bool skipWhitespace) + { + List tokens = new List(); + + int levelCurly = 0; + int levelSquare = 0; + int levelParen = 0; + + while (true) + { + if (skipWhitespace) + t.SkipWhitespace(); + + long cpos = t.Reader.BaseStream.Position; + + ZScriptToken token = t.ReadToken(); + if (token == null) + { + if (!eofIsOk) + throw new ShaderCompileException("Expected {0} or token, got ", type); + break; + } + + // if this is the end token, don't check anything -- just return + if (levelCurly == 0 && levelSquare == 0 && levelParen == 0 && token.Type == type) + { + // rewind and return token list + t.Reader.BaseStream.Position = cpos; + break; + } + + switch (token.Type) + { + case ZScriptTokenType.OpenCurly: + levelCurly++; + break; + case ZScriptTokenType.CloseCurly: + levelCurly--; + break; + case ZScriptTokenType.OpenParen: + levelParen++; + break; + case ZScriptTokenType.CloseParen: + levelParen--; + break; + case ZScriptTokenType.OpenSquare: + levelSquare++; + break; + case ZScriptTokenType.CloseSquare: + levelSquare--; + break; + } + + tokens.Add(token); + + } + + return tokens; + } + + private static void CompileShaderField(ShaderField field, ZScriptTokenizer t) + { + + ZScriptToken token; + // read name and array dimensions + while (true) + { + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.OpenSquare, ZScriptTokenType.Identifier); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected array dimensions or field name, got {0}", token?.ToString() ?? ""); + + // array finished + if (token.Type == ZScriptTokenType.Identifier) + { + field.Name = token.Value; + break; + } + + // read array + List arrayDimTokens = ReadEverythingUntil(t, ZScriptTokenType.CloseSquare, false, false); + if (field.ArrayDimensions == null) + field.ArrayDimensions = new List>(); + field.ArrayDimensions.Add(arrayDimTokens); + + token = t.ExpectToken(ZScriptTokenType.CloseSquare); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected closing square brace, got {0}", token?.ToString() ?? ""); + } + + // read additional array dimensions if present, and initializer. or end parsing + while (true) + { + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.OpenSquare, ZScriptTokenType.OpAssign, ZScriptTokenType.Semicolon); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected array dimensions, initializer or semicolon, got {0}", token?.ToString() ?? ""); + + // field is done + if (token.Type == ZScriptTokenType.Semicolon) + break; + + // has initializer + if (token.Type == ZScriptTokenType.OpAssign) + { + field.Initializer = ReadEverythingUntil(t, ZScriptTokenType.Semicolon, false, false); + token = t.ExpectToken(ZScriptTokenType.Semicolon); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected semicolon, got {0}", token?.ToString() ?? ""); + break; + } + + // read array + List arrayDimTokens = ReadEverythingUntil(t, ZScriptTokenType.CloseSquare, false, false); + if (field.ArrayDimensions == null) + field.ArrayDimensions = new List>(); + field.ArrayDimensions.Add(arrayDimTokens); + + token = t.ExpectToken(ZScriptTokenType.CloseSquare); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected closing square brace, got {0}", token?.ToString() ?? ""); + } + + } + + private static void CompileUniforms(ShaderGroup output, ZScriptTokenizer t) + { + + // so a type of a variable is normally identifier+array dimensions + // array dimensions may also exist on the variable itself (oh god this shitty C syntax) + t.SkipWhitespace(); + ZScriptToken token; + + token = t.ExpectToken(ZScriptTokenType.OpenCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected uniforms block, got {0}", token?.ToString() ?? ""); + + while (true) + { + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier, ZScriptTokenType.CloseCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected uniform or end of block, got {0}", token?.ToString() ?? ""); + + if (token.Type == ZScriptTokenType.CloseCurly) + break; // done reading uniforms + + // first goes the name, then array dimensions, then the variable name, then array dimensions, then initializer + ShaderField field = new ShaderField(); + field.Line = t.PositionToLine(token.Position); + field.TypeName = token.Value; + + CompileShaderField(field, t); + + // done reading field, add it + output.Uniforms.Add(field); + + } + + } + + private static void CompileFunctions(ShaderGroup output, ZScriptTokenizer t) + { + + // so a type of a variable is normally identifier+array dimensions + // array dimensions may also exist on the variable itself (oh god this shitty C syntax) + t.SkipWhitespace(); + ZScriptToken token; + + token = t.ExpectToken(ZScriptTokenType.OpenCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected functions block, got {0}", token?.ToString() ?? ""); + + while (true) + { + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier, ZScriptTokenType.CloseCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected function or end of block, got {0}", token?.ToString() ?? ""); + + if (token.Type == ZScriptTokenType.CloseCurly) + break; // done reading functions + + // () { } + ShaderFunction func = new ShaderFunction(); + func.Line = t.PositionToLine(token.Position); + func.ReturnValue = token.Value; + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected function name, got {0}", token?.ToString() ?? ""); + + func.Name = token.Value; + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.OpenParen); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected function argument list, got {0}", token?.ToString() ?? ""); + + func.Arguments = ReadEverythingUntil(t, ZScriptTokenType.CloseParen, false, false); + + token = t.ExpectToken(ZScriptTokenType.CloseParen); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected end of function arguments, got {0}", token?.ToString() ?? ""); + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.OpenCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected function code block, got {0}", token?.ToString() ?? ""); + + func.CodeLine = t.PositionToLine(token.Position); + func.Code = ReadEverythingUntil(t, ZScriptTokenType.CloseCurly, false, false); + + token = t.ExpectToken(ZScriptTokenType.CloseCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected end of function code block, got {0}", token?.ToString() ?? ""); + + output.Functions.Add(func); + + } + + } + + private static List CompileShaderDataBlock(ZScriptTokenizer t) + { + + List fields = new List(); + + t.SkipWhitespace(); + ZScriptToken token = t.ExpectToken(ZScriptTokenType.OpenCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected data block, got {0}", token?.ToString() ?? ""); + + while (true) + { + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier, ZScriptTokenType.CloseCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected data field or end of block, got {0}", token?.ToString() ?? ""); + + if (token.Type == ZScriptTokenType.CloseCurly) + break; + + ShaderField field = new ShaderField(); + field.Line = t.PositionToLine(token.Position); + field.TypeName = token.Value; + + CompileShaderField(field, t); + + fields.Add(field); + + } + + return fields; + + } + + private static List CompileShaderSource(ZScriptTokenizer t) + { + + // syntax: + // fragment { ... code ... } + // or + // vertex { ... code ... } + + t.SkipWhitespace(); + ZScriptToken token = t.ExpectToken(ZScriptTokenType.OpenCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected shader source block, got {0}", token?.ToString() ?? ""); + + List tokens = ReadEverythingUntil(t, ZScriptTokenType.CloseCurly, false, false); + + token = t.ExpectToken(ZScriptTokenType.CloseCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected end of shader source block, got {0}", token?.ToString() ?? ""); + + return tokens; + + } + + private static void CompileShader(ShaderGroup output, ZScriptTokenizer t) + { + + t.SkipWhitespace(); + + ZScriptToken token = t.ExpectToken(ZScriptTokenType.Identifier); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected shader identifier, got {0}", token?.ToString() ?? ""); + + t.SkipWhitespace(); + + Shader s = new Shader(output); + s.Name = token.Value; + output.Shaders.Add(s); + + token = t.ExpectToken(ZScriptTokenType.Identifier, ZScriptTokenType.OpenCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected parent identifier or shader block, got {0}", token?.ToString() ?? ""); + + // has parent shader id + if (token.Type == ZScriptTokenType.Identifier) + { + + if (token.Value != "extends") + throw new ShaderCompileException("Expected 'extends', got {0}", token.ToString()); + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected parent identifier, got {0}", token?.ToString() ?? ""); + + s.ParentName = token.Value; + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.OpenCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected shader block, got {0}", token?.ToString() ?? ""); + + } + + + s.CodeLine = t.PositionToLine(token.Position); + + while (true) + { + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier, ZScriptTokenType.CloseCurly); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected shader sub-block or end of block, got {0}", token?.ToString() ?? ""); + + if (token.Type == ZScriptTokenType.CloseCurly) + break; + + switch (token.Value) + { + case "in": + s.In = CompileShaderDataBlock(t); + break; + case "out": + s.Out = CompileShaderDataBlock(t); + break; + case "v2f": + s.V2F = CompileShaderDataBlock(t); + break; + case "vertex": + s.SourceVertex = CompileShaderSource(t); + if (s.SourceVertex != null && s.SourceVertex.Count > 0) + s.SourceVertexLine = t.PositionToLine(s.SourceVertex[0].Position); + break; + case "fragment": + s.SourceFragment = CompileShaderSource(t); + if (s.SourceFragment != null && s.SourceFragment.Count > 0) + s.SourceFragmentLine = t.PositionToLine(s.SourceFragment[0].Position); + break; + default: + throw new ShaderCompileException("Expected shader sub-block, got {0}", token.ToString()); + } + + } + + } + + public static ShaderGroup Compile(string src) + { + ShaderGroup output = new ShaderGroup(); + + using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(src))) + using (BinaryReader br = new BinaryReader(ms)) + { + ZScriptTokenizer t = new ZScriptTokenizer(br); + + // main cycle + // in the root scope, we allow three blocks: + // - uniforms{} + // - functions{} + // - shader {} + // everything else is a syntax error. + while (true) + { + t.SkipWhitespace(); + ZScriptToken token = t.ExpectToken(ZScriptTokenType.Identifier); + if (token == null) + break; + + if (!token.IsValid) + throw new ShaderCompileException("Expected 'uniforms', 'functions', or 'shader'; got {0}", token.ToString()); + + switch (token.Value) + { + case "uniforms": + CompileUniforms(output, t); + break; + case "functions": + CompileFunctions(output, t); + break; + case "shader": + CompileShader(output, t); + break; + default: + throw new ShaderCompileException("Expected 'uniforms', 'functions', or 'shader'; got {0}", token.ToString()); + } + } + + // done parsing, postprocess - apply parents + foreach (Shader s in output.Shaders) + { + List parents = new List(); + parents.Add(s.Name); + Shader p = s; + while (p.ParentName != null && p.ParentName != "") + { + string parentName = p.ParentName; + if (parents.Contains(parentName)) + throw new ShaderCompileException("Recursive parent shader {0} found", parentName); + parents.Add(parentName); + p = output.GetShader(parentName); + if (p == null) + throw new ShaderCompileException("Parent shader {0} not found", parentName); + + if (s.In == null) s.In = p.In; + if (s.Out == null) s.Out = p.Out; + if (s.V2F == null) s.V2F = p.V2F; + if (s.SourceFragment == null) + { + s.SourceFragment = p.SourceFragment; + s.SourceFragmentLine = p.SourceFragmentLine; + } + if (s.SourceVertex == null) + { + s.SourceVertex = p.SourceVertex; + s.SourceVertexLine = p.SourceVertexLine; + } + } + } + + return output; + } + } + } +} diff --git a/Source/Core/Resources/display2d.shader b/Source/Core/Resources/display2d.shader new file mode 100755 index 00000000..8acf625b --- /dev/null +++ b/Source/Core/Resources/display2d.shader @@ -0,0 +1,118 @@ +uniforms +{ + mat4 projection; + + // Render settings + // x = texel width + // y = texel height + // z = FSAA blend factor + // w = transparency + vec4 rendersettings; + float desaturation; + + sampler2D texture1; + vec4 texturefactor; +} + +functions +{ + vec3 desaturate(vec3 texel) + { + float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); + return mix(texel, vec3(gray), desaturation); + } + + // This blends the max of 2 pixels + vec4 addcolor(vec4 c1, vec4 c2) + { + return vec4( + max(c1.r, c2.r), + max(c1.g, c2.g), + max(c1.b, c2.b), + clamp(c1.a + c2.a * 0.5, 0.0, 1.0)); + } +} + +shader display2d_normal +{ + in + { + vec3 Position; + vec4 Color; + vec2 TextureCoordinate; + } + + v2f + { + vec4 Color; + vec2 UV; + } + + out + { + vec4 FragColor; + } + + vertex + { + gl_Position = projection * vec4(in.Position, 1.0); + v2f.Color = in.Color; + v2f.UV = in.TextureCoordinate; + } + + fragment + { + vec4 c = texture(texture1, v2f.UV); + out.FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * v2f.Color; + out.FragColor *= texturefactor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + } +} + +shader display2d_fullbright extends display2d_normal +{ + fragment + { + vec4 c = texture(texture1, v2f.UV); + out.FragColor = vec4(c.rgb, c.a * rendersettings.w); + out.FragColor *= texturefactor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + } +} + +shader display2d_fsaa extends display2d_normal +{ + fragment + { + vec4 c = texture(texture1, v2f.UV); + + // If this pixel is not drawn on... + if(c.a < 0.1) + { + // Mix the colors of nearby pixels + vec4 n = vec4(0.0); + n = addcolor(n, texture(texture1, vec2(v2f.UV.x + rendersettings.x, v2f.UV.y))); + n = addcolor(n, texture(texture1, vec2(v2f.UV.x - rendersettings.x, v2f.UV.y))); + n = addcolor(n, texture(texture1, vec2(v2f.UV.x, v2f.UV.y + rendersettings.y))); + n = addcolor(n, texture(texture1, vec2(v2f.UV.x, v2f.UV.y - rendersettings.y))); + + out.FragColor = vec4(desaturate(n.rgb), n.a * rendersettings.z * rendersettings.w); + } + else + { + out.FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * v2f.Color; + } + + out.FragColor *= texturefactor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + } +} \ No newline at end of file diff --git a/Source/Core/Resources/display2d.vp b/Source/Core/Resources/display2d.vp deleted file mode 100644 index 4d00806c..00000000 --- a/Source/Core/Resources/display2d.vp +++ /dev/null @@ -1,16 +0,0 @@ - -in vec3 AttrPosition; -in vec4 AttrColor; -in vec2 AttrUV; - -out vec4 Color; -out vec2 UV; - -uniform mat4 projection; - -void main() -{ - gl_Position = projection * vec4(AttrPosition, 1.0); - Color = AttrColor; - UV = AttrUV; -} diff --git a/Source/Core/Resources/display2d_fsaa.fp b/Source/Core/Resources/display2d_fsaa.fp deleted file mode 100644 index 59cec51b..00000000 --- a/Source/Core/Resources/display2d_fsaa.fp +++ /dev/null @@ -1,60 +0,0 @@ - -in vec4 Color; -in vec2 UV; - -out vec4 FragColor; - -// Render settings -// x = texel width -// y = texel height -// z = FSAA blend factor -// w = transparency -uniform vec4 rendersettings; -uniform float desaturation; - -uniform sampler2D texture1; -uniform vec4 texturefactor; - -// This blends the max of 2 pixels -vec4 addcolor(vec4 c1, vec4 c2) -{ - return vec4( - max(c1.r, c2.r), - max(c1.g, c2.g), - max(c1.b, c2.b), - clamp(c1.a + c2.a * 0.5, 0.0, 1.0)); -} - -vec3 desaturate(vec3 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return mix(texel, vec3(gray), desaturation); -} - -void main() -{ - vec4 c = texture(texture1, UV); - - // If this pixel is not drawn on... - if(c.a < 0.1) - { - // Mix the colors of nearby pixels - vec4 n = vec4(0.0); - n = addcolor(n, texture(texture1, vec2(UV.x + rendersettings.x, UV.y))); - n = addcolor(n, texture(texture1, vec2(UV.x - rendersettings.x, UV.y))); - n = addcolor(n, texture(texture1, vec2(UV.x, UV.y + rendersettings.y))); - n = addcolor(n, texture(texture1, vec2(UV.x, UV.y - rendersettings.y))); - - FragColor = vec4(desaturate(n.rgb), n.a * rendersettings.z * rendersettings.w); - } - else - { - FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * Color; - } - - FragColor *= texturefactor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif -} diff --git a/Source/Core/Resources/display2d_fullbright.fp b/Source/Core/Resources/display2d_fullbright.fp deleted file mode 100644 index c6d973b1..00000000 --- a/Source/Core/Resources/display2d_fullbright.fp +++ /dev/null @@ -1,26 +0,0 @@ - -in vec4 Color; -in vec2 UV; - -out vec4 FragColor; - -// Render settings -// x = texel width -// y = texel height -// z = FSAA blend factor -// w = transparency -uniform vec4 rendersettings; - -uniform sampler2D texture1; -uniform vec4 texturefactor; - -void main() -{ - vec4 c = texture(texture1, UV); - FragColor = vec4(c.rgb, c.a * rendersettings.w); - FragColor *= texturefactor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif -} diff --git a/Source/Core/Resources/display2d_normal.fp b/Source/Core/Resources/display2d_normal.fp deleted file mode 100644 index a58cb381..00000000 --- a/Source/Core/Resources/display2d_normal.fp +++ /dev/null @@ -1,33 +0,0 @@ - -in vec4 Color; -in vec2 UV; - -out vec4 FragColor; - -// Render settings -// x = texel width -// y = texel height -// z = FSAA blend factor -// w = transparency -uniform vec4 rendersettings; -uniform float desaturation; - -uniform sampler2D texture1; -uniform vec4 texturefactor; - -vec3 desaturate(vec3 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return mix(texel, vec3(gray), desaturation); -} - -void main() -{ - vec4 c = texture(texture1, UV); - FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * Color; - FragColor *= texturefactor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif -} diff --git a/Source/Core/Resources/plotter.fp b/Source/Core/Resources/plotter.fp deleted file mode 100644 index e0fff0cc..00000000 --- a/Source/Core/Resources/plotter.fp +++ /dev/null @@ -1,20 +0,0 @@ - -in vec4 Color; -in vec2 UV; - -out vec4 FragColor; - -void main() -{ - // line stipple - if (mod(UV.x, 2.0) > 1.0) - discard; - - // line smoothing - float linewidth = 3.0; - float falloff = 1.8; //1.5..2.5 - float centerdist = abs(UV.y); - float a = pow(clamp((linewidth - centerdist) / linewidth, 0.0, 1.0), falloff); - - FragColor = vec4(Color.rgb, Color.a * a); -} diff --git a/Source/Core/Resources/plotter.vp b/Source/Core/Resources/plotter.vp deleted file mode 100644 index 478e82eb..00000000 --- a/Source/Core/Resources/plotter.vp +++ /dev/null @@ -1,16 +0,0 @@ - -in vec3 AttrPosition; -in vec4 AttrColor; -in vec2 AttrUV; - -out vec4 Color; -out vec2 UV; - -uniform mat4 projection; - -void main() -{ - gl_Position = projection * vec4(AttrPosition, 1.0f); - Color = AttrColor; - UV = AttrUV; -} diff --git a/Source/Core/Resources/things2d.shader b/Source/Core/Resources/things2d.shader new file mode 100755 index 00000000..f94ea9bc --- /dev/null +++ b/Source/Core/Resources/things2d.shader @@ -0,0 +1,105 @@ +uniforms +{ + mat4 projection; + + // Render settings + // w = transparency + vec4 rendersettings; + float desaturation; + + sampler2D texture1; + vec4 texturefactor; + + vec4 fillColor; +} + +functions +{ + vec3 desaturate(vec3 texel) + { + float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); + return mix(texel, vec3(gray), desaturation); + } +} + +shader things2d +{ + in + { + vec3 Position; + vec4 Color; + vec2 TextureCoordinate; + } + + v2f + { + vec4 Color; + vec2 UV; + } + + out + { + vec4 FragColor; + } + + vertex + { + gl_Position = projection * vec4(in.Position, 1.0); + v2f.Color = in.Color; + v2f.UV = in.TextureCoordinate; + } +} + +shader things2d_fill extends things2d +{ + fragment + { + out.FragColor = fillColor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + } +} + +shader things2d_thing extends things2d +{ + fragment + { + vec4 c = texture(texture1, v2f.UV); + out.FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * v2f.Color; + + out.FragColor *= texturefactor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + } +} + +shader things2d_sprite extends things2d +{ + fragment + { + // Take this pixel's color + vec4 c = texture(texture1, v2f.UV); + + // Modulate it by selection color + if (v2f.Color.a > 0.0) + { + vec3 cr = desaturate(c.rgb); + out.FragColor = vec4((cr.r + v2f.Color.r) / 2.0, (cr.g + v2f.Color.g) / 2.0, (cr.b + v2f.Color.b) / 2.0, c.a * rendersettings.w * v2f.Color.a); + } + else + { + // Or leave it as it is + out.FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w); + } + + out.FragColor *= texturefactor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + } +} \ No newline at end of file diff --git a/Source/Core/Resources/things2d.vp b/Source/Core/Resources/things2d.vp deleted file mode 100644 index 4d00806c..00000000 --- a/Source/Core/Resources/things2d.vp +++ /dev/null @@ -1,16 +0,0 @@ - -in vec3 AttrPosition; -in vec4 AttrColor; -in vec2 AttrUV; - -out vec4 Color; -out vec2 UV; - -uniform mat4 projection; - -void main() -{ - gl_Position = projection * vec4(AttrPosition, 1.0); - Color = AttrColor; - UV = AttrUV; -} diff --git a/Source/Core/Resources/things2d_fill.fp b/Source/Core/Resources/things2d_fill.fp deleted file mode 100644 index 8f984384..00000000 --- a/Source/Core/Resources/things2d_fill.fp +++ /dev/null @@ -1,16 +0,0 @@ - -in vec4 Color; -in vec2 UV; - -out vec4 FragColor; - -uniform vec4 fillColor; - -void main() -{ - FragColor = fillColor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif -} diff --git a/Source/Core/Resources/things2d_sprite.fp b/Source/Core/Resources/things2d_sprite.fp deleted file mode 100644 index bd26a71f..00000000 --- a/Source/Core/Resources/things2d_sprite.fp +++ /dev/null @@ -1,43 +0,0 @@ - -in vec4 Color; -in vec2 UV; - -out vec4 FragColor; - -// Render settings -// w = transparency -uniform vec4 rendersettings; -uniform float desaturation; - -uniform sampler2D texture1; -uniform vec4 texturefactor; - -vec3 desaturate(vec3 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return mix(texel, vec3(gray), desaturation); -} - -void main() -{ - // Take this pixel's color - vec4 c = texture(texture1, UV); - - // Modulate it by selection color - if (Color.a > 0.0) - { - vec3 cr = desaturate(c.rgb); - FragColor = vec4((cr.r + Color.r) / 2.0, (cr.g + Color.g) / 2.0, (cr.b + Color.b) / 2.0, c.a * rendersettings.w * Color.a); - } - else - { - // Or leave it as it is - FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w); - } - - FragColor *= texturefactor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif -} diff --git a/Source/Core/Resources/things2d_thing.fp b/Source/Core/Resources/things2d_thing.fp deleted file mode 100644 index 6e0a8106..00000000 --- a/Source/Core/Resources/things2d_thing.fp +++ /dev/null @@ -1,31 +0,0 @@ - -in vec4 Color; -in vec2 UV; - -out vec4 FragColor; - -// Render settings -// w = transparency -uniform vec4 rendersettings; -uniform float desaturation; - -uniform sampler2D texture1; -uniform vec4 texturefactor; - -vec3 desaturate(vec3 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return mix(texel, vec3(gray), desaturation); -} - -void main() -{ - vec4 c = texture(texture1, UV); - FragColor = vec4(desaturate(c.rgb), c.a * rendersettings.w) * Color; - - FragColor *= texturefactor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif -} diff --git a/Source/Core/Resources/world3d.shader b/Source/Core/Resources/world3d.shader new file mode 100755 index 00000000..547c6b38 --- /dev/null +++ b/Source/Core/Resources/world3d.shader @@ -0,0 +1,359 @@ +uniforms +{ + mat4 world; + mat4 view; + mat4 projection; + mat4 modelnormal; + vec4 campos; + + vec4 highlightcolor; + vec4 stencilColor; + float desaturation; + + vec4 fogsettings; + vec4 fogcolor; + vec4 vertexColor; + + sampler2D texture1; + + // dynamic light related + vec4 lightPosAndRadius; + vec3 lightOrientation; // this is a vector that points in light's direction + vec2 light2Radius; // this is used with spotlights + vec4 lightColor; + float ignoreNormals; // ignore normals in lighting equation. used for non-attenuated lights on models. + float spotLight; // use lightOrientation +} + +functions +{ + // This adds fog color to current pixel color + vec4 getFogColor(vec3 PosW, vec4 color) + { + float fogdist = max(16.0, distance(PosW, campos.xyz)); + float fogfactor = exp2(campos.w * fogdist); + + color.rgb = mix(lightColor.rgb, color.rgb, fogfactor); + return color; + } + + vec4 desaturate(vec4 texel) + { + float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); + return vec4(mix(texel.rgb, vec3(gray), desaturation), texel.a); + } +} + +shader world3d_main +{ + in + { + vec3 Position; + vec4 Color; + vec2 TextureCoordinate; + vec3 Normal; + } + + v2f + { + vec4 Color; + vec2 UV; + vec4 viewpos; + } + + out + { + vec4 FragColor; + } + + vertex + { + v2f.viewpos = view * world * vec4(in.Position, 1.0); + gl_Position = projection * v2f.viewpos; + v2f.Color = in.Color; + v2f.UV = in.TextureCoordinate; + } + + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + out.FragColor = desaturate(tcolor * v2f.Color); + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +shader world3d_fullbright extends world3d_main +{ + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + tcolor.a *= v2f.Color.a; + out.FragColor = tcolor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +shader world3d_main_highlight extends world3d_main +{ + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + if (tcolor.a == 0.0) + { + out.FragColor = tcolor; + } + else + { + // Blend texture color and vertex color + vec4 ncolor = desaturate(tcolor * v2f.Color); + + out.FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(v2f.Color.a + 0.25, 0.5)); + } + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +shader world3d_fullbright_highlight extends world3d_fullbright +{ + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + if(tcolor.a == 0.0) + { + out.FragColor = tcolor; + } + else + { + // Blend texture color and vertex color + vec4 ncolor = tcolor * v2f.Color; + + out.FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (tcolor.rgb - 0.4 * highlightcolor.a), max(v2f.Color.a + 0.25, 0.5)); + } + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +shader world3d_vertex_color extends world3d_main +{ + fragment + { + out.FragColor = v2f.Color; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +shader world3d_main_vertexcolor extends world3d_main +{ + vertex + { + v2f.viewpos = view * world * vec4(in.Position, 1.0); + gl_Position = projection * v2f.viewpos; + v2f.Color = vertexColor; + v2f.UV = in.TextureCoordinate; + } +} + +shader world3d_constant_color extends world3d_main_vertexcolor +{ + fragment + { + out.FragColor = vertexColor; + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0f) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +// world3d_main_highlight with vertex program from world3d_vertexcolor +// to-do: rewrite into a function +shader world3d_highlight_vertexcolor extends world3d_main_highlight +{ + vertex + { + v2f.viewpos = view * world * vec4(in.Position, 1.0); + gl_Position = projection * v2f.viewpos; + v2f.Color = vertexColor; + v2f.UV = in.TextureCoordinate; + } +} + +shader world3d_lightpass extends world3d_main +{ + v2f + { + vec4 Color; + vec2 UV; + vec3 PosW; + vec3 Normal; + vec4 viewpos; + } + + vertex + { + v2f.viewpos = view * world * vec4(in.Position, 1.0); + gl_Position = projection * v2f.viewpos; + v2f.PosW = (world * vec4(in.Position, 1.0)).xyz; + v2f.Color = in.Color; + v2f.UV = in.TextureCoordinate; + v2f.Normal = normalize((modelnormal * vec4(in.Normal, 1.0)).xyz); + } + + fragment + { + //is face facing away from light source? + // update 01.02.2017: offset the equation by 3px back to try to emulate GZDoom's broken visibility check. + float diffuseContribution = dot(v2f.Normal, normalize(lightPosAndRadius.xyz - v2f.PosW + v2f.Normal * 3.0)); + if (diffuseContribution < 0.0 && ignoreNormals < 0.5) + discard; + diffuseContribution = max(diffuseContribution, 0.0); // to make sure + + //is pixel in light range? + float dist = distance(v2f.PosW, lightPosAndRadius.xyz); + if (dist > lightPosAndRadius.w) + discard; + + //is pixel tranparent? + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + if (tcolor.a == 0.0) + discard; + + //if it is - calculate color at current pixel + vec4 lightColorMod = vec4(0.0, 0.0, 0.0, 1.0); + + lightColorMod.rgb = lightColor.rgb * max(lightPosAndRadius.w - dist, 0.0) / lightPosAndRadius.w; + + if (spotLight > 0.5) + { + vec3 lightDirection = normalize(lightPosAndRadius.xyz - v2f.PosW); + float cosDir = dot(lightDirection, lightOrientation); + float df = smoothstep(light2Radius.y, light2Radius.x, cosDir); + lightColorMod.rgb *= df; + } + + if (lightColor.a > 0.979 && lightColor.a < 0.981) // attenuated light 98% + lightColorMod.rgb *= diffuseContribution; + + if (lightColorMod.r <= 0.0 && lightColorMod.g <= 0.0 && lightColorMod.b <= 0.0) + discard; + + lightColorMod.rgb *= lightColor.a; + if (lightColor.a > 0.4) //Normal, vavoom or negative light (or attenuated) + lightColorMod *= tcolor; + + out.FragColor = desaturate(lightColorMod); //Additive light + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + } +} + +shader world3d_main_fog extends world3d_lightpass +{ + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + if (tcolor.a == 0.0) + { + out.FragColor = tcolor; + } + else + { + out.FragColor = desaturate(getFogColor(v2f.PosW, tcolor * v2f.Color)); + } + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +shader world3d_main_highlight_fog extends world3d_main_fog +{ + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + if (tcolor.a == 0.0) + { + out.FragColor = tcolor; + } + else + { + // Blend texture color and vertex color + vec4 ncolor = desaturate(getFogColor(v2f.PosW, tcolor * v2f.Color)); + + out.FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(ncolor.a + 0.25, 0.5)); + } + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} + +// world3d_fog, but with vertex shader from customvertexcolor_fog +// to-do: rewrite into a function +shader world3d_main_fog_vertexcolor extends world3d_main_fog +{ + vertex + { + v2f.viewpos = view * world * vec4(in.Position, 1.0); + gl_Position = projection * v2f.viewpos; + v2f.PosW = (world * vec4(in.Position, 1.0)).xyz; + v2f.Color = vertexColor; + v2f.UV = in.TextureCoordinate; + v2f.Normal = normalize((modelnormal * vec4(in.Normal, 1.0)).xyz); + } +} + +shader world3d_main_highlight_fog_vertexcolor extends world3d_main_highlight_fog +{ + vertex + { + v2f.viewpos = view * world * vec4(in.Position, 1.0); + gl_Position = projection * v2f.viewpos; + v2f.PosW = (world * vec4(in.Position, 1.0)).xyz; + v2f.Color = vertexColor; + v2f.UV = in.TextureCoordinate; + v2f.Normal = normalize((modelnormal * vec4(in.Normal, 1.0)).xyz); + } +} \ No newline at end of file diff --git a/Source/Core/Resources/world3d_constant_color.fp b/Source/Core/Resources/world3d_constant_color.fp deleted file mode 100644 index 8e50abcf..00000000 --- a/Source/Core/Resources/world3d_constant_color.fp +++ /dev/null @@ -1,22 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 vertexColor; - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -void main() -{ - FragColor = vertexColor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0f) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_customvertexcolor.vp b/Source/Core/Resources/world3d_customvertexcolor.vp deleted file mode 100644 index 05758195..00000000 --- a/Source/Core/Resources/world3d_customvertexcolor.vp +++ /dev/null @@ -1,23 +0,0 @@ - -in vec3 AttrPosition; -in vec4 AttrColor; -in vec2 AttrUV; -in vec3 AttrNormal; - -out vec4 Color; -out vec2 UV; -out vec4 viewpos; - -uniform mat4 world; -uniform mat4 view; -uniform mat4 projection; - -uniform vec4 vertexColor; - -void main() -{ - viewpos = view * world * vec4(AttrPosition, 1.0); - gl_Position = projection * viewpos; - Color = vertexColor; - UV = AttrUV; -} diff --git a/Source/Core/Resources/world3d_customvertexcolor_fog.vp b/Source/Core/Resources/world3d_customvertexcolor_fog.vp deleted file mode 100644 index 252f1867..00000000 --- a/Source/Core/Resources/world3d_customvertexcolor_fog.vp +++ /dev/null @@ -1,28 +0,0 @@ - -in vec3 AttrPosition; -in vec4 AttrColor; -in vec2 AttrUV; -in vec3 AttrNormal; - -out vec4 Color; -out vec2 UV; -out vec3 PosW; -out vec3 Normal; -out vec4 viewpos; - -uniform mat4 world; -uniform mat4 view; -uniform mat4 projection; -uniform mat4 modelnormal; - -uniform vec4 vertexColor; - -void main() -{ - viewpos = view * world * vec4(AttrPosition, 1.0); - gl_Position = projection * viewpos; - PosW = (world * vec4(AttrPosition, 1.0)).xyz; - Color = vertexColor; - UV = AttrUV; - Normal = normalize((modelnormal * vec4(AttrNormal, 1.0)).xyz); -} diff --git a/Source/Core/Resources/world3d_fullbright.fp b/Source/Core/Resources/world3d_fullbright.fp deleted file mode 100644 index 0be00c5f..00000000 --- a/Source/Core/Resources/world3d_fullbright.fp +++ /dev/null @@ -1,27 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 stencilColor; - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -uniform sampler2D texture1; - -void main() -{ - vec4 tcolor = texture(texture1, UV); - tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); - tcolor.a *= Color.a; - FragColor = tcolor; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_fullbright_highlight.fp b/Source/Core/Resources/world3d_fullbright_highlight.fp deleted file mode 100644 index 1da98e35..00000000 --- a/Source/Core/Resources/world3d_fullbright_highlight.fp +++ /dev/null @@ -1,37 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 highlightcolor; -uniform vec4 stencilColor; - -uniform sampler2D texture1; - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -void main() -{ - vec4 tcolor = texture(texture1, UV); - tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); - if(tcolor.a == 0.0) - { - FragColor = tcolor; - } - else - { - // Blend texture color and vertex color - vec4 ncolor = tcolor * Color; - - FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (tcolor.rgb - 0.4 * highlightcolor.a), max(Color.a + 0.25, 0.5)); - } - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_lightpass.fp b/Source/Core/Resources/world3d_lightpass.fp deleted file mode 100644 index c0fc3ba4..00000000 --- a/Source/Core/Resources/world3d_lightpass.fp +++ /dev/null @@ -1,74 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec3 PosW; -in vec3 Normal; - -out vec4 FragColor; - -uniform vec4 stencilColor; -uniform vec4 lightPosAndRadius; -uniform vec3 lightOrientation; // this is a vector that points in light's direction -uniform vec2 light2Radius; // this is used with spotlights -uniform vec4 lightColor; -uniform float ignoreNormals; // ignore normals in lighting equation. used for non-attenuated lights on models. -uniform float spotLight; // use lightOrientation -uniform float desaturation; - -uniform sampler2D texture1; - -vec4 desaturate(vec4 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return vec4(mix(texel.rgb, vec3(gray), desaturation), texel.a); -} - -void main() -{ - //is face facing away from light source? - // update 01.02.2017: offset the equation by 3px back to try to emulate GZDoom's broken visibility check. - float diffuseContribution = dot(Normal, normalize(lightPosAndRadius.xyz - PosW + Normal * 3.0)); - if (diffuseContribution < 0.0 && ignoreNormals < 0.5) - discard; - diffuseContribution = max(diffuseContribution, 0.0); // to make sure - - //is pixel in light range? - float dist = distance(PosW, lightPosAndRadius.xyz); - if (dist > lightPosAndRadius.w) - discard; - - //is pixel tranparent? - vec4 tcolor = texture(texture1, UV); - tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); - if (tcolor.a == 0.0) - discard; - - //if it is - calculate color at current pixel - vec4 lightColorMod = vec4(0.0, 0.0, 0.0, 1.0); - - lightColorMod.rgb = lightColor.rgb * max(lightPosAndRadius.w - dist, 0.0) / lightPosAndRadius.w; - - if (spotLight > 0.5) - { - vec3 lightDirection = normalize(lightPosAndRadius.xyz - PosW); - float cosDir = dot(lightDirection, lightOrientation); - float df = smoothstep(light2Radius.y, light2Radius.x, cosDir); - lightColorMod.rgb *= df; - } - - if (lightColor.a > 0.979 && lightColor.a < 0.981) // attenuated light 98% - lightColorMod.rgb *= diffuseContribution; - - if (lightColorMod.r <= 0.0 && lightColorMod.g <= 0.0 && lightColorMod.b <= 0.0) - discard; - - lightColorMod.rgb *= lightColor.a; - if (lightColor.a > 0.4) //Normal, vavoom or negative light (or attenuated) - lightColorMod *= tcolor; - - FragColor = desaturate(lightColorMod); //Additive light - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif -} diff --git a/Source/Core/Resources/world3d_lightpass.vp b/Source/Core/Resources/world3d_lightpass.vp deleted file mode 100644 index 94bb4633..00000000 --- a/Source/Core/Resources/world3d_lightpass.vp +++ /dev/null @@ -1,26 +0,0 @@ - -in vec3 AttrPosition; -in vec4 AttrColor; -in vec2 AttrUV; -in vec3 AttrNormal; - -out vec4 Color; -out vec2 UV; -out vec3 PosW; -out vec3 Normal; -out vec4 viewpos; - -uniform mat4 world; -uniform mat4 view; -uniform mat4 projection; -uniform mat4 modelnormal; - -void main() -{ - viewpos = view * world * vec4(AttrPosition, 1.0); - gl_Position = projection * viewpos; - PosW = (world * vec4(AttrPosition, 1.0)).xyz; - Color = AttrColor; - UV = AttrUV; - Normal = normalize((modelnormal * vec4(AttrNormal, 1.0)).xyz); -} diff --git a/Source/Core/Resources/world3d_main.fp b/Source/Core/Resources/world3d_main.fp deleted file mode 100644 index 0c3bd48d..00000000 --- a/Source/Core/Resources/world3d_main.fp +++ /dev/null @@ -1,33 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 stencilColor; -uniform float desaturation; - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -uniform sampler2D texture1; - -vec4 desaturate(vec4 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return vec4(mix(texel.rgb, vec3(gray), desaturation), texel.a); -} - -void main() -{ - vec4 tcolor = texture(texture1, UV); - tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); - FragColor = desaturate(tcolor * Color); - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_main.vp b/Source/Core/Resources/world3d_main.vp deleted file mode 100644 index 7e8ec866..00000000 --- a/Source/Core/Resources/world3d_main.vp +++ /dev/null @@ -1,21 +0,0 @@ - -in vec3 AttrPosition; -in vec4 AttrColor; -in vec2 AttrUV; -in vec3 AttrNormal; - -out vec4 Color; -out vec2 UV; -out vec4 viewpos; - -uniform mat4 world; -uniform mat4 view; -uniform mat4 projection; - -void main() -{ - viewpos = view * world * vec4(AttrPosition, 1.0); - gl_Position = projection * viewpos; - Color = AttrColor; - UV = AttrUV; -} diff --git a/Source/Core/Resources/world3d_main_fog.fp b/Source/Core/Resources/world3d_main_fog.fp deleted file mode 100644 index 73d2a99e..00000000 --- a/Source/Core/Resources/world3d_main_fog.fp +++ /dev/null @@ -1,54 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec3 PosW; -in vec3 Normal; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 stencilColor; -uniform vec4 lightColor; -uniform float desaturation; -uniform vec4 campos; //w is set to fade factor (distance, at wich fog color completely overrides pixel color) - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -uniform sampler2D texture1; - -// This adds fog color to current pixel color -vec4 getFogColor(vec4 color) -{ - float fogdist = max(16.0, distance(PosW, campos.xyz)); - float fogfactor = exp2(campos.w * fogdist); - - color.rgb = mix(lightColor.rgb, color.rgb, fogfactor); - return color; -} - -vec4 desaturate(vec4 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return vec4(mix(texel.rgb, vec3(gray), desaturation), texel.a); -} - -void main() -{ - vec4 tcolor = texture(texture1, UV); - tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); - if (tcolor.a == 0.0) - { - FragColor = tcolor; - } - else - { - FragColor = desaturate(getFogColor(tcolor * Color)); - } - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_main_highlight.fp b/Source/Core/Resources/world3d_main_highlight.fp deleted file mode 100644 index 5d2a76f6..00000000 --- a/Source/Core/Resources/world3d_main_highlight.fp +++ /dev/null @@ -1,44 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 highlightcolor; -uniform vec4 stencilColor; -uniform float desaturation; - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -uniform sampler2D texture1; - -vec4 desaturate(vec4 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return vec4(mix(texel.rgb, vec3(gray), desaturation), texel.a); -} - -void main() -{ - vec4 tcolor = texture(texture1, UV); - tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); - if (tcolor.a == 0.0) - { - FragColor = tcolor; - } - else - { - // Blend texture color and vertex color - vec4 ncolor = desaturate(tcolor * Color); - - FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(Color.a + 0.25, 0.5)); - } - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_main_highlight_fog.fp b/Source/Core/Resources/world3d_main_highlight_fog.fp deleted file mode 100644 index 486436ae..00000000 --- a/Source/Core/Resources/world3d_main_highlight_fog.fp +++ /dev/null @@ -1,58 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec3 PosW; -in vec3 Normal; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 highlightcolor; -uniform vec4 stencilColor; -uniform vec4 lightColor; -uniform float desaturation; -uniform vec4 campos; //w is set to fade factor (distance, at wich fog color completely overrides pixel color) - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -uniform sampler2D texture1; - -// This adds fog color to current pixel color -vec4 getFogColor(vec4 color) -{ - float fogdist = max(16.0, distance(PosW, campos.xyz)); - float fogfactor = exp2(campos.w * fogdist); - - color.rgb = mix(lightColor.rgb, color.rgb, fogfactor); - return color; -} - -vec4 desaturate(vec4 texel) -{ - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return vec4(mix(texel.rgb, vec3(gray), desaturation), texel.a); -} - -void main() -{ - vec4 tcolor = texture(texture1, UV); - tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); - if (tcolor.a == 0.0) - { - FragColor = tcolor; - } - else - { - // Blend texture color and vertex color - vec4 ncolor = desaturate(getFogColor(tcolor * Color)); - - FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(ncolor.a + 0.25, 0.5)); - } - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_skybox.fp b/Source/Core/Resources/world3d_skybox.fp deleted file mode 100644 index 14f0bf43..00000000 --- a/Source/Core/Resources/world3d_skybox.fp +++ /dev/null @@ -1,24 +0,0 @@ - -in vec3 Tex; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 highlightcolor; - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -uniform samplerCube texture1; - -void main() -{ - vec4 ncolor = texture(texture1, Tex); - FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), 1.0); - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/Resources/world3d_skybox.shader b/Source/Core/Resources/world3d_skybox.shader new file mode 100755 index 00000000..a2d11725 --- /dev/null +++ b/Source/Core/Resources/world3d_skybox.shader @@ -0,0 +1,59 @@ +uniforms +{ + mat4 world; + mat4 view; + mat4 projection; + + vec4 campos; //w is set to fade factor (distance, at wich fog color completely overrides pixel color) + + vec4 highlightcolor; + + vec4 fogsettings; + vec4 fogcolor; + + samplerCube texture1; +} + +shader world3d_skybox +{ + in + { + vec3 Position; + vec4 Color; + vec2 TextureCoordinate; + vec3 Normal; + } + + v2f + { + vec3 Tex; + vec4 viewpos; + } + + out + { + vec4 FragColor; + } + + vertex + { + v2f.viewpos = view * world * vec4(in.Position, 1.0); + gl_Position = projection * v2f.viewpos; + vec3 worldpos = (world * vec4(in.Position, 1.0)).xyz; + vec4 skynormal = vec4(0.0, 1.0, 0.0, 0.0); + vec3 normal = normalize((world * skynormal).xyz); + v2f.Tex = reflect(worldpos - campos.xyz, normal); + } + + fragment + { + vec4 ncolor = texture(texture1, v2f.Tex); + out.FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), 1.0); + + #if defined(ALPHA_TEST) + if (out.FragColor.a < 0.5) discard; + #endif + + if (fogsettings.x >= 0.0) out.FragColor = mix(out.FragColor, fogcolor, clamp((-v2f.viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); + } +} \ No newline at end of file diff --git a/Source/Core/Resources/world3d_skybox.vp b/Source/Core/Resources/world3d_skybox.vp deleted file mode 100644 index c8ecf91d..00000000 --- a/Source/Core/Resources/world3d_skybox.vp +++ /dev/null @@ -1,22 +0,0 @@ - -in vec3 AttrPosition; -in vec2 AttrUV; - -out vec3 Tex; -out vec4 viewpos; - -uniform mat4 world; -uniform mat4 view; -uniform mat4 projection; - -uniform vec4 campos; //w is set to fade factor (distance, at wich fog color completely overrides pixel color) - -void main() -{ - viewpos = view * world * vec4(AttrPosition, 1.0); - gl_Position = projection * viewpos; - vec3 worldpos = (world * vec4(AttrPosition, 1.0)).xyz; - vec4 skynormal = vec4(0.0, 1.0, 0.0, 0.0); - vec3 normal = normalize((world * skynormal).xyz); - Tex = reflect(worldpos - campos.xyz, normal); -} diff --git a/Source/Core/Resources/world3d_vertex_color.fp b/Source/Core/Resources/world3d_vertex_color.fp deleted file mode 100644 index 3100ef13..00000000 --- a/Source/Core/Resources/world3d_vertex_color.fp +++ /dev/null @@ -1,20 +0,0 @@ - -in vec4 Color; -in vec2 UV; -in vec4 viewpos; - -out vec4 FragColor; - -uniform vec4 fogsettings; -uniform vec4 fogcolor; - -void main() -{ - FragColor = Color; - - #if defined(ALPHA_TEST) - if (FragColor.a < 0.5) discard; - #endif - - if (fogsettings.x >= 0.0) FragColor = mix(FragColor, fogcolor, clamp((-viewpos.z - fogsettings.x) / (fogsettings.y - fogsettings.x), 0.0, 1.0)); -} diff --git a/Source/Core/ZDoom/ZScriptTokenizer.cs b/Source/Core/ZDoom/ZScriptTokenizer.cs index 891fe3f4..9ad89dd2 100755 --- a/Source/Core/ZDoom/ZScriptTokenizer.cs +++ b/Source/Core/ZDoom/ZScriptTokenizer.cs @@ -104,12 +104,24 @@ namespace CodeImp.DoomBuilder.ZDoom WarningMessage = String.Empty; } + public ZScriptToken(ZScriptToken other) + { + Type = other.Type; + Value = other.Value; + ValueInt = other.ValueInt; + ValueDouble = other.ValueDouble; + IsValid = other.IsValid; + WarningMessage = other.WarningMessage; + Position = other.Position; + } + public ZScriptTokenType Type { get; internal set; } public string Value { get; internal set; } public int ValueInt { get; internal set; } public double ValueDouble { get; internal set; } public bool IsValid { get; internal set; } public string WarningMessage { get; internal set; } + public long Position { get; internal set; } public override string ToString() { @@ -128,10 +140,23 @@ namespace CodeImp.DoomBuilder.ZDoom public BinaryReader Reader { get { return reader; } } public long LastPosition { get; private set; } + private List LinePositions; + public ZScriptTokenizer(BinaryReader br) { reader = br; + long cpos = br.BaseStream.Position; + LinePositions = new List(); + br.BaseStream.Position = 0; + while (br.BaseStream.Position < br.BaseStream.Length) + { + byte b = br.ReadByte(); + if (b == '\n') + LinePositions.Add(br.BaseStream.Position); + } + br.BaseStream.Position = cpos; + if (SB == null) SB = new StringBuilder(); @@ -165,6 +190,14 @@ namespace CodeImp.DoomBuilder.ZDoom } } + public int PositionToLine(long pos) + { + for (int i = 0; i < LinePositions.Count; i++) + if (pos <= LinePositions[i]) + return i+1; + return LinePositions.Count; + } + public void SkipWhitespace() // note that this skips both whitespace, newlines AND comments { while (true) @@ -202,6 +235,7 @@ namespace CodeImp.DoomBuilder.ZDoom } ZScriptToken tok = new ZScriptToken(); + tok.Position = cpos; tok.Type = ZScriptTokenType.Whitespace; tok.Value = SB.ToString(); return tok; @@ -240,6 +274,7 @@ namespace CodeImp.DoomBuilder.ZDoom } ZScriptToken tok = new ZScriptToken(); + tok.Position = cpos; tok.Type = ZScriptTokenType.Identifier; tok.Value = SB.ToString(); return tok; @@ -313,6 +348,7 @@ namespace CodeImp.DoomBuilder.ZDoom } ZScriptToken tok = new ZScriptToken(); + tok.Position = cpos; tok.Type = (isdouble ? ZScriptTokenType.Double : ZScriptTokenType.Integer); tok.Value = SB.ToString(); try @@ -400,6 +436,7 @@ namespace CodeImp.DoomBuilder.ZDoom } ZScriptToken tok = new ZScriptToken(); + tok.Position = cpos; tok.Type = ZScriptTokenType.LineComment; tok.Value = SB.ToString(); return tok; @@ -425,6 +462,7 @@ namespace CodeImp.DoomBuilder.ZDoom } ZScriptToken tok = new ZScriptToken(); + tok.Position = cpos; tok.Type = ZScriptTokenType.BlockComment; tok.Value = SB.ToString(); return tok; @@ -450,6 +488,7 @@ namespace CodeImp.DoomBuilder.ZDoom else if (cnext == c) { ZScriptToken tok = new ZScriptToken(); + tok.Position = cpos; tok.Type = type; tok.Value = SB.ToString(); return tok; @@ -478,6 +517,7 @@ namespace CodeImp.DoomBuilder.ZDoom // found the token. reader.BaseStream.Position = cpos + namedtokentype.Length; ZScriptToken tok = new ZScriptToken(); + tok.Position = cpos; tok.Type = namedtokentypes[namedtokentype]; tok.Value = namedtokentype; return tok; diff --git a/Source/Native/OpenGL/GLShader.cpp b/Source/Native/OpenGL/GLShader.cpp index 2160dcf1..f819562c 100644 --- a/Source/Native/OpenGL/GLShader.cpp +++ b/Source/Native/OpenGL/GLShader.cpp @@ -77,11 +77,11 @@ void GLShader::Bind() void GLShader::CreateProgram(GLRenderDevice* device) { const char* prefixNAT = R"( - #version 150 + #version 330 #line 1 )"; const char* prefixAT = R"( - #version 150 + #version 330 #define ALPHA_TEST #line 1 )";