diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj index bae0172e..616df1dd 100644 --- a/Source/Core/Builder.csproj +++ b/Source/Core/Builder.csproj @@ -200,6 +200,12 @@ + + True + True + Resources.resx + + @@ -565,11 +571,6 @@ - - True - True - Resources.resx - @@ -665,17 +666,9 @@ SettingsSingleFileGenerator Settings.Designer.cs - - - - + - - - - - - + @@ -691,22 +684,8 @@ - - - - - - - - - - - - - - - - + + diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs index 6fd89ae1..b383e929 100755 --- a/Source/Core/Data/DataManager.cs +++ b/Source/Core/Data/DataManager.cs @@ -3399,16 +3399,16 @@ namespace CodeImp.DoomBuilder.Data General.Map.Graphics.SetSamplerState(TextureAddress.Clamp); // Setup matrices - Vector3 offset = new Vector3(0f, 0f, -1.8f); // Sphere size is 10 mu + Vector3f offset = new Vector3f(0f, 0f, -1.8f); // Sphere size is 10 mu Matrix mworld = Matrix.Translation(offset) * Matrix.Scaling(1.0f, 1.0f, yscale); Matrix mprojection = Matrix.PerspectiveFov(Angle2D.PIHALF, 1.0f, 0.5f, 100.0f); // Place camera at origin - General.Map.Graphics.SetUniform(UniformName.campos, new Vector4()); + General.Map.Graphics.SetUniform(UniformName.campos, new Vector4f()); // Begin fullbright shaderpass General.Map.Graphics.SetShader(ShaderName.world3d_fullbright); - General.Map.Graphics.SetUniform(UniformName.fogsettings, new Vector4(-1.0f)); + General.Map.Graphics.SetUniform(UniformName.fogsettings, new Vector4f(-1.0f)); // Render to the six faces of the cube map for (int i = 0; i < 6; i++) @@ -3643,45 +3643,45 @@ namespace CodeImp.DoomBuilder.Data private static Matrix GetCubeMapViewMatrix(CubeMapFace face) { - Vector3 lookdir, updir; + Vector3f lookdir, updir; switch(face) { case CubeMapFace.PositiveX: - lookdir = new Vector3(-1.0f, 0.0f, 0.0f); - updir = new Vector3(0.0f, 1.0f, 0.0f); + lookdir = new Vector3f(-1.0f, 0.0f, 0.0f); + updir = new Vector3f(0.0f, 1.0f, 0.0f); break; case CubeMapFace.NegativeX: - lookdir = new Vector3(1.0f, 0.0f, 0.0f); - updir = new Vector3(0.0f, 1.0f, 0.0f); + lookdir = new Vector3f(1.0f, 0.0f, 0.0f); + updir = new Vector3f(0.0f, 1.0f, 0.0f); break; case CubeMapFace.PositiveY: - lookdir = new Vector3(0.0f, -1.0f, 0.0f); - updir = new Vector3(0.0f, 0.0f, 1.0f); + lookdir = new Vector3f(0.0f, -1.0f, 0.0f); + updir = new Vector3f(0.0f, 0.0f, 1.0f); break; case CubeMapFace.NegativeY: - lookdir = new Vector3(0.0f, 1.0f, 0.0f); - updir = new Vector3(0.0f, 0.0f, -1.0f); + lookdir = new Vector3f(0.0f, 1.0f, 0.0f); + updir = new Vector3f(0.0f, 0.0f, -1.0f); break; case CubeMapFace.PositiveZ: - lookdir = new Vector3(0.0f, 0.0f, 1.0f); - updir = new Vector3(0.0f, 1.0f, 0.0f); + lookdir = new Vector3f(0.0f, 0.0f, 1.0f); + updir = new Vector3f(0.0f, 1.0f, 0.0f); break; case CubeMapFace.NegativeZ: - lookdir = new Vector3(0.0f, 0.0f, -1.0f); - updir = new Vector3(0.0f, 1.0f, 0.0f); + lookdir = new Vector3f(0.0f, 0.0f, -1.0f); + updir = new Vector3f(0.0f, 1.0f, 0.0f); break; default: throw new Exception("Unknown CubeMapFace!"); } - Vector3 eye = new Vector3(); + Vector3f eye = new Vector3f(); return Matrix.LookAt(eye, lookdir, updir); } diff --git a/Source/Core/GZBuilder/Data/DynamicLight.cs b/Source/Core/GZBuilder/Data/DynamicLight.cs index 2f395176..a8df6027 100755 --- a/Source/Core/GZBuilder/Data/DynamicLight.cs +++ b/Source/Core/GZBuilder/Data/DynamicLight.cs @@ -9,14 +9,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data public int PrimaryRadius; public int SecondaryRadius; public int Interval; - public Vector3 Offset; + public Vector3f Offset; public bool DontLightSelf; public DynamicLightData(GZGeneral.LightData type) { Type = type; Color = new Color3(); - Offset = new Vector3(); + Offset = new Vector3f(); } } } diff --git a/Source/Core/GZBuilder/Data/ModelData.cs b/Source/Core/GZBuilder/Data/ModelData.cs index 1ee12cad..c3299873 100755 --- a/Source/Core/GZBuilder/Data/ModelData.cs +++ b/Source/Core/GZBuilder/Data/ModelData.cs @@ -21,7 +21,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data #region ================== Variables private ModelLoadState loadstate; - private Vector3 scale; + private Vector3f scale; private Matrix transform; private Matrix transformrotation; private Matrix transformstretched; @@ -39,7 +39,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data internal GZModel Model; - internal Vector3 Scale { get { return scale; } } + internal Vector3f Scale { get { return scale; } } internal Matrix Transform { get { /* return (General.Settings.GZStretchView ? transformstretched : transform); */ return transformstretched; } } internal Matrix TransformRotation { get { return transformrotation; } } internal bool OverridePalette; // Used for voxel models only @@ -94,7 +94,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data } } - internal void SetTransform(Matrix rotation, Matrix offset, Vector3 scale) + internal void SetTransform(Matrix rotation, Matrix offset, Vector3f scale) { this.scale = scale; transformrotation = rotation * Matrix.Scaling(scale); diff --git a/Source/Core/GZBuilder/md3/GZModel.cs b/Source/Core/GZBuilder/md3/GZModel.cs index 7d32d78e..119af3c1 100755 --- a/Source/Core/GZBuilder/md3/GZModel.cs +++ b/Source/Core/GZBuilder/md3/GZModel.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using CodeImp.DoomBuilder.Rendering; +using CodeImp.DoomBuilder.GZBuilder.Data; namespace CodeImp.DoomBuilder.GZBuilder.MD3 { @@ -8,8 +9,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 internal readonly List Meshes; internal readonly List Textures; internal float Radius; + internal BoundingBoxSizes BBox; - internal GZModel() + internal GZModel() { Meshes = new List(); Textures = new List(); diff --git a/Source/Core/GZBuilder/md3/ModelReader.cs b/Source/Core/GZBuilder/md3/ModelReader.cs index 96e03289..a5a90282 100755 --- a/Source/Core/GZBuilder/md3/ModelReader.cs +++ b/Source/Core/GZBuilder/md3/ModelReader.cs @@ -238,9 +238,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 bbs.MinX = (int)(bbs.MinX * mde.Scale.X); bbs.MaxY = (int)(bbs.MaxY * mde.Scale.Y); bbs.MinY = (int)(bbs.MinY * mde.Scale.Y); + bbs.MaxZ = (int)(bbs.MaxZ * mde.Scale.Z); + bbs.MinZ = (int)(bbs.MinZ * mde.Scale.Z); //calculate model radius mde.Model.Radius = Math.Max(Math.Max(Math.Abs(bbs.MinY), Math.Abs(bbs.MaxY)), Math.Max(Math.Abs(bbs.MinX), Math.Abs(bbs.MaxX))); + mde.Model.BBox = bbs; } private static Texture GetTexture(List containers, string texturename) @@ -853,7 +856,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 List polyIndecesList = new List(); List uvIndecesList = new List(); - List uvCoordsList = new List(); + List uvCoordsList = new List(); List vertList = new List(); // Polygons @@ -874,7 +877,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 s.Position = ofs_uv + start; for(int i = 0; i < num_uv; i++) - uvCoordsList.Add(new Vector2((float)br.ReadInt16() / texWidth, (float)br.ReadInt16() / texHeight)); + uvCoordsList.Add(new Vector2f((float)br.ReadInt16() / texWidth, (float)br.ReadInt16() / texHeight)); // Frames // Find correct frame @@ -910,8 +913,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3 s.Position = ofs_animFrame + start + frame * framesize; } - Vector3 scale = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Vector3 translate = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Vector3f scale = new Vector3f(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); + Vector3f translate = new Vector3f(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); s.Position += 16; // Skip frame name diff --git a/Source/Core/Geometry/Tools.cs b/Source/Core/Geometry/Tools.cs index 1f3253d9..79687589 100755 --- a/Source/Core/Geometry/Tools.cs +++ b/Source/Core/Geometry/Tools.cs @@ -1937,6 +1937,9 @@ namespace CodeImp.DoomBuilder.Geometry if(side.Line.IsFlagSet(General.Map.Config.UpperUnpeggedFlag) || side.Other == null || side.Other.Sector == null) return offset; + // Make sure the offset doesn't go in the wrong direction + scaleY = Math.Abs(scaleY); + //if we don't have UpperUnpegged flag, normalize offset float surfaceHeight = side.GetHighHeight() * scaleY; return (float)Math.Round((fromNormalized ? offset + surfaceHeight : offset - surfaceHeight), General.Map.FormatInterface.VertexDecimals); @@ -1947,6 +1950,9 @@ namespace CodeImp.DoomBuilder.Geometry { if(side.Sector == null) return offset; + // Make sure the offset doesn't go in the wrong direction + scaleY = Math.Abs(scaleY); + // Normalize offset float surfaceHeight; if(side.Other != null && side.Other.Sector != null) @@ -1985,7 +1991,11 @@ namespace CodeImp.DoomBuilder.Geometry public static float GetSidedefBottomOffsetY(Sidedef side, float offset, float scaleY, bool fromNormalized) { float surfaceHeight; - if(side.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag)) + + // Make sure the offset doesn't go in the wrong direction + scaleY = Math.Abs(scaleY); + + if (side.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag)) { if(side.Other == null || side.Other.Sector == null || side.Sector.CeilTexture != General.Map.Config.SkyFlatName || side.Other.Sector.CeilTexture != General.Map.Config.SkyFlatName) @@ -2461,7 +2471,7 @@ namespace CodeImp.DoomBuilder.Geometry /// public static Vector2D HermiteSpline(Vector2D p1, Vector2D t1, Vector2D p2, Vector2D t2, float u) { - return RenderDevice.V2D(Vector2.Hermite(RenderDevice.V2(p1), RenderDevice.V2(t1), RenderDevice.V2(p2), RenderDevice.V2(t2), u)); + return RenderDevice.V2D(Vector2f.Hermite(RenderDevice.V2(p1), RenderDevice.V2(t1), RenderDevice.V2(p2), RenderDevice.V2(t2), u)); } /// @@ -2470,7 +2480,7 @@ namespace CodeImp.DoomBuilder.Geometry /// public static Vector3D HermiteSpline(Vector3D p1, Vector3D t1, Vector3D p2, Vector3D t2, float u) { - return RenderDevice.V3D(Vector3.Hermite(RenderDevice.V3(p1), RenderDevice.V3(t1), RenderDevice.V3(p2), RenderDevice.V3(t2), u)); + return RenderDevice.V3D(Vector3f.Hermite(RenderDevice.V3(p1), RenderDevice.V3(t1), RenderDevice.V3(p2), RenderDevice.V3(t2), u)); } //mxd 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/Color3.cs b/Source/Core/Rendering/Color3.cs index a9023c75..4508a693 100644 --- a/Source/Core/Rendering/Color3.cs +++ b/Source/Core/Rendering/Color3.cs @@ -15,7 +15,7 @@ namespace CodeImp.DoomBuilder.Rendering Blue = b; } - public Color3(Vector3 c) + public Color3(Vector3f c) { Red = c.X; Green = c.Y; diff --git a/Source/Core/Rendering/Color4.cs b/Source/Core/Rendering/Color4.cs index cff4c5ac..ed08374a 100644 --- a/Source/Core/Rendering/Color4.cs +++ b/Source/Core/Rendering/Color4.cs @@ -25,7 +25,7 @@ namespace CodeImp.DoomBuilder.Rendering Alpha = a; } - public Color4(Vector4 c) + public Color4(Vector4f c) { Red = c.X; Green = c.Y; @@ -60,6 +60,11 @@ namespace CodeImp.DoomBuilder.Rendering return System.Drawing.Color.FromArgb(ToArgb()); } + public Vector4f ToVector() + { + return new Vector4f(Red, Green, Blue, Alpha); + } + public override bool Equals(object o) { if (o is Color4) diff --git a/Source/Core/Rendering/Matrix.cs b/Source/Core/Rendering/Matrix.cs index 24a5b3a9..ce7d9707 100644 --- a/Source/Core/Rendering/Matrix.cs +++ b/Source/Core/Rendering/Matrix.cs @@ -187,7 +187,7 @@ namespace CodeImp.DoomBuilder.Rendering } } - public static Matrix Translation(Vector3 v) + public static Matrix Translation(Vector3f v) { Matrix result = new Matrix(); Matrix_Translation(v.X, v.Y, v.Z, out result); @@ -229,7 +229,7 @@ namespace CodeImp.DoomBuilder.Rendering return result; } - public static Matrix Scaling(Vector3 v) + public static Matrix Scaling(Vector3f v) { Matrix result = new Matrix(); Matrix_Scaling(v.X, v.Y, v.Z, out result); @@ -276,11 +276,11 @@ namespace CodeImp.DoomBuilder.Rendering #endif - public static Matrix LookAt(Vector3 eye, Vector3 target, Vector3 up) + public static Matrix LookAt(Vector3f eye, Vector3f target, Vector3f up) { - Vector3 zaxis = Vector3.Normalize(target - eye); - Vector3 xaxis = Vector3.Normalize(Vector3.Cross(up, zaxis)); - Vector3 yaxis = Vector3.Cross(zaxis, xaxis); + Vector3f zaxis = Vector3f.Normalize(target - eye); + Vector3f xaxis = Vector3f.Normalize(Vector3f.Cross(up, zaxis)); + Vector3f yaxis = Vector3f.Cross(zaxis, xaxis); Matrix result = Null; result.M11 = -xaxis.X; diff --git a/Source/Core/Rendering/RenderDevice.cs b/Source/Core/Rendering/RenderDevice.cs index c4f219c8..54c78884 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 @@ -45,53 +46,64 @@ namespace CodeImp.DoomBuilder.Rendering CreateDevice(); - DeclareUniform(UniformName.rendersettings, "rendersettings", UniformType.Vec4); + DeclareUniform(UniformName.rendersettings, "rendersettings", UniformType.Vec4f); DeclareUniform(UniformName.projection, "projection", UniformType.Mat4); DeclareUniform(UniformName.desaturation, "desaturation", UniformType.Float); - DeclareUniform(UniformName.highlightcolor, "highlightcolor", UniformType.Vec4); + DeclareUniform(UniformName.highlightcolor, "highlightcolor", UniformType.Vec4f); DeclareUniform(UniformName.view, "view", UniformType.Mat4); DeclareUniform(UniformName.world, "world", UniformType.Mat4); DeclareUniform(UniformName.modelnormal, "modelnormal", UniformType.Mat4); - DeclareUniform(UniformName.FillColor, "fillColor", UniformType.Vec4); - DeclareUniform(UniformName.vertexColor, "vertexColor", UniformType.Vec4); - DeclareUniform(UniformName.stencilColor, "stencilColor", UniformType.Vec4); - DeclareUniform(UniformName.lightPosAndRadius, "lightPosAndRadius", UniformType.Vec4); - DeclareUniform(UniformName.lightOrientation, "lightOrientation", UniformType.Vec3); - DeclareUniform(UniformName.light2Radius, "light2Radius", UniformType.Vec2); - DeclareUniform(UniformName.lightColor, "lightColor", UniformType.Vec4); + DeclareUniform(UniformName.FillColor, "fillColor", UniformType.Vec4f); + DeclareUniform(UniformName.vertexColor, "vertexColor", UniformType.Vec4f); + DeclareUniform(UniformName.stencilColor, "stencilColor", UniformType.Vec4f); + DeclareUniform(UniformName.lightPosAndRadius, "lightPosAndRadius", UniformType.Vec4fArray); + DeclareUniform(UniformName.lightOrientation, "lightOrientation", UniformType.Vec4fArray); + DeclareUniform(UniformName.light2Radius, "light2Radius", UniformType.Vec2fArray); + DeclareUniform(UniformName.lightColor, "lightColor", UniformType.Vec4fArray); DeclareUniform(UniformName.ignoreNormals, "ignoreNormals", UniformType.Float); DeclareUniform(UniformName.spotLight, "spotLight", UniformType.Float); - DeclareUniform(UniformName.campos, "campos", UniformType.Vec4); - DeclareUniform(UniformName.texturefactor, "texturefactor", UniformType.Vec4); - DeclareUniform(UniformName.fogsettings, "fogsettings", UniformType.Vec4); - DeclareUniform(UniformName.fogcolor, "fogcolor", UniformType.Vec4); + DeclareUniform(UniformName.campos, "campos", UniformType.Vec4f); + DeclareUniform(UniformName.texturefactor, "texturefactor", UniformType.Vec4f); + DeclareUniform(UniformName.fogsettings, "fogsettings", UniformType.Vec4f); + DeclareUniform(UniformName.fogcolor, "fogcolor", UniformType.Vec4f); + DeclareUniform(UniformName.sectorfogcolor, "sectorfogcolor", UniformType.Vec4f); + DeclareUniform(UniformName.lightsEnabled, "lightsEnabled", UniformType.Float); DeclareUniform(UniformName.slopeHandleLength, "slopeHandleLength", UniformType.Float); - 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"); - DeclareShader(ShaderName.world3d_slope_handle, "world3d_slopehandle.vp", "world3d_constant_color.fp"); + // 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"); - SetupSettings(); + // 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"); + + // Slope handle + CompileShader(ShaderName.world3d_slope_handle, "world3d.shader", "world3d_slope_handle"); + + SetupSettings(); } ~RenderDevice() @@ -112,7 +124,7 @@ namespace CodeImp.DoomBuilder.Rendering Handle = RenderDevice_New(display, RenderTarget.Handle); if (Handle == IntPtr.Zero) - throw new Exception("RenderDevice_New failed"); + throw new RenderDeviceException(string.Format("Could not create render device: {0}", BuilderNative_GetError())); } public bool Disposed { get { return Handle == IntPtr.Zero; } } @@ -120,7 +132,7 @@ namespace CodeImp.DoomBuilder.Rendering void ThrowIfFailed(bool result) { if (!result) - throw new RenderDeviceException(Marshal.PtrToStringAnsi(RenderDevice_GetError(Handle))); + throw new RenderDeviceException(BuilderNative_GetError()); } public void Dispose() @@ -142,6 +154,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); @@ -152,7 +184,10 @@ namespace CodeImp.DoomBuilder.Rendering byte[] data = new byte[stream.Length]; if (stream.Read(data, 0, data.Length) != data.Length) throw new Exception("Could not read resource stream"); - return Encoding.UTF8.GetString(data); + int start = 0; + if (data.Length >= 3 && data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf) + start = 3; + return Encoding.UTF8.GetString(data, start, data.Length - start); } } @@ -163,42 +198,104 @@ namespace CodeImp.DoomBuilder.Rendering public void SetUniform(UniformName uniform, bool value) { - RenderDevice_SetUniform(Handle, uniform, new float[] { value ? 1.0f : 0.0f }, 1); + RenderDevice_SetUniform(Handle, uniform, new float[] { value ? 1.0f : 0.0f }, 1, sizeof(float)); } public void SetUniform(UniformName uniform, float value) { - RenderDevice_SetUniform(Handle, uniform, new float[] { value }, 1); + RenderDevice_SetUniform(Handle, uniform, new float[] { value }, 1, sizeof(float)); } - public void SetUniform(UniformName uniform, Vector2 value) + public void SetUniform(UniformName uniform, Vector2f value) { - RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y }, 2); + RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y }, 1, sizeof(float) * 2); } - public void SetUniform(UniformName uniform, Vector3 value) + public void SetUniform(UniformName uniform, Vector3f value) { - RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z }, 3); + RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z }, 1, sizeof(float) * 3); } - public void SetUniform(UniformName uniform, Vector4 value) + public void SetUniform(UniformName uniform, Vector4f value) { - RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z, value.W }, 4); + RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z, value.W }, 1, sizeof(float) * 4); } public void SetUniform(UniformName uniform, Color4 value) { - RenderDevice_SetUniform(Handle, uniform, new float[] { value.Red, value.Green, value.Blue, value.Alpha }, 4); + RenderDevice_SetUniform(Handle, uniform, new float[] { value.Red, value.Green, value.Blue, value.Alpha }, 1, sizeof(float) * 4); } public void SetUniform(UniformName uniform, Matrix matrix) { - RenderDevice_SetUniform(Handle, uniform, ref matrix, 16); + RenderDevice_SetUniform(Handle, uniform, ref matrix, 1, sizeof(float) * 16); } public void SetUniform(UniformName uniform, ref Matrix matrix) { - RenderDevice_SetUniform(Handle, uniform, ref matrix, 16); + RenderDevice_SetUniform(Handle, uniform, ref matrix, 1, sizeof(float) * 16); + } + + public void SetUniform(UniformName uniform, int value) + { + RenderDevice_SetUniform(Handle, uniform, new int[] { value }, 1, sizeof(int)); + } + + public void SetUniform(UniformName uniform, Vector2i value) + { + RenderDevice_SetUniform(Handle, uniform, new int[] { value.X, value.Y }, 1, sizeof(int) * 2); + } + + public void SetUniform(UniformName uniform, Vector3i value) + { + RenderDevice_SetUniform(Handle, uniform, new int[] { value.X, value.Y, value.Z }, 1, sizeof(int) * 3); + } + + public void SetUniform(UniformName uniform, Vector4i value) + { + RenderDevice_SetUniform(Handle, uniform, new int[] { value.X, value.Y, value.Z, value.W }, 1, sizeof(int) * 4); + } + + public void SetUniform(UniformName uniform, Vector2f[] value) + { + float[] conv = new float[value.Length * 2]; + int cv = 0; + for (int i = 0; i < conv.Length; i += 2) + { + conv[i] = value[cv].X; + conv[i + 1] = value[cv].Y; + cv++; + } + RenderDevice_SetUniform(Handle, uniform, conv, value.Length, sizeof(float) * conv.Length); + } + + public void SetUniform(UniformName uniform, Vector3f[] value) + { + float[] conv = new float[value.Length * 3]; + int cv = 0; + for (int i = 0; i < conv.Length; i += 3) + { + conv[i] = value[cv].X; + conv[i + 1] = value[cv].Y; + conv[i + 2] = value[cv].Z; + cv++; + } + RenderDevice_SetUniform(Handle, uniform, conv, value.Length, sizeof(float) * conv.Length); + } + + public void SetUniform(UniformName uniform, Vector4f[] value) + { + float[] conv = new float[value.Length * 4]; + int cv = 0; + for (int i = 0; i < conv.Length; i += 4) + { + conv[i] = value[cv].X; + conv[i + 1] = value[cv].Y; + conv[i + 2] = value[cv].Z; + conv[i + 3] = value[cv].W; + cv++; + } + RenderDevice_SetUniform(Handle, uniform, conv, value.Length, sizeof(float) * conv.Length); } public void SetVertexBuffer(VertexBuffer buffer) @@ -465,17 +562,20 @@ namespace CodeImp.DoomBuilder.Rendering [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] static extern void RenderDevice_DeclareShader(IntPtr handle, ShaderName index, string name, string vertexShader, string fragShader); - [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr RenderDevice_GetError(IntPtr handle); + [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + static extern string BuilderNative_GetError(); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] static extern bool RenderDevice_SetShader(IntPtr handle, ShaderName name); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count); + static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, int[] data, int count, int bytesize); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] - static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, ref Matrix data, int count); + static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count, int bytesize); + + [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] + static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, ref Matrix data, int count, int bytesize); [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] static extern void RenderDevice_SetVertexBuffer(IntPtr handle, IntPtr buffer); @@ -585,25 +685,25 @@ namespace CodeImp.DoomBuilder.Rendering internal RenderTargetControl RenderTarget { get; private set; } // This makes a Vector3 from Vector3D - public static Vector3 V3(Vector3D v3d) + public static Vector3f V3(Vector3D v3d) { - return new Vector3(v3d.x, v3d.y, v3d.z); + return new Vector3f(v3d.x, v3d.y, v3d.z); } // This makes a Vector3D from Vector3 - public static Vector3D V3D(Vector3 v3) + public static Vector3D V3D(Vector3f v3) { return new Vector3D(v3.X, v3.Y, v3.Z); } // This makes a Vector2 from Vector2D - public static Vector2 V2(Vector2D v2d) + public static Vector2f V2(Vector2D v2d) { - return new Vector2(v2d.x, v2d.y); + return new Vector2f(v2d.x, v2d.y); } // This makes a Vector2D from Vector2 - public static Vector2D V2D(Vector2 v2) + public static Vector2D V2D(Vector2f v2) { return new Vector2D(v2.X, v2.Y); } @@ -617,7 +717,6 @@ namespace CodeImp.DoomBuilder.Rendering things2d_thing, things2d_sprite, things2d_fill, - plotter, world3d_main, world3d_fullbright, world3d_main_highlight, @@ -635,17 +734,23 @@ namespace CodeImp.DoomBuilder.Rendering world3d_main_highlight_fog_vertexcolor, world3d_vertex_color, world3d_constant_color, - world3d_lightpass, world3d_slope_handle } public enum UniformType : int { - Vec4, - Vec3, - Vec2, + Vec4f, + Vec3f, + Vec2f, Float, - Mat4 + Mat4, + Vec4i, + Vec3i, + Vec2i, + Int, + Vec4fArray, + Vec3fArray, + Vec2fArray } public enum UniformName : int @@ -670,6 +775,8 @@ namespace CodeImp.DoomBuilder.Rendering texturefactor, fogsettings, fogcolor, + sectorfogcolor, + lightsEnabled, slopeHandleLength } diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs index 29609c10..7c9c1689 100755 --- a/Source/Core/Rendering/Renderer2D.cs +++ b/Source/Core/Rendering/Renderer2D.cs @@ -487,7 +487,7 @@ namespace CodeImp.DoomBuilder.Rendering private void SetDisplay2DSettings(float texelx, float texely, float fsaafactor, float alpha, bool bilinear, bool flipY = false) { - Vector4 values = new Vector4(texelx, texely, fsaafactor, alpha); + Vector4f values = new Vector4f(texelx, texely, fsaafactor, alpha); graphics.SetUniform(UniformName.rendersettings, values); if (flipY) graphics.SetUniform(UniformName.projection, worldmatrix * viewmatrix * Matrix.Scaling(1f, -1f, 1f)); @@ -498,7 +498,7 @@ namespace CodeImp.DoomBuilder.Rendering private void SetThings2DSettings(float alpha) { - Vector4 values = new Vector4(0.0f, 0.0f, 1.0f, alpha); + Vector4f values = new Vector4f(0.0f, 0.0f, 1.0f, alpha); graphics.SetUniform(UniformName.rendersettings, values); graphics.SetUniform(UniformName.projection, worldmatrix * viewmatrix); } diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs index db3c7271..e644c2ce 100755 --- a/Source/Core/Rendering/Renderer3D.cs +++ b/Source/Core/Rendering/Renderer3D.cs @@ -37,6 +37,7 @@ namespace CodeImp.DoomBuilder.Rendering private const float PROJ_NEAR_PLANE = 1f; private const float FOG_RANGE = 0.9f; + private const int MAX_DYNLIGHTS_PER_SURFACE = 64; #endregion @@ -287,7 +288,7 @@ namespace CodeImp.DoomBuilder.Rendering General.Settings.ViewDistance, Angle2D.DegToRad(General.Settings.VisualFOV)); // Make the view matrix - view3d = Matrix.LookAt(RenderDevice.V3(pos), RenderDevice.V3(lookat), new Vector3(0f, 0f, 1f)); + view3d = Matrix.LookAt(RenderDevice.V3(pos), RenderDevice.V3(lookat), new Vector3f(0f, 0f, 1f)); // Make the billboard matrix billboard = Matrix.RotationZ(anglexy + Angle2D.PI); @@ -322,7 +323,7 @@ namespace CodeImp.DoomBuilder.Rendering graphics.SetAlphaTestEnable(false); graphics.SetSourceBlend(Blend.SourceAlpha); graphics.SetDestinationBlend(Blend.InverseSourceAlpha); - graphics.SetUniform(UniformName.fogsettings, new Vector4(-1.0f)); + graphics.SetUniform(UniformName.fogsettings, new Vector4f(-1.0f)); graphics.SetUniform(UniformName.fogcolor, General.Colors.Background.ToColorValue()); graphics.SetUniform(UniformName.texturefactor, new Color4(1f, 1f, 1f, 1f)); graphics.SetUniform(UniformName.highlightcolor, new Color4()); //mxd @@ -412,14 +413,14 @@ namespace CodeImp.DoomBuilder.Rendering // SOLID PASS world = Matrix.Identity; graphics.SetUniform(UniformName.world, ref world); - RenderSinglePass(solidgeo, solidthings); + RenderSinglePass(solidgeo, solidthings, lightthings); //mxd. Render models, without backface culling if(maskedmodelthings.Count > 0) { graphics.SetAlphaTestEnable(true); graphics.SetCullMode(Cull.None); - RenderModels(false, false); + RenderModels(false, lightthings); graphics.SetCullMode(Cull.Clockwise); } @@ -429,33 +430,9 @@ namespace CodeImp.DoomBuilder.Rendering world = Matrix.Identity; graphics.SetUniform(UniformName.world, ref world); graphics.SetAlphaTestEnable(true); - RenderSinglePass(maskedgeo, maskedthings); + RenderSinglePass(maskedgeo, maskedthings, lightthings); } - //mxd. LIGHT PASS - if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && lightthings.Count > 0) - { - world = Matrix.Identity; - graphics.SetUniform(UniformName.world, ref world); - graphics.SetAlphaBlendEnable(true); - graphics.SetAlphaTestEnable(false); - graphics.SetZWriteEnable(false); - graphics.SetDestinationBlend(Blend.One); - - RenderLights(solidgeo, lightthings); - RenderLights(maskedgeo, lightthings); - - if (maskedmodelthings.Count > 0) - { - graphics.SetAlphaTestEnable(true); - graphics.SetCullMode(Cull.None); - graphics.SetUniform(UniformName.ignoreNormals, true); - RenderModels(true, false); - graphics.SetUniform(UniformName.ignoreNormals, false); - graphics.SetCullMode(Cull.Clockwise); - } - } - // ALPHA AND ADDITIVE PASS if(translucentgeo.Count > 0 || translucentthings.Count > 0) { @@ -465,21 +442,9 @@ namespace CodeImp.DoomBuilder.Rendering graphics.SetAlphaTestEnable(false); graphics.SetZWriteEnable(false); graphics.SetSourceBlend(Blend.SourceAlpha); - RenderTranslucentPass(translucentgeo, translucentthings); + RenderTranslucentPass(translucentgeo, translucentthings, lightthings); } - // [ZZ] LIGHT PASS on ALPHA GEOMETRY (GZDoom does this) - if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && lightthings.Count > 0 && translucentgeo.Count > 0) - { - world = Matrix.Identity; - graphics.SetUniform(UniformName.world, ref world); - graphics.SetAlphaBlendEnable(true); - graphics.SetAlphaTestEnable(false); - graphics.SetZWriteEnable(false); - graphics.SetDestinationBlend(Blend.One); - RenderTranslucentLights(translucentgeo, lightthings); - } - //mxd. Render translucent models, with backface culling if(translucentmodelthings.Count > 0) { @@ -487,16 +452,7 @@ namespace CodeImp.DoomBuilder.Rendering graphics.SetAlphaTestEnable(false); graphics.SetZWriteEnable(false); graphics.SetSourceBlend(Blend.SourceAlpha); - RenderModels(false, true); - } - - // [ZZ] light pass on alpha models - if (General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && lightthings.Count > 0 && translucentmodelthings.Count > 0) - { - graphics.SetAlphaTestEnable(true); - graphics.SetUniform(UniformName.ignoreNormals, true); - RenderModels(true, true); - graphics.SetUniform(UniformName.ignoreNormals, false); + RenderModels(true, lightthings); } // THING CAGES @@ -801,17 +757,28 @@ namespace CodeImp.DoomBuilder.Rendering } // This performs a single render pass - private void RenderSinglePass(Dictionary> geopass, Dictionary> thingspass) + private void RenderSinglePass(Dictionary> geopass, Dictionary> thingspass, List lights) { ImageData curtexture; ShaderName currentshaderpass = shaderpass; ShaderName highshaderpass = (ShaderName)(shaderpass + 2); - // Begin rendering with this shader - graphics.SetShader(shaderpass); + // Begin rendering with this shader + graphics.SetShader(shaderpass); - // Render the geometry collected - foreach(KeyValuePair> group in geopass) + // Light data arrays + Vector4f[] lightColor = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector4f[] lightPosAndRadius = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector4f[] lightOrientation = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector2f[] light2Radius = new Vector2f[MAX_DYNLIGHTS_PER_SURFACE]; + + graphics.SetUniform(UniformName.lightsEnabled, lights.Count > 0); + graphics.SetUniform(UniformName.ignoreNormals, false); + + bool hadlights = false; + + // Render the geometry collected + foreach (KeyValuePair> group in geopass) { // What texture to use? if(group.Key is UnknownImage) @@ -832,6 +799,54 @@ namespace CodeImp.DoomBuilder.Rendering foreach(VisualGeometry g in group.Value) { + + int lightIndex = 0; + + foreach (VisualThing light in lights) + { + if (BoundingBoxesIntersect(g.BoundingBox, light.BoundingBox)) + { + + //t.LightType.LightRenderStyle + //Vector4f lightColor, lightPosAndRadius, lightOrientation, light2Radius; + + lightColor[lightIndex] = light.LightColor.ToVector(); + lightPosAndRadius[lightIndex] = new Vector4f(light.Center, light.LightRadius); + + // set type of light + if (light.LightType.LightType == GZGeneral.LightType.SPOT) + { + lightOrientation[lightIndex] = new Vector4f(light.VectorLookAt, 1f); + light2Radius[lightIndex] = new Vector2f(CosDeg(light.LightSpotRadius1), CosDeg(light.LightSpotRadius2)); + } + else lightOrientation[lightIndex].W = 0f; + + lightIndex++; + + if (lightIndex >= lightColor.Length) + break; + + } + } + + bool havelights = (lightIndex > 0); + + for (int i = lightIndex; i < lightColor.Length; i++) + lightColor[i].W = 0; + + if (havelights != hadlights || havelights) + { + graphics.SetUniform(UniformName.lightColor, lightColor); + if (havelights) + { + graphics.SetUniform(UniformName.lightPosAndRadius, lightPosAndRadius); + graphics.SetUniform(UniformName.lightOrientation, lightOrientation); + graphics.SetUniform(UniformName.light2Radius, light2Radius); + } + } + + hadlights = havelights; + // Changing sector? if(!object.ReferenceEquals(g.Sector, sector)) { @@ -880,8 +895,8 @@ namespace CodeImp.DoomBuilder.Rendering //mxd. Set variables for fog rendering? if(wantedshaderpass > ShaderName.world3d_p7) { - graphics.SetUniform(UniformName.campos, new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, g.FogFactor)); - graphics.SetUniform(UniformName.lightColor, sector.Sector.FogColor); + graphics.SetUniform(UniformName.campos, new Vector4f(cameraposition.x, cameraposition.y, cameraposition.z, g.FogFactor)); + graphics.SetUniform(UniformName.sectorfogcolor, sector.Sector.FogColor); } // Set the colors to use @@ -896,8 +911,10 @@ namespace CodeImp.DoomBuilder.Rendering } } - // Get things for this pass - if(thingspass.Count > 0) + graphics.SetUniform(UniformName.lightsEnabled, false); + + // Get things for this pass + if (thingspass.Count > 0) { // Texture addressing graphics.SetSamplerState(TextureAddress.Clamp); @@ -974,11 +991,11 @@ namespace CodeImp.DoomBuilder.Rendering if(wantedshaderpass > ShaderName.world3d_p7) { graphics.SetUniform(UniformName.modelnormal, Matrix.Identity); - graphics.SetUniform(UniformName.campos, new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, t.FogFactor)); + graphics.SetUniform(UniformName.campos, new Vector4f(cameraposition.x, cameraposition.y, cameraposition.z, t.FogFactor)); } // Set the colors to use - if(t.Thing.Sector != null) graphics.SetUniform(UniformName.lightColor, t.Thing.Sector.FogColor); + if(t.Thing.Sector != null) graphics.SetUniform(UniformName.sectorfogcolor, t.Thing.Sector.FogColor); graphics.SetUniform(UniformName.vertexColor, vertexcolor); graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection))); @@ -1012,7 +1029,7 @@ namespace CodeImp.DoomBuilder.Rendering } //mxd - private void RenderTranslucentPass(List geopass, List thingspass) + private void RenderTranslucentPass(List geopass, List thingspass, List lights) { ShaderName currentshaderpass = shaderpass; ShaderName highshaderpass = (ShaderName)(shaderpass + 2); @@ -1020,12 +1037,6 @@ namespace CodeImp.DoomBuilder.Rendering // Sort geometry by camera distance. First vertex of the BoundingBox is it's center geopass.Sort(delegate(VisualGeometry vg1, VisualGeometry vg2) { - /*if(vg1 == vg2) return 0; - return (int)((General.Map.VisualCamera.Position - vg2.BoundingBox[0]).GetLengthSq() - -(General.Map.VisualCamera.Position - vg1.BoundingBox[0]).GetLengthSq());*/ - - // This does not work when you have huge translucent 3D floor combined with small translucent something over it. - // The huge translucent 3D floor may easily have it's center CLOSER and thus get drawn over everything, which is certainly not expected behavior. if (vg1 == vg2) return 0; @@ -1049,6 +1060,7 @@ namespace CodeImp.DoomBuilder.Rendering } return (int)(dist2 - dist1); + }); ImageData curtexture; @@ -1060,11 +1072,71 @@ namespace CodeImp.DoomBuilder.Rendering // Begin rendering with this shader graphics.SetShader(shaderpass); - // Go for all geometry - foreach(VisualGeometry g in geopass) + + // Light data arrays + Vector4f[] lightColor = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector4f[] lightPosAndRadius = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector4f[] lightOrientation = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector2f[] light2Radius = new Vector2f[MAX_DYNLIGHTS_PER_SURFACE]; + + graphics.SetUniform(UniformName.lightsEnabled, lights.Count > 0); + graphics.SetUniform(UniformName.ignoreNormals, false); + + bool hadlights = false; + + // Go for all geometry + foreach (VisualGeometry g in geopass) { - // Change blend mode? - if(g.RenderPass != currentpass) + + int lightIndex = 0; + + foreach (VisualThing light in lights) + { + if (BoundingBoxesIntersect(g.BoundingBox, light.BoundingBox)) + { + + //t.LightType.LightRenderStyle + //Vector4f lightColor, lightPosAndRadius, lightOrientation, light2Radius; + + lightColor[lightIndex] = light.LightColor.ToVector(); + lightPosAndRadius[lightIndex] = new Vector4f(light.Center, light.LightRadius); + + // set type of light + if (light.LightType.LightType == GZGeneral.LightType.SPOT) + { + lightOrientation[lightIndex] = new Vector4f(light.VectorLookAt, 1f); + light2Radius[lightIndex] = new Vector2f(CosDeg(light.LightSpotRadius1), CosDeg(light.LightSpotRadius2)); + } + else lightOrientation[lightIndex].W = 0f; + + lightIndex++; + + if (lightIndex >= lightColor.Length) + break; + + } + } + + bool havelights = (lightIndex > 0); + + for (int i = lightIndex; i < lightColor.Length; i++) + lightColor[i].W = 0; + + if (havelights != hadlights || havelights) + { + graphics.SetUniform(UniformName.lightColor, lightColor); + if (havelights) + { + graphics.SetUniform(UniformName.lightPosAndRadius, lightPosAndRadius); + graphics.SetUniform(UniformName.lightOrientation, lightOrientation); + graphics.SetUniform(UniformName.light2Radius, light2Radius); + } + } + + hadlights = havelights; + + // Change blend mode? + if (g.RenderPass != currentpass) { switch(g.RenderPass) { @@ -1143,7 +1215,7 @@ namespace CodeImp.DoomBuilder.Rendering // Set variables for fog rendering? if (wantedshaderpass > ShaderName.world3d_p7 && g.FogFactor != fogfactor) { - graphics.SetUniform(UniformName.campos, new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, g.FogFactor)); + graphics.SetUniform(UniformName.campos, new Vector4f(cameraposition.x, cameraposition.y, cameraposition.z, g.FogFactor)); fogfactor = g.FogFactor; } @@ -1151,7 +1223,7 @@ namespace CodeImp.DoomBuilder.Rendering graphics.SetUniform(UniformName.desaturation, sector.Sector.Desaturation); // Set the colors to use - graphics.SetUniform(UniformName.lightColor, sector.Sector.FogColor); + graphics.SetUniform(UniformName.sectorfogcolor, sector.Sector.FogColor); graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((g == highlighted) && showhighlight, (g.Selected && showselection))); // Render! @@ -1160,8 +1232,10 @@ namespace CodeImp.DoomBuilder.Rendering else graphics.SetUniform(UniformName.desaturation, 0.0f); } - // Get things for this pass - if(thingspass.Count > 0) + graphics.SetUniform(UniformName.lightsEnabled, false); + + // Get things for this pass + if (thingspass.Count > 0) { // Texture addressing graphics.SetSamplerState(TextureAddress.Clamp); @@ -1272,13 +1346,13 @@ namespace CodeImp.DoomBuilder.Rendering graphics.SetUniform(UniformName.modelnormal, Matrix.Identity); if (t.FogFactor != fogfactor) { - graphics.SetUniform(UniformName.campos, new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, t.FogFactor)); + graphics.SetUniform(UniformName.campos, new Vector4f(cameraposition.x, cameraposition.y, cameraposition.z, t.FogFactor)); fogfactor = t.FogFactor; } } // Set the colors to use - graphics.SetUniform(UniformName.lightColor, t.Thing.Sector.FogColor); + graphics.SetUniform(UniformName.sectorfogcolor, t.Thing.Sector.FogColor); graphics.SetUniform(UniformName.vertexColor, vertexcolor); graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection))); @@ -1349,206 +1423,8 @@ namespace CodeImp.DoomBuilder.Rendering return (float)Math.Cos(Angle2D.DegToRad(angle)); } - //mxd. Dynamic lights pass! - private VisualSector RenderLightsFromGeometryList(List geometrytolit, List lights, VisualSector sector, bool settexture) - { - foreach (VisualGeometry g in geometrytolit) - { - // Changing sector? - if (!object.ReferenceEquals(g.Sector, sector)) - { - // Only do this sector when a vertexbuffer is created - // mxd. no Map means that sector was deleted recently, I suppose - if (g.Sector.GeometryBuffer != null && g.Sector.Sector.Map != null) - { - // Change current sector - sector = g.Sector; - - // Set stream source - graphics.SetVertexBuffer(sector.GeometryBuffer); - } - else - { - sector = null; - } - } - - if (sector == null) continue; - - graphics.SetUniform(UniformName.desaturation, sector.Sector.Desaturation); - - // note: additive geometry doesn't receive lighting - if (g.RenderPass == RenderPass.Additive) - continue; - - if (settexture) - graphics.SetTexture(g.Texture.Texture); - - //normal lights - int count = lightOffsets[0]; - Vector4 lpr; - if (lightOffsets[0] > 0) - { - graphics.SetBlendOperation(BlendOperation.Add); - - for (int i = 0; i < count; i++) - { - if (BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - graphics.SetUniform(UniformName.lightColor, lights[i].LightColor); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - graphics.Draw(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles); - } - } - } - - //attenuated lights - if (lightOffsets[1] > 0) - { - count += lightOffsets[1]; - graphics.SetBlendOperation(BlendOperation.Add); - - for (int i = lightOffsets[0]; i < count; i++) - { - if (BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - graphics.SetUniform(UniformName.lightColor, lights[i].LightColor); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - graphics.Draw(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles); - } - } - } - - //additive lights - if (lightOffsets[2] > 0) - { - count += lightOffsets[2]; - graphics.SetBlendOperation(BlendOperation.Add); - - for (int i = lightOffsets[0] + lightOffsets[1]; i < count; i++) - { - if (BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - graphics.SetUniform(UniformName.lightColor, lights[i].LightColor); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - graphics.Draw(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles); - } - } - } - - //negative lights - if (lightOffsets[3] > 0) - { - count += lightOffsets[3]; - graphics.SetBlendOperation(BlendOperation.ReverseSubtract); - - for (int i = lightOffsets[0] + lightOffsets[1] + lightOffsets[2]; i < count; i++) - { - if (BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - Color4 lc = lights[i].LightColor; - graphics.SetUniform(UniformName.lightColor, new Color4((lc.Green + lc.Blue) / 2, (lc.Red + lc.Blue) / 2, (lc.Green + lc.Red) / 2, lc.Alpha)); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - graphics.Draw(PrimitiveType.TriangleList, g.VertexOffset, g.Triangles); - } - } - } - } - - return sector; - } - - // [ZZ] split into RenderLights and RenderTranslucentLights - private void RenderTranslucentLights(List geometrytolit, List lights) - { - if (geometrytolit.Count == 0) return; - - graphics.SetUniform(UniformName.modelnormal, Matrix.Identity); - graphics.SetShader(ShaderName.world3d_lightpass); - graphics.SetAlphaBlendEnable(true); - - VisualSector sector = null; - - graphics.SetSourceBlend(Blend.One); - graphics.SetDestinationBlend(Blend.One); - - // - RenderLightsFromGeometryList(geometrytolit, lights, sector, true); - - // - graphics.SetBlendOperation(BlendOperation.Add); - graphics.SetAlphaBlendEnable(false); - } - - // - private void RenderLights(Dictionary> geometrytolit, List lights) - { - // Anything to do? - if (geometrytolit.Count == 0) return; - - graphics.SetUniform(UniformName.modelnormal, Matrix.Identity); - graphics.SetShader(ShaderName.world3d_lightpass); - graphics.SetAlphaBlendEnable(true); - - VisualSector sector = null; - - graphics.SetSourceBlend(Blend.One); - graphics.SetDestinationBlend(Blend.One); - - foreach (KeyValuePair> group in geometrytolit) - { - if (group.Key.Texture == null) continue; - graphics.SetTexture(group.Key.Texture); - - sector = RenderLightsFromGeometryList(group.Value, lights, sector, false); - } - - graphics.SetBlendOperation(BlendOperation.Add); - graphics.SetAlphaBlendEnable(false); - } - //mxd. Render models - private void RenderModels(bool lightpass, bool trans) + private void RenderModels(bool trans, List lights) { ShaderName shaderpass = (fullbrightness ? ShaderName.world3d_fullbright : ShaderName.world3d_main_vertexcolor); ShaderName currentshaderpass = shaderpass; @@ -1557,15 +1433,18 @@ namespace CodeImp.DoomBuilder.Rendering RenderPass currentpass = RenderPass.Solid; // Begin rendering with this shader - if (!lightpass) - { - graphics.SetShader(currentshaderpass); - } - else - { - graphics.SetShader(ShaderName.world3d_lightpass); - graphics.SetAlphaBlendEnable(true); - } + graphics.SetShader(currentshaderpass); + + // Light data arrays + Vector4f[] lightColor = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector4f[] lightPosAndRadius = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector4f[] lightOrientation = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE]; + Vector2f[] light2Radius = new Vector2f[MAX_DYNLIGHTS_PER_SURFACE]; + + graphics.SetUniform(UniformName.lightsEnabled, lights.Count > 0); + graphics.SetUniform(UniformName.ignoreNormals, true); + + bool hadlights = false; List things; if (trans) @@ -1585,6 +1464,7 @@ namespace CodeImp.DoomBuilder.Rendering foreach(VisualThing t in things) { + if (trans) { // Change blend mode? @@ -1625,7 +1505,7 @@ namespace CodeImp.DoomBuilder.Rendering wantedshaderpass += 8; // Switch shader pass? - if (!lightpass && currentshaderpass != wantedshaderpass) + if (currentshaderpass != wantedshaderpass) { graphics.SetShader(wantedshaderpass); currentshaderpass = wantedshaderpass; @@ -1649,147 +1529,73 @@ namespace CodeImp.DoomBuilder.Rendering { // this is not right... graphics.SetUniform(UniformName.modelnormal, General.Map.Data.ModeldefEntries[t.Thing.Type].TransformRotation * modelrotation); - if (t.Thing.Sector != null) graphics.SetUniform(UniformName.lightColor, t.Thing.Sector.FogColor); - graphics.SetUniform(UniformName.campos, new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, t.FogFactor)); + if (t.Thing.Sector != null) graphics.SetUniform(UniformName.sectorfogcolor, t.Thing.Sector.FogColor); + graphics.SetUniform(UniformName.campos, new Vector4f(cameraposition.x, cameraposition.y, cameraposition.z, t.FogFactor)); } if (t.Thing.Sector != null) graphics.SetUniform(UniformName.desaturation, t.Thing.Sector.Desaturation); else graphics.SetUniform(UniformName.desaturation, 0.0f); + int lightIndex = 0; + + foreach (VisualThing light in lights) + { + if (BoundingBoxesIntersect(t.BoundingBox, light.BoundingBox)) + { + + //t.LightType.LightRenderStyle + //Vector4f lightColor, lightPosAndRadius, lightOrientation, light2Radius; + + lightColor[lightIndex] = light.LightColor.ToVector(); + lightPosAndRadius[lightIndex] = new Vector4f(light.Center, light.LightRadius); + + // set type of light + if (light.LightType.LightType == GZGeneral.LightType.SPOT) + { + lightOrientation[lightIndex] = new Vector4f(light.VectorLookAt, 1f); + light2Radius[lightIndex] = new Vector2f(CosDeg(light.LightSpotRadius1), CosDeg(light.LightSpotRadius2)); + } + else lightOrientation[lightIndex].W = 0f; + + lightIndex++; + + if (lightIndex >= lightColor.Length) + break; + + } + } + + bool havelights = (lightIndex > 0); + + for (int i = lightIndex; i < lightColor.Length; i++) + lightColor[i].W = 0; + + if (hadlights != havelights || havelights) + { + graphics.SetUniform(UniformName.lightColor, lightColor); + if (havelights) + { + graphics.SetUniform(UniformName.lightPosAndRadius, lightPosAndRadius); + graphics.SetUniform(UniformName.lightOrientation, lightOrientation); + graphics.SetUniform(UniformName.light2Radius, light2Radius); + } + } + + hadlights = havelights; + GZModel model = General.Map.Data.ModeldefEntries[t.Thing.Type].Model; for (int j = 0; j < model.Meshes.Count; j++) { graphics.SetTexture(model.Textures[j]); - if (!lightpass) - { - // Render! - model.Meshes[j].Draw(graphics); - } - else if (lightpass && t.RenderPass != RenderPass.Additive) // additive stuff does not get any lighting - { - List lights = lightthings; - // - int count = lightOffsets[0]; - Vector4 lpr; - - // normal lights - if (lightOffsets[0] > 0) - { - graphics.SetBlendOperation(BlendOperation.Add); - - for (int i = 0; i < count; i++) - { - if (BoundingBoxesIntersect(t.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - graphics.SetUniform(UniformName.lightColor, lights[i].LightColor); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - model.Meshes[j].Draw(graphics); - } - } - } - - //attenuated lights - if (lightOffsets[1] > 0) - { - count += lightOffsets[1]; - graphics.SetBlendOperation(BlendOperation.Add); - - for (int i = lightOffsets[0]; i < count; i++) - { - if (BoundingBoxesIntersect(t.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - graphics.SetUniform(UniformName.lightColor, lights[i].LightColor); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - model.Meshes[j].Draw(graphics); - } - } - } - - //additive lights - if (lightOffsets[2] > 0) - { - count += lightOffsets[2]; - graphics.SetBlendOperation(BlendOperation.Add); - - for (int i = lightOffsets[0] + lightOffsets[1]; i < count; i++) - { - if (BoundingBoxesIntersect(t.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - graphics.SetUniform(UniformName.lightColor, lights[i].LightColor); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - model.Meshes[j].Draw(graphics); - } - } - } - - //negative lights - if (lightOffsets[3] > 0) - { - count += lightOffsets[3]; - graphics.SetBlendOperation(BlendOperation.ReverseSubtract); - - for (int i = lightOffsets[0] + lightOffsets[1] + lightOffsets[2]; i < count; i++) - { - if (BoundingBoxesIntersect(t.BoundingBox, lights[i].BoundingBox)) - { - lpr = new Vector4(lights[i].Center, lights[i].LightRadius); - if (lpr.W == 0) continue; - Color4 lc = lights[i].LightColor; - graphics.SetUniform(UniformName.lightColor, new Color4((lc.Green + lc.Blue) / 2, (lc.Red + lc.Blue) / 2, (lc.Green + lc.Red) / 2, lc.Alpha)); - graphics.SetUniform(UniformName.lightPosAndRadius, lpr); - GZGeneral.LightData ld = lights[i].LightType; - if (ld.LightType == GZGeneral.LightType.SPOT) - { - graphics.SetUniform(UniformName.spotLight, true); - graphics.SetUniform(UniformName.lightOrientation, lights[i].VectorLookAt); - graphics.SetUniform(UniformName.light2Radius, new Vector2(CosDeg(lights[i].LightSpotRadius1), CosDeg(lights[i].LightSpotRadius2))); - } - else graphics.SetUniform(UniformName.spotLight, false); - model.Meshes[j].Draw(graphics); - } - } - } - } + // Render! + model.Meshes[j].Draw(graphics); } } - if (lightpass) - { - graphics.SetBlendOperation(BlendOperation.Add); - graphics.SetAlphaBlendEnable(false); - } + graphics.SetUniform(UniformName.lightsEnabled, false); + } //mxd @@ -1800,7 +1606,7 @@ namespace CodeImp.DoomBuilder.Rendering // Set render settings graphics.SetShader(ShaderName.world3d_skybox); graphics.SetTexture(General.Map.Data.SkyBox); - graphics.SetUniform(UniformName.campos, new Vector4(cameraposition.x, cameraposition.y, cameraposition.z, 0f)); + graphics.SetUniform(UniformName.campos, new Vector4f(cameraposition.x, cameraposition.y, cameraposition.z, 0f)); foreach(VisualGeometry g in geo) { @@ -1853,20 +1659,20 @@ namespace CodeImp.DoomBuilder.Rendering if(General.Map.Data.GldefsEntries.ContainsKey(t.Thing.Type) && General.Map.Data.GldefsEntries[t.Thing.Type].DontLightSelf && t.Thing.Index == lt.Thing.Index) continue; - float distSquared = Vector3.DistanceSquared(lt.Center, t.Center); + float distSquared = Vector3f.DistanceSquared(lt.Center, t.Center); float radiusSquared = lt.LightRadius * lt.LightRadius; if(distSquared < radiusSquared) { int sign = (lt.LightType.LightRenderStyle == GZGeneral.LightRenderStyle.SUBTRACTIVE ? -1 : 1); - Vector3 L = (t.Center - lt.Center); + Vector3f L = (t.Center - lt.Center); float dist = L.Length(); float scaler = 1 - dist / lt.LightRadius * lt.LightColor.Alpha; if (lt.LightType.LightType == GZGeneral.LightType.SPOT) { - Vector3 lookAt = lt.VectorLookAt; + Vector3f lookAt = lt.VectorLookAt; L.Normalize(); - float cosDir = Vector3.Dot(-L, lookAt); + float cosDir = Vector3f.Dot(-L, lookAt); scaler *= (float)Smoothstep(CosDeg(lt.LightSpotRadius2), CosDeg(lt.LightSpotRadius1), cosDir); } @@ -2061,7 +1867,7 @@ namespace CodeImp.DoomBuilder.Rendering graphics.SetShader(ShaderName.display2d_normal); graphics.SetUniform(UniformName.projection, world * view2d); graphics.SetUniform(UniformName.texturefactor, new Color4(1f, 1f, 1f, 1f)); - graphics.SetUniform(UniformName.rendersettings, new Vector4(1.0f, 1.0f, 0.0f, 1.0f)); + graphics.SetUniform(UniformName.rendersettings, new Vector4f(1.0f, 1.0f, 0.0f, 1.0f)); graphics.SetSamplerFilter(General.Settings.VisualBilinear ? TextureFilter.Linear : TextureFilter.Nearest); // Texture @@ -2085,11 +1891,11 @@ namespace CodeImp.DoomBuilder.Rendering { if (usefog) { - graphics.SetUniform(UniformName.fogsettings, new Vector4(General.Settings.ViewDistance * FOG_RANGE, General.Settings.ViewDistance, 0.0f, 0.0f)); + graphics.SetUniform(UniformName.fogsettings, new Vector4f(General.Settings.ViewDistance * FOG_RANGE, General.Settings.ViewDistance, 0.0f, 0.0f)); } else { - graphics.SetUniform(UniformName.fogsettings, new Vector4(-1.0f)); + graphics.SetUniform(UniformName.fogsettings, new Vector4f(-1.0f)); } } diff --git a/Source/Core/Rendering/Shaders/ShaderCompiler.cs b/Source/Core/Rendering/Shaders/ShaderCompiler.cs new file mode 100755 index 00000000..9dcdfa24 --- /dev/null +++ b/Source/Core/Rendering/Shaders/ShaderCompiler.cs @@ -0,0 +1,974 @@ +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 bool Override; + public List Arguments; + public List Code; + } + + class Shader + { + internal 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; + // functions local to the shader/parents + public List Functions = new List(); + + private const string GLSLInternalSeparator = "_"; + + public Shader(ShaderGroup group) + { + Group = group; + } + + public ShaderFunction GetFunction(string identifier) + { + foreach (ShaderFunction func in Functions) + if (func.Name == identifier) + return func; + return null; + } + + // 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 = GetFunction(token.Value); + if (func == null) 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 = GetFunction(functionName); + if (func == null) 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 CompileShaderFunction(ShaderFunction func, ZScriptTokenizer t) + { + ZScriptToken token; + + 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() ?? ""); + + } + + private static void CompileFunctions(ShaderGroup output, ZScriptTokenizer t) + { + + 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 + + bool isoverride = false; + if (token.Value == "override") + { + isoverride = true; + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected function return type, got {0}", token?.ToString() ?? ""); + } + + // () { } + ShaderFunction func = new ShaderFunction(); + func.Line = t.PositionToLine(token.Position); + func.ReturnValue = token.Value; + func.Override = isoverride; + + CompileShaderFunction(func, t); + + // check if function with such name already exists in the shader + // delete it. + // overloading is not supported for now + for (int i = 0; i < output.Functions.Count; i++) + { + if (output.Functions[i].Name == func.Name) + { + if (!isoverride) + throw new ShaderCompileException("Function {0} is double-defined without 'override' keyword! (previous declaration at line {1})", func.Name, output.Functions[i].Line); + output.Functions.RemoveAt(i); + i--; + continue; + } + } + + output.Functions.Add(func); + + } + + } + + private static void CompileShaderFunctions(Shader output, ZScriptTokenizer t) + { + + 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 + + bool isoverride = false; + if (token.Value == "override") + { + isoverride = true; + + t.SkipWhitespace(); + token = t.ExpectToken(ZScriptTokenType.Identifier); + if (!(token?.IsValid ?? true)) + throw new ShaderCompileException("Expected function return type, got {0}", token?.ToString() ?? ""); + } + + // () { } + ShaderFunction func = new ShaderFunction(); + func.Line = t.PositionToLine(token.Position); + func.ReturnValue = token.Value; + func.Override = isoverride; + + CompileShaderFunction(func, t); + + // check if function with such name already exists in the shader + // delete it. + // overloading is not supported for now + if (!isoverride) + { + ShaderFunction existingFunc = output.Group.GetFunction(func.Name); + if (existingFunc != null) + throw new ShaderCompileException("Function {0} is double-defined without 'override' keyword! (previous declaration at line {1})", func.Name, existingFunc.Line); + } + for (int i = 0; i < output.Functions.Count; i++) + { + if (output.Functions[i].Name == func.Name) + { + if (!isoverride) + throw new ShaderCompileException("Function {0} is double-defined without 'override' keyword! (previous declaration at line {1})", func.Name, output.Functions[i].Line); + output.Functions.RemoveAt(i); + i--; + continue; + } + } + + 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 "functions": + CompileShaderFunctions(s, 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; + } + + // add functions from parent + foreach (ShaderFunction func in p.Functions) + { + if (s.GetFunction(func.Name) == null) + s.Functions.Add(func); + } + } + } + + return output; + } + } + } +} diff --git a/Source/Core/Rendering/Vector2.cs b/Source/Core/Rendering/Vector2.cs index b5c0e211..243e9110 100644 --- a/Source/Core/Rendering/Vector2.cs +++ b/Source/Core/Rendering/Vector2.cs @@ -6,15 +6,15 @@ using System.Threading.Tasks; namespace CodeImp.DoomBuilder.Rendering { - public struct Vector2 + public struct Vector2f { - public Vector2(float v) + public Vector2f(float v) { X = v; Y = v; } - public Vector2(float x, float y) + public Vector2f(float x, float y) { X = x; Y = y; @@ -23,7 +23,7 @@ namespace CodeImp.DoomBuilder.Rendering public float X; public float Y; - public static Vector2 Hermite(Vector2 value1, Vector2 tangent1, Vector2 value2, Vector2 tangent2, float amount) + public static Vector2f Hermite(Vector2f value1, Vector2f tangent1, Vector2f value2, Vector2f tangent2, float amount) { float squared = amount * amount; float cubed = amount * squared; @@ -31,16 +31,16 @@ namespace CodeImp.DoomBuilder.Rendering float part2 = (-2.0f * cubed) + (3.0f * squared); float part3 = (cubed - (2.0f * squared)) + amount; float part4 = cubed - squared; - return new Vector2( + return new Vector2f( (((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4), (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4)); } public override bool Equals(object o) { - if (o is Vector2) + if (o is Vector2f) { - Vector2 v = (Vector2)o; + Vector2f v = (Vector2f)o; return this == v; } else @@ -54,27 +54,88 @@ namespace CodeImp.DoomBuilder.Rendering return X.GetHashCode() + Y.GetHashCode(); } - public static Vector2 operator +(Vector2 left, Vector2 right) + public static Vector2f operator +(Vector2f left, Vector2f right) { - return new Vector2(left.X + right.X, left.Y + right.Y); + return new Vector2f(left.X + right.X, left.Y + right.Y); } - public static Vector2 operator -(Vector2 left, Vector2 right) + public static Vector2f operator -(Vector2f left, Vector2f right) { - return new Vector2(left.X - right.X, left.Y - right.Y); + return new Vector2f(left.X - right.X, left.Y - right.Y); } - public static Vector2 operator -(Vector2 v) + public static Vector2f operator -(Vector2f v) { - return new Vector2(-v.X, -v.Y); + return new Vector2f(-v.X, -v.Y); } - public static bool operator ==(Vector2 left, Vector2 right) + public static bool operator ==(Vector2f left, Vector2f right) { return left.X == right.X && left.Y == right.Y; } - public static bool operator !=(Vector2 left, Vector2 right) + public static bool operator !=(Vector2f left, Vector2f right) + { + return left.X != right.X || left.Y != right.Y; + } + } + + public struct Vector2i + { + public Vector2i(int v) + { + X = v; + Y = v; + } + + public Vector2i(int x, int y) + { + X = x; + Y = y; + } + + public int X; + public int Y; + + public override bool Equals(object o) + { + if (o is Vector2i) + { + Vector2i v = (Vector2i)o; + return this == v; + } + else + { + return false; + } + } + + public override int GetHashCode() + { + return X.GetHashCode() + Y.GetHashCode(); + } + + public static Vector2i operator +(Vector2i left, Vector2i right) + { + return new Vector2i(left.X + right.X, left.Y + right.Y); + } + + public static Vector2i operator -(Vector2i left, Vector2i right) + { + return new Vector2i(left.X - right.X, left.Y - right.Y); + } + + public static Vector2i operator -(Vector2i v) + { + return new Vector2i(-v.X, -v.Y); + } + + public static bool operator ==(Vector2i left, Vector2i right) + { + return left.X == right.X && left.Y == right.Y; + } + + public static bool operator !=(Vector2i left, Vector2i right) { return left.X != right.X || left.Y != right.Y; } diff --git a/Source/Core/Rendering/Vector3.cs b/Source/Core/Rendering/Vector3.cs index d944f9e1..ab15ff82 100644 --- a/Source/Core/Rendering/Vector3.cs +++ b/Source/Core/Rendering/Vector3.cs @@ -6,23 +6,23 @@ using System.Threading.Tasks; namespace CodeImp.DoomBuilder.Rendering { - public struct Vector3 + public struct Vector3f { - public Vector3(float v) + public Vector3f(float v) { X = v; Y = v; Z = v; } - public Vector3(Vector2 xy, float z) + public Vector3f(Vector2f xy, float z) { X = xy.X; Y = xy.Y; Z = z; } - public Vector3(float x, float y, float z) + public Vector3f(float x, float y, float z) { X = x; Y = y; @@ -33,16 +33,16 @@ namespace CodeImp.DoomBuilder.Rendering public float Y; public float Z; - public static Vector4 Transform(Vector3 vector, Matrix transform) + public static Vector4f Transform(Vector3f vector, Matrix transform) { - return new Vector4( + return new Vector4f( (((vector.X * transform.M11) + (vector.Y * transform.M21)) + (vector.Z * transform.M31)) + transform.M41, (((vector.X * transform.M12) + (vector.Y * transform.M22)) + (vector.Z * transform.M32)) + transform.M42, (((vector.X * transform.M13) + (vector.Y * transform.M23)) + (vector.Z * transform.M33)) + transform.M43, (((vector.X * transform.M14) + (vector.Y * transform.M24)) + (vector.Z * transform.M34)) + transform.M44); } - public static Vector3 Hermite(Vector3 value1, Vector3 tangent1, Vector3 value2, Vector3 tangent2, float amount) + public static Vector3f Hermite(Vector3f value1, Vector3f tangent1, Vector3f value2, Vector3f tangent2, float amount) { float squared = amount * amount; float cubed = amount * squared; @@ -50,26 +50,26 @@ namespace CodeImp.DoomBuilder.Rendering float part2 = (-2.0f * cubed) + (3.0f * squared); float part3 = (cubed - (2.0f * squared)) + amount; float part4 = cubed - squared; - return new Vector3( + return new Vector3f( (((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4), (((value1.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4), (((value1.Z * part1) + (value2.Z * part2)) + (tangent1.Z * part3)) + (tangent2.Z * part4)); } - public static float DistanceSquared(Vector3 a, Vector3 b) + public static float DistanceSquared(Vector3f a, Vector3f b) { - Vector3 c = b - a; - return Vector3.Dot(c, c); + Vector3f c = b - a; + return Vector3f.Dot(c, c); } - public static float Dot(Vector3 a, Vector3 b) + public static float Dot(Vector3f a, Vector3f b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; } - public static Vector3 Cross(Vector3 left, Vector3 right) + public static Vector3f Cross(Vector3f left, Vector3f right) { - Vector3 result = new Vector3(); + Vector3f result = new Vector3f(); result.X = left.Y * right.Z - left.Z * right.Y; result.Y = left.Z * right.X - left.X * right.Z; result.Z = left.X * right.Y - left.Y * right.X; @@ -78,10 +78,10 @@ namespace CodeImp.DoomBuilder.Rendering public float Length() { - return (float)Math.Sqrt(Vector3.Dot(this, this)); + return (float)Math.Sqrt(Vector3f.Dot(this, this)); } - public static Vector3 Normalize(Vector3 v) + public static Vector3f Normalize(Vector3f v) { v.Normalize(); return v; @@ -100,9 +100,9 @@ namespace CodeImp.DoomBuilder.Rendering public override bool Equals(object o) { - if (o is Vector3) + if (o is Vector3f) { - Vector3 v = (Vector3)o; + Vector3f v = (Vector3f)o; return this == v; } else @@ -116,27 +116,98 @@ namespace CodeImp.DoomBuilder.Rendering return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode(); } - public static Vector3 operator +(Vector3 left, Vector3 right) + public static Vector3f operator +(Vector3f left, Vector3f right) { - return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z); + return new Vector3f(left.X + right.X, left.Y + right.Y, left.Z + right.Z); } - public static Vector3 operator -(Vector3 left, Vector3 right) + public static Vector3f operator -(Vector3f left, Vector3f right) { - return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + return new Vector3f(left.X - right.X, left.Y - right.Y, left.Z - right.Z); } - public static Vector3 operator -(Vector3 v) + public static Vector3f operator -(Vector3f v) { - return new Vector3(-v.X, -v.Y, -v.Z); + return new Vector3f(-v.X, -v.Y, -v.Z); } - public static bool operator ==(Vector3 left, Vector3 right) + public static bool operator ==(Vector3f left, Vector3f right) { return left.X == right.X && left.Y == right.Y && left.Z == right.Z; } - public static bool operator !=(Vector3 left, Vector3 right) + public static bool operator !=(Vector3f left, Vector3f right) + { + return left.X != right.X || left.Y != right.Y || left.Z != right.Z; + } + } + + public struct Vector3i + { + public Vector3i(int v) + { + X = v; + Y = v; + Z = v; + } + + public Vector3i(Vector2i xy, int z) + { + X = xy.X; + Y = xy.Y; + Z = z; + } + + public Vector3i(int x, int y, int z) + { + X = x; + Y = y; + Z = z; + } + + public int X; + public int Y; + public int Z; + + public override bool Equals(object o) + { + if (o is Vector3i) + { + Vector3i v = (Vector3i)o; + return this == v; + } + else + { + return false; + } + } + + public override int GetHashCode() + { + return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode(); + } + + public static Vector3i operator +(Vector3i left, Vector3i right) + { + return new Vector3i(left.X + right.X, left.Y + right.Y, left.Z + right.Z); + } + + public static Vector3i operator -(Vector3i left, Vector3i right) + { + return new Vector3i(left.X - right.X, left.Y - right.Y, left.Z - right.Z); + } + + public static Vector3i operator -(Vector3i v) + { + return new Vector3i(-v.X, -v.Y, -v.Z); + } + + public static bool operator ==(Vector3i left, Vector3i right) + { + return left.X == right.X && left.Y == right.Y && left.Z == right.Z; + } + + public static bool operator !=(Vector3i left, Vector3i right) { return left.X != right.X || left.Y != right.Y || left.Z != right.Z; } diff --git a/Source/Core/Rendering/Vector4.cs b/Source/Core/Rendering/Vector4.cs index f8a836eb..92bb48c0 100644 --- a/Source/Core/Rendering/Vector4.cs +++ b/Source/Core/Rendering/Vector4.cs @@ -6,9 +6,9 @@ using System.Threading.Tasks; namespace CodeImp.DoomBuilder.Rendering { - public struct Vector4 + public struct Vector4f { - public Vector4(float v) + public Vector4f(float v) { X = v; Y = v; @@ -16,7 +16,7 @@ namespace CodeImp.DoomBuilder.Rendering W = v; } - public Vector4(Vector2 xy, float z, float w) + public Vector4f(Vector2f xy, float z, float w) { X = xy.X; Y = xy.Y; @@ -24,7 +24,7 @@ namespace CodeImp.DoomBuilder.Rendering W = w; } - public Vector4(Vector3 xyz, float w) + public Vector4f(Vector3f xyz, float w) { X = xyz.X; Y = xyz.Y; @@ -32,7 +32,7 @@ namespace CodeImp.DoomBuilder.Rendering W = w; } - public Vector4(float x, float y, float z, float w) + public Vector4f(float x, float y, float z, float w) { X = x; Y = y; @@ -47,9 +47,9 @@ namespace CodeImp.DoomBuilder.Rendering public override bool Equals(object o) { - if (o is Vector4) + if (o is Vector4f) { - Vector4 v = (Vector4)o; + Vector4f v = (Vector4f)o; return this == v; } else @@ -58,19 +58,19 @@ namespace CodeImp.DoomBuilder.Rendering } } - public static Vector4 operator +(Vector4 left, Vector4 right) + public static Vector4f operator +(Vector4f left, Vector4f right) { - return new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + return new Vector4f(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); } - public static Vector4 operator -(Vector4 left, Vector4 right) + public static Vector4f operator -(Vector4f left, Vector4f right) { - return new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + return new Vector4f(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); } - public static Vector4 operator -(Vector4 v) + public static Vector4f operator -(Vector4f v) { - return new Vector4(-v.X, -v.Y, -v.Z, -v.W); + return new Vector4f(-v.X, -v.Y, -v.Z, -v.W); } public override int GetHashCode() @@ -78,12 +78,95 @@ namespace CodeImp.DoomBuilder.Rendering return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode(); } - public static bool operator ==(Vector4 left, Vector4 right) + public static bool operator ==(Vector4f left, Vector4f right) { return left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W; } - public static bool operator !=(Vector4 left, Vector4 right) + public static bool operator !=(Vector4f left, Vector4f right) + { + return left.X != right.X || left.Y != right.Y || left.Z != right.Z || left.W != right.W; + } + } + + public struct Vector4i + { + public Vector4i(int v) + { + X = v; + Y = v; + Z = v; + W = v; + } + + public Vector4i(Vector2i xy, int z, int w) + { + X = xy.X; + Y = xy.Y; + Z = z; + W = w; + } + + public Vector4i(Vector3i xyz, int w) + { + X = xyz.X; + Y = xyz.Y; + Z = xyz.Z; + W = w; + } + + public Vector4i(int x, int y, int z, int w) + { + X = x; + Y = y; + Z = z; + W = w; + } + + public int X; + public int Y; + public int Z; + public int W; + + public override bool Equals(object o) + { + if (o is Vector4i) + { + Vector4i v = (Vector4i)o; + return this == v; + } + else + { + return false; + } + } + + public static Vector4i operator +(Vector4i left, Vector4i right) + { + return new Vector4i(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W); + } + + public static Vector4i operator -(Vector4i left, Vector4i right) + { + return new Vector4i(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W); + } + + public static Vector4i operator -(Vector4i v) + { + return new Vector4i(-v.X, -v.Y, -v.Z, -v.W); + } + + public override int GetHashCode() + { + return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode(); + } + + public static bool operator ==(Vector4i left, Vector4i right) + { + return left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W; + } + + public static bool operator !=(Vector4i left, Vector4i right) { return left.X != right.X || left.Y != right.Y || left.Z != right.Z || left.W != right.W; } 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..d4ee1edb --- /dev/null +++ b/Source/Core/Resources/world3d.shader @@ -0,0 +1,373 @@ +uniforms +{ + mat4 world; + mat4 view; + mat4 projection; + mat4 modelnormal; + vec4 campos; + + vec4 highlightcolor; + vec4 stencilColor; + float desaturation; + + vec4 fogsettings; + vec4 fogcolor; + vec4 sectorfogcolor; + vec4 vertexColor; + + sampler2D texture1; + + // dynamic light related + vec4 lightPosAndRadius[64]; + vec4 lightOrientation[64]; // this is a vector that points in light's direction + vec2 light2Radius[64]; // this is used with spotlights + vec4 lightColor[64]; + float ignoreNormals; + float lightsEnabled; + + // Slope handle length + float slopeHandleLength; + +} + +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(sectorfogcolor.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); + } + + vec3 getOneDynLightContribution(vec3 PosW, vec3 Normal, vec3 light, vec4 lColor, vec4 lPosAndRadius, vec4 lOrientation, vec2 l2Radius) + { + + //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(lPosAndRadius.xyz - PosW + Normal * 3.0)); + if (diffuseContribution < 0.0 && (ignoreNormals == 0 || (lColor.a > 0.979 && lColor.a < 0.981))) // attenuated light and facing away + return light; + + diffuseContribution = max(diffuseContribution, 0.0); // to make sure + + //is pixel in light range? + float dist = distance(PosW, lPosAndRadius.xyz); + + if (dist > lPosAndRadius.w) + return light; + + float power = 1.0; + power *= max(lPosAndRadius.w - dist, 0.0) / lPosAndRadius.w; + + if (lOrientation.w > 0.5) + { + vec3 lightDirection = normalize(lPosAndRadius.xyz - PosW); + float cosDir = dot(lightDirection, lOrientation.xyz); + float df = smoothstep(l2Radius.y, l2Radius.x, cosDir); + power *= df; + } + + if (lColor.a > 0.979 && lColor.a < 0.981) // attenuated light 98% + power *= diffuseContribution; + + // for w/e reason GZDoom also does this + power *= lColor.a; + + if (lColor.a >= 1) + return light.rgb - lColor.rgb * power; + + return light.rgb + lColor.rgb * power; + + } + + vec4 getDynLightContribution(vec4 tcolor, vec4 baselight, vec3 PosW, vec3 Normal) + { + vec3 light = vec3(0, 0, 0); + vec3 addlight = vec3(0, 0, 0); + + if (lightsEnabled != 0) + { + for (int i = 0; i < 64; i++) + { + if (lightColor[i].a == 0) + break; + if (lightColor[i].a < 0.4) // additive + addlight = getOneDynLightContribution(PosW, Normal, addlight, lightColor[i], lightPosAndRadius[i], lightOrientation[i], light2Radius[i]); + else light = getOneDynLightContribution(PosW, Normal, light, lightColor[i], lightPosAndRadius[i], lightOrientation[i], light2Radius[i]); + } + } + + return vec4(tcolor.rgb*(baselight.rgb+light)+addlight, tcolor.a*baselight.a); + } +} + +shader world3d_main +{ + in + { + vec3 Position; + vec4 Color; + vec2 TextureCoordinate; + vec3 Normal; + } + + v2f + { + vec4 Color; + vec2 UV; + vec3 PosW; + vec3 Normal; + vec4 viewpos; + } + + out + { + vec4 FragColor; + } + + 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 + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal); + out.FragColor = desaturate(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_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); + tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal); + if (tcolor.a == 0.0) + { + out.FragColor = tcolor; + } + else + { + // Blend texture color and vertex color + vec4 ncolor = desaturate(tcolor); + + 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_main_fog extends world3d_main +{ + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal); + if (tcolor.a == 0.0) + { + out.FragColor = tcolor; + } + else + { + out.FragColor = desaturate(getFogColor(v2f.PosW, 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_fog extends world3d_main_fog +{ + fragment + { + vec4 tcolor = texture(texture1, v2f.UV); + tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); + tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal); + if (tcolor.a == 0.0) + { + out.FragColor = tcolor; + } + else + { + // Blend texture color and vertex color + vec4 ncolor = desaturate(getFogColor(v2f.PosW, tcolor)); + + 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); + } +} + +// Slope handle shader +shader world3d_slope_handle extends world3d_vertex_color +{ + vertex + { + v2f.viewpos = view * world * vec4(in.Position.x * slopeHandleLength, in.Position.y, in.Position.z, 1.0); + gl_Position = projection * v2f.viewpos; + v2f.Color = in.Color * vertexColor; + v2f.UV = in.TextureCoordinate; + } +} \ 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/VisualModes/VisualGeometry.cs b/Source/Core/VisualModes/VisualGeometry.cs index d5e1b8b0..40a8ee1b 100755 --- a/Source/Core/VisualModes/VisualGeometry.cs +++ b/Source/Core/VisualModes/VisualGeometry.cs @@ -179,8 +179,8 @@ namespace CodeImp.DoomBuilder.VisualModes WorldVertex p2 = vertices[startindex + 1]; WorldVertex p3 = vertices[startindex + 2]; - Vector3 U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z); - Vector3 V = new Vector3(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z); + Vector3f U = new Vector3f(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z); + Vector3f V = new Vector3f(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z); p1.nx = p2.nx = p3.nx = -(U.Y * V.Z - U.Z * V.Y); p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z); diff --git a/Source/Core/VisualModes/VisualSlope.cs b/Source/Core/VisualModes/VisualSlope.cs index 48d1b83e..9461a432 100644 --- a/Source/Core/VisualModes/VisualSlope.cs +++ b/Source/Core/VisualModes/VisualSlope.cs @@ -109,15 +109,18 @@ namespace CodeImp.DoomBuilder.VisualModes public virtual void Update() {} - public void SetPosition(Vector3D pos, Geometry.Plane plane, float angle) + public void SetPosition(Vector3D pos, Plane plane, float angle) { - + Vector3D lookatpoint = new Vector3D(pos.x+128.0f, pos.y+128.0f, plane.GetZ(pos.x + 128.0f, pos.y + 128.0f)); Matrix translate = Matrix.Translation(pos.x, pos.y, pos.z); Matrix rotate = Matrix.RotationZ(angle); - Vector3 v = new Vector3(plane.Normal.x, plane.Normal.y, plane.Normal.z); + Matrix planerotate = Matrix.LookAt(new Vector3f(pos.x, pos.y, pos.z), new Vector3f(lookatpoint.x, lookatpoint.y, lookatpoint.z+0.1f), new Vector3f(0.0f, 1.0f, 0.0f)); + + Matrix xrotate = Matrix.RotationX(90.0f); + //Vector3 v = new Vector3(plane.Normal.x, plane.Normal.y, plane.Normal.z); // Matrix rotate = Matrix.RotationAxis(v, angle); - //position = Matrix.Multiply(rotate, translate); - position = Matrix.Multiply(rotate, translate); + //position = Matrix.Multiply(translate, planerotate); + position = planerotate; } #endregion diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs index 955e41ad..7a184501 100755 --- a/Source/Core/VisualModes/VisualThing.cs +++ b/Source/Core/VisualModes/VisualThing.cs @@ -26,6 +26,7 @@ using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Rendering; using Plane = CodeImp.DoomBuilder.Geometry.Plane; using CodeImp.DoomBuilder.GZBuilder; +using CodeImp.DoomBuilder.GZBuilder.MD3; #endregion @@ -87,12 +88,12 @@ namespace CodeImp.DoomBuilder.VisualModes private float lightSpotRadius2; private float lightPrimaryRadius; private float lightSecondaryRadius; - private Vector3 position_v3; + private Vector3f position_v3; private float lightDelta; //used in light animation private Vector3D[] boundingBox; //gldefs light - private Vector3 lightOffset; + private Vector3f lightOffset; private int lightInterval; private bool isGldefsLight; @@ -116,18 +117,18 @@ namespace CodeImp.DoomBuilder.VisualModes internal int VertexColor { get { return vertices.Length > 0 && vertices[0].Length > 0 ? vertices[0][0].c : 0; } } public int CameraDistance { get { return cameradistance; } } public float FogFactor { get { return fogfactor; } } - public Vector3 Center + public Vector3f Center { get { if (isGldefsLight) return position_v3 + lightOffset; else if (Thing.DynamicLightType != null) return position_v3; // fixes GZDoomBuilder-Bugfix#137 - return new Vector3(position_v3.X, position_v3.Y, position_v3.Z + thingheight / 2f); + return new Vector3f(position_v3.X, position_v3.Y, position_v3.Z + thingheight / 2f); } } public Vector3D CenterV3D { get { return RenderDevice.V3D(Center); } } public float LocalCenterZ { get { return thingheight / 2f; } } //mxd - public Vector3 PositionV3 { get { return position_v3; } } + public Vector3f PositionV3 { get { return position_v3; } } public Vector3D[] BoundingBox { get { return boundingBox; } } //mxd. light properties @@ -141,12 +142,12 @@ namespace CodeImp.DoomBuilder.VisualModes public PixelColor StencilColor { get { return stencilColor; } } // [ZZ] this is used for spotlights - public Vector3 VectorLookAt + public Vector3f VectorLookAt { get { // this esoteric value (1.5708) is 90 degrees but in radians - return new Vector3((float)(Math.Cos(Thing.Angle+1.5708) * Math.Cos(Angle2D.DegToRad(Thing.Pitch))), (float)(Math.Sin(Thing.Angle+1.5708) * Math.Cos(Angle2D.DegToRad(Thing.Pitch))), (float)Math.Sin(Angle2D.DegToRad(Thing.Pitch))); + return new Vector3f((float)(Math.Cos(Thing.Angle+1.5708) * Math.Cos(Angle2D.DegToRad(Thing.Pitch))), (float)(Math.Sin(Thing.Angle+1.5708) * Math.Cos(Angle2D.DegToRad(Thing.Pitch))), (float)Math.Sin(Angle2D.DegToRad(Thing.Pitch))); } } @@ -357,7 +358,7 @@ namespace CodeImp.DoomBuilder.VisualModes float zoffset = ((thing.Pitch == 0f && thing.Position.z == 0f) ? 0.1f : 0f); // Slight offset to avoid z-fighting... for(int i = 0; i < vertices[c].Length; i++) { - Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform); + Vector4f transformed = Vector3f.Transform(new Vector3f(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform); vertices[c][i].x = transformed.X; vertices[c][i].y = transformed.Y; vertices[c][i].z = transformed.Z + zoffset; @@ -385,7 +386,7 @@ namespace CodeImp.DoomBuilder.VisualModes // Apply transform for(int i = 0; i < vertices[c].Length; i++) { - Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform); + Vector4f transformed = Vector3f.Transform(new Vector3f(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform); vertices[c][i].x = transformed.X; vertices[c][i].y = transformed.Y; vertices[c][i].z = transformed.Z; @@ -496,7 +497,7 @@ namespace CodeImp.DoomBuilder.VisualModes // Apply transform for(int i = 0; i < vertices[c].Length; i++) { - Vector4 transformed = Vector3.Transform(new Vector3(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform); + Vector4f transformed = Vector3f.Transform(new Vector3f(vertices[c][i].x, vertices[c][i].y, vertices[c][i].z), transform); vertices[c][i].x = transformed.X; vertices[c][i].y = transformed.Y; vertices[c][i].z = transformed.Z; @@ -769,7 +770,7 @@ namespace CodeImp.DoomBuilder.VisualModes //apply settings lightColor = new Color4(light.Color.Red, light.Color.Green, light.Color.Blue, (float)ld.LightRenderStyle / 100.0f); Vector2D o = new Vector2D(light.Offset.X, light.Offset.Y).GetRotated(thing.Angle - Angle2D.PIHALF); - lightOffset = new Vector3(o.x, o.y, light.Offset.Z); + lightOffset = new Vector3f(o.x, o.y, light.Offset.Z); lightType = light.Type; if(ld.LightModifier == GZGeneral.LightModifier.SECTOR) @@ -851,17 +852,50 @@ namespace CodeImp.DoomBuilder.VisualModes { boundingBox = new Vector3D[9]; boundingBox[0] = CenterV3D; - float h2 = height / 2.0f; - boundingBox[1] = new Vector3D(position_v3.X - width, position_v3.Y - width, Center.Z - h2); - boundingBox[2] = new Vector3D(position_v3.X + width, position_v3.Y - width, Center.Z - h2); - boundingBox[3] = new Vector3D(position_v3.X - width, position_v3.Y + width, Center.Z - h2); - boundingBox[4] = new Vector3D(position_v3.X + width, position_v3.Y + width, Center.Z - h2); + if (Thing.RenderMode != ThingRenderMode.MODEL && Thing.RenderMode != ThingRenderMode.VOXEL) + { - boundingBox[5] = new Vector3D(position_v3.X - width, position_v3.Y - width, Center.Z + h2); - boundingBox[6] = new Vector3D(position_v3.X + width, position_v3.Y - width, Center.Z + h2); - boundingBox[7] = new Vector3D(position_v3.X - width, position_v3.Y + width, Center.Z + h2); - boundingBox[8] = new Vector3D(position_v3.X + width, position_v3.Y + width, Center.Z + h2); + float h2 = height / 2.0f; + + boundingBox[1] = new Vector3D(position_v3.X - width, position_v3.Y - width, Center.Z - h2); + boundingBox[2] = new Vector3D(position_v3.X + width, position_v3.Y - width, Center.Z - h2); + boundingBox[3] = new Vector3D(position_v3.X - width, position_v3.Y + width, Center.Z - h2); + boundingBox[4] = new Vector3D(position_v3.X + width, position_v3.Y + width, Center.Z - h2); + + boundingBox[5] = new Vector3D(position_v3.X - width, position_v3.Y - width, Center.Z + h2); + boundingBox[6] = new Vector3D(position_v3.X + width, position_v3.Y - width, Center.Z + h2); + boundingBox[7] = new Vector3D(position_v3.X - width, position_v3.Y + width, Center.Z + h2); + boundingBox[8] = new Vector3D(position_v3.X + width, position_v3.Y + width, Center.Z + h2); + + } + else + { + + GZModel model = General.Map?.Data?.ModeldefEntries[Thing.Type]?.Model; + + if (model != null) + { + + Vector3D offs = new Vector3D(position_v3.X, position_v3.Y, position_v3.Z); + + boundingBox[5] = new Vector3D(model.BBox.MinX, model.BBox.MinY, model.BBox.MaxZ) + offs; + boundingBox[6] = new Vector3D(model.BBox.MaxX, model.BBox.MinY, model.BBox.MaxZ) + offs; + boundingBox[7] = new Vector3D(model.BBox.MinX, model.BBox.MaxY, model.BBox.MaxZ) + offs; + boundingBox[8] = new Vector3D(model.BBox.MaxX, model.BBox.MaxY, model.BBox.MaxZ) + offs; + + boundingBox[1] = new Vector3D(model.BBox.MinX, model.BBox.MinY, model.BBox.MinZ) + offs; + boundingBox[2] = new Vector3D(model.BBox.MaxX, model.BBox.MinY, model.BBox.MinZ) + offs; + boundingBox[3] = new Vector3D(model.BBox.MinX, model.BBox.MaxY, model.BBox.MinZ) + offs; + boundingBox[4] = new Vector3D(model.BBox.MaxX, model.BBox.MaxY, model.BBox.MinZ) + offs; + + boundingBox[0] = new Vector3D(0.5f * (model.BBox.MinX + model.BBox.MaxX), + 0.5f * (model.BBox.MinY + model.BBox.MaxY), + 0.5f * (model.BBox.MinZ + model.BBox.MaxZ)) + offs; + + } + + } } //mxd. This updates the sprite frame to be rendered @@ -894,3 +928,4 @@ namespace CodeImp.DoomBuilder.VisualModes #endregion } } + diff --git a/Source/Core/ZDoom/ModeldefStructure.cs b/Source/Core/ZDoom/ModeldefStructure.cs index 8705afde..088f9491 100755 --- a/Source/Core/ZDoom/ModeldefStructure.cs +++ b/Source/Core/ZDoom/ModeldefStructure.cs @@ -37,8 +37,8 @@ namespace CodeImp.DoomBuilder.ZDoom private Dictionary[] surfaceskinenames; private string[] modelnames; private string path; - private Vector3 scale; - private Vector3 offset; + private Vector3f scale; + private Vector3f offset; private float angleoffset; private float pitchoffset; private float rolloffset; @@ -55,8 +55,8 @@ namespace CodeImp.DoomBuilder.ZDoom public string[] SkinNames { get { return skinnames; } } public Dictionary[] SurfaceSkinNames { get { return surfaceskinenames; } } public string[] ModelNames { get { return modelnames; } } - public Vector3 Scale { get { return scale; } } - public Vector3 Offset { get { return offset; } } + public Vector3f Scale { get { return scale; } } + public Vector3f Offset { get { return offset; } } public float AngleOffset { get { return angleoffset; } } public float PitchOffset { get { return pitchoffset; } } public float RollOffset { get { return rolloffset; } } @@ -77,7 +77,7 @@ namespace CodeImp.DoomBuilder.ZDoom skinnames = new string[MAX_MODELS]; modelnames = new string[MAX_MODELS]; frames = new Dictionary>(StringComparer.OrdinalIgnoreCase); - scale = new Vector3(1.0f, 1.0f, 1.0f); + scale = new Vector3f(1.0f, 1.0f, 1.0f); surfaceskinenames = new Dictionary[MAX_MODELS]; for(int i = 0; i < MAX_MODELS; i++) { diff --git a/Source/Core/ZDoom/VoxeldefParser.cs b/Source/Core/ZDoom/VoxeldefParser.cs index 1b964906..36c7f214 100755 --- a/Source/Core/ZDoom/VoxeldefParser.cs +++ b/Source/Core/ZDoom/VoxeldefParser.cs @@ -78,7 +78,7 @@ namespace CodeImp.DoomBuilder.ZDoom if(!string.IsNullOrEmpty(modelName) && spriteNames.Count > 0) { mde.ModelNames.Add(modelName); - mde.SetTransform(Matrix.RotationZ(Angle2D.DegToRad(mde.AngleOffset)), Matrix.Identity, new Vector3(scale)); + mde.SetTransform(Matrix.RotationZ(Angle2D.DegToRad(mde.AngleOffset)), Matrix.Identity, new Vector3f(scale)); foreach(string s in spriteNames) { diff --git a/Source/Core/ZDoom/ZScriptTokenizer.cs b/Source/Core/ZDoom/ZScriptTokenizer.cs index 891fe3f4..33fd3231 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; @@ -542,6 +582,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/Backend.cpp b/Source/Native/Backend.cpp index 7304a11b..b7581ca5 100644 --- a/Source/Native/Backend.cpp +++ b/Source/Native/Backend.cpp @@ -23,6 +23,33 @@ #include "Backend.h" #include "OpenGL/GLBackend.h" +namespace +{ + std::string mLastError; + std::string mReturnError; + char mSetErrorBuffer[4096]; +} + +void SetError(const char* fmt, ...) +{ + va_list va; + va_start(va, fmt); + mSetErrorBuffer[0] = 0; + _vsnprintf(mSetErrorBuffer, sizeof(mSetErrorBuffer) - 1, fmt, va); + va_end(va); + mSetErrorBuffer[sizeof(mSetErrorBuffer) - 1] = 0; + mLastError = mSetErrorBuffer; +} + +const char* GetError() +{ + mReturnError.swap(mLastError); + mLastError.clear(); + return mReturnError.c_str(); +} + +///////////////////////////////////////////////////////////////////////////// + Backend* Backend::Get() { static std::unique_ptr backend; @@ -45,9 +72,9 @@ extern "C" Backend::Get()->DeleteRenderDevice(device); } - const char* RenderDevice_GetError(RenderDevice* device) + const char* BuilderNative_GetError() { - return device->GetError(); + return GetError(); } void RenderDevice_DeclareUniform(RenderDevice* device, UniformName name, const char* variablename, UniformType type) @@ -65,9 +92,9 @@ extern "C" device->SetShader(name); } - void RenderDevice_SetUniform(RenderDevice* device, UniformName name, const void* values, int count) + void RenderDevice_SetUniform(RenderDevice* device, UniformName name, const void* values, int count, int bytesize) { - device->SetUniform(name, values, count); + device->SetUniform(name, values, count, bytesize); } void RenderDevice_SetVertexBuffer(RenderDevice* device, VertexBuffer* buffer) diff --git a/Source/Native/Backend.h b/Source/Native/Backend.h index c2944cfe..028de035 100644 --- a/Source/Native/Backend.h +++ b/Source/Native/Backend.h @@ -37,7 +37,7 @@ enum class ShaderFlags : int { None, Debug }; enum class PrimitiveType : int { LineList, TriangleList, TriangleStrip }; enum class TextureFilter : int { Nearest, Linear }; enum class MipmapFilter : int { None, Nearest, Linear }; -enum class UniformType : int { Vec4f, Vec3f, Vec2f, Float, Mat4 }; +enum class UniformType : int { Vec4f, Vec3f, Vec2f, Float, Mat4, Vec4i, Vec3i, Vec2i, Int, Vec4fArray, Vec3fArray, Vec2fArray }; typedef int UniformName; typedef int ShaderName; @@ -51,12 +51,10 @@ class RenderDevice public: virtual ~RenderDevice() = default; - virtual const char* GetError() = 0; - virtual void DeclareUniform(UniformName name, const char* glslname, UniformType type) = 0; virtual void DeclareShader(ShaderName index, const char* name, const char* vertexshader, const char* fragmentshader) = 0; virtual void SetShader(ShaderName name) = 0; - virtual void SetUniform(UniformName name, const void* values, int count) = 0; + virtual void SetUniform(UniformName name, const void* values, int count, int bytesize) = 0; virtual void SetVertexBuffer(VertexBuffer* buffer) = 0; virtual void SetIndexBuffer(IndexBuffer* buffer) = 0; virtual void SetAlphaBlendEnable(bool value) = 0; @@ -129,3 +127,6 @@ public: virtual Texture* NewTexture() = 0; virtual void DeleteTexture(Texture* texture) = 0; }; + +void SetError(const char* fmt, ...); +const char* GetError(); diff --git a/Source/Native/OpenGL/GLRenderDevice.cpp b/Source/Native/OpenGL/GLRenderDevice.cpp index 2777f8d4..2d9277ed 100644 --- a/Source/Native/OpenGL/GLRenderDevice.cpp +++ b/Source/Native/OpenGL/GLRenderDevice.cpp @@ -679,24 +679,6 @@ bool GLRenderDevice::CheckGLError() return false; } -void GLRenderDevice::SetError(const char* fmt, ...) -{ - va_list va; - va_start(va, fmt); - mSetErrorBuffer[0] = 0; - mSetErrorBuffer[sizeof(mSetErrorBuffer) - 1] = 0; - _vsnprintf(mSetErrorBuffer, sizeof(mSetErrorBuffer)-1, fmt, va); - va_end(va); - mLastError = mSetErrorBuffer; -} - -const char* GLRenderDevice::GetError() -{ - mReturnError.swap(mLastError); - mLastError.clear(); - return mReturnError.c_str(); -} - GLShader* GLRenderDevice::GetActiveShader() { if (mAlphaTest) @@ -716,12 +698,16 @@ void GLRenderDevice::SetShader(ShaderName name) } } -void GLRenderDevice::SetUniform(UniformName name, const void* values, int count) +void GLRenderDevice::SetUniform(UniformName name, const void* values, int count, int bytesize) { - float* dest = mUniformData.data() + mUniformInfo[(int)name].Offset; - if (memcmp(dest, values, sizeof(float) * count) != 0) + // "count" should be in bytes now + UniformInfo& info = mUniformInfo[(int)name]; + info.Count = count; + info.Data.resize(bytesize); + uint8_t* dest = info.Data.data(); + if (memcmp(dest, values, bytesize) != 0) { - memcpy(dest, values, sizeof(float) * count); + memcpy(dest, values, bytesize); mUniformInfo[(int)name].LastUpdate++; mNeedApply = true; mUniformsChanged = true; @@ -858,9 +844,6 @@ void GLRenderDevice::DeclareUniform(UniformName name, const char* glslname, Unif UniformInfo& info = mUniformInfo[index]; info.Name = glslname; info.Type = type; - info.Offset = (int)mUniformData.size(); - - mUniformData.resize(mUniformData.size() + (type == UniformType::Mat4 ? 16 : 4)); } bool GLRenderDevice::ApplyUniforms() @@ -872,18 +855,27 @@ bool GLRenderDevice::ApplyUniforms() int count = (int)mUniformInfo.size(); for (int i = 0; i < count; i++) { - if (lastupdates[i] != mUniformInfo.data()[i].LastUpdate) + UniformInfo& info = mUniformInfo.data()[i]; + if (lastupdates[i] != info.LastUpdate) { - float* data = mUniformData.data() + mUniformInfo[i].Offset; + float* data = (float*)info.Data.data(); + int* idata = (int*)info.Data.data(); GLuint location = locations[i]; switch (mUniformInfo[i].Type) { - default: + default: break; case UniformType::Vec4f: glUniform4fv(location, 1, data); break; case UniformType::Vec3f: glUniform3fv(location, 1, data); break; case UniformType::Vec2f: glUniform2fv(location, 1, data); break; case UniformType::Float: glUniform1fv(location, 1, data); break; case UniformType::Mat4: glUniformMatrix4fv(location, 1, GL_FALSE, data); break; + case UniformType::Vec4i: glUniform4iv(location, 1, idata); break; + case UniformType::Vec3i: glUniform3iv(location, 1, idata); break; + case UniformType::Vec2i: glUniform2iv(location, 1, idata); break; + case UniformType::Int: glUniform1iv(location, 1, idata); break; + case UniformType::Vec4fArray: glUniform4fv(location, info.Count, data); break; + case UniformType::Vec3fArray: glUniform3fv(location, info.Count, data); break; + case UniformType::Vec2fArray: glUniform2fv(location, info.Count, data); break; } lastupdates[i] = mUniformInfo[i].LastUpdate; } diff --git a/Source/Native/OpenGL/GLRenderDevice.h b/Source/Native/OpenGL/GLRenderDevice.h index cbe1d90e..e91ac9fa 100644 --- a/Source/Native/OpenGL/GLRenderDevice.h +++ b/Source/Native/OpenGL/GLRenderDevice.h @@ -41,7 +41,7 @@ public: void DeclareUniform(UniformName name, const char* glslname, UniformType type) override; void DeclareShader(ShaderName index, const char* name, const char* vertexshader, const char* fragmentshader) override; void SetShader(ShaderName name) override; - void SetUniform(UniformName name, const void* values, int count) override; + void SetUniform(UniformName name, const void* values, int count, int bytesize) override; void SetVertexBuffer(VertexBuffer* buffer) override; void SetIndexBuffer(IndexBuffer* buffer) override; void SetAlphaBlendEnable(bool value) override; @@ -94,8 +94,6 @@ public: void RequireContext(); bool CheckGLError(); - void SetError(const char* fmt, ...); - const char* GetError(); GLShader* GetActiveShader(); @@ -161,12 +159,12 @@ public: { std::string Name; UniformType Type = {}; - int Offset = 0; int LastUpdate = 0; + int Count = 0; + std::vector Data; }; std::vector mUniformInfo; - std::vector mUniformData; GLuint mStreamVertexBuffer = 0; GLuint mStreamVAO = 0; @@ -195,10 +193,6 @@ public: bool mContextIsCurrent = false; - std::string mLastError; - std::string mReturnError; - char mSetErrorBuffer[4096]; - int mViewportWidth = 0; int mViewportHeight = 0; }; 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 )"; diff --git a/Source/Native/OpenGL/OpenGLContext.cpp b/Source/Native/OpenGL/OpenGLContext.cpp index 870bbfd3..2e70e3b9 100644 --- a/Source/Native/OpenGL/OpenGLContext.cpp +++ b/Source/Native/OpenGL/OpenGLContext.cpp @@ -21,6 +21,7 @@ #include "Precomp.h" #include "OpenGLContext.h" +#include "../Backend.h" #include class OpenGLLoadFunctions @@ -119,7 +120,7 @@ public: OpenGLCreationHelper(HWND window); ~OpenGLCreationHelper(); - HGLRC CreateContext(HDC hdc, int major_version, int minor_version, HGLRC share_context = 0); + HGLRC CreateContext(HDC hdc, HGLRC share_context = 0); private: HWND window; @@ -142,7 +143,7 @@ OpenGLContext::OpenGLContext(void* windowptr) : window((HWND)windowptr) { dc = GetDC(window); OpenGLCreationHelper helper(window); - context = helper.CreateContext(dc, 3, 2); + context = helper.CreateContext(dc); if (context) { MakeCurrent(); @@ -229,9 +230,11 @@ OpenGLCreationHelper::OpenGLCreationHelper(HWND window) : window(window) memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 24; + pfd.cColorBits = 32; + pfd.cDepthBits = 16; + pfd.cStencilBits = 8; int pixelformat = ChoosePixelFormat(query_dc, &pfd); SetPixelFormat(query_dc, pixelformat, &pfd); @@ -253,7 +256,7 @@ OpenGLCreationHelper::~OpenGLCreationHelper() DestroyWindow(query_window); } -HGLRC OpenGLCreationHelper::CreateContext(HDC hdc, int major_version, int minor_version, HGLRC share_context) +HGLRC OpenGLCreationHelper::CreateContext(HDC hdc, HGLRC share_context) { if (query_context == 0) return 0; @@ -264,13 +267,10 @@ HGLRC OpenGLCreationHelper::CreateContext(HDC hdc, int major_version, int minor_ pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 24; - pfd.cRedBits = 8; - pfd.cGreenBits = 8; - pfd.cBlueBits = 8; - pfd.cAlphaBits = 8; - pfd.cDepthBits = 24; + pfd.cColorBits = 32; + pfd.cDepthBits = 16; pfd.cStencilBits = 8; + int pixelformat = ChoosePixelFormat(hdc, &pfd); SetPixelFormat(hdc, pixelformat, &pfd); @@ -278,25 +278,43 @@ HGLRC OpenGLCreationHelper::CreateContext(HDC hdc, int major_version, int minor_ ptr_wglCreateContextAttribsARB wglCreateContextAttribsARB = (ptr_wglCreateContextAttribsARB)wglGetProcAddress("wglCreateContextAttribsARB"); + typedef GLenum(WINAPI* glErrorPtr)(); + glErrorPtr error = reinterpret_cast(GetProcAddress(LoadLibrary("opengl32.dll"), "glGetError")); + HGLRC opengl3_context = 0; if (wglCreateContextAttribsARB) { - std::vector int_attributes; + for (int profile : { 1/*WGL_CONTEXT_CORE_PROFILE_BIT_ARB*/, 2 /*WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB*/ }) + { + for (int version : { 46, 45, 44, 43, 42, 41, 40, 33, 32 }) + { + std::vector int_attributes; + int_attributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); + int_attributes.push_back(version / 10); + int_attributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); + int_attributes.push_back(version % 10); + int_attributes.push_back(0x9126); // WGL_CONTEXT_PROFILE_MASK_ARB + int_attributes.push_back(profile); + int_attributes.push_back(0); + opengl3_context = wglCreateContextAttribsARB(hdc, share_context, int_attributes.data()); - int_attributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB); - int_attributes.push_back(major_version); - int_attributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB); - int_attributes.push_back(minor_version); + if (opengl3_context) + break; + } - int_attributes.push_back(0x2094); // WGL_CONTEXT_FLAGS_ARB - int_attributes.push_back(0x2); // WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB + if (opengl3_context) + break; + } - int_attributes.push_back(0x9126); // WGL_CONTEXT_PROFILE_MASK_ARB - int_attributes.push_back(0x1); // WGL_CONTEXT_CORE_PROFILE_BIT_ARB - - int_attributes.push_back(0); - - opengl3_context = wglCreateContextAttribsARB(hdc, share_context, int_attributes.data()); + // Grab the error from the last create attempt + if (!opengl3_context) + { + SetError("No OpenGL 3.2 support found (error code %d)", (int)error()); + } + } + else + { + SetError("No OpenGL driver supporting OpenGL 3 found"); } wglMakeCurrent(0, 0); @@ -809,32 +827,36 @@ GLXContext OpenGLContext::create_context_glx_1_3(GLXContext shared_context) // threads issuing X commands while this code is running. int (*oldHandler)(::Display*, XErrorEvent*) = XSetErrorHandler(&cl_ctxErrorHandler); - std::vector int_attributes; - - int_attributes.push_back(0x2091); // GLX_CONTEXT_MAJOR_VERSION_ARB - int_attributes.push_back(major_version); - int_attributes.push_back(0x2092); // GLX_CONTEXT_MINOR_VERSION_ARB - int_attributes.push_back(minor_version); - - int_attributes.push_back(0x2094); // GLX_CONTEXT_FLAGS_ARB - int_attributes.push_back(0x2); // GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB - - int_attributes.push_back(0x9126); // GLX_CONTEXT_PROFILE_MASK_ARB - int_attributes.push_back(0x1); // GLX_CONTEXT_CORE_PROFILE_BIT_ARB - - int_attributes.push_back(None); - - cl_ctxErrorOccurred = false; - - GLXContext context_gl3 = glXCreateContextAttribs(disp, fbconfig, shared_context, True, &int_attributes[0]); - - if (cl_ctxErrorOccurred) + GLXContext context_gl3 = 0; + for (int profile : { 1/*GLX_CONTEXT_CORE_PROFILE_BIT_ARB*/, 2 /*GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB*/ }) { - if (context_gl3) + for (int version : { 46, 45, 44, 43, 42, 41, 40, 33, 32 }) { - glx.glXDestroyContext(disp, context_gl3); - context_gl3 = nullptr; + std::vector int_attributes; + int_attributes.push_back(0x2091); // GLX_CONTEXT_MAJOR_VERSION_ARB + int_attributes.push_back(version / 10); + int_attributes.push_back(0x2092); // GLX_CONTEXT_MINOR_VERSION_ARB + int_attributes.push_back(version % 10); + int_attributes.push_back(0x9126); // GLX_CONTEXT_PROFILE_MASK_ARB + int_attributes.push_back(profile); + int_attributes.push_back(None); + + cl_ctxErrorOccurred = false; + + context_gl3 = glXCreateContextAttribs(disp, fbconfig, shared_context, True, int_attributes.data()); + + if (cl_ctxErrorOccurred && context_gl3) + { + glx.glXDestroyContext(disp, context_gl3); + context_gl3 = nullptr; + } + + if (context_gl3) + break; } + + if (context_gl3) + break; } // Restore the original error handler diff --git a/Source/Native/exports.def b/Source/Native/exports.def index 40a8c28b..84dcc0aa 100644 --- a/Source/Native/exports.def +++ b/Source/Native/exports.def @@ -1,9 +1,9 @@ EXPORTS + BuilderNative_GetError RenderDevice_New RenderDevice_Delete - RenderDevice_GetError RenderDevice_DeclareUniform RenderDevice_DeclareShader RenderDevice_SetShader diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index 4d2953b9..e59a3765 100755 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -4332,7 +4332,7 @@ namespace CodeImp.DoomBuilder.BuilderModes float offset; if (!texture.WorldPanning && !General.Map.Data.MapInfo.ForceWorldPanning) - offset = ((start.Sidedef.Sector.CeilHeight - j.ceilingHeight) / scaley) * j.scaleY + ystartalign - j.sidedef.OffsetY; //mxd + offset = ((start.Sidedef.Sector.CeilHeight - j.ceilingHeight) / scaley) * Math.Abs(j.scaleY) + ystartalign - j.sidedef.OffsetY; //mxd else offset = (start.Sidedef.Sector.CeilHeight - j.ceilingHeight + ystartalign - j.sidedef.OffsetY); @@ -4474,7 +4474,7 @@ namespace CodeImp.DoomBuilder.BuilderModes if(aligny) { - float offset = ((start.Sidedef.Sector.CeilHeight - j.ceilingHeight) / scaley) * j.scaleY + ystartalign; //mxd + float offset = ((start.Sidedef.Sector.CeilHeight - j.ceilingHeight) / scaley) * Math.Abs(j.scaleY) + ystartalign; //mxd offset -= j.sidedef.OffsetY; //mxd if(matchtop)