mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2026-05-16 16:54:50 +08:00
HD lights rendering in interiors
This commit is contained in:
+71
-1
@@ -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<YmapGrassInstanceBatch>
|
||||
{
|
||||
|
||||
+24
-2
@@ -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;
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace CodeWalker.Rendering
|
||||
public List<ShaderRenderBucket> RenderBuckets = new List<ShaderRenderBucket>();
|
||||
public List<RenderableBoundGeometryInst> RenderBoundGeoms = new List<RenderableBoundGeometryInst>();
|
||||
public List<RenderableInstanceBatchInst> RenderInstBatches = new List<RenderableInstanceBatchInst>();
|
||||
public List<RenderableLightInst> RenderLights = new List<RenderableLightInst>();
|
||||
public List<RenderableLODLights> RenderLODLights = new List<RenderableLODLights>();
|
||||
public List<RenderableDistantLODLights> RenderDistLODLights = new List<RenderableDistantLODLights>();
|
||||
public List<RenderablePathBatch> RenderPathBatches = new List<RenderablePathBatch>();
|
||||
@@ -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);
|
||||
|
||||
@@ -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<DeferredLightVSVars> LightVSVars;
|
||||
GpuVarsBuffer<DeferredLightPSVars> LightPSVars;
|
||||
GpuVarsBuffer<DeferredLightInstVars> 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<DeferredLightVSVars>(device);
|
||||
LightPSVars = new GpuVarsBuffer<DeferredLightPSVars>(device);
|
||||
LightInstVars = new GpuVarsBuffer<DeferredLightInstVars>(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<RenderableLODLights> 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<RenderableLightInst> 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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user