Add support for most new blendmodes.

This commit is contained in:
sphere 2021-06-17 11:05:08 +02:00
parent 131770266a
commit f4a771553b
10 changed files with 169 additions and 21 deletions

View file

@ -39,7 +39,7 @@ namespace CodeImp.DoomBuilder.IO
public SRB2MapSetIO(WAD wad, MapManager manager) : base(wad, manager)
{
translucentLineTypes = new Dictionary<int, float>() {
{ 900, 0.9f },
{ 900, 0.9f }, // translucent
{ 901, 0.8f },
{ 902, 0.7f },
{ 903, 0.6f },
@ -48,6 +48,36 @@ namespace CodeImp.DoomBuilder.IO
{ 906, 0.3f },
{ 907, 0.2f },
{ 908, 0.1f },
{ 910, 1.0f }, // additive
{ 911, 0.9f },
{ 912, 0.8f },
{ 913, 0.7f },
{ 914, 0.6f },
{ 915, 0.5f },
{ 916, 0.4f },
{ 917, 0.3f },
{ 918, 0.2f },
{ 919, 0.1f },
{ 920, 1.0f }, // subtractive
{ 921, 0.9f },
{ 922, 0.8f },
{ 923, 0.7f },
{ 924, 0.6f },
{ 925, 0.5f },
{ 926, 0.4f },
{ 927, 0.3f },
{ 928, 0.2f },
{ 929, 0.1f },
{ 930, 1.0f }, // reverse subtractive
{ 931, 0.9f },
{ 932, 0.8f },
{ 933, 0.7f },
{ 934, 0.6f },
{ 935, 0.5f },
{ 936, 0.4f },
{ 937, 0.3f },
{ 938, 0.2f },
{ 939, 0.1f }
};
startTypes = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };

View file

@ -804,23 +804,47 @@ namespace CodeImp.DoomBuilder.Map
if (noshade) Args[2] += 1;
if (doubleshadow) Args[2] += 2;
if (fog) Args[2] += 4;
Args[3] = render ? (translucent ? ParseTranslucency(Front.HighTexture) : 255) : 0;
if (ParseAdditive(Front.HighTexture)) Args[2] += 64;
if (ParseSubtractive(Front.HighTexture)) Args[2] += 2048; // hack for SRB2, not actually in UDMF
if (ParseReverseSubtractive(Front.HighTexture)) Args[2] += 4096; // hack for SRB2, not actually in UDMF
Args[3] = render ? (translucent ? ParseTranslucency(Front.HighTexture) : 255) : 0;
}
//Read translucency value from texture name (#000-#255)
private int ParseTranslucency(string tex)
{
int result = 128;
if (tex.StartsWith("#") && tex.Length == 4)
if (tex.StartsWith("#"))
{
int alpha;
if (int.TryParse(tex.Substring(1), out alpha) && alpha >= 0 && alpha <= 255) result = alpha;
if (int.TryParse(tex.Substring(1, 3), out alpha) && alpha >= 0 && alpha <= 255) result = alpha;
}
return result;
}
private bool ParseAdditive(string tex)
{
if (tex.StartsWith("#") && tex.Length >= 5)
return int.TryParse(tex.Substring(4, 1), out int value) && value == 1;
else
return false;
}
private bool ParseSubtractive(string tex)
{
if (tex.StartsWith("#") && tex.Length >= 5)
return int.TryParse(tex.Substring(4, 1), out int value) && value == 2;
else
return false;
}
private bool ParseReverseSubtractive(string tex)
{
if (tex.StartsWith("#") && tex.Length >= 5)
return int.TryParse(tex.Substring(4, 1), out int value) && value == 3;
else
return false;
}
//Read color value from texture name (#RRGGBBA)
public void ParseColor(string tex, out int color, out int alpha)
//Read color value from texture name (#RRGGBBA)
public void ParseColor(string tex, out int color, out int alpha)
{
color = 0x000000;
alpha = 255;
@ -902,10 +926,13 @@ namespace CodeImp.DoomBuilder.Map
//Set translucent line arguments for SRB2-style translucent walls. See http://zdoom.org/wiki/TranslucentLine.
public void SetTranslucentLineArgs()
{
Args[0] = 0; //lineid (irrelevant for SRB2)
bool additive = (Action >= 910 && Action <= 919);
bool subtractive = (Action >= 920 && Action <= 929);
bool reversesubtractive = (Action >= 930 && Action <= 939);
Args[0] = 0; //lineid (irrelevant for SRB2)
Args[1] = (int)(General.Map.FormatInterface.TranslucentLineTypes[Action]*255); //amount
Args[2] = 0; //additive
Args[3] = 0; //moreflags (irrelevant for SRB2)
Args[2] = additive ? 1 : (subtractive ? 2 : (reversesubtractive ? 3 : 0)); //additive/subtractive/reversesubtractive
Args[3] = 0; //moreflags (irrelevant for SRB2)
}
// This checks and returns a flag without creating it

View file

@ -25,7 +25,9 @@ namespace CodeImp.DoomBuilder.Rendering
Solid = 0,
Mask = 1,
Alpha = 2,
Additive = 3
}
Additive = 3,
Subtractive = 4,
ReverseSubtractive = 5
}
}

View file

@ -988,10 +988,26 @@ namespace CodeImp.DoomBuilder.Rendering
switch(g.RenderPass)
{
case RenderPass.Additive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.Subtractive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.ReverseSubtractive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Subtract);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.InverseSourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.Alpha:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);
break;
}
@ -1117,10 +1133,26 @@ namespace CodeImp.DoomBuilder.Rendering
switch(t.RenderPass)
{
case RenderPass.Additive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.Subtractive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.ReverseSubtractive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Subtract);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.InverseSourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.Alpha:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);
break;
}
@ -1231,6 +1263,10 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Device.SetRenderState(RenderState.CullMode, Cull.Counterclockwise); //mxd
}
// Reset source blend blending operation
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
// Done rendering with this shader
graphics.Shaders.World3D.EndPass();
}
@ -1479,10 +1515,26 @@ namespace CodeImp.DoomBuilder.Rendering
switch(t.RenderPass)
{
case RenderPass.Additive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.Subtractive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.ReverseSubtractive:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Subtract);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.InverseSourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.One);
break;
case RenderPass.Alpha:
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);
break;
}
@ -1554,6 +1606,10 @@ namespace CodeImp.DoomBuilder.Rendering
}
}
// Reset source blend and blending operation
graphics.Device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
graphics.Shaders.World3D.EndPass();
}
@ -1692,7 +1748,9 @@ namespace CodeImp.DoomBuilder.Rendering
break;
case RenderPass.Additive:
case RenderPass.Alpha:
case RenderPass.Subtractive:
case RenderPass.ReverseSubtractive:
case RenderPass.Alpha:
translucentgeo.Add(g);
break;
@ -1734,6 +1792,8 @@ namespace CodeImp.DoomBuilder.Rendering
break;
case RenderPass.Additive:
case RenderPass.Subtractive:
case RenderPass.ReverseSubtractive:
case RenderPass.Alpha:
translucentmodelthings.Add(t);
break;
@ -1759,6 +1819,8 @@ namespace CodeImp.DoomBuilder.Rendering
break;
case RenderPass.Additive:
case RenderPass.Subtractive:
case RenderPass.ReverseSubtractive:
case RenderPass.Alpha:
translucentthings.Add(t);
break;

View file

@ -132,11 +132,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
if (!General.Map.FormatInterface.HasLinedefParameters) Sidedef.Line.SetTranslucentLineArgs();
alpha = (byte)General.Clamp(Sidedef.Line.Args[1], 0, 255);
if(canhavealpha && Sidedef.Line.Args[2] == 1)
if (canhavealpha && Sidedef.Line.Args[2] == 1)
this.RenderPass = RenderPass.Additive;
else if(canhavealpha && (alpha < 255 || Texture.IsTranslucent))
else if (canhavealpha && Sidedef.Line.Args[2] == 2)
this.RenderPass = RenderPass.Subtractive;
else if (canhavealpha && Sidedef.Line.Args[2] == 3)
this.RenderPass = RenderPass.ReverseSubtractive;
else if (canhavealpha && (alpha < 255 || Texture.IsTranslucent))
this.RenderPass = RenderPass.Alpha;
else if(solidasmask)
else if (solidasmask)
this.RenderPass = RenderPass.Mask;
else
this.RenderPass = RenderPass.Solid;

View file

@ -33,6 +33,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Render using Additive pass?
private bool renderadditive;
private bool rendersubtractive;
private bool renderreversesubtractive;
//mxd. Sidedef should be clipped by floor/ceiling?
private bool clipsides;
@ -48,6 +50,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
public bool VavoomType { get { return vavoomtype; } }
public bool RenderInside { get { return renderinside; } } //mxd
public bool RenderAdditive { get { return renderadditive; } } //mxd
public bool RenderSubtractive { get { return rendersubtractive; } }
public bool RenderReverseSubtractive { get { return renderreversesubtractive; } }
public bool IgnoreBottomHeight { get { return ignorebottomheight; } } //mxd
public bool Sloped3dFloor { get { return sloped3dfloor; } } //mxd
public bool ClipSidedefs { get { return clipsides; } } //mxd
@ -65,7 +69,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
IgnoreBottomHeight = 8,
UseUpperTexture = 16,
UseLowerTexture = 32,
RenderAdditive = 64
RenderAdditive = 64,
// Fake flags for SRB2
RenderSubtractive = 2048,
RenderReverseSubtractive = 4096
}
//mxd. 3D-Floor Types
@ -80,7 +87,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
HiTagIsLineID = 8,
InvertVisibilityRules = 16,
InvertShootabilityRules = 32,
//Fake flags added for SRB2
//Fake flags for SRB2
DontRenderPlanes = 64,
DontRenderSides = 128
}
@ -122,6 +129,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
//mxd. check for Swimmable/RenderInside/RenderAdditive flags
renderadditive = (linedef.Args[2] & (int)Flags.RenderAdditive) == (int)Flags.RenderAdditive;
rendersubtractive = (linedef.Args[2] & (int)Flags.RenderSubtractive) == (int)Flags.RenderSubtractive;
renderreversesubtractive = (linedef.Args[2] & (int)Flags.RenderReverseSubtractive) == (int)Flags.RenderReverseSubtractive;
renderinside = ((((linedef.Args[1] & (int)FloorTypes.Swimmable) == (int)FloorTypes.Swimmable) && (linedef.Args[1] & (int)FloorTypes.NonSolid) != (int)FloorTypes.NonSolid))
|| ((linedef.Args[1] & (int)FloorTypes.RenderInside) == (int)FloorTypes.RenderInside);
ignorebottomheight = ((linedef.Args[2] & (int)Flags.IgnoreBottomHeight) == (int)Flags.IgnoreBottomHeight);
@ -136,7 +145,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
ceiling.plane = (ignorebottomheight ? sd.Ceiling.plane : sd.Floor.plane.GetInverted()); //mxd. Use upper plane when "ignorebottomheight" flag is set
//mxd
clipsides = (!renderinside && !renderadditive && alpha > 254 && !ignorebottomheight);
clipsides = (!renderinside && !renderadditive && !rendersubtractive && !renderreversesubtractive && alpha > 254 && !ignorebottomheight);
// A 3D floor's color is always that of the sector it is placed in
// (unless it's affected by glow) - mxd
@ -146,6 +155,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
vavoomtype = true;
renderadditive = false; //mxd
rendersubtractive = false;
renderreversesubtractive = false;
clipsides = true; //mxd
floor.type = SectorLevelType.Ceiling;
floor.plane = sd.Ceiling.plane;
@ -170,7 +181,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Check slopes, cause GZDoom can't handle sloped translucent 3d floors...
//MascaraSnake: SRB2 can, so only check in Doom
sloped3dfloor = (!General.Map.FormatInterface.HasTranslucent3DFloors && (alpha < 255 || renderadditive) &&
sloped3dfloor = (!General.Map.FormatInterface.HasTranslucent3DFloors && (alpha < 255 || renderadditive || rendersubtractive || renderreversesubtractive) &&
(Angle2D.RadToDeg(ceiling.plane.Normal.GetAngleZ()) != 270 ||
Angle2D.RadToDeg(floor.plane.Normal.GetAngleZ()) != 90));

View file

@ -173,6 +173,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.RenderPass = RenderPass.Mask;
else if(extrafloor.RenderAdditive) //mxd
this.RenderPass = RenderPass.Additive;
else if (extrafloor.RenderSubtractive)
this.RenderPass = RenderPass.Subtractive;
else if (extrafloor.RenderReverseSubtractive)
this.RenderPass = RenderPass.ReverseSubtractive;
else if(level.alpha < 255)
this.RenderPass = RenderPass.Alpha;
else

View file

@ -174,6 +174,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.RenderPass = RenderPass.Mask;
else if(extrafloor.RenderAdditive) //mxd
this.RenderPass = RenderPass.Additive;
else if (extrafloor.RenderSubtractive)
this.RenderPass = RenderPass.Subtractive;
else if (extrafloor.RenderReverseSubtractive)
this.RenderPass = RenderPass.ReverseSubtractive;
else if(level.alpha < 255)
this.RenderPass = RenderPass.Alpha;
else

View file

@ -230,13 +230,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon> { poly };
bool translucent = (extrafloor.RenderAdditive || extrafloor.Alpha < 255);
bool translucent = (extrafloor.RenderAdditive || extrafloor.RenderSubtractive || extrafloor.RenderReverseSubtractive || extrafloor.Alpha < 255);
foreach(Effect3DFloor ef in sd.ExtraFloors)
{
//mxd. Our poly should be clipped when our ond other extrafloors are both solid or both translucent,
// or when only our extrafloor is translucent.
// Our poly should not be clipped when our extrafloor is translucent and the other one isn't and both have renderinside setting.
bool othertranslucent = (ef.RenderAdditive || ef.Alpha < 255);
bool othertranslucent = (ef.RenderAdditive || ef.RenderSubtractive || extrafloor.RenderReverseSubtractive || ef.Alpha < 255);
if(translucent && !othertranslucent && !ef.ClipSidedefs) continue;
if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs)
{
@ -279,6 +279,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if (extrafloor.Sloped3dFloor) this.RenderPass = RenderPass.Mask; //mxd
else if(extrafloor.RenderAdditive) this.RenderPass = RenderPass.Additive; //mxd
else if (extrafloor.RenderSubtractive) this.RenderPass = RenderPass.Subtractive;
else if (extrafloor.RenderReverseSubtractive) this.RenderPass = RenderPass.ReverseSubtractive;
else if(extrafloor.Alpha < 255 || extrafloor.DontRenderSides) this.RenderPass = RenderPass.Alpha;
else this.RenderPass = RenderPass.Mask;

View file

@ -262,6 +262,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if (extrafloor.Sloped3dFloor) this.RenderPass = RenderPass.Mask; //mxd
else if(extrafloor.RenderAdditive) this.RenderPass = RenderPass.Additive; //mxd
else if (extrafloor.RenderSubtractive) this.RenderPass = RenderPass.Subtractive;
else if (extrafloor.RenderReverseSubtractive) this.RenderPass = RenderPass.ReverseSubtractive;
else if(extrafloor.Alpha < 255 || extrafloor.DontRenderSides) this.RenderPass = RenderPass.Alpha;
else this.RenderPass = RenderPass.Mask;