diff --git a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj
index 2af5424..e972b36 100644
--- a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj
+++ b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj
@@ -434,6 +434,16 @@
Pixel
4.0
+
+ Pixel
+ 4.1
+ Pixel
+ 4.1
+ Pixel
+ 4.1
+ Pixel
+ 4.1
+
Vertex
4.0
diff --git a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters
index b6bf4d5..136dd7b 100644
--- a/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters
+++ b/CodeWalker.Shaders/CodeWalker.Shaders.vcxproj.filters
@@ -268,6 +268,9 @@
Lights
+
+ Lights
+
diff --git a/CodeWalker.Shaders/LightPS.hlsl b/CodeWalker.Shaders/LightPS.hlsl
index 0f7d3c6..7096c76 100644
--- a/CodeWalker.Shaders/LightPS.hlsl
+++ b/CodeWalker.Shaders/LightPS.hlsl
@@ -1,9 +1,6 @@
#include "LightPS.hlsli"
-//currently unused - TODO: implement individual HD lights here
-
-
Texture2D DepthTex : register(t0);
Texture2D DiffuseTex : register(t2);
Texture2D NormalTex : register(t3);
@@ -14,11 +11,10 @@ struct VS_Output
{
float4 Pos : SV_POSITION;
float4 Screen : TEXCOORD0;
- uint IID : SV_INSTANCEID;
};
-PS_OUTPUT main(VS_Output input)
+float4 main(VS_Output input) : SV_TARGET
{
uint3 ssloc = uint3(input.Pos.xy, 0); //pixel location
float depth = DepthTex.Load(ssloc).r;
@@ -29,39 +25,14 @@ PS_OUTPUT main(VS_Output input)
float4 specular = SpecularTex.Load(ssloc);
float4 irradiance = IrradianceTex.Load(ssloc);
-
- PS_OUTPUT output;
- output.Depth = input.Pos.z;
-
- switch (RenderMode)
- {
- case 5: output.Colour = float4(diffuse.rgb, 1); return output;
- case 6: output.Colour = float4(normal.rgb, 1); return output;
- case 7: output.Colour = float4(specular.rgb, 1); return output;
- }
-
-
float4 spos = float4(input.Screen.xy/input.Screen.w, depth, 1);
float4 cpos = mul(spos, ViewProjInv);
float3 camRel = cpos.xyz * (1/cpos.w);
float3 norm = normal.xyz * 2 - 1;
-
- if (LightType == 0) //directional light
- {
- float3 c = DeferredDirectionalLight(camRel, norm, diffuse, specular, irradiance);
-
- PS_OUTPUT output;
- output.Colour = float4(c, 1);
- output.Depth = depth;
- return output;
- }
-
-
- float4 lcol = DeferredLODLight(camRel, norm, diffuse, specular, irradiance, input.IID);
+ float4 lcol = DeferredLight(camRel, norm, diffuse, specular, irradiance);
if (lcol.a <= 0) discard;
- output.Colour = lcol;
- return output;
+ return lcol;
}
diff --git a/CodeWalker.Shaders/LightPS.hlsli b/CodeWalker.Shaders/LightPS.hlsli
index 7bb7002..f284acf 100644
--- a/CodeWalker.Shaders/LightPS.hlsli
+++ b/CodeWalker.Shaders/LightPS.hlsli
@@ -22,6 +22,23 @@ cbuffer PSLightVars : register(b0)
float SampleMult;//for MSAA
}
+cbuffer PSLightInstVars : register(b2)
+{
+ float3 InstPosition;//camera relative
+ float InstIntensity;
+ float3 InstColour;
+ float InstFalloff;
+ float3 InstDirection;
+ float InstFalloffExponent;
+ float3 InstTangentX;
+ float InstConeInnerAngle;
+ float3 InstTangentY;
+ float InstConeOuterAngle;
+ float3 InstCapsuleExtent;
+ uint InstType;
+ float3 InstCullingPlaneNormal;
+ float InstCullingPlaneOffset;
+}
@@ -52,8 +69,6 @@ float3 GetReflectedDir(float3 camRel, float3 norm)
}
-
-
float3 DeferredDirectionalLight(float3 camRel, float3 norm, float4 diffuse, float4 specular, float4 irradiance)
{
float3 refl = GetReflectedDir(camRel, norm);
@@ -88,7 +103,7 @@ float4 DeferredLODLight(float3 camRel, float3 norm, float4 diffuse, float4 specu
else if (LightType == 2)//spot (cone)
{
float ang = acos(-dot(ldir, lodlight.Direction));
- float iang = lodlight.InnerAngle * 0.01745329;
+ float iang = lodlight.InnerAngle * 0.01745329 * 0.5;
float oang = lodlight.OuterAngleOrCapExt * 0.01745329 * 0.5;
if (ang > oang) return 0;
lamt *= saturate(1 - ((ang - iang) / (oang - iang)));
@@ -113,5 +128,52 @@ float4 DeferredLODLight(float3 camRel, float3 norm, float4 diffuse, float4 specu
return float4(lcol, 1);
}
+float4 DeferredLight(float3 camRel, float3 norm, float4 diffuse, float4 specular, float4 irradiance)
+{
+ float3 srpos = InstPosition - camRel; //light position relative to surface position
+ float ldist = length(srpos);
+ if (ldist > InstFalloff) return 0; //out of range of the light... TODO: capsules!
+ if (ldist <= 0) return 0;
+
+ float4 rgbi = float4(InstColour, InstIntensity);
+ float3 lcol = rgbi.rgb;// * rgbi.a; // * 5.0f;
+ float3 ldir = srpos / ldist;
+ float pclit = saturate(dot(ldir, norm));
+ float lamt = 1;
+
+ if (InstType == 1)//point (sphere)
+ {
+ lamt *= pow(saturate(1 - (ldist / InstFalloff)), InstFalloffExponent);
+ }
+ else if (InstType == 2)//spot (cone)
+ {
+ float ang = acos(-dot(ldir, InstDirection));
+ float iang = InstConeInnerAngle * 0.01745329 * 0.5;
+ float oang = InstConeOuterAngle * 0.01745329 * 0.5;
+ if (ang > oang) return 0;
+ lamt *= saturate(1 - ((ang - iang) / (oang - iang)));
+ lamt *= pow(saturate(1 - (ldist / InstFalloff)), InstFalloffExponent);
+ }
+ else if (InstType == 4)//capsule
+ {
+ lamt *= pow(saturate(1 - (ldist / InstFalloff)), InstFalloffExponent); //TODO! proper capsule lighting... (use point-line dist!)
+ }
+
+ pclit *= lamt;
+
+ if (pclit <= 0) return 0;
+
+ float3 refl = GetReflectedDir(camRel, norm);
+ float specb = saturate(dot(refl, ldir));
+ float specp = max(exp(specb * 10) - 1, 0);
+ float3 spec = lcol * (0.00006 * specp * specular.r * lamt);
+
+ lcol = lcol * diffuse.rgb * pclit + spec;
+
+ return float4(lcol, 1);
+}
+
+
+
diff --git a/CodeWalker.Shaders/LightPS_MS.hlsl b/CodeWalker.Shaders/LightPS_MS.hlsl
new file mode 100644
index 0000000..ebfab23
--- /dev/null
+++ b/CodeWalker.Shaders/LightPS_MS.hlsl
@@ -0,0 +1,52 @@
+#include "LightPS.hlsli"
+
+
+Texture2DMS DepthTex : register(t0);
+Texture2DMS DiffuseTex : register(t2);
+Texture2DMS NormalTex : register(t3);
+Texture2DMS SpecularTex : register(t4);
+Texture2DMS IrradianceTex : register(t5);
+
+struct VS_Output
+{
+ float4 Pos : SV_POSITION;
+ float4 Screen : TEXCOORD0;
+};
+
+float4 main(VS_Output input) : SV_TARGET
+{
+ uint2 ssloc = uint2(input.Pos.xy); //pixel location
+ float2 spos = float2(input.Screen.xy / input.Screen.w);
+ float4 c = 0;
+ float d = 0;
+ int sc = min(SampleCount, 8);
+
+ [unroll]
+ for (int i = 0; i < sc; i++)
+ {
+ float depth = DepthTex.Load(ssloc, i);
+ if (depth == 0) continue; //no existing subpixel rendered here
+
+ float4 diffuse = DiffuseTex.Load(ssloc, i);
+ float4 normal = NormalTex.Load(ssloc, i);
+ float4 specular = SpecularTex.Load(ssloc, i);
+ float4 irradiance = IrradianceTex.Load(ssloc, i);
+
+ float4 cpos = mul(float4(spos, depth, 1), ViewProjInv);
+ float3 camRel = cpos.xyz * (1 / cpos.w);
+ float3 norm = normal.xyz * 2 - 1;
+
+ float4 colour = DeferredLight(camRel, norm, diffuse, specular, irradiance);
+
+ c += colour;
+ d += depth;
+ }
+
+ c *= SampleMult;
+ d *= SampleMult;
+
+ if (d <= 0) discard;
+
+ return c;
+}
+
diff --git a/CodeWalker.Shaders/LightVS.hlsl b/CodeWalker.Shaders/LightVS.hlsl
index 59af1f9..07d4254 100644
--- a/CodeWalker.Shaders/LightVS.hlsl
+++ b/CodeWalker.Shaders/LightVS.hlsl
@@ -1,28 +1,10 @@
#include "Common.hlsli"
-//currently unused - TODO: implement individual HD lights here
-
-
-
-struct LODLight
-{
- float3 Position;
- uint Colour;
- float3 Direction;
- uint TimeAndStateFlags;
- float4 TangentX;
- float4 TangentY;
- float Falloff;
- float FalloffExponent;
- float InnerAngle; //for cone
- float OuterAngleOrCapExt; //outer angle for cone, cap extent for capsule
-};
struct VS_Output
{
float4 Pos : SV_POSITION;
float4 Screen : TEXCOORD0;
- uint IID : SV_INSTANCEID;
};
@@ -36,44 +18,51 @@ cbuffer VSLightVars : register(b0)
uint Pad1;
}
-StructuredBuffer LODLights : register(t0);
+cbuffer VSLightInstVars : register(b1)
+{
+ float3 InstPosition;//camera relative
+ float InstIntensity;
+ float3 InstColour;
+ float InstFalloff;
+ float3 InstDirection;
+ float InstFalloffExponent;
+ float3 InstTangentX;
+ float InstConeInnerAngle;
+ float3 InstTangentY;
+ float InstConeOuterAngle;
+ float3 InstCapsuleExtent;
+ uint InstType;
+ float3 InstCullingPlaneNormal;
+ float InstCullingPlaneOffset;
+}
VS_Output main(float4 ipos : POSITION, uint iid : SV_InstanceID)
{
float3 opos = 0;
- if (LightType > 0)
+
+ float extent = InstFalloff;
+ if (InstType == 1)//point (sphere)
{
- LODLight lodlight = LODLights[iid];
- float extent = lodlight.Falloff;
-
- if (LightType == 1)//point (sphere)
- {
- opos = ipos.xyz * extent;
- }
- else if (LightType == 2)//spot (cone)
- {
- float arads = lodlight.OuterAngleOrCapExt * 0.01745329 * 0.5; // deg -> rad
- float3 cpos = ipos.xyz * (tan(arads) * extent);
- cpos.y += ipos.w * extent;
- opos = (cpos.x * lodlight.TangentX.xyz) + (cpos.y * lodlight.Direction.xyz) + (cpos.z * lodlight.TangentY.xyz);
- }
- else if (LightType == 4)//capsule
- {
- float3 cpos = ipos.xyz * extent;
- cpos.y += (ipos.w*2-1) * lodlight.OuterAngleOrCapExt * 0.1;
- opos = (cpos.x * lodlight.TangentX.xyz) + (cpos.y * lodlight.Direction.xyz) + (cpos.z * lodlight.TangentY.xyz);
- }
- opos += (lodlight.Position - CameraPos.xyz);
+ opos = ipos.xyz * extent;
}
- else
+ else if (InstType == 2)//spot (cone)
{
- opos = ipos.xyz;
+ float arads = InstConeOuterAngle * 0.01745329 * 0.5; // deg -> rad
+ float3 cpos = ipos.xyz * (tan(arads) * extent);
+ cpos.y += ipos.w * extent;
+ opos = (cpos.x * InstTangentX) + (cpos.y * InstDirection) + (cpos.z * InstTangentY);
}
- float4 spos = mul(float4(opos, 1), ViewProj);
+ else if (InstType == 4)//capsule
+ {
+ float3 cpos = ipos.xyz * extent;
+ cpos += InstCapsuleExtent * (ipos.w * 2 - 1) * 0.1;
+ opos = (cpos.x * InstTangentX.xyz) + (cpos.y * InstDirection.xyz) + (cpos.z * InstTangentY.xyz);
+ }
+
+ float4 spos = mul(float4(opos + InstPosition, 1), ViewProj);
VS_Output output;
output.Pos = spos;
output.Screen = spos;
- output.IID = iid;
return output;
}
diff --git a/Rendering/Renderable.cs b/Rendering/Renderable.cs
index 5358b9a..4a360be 100644
--- a/Rendering/Renderable.cs
+++ b/Rendering/Renderable.cs
@@ -26,12 +26,19 @@ namespace CodeWalker.Rendering
public Quaternion Orientation;
public Vector3 Scale;
public uint TintPaletteIndex;
+ public bool CastShadow;
}
public struct RenderableGeometryInst
{
public RenderableGeometry Geom;
public RenderableInst Inst;
}
+ public struct RenderableLightInst
+ {
+ public RenderableLight Light;
+ public Vector3 EntityPosition;
+ public Quaternion EntityRotation;
+ }
public struct RenderableBoundCompositeInst
{
@@ -83,6 +90,10 @@ namespace CodeWalker.Rendering
public ClothInstance Cloth;
+ public RenderableLight[] Lights;
+
+
+
public override void Init(DrawableBase drawable)
{
Key = drawable;
@@ -146,6 +157,8 @@ namespace CodeWalker.Rendering
+ var fd = drawable as FragDrawable;
+ var dd = drawable as Drawable;
bool hasskeleton = false;
@@ -164,7 +177,6 @@ namespace CodeWalker.Rendering
modeltransforms = skeleton.Transformations;
//for fragments, get the default pose from the root fragment...
- var fd = drawable as FragDrawable;
if (fd != null)
{
var frag = fd.OwnerFragment;
@@ -306,6 +318,23 @@ namespace CodeWalker.Rendering
+ var lights = dd?.LightAttributes?.data_items;
+ if ((lights == null) && (fd != null) && (fd?.OwnerFragment?.Drawable == fd))
+ {
+ lights = fd.OwnerFragment.LightAttributes?.data_items;
+ }
+ if (lights != null)
+ {
+ var rlights = new RenderableLight[lights.Length];
+ for (int i = 0; i < lights.Length; i++)
+ {
+ var rlight = new RenderableLight();
+ rlight.Owner = this;
+ rlight.Init(ref lights[i]);
+ rlights[i] = rlight;
+ }
+ Lights = rlights;
+ }
UpdateBoneTransforms();
@@ -1300,6 +1329,47 @@ namespace CodeWalker.Rendering
}
}
+ public class RenderableLight
+ {
+ public Renderable Owner;
+ public Vector3 Position;
+ public Vector3 Colour;
+ public Vector3 Direction;
+ public Vector3 TangentX;
+ public Vector3 TangentY;
+ public LightType Type;
+ public float Intensity;
+ public float Falloff;
+ public float FalloffExponent;
+ public float ConeInnerAngle;
+ public float ConeOuterAngle;
+ public Vector3 CapsuleExtent;
+ public Vector3 CullingPlaneNormal;
+ public float CullingPlaneOffset;
+ public uint TimeFlags;
+ public MetaHash TextureHash;
+
+ public void Init(ref LightAttributes_s l)
+ {
+ Position = l.Position;
+ Colour = new Vector3(l.ColorR, l.ColorG, l.ColorB) * ((l.Intensity * 5.0f) / 255.0f);
+ Direction = l.Direction;
+ TangentX = l.Tangent;
+ TangentY = Vector3.Cross(l.Direction, l.Tangent);
+ Type = l.Type;
+ Intensity = l.Intensity;
+ Falloff = l.Falloff;
+ FalloffExponent = l.FalloffExponent;
+ ConeInnerAngle = l.ConeInnerAngle;
+ ConeOuterAngle = l.ConeOuterAngle;
+ CapsuleExtent = l.Extent;
+ CullingPlaneNormal = l.CullingPlaneNormal;
+ CullingPlaneOffset = l.CullingPlaneOffset;
+ TimeFlags = l.TimeFlags;
+ TextureHash = l.ProjectedTextureHash;
+ }
+ }
+
public class RenderableInstanceBatch : RenderableCacheItem
{
diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs
index af04ba5..4ff5c02 100644
--- a/Rendering/Renderer.cs
+++ b/Rendering/Renderer.cs
@@ -102,7 +102,7 @@ namespace CodeWalker.Rendering
public bool renderchildents = false;//when rendering single ymap, render root only or not...
public bool renderentities = true;
public bool rendergrass = true;
- public bool renderlights = false; //render individual drawable lights (TODO!)
+ public bool renderlights = true; //render individual drawable lights
public bool renderlodlights = true; //render LOD lights from ymaps
public bool renderdistlodlights = true; //render distant lod lights (coronas)
public bool rendercars = false;
@@ -1292,6 +1292,7 @@ namespace CodeWalker.Rendering
rinst.Orientation = Quaternion.Identity;
rinst.Scale = Vector3.One;
rinst.TintPaletteIndex = 0;
+ rinst.CastShadow = false;
rinst.Renderable = sdrnd;
shader.SetShader(context);
shader.SetInputLayout(context, VertexType.PTT);
@@ -1383,6 +1384,7 @@ namespace CodeWalker.Rendering
rinst.Orientation = Quaternion.Identity;
rinst.Scale = frag.Scale;// Vector3.One;
rinst.TintPaletteIndex = 0;
+ rinst.CastShadow = false;
rinst.Renderable = rnd;
shader.SetEntityVars(context, ref rinst);
@@ -2599,6 +2601,9 @@ namespace CodeWalker.Rendering
Vector3 bscen = (arche != null) ? arche.BSCenter : rndbl.Key.BoundingCenter;
float radius = (arche != null) ? arche.BSRadius : rndbl.Key.BoundingSphereRadius;
float distance = 0;// (camrel + bscen).Length();
+ bool interiorent = false;
+ bool castshadow = true;
+
if (entity != null)
{
position = entity.Position;
@@ -2610,6 +2615,8 @@ namespace CodeWalker.Rendering
bscen = entity.BSCenter;
camrel += position;
distance = entity.Distance;
+ castshadow = (entity.MloParent == null);//don't cast sun/moon shadows if this is an interior entity - optimisation!
+ interiorent = (entity.MloParent != null);
}
else
{
@@ -2663,8 +2670,22 @@ namespace CodeWalker.Rendering
RenderSkeleton(rndbl, entity);
}
+
+ if (renderlights && shaders.deferred && (rndbl.Lights != null) && interiorent)//only interior ents making lights! todo: fix LOD lights
+ {
+ var linst = new RenderableLightInst();
+ for (int i = 0; i < rndbl.Lights.Length; i++)
+ {
+ linst.EntityPosition = position;
+ linst.EntityRotation = orientation;
+ linst.Light = rndbl.Lights[i];
+ shaders.Enqueue(ref linst);
+ }
+ }
+
+
bool retval = true;// false;
- if (rndbl.IsLoaded && (rndbl.AllTexturesLoaded || !waitforchildrentoload))
+ if ((rndbl.AllTexturesLoaded || !waitforchildrentoload))
{
RenderableGeometryInst rginst = new RenderableGeometryInst();
rginst.Inst.Renderable = rndbl;
@@ -2678,6 +2699,7 @@ namespace CodeWalker.Rendering
rginst.Inst.BSCenter = bscen;
rginst.Inst.Radius = radius;
rginst.Inst.Distance = distance;
+ rginst.Inst.CastShadow = castshadow;
RenderableModel[] models = isselected ? rndbl.AllModels : rndbl.HDModels;
diff --git a/Rendering/ShaderManager.cs b/Rendering/ShaderManager.cs
index 0d4b348..34394df 100644
--- a/Rendering/ShaderManager.cs
+++ b/Rendering/ShaderManager.cs
@@ -71,6 +71,7 @@ namespace CodeWalker.Rendering
public List RenderBuckets = new List();
public List RenderBoundGeoms = new List();
public List RenderInstBatches = new List();
+ public List RenderLights = new List();
public List RenderLODLights = new List();
public List RenderDistLODLights = new List();
public List RenderPathBatches = new List();
@@ -326,6 +327,7 @@ namespace CodeWalker.Rendering
RenderBoundGeoms.Clear();
RenderInstBatches.Clear();
+ RenderLights.Clear();
RenderLODLights.Clear();
RenderDistLODLights.Clear();
RenderPathBatches.Clear();
@@ -583,6 +585,14 @@ namespace CodeWalker.Rendering
context.OutputMerger.DepthStencilState = dsDisableWriteRev;//only render parts behind or at surface
DefScene.RenderLights(context, camera, RenderLODLights);
}
+
+ if (RenderLights.Count > 0)
+ {
+ context.Rasterizer.State = rsSolid;
+ context.OutputMerger.BlendState = bsAdd; //additive blend for lights...
+ context.OutputMerger.DepthStencilState = dsDisableWriteRev;//only render parts behind or at surface
+ DefScene.RenderLights(context, camera, RenderLights);
+ }
}
Basic.Deferred = false;
@@ -682,10 +692,13 @@ namespace CodeWalker.Rendering
for (int g = 0; g < sbgeoms.Count; g++)
{
var sbgeom = sbgeoms[g];
- float idist = sbgeom.Inst.Distance - sbgeom.Inst.Radius;
- if (idist <= maxdist)
+ if (sbgeom.Inst.CastShadow)
{
- shadowcasters.Add(sbgeom);
+ float idist = sbgeom.Inst.Distance - sbgeom.Inst.Radius;
+ if (idist <= maxdist)
+ {
+ shadowcasters.Add(sbgeom);
+ }
}
}
}
@@ -853,6 +866,10 @@ namespace CodeWalker.Rendering
batch.Geometries.Add(geom);
}
+ public void Enqueue(ref RenderableLightInst light)
+ {
+ RenderLights.Add(light);
+ }
public void Enqueue(ref RenderableBoundGeometryInst geom)
{
RenderBoundGeoms.Add(geom);
diff --git a/Rendering/Shaders/DeferredScene.cs b/Rendering/Shaders/DeferredScene.cs
index 92b8b3e..879f089 100644
--- a/Rendering/Shaders/DeferredScene.cs
+++ b/Rendering/Shaders/DeferredScene.cs
@@ -40,6 +40,23 @@ namespace CodeWalker.Rendering
public uint SampleCount;//for MSAA
public float SampleMult;//for MSAA
}
+ public struct DeferredLightInstVars
+ {
+ public Vector3 InstPosition;
+ public float InstIntensity;
+ public Vector3 InstColour;
+ public float InstFalloff;
+ public Vector3 InstDirection;
+ public float InstFalloffExponent;
+ public Vector3 InstTangentX;
+ public float InstConeInnerAngle;
+ public Vector3 InstTangentY;
+ public float InstConeOuterAngle;
+ public Vector3 InstCapsuleExtent;
+ public uint InstType;
+ public Vector3 InstCullingPlaneNormal;
+ public float InstCullingPlaneOffset;
+ }
public struct DeferredSSAAPSVars
{
@@ -70,6 +87,9 @@ namespace CodeWalker.Rendering
VertexShader LodLightVS;
PixelShader LodLightPS;
PixelShader LodLightMSPS;
+ VertexShader LightVS;
+ PixelShader LightPS;
+ PixelShader LightMSPS;
UnitCone LightCone;
UnitSphere LightSphere;
UnitCapsule LightCapsule;
@@ -79,6 +99,7 @@ namespace CodeWalker.Rendering
GpuVarsBuffer LightVSVars;
GpuVarsBuffer LightPSVars;
+ GpuVarsBuffer LightInstVars;
@@ -113,6 +134,9 @@ namespace CodeWalker.Rendering
byte[] bLodLightVS = File.ReadAllBytes("Shaders\\LodLightsVS.cso");
byte[] bLodLightPS = File.ReadAllBytes("Shaders\\LodLightsPS.cso");
byte[] bLodLightMSPS = File.ReadAllBytes("Shaders\\LodLightsPS_MS.cso");
+ byte[] bLightVS = File.ReadAllBytes("Shaders\\LightVS.cso");
+ byte[] bLightPS = File.ReadAllBytes("Shaders\\LightPS.cso");
+ byte[] bLightMSPS = File.ReadAllBytes("Shaders\\LightPS_MS.cso");
byte[] bFinalVS = File.ReadAllBytes("Shaders\\PPFinalPassVS.cso");
byte[] bSSAAPS = File.ReadAllBytes("Shaders\\PPSSAAPS.cso");
@@ -120,12 +144,15 @@ namespace CodeWalker.Rendering
DirLightPS = new PixelShader(device, bDirLightPS);
LodLightVS = new VertexShader(device, bLodLightVS);
LodLightPS = new PixelShader(device, bLodLightPS);
+ LightVS = new VertexShader(device, bLightVS);
+ LightPS = new PixelShader(device, bLightPS);
try
{
//error could happen here if the device isn't supporting feature level 10.1
DirLightMSPS = new PixelShader(device, bDirLightMSPS);
LodLightMSPS = new PixelShader(device, bLodLightMSPS);
+ LightMSPS = new PixelShader(device, bLightMSPS);
}
catch
{
@@ -145,6 +172,7 @@ namespace CodeWalker.Rendering
LightVSVars = new GpuVarsBuffer(device);
LightPSVars = new GpuVarsBuffer(device);
+ LightInstVars = new GpuVarsBuffer(device);
FinalVS = new VertexShader(device, bFinalVS);
@@ -190,6 +218,11 @@ namespace CodeWalker.Rendering
LightPSVars.Dispose();
LightPSVars = null;
}
+ if (LightInstVars != null)
+ {
+ LightInstVars.Dispose();
+ LightInstVars = null;
+ }
if (LightQuadLayout != null)
{
LightQuadLayout.Dispose();
@@ -245,6 +278,21 @@ namespace CodeWalker.Rendering
LodLightVS.Dispose();
LodLightVS = null;
}
+ if (LightPS != null)
+ {
+ LightPS.Dispose();
+ LightPS = null;
+ }
+ if (LightMSPS != null)
+ {
+ LightMSPS.Dispose();
+ LightMSPS = null;
+ }
+ if (LightVS != null)
+ {
+ LightVS.Dispose();
+ LightVS = null;
+ }
if (SSAAPSVars != null)
{
SSAAPSVars.Dispose();
@@ -376,7 +424,6 @@ namespace CodeWalker.Rendering
context.PixelShader.SetSamplers(0, null, null);
}
-
public void RenderLights(DeviceContext context, Camera camera, List lodlights)
{
//instanced rendering of all other lights, using appropriate shapes
@@ -456,8 +503,90 @@ namespace CodeWalker.Rendering
context.PixelShader.SetSamplers(0, null, null);
}
+ public void RenderLights(DeviceContext context, Camera camera, List lights)
+ {
+ //instanced rendering of all other lights, using appropriate shapes
+ //blend mode: additive
+ var ps = (MSAASampleCount > 1) ? LightMSPS : LightPS;
+
+ context.VertexShader.Set(LightVS);
+ context.PixelShader.Set(ps);
+
+ LightVSVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
+ LightVSVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f);
+ LightVSVars.Vars.LightType = 0;
+ LightVSVars.Vars.IsLOD = 0;
+ LightVSVars.Vars.Pad0 = 0;
+ LightVSVars.Vars.Pad1 = 0;
+ LightVSVars.Update(context);
+ LightVSVars.SetVSCBuffer(context, 0);
+
+ LightPSVars.Vars.ViewProjInv = Matrix.Transpose(camera.ViewProjInvMatrix);
+ LightPSVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f);
+ LightPSVars.Vars.EnableShadows = 0;
+ LightPSVars.Vars.RenderMode = 0;
+ LightPSVars.Vars.RenderModeIndex = 1;
+ LightPSVars.Vars.RenderSamplerCoord = 0;
+ LightPSVars.Vars.LightType = 0;
+ LightPSVars.Vars.IsLOD = 0;
+ LightPSVars.Vars.SampleCount = (uint)MSAASampleCount;
+ LightPSVars.Vars.SampleMult = 1.0f / MSAASampleCount;
+ LightPSVars.Update(context);
+ LightPSVars.SetPSCBuffer(context, 0);
+
+ context.PixelShader.SetShaderResources(0, GBuffers.DepthSRV);
+ context.PixelShader.SetShaderResources(2, GBuffers.SRVs);
+
+
+ for (int i = 0; i < lights.Count; i++)
+ {
+ var li = lights[i];
+ var rl = li.Light;
+
+ LightInstVars.Vars.InstPosition = li.EntityPosition + li.EntityRotation.Multiply(rl.Position) - camera.Position;
+ LightInstVars.Vars.InstDirection = li.EntityRotation.Multiply(rl.Direction);
+ LightInstVars.Vars.InstTangentX = li.EntityRotation.Multiply(rl.TangentX);
+ LightInstVars.Vars.InstTangentY = li.EntityRotation.Multiply(rl.TangentY);
+ LightInstVars.Vars.InstCapsuleExtent = li.EntityRotation.Multiply(rl.CapsuleExtent);
+ LightInstVars.Vars.InstCullingPlaneNormal = li.EntityRotation.Multiply(rl.CullingPlaneNormal);
+ LightInstVars.Vars.InstColour = rl.Colour;
+ LightInstVars.Vars.InstIntensity = rl.Intensity;
+ LightInstVars.Vars.InstFalloff = rl.Falloff;
+ LightInstVars.Vars.InstFalloffExponent = rl.FalloffExponent;
+ LightInstVars.Vars.InstConeInnerAngle = rl.ConeInnerAngle;
+ LightInstVars.Vars.InstConeOuterAngle = rl.ConeOuterAngle;
+ LightInstVars.Vars.InstType = (uint)rl.Type;
+ LightInstVars.Vars.InstCullingPlaneOffset = rl.CullingPlaneOffset;
+ LightInstVars.Update(context);
+ LightInstVars.SetVSCBuffer(context, 1);
+ LightInstVars.SetPSCBuffer(context, 2);
+
+ switch (rl.Type)
+ {
+ case LightType.Point:
+ LightSphere.Draw(context);
+ break;
+ case LightType.Spot:
+ LightCone.Draw(context);
+ break;
+ case LightType.Capsule:
+ LightCapsule.Draw(context);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+
+ context.VertexShader.Set(null);
+ context.PixelShader.Set(null);
+ context.PixelShader.SetShaderResources(0, null, null, null);
+ context.PixelShader.SetSamplers(0, null, null);
+ }
+
public void SSAAPass(DeviceContext context)
{
diff --git a/Shaders/LightPS.cso b/Shaders/LightPS.cso
index b92ff1a..eb4c2b7 100644
Binary files a/Shaders/LightPS.cso and b/Shaders/LightPS.cso differ
diff --git a/Shaders/LightPS_MS.cso b/Shaders/LightPS_MS.cso
new file mode 100644
index 0000000..0877aac
Binary files /dev/null and b/Shaders/LightPS_MS.cso differ
diff --git a/Shaders/LightVS.cso b/Shaders/LightVS.cso
index eea120a..6fdaf6d 100644
Binary files a/Shaders/LightVS.cso and b/Shaders/LightVS.cso differ
diff --git a/Shaders/LodLightsPS.cso b/Shaders/LodLightsPS.cso
index b95822b..5bfe0f6 100644
Binary files a/Shaders/LodLightsPS.cso and b/Shaders/LodLightsPS.cso differ
diff --git a/Shaders/LodLightsPS_MS.cso b/Shaders/LodLightsPS_MS.cso
index 5e54009..ff6ed20 100644
Binary files a/Shaders/LodLightsPS_MS.cso and b/Shaders/LodLightsPS_MS.cso differ