New feature: classic lighting renderer for visual mode (#680)

Added classic rendering mode to closer emulate software renderer visuals in visual mode
This commit is contained in:
volte 2022-01-04 14:17:12 -05:00 committed by GitHub
parent 90896acd43
commit 7fbd07e586
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 1039 additions and 414 deletions

View file

@ -4,4 +4,6 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UDMF/@EntryIndexedValue">UDMF</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UDMF/@EntryIndexedValue">UDMF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=Builder_002FProperties_002FResources/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -209,6 +209,7 @@
<Compile Include="Controls\Scripting\ScriptLumpDocumentTab.cs"> <Compile Include="Controls\Scripting\ScriptLumpDocumentTab.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Data\ColorMap.cs" />
<Compile Include="Data\DirectoryReader.cs" /> <Compile Include="Data\DirectoryReader.cs" />
<Compile Include="Data\FileImage.cs" /> <Compile Include="Data\FileImage.cs" />
<Compile Include="Data\FlatImage.cs" /> <Compile Include="Data\FlatImage.cs" />
@ -1307,6 +1308,7 @@
<None Include="Resources\Angle6.png" /> <None Include="Resources\Angle6.png" />
<None Include="Resources\Angle7.png" /> <None Include="Resources\Angle7.png" />
<None Include="Resources\AboutBack.png" /> <None Include="Resources\AboutBack.png" />
<Content Include="Resources\ClassicRendering.png" />
<Content Include="Resources\DB2.ico" /> <Content Include="Resources\DB2.ico" />
<None Include="Resources\GZDB2.ico" /> <None Include="Resources\GZDB2.ico" />
<None Include="Resources\UDB.ico" /> <None Include="Resources\UDB.ico" />
@ -1365,6 +1367,7 @@
<None Include="Resources\ScriptError.png" /> <None Include="Resources\ScriptError.png" />
<None Include="Resources\ScriptConstant.png" /> <None Include="Resources\ScriptConstant.png" />
<None Include="Resources\Sky.png" /> <None Include="Resources\Sky.png" />
<None Include="Resources\ClassicRendering.png" />
<None Include="Resources\Update.png" /> <None Include="Resources\Update.png" />
<None Include="Resources\Reload.png" /> <None Include="Resources\Reload.png" />
<None Include="Resources\Preferences.png" /> <None Include="Resources\Preferences.png" />

View file

@ -206,6 +206,7 @@
<Compile Include="Controls\Scripting\ScriptLumpDocumentTab.cs"> <Compile Include="Controls\Scripting\ScriptLumpDocumentTab.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Data\ColorMap.cs" />
<Compile Include="Data\DirectoryReader.cs" /> <Compile Include="Data\DirectoryReader.cs" />
<Compile Include="Data\FileImage.cs" /> <Compile Include="Data\FileImage.cs" />
<Compile Include="Data\FlatImage.cs" /> <Compile Include="Data\FlatImage.cs" />

View file

@ -146,6 +146,9 @@ namespace CodeImp.DoomBuilder.Config
private bool dynamicgridsize; private bool dynamicgridsize;
private int ignoredremoterevision; private int ignoredremoterevision;
//volte
private bool classicRendering;
// These are not stored in the configuration, only used at runtime // These are not stored in the configuration, only used at runtime
private int defaultbrightness; private int defaultbrightness;
private int defaultfloorheight; private int defaultfloorheight;
@ -271,6 +274,9 @@ namespace CodeImp.DoomBuilder.Config
public bool DynamicGridSize { get { return dynamicgridsize; } internal set { dynamicgridsize = value; } } //mxd public bool DynamicGridSize { get { return dynamicgridsize; } internal set { dynamicgridsize = value; } } //mxd
internal int IgnoredRemoteRevision { get { return ignoredremoterevision; } set { ignoredremoterevision = value; } } //mxd internal int IgnoredRemoteRevision { get { return ignoredremoterevision; } set { ignoredremoterevision = value; } } //mxd
//volte
public bool ClassicRendering { get { return classicRendering; } internal set { classicRendering = value; } }
//mxd. Left here for compatibility reasons... //mxd. Left here for compatibility reasons...
public string DefaultTexture { get { return General.Map != null ? General.Map.Options.DefaultWallTexture : "-"; } set { if(General.Map != null) General.Map.Options.DefaultWallTexture = value; } } public string DefaultTexture { get { return General.Map != null ? General.Map.Options.DefaultWallTexture : "-"; } set { if(General.Map != null) General.Map.Options.DefaultWallTexture = value; } }
public string DefaultFloorTexture { get { return General.Map != null ? General.Map.Options.DefaultFloorTexture : "-"; } set { if(General.Map != null) General.Map.Options.DefaultFloorTexture = value; } } public string DefaultFloorTexture { get { return General.Map != null ? General.Map.Options.DefaultFloorTexture : "-"; } set { if(General.Map != null) General.Map.Options.DefaultFloorTexture = value; } }
@ -404,6 +410,9 @@ namespace CodeImp.DoomBuilder.Config
dynamicgridsize = cfg.ReadSetting("dynamicgridsize", true); //mxd dynamicgridsize = cfg.ReadSetting("dynamicgridsize", true); //mxd
ignoredremoterevision = cfg.ReadSetting("ignoredremoterevision", 0); //mxd ignoredremoterevision = cfg.ReadSetting("ignoredremoterevision", 0); //mxd
// volte
classicRendering = cfg.ReadSetting("classicrendering", false);
//mxd. Sector defaults //mxd. Sector defaults
defaultceilheight = cfg.ReadSetting("defaultceilheight", 128); defaultceilheight = cfg.ReadSetting("defaultceilheight", 128);
defaultfloorheight = cfg.ReadSetting("defaultfloorheight", 0); defaultfloorheight = cfg.ReadSetting("defaultfloorheight", 0);
@ -544,6 +553,9 @@ namespace CodeImp.DoomBuilder.Config
cfg.WriteSetting("dynamicgridsize", dynamicgridsize); //mxd cfg.WriteSetting("dynamicgridsize", dynamicgridsize); //mxd
cfg.WriteSetting("ignoredremoterevision", ignoredremoterevision); //mxd cfg.WriteSetting("ignoredremoterevision", ignoredremoterevision); //mxd
//volte
cfg.WriteSetting("classicrendering", classicRendering);
//mxd. Sector defaults //mxd. Sector defaults
cfg.WriteSetting("defaultceilheight", defaultceilheight); cfg.WriteSetting("defaultceilheight", defaultceilheight);
cfg.WriteSetting("defaultfloorheight", defaultfloorheight); cfg.WriteSetting("defaultfloorheight", defaultfloorheight);

View file

@ -0,0 +1,107 @@
#region ================== Copyright
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.CompilerServices;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.Data
{
public sealed class ColorMap
{
#region ================== Constants
#endregion
#region ================== Variables
private PixelColor[] colors;
#endregion
#region ================== Properties
public PixelColor this[int index] { get { return colors[index]; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public ColorMap()
{
colors = new PixelColor[34 * 256];
for(int i = 0; i < 34 * 256; i++)
{
// Set colors to gray
colors[i].r = 127;
colors[i].g = 127;
colors[i].b = 127;
colors[i].a = 255;
}
}
// Constructor
public ColorMap(Stream stream, Playpal palette)
{
BinaryReader reader = new BinaryReader(stream);
var colors = new List<PixelColor>();
// Read all palette entries
stream.Seek(0, SeekOrigin.Begin);
while (stream.Position < stream.Length)
{
// Read colors
var index = reader.ReadByte();
var color = palette[index];
colors.Add(color);
}
this.colors = colors.ToArray();
}
#endregion
#region ================== Methods
public Bitmap CreateBitmap() {
var width = 256;
var height = (int)Math.Ceiling((float)colors.Length / 256);
var bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int index = width * y + x;
bitmap.SetPixel(x, y, colors[index].ToColor());
}
}
return bitmap;
}
#endregion
}
}

View file

@ -66,6 +66,7 @@ namespace CodeImp.DoomBuilder.Data
// Palette // Palette
private Playpal palette; private Playpal palette;
private ColorMap mainColormap;
// Textures, Flats and Sprites // Textures, Flats and Sprites
private Dictionary<long, ImageData> textures; private Dictionary<long, ImageData> textures;
@ -163,6 +164,7 @@ namespace CodeImp.DoomBuilder.Data
internal IEnumerable<DataReader> Containers { get { return containers; } } internal IEnumerable<DataReader> Containers { get { return containers; } }
public Playpal Palette { get { return palette; } } public Playpal Palette { get { return palette; } }
public ColorMap MainColorMap { get { return mainColormap; } }
public ICollection<ImageData> Textures { get { return textures.Values; } } public ICollection<ImageData> Textures { get { return textures.Values; } }
public ICollection<ImageData> Flats { get { return flats.Values; } } public ICollection<ImageData> Flats { get { return flats.Values; } }
public List<string> TextureNames { get { return texturenames; } } public List<string> TextureNames { get { return texturenames; } }
@ -428,6 +430,7 @@ namespace CodeImp.DoomBuilder.Data
// Load stuff // Load stuff
LoadX11R6RGB(); //mxd LoadX11R6RGB(); //mxd
LoadPalette(); LoadPalette();
LoadMainColorMap();
Dictionary<string, TexturesParser> cachedparsers = new Dictionary<string, TexturesParser>(); //mxd Dictionary<string, TexturesParser> cachedparsers = new Dictionary<string, TexturesParser>(); //mxd
int texcount = LoadTextures(texturesonly, texturenamesshorttofull, cachedparsers); int texcount = LoadTextures(texturesonly, texturenamesshorttofull, cachedparsers);
int flatcount = LoadFlats(flatsonly, flatnamesshorttofull, cachedparsers); int flatcount = LoadFlats(flatsonly, flatnamesshorttofull, cachedparsers);
@ -839,6 +842,24 @@ namespace CodeImp.DoomBuilder.Data
} }
} }
private void LoadMainColorMap()
{
// Go for all opened containers
for(int i = containers.Count - 1; i >= 0; i--)
{
// Load palette
mainColormap = containers[i].LoadMainColorMap(palette);
if(mainColormap != null) break;
}
// Make empty palette when still no palette found
if(mainColormap == null)
{
General.ErrorLogger.Add(ErrorType.Warning, "None of the loaded resources define a colormap. Did you forget to configure an IWAD for this game configuration?");
mainColormap = new ColorMap();
}
}
#endregion #endregion
#region ================== Colormaps #region ================== Colormaps

View file

@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using CodeImp.DoomBuilder.Compilers; using CodeImp.DoomBuilder.Compilers;
using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.ZDoom; using CodeImp.DoomBuilder.ZDoom;
#endregion #endregion
@ -165,6 +166,8 @@ namespace CodeImp.DoomBuilder.Data
// When implemented, this should find and load a PLAYPAL palette // When implemented, this should find and load a PLAYPAL palette
public virtual Playpal LoadPalette() { return null; } public virtual Playpal LoadPalette() { return null; }
public virtual ColorMap LoadMainColorMap(Playpal palette) { return null; }
#endregion #endregion
#region ================== Colormaps #region ================== Colormaps

View file

@ -38,6 +38,7 @@ namespace CodeImp.DoomBuilder.Data
{ {
#region ================== Constants #region ================== Constants
public const int TEXTURE_INDEXED = 1;
#endregion #endregion
#region ================== Variables #region ================== Variables
@ -61,6 +62,7 @@ namespace CodeImp.DoomBuilder.Data
protected bool hasPatchWithSameName; //mxd protected bool hasPatchWithSameName; //mxd
protected int namewidth; // biwa protected int namewidth; // biwa
protected int shortnamewidth; // biwa protected int shortnamewidth; // biwa
protected bool wantIndexed; // volte
//mxd. Hashing //mxd. Hashing
private static int hashcounter; private static int hashcounter;
@ -85,6 +87,7 @@ namespace CodeImp.DoomBuilder.Data
private int mipmaplevels; // 0 = all mipmaps private int mipmaplevels; // 0 = all mipmaps
protected bool dynamictexture; protected bool dynamictexture;
private Texture texture; private Texture texture;
private Texture indexedTexture;
// Disposing // Disposing
protected bool isdisposed; protected bool isdisposed;
@ -105,7 +108,8 @@ namespace CodeImp.DoomBuilder.Data
public bool HasPatchWithSameName { get { return hasPatchWithSameName; } } //mxd public bool HasPatchWithSameName { get { return hasPatchWithSameName; } } //mxd
internal bool HasLongName { get { return hasLongName; } } //mxd internal bool HasLongName { get { return hasLongName; } } //mxd
public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } } public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } }
public Texture Texture { get { return GetTexture(); } } public Texture Texture { get { return GetTexture(false); } }
public Texture IndexedTexture { get { return GetTexture(true); } }
public bool IsPreviewLoaded public bool IsPreviewLoaded
{ {
get get
@ -176,6 +180,7 @@ namespace CodeImp.DoomBuilder.Data
previewbitmap?.Dispose(); previewbitmap?.Dispose();
spritepreviewbitmap?.Dispose(); spritepreviewbitmap?.Dispose();
texture?.Dispose(); texture?.Dispose();
indexedTexture?.Dispose();
loadedbitmap = null; loadedbitmap = null;
previewbitmap = null; previewbitmap = null;
spritepreviewbitmap = null; spritepreviewbitmap = null;
@ -330,6 +335,7 @@ namespace CodeImp.DoomBuilder.Data
loadedbitmap?.Dispose(); loadedbitmap?.Dispose();
texture?.Dispose(); texture?.Dispose();
indexedTexture?.Dispose();
imagestate = ImageLoadState.Ready; imagestate = ImageLoadState.Ready;
loadedbitmap = loadResult.bitmap; loadedbitmap = loadResult.bitmap;
alphatest = loadResult.alphatest; alphatest = loadResult.alphatest;
@ -676,13 +682,24 @@ namespace CodeImp.DoomBuilder.Data
loadResult.bitmap.UnlockBits(bmpdata); loadResult.bitmap.UnlockBits(bmpdata);
} }
Texture GetTexture() Texture GetTexture(bool indexed = false)
{ {
if (texture != null) if (indexed && indexedTexture != null)
return indexedTexture;
if (!indexed && texture != null)
return texture; return texture;
else if (imagestate == ImageLoadState.Loading)
if (indexed && !wantIndexed)
{
// indexed texture requested, but we didn't generate it, so we have to reload the image
ReleaseTexture();
imagestate = ImageLoadState.None;
wantIndexed = true;
}
if (imagestate == ImageLoadState.Loading)
return General.Map.Data.LoadingTexture; return General.Map.Data.LoadingTexture;
else if (loadfailed) if (loadfailed)
return General.Map.Data.FailedTexture; return General.Map.Data.FailedTexture;
if (imagestate == ImageLoadState.None) if (imagestate == ImageLoadState.None)
@ -691,7 +708,18 @@ namespace CodeImp.DoomBuilder.Data
return General.Map.Data.LoadingTexture; return General.Map.Data.LoadingTexture;
} }
if (loadedbitmap == null)
{
return General.Map.Data.LoadingTexture;
}
texture = new Texture(General.Map.Graphics, loadedbitmap); texture = new Texture(General.Map.Graphics, loadedbitmap);
if (wantIndexed)
{
Bitmap indexedBitmap = CreateIndexedBitmap(loadedbitmap, General.Map.Data.Palette);
indexedTexture = new Texture(General.Map.Graphics, indexedBitmap);
indexedTexture.UserData = TEXTURE_INDEXED;
}
loadedbitmap.Dispose(); loadedbitmap.Dispose();
loadedbitmap = null; loadedbitmap = null;
@ -699,7 +727,33 @@ namespace CodeImp.DoomBuilder.Data
#if DEBUG #if DEBUG
texture.Tag = name; //mxd. Helps with tracking undisposed resources... texture.Tag = name; //mxd. Helps with tracking undisposed resources...
#endif #endif
return texture;
return indexed ? indexedTexture : texture;
}
Bitmap CreateIndexedBitmap(Bitmap original, Playpal palette)
{
int[] indices = new int[original.Width * original.Height];
Bitmap indexed = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
BitmapData indata = original.LockBits(new Rectangle(0, 0, original.Size.Width, original.Size.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
PixelColor* inpixels = (PixelColor*)indata.Scan0.ToPointer();
General.Colors.QuantizeColorsToPlaypal(inpixels, indices, palette);
BitmapData outdata = indexed.LockBits(new Rectangle(0, 0, indexed.Size.Width, indexed.Size.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
PixelColor *outpixels = (PixelColor*)outdata.Scan0.ToPointer();
for (int i = 0; i < indices.Length; i++)
{
outpixels[i].r = (byte)indices[i];
outpixels[i].g = 0;
outpixels[i].b = 0;
outpixels[i].a = inpixels[i].a;
}
original.UnlockBits(indata);
indexed.UnlockBits(outdata);
return indexed;
} }
// This updates a dynamic texture // This updates a dynamic texture
@ -718,6 +772,8 @@ namespace CodeImp.DoomBuilder.Data
{ {
texture?.Dispose(); texture?.Dispose();
texture = null; texture = null;
indexedTexture?.Dispose();
indexedTexture = null;
} }
// This returns a preview image // This returns a preview image

View file

@ -152,6 +152,37 @@ namespace CodeImp.DoomBuilder.Data
return palette; return palette;
} }
// This loads the COLORMAP
public override ColorMap LoadMainColorMap(Playpal palette)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Colormap from wad(s)
ColorMap colormap = null;
foreach(WADReader wr in wads)
{
ColorMap wadcolormap = wr.LoadMainColorMap(palette);
if(wadcolormap != null) return wadcolormap;
}
// Find in root directory
string foundfile = FindFirstFile("COLORMAP", false);
if((foundfile != null) && FileExists(foundfile))
{
MemoryStream stream = LoadFile(foundfile);
if(stream.Length >= 256) //mxd
colormap = new ColorMap(stream, palette);
else
General.ErrorLogger.Add(ErrorType.Warning, "Warning: invalid colormap \"" + foundfile + "\"");
stream.Dispose();
}
// Done
return colormap;
}
#endregion #endregion
#region ================== Textures #region ================== Textures

View file

@ -16,6 +16,9 @@
#region ================== Namespaces #region ================== Namespaces
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO; using System.IO;
using CodeImp.DoomBuilder.Rendering; using CodeImp.DoomBuilder.Rendering;
@ -84,6 +87,38 @@ namespace CodeImp.DoomBuilder.Data
#region ================== Methods #region ================== Methods
public Bitmap CreateBitmap() {
var bitmap = new Bitmap(16, 16, PixelFormat.Format32bppRgb);
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
int index = 16 * y + x;
bitmap.SetPixel(x, y, colors[index].ToColor());
}
}
return bitmap;
}
public int FindClosestColor(PixelColor match)
{
float minDist = 99999;
int minIndex = 0;
for (int i = 0; i < colors.Length; i++)
{
PixelColor color = colors[i];
float dr = (float)match.r - (float)color.r;
float dg = (float)match.g - (float)color.g;
float db = (float)match.b - (float)color.b;
float sqDist = dr * dr + dg * dg + db * db;
if (sqDist < minDist)
{
minIndex = i;
minDist = sqDist;
}
}
return minIndex;
}
#endregion #endregion
} }
} }

View file

@ -26,6 +26,7 @@ using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data.Scripting; using CodeImp.DoomBuilder.Data.Scripting;
using CodeImp.DoomBuilder.GZBuilder.Data; using CodeImp.DoomBuilder.GZBuilder.Data;
using CodeImp.DoomBuilder.IO; using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.ZDoom; using CodeImp.DoomBuilder.ZDoom;
#endregion #endregion
@ -308,6 +309,21 @@ namespace CodeImp.DoomBuilder.Data
return null; // No palette return null; // No palette
} }
public override ColorMap LoadMainColorMap(Playpal palette)
{
// Error when suspended
if(issuspended) throw new Exception("Data reader is suspended");
// Look for a lump named COLORMAP
Lump lump = file.FindLump("COLORMAP");
if (lump != null)
{
using (Stream s = lump.GetSafeStream())
return new ColorMap(s, palette);
}
return null; // No palette
}
#endregion #endregion
#region ================== Colormaps #region ================== Colormaps

View file

@ -210,6 +210,16 @@ namespace CodeImp.DoomBuilder.Properties {
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ClassicRendering {
get {
object obj = ResourceManager.GetObject("ClassicRendering", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap. /// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary> /// </summary>

View file

@ -532,6 +532,9 @@
<data name="Sky" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="Sky" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Sky.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\Sky.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="ClassicRendering" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ClassicRendering.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Pin" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="Pin" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Pin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\Pin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>

View file

@ -19,6 +19,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Drawing; using System.Drawing;
using CodeImp.DoomBuilder.Data;
using Configuration = CodeImp.DoomBuilder.IO.Configuration; using Configuration = CodeImp.DoomBuilder.IO.Configuration;
#endregion #endregion
@ -276,6 +277,12 @@ namespace CodeImp.DoomBuilder.Rendering
} }
} }
// This quantizes an image to a PLAYPAL lump, putting indices into an array of integers.
internal unsafe void QuantizeColorsToPlaypal(PixelColor* inPixels, int[] indices, Playpal playpal)
{
System.Threading.Tasks.Parallel.For(0, indices.Length, (i) => indices[i] = playpal.FindClosestColor(inPixels[i]));
}
// This clamps a value between 0 and 1 // This clamps a value between 0 and 1
private static float Saturate(float v) private static float Saturate(float v)
{ {

View file

@ -17,6 +17,7 @@
#region ================== Namespaces #region ================== Namespaces
using System.Collections.Generic; using System.Collections.Generic;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.VisualModes;
@ -46,6 +47,7 @@ namespace CodeImp.DoomBuilder.Rendering
int CalculateBrightness(int level); int CalculateBrightness(int level);
int CalculateBrightness(int level, Sidedef sd); //mxd int CalculateBrightness(int level, Sidedef sd); //mxd
void SetClassicLightingColorMap(ColorMap colormap);
void SetHighlightedObject(IVisualPickable obj); void SetHighlightedObject(IVisualPickable obj);
void AddSectorGeometry(VisualGeometry g); void AddSectorGeometry(VisualGeometry g);
void AddThingGeometry(VisualThing t); void AddThingGeometry(VisualThing t);

View file

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using CodeImp.DoomBuilder.Controls; using CodeImp.DoomBuilder.Controls;
@ -70,6 +71,11 @@ namespace CodeImp.DoomBuilder.Rendering
DeclareUniform(UniformName.lightsEnabled, "lightsEnabled", UniformType.Float); DeclareUniform(UniformName.lightsEnabled, "lightsEnabled", UniformType.Float);
DeclareUniform(UniformName.slopeHandleLength, "slopeHandleLength", UniformType.Float); DeclareUniform(UniformName.slopeHandleLength, "slopeHandleLength", UniformType.Float);
// volte: classic rendering
DeclareUniform(UniformName.drawPaletted, "drawPaletted", UniformType.Int);
DeclareUniform(UniformName.colormapSize, "colormapSize", UniformType.Vec2i);
DeclareUniform(UniformName.lightLevel, "lightLevel", UniformType.Int);
// 2d fsaa // 2d fsaa
CompileShader(ShaderName.display2d_fsaa, "display2d.shader", "display2d_fsaa"); CompileShader(ShaderName.display2d_fsaa, "display2d.shader", "display2d_fsaa");
@ -91,6 +97,10 @@ namespace CodeImp.DoomBuilder.Rendering
CompileShader(ShaderName.world3d_main_vertexcolor, "world3d.shader", "world3d_main_vertexcolor"); CompileShader(ShaderName.world3d_main_vertexcolor, "world3d.shader", "world3d_main_vertexcolor");
CompileShader(ShaderName.world3d_constant_color, "world3d.shader", "world3d_constant_color"); CompileShader(ShaderName.world3d_constant_color, "world3d.shader", "world3d_constant_color");
// classic rendering
CompileShader(ShaderName.world3d_classic, "world3d.shader", "world3d_classic");
CompileShader(ShaderName.world3d_classic_highlight, "world3d.shader", "world3d_classic_highlight");
// skybox shader // skybox shader
CompileShader(ShaderName.world3d_skybox, "world3d_skybox.shader", "world3d_skybox"); CompileShader(ShaderName.world3d_skybox, "world3d_skybox.shader", "world3d_skybox");
@ -125,7 +135,11 @@ namespace CodeImp.DoomBuilder.Rendering
Handle = RenderDevice_New(display, RenderTarget.Handle); Handle = RenderDevice_New(display, RenderTarget.Handle);
if (Handle == IntPtr.Zero) if (Handle == IntPtr.Zero)
throw new RenderDeviceException(string.Format("Could not create render device: {0}", BuilderNative_GetError())); {
StringBuilder sb = new StringBuilder(4096);
BuilderNative_GetError(sb, sb.Capacity);
throw new RenderDeviceException(string.Format("Could not create render device: {0}", sb));
}
} }
public bool Disposed { get { return Handle == IntPtr.Zero; } } public bool Disposed { get { return Handle == IntPtr.Zero; } }
@ -133,7 +147,11 @@ namespace CodeImp.DoomBuilder.Rendering
void ThrowIfFailed(bool result) void ThrowIfFailed(bool result)
{ {
if (!result) if (!result)
throw new RenderDeviceException(BuilderNative_GetError()); {
StringBuilder sb = new StringBuilder(4096);
BuilderNative_GetError(sb, sb.Capacity);
throw new RenderDeviceException(sb.ToString());
}
} }
public void Dispose() public void Dispose()
@ -359,24 +377,24 @@ namespace CodeImp.DoomBuilder.Rendering
RenderDevice_SetZWriteEnable(Handle, value); RenderDevice_SetZWriteEnable(Handle, value);
} }
public void SetTexture(BaseTexture value) public void SetTexture(BaseTexture value, int unit = 0)
{ {
RenderDevice_SetTexture(Handle, value != null ? value.Handle : IntPtr.Zero); RenderDevice_SetTexture(Handle, unit, value != null ? value.Handle : IntPtr.Zero);
} }
public void SetSamplerFilter(TextureFilter filter) public void SetSamplerFilter(TextureFilter filter, int unit = 0)
{ {
SetSamplerFilter(filter, filter, MipmapFilter.None, 0.0f); SetSamplerFilter(filter, filter, MipmapFilter.None, 0.0f, unit);
} }
public void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy) public void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy, int unit = 0)
{ {
RenderDevice_SetSamplerFilter(Handle, minfilter, magfilter, mipfilter, maxanisotropy); RenderDevice_SetSamplerFilter(Handle, unit, minfilter, magfilter, mipfilter, maxanisotropy);
} }
public void SetSamplerState(TextureAddress address) public void SetSamplerState(TextureAddress address, int unit = 0)
{ {
RenderDevice_SetSamplerState(Handle, address); RenderDevice_SetSamplerState(Handle, unit, address);
} }
public void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) public void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount)
@ -564,7 +582,7 @@ namespace CodeImp.DoomBuilder.Rendering
static extern void RenderDevice_DeclareShader(IntPtr handle, ShaderName index, string name, string vertexShader, string fragShader); static extern void RenderDevice_DeclareShader(IntPtr handle, ShaderName index, string name, string vertexShader, string fragShader);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern string BuilderNative_GetError(); static extern void BuilderNative_GetError(StringBuilder str, int length);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern bool RenderDevice_SetShader(IntPtr handle, ShaderName name); static extern bool RenderDevice_SetShader(IntPtr handle, ShaderName name);
@ -615,13 +633,13 @@ namespace CodeImp.DoomBuilder.Rendering
static extern void RenderDevice_SetZWriteEnable(IntPtr handle, bool value); static extern void RenderDevice_SetZWriteEnable(IntPtr handle, bool value);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetTexture(IntPtr handle, IntPtr texture); static extern void RenderDevice_SetTexture(IntPtr handle, int unit, IntPtr texture);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetSamplerFilter(IntPtr handle, TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy); static extern void RenderDevice_SetSamplerFilter(IntPtr handle, int unit, TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetSamplerState(IntPtr handle, TextureAddress address); static extern void RenderDevice_SetSamplerState(IntPtr handle, int unit, TextureAddress address);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern bool RenderDevice_Draw(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount); static extern bool RenderDevice_Draw(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount);
@ -735,7 +753,10 @@ namespace CodeImp.DoomBuilder.Rendering
world3d_main_highlight_fog_vertexcolor, world3d_main_highlight_fog_vertexcolor,
world3d_vertex_color, world3d_vertex_color,
world3d_constant_color, world3d_constant_color,
world3d_slope_handle world3d_slope_handle,
world3d_classic,
world3d_p19,
world3d_classic_highlight
} }
public enum UniformType : int public enum UniformType : int
@ -778,7 +799,10 @@ namespace CodeImp.DoomBuilder.Rendering
fogcolor, fogcolor,
sectorfogcolor, sectorfogcolor,
lightsEnabled, lightsEnabled,
slopeHandleLength slopeHandleLength,
drawPaletted,
colormapSize,
lightLevel
} }
public enum VertexFormat : int { Flat, World } public enum VertexFormat : int { Flat, World }

View file

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D;
using CodeImp.DoomBuilder.Data; using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.GZBuilder.Data; using CodeImp.DoomBuilder.GZBuilder.Data;
@ -26,6 +27,7 @@ using CodeImp.DoomBuilder.GZBuilder.MD3;
using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.GZBuilder; using CodeImp.DoomBuilder.GZBuilder;
using ColorMap = System.Drawing.Imaging.ColorMap;
#endregion #endregion
@ -65,6 +67,9 @@ namespace CodeImp.DoomBuilder.Rendering
private VisualVertexHandle vertexhandle; private VisualVertexHandle vertexhandle;
private int[] lightOffsets; private int[] lightOffsets;
private Data.ColorMap classicLightingColorMap = null;
private Texture classicLightingColorMapTex = null;
// Slope handle // Slope handle
private VisualSlopeHandle visualslopehandle; private VisualSlopeHandle visualslopehandle;
@ -135,6 +140,11 @@ namespace CodeImp.DoomBuilder.Rendering
public bool ShowSelection { get { return showselection; } set { showselection = value; } } public bool ShowSelection { get { return showselection; } set { showselection = value; } }
public bool ShowHighlight { get { return showhighlight; } set { showhighlight = value; } } public bool ShowHighlight { get { return showhighlight; } set { showhighlight = value; } }
protected bool UseIndexedTexture
{
get { return General.Settings.ClassicRendering && !fullbrightness; }
}
#endregion #endregion
#region ================== Constructor / Disposer #region ================== Constructor / Disposer
@ -294,6 +304,25 @@ namespace CodeImp.DoomBuilder.Rendering
billboard = Matrix.RotationZ((float)(anglexy + Angle2D.PI)); billboard = Matrix.RotationZ((float)(anglexy + Angle2D.PI));
} }
// volte: Set the active colormap for classic lighting
public void SetClassicLightingColorMap(Data.ColorMap colormap)
{
if (colormap == classicLightingColorMap)
{
return;
}
classicLightingColorMap = colormap;
if (classicLightingColorMap == null)
{
classicLightingColorMapTex = null;
}
else
{
classicLightingColorMapTex = new Texture(graphics, classicLightingColorMap.CreateBitmap());
}
}
// This creates 2D view matrix // This creates 2D view matrix
private void CreateMatrices2D() private void CreateMatrices2D()
{ {
@ -327,8 +356,10 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetUniform(UniformName.fogcolor, General.Colors.Background.ToColorValue()); graphics.SetUniform(UniformName.fogcolor, General.Colors.Background.ToColorValue());
graphics.SetUniform(UniformName.texturefactor, new Color4(1f, 1f, 1f, 1f)); graphics.SetUniform(UniformName.texturefactor, new Color4(1f, 1f, 1f, 1f));
graphics.SetUniform(UniformName.highlightcolor, new Color4()); //mxd graphics.SetUniform(UniformName.highlightcolor, new Color4()); //mxd
TextureFilter texFilter = General.Settings.VisualBilinear ? TextureFilter.Linear : TextureFilter.Nearest; TextureFilter texFilter = (!General.Settings.ClassicRendering && General.Settings.VisualBilinear) ? TextureFilter.Linear : TextureFilter.Nearest;
graphics.SetSamplerFilter(texFilter, texFilter, MipmapFilter.Linear, General.Settings.FilterAnisotropy); MipmapFilter mipFilter = General.Settings.ClassicRendering ? MipmapFilter.None : MipmapFilter.Linear;
float aniso = General.Settings.ClassicRendering ? 0 : General.Settings.FilterAnisotropy;
graphics.SetSamplerFilter(texFilter, texFilter, mipFilter, aniso);
// Texture addressing // Texture addressing
graphics.SetSamplerState(TextureAddress.Wrap); graphics.SetSamplerState(TextureAddress.Wrap);
@ -352,7 +383,18 @@ namespace CodeImp.DoomBuilder.Rendering
} }
// Determine shader pass to use // Determine shader pass to use
shaderpass = (fullbrightness ? ShaderName.world3d_fullbright : ShaderName.world3d_main); if (fullbrightness)
{
shaderpass = ShaderName.world3d_fullbright;
}
else if (General.Settings.ClassicRendering)
{
shaderpass = ShaderName.world3d_classic;
}
else
{
shaderpass = ShaderName.world3d_main;
}
// Create crosshair vertices // Create crosshair vertices
if(crosshairverts == null) if(crosshairverts == null)
@ -787,13 +829,24 @@ namespace CodeImp.DoomBuilder.Rendering
bool hadlights = false; bool hadlights = false;
// volte: Set textures for classic lighting
if (classicLightingColorMap != null)
{
graphics.SetUniform(UniformName.colormapSize, new Vector2i(classicLightingColorMapTex.Width, classicLightingColorMapTex.Height));
graphics.SetTexture(classicLightingColorMapTex, 1);
graphics.SetSamplerFilter(TextureFilter.Nearest, TextureFilter.Nearest, MipmapFilter.None, 0, 1);
graphics.SetSamplerState(TextureAddress.Clamp, 1);
}
// Render the geometry collected // Render the geometry collected
foreach (KeyValuePair<ImageData, List<VisualGeometry>> group in geopass) foreach (KeyValuePair<ImageData, List<VisualGeometry>> group in geopass)
{ {
curtexture = group.Key; curtexture = group.Key;
// Apply texture // Apply texture
graphics.SetTexture(curtexture.Texture); Texture texture = UseIndexedTexture ? curtexture.IndexedTexture : curtexture.Texture;
graphics.SetTexture(texture);
graphics.SetUniform(UniformName.drawPaletted, texture.UserData == ImageData.TEXTURE_INDEXED);
//mxd. Sort geometry by sector index //mxd. Sort geometry by sector index
group.Value.Sort((g1, g2) => g1.Sector.Sector.FixedIndex - g2.Sector.Sector.FixedIndex); group.Value.Sort((g1, g2) => g1.Sector.Sector.FixedIndex - g2.Sector.Sector.FixedIndex);
@ -880,7 +933,7 @@ namespace CodeImp.DoomBuilder.Rendering
ShaderName wantedshaderpass = (((g == highlighted) && showhighlight) || (g.Selected && showselection)) ? highshaderpass : shaderpass; ShaderName wantedshaderpass = (((g == highlighted) && showhighlight) || (g.Selected && showselection)) ? highshaderpass : shaderpass;
//mxd. Render fog? //mxd. Render fog?
if(General.Settings.GZDrawFog && !fullbrightness && sector.Sector.FogMode != SectorFogMode.NONE) if(General.Settings.GZDrawFog && !fullbrightness && !General.Settings.ClassicRendering && sector.Sector.FogMode != SectorFogMode.NONE)
wantedshaderpass += 8; wantedshaderpass += 8;
// Switch shader pass? // Switch shader pass?
@ -896,6 +949,9 @@ namespace CodeImp.DoomBuilder.Rendering
} }
} }
// volte: set sector light level for classic rendering mode
graphics.SetUniform(UniformName.lightLevel, sector.Sector.Brightness);
//mxd. Set variables for fog rendering? //mxd. Set variables for fog rendering?
if(wantedshaderpass > ShaderName.world3d_p7) if(wantedshaderpass > ShaderName.world3d_p7)
{ {
@ -934,7 +990,9 @@ namespace CodeImp.DoomBuilder.Rendering
curtexture = group.Key; curtexture = group.Key;
// Apply texture // Apply texture
graphics.SetTexture(curtexture.Texture); Texture texture = UseIndexedTexture ? curtexture.IndexedTexture : curtexture.Texture;
graphics.SetTexture(texture);
graphics.SetUniform(UniformName.drawPaletted, texture.UserData == ImageData.TEXTURE_INDEXED);
// Render all things with this texture // Render all things with this texture
foreach(VisualThing t in group.Value) foreach(VisualThing t in group.Value)
@ -958,20 +1016,20 @@ namespace CodeImp.DoomBuilder.Rendering
ShaderName wantedshaderpass = (((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass; ShaderName wantedshaderpass = (((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass;
//mxd. If fog is enagled, switch to shader, which calculates it //mxd. If fog is enagled, switch to shader, which calculates it
if(General.Settings.GZDrawFog && !fullbrightness && t.Thing.Sector != null && t.Thing.Sector.FogMode != SectorFogMode.NONE) if(General.Settings.GZDrawFog && !fullbrightness && !General.Settings.ClassicRendering && t.Thing.Sector != null && t.Thing.Sector.FogMode != SectorFogMode.NONE)
wantedshaderpass += 8; wantedshaderpass += 8;
//mxd. Create the matrix for positioning //mxd. Create the matrix for positioning
world = CreateThingPositionMatrix(t); world = CreateThingPositionMatrix(t);
//mxd. If current thing is light - set it's color to light color //mxd. If current thing is light - set it's color to light color
if(t.LightType != null && t.LightType.LightInternal && !fullbrightness) if(t.LightType != null && t.LightType.LightInternal && !fullbrightness && !General.Settings.ClassicRendering)
{ {
wantedshaderpass += 4; // Render using one of passes, which uses World3D.VertexColor wantedshaderpass += 4; // Render using one of passes, which uses World3D.VertexColor
vertexcolor = t.LightColor; vertexcolor = t.LightColor;
} }
//mxd. Check if Thing is affected by dynamic lights and set color accordingly //mxd. Check if Thing is affected by dynamic lights and set color accordingly
else if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && lightthings.Count > 0) else if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && !General.Settings.ClassicRendering && lightthings.Count > 0)
{ {
Color4 litcolor = GetLitColorForThing(t); Color4 litcolor = GetLitColorForThing(t);
if(litcolor.ToArgb() != 0) if(litcolor.ToArgb() != 0)
@ -1000,7 +1058,11 @@ namespace CodeImp.DoomBuilder.Rendering
} }
// Set the colors to use // Set the colors to use
if(t.Thing.Sector != null) graphics.SetUniform(UniformName.sectorfogcolor, t.Thing.Sector.FogColor); if (t.Thing.Sector != null)
{
graphics.SetUniform(UniformName.lightLevel, t.Thing.Sector.Brightness);
graphics.SetUniform(UniformName.sectorfogcolor, t.Thing.Sector.FogColor);
}
graphics.SetUniform(UniformName.vertexColor, vertexcolor); graphics.SetUniform(UniformName.vertexColor, vertexcolor);
graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection))); graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection)));
@ -1163,7 +1225,10 @@ namespace CodeImp.DoomBuilder.Rendering
curtexture = g.Texture; curtexture = g.Texture;
// Apply texture // Apply texture
graphics.SetTexture(curtexture.Texture); Texture texture = UseIndexedTexture ? curtexture.IndexedTexture : curtexture.Texture;
graphics.SetTexture(texture);
graphics.SetUniform(UniformName.drawPaletted, texture.UserData == ImageData.TEXTURE_INDEXED);
curtexturename = g.Texture.LongName; curtexturename = g.Texture.LongName;
} }
@ -1195,7 +1260,7 @@ namespace CodeImp.DoomBuilder.Rendering
ShaderName wantedshaderpass = (((g == highlighted) && showhighlight) || (g.Selected && showselection)) ? highshaderpass : shaderpass; ShaderName wantedshaderpass = (((g == highlighted) && showhighlight) || (g.Selected && showselection)) ? highshaderpass : shaderpass;
//mxd. Render fog? //mxd. Render fog?
if (General.Settings.GZDrawFog && !fullbrightness && sector.Sector.FogMode != SectorFogMode.NONE) if (General.Settings.GZDrawFog && !fullbrightness && !General.Settings.ClassicRendering && sector.Sector.FogMode != SectorFogMode.NONE)
wantedshaderpass += 8; wantedshaderpass += 8;
// Switch shader pass? // Switch shader pass?
@ -1295,7 +1360,10 @@ namespace CodeImp.DoomBuilder.Rendering
curtexture = t.Texture; curtexture = t.Texture;
// Apply texture // Apply texture
graphics.SetTexture(curtexture.Texture); Texture texture = UseIndexedTexture ? curtexture.IndexedTexture : curtexture.Texture;
graphics.SetTexture(texture);
graphics.SetUniform(UniformName.drawPaletted, texture.UserData == ImageData.TEXTURE_INDEXED);
curtexturename = t.Texture.LongName; curtexturename = t.Texture.LongName;
} }
@ -1306,20 +1374,20 @@ namespace CodeImp.DoomBuilder.Rendering
ShaderName wantedshaderpass = (((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass; ShaderName wantedshaderpass = (((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass;
//mxd. if fog is enagled, switch to shader, which calculates it //mxd. if fog is enagled, switch to shader, which calculates it
if(General.Settings.GZDrawFog && !fullbrightness && t.Thing.Sector != null && t.Thing.Sector.FogMode != SectorFogMode.NONE) if(General.Settings.GZDrawFog && !fullbrightness && !General.Settings.ClassicRendering && t.Thing.Sector != null && t.Thing.Sector.FogMode != SectorFogMode.NONE)
wantedshaderpass += 8; wantedshaderpass += 8;
//mxd. Create the matrix for positioning //mxd. Create the matrix for positioning
world = CreateThingPositionMatrix(t); world = CreateThingPositionMatrix(t);
//mxd. If current thing is light - set it's color to light color //mxd. If current thing is light - set it's color to light color
if(t.LightType != null && t.LightType.LightInternal && !fullbrightness) if(t.LightType != null && t.LightType.LightInternal && !fullbrightness && !General.Settings.ClassicRendering)
{ {
wantedshaderpass += 4; // Render using one of passes, which uses World3D.VertexColor wantedshaderpass += 4; // Render using one of passes, which uses World3D.VertexColor
vertexcolor = t.LightColor; vertexcolor = t.LightColor;
} }
//mxd. Check if Thing is affected by dynamic lights and set color accordingly //mxd. Check if Thing is affected by dynamic lights and set color accordingly
else if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && lightthings.Count > 0) else if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && !General.Settings.ClassicRendering && lightthings.Count > 0)
{ {
Color4 litcolor = GetLitColorForThing(t); Color4 litcolor = GetLitColorForThing(t);
if(litcolor.ToArgb() != 0) if(litcolor.ToArgb() != 0)
@ -1506,7 +1574,7 @@ namespace CodeImp.DoomBuilder.Rendering
ShaderName wantedshaderpass = ((((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass); ShaderName wantedshaderpass = ((((t == highlighted) && showhighlight) || (t.Selected && showselection)) ? highshaderpass : shaderpass);
// If fog is enagled, switch to shader, which calculates it // If fog is enagled, switch to shader, which calculates it
if (General.Settings.GZDrawFog && !fullbrightness && t.Thing.Sector != null && t.Thing.Sector.FogMode != SectorFogMode.NONE) if (General.Settings.GZDrawFog && !fullbrightness && !General.Settings.ClassicRendering && t.Thing.Sector != null && t.Thing.Sector.FogMode != SectorFogMode.NONE)
wantedshaderpass += 8; wantedshaderpass += 8;
// Switch shader pass? // Switch shader pass?

View file

@ -97,6 +97,7 @@ namespace CodeImp.DoomBuilder.Rendering
public TextureFormat Format { get; private set; } public TextureFormat Format { get; private set; }
public object Tag { get; set; } public object Tag { get; set; }
public int UserData { get; set; }
} }
public class CubeTexture : BaseTexture public class CubeTexture : BaseTexture

View file

@ -1330,6 +1330,16 @@ gztogglevisualvertices
default = 262230; default = 262230;
} }
toggleclassicrendering
{
title = "Toggle classic rendering";
category = "visual";
description = "When enabled, attempts to simulate classic Doom rendering with banded light and palettized textures.";
allowkeys = true;
allowmouse = true;
allowscroll = false;
}
gztoggleenhancedrendering gztoggleenhancedrendering
{ {
title = "Toggle Enhanced Rendering Effects"; title = "Toggle Enhanced Rendering Effects";

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -16,6 +16,13 @@ uniforms
vec4 vertexColor; vec4 vertexColor;
sampler2D texture1; sampler2D texture1;
sampler2D texture2;
sampler2D texture3;
// classic lighting related
int drawPaletted;
ivec2 colormapSize;
int lightLevel;
// dynamic light related // dynamic light related
vec4 lightPosAndRadius[64]; vec4 lightPosAndRadius[64];
@ -32,6 +39,59 @@ uniforms
functions functions
{ {
vec4 getColorMappedColor(int entry, int depth)
{
vec2 uv = vec2((float(entry) + 0.5) / colormapSize.x, (float(depth) + 0.5) / colormapSize.y);
vec4 colormapColor = texture(texture2, uv);
return colormapColor;
}
int classicLightLevelToColorMapOffset(int lightLevel, vec3 position, vec3 normal)
{
const int LIGHTLEVELS = 16;
const int LIGHTSEGSHIFT = 4;
const int NUMCOLORMAPS = 32;
const int MAXLIGHTSCALE = 48;
const int DISTMAP = 2;
int scaledLightLevel = lightLevel >> LIGHTSEGSHIFT;
bool isFlat = abs(dot(normal, vec3(0, 0, 1))) > 1e-3;
if (abs(dot(normal, vec3(0, 1, 0))) < 1e-3)
{
scaledLightLevel++;
}
else if (abs(dot(normal, vec3(1, 0, 0))) < 1e-3)
{
scaledLightLevel--;
}
int level;
float dist = distance(position, campos.xyz);
if (!isFlat)
{
int startmap = int(((LIGHTLEVELS-1-scaledLightLevel)*2)*NUMCOLORMAPS/LIGHTLEVELS);
// same calculation as Eternity Engine
int index = int(2560.0 / dist);
if (index >= MAXLIGHTSCALE) index = MAXLIGHTSCALE - 1;
level = startmap - index / DISTMAP;
}
else
{
// same calculation as Eternity Engine
float startmap = 2.0 * (30.0 - lightLevel / 8.0f);
level = int(startmap - (1280.0f / dist)) + 1;
}
if (level < 0) level = 0;
if (level >= NUMCOLORMAPS) level = NUMCOLORMAPS - 1;
return level;
}
// This adds fog color to current pixel color // This adds fog color to current pixel color
vec4 getFogColor(vec3 PosW, vec4 color) vec4 getFogColor(vec3 PosW, vec4 color)
{ {
@ -371,3 +431,66 @@ shader world3d_slope_handle extends world3d_vertex_color
v2f.UV = in.TextureCoordinate; v2f.UV = in.TextureCoordinate;
} }
} }
shader world3d_classic extends world3d_main
{
fragment
{
vec4 pcolor;
if (bool(drawPaletted))
{
vec4 color = texture(texture1, v2f.UV);
int entry = int(color.r * 255);
float alpha = color.a;
int colorMapOffset = classicLightLevelToColorMapOffset(lightLevel, v2f.PosW, v2f.Normal);
pcolor = getColorMappedColor(entry, colorMapOffset);
pcolor.a = alpha;
}
else
{
pcolor = texture(texture1, v2f.UV);
}
out.FragColor = pcolor;
#if defined(ALPHA_TEST)
if (out.FragColor.a < 0.5) discard;
#endif
}
}
shader world3d_classic_highlight extends world3d_main
{
fragment
{
vec4 pcolor;
if (bool(drawPaletted))
{
vec4 color = texture(texture1, v2f.UV);
int entry = int(color.r * 255);
float alpha = color.a;
int modifiedLightLevel = max(lightLevel, 128);
int colorMapOffset = classicLightLevelToColorMapOffset(modifiedLightLevel, v2f.PosW, v2f.Normal);
pcolor = getColorMappedColor(entry, colorMapOffset);
pcolor.a = alpha;
}
else
{
pcolor = texture(texture1, v2f.UV);
}
out.FragColor = pcolor;
if (pcolor.a > 0.0)
{
out.FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (pcolor.rgb - 0.4 * highlightcolor.a), max(pcolor.a + 0.25, 0.5));
}
#if defined(ALPHA_TEST)
if (out.FragColor.a < 0.5) discard;
#endif
}
}

View file

@ -191,6 +191,7 @@ namespace CodeImp.DoomBuilder.Windows
this.itemallmdl = new System.Windows.Forms.ToolStripMenuItem(); this.itemallmdl = new System.Windows.Forms.ToolStripMenuItem();
this.itemtogglefog = new System.Windows.Forms.ToolStripMenuItem(); this.itemtogglefog = new System.Windows.Forms.ToolStripMenuItem();
this.itemtogglesky = new System.Windows.Forms.ToolStripMenuItem(); this.itemtogglesky = new System.Windows.Forms.ToolStripMenuItem();
this.itemtoggleclassicrendering = new System.Windows.Forms.ToolStripMenuItem();
this.itemtoggleeventlines = new System.Windows.Forms.ToolStripMenuItem(); this.itemtoggleeventlines = new System.Windows.Forms.ToolStripMenuItem();
this.itemtogglevisualverts = new System.Windows.Forms.ToolStripMenuItem(); this.itemtogglevisualverts = new System.Windows.Forms.ToolStripMenuItem();
this.buttonfullbrightness = new System.Windows.Forms.ToolStripButton(); this.buttonfullbrightness = new System.Windows.Forms.ToolStripButton();
@ -224,6 +225,7 @@ namespace CodeImp.DoomBuilder.Windows
this.modelsshowall = new System.Windows.Forms.ToolStripMenuItem(); this.modelsshowall = new System.Windows.Forms.ToolStripMenuItem();
this.buttontogglefog = new System.Windows.Forms.ToolStripButton(); this.buttontogglefog = new System.Windows.Forms.ToolStripButton();
this.buttontogglesky = new System.Windows.Forms.ToolStripButton(); this.buttontogglesky = new System.Windows.Forms.ToolStripButton();
this.buttontoggleclassicrendering = new System.Windows.Forms.ToolStripButton();
this.buttontoggleeventlines = new System.Windows.Forms.ToolStripButton(); this.buttontoggleeventlines = new System.Windows.Forms.ToolStripButton();
this.buttontogglevisualvertices = new System.Windows.Forms.ToolStripButton(); this.buttontogglevisualvertices = new System.Windows.Forms.ToolStripButton();
this.separatorgzmodes = new System.Windows.Forms.ToolStripSeparator(); this.separatorgzmodes = new System.Windows.Forms.ToolStripSeparator();
@ -798,6 +800,7 @@ namespace CodeImp.DoomBuilder.Windows
this.itemmodelmodes, this.itemmodelmodes,
this.itemtogglefog, this.itemtogglefog,
this.itemtogglesky, this.itemtogglesky,
this.itemtoggleclassicrendering,
this.itemtoggleeventlines, this.itemtoggleeventlines,
this.itemtogglevisualverts, this.itemtogglevisualverts,
this.separatorhelpers, this.separatorhelpers,
@ -1395,6 +1398,7 @@ namespace CodeImp.DoomBuilder.Windows
this.modelrendermode, this.modelrendermode,
this.buttontogglefog, this.buttontogglefog,
this.buttontogglesky, this.buttontogglesky,
this.buttontoggleclassicrendering,
this.buttontoggleeventlines, this.buttontoggleeventlines,
this.buttontogglevisualvertices, this.buttontogglevisualvertices,
this.separatorgzmodes, this.separatorgzmodes,
@ -1797,6 +1801,16 @@ namespace CodeImp.DoomBuilder.Windows
this.itemtogglesky.Text = "Render sky (Visual mode)"; this.itemtogglesky.Text = "Render sky (Visual mode)";
this.itemtogglesky.Click += new System.EventHandler(this.InvokeTaggedAction); this.itemtogglesky.Click += new System.EventHandler(this.InvokeTaggedAction);
// //
// itemclassicrendering
//
this.itemtoggleclassicrendering.CheckOnClick = true;
this.itemtoggleclassicrendering.Image = global::CodeImp.DoomBuilder.Properties.Resources.ClassicRendering;
this.itemtoggleclassicrendering.Name = "itemtoggleclassicrendering";
this.itemtoggleclassicrendering.Size = new System.Drawing.Size(273, 22);
this.itemtoggleclassicrendering.Tag = "builder_toggleclassicrendering";
this.itemtoggleclassicrendering.Text = "Classic rendering (Visual mode)";
this.itemtoggleclassicrendering.Click += new System.EventHandler(this.InvokeTaggedAction);
//
// itemeventlines // itemeventlines
// //
this.itemtoggleeventlines.CheckOnClick = true; this.itemtoggleeventlines.CheckOnClick = true;
@ -2170,6 +2184,18 @@ namespace CodeImp.DoomBuilder.Windows
this.buttontogglesky.Text = "Render Sky (Visual mode)"; this.buttontogglesky.Text = "Render Sky (Visual mode)";
this.buttontogglesky.Click += new System.EventHandler(this.InvokeTaggedAction); this.buttontogglesky.Click += new System.EventHandler(this.InvokeTaggedAction);
// //
// buttontoggleclassicrendering
//
this.buttontoggleclassicrendering.CheckOnClick = true;
this.buttontoggleclassicrendering.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.buttontoggleclassicrendering.Image = global::CodeImp.DoomBuilder.Properties.Resources.ClassicRendering;
this.buttontoggleclassicrendering.ImageTransparentColor = System.Drawing.Color.Magenta;
this.buttontoggleclassicrendering.Name = "buttontoggleclassicrendering";
this.buttontoggleclassicrendering.Size = new System.Drawing.Size(23, 20);
this.buttontoggleclassicrendering.Tag = "builder_toggleclassicrendering";
this.buttontoggleclassicrendering.Text = "Classic Rendering (Visual mode)";
this.buttontoggleclassicrendering.Click += new System.EventHandler(this.InvokeTaggedAction);
//
// buttontoggleeventlines // buttontoggleeventlines
// //
this.buttontoggleeventlines.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; this.buttontoggleeventlines.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
@ -3013,6 +3039,7 @@ namespace CodeImp.DoomBuilder.Windows
private System.Windows.Forms.ToolStripSeparator seperatorgeometry; private System.Windows.Forms.ToolStripSeparator seperatorgeometry;
private System.Windows.Forms.ToolStripButton buttontogglefog; private System.Windows.Forms.ToolStripButton buttontogglefog;
private System.Windows.Forms.ToolStripButton buttontogglesky; private System.Windows.Forms.ToolStripButton buttontogglesky;
private System.Windows.Forms.ToolStripButton buttontoggleclassicrendering;
private System.Windows.Forms.ToolStripStatusLabel warnsLabel; private System.Windows.Forms.ToolStripStatusLabel warnsLabel;
private System.Windows.Forms.ToolStripMenuItem itemReloadModedef; private System.Windows.Forms.ToolStripMenuItem itemReloadModedef;
private System.Windows.Forms.ToolStripMenuItem itemReloadGldefs; private System.Windows.Forms.ToolStripMenuItem itemReloadGldefs;
@ -3072,6 +3099,7 @@ namespace CodeImp.DoomBuilder.Windows
private System.Windows.Forms.ToolStripMenuItem itemallmdl; private System.Windows.Forms.ToolStripMenuItem itemallmdl;
private System.Windows.Forms.ToolStripMenuItem itemtogglefog; private System.Windows.Forms.ToolStripMenuItem itemtogglefog;
private System.Windows.Forms.ToolStripMenuItem itemtogglesky; private System.Windows.Forms.ToolStripMenuItem itemtogglesky;
private System.Windows.Forms.ToolStripMenuItem itemtoggleclassicrendering;
private System.Windows.Forms.ToolStripMenuItem itemtoggleeventlines; private System.Windows.Forms.ToolStripMenuItem itemtoggleeventlines;
private System.Windows.Forms.ToolStripMenuItem itemtogglevisualverts; private System.Windows.Forms.ToolStripMenuItem itemtogglevisualverts;
private ToolStripMenuItem itemimport; private ToolStripMenuItem itemimport;

View file

@ -2164,6 +2164,7 @@ namespace CodeImp.DoomBuilder.Windows
buttonsplitjoinedsectors.Checked = General.Settings.SplitJoinedSectors; //mxd buttonsplitjoinedsectors.Checked = General.Settings.SplitJoinedSectors; //mxd
buttonautoclearsidetextures.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd buttonautoclearsidetextures.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
buttontest.Visible = General.Settings.ToolbarTesting && maploaded; buttontest.Visible = General.Settings.ToolbarTesting && maploaded;
buttontoggleclassicrendering.Visible = General.Settings.ToolbarViewModes && maploaded;
//mxd //mxd
modelrendermode.Visible = General.Settings.GZToolbarGZDoom && maploaded; modelrendermode.Visible = General.Settings.GZToolbarGZDoom && maploaded;
@ -2330,6 +2331,7 @@ namespace CodeImp.DoomBuilder.Windows
buttontogglefog.Checked = General.Settings.GZDrawFog; buttontogglefog.Checked = General.Settings.GZDrawFog;
buttontogglesky.Checked = General.Settings.GZDrawSky; buttontogglesky.Checked = General.Settings.GZDrawSky;
buttontoggleclassicrendering.Checked = General.Settings.ClassicRendering;
buttontoggleeventlines.Checked = General.Settings.GZShowEventLines; buttontoggleeventlines.Checked = General.Settings.GZShowEventLines;
buttontogglevisualvertices.Visible = General.Map.UDMF; buttontogglevisualvertices.Visible = General.Map.UDMF;
buttontogglevisualvertices.Checked = General.Settings.GZShowVisualVertices; buttontogglevisualvertices.Checked = General.Settings.GZShowVisualVertices;
@ -3141,6 +3143,7 @@ namespace CodeImp.DoomBuilder.Windows
itemtogglefixedthingsscale.Checked = General.Settings.FixedThingsScale; //mxd itemtogglefixedthingsscale.Checked = General.Settings.FixedThingsScale; //mxd
itemtogglefog.Checked = General.Settings.GZDrawFog; itemtogglefog.Checked = General.Settings.GZDrawFog;
itemtogglesky.Checked = General.Settings.GZDrawSky; itemtogglesky.Checked = General.Settings.GZDrawSky;
itemtoggleclassicrendering.Checked = General.Settings.ClassicRendering;
itemtoggleeventlines.Checked = General.Settings.GZShowEventLines; itemtoggleeventlines.Checked = General.Settings.GZShowEventLines;
itemtogglevisualverts.Visible = (General.Map != null && General.Map.UDMF); itemtogglevisualverts.Visible = (General.Map != null && General.Map.UDMF);
itemtogglevisualverts.Checked = General.Settings.GZShowVisualVertices; itemtogglevisualverts.Checked = General.Settings.GZShowVisualVertices;
@ -3215,6 +3218,20 @@ namespace CodeImp.DoomBuilder.Windows
General.MainWindow.UpdateGZDoomPanel(); General.MainWindow.UpdateGZDoomPanel();
} }
//mxd
[BeginAction("toggleclassicrendering")]
internal void ToggleClassicRendering()
{
General.Settings.ClassicRendering = !General.Settings.ClassicRendering;
itemtoggleclassicrendering.Checked = General.Settings.ClassicRendering;
buttontoggleclassicrendering.Checked = General.Settings.ClassicRendering;
General.MainWindow.DisplayStatus(StatusType.Action, "Classic rendering is " + (General.Settings.ClassicRendering ? "ENABLED" : "DISABLED"));
General.MainWindow.RedrawDisplay();
General.MainWindow.UpdateGZDoomPanel();
}
[BeginAction("gztoggleeventlines")] [BeginAction("gztoggleeventlines")]
internal void ToggleEventLines() internal void ToggleEventLines()
{ {

View file

@ -76,9 +76,12 @@ extern "C"
Backend::Get()->DeleteRenderDevice(device); Backend::Get()->DeleteRenderDevice(device);
} }
const char* BuilderNative_GetError() void BuilderNative_GetError(char *out, int len)
{ {
return GetError(); std::string result = mLastError;
result = result.substr(0, len);
std::copy(result.begin(), result.end(), out);
out[std::min(len - 1, (int)result.size())] = 0;
} }
void RenderDevice_DeclareUniform(RenderDevice* device, UniformName name, const char* variablename, UniformType type) void RenderDevice_DeclareUniform(RenderDevice* device, UniformName name, const char* variablename, UniformType type)
@ -161,19 +164,19 @@ extern "C"
device->SetZWriteEnable(value); device->SetZWriteEnable(value);
} }
void RenderDevice_SetTexture(RenderDevice* device, Texture* texture) void RenderDevice_SetTexture(RenderDevice* device, int unit, Texture* texture)
{ {
device->SetTexture(texture); device->SetTexture(unit, texture);
} }
void RenderDevice_SetSamplerFilter(RenderDevice* device, TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy) void RenderDevice_SetSamplerFilter(RenderDevice* device, int unit, TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy)
{ {
device->SetSamplerFilter(minfilter, magfilter, mipfilter, maxanisotropy); device->SetSamplerFilter(unit, minfilter, magfilter, mipfilter, maxanisotropy);
} }
void RenderDevice_SetSamplerState(RenderDevice* device, TextureAddress address) void RenderDevice_SetSamplerState(RenderDevice* device, int unit, TextureAddress address)
{ {
device->SetSamplerState(address); device->SetSamplerState(unit, address);
} }
bool RenderDevice_Draw(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount) bool RenderDevice_Draw(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount)

View file

@ -83,9 +83,9 @@ public:
virtual void SetMultisampleAntialias(bool value) = 0; virtual void SetMultisampleAntialias(bool value) = 0;
virtual void SetZEnable(bool value) = 0; virtual void SetZEnable(bool value) = 0;
virtual void SetZWriteEnable(bool value) = 0; virtual void SetZWriteEnable(bool value) = 0;
virtual void SetTexture(Texture* texture) = 0; virtual void SetTexture(int unit, Texture* texture) = 0;
virtual void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy) = 0; virtual void SetSamplerFilter(int unit, TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy) = 0;
virtual void SetSamplerState(TextureAddress address) = 0; virtual void SetSamplerState(int unit, TextureAddress address) = 0;
virtual bool Draw(PrimitiveType type, int startIndex, int primitiveCount) = 0; virtual bool Draw(PrimitiveType type, int startIndex, int primitiveCount) = 0;
virtual bool DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) = 0; virtual bool DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) = 0;
virtual bool DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data) = 0; virtual bool DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data) = 0;

View file

@ -113,16 +113,15 @@ GLRenderDevice::~GLRenderDevice()
glDeleteVertexArrays(1, &handle); glDeleteVertexArrays(1, &handle);
} }
for (auto& it : mSamplers) for (auto& it : mTextureUnit)
{
for (GLuint handle : it.second.WrapModes)
{ {
GLuint &handle = it.SamplerHandle;
if (handle != 0) if (handle != 0)
{
glDeleteSamplers(1, &handle); glDeleteSamplers(1, &handle);
} }
} }
mShaderManager->ReleaseResources(); mShaderManager->ReleaseResources();
Context->ClearCurrent(); Context->ClearCurrent();
} }
@ -264,27 +263,46 @@ void GLRenderDevice::SetZWriteEnable(bool value)
} }
} }
void GLRenderDevice::SetTexture(Texture* texture) void GLRenderDevice::SetTexture(int unit, Texture* texture)
{ {
if (mTextureUnit.Tex != texture) if (mTextureUnit[unit].Tex != texture)
{ {
mTextureUnit.Tex = static_cast<GLTexture*>(texture); mTextureUnit[unit].Tex = static_cast<GLTexture*>(texture);
mNeedApply = true; mNeedApply = true;
mTexturesChanged = true; mTexturesChanged = true;
} }
} }
void GLRenderDevice::SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy) void GLRenderDevice::SetSamplerFilter(int unit, TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy)
{ {
SamplerFilterKey key; bool dirty = false;
key.MinFilter = GetGLMinFilter(minfilter, mipfilter);
key.MagFilter = (magfilter == TextureFilter::Nearest) ? GL_NEAREST : GL_LINEAR;
key.MaxAnisotropy = maxanisotropy;
if (mSamplerFilterKey != key)
{
mSamplerFilterKey = key;
mSamplerFilter = &mSamplers[mSamplerFilterKey];
if (mTextureUnit[unit].MinFilter != minfilter)
{
mTextureUnit[unit].MinFilter = minfilter;
dirty = true;
}
if (mTextureUnit[unit].MagFilter != magfilter)
{
mTextureUnit[unit].MagFilter = magfilter;
dirty = true;
}
if (mTextureUnit[unit].MipFilter != mipfilter)
{
mTextureUnit[unit].MipFilter = mipfilter;
dirty = true;
}
if ( mTextureUnit[unit].MaxAnisotropy != maxanisotropy)
{
mTextureUnit[unit].MaxAnisotropy = maxanisotropy;
dirty = true;
}
if (dirty)
{
mNeedApply = true; mNeedApply = true;
mTexturesChanged = true; mTexturesChanged = true;
} }
@ -315,11 +333,20 @@ GLint GLRenderDevice::GetGLMinFilter(TextureFilter filter, MipmapFilter mipfilte
} }
} }
void GLRenderDevice::SetSamplerState(TextureAddress address) GLRenderDevice::SamplerFilterKey GLRenderDevice::GetSamplerFilterKey(TextureFilter filter, MipmapFilter mipFilter, float maxAnisotropy)
{ {
if (mTextureUnit.WrapMode != address) SamplerFilterKey key;
key.MinFilter = GetGLMinFilter(filter, mipFilter);
key.MagFilter = (filter == TextureFilter::Linear) ? GL_LINEAR : GL_NEAREST;
key.MaxAnisotropy = maxAnisotropy;
return key;
}
void GLRenderDevice::SetSamplerState(int unit, TextureAddress address)
{
if (mTextureUnit[unit].WrapMode != address)
{ {
mTextureUnit.WrapMode = address; mTextureUnit[unit].WrapMode = address;
mNeedApply = true; mNeedApply = true;
mTexturesChanged = true; mTexturesChanged = true;
} }
@ -901,42 +928,47 @@ bool GLRenderDevice::ApplyUniforms()
bool GLRenderDevice::ApplyTextures() bool GLRenderDevice::ApplyTextures()
{ {
glActiveTexture(GL_TEXTURE0); bool hasError = false;
if (mTextureUnit.Tex) for (int index = 0; index < 10; index++)
{ {
GLenum target = mTextureUnit.Tex->IsCubeTexture() ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; TextureUnit &unit = mTextureUnit[index];
if (unit.Tex)
{
glActiveTexture(GL_TEXTURE0 + index);
GLenum target = unit.Tex->IsCubeTexture() ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
glBindTexture(target, mTextureUnit.Tex->GetTexture(this)); glBindTexture(target, unit.Tex->GetTexture(this));
SamplerFilterKey key = GetSamplerFilterKey(unit.MagFilter, unit.MipFilter, unit.MaxAnisotropy);
SamplerFilter &filter = mSamplers[key];
GLuint &samplerHandle = filter.WrapModes[(int)unit.WrapMode];
GLuint& samplerHandle = mSamplerFilter->WrapModes[(int)mTextureUnit.WrapMode];
if (samplerHandle == 0) if (samplerHandle == 0)
{ {
static const int wrapMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE }; static const int wrapMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE };
glGenSamplers(1, &samplerHandle); glGenSamplers(1, &samplerHandle);
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, mSamplerFilterKey.MinFilter); glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, key.MinFilter);
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, mSamplerFilterKey.MagFilter); glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, key.MagFilter);
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrapMode[(int)mTextureUnit.WrapMode]); glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrapMode[(int)unit.WrapMode]);
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrapMode[(int)mTextureUnit.WrapMode]); glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrapMode[(int)unit.WrapMode]);
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrapMode[(int)mTextureUnit.WrapMode]); glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrapMode[(int)unit.WrapMode]);
if (mSamplerFilterKey.MaxAnisotropy > 0.0f) if (key.MaxAnisotropy > 0.0f)
glSamplerParameterf(samplerHandle, GL_TEXTURE_MAX_ANISOTROPY_EXT, mSamplerFilterKey.MaxAnisotropy); glSamplerParameterf(samplerHandle, GL_TEXTURE_MAX_ANISOTROPY_EXT, key.MaxAnisotropy);
} }
if (mTextureUnit.SamplerHandle != samplerHandle) if (unit.SamplerHandle != samplerHandle)
{ {
mTextureUnit.SamplerHandle = samplerHandle; unit.SamplerHandle = samplerHandle;
glBindSampler(0, samplerHandle); glBindSampler(index, samplerHandle);
} }
} }
else
{ hasError |= CheckGLError();
glBindTexture(GL_TEXTURE_2D, 0);
} }
mTexturesChanged = false; mTexturesChanged = false;
return hasError;
return CheckGLError();
} }
std::mutex& GLRenderDevice::GetMutex() std::mutex& GLRenderDevice::GetMutex()

View file

@ -54,9 +54,9 @@ public:
void SetMultisampleAntialias(bool value) override; void SetMultisampleAntialias(bool value) override;
void SetZEnable(bool value) override; void SetZEnable(bool value) override;
void SetZWriteEnable(bool value) override; void SetZWriteEnable(bool value) override;
void SetTexture(Texture* texture) override; void SetTexture(int unit, Texture* texture) override;
void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy) override; void SetSamplerFilter(int unit, TextureFilter minfilter, TextureFilter magfilter, MipmapFilter mipfilter, float maxanisotropy) override;
void SetSamplerState(TextureAddress address) override; void SetSamplerState(int unit, TextureAddress address) override;
bool Draw(PrimitiveType type, int startIndex, int primitiveCount) override; bool Draw(PrimitiveType type, int startIndex, int primitiveCount) override;
bool DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) override; bool DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount) override;
bool DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data) override; bool DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data) override;
@ -120,7 +120,11 @@ public:
GLTexture* Tex = nullptr; GLTexture* Tex = nullptr;
TextureAddress WrapMode = TextureAddress::Wrap; TextureAddress WrapMode = TextureAddress::Wrap;
GLuint SamplerHandle = 0; GLuint SamplerHandle = 0;
} mTextureUnit; TextureFilter MinFilter = TextureFilter::Nearest;
TextureFilter MagFilter = TextureFilter::Nearest;
MipmapFilter MipFilter = MipmapFilter::None;
float MaxAnisotropy = 1;
} mTextureUnit[10];
struct SamplerFilterKey struct SamplerFilterKey
{ {
@ -139,8 +143,8 @@ public:
}; };
std::map<SamplerFilterKey, SamplerFilter> mSamplers; std::map<SamplerFilterKey, SamplerFilter> mSamplers;
SamplerFilterKey mSamplerFilterKey;
SamplerFilter* mSamplerFilter = nullptr; SamplerFilterKey GetSamplerFilterKey(TextureFilter filter, MipmapFilter mipFilter, float maxAnisotropy);
int mVertexBuffer = -1; int mVertexBuffer = -1;
int64_t mVertexBufferStartIndex = 0; int64_t mVertexBufferStartIndex = 0;

View file

@ -41,6 +41,8 @@ bool GLShader::CheckCompile(GLRenderDevice* device)
CreateProgram(device); CreateProgram(device);
glUseProgram(mProgram); glUseProgram(mProgram);
glUniform1i(glGetUniformLocation(mProgram, "texture1"), 0); glUniform1i(glGetUniformLocation(mProgram, "texture1"), 0);
glUniform1i(glGetUniformLocation(mProgram, "texture2"), 1);
glUniform1i(glGetUniformLocation(mProgram, "texture3"), 2);
glUseProgram(0); glUseProgram(0);
} }

View file

@ -24,9 +24,11 @@
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#include <cstdint> #include <cstdint>
#include <algorithm>
#include <vector> #include <vector>
#include <map> #include <map>
#include <memory> #include <memory>
#include <string>
#ifdef WIN32 #ifdef WIN32
#include <Windows.h> #include <Windows.h>

View file

@ -1614,6 +1614,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This draws a frame // This draws a frame
public override void OnRedrawDisplay() public override void OnRedrawDisplay()
{ {
renderer.SetClassicLightingColorMap(General.Map.Data.MainColorMap);
// Start drawing // Start drawing
if(renderer.Start()) if(renderer.Start())
{ {