Spot lights geometry improvement, LodLights cone angles and game crash fixes

This commit is contained in:
dexy 2021-05-01 21:17:43 +10:00
parent ea876743bc
commit 77e036e750
10 changed files with 178 additions and 24 deletions

View File

@ -589,7 +589,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.timeAndStateFlags, 56, MetaStructureEntryDataType.Array, 0, 6, 0), new MetaStructureEntryInfo_s(MetaName.timeAndStateFlags, 56, MetaStructureEntryDataType.Array, 0, 6, 0),
new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0), new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)MetaTypeName.HASH, 72, MetaStructureEntryDataType.Array, 0, 8, 0), new MetaStructureEntryInfo_s(MetaName.hash, 72, MetaStructureEntryDataType.Array, 0, 8, 0),
new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.coneInnerAngle, 88, MetaStructureEntryDataType.Array, 0, 10, 0), new MetaStructureEntryInfo_s(MetaName.coneInnerAngle, 88, MetaStructureEntryDataType.Array, 0, 10, 0),
new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0), new MetaStructureEntryInfo_s((MetaName)MetaTypeName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),

View File

@ -14110,7 +14110,7 @@ namespace CodeWalker.GameFiles
new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UInt, 0, 0, 0), new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UInt, 0, 0, 0),
new PsoStructureEntryInfo(MetaName.timeAndStateFlags, PsoDataType.Array, 56, 0, (MetaName)6), new PsoStructureEntryInfo(MetaName.timeAndStateFlags, PsoDataType.Array, 56, 0, (MetaName)6),
new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UInt, 0, 0, 0), new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UInt, 0, 0, 0),
new PsoStructureEntryInfo((MetaName)MetaTypeName.HASH, PsoDataType.Array, 72, 0, (MetaName)8), new PsoStructureEntryInfo(MetaName.hash, PsoDataType.Array, 72, 0, (MetaName)8),
new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UByte, 0, 0, 0), new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UByte, 0, 0, 0),
new PsoStructureEntryInfo(MetaName.coneInnerAngle, PsoDataType.Array, 88, 0, (MetaName)10), new PsoStructureEntryInfo(MetaName.coneInnerAngle, PsoDataType.Array, 88, 0, (MetaName)10),
new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UByte, 0, 0, 0), new PsoStructureEntryInfo((MetaName)MetaTypeName.ARRAYINFO, PsoDataType.UByte, 0, 0, 0),

View File

@ -49,9 +49,9 @@ VS_Output main(float4 ipos : POSITION, uint iid : SV_InstanceID)
else if (InstType == 2)//spot (cone) else if (InstType == 2)//spot (cone)
{ {
float arads = InstConeOuterAngle; float arads = InstConeOuterAngle;
float3 cpos = ipos.xyz * (tan(arads) * extent); float3 tpos = (ipos.xyz * sin(arads)) + float3(0, 0, ipos.w * cos(arads));
cpos.y += ipos.w * extent; float3 cpos = ((ipos.w > 0) ? normalize(tpos) : tpos) * extent;
opos = (cpos.x * InstTangentX) + (cpos.y * InstDirection) + (cpos.z * InstTangentY); opos = (cpos.x * InstTangentX) + (cpos.y * InstTangentY) + (cpos.z * InstDirection);
} }
else if (InstType == 4)//capsule else if (InstType == 4)//capsule
{ {

View File

@ -47,9 +47,9 @@ VS_Output main(float4 ipos : POSITION, uint iid : SV_InstanceID)
else if (LightType == 2)//spot (cone) else if (LightType == 2)//spot (cone)
{ {
float arads = lodlight.OuterAngleOrCapExt; float arads = lodlight.OuterAngleOrCapExt;
float3 cpos = ipos.xyz * (tan(arads) * extent); float3 tpos = (ipos.xyz * sin(arads)) + float3(0, 0, ipos.w * cos(arads));
cpos.y += ipos.w * extent; float3 cpos = ((ipos.w>0) ? normalize(tpos) : tpos) * extent;
opos = (cpos.x * lodlight.TangentX.xyz) + (cpos.y * lodlight.Direction.xyz) + (cpos.z * lodlight.TangentY.xyz); opos = (cpos.x * lodlight.TangentX.xyz) + (cpos.y * lodlight.TangentY.xyz) + (cpos.z * lodlight.Direction.xyz);
} }
else if (LightType == 4)//capsule else if (LightType == 4)//capsule
{ {

View File

@ -1513,8 +1513,8 @@ namespace CodeWalker.Rendering
light.TangentY = new Vector4(l.TangentY, 0.0f); light.TangentY = new Vector4(l.TangentY, 0.0f);
light.Falloff = l.Falloff; light.Falloff = l.Falloff;
light.FalloffExponent = Math.Max(l.FalloffExponent*0.01f, 0.5f);//is this right? light.FalloffExponent = Math.Max(l.FalloffExponent*0.01f, 0.5f);//is this right?
light.InnerAngle = l.ConeInnerAngle * 0.0087266462f; //pi/360 light.InnerAngle = l.ConeInnerAngle * 0.012319971f; //pi/255
light.OuterAngleOrCapExt = l.ConeOuterAngleOrCapExt * 0.0087266462f; //pi/360 light.OuterAngleOrCapExt = l.ConeOuterAngleOrCapExt * 0.012319971f; //pi/255
var type = l.Type; var type = l.Type;
switch (type) switch (type)
{ {

View File

@ -1036,8 +1036,8 @@ namespace CodeWalker.Rendering
var tx = lodlight.TangentX; var tx = lodlight.TangentX;
var ty = lodlight.TangentY; var ty = lodlight.TangentY;
var extent = lodlight.Falloff; var extent = lodlight.Falloff;
var innerAngle = lodlight.ConeInnerAngle * 0.0087266462f; //pi/360 var innerAngle = lodlight.ConeInnerAngle * 0.012319971f; //pi/255
var outerAngle = lodlight.ConeOuterAngleOrCapExt * 0.0087266462f; //pi/360 var outerAngle = lodlight.ConeOuterAngleOrCapExt * 0.012319971f; //pi/255
var type = lodlight.Type; var type = lodlight.Type;
switch (type) switch (type)
{ {
@ -1047,10 +1047,8 @@ namespace CodeWalker.Rendering
RenderSelectionCircle(pos, Vector3.UnitY, Vector3.UnitZ, extent, colwht); RenderSelectionCircle(pos, Vector3.UnitY, Vector3.UnitZ, extent, colwht);
break; break;
case LightType.Spot: case LightType.Spot:
float coneouterrad = extent * (float)Math.Tan(outerAngle); RenderSelectionCone(pos, tx, ty, dir, (float)Math.Sin(outerAngle)*extent, (float)Math.Cos(outerAngle)*extent, colblu);
float coneinnerrad = extent * (float)Math.Tan(innerAngle); RenderSelectionCone(pos, tx, ty, dir, (float)Math.Sin(innerAngle)*extent, (float)Math.Cos(innerAngle)*extent, colwht);
RenderSelectionCone(pos, tx, ty, dir, coneouterrad, extent, colblu);
RenderSelectionCone(pos, tx, ty, dir, coneinnerrad, extent, colwht);
break; break;
case LightType.Capsule: case LightType.Capsule:
outerAngle = lodlight.ConeOuterAngleOrCapExt * 0.25f; outerAngle = lodlight.ConeOuterAngleOrCapExt * 0.25f;

View File

@ -90,7 +90,7 @@ namespace CodeWalker.Rendering
VertexShader LightVS; VertexShader LightVS;
PixelShader LightPS; PixelShader LightPS;
PixelShader LightMSPS; PixelShader LightMSPS;
UnitCone LightCone; LightCone LightCone;
UnitSphere LightSphere; UnitSphere LightSphere;
UnitCapsule LightCapsule; UnitCapsule LightCapsule;
UnitQuad LightQuad; UnitQuad LightQuad;
@ -160,8 +160,8 @@ namespace CodeWalker.Rendering
} }
LightCone = new UnitCone(device, bLodLightVS, 4, false); LightCone = new LightCone(device, bLodLightVS, 2);
LightSphere = new UnitSphere(device, bLodLightVS, 4, true); LightSphere = new UnitSphere(device, bLodLightVS, 3, true);
LightCapsule = new UnitCapsule(device, bLodLightVS, 4, false); LightCapsule = new UnitCapsule(device, bLodLightVS, 4, false);
LightQuad = new UnitQuad(device, true); LightQuad = new UnitQuad(device, true);
LightQuadLayout = new InputLayout(device, bDirLightVS, new[] LightQuadLayout = new InputLayout(device, bDirLightVS, new[]

View File

@ -20,12 +20,12 @@ namespace CodeWalker.Rendering
private VertexBufferBinding vbbinding; private VertexBufferBinding vbbinding;
private int indexcount; private int indexcount;
private struct SphTri private struct Tri
{ {
public int v1; public int v1;
public int v2; public int v2;
public int v3; public int v3;
public SphTri(int i1, int i2, int i3) public Tri(int i1, int i2, int i3)
{ {
v1 = i1; v1 = i1;
v2 = i2; v2 = i2;
@ -46,7 +46,7 @@ namespace CodeWalker.Rendering
List<Vector4> verts = new List<Vector4>(); List<Vector4> verts = new List<Vector4>();
Dictionary<Vector4, int> vdict = new Dictionary<Vector4, int>(); Dictionary<Vector4, int> vdict = new Dictionary<Vector4, int>();
List<SphTri> curtris = new List<SphTri>(); List<Tri> curtris = new List<Tri>();
verts.Add(new Vector4(0.0f, 0.0f, 0.0f, 0.0f));//top end (translated by VS!) verts.Add(new Vector4(0.0f, 0.0f, 0.0f, 0.0f));//top end (translated by VS!)
verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));//top normal verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));//top normal
@ -82,8 +82,8 @@ namespace CodeWalker.Rendering
i1 = 2; i1 = 2;
} }
curtris.Add(new SphTri(0, i0, i1)); //fill the cone curtris.Add(new Tri(0, i0, i1)); //fill the cone
curtris.Add(new SphTri(1, i1+1, i0+1)); //bottom cap triangles curtris.Add(new Tri(1, i1+1, i0+1)); //bottom cap triangles
} }
@ -149,4 +149,160 @@ namespace CodeWalker.Rendering
} }
public class LightCone
{
private Buffer VertexBuffer { get; set; }
private Buffer IndexBuffer { get; set; }
private InputLayout InputLayout { get; set; }
private VertexBufferBinding vbbinding;
private int indexcount;
private struct Tri
{
public Vector4 v1;
public Vector4 v2;
public Vector4 v3;
public Tri(Vector4 i1, Vector4 i2, Vector4 i3)
{
v1 = i1;
v2 = i2;
v3 = i3;
}
}
public LightCone(Device device, byte[] vsbytes, int detail)
{
InputLayout = new InputLayout(device, vsbytes, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
});
var tris = new List<Tri>();
var newtris = new List<Tri>();
var curtris = new List<Tri>();
curtris.Clear();//"cone" triangles
curtris.Add(new Tri(new Vector4(0, 0, 0, 0), new Vector4(-1, 0, 0, 1), new Vector4(0, -1, 0, 1)));
curtris.Add(new Tri(new Vector4(0, 0, 0, 0), new Vector4(0, 1, 0, 1), new Vector4(-1, 0, 0, 1)));
curtris.Add(new Tri(new Vector4(0, 0, 0, 0), new Vector4(1, 0, 0, 1), new Vector4(0, 1, 0, 1)));
curtris.Add(new Tri(new Vector4(0, 0, 0, 0), new Vector4(0, -1, 0, 1), new Vector4(1, 0, 0, 1)));
for (int i = 0; i < detail; i++)
{
foreach (var tri in curtris)
{
var v1 = tri.v1;
var v2 = tri.v2;
var v3 = tri.v3;
var v4 = new Vector4(Vector3.Normalize((v2 + v3).XYZ() * 0.5f), 1);
newtris.Add(new Tri(v1, v2, v4));
newtris.Add(new Tri(v1, v4, v3));
}
curtris = newtris;
newtris = new List<Tri>();
}
tris.AddRange(curtris);
curtris.Clear();//hemisphere triangles
curtris.Add(new Tri(new Vector4(0, 0, 1, 1), new Vector4(0, -1, 0, 1), new Vector4(-1, 0, 0, 1)));
curtris.Add(new Tri(new Vector4(0, 0, 1, 1), new Vector4(-1, 0, 0, 1), new Vector4(0, 1, 0, 1)));
curtris.Add(new Tri(new Vector4(0, 0, 1, 1), new Vector4(0, 1, 0, 1), new Vector4(1, 0, 0, 1)));
curtris.Add(new Tri(new Vector4(0, 0, 1, 1), new Vector4(1, 0, 0, 1), new Vector4(0, -1, 0, 1)));
for (int i = 0; i < detail; i++)
{
foreach (var tri in curtris)
{
var v1 = tri.v1;
var v2 = tri.v2;
var v3 = tri.v3;
var v4 = new Vector4(Vector3.Normalize((v1 + v2).XYZ() * 0.5f), 1);
var v5 = new Vector4(Vector3.Normalize((v2 + v3).XYZ() * 0.5f), 1);
var v6 = new Vector4(Vector3.Normalize((v3 + v1).XYZ() * 0.5f), 1);
newtris.Add(new Tri(v1, v4, v6));
newtris.Add(new Tri(v4, v2, v5));
newtris.Add(new Tri(v4, v5, v6));
newtris.Add(new Tri(v6, v5, v3));
}
curtris = newtris;
newtris = new List<Tri>();
}
tris.AddRange(curtris);
var verts = new List<Vector4>();
var vdict = new Dictionary<Vector4, int>();
var idata = new List<uint>();
uint addVert(Vector4 v)
{
if (vdict.TryGetValue(v, out int i)) return (uint)i;
var n = verts.Count;
verts.Add(v);
vdict[v] = n;
return (uint)n;
}
foreach (var tri in tris)
{
idata.Add(addVert(tri.v1));
idata.Add(addVert(tri.v2));
idata.Add(addVert(tri.v3));
}
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, verts.ToArray());
vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0);
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray());
indexcount = idata.Count;
}
public void Draw(DeviceContext context)
{
context.InputAssembler.InputLayout = InputLayout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexed(indexcount, 0, 0);
}
public void DrawInstanced(DeviceContext context, int count)
{
context.InputAssembler.InputLayout = InputLayout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexedInstanced(indexcount, count, 0, 0, 0);
}
public void Dispose()
{
if (VertexBuffer != null)
{
VertexBuffer.Dispose();
VertexBuffer = null;
}
if (IndexBuffer != null)
{
IndexBuffer.Dispose();
IndexBuffer = null;
}
if (InputLayout != null)
{
InputLayout.Dispose();
InputLayout = null;
}
}
}
} }

Binary file not shown.

Binary file not shown.