Rewrote dynamic light support. Resolves #319. Resolves #318. Resolves #233.

This commit is contained in:
ZZYZX 2020-01-03 03:22:33 +02:00
parent 54fb563a9a
commit 044dbbcfd0
22 changed files with 811 additions and 673 deletions

View file

@ -3399,16 +3399,16 @@ namespace CodeImp.DoomBuilder.Data
General.Map.Graphics.SetSamplerState(TextureAddress.Clamp); General.Map.Graphics.SetSamplerState(TextureAddress.Clamp);
// Setup matrices // 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 mworld = Matrix.Translation(offset) * Matrix.Scaling(1.0f, 1.0f, yscale);
Matrix mprojection = Matrix.PerspectiveFov(Angle2D.PIHALF, 1.0f, 0.5f, 100.0f); Matrix mprojection = Matrix.PerspectiveFov(Angle2D.PIHALF, 1.0f, 0.5f, 100.0f);
// Place camera at origin // Place camera at origin
General.Map.Graphics.SetUniform(UniformName.campos, new Vector4()); General.Map.Graphics.SetUniform(UniformName.campos, new Vector4f());
// Begin fullbright shaderpass // Begin fullbright shaderpass
General.Map.Graphics.SetShader(ShaderName.world3d_fullbright); 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 // Render to the six faces of the cube map
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
@ -3643,45 +3643,45 @@ namespace CodeImp.DoomBuilder.Data
private static Matrix GetCubeMapViewMatrix(CubeMapFace face) private static Matrix GetCubeMapViewMatrix(CubeMapFace face)
{ {
Vector3 lookdir, updir; Vector3f lookdir, updir;
switch(face) switch(face)
{ {
case CubeMapFace.PositiveX: case CubeMapFace.PositiveX:
lookdir = new Vector3(-1.0f, 0.0f, 0.0f); lookdir = new Vector3f(-1.0f, 0.0f, 0.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f); updir = new Vector3f(0.0f, 1.0f, 0.0f);
break; break;
case CubeMapFace.NegativeX: case CubeMapFace.NegativeX:
lookdir = new Vector3(1.0f, 0.0f, 0.0f); lookdir = new Vector3f(1.0f, 0.0f, 0.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f); updir = new Vector3f(0.0f, 1.0f, 0.0f);
break; break;
case CubeMapFace.PositiveY: case CubeMapFace.PositiveY:
lookdir = new Vector3(0.0f, -1.0f, 0.0f); lookdir = new Vector3f(0.0f, -1.0f, 0.0f);
updir = new Vector3(0.0f, 0.0f, 1.0f); updir = new Vector3f(0.0f, 0.0f, 1.0f);
break; break;
case CubeMapFace.NegativeY: case CubeMapFace.NegativeY:
lookdir = new Vector3(0.0f, 1.0f, 0.0f); lookdir = new Vector3f(0.0f, 1.0f, 0.0f);
updir = new Vector3(0.0f, 0.0f, -1.0f); updir = new Vector3f(0.0f, 0.0f, -1.0f);
break; break;
case CubeMapFace.PositiveZ: case CubeMapFace.PositiveZ:
lookdir = new Vector3(0.0f, 0.0f, 1.0f); lookdir = new Vector3f(0.0f, 0.0f, 1.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f); updir = new Vector3f(0.0f, 1.0f, 0.0f);
break; break;
case CubeMapFace.NegativeZ: case CubeMapFace.NegativeZ:
lookdir = new Vector3(0.0f, 0.0f, -1.0f); lookdir = new Vector3f(0.0f, 0.0f, -1.0f);
updir = new Vector3(0.0f, 1.0f, 0.0f); updir = new Vector3f(0.0f, 1.0f, 0.0f);
break; break;
default: default:
throw new Exception("Unknown CubeMapFace!"); throw new Exception("Unknown CubeMapFace!");
} }
Vector3 eye = new Vector3(); Vector3f eye = new Vector3f();
return Matrix.LookAt(eye, lookdir, updir); return Matrix.LookAt(eye, lookdir, updir);
} }

View file

@ -9,14 +9,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
public int PrimaryRadius; public int PrimaryRadius;
public int SecondaryRadius; public int SecondaryRadius;
public int Interval; public int Interval;
public Vector3 Offset; public Vector3f Offset;
public bool DontLightSelf; public bool DontLightSelf;
public DynamicLightData(GZGeneral.LightData type) public DynamicLightData(GZGeneral.LightData type)
{ {
Type = type; Type = type;
Color = new Color3(); Color = new Color3();
Offset = new Vector3(); Offset = new Vector3f();
} }
} }
} }

View file

@ -21,7 +21,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
#region ================== Variables #region ================== Variables
private ModelLoadState loadstate; private ModelLoadState loadstate;
private Vector3 scale; private Vector3f scale;
private Matrix transform; private Matrix transform;
private Matrix transformrotation; private Matrix transformrotation;
private Matrix transformstretched; private Matrix transformstretched;
@ -39,7 +39,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
internal GZModel Model; 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 Transform { get { /* return (General.Settings.GZStretchView ? transformstretched : transform); */ return transformstretched; } }
internal Matrix TransformRotation { get { return transformrotation; } } internal Matrix TransformRotation { get { return transformrotation; } }
internal bool OverridePalette; // Used for voxel models only 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; this.scale = scale;
transformrotation = rotation * Matrix.Scaling(scale); transformrotation = rotation * Matrix.Scaling(scale);

View file

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using CodeImp.DoomBuilder.Rendering; using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.GZBuilder.Data;
namespace CodeImp.DoomBuilder.GZBuilder.MD3 namespace CodeImp.DoomBuilder.GZBuilder.MD3
{ {
@ -8,8 +9,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
internal readonly List<Mesh> Meshes; internal readonly List<Mesh> Meshes;
internal readonly List<Texture> Textures; internal readonly List<Texture> Textures;
internal float Radius; internal float Radius;
internal BoundingBoxSizes BBox;
internal GZModel() internal GZModel()
{ {
Meshes = new List<Mesh>(); Meshes = new List<Mesh>();
Textures = new List<Texture>(); Textures = new List<Texture>();

View file

@ -238,9 +238,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
bbs.MinX = (int)(bbs.MinX * mde.Scale.X); bbs.MinX = (int)(bbs.MinX * mde.Scale.X);
bbs.MaxY = (int)(bbs.MaxY * mde.Scale.Y); bbs.MaxY = (int)(bbs.MaxY * mde.Scale.Y);
bbs.MinY = (int)(bbs.MinY * 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 //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.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<DataReader> containers, string texturename) private static Texture GetTexture(List<DataReader> containers, string texturename)
@ -853,7 +856,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
List<int> polyIndecesList = new List<int>(); List<int> polyIndecesList = new List<int>();
List<int> uvIndecesList = new List<int>(); List<int> uvIndecesList = new List<int>();
List<Vector2> uvCoordsList = new List<Vector2>(); List<Vector2f> uvCoordsList = new List<Vector2f>();
List<WorldVertex> vertList = new List<WorldVertex>(); List<WorldVertex> vertList = new List<WorldVertex>();
// Polygons // Polygons
@ -874,7 +877,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
s.Position = ofs_uv + start; s.Position = ofs_uv + start;
for(int i = 0; i < num_uv; i++) 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 // Frames
// Find correct frame // Find correct frame
@ -910,8 +913,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
s.Position = ofs_animFrame + start + frame * framesize; s.Position = ofs_animFrame + start + frame * framesize;
} }
Vector3 scale = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Vector3f scale = new Vector3f(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
Vector3 translate = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); Vector3f translate = new Vector3f(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
s.Position += 16; // Skip frame name s.Position += 16; // Skip frame name

View file

@ -2471,7 +2471,7 @@ namespace CodeImp.DoomBuilder.Geometry
/// </summary> /// </summary>
public static Vector2D HermiteSpline(Vector2D p1, Vector2D t1, Vector2D p2, Vector2D t2, float u) 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));
} }
/// <summary> /// <summary>
@ -2480,7 +2480,7 @@ namespace CodeImp.DoomBuilder.Geometry
/// </summary> /// </summary>
public static Vector3D HermiteSpline(Vector3D p1, Vector3D t1, Vector3D p2, Vector3D t2, float u) 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 //mxd

View file

@ -15,7 +15,7 @@ namespace CodeImp.DoomBuilder.Rendering
Blue = b; Blue = b;
} }
public Color3(Vector3 c) public Color3(Vector3f c)
{ {
Red = c.X; Red = c.X;
Green = c.Y; Green = c.Y;

View file

@ -25,7 +25,7 @@ namespace CodeImp.DoomBuilder.Rendering
Alpha = a; Alpha = a;
} }
public Color4(Vector4 c) public Color4(Vector4f c)
{ {
Red = c.X; Red = c.X;
Green = c.Y; Green = c.Y;
@ -60,6 +60,11 @@ namespace CodeImp.DoomBuilder.Rendering
return System.Drawing.Color.FromArgb(ToArgb()); return System.Drawing.Color.FromArgb(ToArgb());
} }
public Vector4f ToVector()
{
return new Vector4f(Red, Green, Blue, Alpha);
}
public override bool Equals(object o) public override bool Equals(object o)
{ {
if (o is Color4) if (o is Color4)

View file

@ -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 result = new Matrix();
Matrix_Translation(v.X, v.Y, v.Z, out result); Matrix_Translation(v.X, v.Y, v.Z, out result);
@ -229,7 +229,7 @@ namespace CodeImp.DoomBuilder.Rendering
return result; return result;
} }
public static Matrix Scaling(Vector3 v) public static Matrix Scaling(Vector3f v)
{ {
Matrix result = new Matrix(); Matrix result = new Matrix();
Matrix_Scaling(v.X, v.Y, v.Z, out result); Matrix_Scaling(v.X, v.Y, v.Z, out result);
@ -276,11 +276,11 @@ namespace CodeImp.DoomBuilder.Rendering
#endif #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); Vector3f zaxis = Vector3f.Normalize(target - eye);
Vector3 xaxis = Vector3.Normalize(Vector3.Cross(up, zaxis)); Vector3f xaxis = Vector3f.Normalize(Vector3f.Cross(up, zaxis));
Vector3 yaxis = Vector3.Cross(zaxis, xaxis); Vector3f yaxis = Vector3f.Cross(zaxis, xaxis);
Matrix result = Null; Matrix result = Null;
result.M11 = -xaxis.X; result.M11 = -xaxis.X;

View file

@ -46,26 +46,27 @@ namespace CodeImp.DoomBuilder.Rendering
CreateDevice(); CreateDevice();
DeclareUniform(UniformName.rendersettings, "rendersettings", UniformType.Vec4); DeclareUniform(UniformName.rendersettings, "rendersettings", UniformType.Vec4f);
DeclareUniform(UniformName.projection, "projection", UniformType.Mat4); DeclareUniform(UniformName.projection, "projection", UniformType.Mat4);
DeclareUniform(UniformName.desaturation, "desaturation", UniformType.Float); 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.view, "view", UniformType.Mat4);
DeclareUniform(UniformName.world, "world", UniformType.Mat4); DeclareUniform(UniformName.world, "world", UniformType.Mat4);
DeclareUniform(UniformName.modelnormal, "modelnormal", UniformType.Mat4); DeclareUniform(UniformName.modelnormal, "modelnormal", UniformType.Mat4);
DeclareUniform(UniformName.FillColor, "fillColor", UniformType.Vec4); DeclareUniform(UniformName.FillColor, "fillColor", UniformType.Vec4f);
DeclareUniform(UniformName.vertexColor, "vertexColor", UniformType.Vec4); DeclareUniform(UniformName.vertexColor, "vertexColor", UniformType.Vec4f);
DeclareUniform(UniformName.stencilColor, "stencilColor", UniformType.Vec4); DeclareUniform(UniformName.stencilColor, "stencilColor", UniformType.Vec4f);
DeclareUniform(UniformName.lightPosAndRadius, "lightPosAndRadius", UniformType.Vec4); DeclareUniform(UniformName.lightPosAndRadius, "lightPosAndRadius", UniformType.Vec4fArray);
DeclareUniform(UniformName.lightOrientation, "lightOrientation", UniformType.Vec3); DeclareUniform(UniformName.lightOrientation, "lightOrientation", UniformType.Vec4fArray);
DeclareUniform(UniformName.light2Radius, "light2Radius", UniformType.Vec2); DeclareUniform(UniformName.light2Radius, "light2Radius", UniformType.Vec2fArray);
DeclareUniform(UniformName.lightColor, "lightColor", UniformType.Vec4); DeclareUniform(UniformName.lightColor, "lightColor", UniformType.Vec4fArray);
DeclareUniform(UniformName.ignoreNormals, "ignoreNormals", UniformType.Float);
DeclareUniform(UniformName.spotLight, "spotLight", UniformType.Float); DeclareUniform(UniformName.spotLight, "spotLight", UniformType.Float);
DeclareUniform(UniformName.campos, "campos", UniformType.Vec4); DeclareUniform(UniformName.campos, "campos", UniformType.Vec4f);
DeclareUniform(UniformName.texturefactor, "texturefactor", UniformType.Vec4); DeclareUniform(UniformName.texturefactor, "texturefactor", UniformType.Vec4f);
DeclareUniform(UniformName.fogsettings, "fogsettings", UniformType.Vec4); DeclareUniform(UniformName.fogsettings, "fogsettings", UniformType.Vec4f);
DeclareUniform(UniformName.fogcolor, "fogcolor", UniformType.Vec4); DeclareUniform(UniformName.fogcolor, "fogcolor", UniformType.Vec4f);
DeclareUniform(UniformName.sectorfogcolor, "sectorfogcolor", UniformType.Vec4f);
DeclareUniform(UniformName.lightsEnabled, "lightsEnabled", UniformType.Float);
// 2d fsaa // 2d fsaa
CompileShader(ShaderName.display2d_fsaa, "display2d.shader", "display2d_fsaa"); CompileShader(ShaderName.display2d_fsaa, "display2d.shader", "display2d_fsaa");
@ -97,9 +98,6 @@ namespace CodeImp.DoomBuilder.Rendering
CompileShader(ShaderName.world3d_main_fog_vertexcolor, "world3d.shader", "world3d_main_fog_vertexcolor"); 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"); CompileShader(ShaderName.world3d_main_highlight_fog_vertexcolor, "world3d.shader", "world3d_main_highlight_fog_vertexcolor");
// pure light shader
CompileShader(ShaderName.world3d_lightpass, "world3d.shader", "world3d_lightpass");
SetupSettings(); SetupSettings();
} }
@ -203,17 +201,17 @@ namespace CodeImp.DoomBuilder.Rendering
RenderDevice_SetUniform(Handle, uniform, new float[] { value }, 1, sizeof(float)); 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 }, 1, sizeof(float) * 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 }, 1, sizeof(float) * 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 }, 1, sizeof(float) * 4); RenderDevice_SetUniform(Handle, uniform, new float[] { value.X, value.Y, value.Z, value.W }, 1, sizeof(float) * 4);
} }
@ -233,6 +231,68 @@ namespace CodeImp.DoomBuilder.Rendering
RenderDevice_SetUniform(Handle, uniform, ref matrix, 1, sizeof(float) * 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) public void SetVertexBuffer(VertexBuffer buffer)
{ {
RenderDevice_SetVertexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero); RenderDevice_SetVertexBuffer(Handle, buffer != null ? buffer.Handle : IntPtr.Zero);
@ -503,6 +563,9 @@ namespace CodeImp.DoomBuilder.Rendering
[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);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, int[] data, int count, int bytesize);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)] [DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count, int bytesize); static extern void RenderDevice_SetUniform(IntPtr handle, UniformName name, float[] data, int count, int bytesize);
@ -617,25 +680,25 @@ namespace CodeImp.DoomBuilder.Rendering
internal RenderTargetControl RenderTarget { get; private set; } internal RenderTargetControl RenderTarget { get; private set; }
// This makes a Vector3 from Vector3D // 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 // 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); return new Vector3D(v3.X, v3.Y, v3.Z);
} }
// This makes a Vector2 from Vector2D // 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 // 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); return new Vector2D(v2.X, v2.Y);
} }
@ -665,17 +728,23 @@ namespace CodeImp.DoomBuilder.Rendering
world3d_p13, world3d_p13,
world3d_main_highlight_fog_vertexcolor, world3d_main_highlight_fog_vertexcolor,
world3d_vertex_color, world3d_vertex_color,
world3d_constant_color, world3d_constant_color
world3d_lightpass
} }
public enum UniformType : int public enum UniformType : int
{ {
Vec4, Vec4f,
Vec3, Vec3f,
Vec2, Vec2f,
Float, Float,
Mat4 Mat4,
Vec4i,
Vec3i,
Vec2i,
Int,
Vec4fArray,
Vec3fArray,
Vec2fArray
} }
public enum UniformName : int public enum UniformName : int
@ -694,12 +763,13 @@ namespace CodeImp.DoomBuilder.Rendering
lightOrientation, lightOrientation,
light2Radius, light2Radius,
lightColor, lightColor,
ignoreNormals,
spotLight, spotLight,
campos, campos,
texturefactor, texturefactor,
fogsettings, fogsettings,
fogcolor fogcolor,
sectorfogcolor,
lightsEnabled
} }
public enum VertexFormat : int { Flat, World } public enum VertexFormat : int { Flat, World }

View file

@ -487,7 +487,7 @@ namespace CodeImp.DoomBuilder.Rendering
private void SetDisplay2DSettings(float texelx, float texely, float fsaafactor, float alpha, bool bilinear, bool flipY = false) 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); graphics.SetUniform(UniformName.rendersettings, values);
if (flipY) if (flipY)
graphics.SetUniform(UniformName.projection, worldmatrix * viewmatrix * Matrix.Scaling(1f, -1f, 1f)); graphics.SetUniform(UniformName.projection, worldmatrix * viewmatrix * Matrix.Scaling(1f, -1f, 1f));
@ -498,7 +498,7 @@ namespace CodeImp.DoomBuilder.Rendering
private void SetThings2DSettings(float alpha) 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.rendersettings, values);
graphics.SetUniform(UniformName.projection, worldmatrix * viewmatrix); graphics.SetUniform(UniformName.projection, worldmatrix * viewmatrix);
} }

View file

@ -37,6 +37,7 @@ namespace CodeImp.DoomBuilder.Rendering
private const float PROJ_NEAR_PLANE = 1f; private const float PROJ_NEAR_PLANE = 1f;
private const float FOG_RANGE = 0.9f; private const float FOG_RANGE = 0.9f;
private const int MAX_DYNLIGHTS_PER_SURFACE = 64;
#endregion #endregion
@ -271,7 +272,7 @@ namespace CodeImp.DoomBuilder.Rendering
General.Settings.ViewDistance, Angle2D.DegToRad(General.Settings.VisualFOV)); General.Settings.ViewDistance, Angle2D.DegToRad(General.Settings.VisualFOV));
// Make the view matrix // 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 // Make the billboard matrix
billboard = Matrix.RotationZ(anglexy + Angle2D.PI); billboard = Matrix.RotationZ(anglexy + Angle2D.PI);
@ -306,7 +307,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetAlphaTestEnable(false); graphics.SetAlphaTestEnable(false);
graphics.SetSourceBlend(Blend.SourceAlpha); graphics.SetSourceBlend(Blend.SourceAlpha);
graphics.SetDestinationBlend(Blend.InverseSourceAlpha); 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.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
@ -393,14 +394,14 @@ namespace CodeImp.DoomBuilder.Rendering
// SOLID PASS // SOLID PASS
world = Matrix.Identity; world = Matrix.Identity;
graphics.SetUniform(UniformName.world, ref world); graphics.SetUniform(UniformName.world, ref world);
RenderSinglePass(solidgeo, solidthings); RenderSinglePass(solidgeo, solidthings, lightthings);
//mxd. Render models, without backface culling //mxd. Render models, without backface culling
if(maskedmodelthings.Count > 0) if(maskedmodelthings.Count > 0)
{ {
graphics.SetAlphaTestEnable(true); graphics.SetAlphaTestEnable(true);
graphics.SetCullMode(Cull.None); graphics.SetCullMode(Cull.None);
RenderModels(false, false); RenderModels(false, lightthings);
graphics.SetCullMode(Cull.Clockwise); graphics.SetCullMode(Cull.Clockwise);
} }
@ -410,33 +411,9 @@ namespace CodeImp.DoomBuilder.Rendering
world = Matrix.Identity; world = Matrix.Identity;
graphics.SetUniform(UniformName.world, ref world); graphics.SetUniform(UniformName.world, ref world);
graphics.SetAlphaTestEnable(true); 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 // ALPHA AND ADDITIVE PASS
if(translucentgeo.Count > 0 || translucentthings.Count > 0) if(translucentgeo.Count > 0 || translucentthings.Count > 0)
{ {
@ -446,21 +423,9 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetAlphaTestEnable(false); graphics.SetAlphaTestEnable(false);
graphics.SetZWriteEnable(false); graphics.SetZWriteEnable(false);
graphics.SetSourceBlend(Blend.SourceAlpha); 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 //mxd. Render translucent models, with backface culling
if(translucentmodelthings.Count > 0) if(translucentmodelthings.Count > 0)
{ {
@ -468,16 +433,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetAlphaTestEnable(false); graphics.SetAlphaTestEnable(false);
graphics.SetZWriteEnable(false); graphics.SetZWriteEnable(false);
graphics.SetSourceBlend(Blend.SourceAlpha); graphics.SetSourceBlend(Blend.SourceAlpha);
RenderModels(false, true); RenderModels(true, lightthings);
}
// [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);
} }
// THING CAGES // THING CAGES
@ -739,17 +695,27 @@ namespace CodeImp.DoomBuilder.Rendering
} }
// This performs a single render pass // This performs a single render pass
private void RenderSinglePass(Dictionary<ImageData, List<VisualGeometry>> geopass, Dictionary<ImageData, List<VisualThing>> thingspass) private void RenderSinglePass(Dictionary<ImageData, List<VisualGeometry>> geopass, Dictionary<ImageData, List<VisualThing>> thingspass, List<VisualThing> lights)
{ {
ImageData curtexture; ImageData curtexture;
ShaderName currentshaderpass = shaderpass; ShaderName currentshaderpass = shaderpass;
ShaderName highshaderpass = (ShaderName)(shaderpass + 2); ShaderName highshaderpass = (ShaderName)(shaderpass + 2);
// Begin rendering with this shader // Begin rendering with this shader
graphics.SetShader(shaderpass); graphics.SetShader(shaderpass);
// Render the geometry collected // Light data arrays
foreach(KeyValuePair<ImageData, List<VisualGeometry>> group in geopass) 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);
bool hadlights = false;
// Render the geometry collected
foreach (KeyValuePair<ImageData, List<VisualGeometry>> group in geopass)
{ {
// What texture to use? // What texture to use?
if(group.Key is UnknownImage) if(group.Key is UnknownImage)
@ -770,6 +736,54 @@ namespace CodeImp.DoomBuilder.Rendering
foreach(VisualGeometry g in group.Value) 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? // Changing sector?
if(!object.ReferenceEquals(g.Sector, sector)) if(!object.ReferenceEquals(g.Sector, sector))
{ {
@ -818,8 +832,8 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd. Set variables for fog rendering? //mxd. Set variables for fog rendering?
if(wantedshaderpass > ShaderName.world3d_p7) if(wantedshaderpass > ShaderName.world3d_p7)
{ {
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));
graphics.SetUniform(UniformName.lightColor, sector.Sector.FogColor); graphics.SetUniform(UniformName.sectorfogcolor, sector.Sector.FogColor);
} }
// Set the colors to use // Set the colors to use
@ -834,8 +848,10 @@ namespace CodeImp.DoomBuilder.Rendering
} }
} }
// Get things for this pass graphics.SetUniform(UniformName.lightsEnabled, false);
if(thingspass.Count > 0)
// Get things for this pass
if (thingspass.Count > 0)
{ {
// Texture addressing // Texture addressing
graphics.SetSamplerState(TextureAddress.Clamp); graphics.SetSamplerState(TextureAddress.Clamp);
@ -912,11 +928,11 @@ namespace CodeImp.DoomBuilder.Rendering
if(wantedshaderpass > ShaderName.world3d_p7) if(wantedshaderpass > ShaderName.world3d_p7)
{ {
graphics.SetUniform(UniformName.modelnormal, Matrix.Identity); 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 // 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.vertexColor, vertexcolor);
graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection))); graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection)));
@ -950,7 +966,7 @@ namespace CodeImp.DoomBuilder.Rendering
} }
//mxd //mxd
private void RenderTranslucentPass(List<VisualGeometry> geopass, List<VisualThing> thingspass) private void RenderTranslucentPass(List<VisualGeometry> geopass, List<VisualThing> thingspass, List<VisualThing> lights)
{ {
ShaderName currentshaderpass = shaderpass; ShaderName currentshaderpass = shaderpass;
ShaderName highshaderpass = (ShaderName)(shaderpass + 2); ShaderName highshaderpass = (ShaderName)(shaderpass + 2);
@ -958,12 +974,6 @@ namespace CodeImp.DoomBuilder.Rendering
// Sort geometry by camera distance. First vertex of the BoundingBox is it's center // Sort geometry by camera distance. First vertex of the BoundingBox is it's center
geopass.Sort(delegate(VisualGeometry vg1, VisualGeometry vg2) 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) if (vg1 == vg2)
return 0; return 0;
@ -987,6 +997,7 @@ namespace CodeImp.DoomBuilder.Rendering
} }
return (int)(dist2 - dist1); return (int)(dist2 - dist1);
}); });
ImageData curtexture; ImageData curtexture;
@ -998,11 +1009,70 @@ namespace CodeImp.DoomBuilder.Rendering
// Begin rendering with this shader // Begin rendering with this shader
graphics.SetShader(shaderpass); 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);
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) switch(g.RenderPass)
{ {
@ -1081,7 +1151,7 @@ namespace CodeImp.DoomBuilder.Rendering
// Set variables for fog rendering? // Set variables for fog rendering?
if (wantedshaderpass > ShaderName.world3d_p7 && g.FogFactor != fogfactor) 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; fogfactor = g.FogFactor;
} }
@ -1089,7 +1159,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetUniform(UniformName.desaturation, sector.Sector.Desaturation); graphics.SetUniform(UniformName.desaturation, sector.Sector.Desaturation);
// Set the colors to use // 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))); graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((g == highlighted) && showhighlight, (g.Selected && showselection)));
// Render! // Render!
@ -1098,8 +1168,10 @@ namespace CodeImp.DoomBuilder.Rendering
else graphics.SetUniform(UniformName.desaturation, 0.0f); else graphics.SetUniform(UniformName.desaturation, 0.0f);
} }
// Get things for this pass graphics.SetUniform(UniformName.lightsEnabled, false);
if(thingspass.Count > 0)
// Get things for this pass
if (thingspass.Count > 0)
{ {
// Texture addressing // Texture addressing
graphics.SetSamplerState(TextureAddress.Clamp); graphics.SetSamplerState(TextureAddress.Clamp);
@ -1210,13 +1282,13 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetUniform(UniformName.modelnormal, Matrix.Identity); graphics.SetUniform(UniformName.modelnormal, Matrix.Identity);
if (t.FogFactor != fogfactor) 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; fogfactor = t.FogFactor;
} }
} }
// Set the colors to use // 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.vertexColor, vertexcolor);
graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection))); graphics.SetUniform(UniformName.highlightcolor, CalculateHighlightColor((t == highlighted) && showhighlight, (t.Selected && showselection)));
@ -1287,206 +1359,8 @@ namespace CodeImp.DoomBuilder.Rendering
return (float)Math.Cos(Angle2D.DegToRad(angle)); return (float)Math.Cos(Angle2D.DegToRad(angle));
} }
//mxd. Dynamic lights pass!
private VisualSector RenderLightsFromGeometryList(List<VisualGeometry> geometrytolit, List<VisualThing> 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<VisualGeometry> geometrytolit, List<VisualThing> 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<ImageData, List<VisualGeometry>> geometrytolit, List<VisualThing> 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<ImageData, List<VisualGeometry>> 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 //mxd. Render models
private void RenderModels(bool lightpass, bool trans) private void RenderModels(bool trans, List<VisualThing> lights)
{ {
ShaderName shaderpass = (fullbrightness ? ShaderName.world3d_fullbright : ShaderName.world3d_main_vertexcolor); ShaderName shaderpass = (fullbrightness ? ShaderName.world3d_fullbright : ShaderName.world3d_main_vertexcolor);
ShaderName currentshaderpass = shaderpass; ShaderName currentshaderpass = shaderpass;
@ -1495,15 +1369,17 @@ namespace CodeImp.DoomBuilder.Rendering
RenderPass currentpass = RenderPass.Solid; RenderPass currentpass = RenderPass.Solid;
// Begin rendering with this shader // Begin rendering with this shader
if (!lightpass) graphics.SetShader(currentshaderpass);
{
graphics.SetShader(currentshaderpass); // Light data arrays
} Vector4f[] lightColor = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE];
else Vector4f[] lightPosAndRadius = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE];
{ Vector4f[] lightOrientation = new Vector4f[MAX_DYNLIGHTS_PER_SURFACE];
graphics.SetShader(ShaderName.world3d_lightpass); Vector2f[] light2Radius = new Vector2f[MAX_DYNLIGHTS_PER_SURFACE];
graphics.SetAlphaBlendEnable(true);
} graphics.SetUniform(UniformName.lightsEnabled, lights.Count > 0);
bool hadlights = false;
List<VisualThing> things; List<VisualThing> things;
if (trans) if (trans)
@ -1523,6 +1399,7 @@ namespace CodeImp.DoomBuilder.Rendering
foreach(VisualThing t in things) foreach(VisualThing t in things)
{ {
if (trans) if (trans)
{ {
// Change blend mode? // Change blend mode?
@ -1563,7 +1440,7 @@ namespace CodeImp.DoomBuilder.Rendering
wantedshaderpass += 8; wantedshaderpass += 8;
// Switch shader pass? // Switch shader pass?
if (!lightpass && currentshaderpass != wantedshaderpass) if (currentshaderpass != wantedshaderpass)
{ {
graphics.SetShader(wantedshaderpass); graphics.SetShader(wantedshaderpass);
currentshaderpass = wantedshaderpass; currentshaderpass = wantedshaderpass;
@ -1587,147 +1464,73 @@ namespace CodeImp.DoomBuilder.Rendering
{ {
// this is not right... // this is not right...
graphics.SetUniform(UniformName.modelnormal, General.Map.Data.ModeldefEntries[t.Thing.Type].TransformRotation * modelrotation); 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); if (t.Thing.Sector != null) graphics.SetUniform(UniformName.sectorfogcolor, t.Thing.Sector.FogColor);
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));
} }
if (t.Thing.Sector != null) if (t.Thing.Sector != null)
graphics.SetUniform(UniformName.desaturation, t.Thing.Sector.Desaturation); graphics.SetUniform(UniformName.desaturation, t.Thing.Sector.Desaturation);
else graphics.SetUniform(UniformName.desaturation, 0.0f); 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; GZModel model = General.Map.Data.ModeldefEntries[t.Thing.Type].Model;
for (int j = 0; j < model.Meshes.Count; j++) for (int j = 0; j < model.Meshes.Count; j++)
{ {
graphics.SetTexture(model.Textures[j]); graphics.SetTexture(model.Textures[j]);
if (!lightpass) // Render!
{ model.Meshes[j].Draw(graphics);
// Render!
model.Meshes[j].Draw(graphics);
}
else if (lightpass && t.RenderPass != RenderPass.Additive) // additive stuff does not get any lighting
{
List<VisualThing> 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);
}
}
}
}
} }
} }
if (lightpass) graphics.SetUniform(UniformName.lightsEnabled, false);
{
graphics.SetBlendOperation(BlendOperation.Add);
graphics.SetAlphaBlendEnable(false);
}
} }
//mxd //mxd
@ -1738,7 +1541,7 @@ namespace CodeImp.DoomBuilder.Rendering
// Set render settings // Set render settings
graphics.SetShader(ShaderName.world3d_skybox); graphics.SetShader(ShaderName.world3d_skybox);
graphics.SetTexture(General.Map.Data.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) foreach(VisualGeometry g in geo)
{ {
@ -1791,20 +1594,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) if(General.Map.Data.GldefsEntries.ContainsKey(t.Thing.Type) && General.Map.Data.GldefsEntries[t.Thing.Type].DontLightSelf && t.Thing.Index == lt.Thing.Index)
continue; continue;
float distSquared = Vector3.DistanceSquared(lt.Center, t.Center); float distSquared = Vector3f.DistanceSquared(lt.Center, t.Center);
float radiusSquared = lt.LightRadius * lt.LightRadius; float radiusSquared = lt.LightRadius * lt.LightRadius;
if(distSquared < radiusSquared) if(distSquared < radiusSquared)
{ {
int sign = (lt.LightType.LightRenderStyle == GZGeneral.LightRenderStyle.SUBTRACTIVE ? -1 : 1); 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 dist = L.Length();
float scaler = 1 - dist / lt.LightRadius * lt.LightColor.Alpha; float scaler = 1 - dist / lt.LightRadius * lt.LightColor.Alpha;
if (lt.LightType.LightType == GZGeneral.LightType.SPOT) if (lt.LightType.LightType == GZGeneral.LightType.SPOT)
{ {
Vector3 lookAt = lt.VectorLookAt; Vector3f lookAt = lt.VectorLookAt;
L.Normalize(); L.Normalize();
float cosDir = Vector3.Dot(-L, lookAt); float cosDir = Vector3f.Dot(-L, lookAt);
scaler *= (float)Smoothstep(CosDeg(lt.LightSpotRadius2), CosDeg(lt.LightSpotRadius1), cosDir); scaler *= (float)Smoothstep(CosDeg(lt.LightSpotRadius2), CosDeg(lt.LightSpotRadius1), cosDir);
} }
@ -1997,7 +1800,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetShader(ShaderName.display2d_normal); graphics.SetShader(ShaderName.display2d_normal);
graphics.SetUniform(UniformName.projection, world * view2d); graphics.SetUniform(UniformName.projection, world * view2d);
graphics.SetUniform(UniformName.texturefactor, new Color4(1f, 1f, 1f, 1f)); 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); graphics.SetSamplerFilter(General.Settings.VisualBilinear ? TextureFilter.Linear : TextureFilter.Nearest);
// Texture // Texture
@ -2021,11 +1824,11 @@ namespace CodeImp.DoomBuilder.Rendering
{ {
if (usefog) 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 else
{ {
graphics.SetUniform(UniformName.fogsettings, new Vector4(-1.0f)); graphics.SetUniform(UniformName.fogsettings, new Vector4f(-1.0f));
} }
} }

View file

@ -6,15 +6,15 @@ using System.Threading.Tasks;
namespace CodeImp.DoomBuilder.Rendering namespace CodeImp.DoomBuilder.Rendering
{ {
public struct Vector2 public struct Vector2f
{ {
public Vector2(float v) public Vector2f(float v)
{ {
X = v; X = v;
Y = v; Y = v;
} }
public Vector2(float x, float y) public Vector2f(float x, float y)
{ {
X = x; X = x;
Y = y; Y = y;
@ -23,7 +23,7 @@ namespace CodeImp.DoomBuilder.Rendering
public float X; public float X;
public float Y; 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 squared = amount * amount;
float cubed = amount * squared; float cubed = amount * squared;
@ -31,16 +31,16 @@ namespace CodeImp.DoomBuilder.Rendering
float part2 = (-2.0f * cubed) + (3.0f * squared); float part2 = (-2.0f * cubed) + (3.0f * squared);
float part3 = (cubed - (2.0f * squared)) + amount; float part3 = (cubed - (2.0f * squared)) + amount;
float part4 = cubed - squared; float part4 = cubed - squared;
return new Vector2( return new Vector2f(
(((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4), (((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.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4));
} }
public override bool Equals(object o) 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; return this == v;
} }
else else
@ -54,27 +54,88 @@ namespace CodeImp.DoomBuilder.Rendering
return X.GetHashCode() + Y.GetHashCode(); 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; 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; return left.X != right.X || left.Y != right.Y;
} }

View file

@ -6,23 +6,23 @@ using System.Threading.Tasks;
namespace CodeImp.DoomBuilder.Rendering namespace CodeImp.DoomBuilder.Rendering
{ {
public struct Vector3 public struct Vector3f
{ {
public Vector3(float v) public Vector3f(float v)
{ {
X = v; X = v;
Y = v; Y = v;
Z = v; Z = v;
} }
public Vector3(Vector2 xy, float z) public Vector3f(Vector2f xy, float z)
{ {
X = xy.X; X = xy.X;
Y = xy.Y; Y = xy.Y;
Z = z; Z = z;
} }
public Vector3(float x, float y, float z) public Vector3f(float x, float y, float z)
{ {
X = x; X = x;
Y = y; Y = y;
@ -33,16 +33,16 @@ namespace CodeImp.DoomBuilder.Rendering
public float Y; public float Y;
public float Z; 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.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.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.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); (((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 squared = amount * amount;
float cubed = amount * squared; float cubed = amount * squared;
@ -50,26 +50,26 @@ namespace CodeImp.DoomBuilder.Rendering
float part2 = (-2.0f * cubed) + (3.0f * squared); float part2 = (-2.0f * cubed) + (3.0f * squared);
float part3 = (cubed - (2.0f * squared)) + amount; float part3 = (cubed - (2.0f * squared)) + amount;
float part4 = cubed - squared; float part4 = cubed - squared;
return new Vector3( return new Vector3f(
(((value1.X * part1) + (value2.X * part2)) + (tangent1.X * part3)) + (tangent2.X * part4), (((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.Y * part1) + (value2.Y * part2)) + (tangent1.Y * part3)) + (tangent2.Y * part4),
(((value1.Z * part1) + (value2.Z * part2)) + (tangent1.Z * part3)) + (tangent2.Z * 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; Vector3f c = b - a;
return Vector3.Dot(c, c); 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; 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.X = left.Y * right.Z - left.Z * right.Y;
result.Y = left.Z * right.X - left.X * right.Z; result.Y = left.Z * right.X - left.X * right.Z;
result.Z = left.X * right.Y - left.Y * right.X; result.Z = left.X * right.Y - left.Y * right.X;
@ -78,10 +78,10 @@ namespace CodeImp.DoomBuilder.Rendering
public float Length() 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(); v.Normalize();
return v; return v;
@ -100,9 +100,9 @@ namespace CodeImp.DoomBuilder.Rendering
public override bool Equals(object o) 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; return this == v;
} }
else else
@ -116,27 +116,98 @@ namespace CodeImp.DoomBuilder.Rendering
return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode(); 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; 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; return left.X != right.X || left.Y != right.Y || left.Z != right.Z;
} }

View file

@ -6,9 +6,9 @@ using System.Threading.Tasks;
namespace CodeImp.DoomBuilder.Rendering namespace CodeImp.DoomBuilder.Rendering
{ {
public struct Vector4 public struct Vector4f
{ {
public Vector4(float v) public Vector4f(float v)
{ {
X = v; X = v;
Y = v; Y = v;
@ -16,7 +16,7 @@ namespace CodeImp.DoomBuilder.Rendering
W = v; W = v;
} }
public Vector4(Vector2 xy, float z, float w) public Vector4f(Vector2f xy, float z, float w)
{ {
X = xy.X; X = xy.X;
Y = xy.Y; Y = xy.Y;
@ -24,7 +24,7 @@ namespace CodeImp.DoomBuilder.Rendering
W = w; W = w;
} }
public Vector4(Vector3 xyz, float w) public Vector4f(Vector3f xyz, float w)
{ {
X = xyz.X; X = xyz.X;
Y = xyz.Y; Y = xyz.Y;
@ -32,7 +32,7 @@ namespace CodeImp.DoomBuilder.Rendering
W = w; W = w;
} }
public Vector4(float x, float y, float z, float w) public Vector4f(float x, float y, float z, float w)
{ {
X = x; X = x;
Y = y; Y = y;
@ -47,9 +47,9 @@ namespace CodeImp.DoomBuilder.Rendering
public override bool Equals(object o) 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; return this == v;
} }
else 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() public override int GetHashCode()
@ -78,12 +78,95 @@ namespace CodeImp.DoomBuilder.Rendering
return X.GetHashCode() + Y.GetHashCode() + Z.GetHashCode() + W.GetHashCode(); 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; 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; return left.X != right.X || left.Y != right.Y || left.Z != right.Z || left.W != right.W;
} }

View file

@ -12,17 +12,18 @@ uniforms
vec4 fogsettings; vec4 fogsettings;
vec4 fogcolor; vec4 fogcolor;
vec4 sectorfogcolor;
vec4 vertexColor; vec4 vertexColor;
sampler2D texture1; sampler2D texture1;
// dynamic light related // dynamic light related
vec4 lightPosAndRadius; vec4 lightPosAndRadius[64];
vec3 lightOrientation; // this is a vector that points in light's direction vec4 lightOrientation[64]; // this is a vector that points in light's direction
vec2 light2Radius; // this is used with spotlights vec2 light2Radius[64]; // this is used with spotlights
vec4 lightColor; vec4 lightColor[64];
float ignoreNormals; // ignore normals in lighting equation. used for non-attenuated lights on models. float lightsEnabled;
float spotLight; // use lightOrientation
} }
functions functions
@ -33,7 +34,7 @@ functions
float fogdist = max(16.0, distance(PosW, campos.xyz)); float fogdist = max(16.0, distance(PosW, campos.xyz));
float fogfactor = exp2(campos.w * fogdist); float fogfactor = exp2(campos.w * fogdist);
color.rgb = mix(lightColor.rgb, color.rgb, fogfactor); color.rgb = mix(sectorfogcolor.rgb, color.rgb, fogfactor);
return color; return color;
} }
@ -42,6 +43,67 @@ functions
float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14);
return vec4(mix(texel.rgb, vec3(gray), desaturation), texel.a); 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 && (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 shader world3d_main
@ -53,14 +115,16 @@ shader world3d_main
vec2 TextureCoordinate; vec2 TextureCoordinate;
vec3 Normal; vec3 Normal;
} }
v2f v2f
{ {
vec4 Color; vec4 Color;
vec2 UV; vec2 UV;
vec3 PosW;
vec3 Normal;
vec4 viewpos; vec4 viewpos;
} }
out out
{ {
vec4 FragColor; vec4 FragColor;
@ -68,17 +132,20 @@ shader world3d_main
vertex vertex
{ {
v2f.viewpos = view * world * vec4(in.Position, 1.0); v2f.viewpos = view * world * vec4(in.Position, 1.0);
gl_Position = projection * v2f.viewpos; gl_Position = projection * v2f.viewpos;
v2f.Color = in.Color; v2f.PosW = (world * vec4(in.Position, 1.0)).xyz;
v2f.UV = in.TextureCoordinate; v2f.Color = in.Color;
v2f.UV = in.TextureCoordinate;
v2f.Normal = normalize((modelnormal * vec4(in.Normal, 1.0)).xyz);
} }
fragment fragment
{ {
vec4 tcolor = texture(texture1, v2f.UV); vec4 tcolor = texture(texture1, v2f.UV);
tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a);
out.FragColor = desaturate(tcolor * v2f.Color); tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal);
out.FragColor = desaturate(tcolor);
#if defined(ALPHA_TEST) #if defined(ALPHA_TEST)
if (out.FragColor.a < 0.5) discard; if (out.FragColor.a < 0.5) discard;
@ -111,6 +178,7 @@ shader world3d_main_highlight extends world3d_main
{ {
vec4 tcolor = texture(texture1, v2f.UV); vec4 tcolor = texture(texture1, v2f.UV);
tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a);
tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal);
if (tcolor.a == 0.0) if (tcolor.a == 0.0)
{ {
out.FragColor = tcolor; out.FragColor = tcolor;
@ -118,7 +186,7 @@ shader world3d_main_highlight extends world3d_main
else else
{ {
// Blend texture color and vertex color // Blend texture color and vertex color
vec4 ncolor = desaturate(tcolor * v2f.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)); out.FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(v2f.Color.a + 0.25, 0.5));
} }
@ -209,91 +277,20 @@ shader world3d_highlight_vertexcolor extends world3d_main_highlight
} }
} }
shader world3d_lightpass extends world3d_main shader world3d_main_fog extends world3d_main
{
v2f
{
vec4 Color;
vec2 UV;
vec3 PosW;
vec3 Normal;
vec4 viewpos;
}
vertex
{
v2f.viewpos = view * world * vec4(in.Position, 1.0);
gl_Position = projection * v2f.viewpos;
v2f.PosW = (world * vec4(in.Position, 1.0)).xyz;
v2f.Color = in.Color;
v2f.UV = in.TextureCoordinate;
v2f.Normal = normalize((modelnormal * vec4(in.Normal, 1.0)).xyz);
}
fragment
{
//is face facing away from light source?
// update 01.02.2017: offset the equation by 3px back to try to emulate GZDoom's broken visibility check.
float diffuseContribution = dot(v2f.Normal, normalize(lightPosAndRadius.xyz - v2f.PosW + v2f.Normal * 3.0));
if (diffuseContribution < 0.0 && ignoreNormals < 0.5)
discard;
diffuseContribution = max(diffuseContribution, 0.0); // to make sure
//is pixel in light range?
float dist = distance(v2f.PosW, lightPosAndRadius.xyz);
if (dist > lightPosAndRadius.w)
discard;
//is pixel tranparent?
vec4 tcolor = texture(texture1, v2f.UV);
tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a);
if (tcolor.a == 0.0)
discard;
//if it is - calculate color at current pixel
vec4 lightColorMod = vec4(0.0, 0.0, 0.0, 1.0);
lightColorMod.rgb = lightColor.rgb * max(lightPosAndRadius.w - dist, 0.0) / lightPosAndRadius.w;
if (spotLight > 0.5)
{
vec3 lightDirection = normalize(lightPosAndRadius.xyz - v2f.PosW);
float cosDir = dot(lightDirection, lightOrientation);
float df = smoothstep(light2Radius.y, light2Radius.x, cosDir);
lightColorMod.rgb *= df;
}
if (lightColor.a > 0.979 && lightColor.a < 0.981) // attenuated light 98%
lightColorMod.rgb *= diffuseContribution;
if (lightColorMod.r <= 0.0 && lightColorMod.g <= 0.0 && lightColorMod.b <= 0.0)
discard;
lightColorMod.rgb *= lightColor.a;
if (lightColor.a > 0.4) //Normal, vavoom or negative light (or attenuated)
lightColorMod *= tcolor;
out.FragColor = desaturate(lightColorMod); //Additive light
#if defined(ALPHA_TEST)
if (out.FragColor.a < 0.5) discard;
#endif
}
}
shader world3d_main_fog extends world3d_lightpass
{ {
fragment fragment
{ {
vec4 tcolor = texture(texture1, v2f.UV); vec4 tcolor = texture(texture1, v2f.UV);
tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a);
tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal);
if (tcolor.a == 0.0) if (tcolor.a == 0.0)
{ {
out.FragColor = tcolor; out.FragColor = tcolor;
} }
else else
{ {
out.FragColor = desaturate(getFogColor(v2f.PosW, tcolor * v2f.Color)); out.FragColor = desaturate(getFogColor(v2f.PosW, tcolor));
} }
#if defined(ALPHA_TEST) #if defined(ALPHA_TEST)
@ -310,6 +307,7 @@ shader world3d_main_highlight_fog extends world3d_main_fog
{ {
vec4 tcolor = texture(texture1, v2f.UV); vec4 tcolor = texture(texture1, v2f.UV);
tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a); tcolor = mix(tcolor, vec4(stencilColor.rgb, tcolor.a), stencilColor.a);
tcolor = getDynLightContribution(tcolor, v2f.Color, v2f.PosW, v2f.Normal);
if (tcolor.a == 0.0) if (tcolor.a == 0.0)
{ {
out.FragColor = tcolor; out.FragColor = tcolor;
@ -317,7 +315,7 @@ shader world3d_main_highlight_fog extends world3d_main_fog
else else
{ {
// Blend texture color and vertex color // Blend texture color and vertex color
vec4 ncolor = desaturate(getFogColor(v2f.PosW, tcolor * v2f.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)); out.FragColor = vec4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4 * highlightcolor.a), max(ncolor.a + 0.25, 0.5));
} }

View file

@ -179,8 +179,8 @@ namespace CodeImp.DoomBuilder.VisualModes
WorldVertex p2 = vertices[startindex + 1]; WorldVertex p2 = vertices[startindex + 1];
WorldVertex p3 = vertices[startindex + 2]; WorldVertex p3 = vertices[startindex + 2];
Vector3 U = new Vector3(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z); Vector3f U = new Vector3f(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 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.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); p1.ny = p2.ny = p3.ny = -(U.Z * V.X - U.X * V.Z);

View file

@ -26,6 +26,7 @@ using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering; using CodeImp.DoomBuilder.Rendering;
using Plane = CodeImp.DoomBuilder.Geometry.Plane; using Plane = CodeImp.DoomBuilder.Geometry.Plane;
using CodeImp.DoomBuilder.GZBuilder; using CodeImp.DoomBuilder.GZBuilder;
using CodeImp.DoomBuilder.GZBuilder.MD3;
#endregion #endregion
@ -87,12 +88,12 @@ namespace CodeImp.DoomBuilder.VisualModes
private float lightSpotRadius2; private float lightSpotRadius2;
private float lightPrimaryRadius; private float lightPrimaryRadius;
private float lightSecondaryRadius; private float lightSecondaryRadius;
private Vector3 position_v3; private Vector3f position_v3;
private float lightDelta; //used in light animation private float lightDelta; //used in light animation
private Vector3D[] boundingBox; private Vector3D[] boundingBox;
//gldefs light //gldefs light
private Vector3 lightOffset; private Vector3f lightOffset;
private int lightInterval; private int lightInterval;
private bool isGldefsLight; 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; } } internal int VertexColor { get { return vertices.Length > 0 && vertices[0].Length > 0 ? vertices[0][0].c : 0; } }
public int CameraDistance { get { return cameradistance; } } public int CameraDistance { get { return cameradistance; } }
public float FogFactor { get { return fogfactor; } } public float FogFactor { get { return fogfactor; } }
public Vector3 Center public Vector3f Center
{ {
get get
{ {
if (isGldefsLight) return position_v3 + lightOffset; if (isGldefsLight) return position_v3 + lightOffset;
else if (Thing.DynamicLightType != null) return position_v3; // fixes GZDoomBuilder-Bugfix#137 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 Vector3D CenterV3D { get { return RenderDevice.V3D(Center); } }
public float LocalCenterZ { get { return thingheight / 2f; } } //mxd 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; } } public Vector3D[] BoundingBox { get { return boundingBox; } }
//mxd. light properties //mxd. light properties
@ -141,12 +142,12 @@ namespace CodeImp.DoomBuilder.VisualModes
public PixelColor StencilColor { get { return stencilColor; } } public PixelColor StencilColor { get { return stencilColor; } }
// [ZZ] this is used for spotlights // [ZZ] this is used for spotlights
public Vector3 VectorLookAt public Vector3f VectorLookAt
{ {
get get
{ {
// this esoteric value (1.5708) is 90 degrees but in radians // 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... 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++) 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].x = transformed.X;
vertices[c][i].y = transformed.Y; vertices[c][i].y = transformed.Y;
vertices[c][i].z = transformed.Z + zoffset; vertices[c][i].z = transformed.Z + zoffset;
@ -385,7 +386,7 @@ namespace CodeImp.DoomBuilder.VisualModes
// Apply transform // Apply transform
for(int i = 0; i < vertices[c].Length; i++) 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].x = transformed.X;
vertices[c][i].y = transformed.Y; vertices[c][i].y = transformed.Y;
vertices[c][i].z = transformed.Z; vertices[c][i].z = transformed.Z;
@ -496,7 +497,7 @@ namespace CodeImp.DoomBuilder.VisualModes
// Apply transform // Apply transform
for(int i = 0; i < vertices[c].Length; i++) 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].x = transformed.X;
vertices[c][i].y = transformed.Y; vertices[c][i].y = transformed.Y;
vertices[c][i].z = transformed.Z; vertices[c][i].z = transformed.Z;
@ -769,7 +770,7 @@ namespace CodeImp.DoomBuilder.VisualModes
//apply settings //apply settings
lightColor = new Color4(light.Color.Red, light.Color.Green, light.Color.Blue, (float)ld.LightRenderStyle / 100.0f); 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); 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; lightType = light.Type;
if(ld.LightModifier == GZGeneral.LightModifier.SECTOR) if(ld.LightModifier == GZGeneral.LightModifier.SECTOR)
@ -851,17 +852,50 @@ namespace CodeImp.DoomBuilder.VisualModes
{ {
boundingBox = new Vector3D[9]; boundingBox = new Vector3D[9];
boundingBox[0] = CenterV3D; boundingBox[0] = CenterV3D;
float h2 = height / 2.0f;
boundingBox[1] = new Vector3D(position_v3.X - width, position_v3.Y - width, Center.Z - h2); if (Thing.RenderMode != ThingRenderMode.MODEL && Thing.RenderMode != ThingRenderMode.VOXEL)
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); float h2 = height / 2.0f;
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[1] = 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); 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 //mxd. This updates the sprite frame to be rendered
@ -894,3 +928,4 @@ namespace CodeImp.DoomBuilder.VisualModes
#endregion #endregion
} }
} }

View file

@ -37,8 +37,8 @@ namespace CodeImp.DoomBuilder.ZDoom
private Dictionary<int, string>[] surfaceskinenames; private Dictionary<int, string>[] surfaceskinenames;
private string[] modelnames; private string[] modelnames;
private string path; private string path;
private Vector3 scale; private Vector3f scale;
private Vector3 offset; private Vector3f offset;
private float angleoffset; private float angleoffset;
private float pitchoffset; private float pitchoffset;
private float rolloffset; private float rolloffset;
@ -55,8 +55,8 @@ namespace CodeImp.DoomBuilder.ZDoom
public string[] SkinNames { get { return skinnames; } } public string[] SkinNames { get { return skinnames; } }
public Dictionary<int, string>[] SurfaceSkinNames { get { return surfaceskinenames; } } public Dictionary<int, string>[] SurfaceSkinNames { get { return surfaceskinenames; } }
public string[] ModelNames { get { return modelnames; } } public string[] ModelNames { get { return modelnames; } }
public Vector3 Scale { get { return scale; } } public Vector3f Scale { get { return scale; } }
public Vector3 Offset { get { return offset; } } public Vector3f Offset { get { return offset; } }
public float AngleOffset { get { return angleoffset; } } public float AngleOffset { get { return angleoffset; } }
public float PitchOffset { get { return pitchoffset; } } public float PitchOffset { get { return pitchoffset; } }
public float RollOffset { get { return rolloffset; } } public float RollOffset { get { return rolloffset; } }
@ -77,7 +77,7 @@ namespace CodeImp.DoomBuilder.ZDoom
skinnames = new string[MAX_MODELS]; skinnames = new string[MAX_MODELS];
modelnames = new string[MAX_MODELS]; modelnames = new string[MAX_MODELS];
frames = new Dictionary<string, HashSet<FrameStructure>>(StringComparer.OrdinalIgnoreCase); frames = new Dictionary<string, HashSet<FrameStructure>>(StringComparer.OrdinalIgnoreCase);
scale = new Vector3(1.0f, 1.0f, 1.0f); scale = new Vector3f(1.0f, 1.0f, 1.0f);
surfaceskinenames = new Dictionary<int, string>[MAX_MODELS]; surfaceskinenames = new Dictionary<int, string>[MAX_MODELS];
for(int i = 0; i < MAX_MODELS; i++) for(int i = 0; i < MAX_MODELS; i++)
{ {

View file

@ -78,7 +78,7 @@ namespace CodeImp.DoomBuilder.ZDoom
if(!string.IsNullOrEmpty(modelName) && spriteNames.Count > 0) if(!string.IsNullOrEmpty(modelName) && spriteNames.Count > 0)
{ {
mde.ModelNames.Add(modelName); 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) foreach(string s in spriteNames)
{ {

View file

@ -37,7 +37,7 @@ enum class ShaderFlags : int { None, Debug };
enum class PrimitiveType : int { LineList, TriangleList, TriangleStrip }; enum class PrimitiveType : int { LineList, TriangleList, TriangleStrip };
enum class TextureFilter : int { Nearest, Linear }; enum class TextureFilter : int { Nearest, Linear };
enum class MipmapFilter : int { None, 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 UniformName;
typedef int ShaderName; typedef int ShaderName;

View file

@ -863,12 +863,19 @@ bool GLRenderDevice::ApplyUniforms()
GLuint location = locations[i]; GLuint location = locations[i];
switch (mUniformInfo[i].Type) switch (mUniformInfo[i].Type)
{ {
default: default: break;
case UniformType::Vec4f: glUniform4fv(location, 1, data); break; case UniformType::Vec4f: glUniform4fv(location, 1, data); break;
case UniformType::Vec3f: glUniform3fv(location, 1, data); break; case UniformType::Vec3f: glUniform3fv(location, 1, data); break;
case UniformType::Vec2f: glUniform2fv(location, 1, data); break; case UniformType::Vec2f: glUniform2fv(location, 1, data); break;
case UniformType::Float: glUniform1fv(location, 1, data); break; case UniformType::Float: glUniform1fv(location, 1, data); break;
case UniformType::Mat4: glUniformMatrix4fv(location, 1, GL_FALSE, 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; lastupdates[i] = mUniformInfo[i].LastUpdate;
} }