Deferred shading

This commit is contained in:
dexy
2019-12-04 00:52:22 +11:00
Unverified
parent 755477590d
commit 9a53c2147b
60 changed files with 2724 additions and 509 deletions
+132 -22
View File
@@ -1355,6 +1355,136 @@ namespace CodeWalker.Rendering
}
}
public class RenderableLODLights : RenderableCacheItem<YmapFile>
{
public struct LODLight
{
public Vector3 Position;
public uint Colour;
public Vector3 Direction;
public uint TimeAndStateFlags;
public Vector4 TangentX;
public Vector4 TangentY;
public float Falloff;
public float FalloffExponent;
public float InnerAngle;//for cone
public float OuterAngleOrCapExt;//outer angle for cone, cap extent for capsule
}
public LODLight[] Points;
public LODLight[] Spots;
public LODLight[] Caps;
public GpuSBuffer<LODLight> PointsBuffer { get; set; }
public GpuSBuffer<LODLight> SpotsBuffer { get; set; }
public GpuSBuffer<LODLight> CapsBuffer { get; set; }
public override void Init(YmapFile key)
{
Key = key;
var ll = key.LODLights;
var dll = key.Parent?.DistantLODLights;
if (ll == null) return;
if (dll == null) return;
var n = dll.positions?.Length ?? 0;
n = Math.Min(n, dll.colours?.Length ?? 0);
n = Math.Min(n, ll.direction?.Length ?? 0);
n = Math.Min(n, ll.falloff?.Length ?? 0);
n = Math.Min(n, ll.falloffExponent?.Length ?? 0);
n = Math.Min(n, ll.timeAndStateFlags?.Length ?? 0);
n = Math.Min(n, ll.hash?.Length ?? 0);
n = Math.Min(n, ll.coneInnerAngle?.Length ?? 0);
n = Math.Min(n, ll.coneOuterAngleOrCapExt?.Length ?? 0);
n = Math.Min(n, ll.coronaIntensity?.Length ?? 0);
if (n <= 0)
{ return; }
var points = new List<LODLight>();
var spots = new List<LODLight>();
var caps = new List<LODLight>();
for (int i = 0; i < n; i++)
{
var light = new LODLight();
light.Position = dll.positions[i].ToVector3();
light.Colour = dll.colours[i];
light.Direction = ll.direction[i].ToVector3();
light.TimeAndStateFlags = ll.timeAndStateFlags[i];
light.TangentX = new Vector4(Vector3.Normalize(light.Direction.GetPerpVec()), 0.0f);
light.TangentY = new Vector4(Vector3.Cross(light.Direction, light.TangentX.XYZ()), 0.0f);
light.Falloff = ll.falloff[i];
light.FalloffExponent = ll.falloffExponent[i];
light.InnerAngle = ll.coneInnerAngle[i];
light.OuterAngleOrCapExt = ll.coneOuterAngleOrCapExt[i];
var type = (LightType)((light.TimeAndStateFlags >> 26) & 7);
switch (type)
{
case LightType.Point:
points.Add(light);
break;
case LightType.Spot:
spots.Add(light);
break;
case LightType.Capsule:
caps.Add(light);
break;
default: break;//just checking...
}
}
Points = points.ToArray();
Spots = spots.ToArray();
Caps = caps.ToArray();
}
public override void Load(Device device)
{
if ((Points != null) && (Points.Length > 0))
{
PointsBuffer = new GpuSBuffer<LODLight>(device, Points);
}
if ((Spots != null) && (Spots.Length > 0))
{
SpotsBuffer = new GpuSBuffer<LODLight>(device, Spots);
}
if ((Caps != null) && (Caps.Length > 0))
{
CapsBuffer = new GpuSBuffer<LODLight>(device, Caps);
}
IsLoaded = true;
}
public override void Unload()
{
IsLoaded = false;
if (PointsBuffer != null)
{
PointsBuffer.Dispose();
PointsBuffer = null;
}
if (SpotsBuffer != null)
{
SpotsBuffer.Dispose();
SpotsBuffer = null;
}
if (CapsBuffer != null)
{
CapsBuffer.Dispose();
CapsBuffer = null;
}
}
}
public class RenderableDistantLODLights : RenderableCacheItem<YmapDistantLODLights>
{
public struct DistLODLight
@@ -1815,7 +1945,7 @@ namespace CodeWalker.Rendering
p2 = bgeom.GetVertex(bcap.capsuleIndex2);
a1 = p2 - p1;
n1 = Vector3.Normalize(a1);
p3 = Vector3.Normalize(GetPerpVec(n1));
p3 = Vector3.Normalize(n1.GetPerpVec());
//p4 = Vector3.Normalize(Vector3.Cross(n1, p3));
Quaternion q1 = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, p3, n1));
rcapsules[curcapsule].Point1 = p1;
@@ -1848,7 +1978,7 @@ namespace CodeWalker.Rendering
p2 = bgeom.GetVertex(pcyl.cylinderIndex2);
a1 = p2 - p1;
n1 = Vector3.Normalize(a1);
p3 = Vector3.Normalize(GetPerpVec(n1));
p3 = Vector3.Normalize(n1.GetPerpVec());
//p4 = Vector3.Normalize(Vector3.Cross(n1, p3));
Quaternion q2 = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, p3, n1));
rcylinders[curcylinder].Point1 = p1;
@@ -1898,26 +2028,6 @@ namespace CodeWalker.Rendering
index++;
}
private Vector3 GetPerpVec(Vector3 n)
{
//make a vector perpendicular to the given one
float nx = Math.Abs(n.X);
float ny = Math.Abs(n.Y);
float nz = Math.Abs(n.Z);
if ((nx < ny) && (nx < nz))
{
return Vector3.Cross(n, Vector3.Right);
}
else if (ny < nz)
{
return Vector3.Cross(n, Vector3.Up);
}
else
{
return Vector3.Cross(n, Vector3.ForwardLH);
}
}
public void Load(Device device)
{
+15 -2
View File
@@ -29,8 +29,9 @@ namespace CodeWalker.Rendering
return renderables.CacheUse
+ textures.CacheUse
+ boundcomps.CacheUse
+ instbatches.CacheUse
+ distlodlights.CacheUse
+ instbatches.CacheUse
+ lodlights.CacheUse
+ distlodlights.CacheUse
+ pathbatches.CacheUse
+ waterquads.CacheUse;
}
@@ -43,6 +44,7 @@ namespace CodeWalker.Rendering
+ textures.CurrentLoadedCount
+ boundcomps.CurrentLoadedCount
+ instbatches.CurrentLoadedCount
+ lodlights.CurrentLoadedCount
+ distlodlights.CurrentLoadedCount
+ pathbatches.CurrentLoadedCount
+ waterquads.CurrentLoadedCount;
@@ -56,6 +58,7 @@ namespace CodeWalker.Rendering
+ textures.QueueLength
+ boundcomps.QueueLength
+ instbatches.QueueLength
+ lodlights.QueueLength
+ distlodlights.QueueLength
+ pathbatches.QueueLength
+ waterquads.QueueLength;
@@ -95,6 +98,7 @@ namespace CodeWalker.Rendering
private RenderableCacheLookup<Texture, RenderableTexture> textures = new RenderableCacheLookup<Texture, RenderableTexture>(Settings.Default.GPUTextureCacheSize, Settings.Default.GPUCacheTime);
private RenderableCacheLookup<BoundComposite, RenderableBoundComposite> boundcomps = new RenderableCacheLookup<BoundComposite, RenderableBoundComposite>(Settings.Default.GPUBoundCompCacheSize, Settings.Default.GPUCacheTime);
private RenderableCacheLookup<YmapGrassInstanceBatch, RenderableInstanceBatch> instbatches = new RenderableCacheLookup<YmapGrassInstanceBatch, RenderableInstanceBatch>(67108864, Settings.Default.GPUCacheTime); //64MB - todo: make this a setting
private RenderableCacheLookup<YmapFile, RenderableLODLights> lodlights = new RenderableCacheLookup<YmapFile, RenderableLODLights>(33554432, Settings.Default.GPUCacheTime); //32MB - todo: make this a setting
private RenderableCacheLookup<YmapDistantLODLights, RenderableDistantLODLights> distlodlights = new RenderableCacheLookup<YmapDistantLODLights, RenderableDistantLODLights>(33554432, Settings.Default.GPUCacheTime); //32MB - todo: make this a setting
private RenderableCacheLookup<BasePathData, RenderablePathBatch> pathbatches = new RenderableCacheLookup<BasePathData, RenderablePathBatch>(536870912 /*33554432*/, Settings.Default.GPUCacheTime); // 512MB /*32MB*/ - todo: make this a setting
private RenderableCacheLookup<WaterQuad, RenderableWaterQuad> waterquads = new RenderableCacheLookup<WaterQuad, RenderableWaterQuad>(4194304, Settings.Default.GPUCacheTime); //4MB - todo: make this a setting
@@ -117,6 +121,7 @@ namespace CodeWalker.Rendering
textures.Clear();
boundcomps.Clear();
instbatches.Clear();
lodlights.Clear();
distlodlights.Clear();
pathbatches.Clear();
waterquads.Clear();
@@ -134,6 +139,7 @@ namespace CodeWalker.Rendering
int texturecount = textures.LoadProc(currentDevice, MaxItemsPerLoop);
int boundcompcount = boundcomps.LoadProc(currentDevice, MaxItemsPerLoop);
int instbatchcount = instbatches.LoadProc(currentDevice, MaxItemsPerLoop);
int lodlightcount = lodlights.LoadProc(currentDevice, MaxItemsPerLoop);
int distlodlightcount = distlodlights.LoadProc(currentDevice, MaxItemsPerLoop);
int pathbatchcount = pathbatches.LoadProc(currentDevice, MaxItemsPerLoop);
int waterquadcount = waterquads.LoadProc(currentDevice, MaxItemsPerLoop);
@@ -144,6 +150,7 @@ namespace CodeWalker.Rendering
(texturecount >= MaxItemsPerLoop) ||
(boundcompcount >= MaxItemsPerLoop) ||
(instbatchcount >= MaxItemsPerLoop) ||
(lodlightcount >= MaxItemsPerLoop) ||
(distlodlightcount >= MaxItemsPerLoop) ||
(pathbatchcount >= MaxItemsPerLoop) ||
(waterquadcount >= MaxItemsPerLoop);
@@ -161,6 +168,7 @@ namespace CodeWalker.Rendering
textures.UnloadProc();
boundcomps.UnloadProc();
instbatches.UnloadProc();
lodlights.UnloadProc();
distlodlights.UnloadProc();
pathbatches.UnloadProc();
waterquads.UnloadProc();
@@ -182,6 +190,7 @@ namespace CodeWalker.Rendering
textures.RenderThreadSync();
boundcomps.RenderThreadSync();
instbatches.RenderThreadSync();
lodlights.RenderThreadSync();
distlodlights.RenderThreadSync();
pathbatches.RenderThreadSync();
waterquads.RenderThreadSync();
@@ -207,6 +216,10 @@ namespace CodeWalker.Rendering
{
return distlodlights.Get(lights);
}
public RenderableLODLights GetRenderableLODLights(YmapFile ymap)
{
return lodlights.Get(ymap);
}
public RenderablePathBatch GetRenderablePathBatch(BasePathData pathdata)
{
return pathbatches.Get(pathdata);
+35 -4
View File
@@ -102,7 +102,9 @@ 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 renderdistlodlights = true;
public bool renderlights = false; //render individual drawable lights (TODO!)
public bool renderlodlights = true; //render LOD lights from ymaps
public bool renderdistlodlights = true; //render distant lod lights (coronas)
public bool rendercars = false;
public bool rendercollisionmeshes = Settings.Default.ShowCollisionMeshes;
@@ -1575,10 +1577,14 @@ namespace CodeWalker.Rendering
for (int y = 0; y < VisibleYmaps.Count; y++)
{
var ymap = VisibleYmaps[y];
YmapFile pymap = ymap.Parent;
if ((pymap == null) && (ymap._CMapData.parent != 0))
{
renderworldVisibleYmapDict.TryGetValue(ymap._CMapData.parent, out pymap);
ymap.Parent = pymap;
}
if (ymap.RootEntities != null)
{
YmapFile pymap;
renderworldVisibleYmapDict.TryGetValue(ymap._CMapData.parent, out pymap);
for (int i = 0; i < ymap.RootEntities.Length; i++)
{
var ent = ymap.RootEntities[i];
@@ -1699,6 +1705,17 @@ namespace CodeWalker.Rendering
}
}
}
if (renderlodlights && shaders.deferred)
{
for (int y = 0; y < VisibleYmaps.Count; y++)
{
var ymap = VisibleYmaps[y];
if (ymap.LODLights != null)
{
RenderYmapLODLights(ymap);
}
}
}
}
private bool RenderWorldYmapIsVisible(YmapFile ymap)
{
@@ -2185,6 +2202,20 @@ namespace CodeWalker.Rendering
}
private void RenderYmapLODLights(YmapFile ymap)
{
if (ymap.LODLights == null) return;
if (ymap.Parent?.DistantLODLights == null) return; //need to get lodlights positions from parent (distlodlights)
RenderableLODLights lights = renderableCache.GetRenderableLODLights(ymap);
if (!lights.IsLoaded) return;
shaders.Enqueue(lights);
}
private void RenderYmapDistantLODLights(YmapFile ymap)
{
//enqueue ymap DistantLODLights instance batch for rendering
@@ -2211,7 +2242,7 @@ namespace CodeWalker.Rendering
Texture lighttex = null;
if ((graphicsytd != null) && (graphicsytd.Loaded) && (graphicsytd.TextureDict != null) && (graphicsytd.TextureDict.Dict != null))
{
graphicsytd.TextureDict.Dict.TryGetValue(texhash, out lighttex); //starfield hash
graphicsytd.TextureDict.Dict.TryGetValue(texhash, out lighttex);
}
if (lighttex == null) return;
+110 -18
View File
@@ -32,9 +32,11 @@ namespace CodeWalker.Rendering
DepthStencilState dsDisableAll;
DepthStencilState dsDisableComp;
DepthStencilState dsDisableWrite;
DepthStencilState dsDisableWriteRev;
public DeferredScene DefScene { get; set; }
public PostProcessor HDR { get; set; }
public BasicShader Basic { get; set; }
public CableShader Cable { get; set; }
@@ -57,6 +59,7 @@ namespace CodeWalker.Rendering
List<ShaderBatch> shadowbatches = new List<ShaderBatch>();
int shadowcastercount = 0; //total casters rendered
public bool deferred = Settings.Default.Deferred;
public bool hdr = Settings.Default.HDR;
public float hdrLumBlendSpeed = 1.0f;
int Width;
@@ -68,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<RenderableLODLights> RenderLODLights = new List<RenderableLODLights>();
public List<RenderableDistantLODLights> RenderDistLODLights = new List<RenderableDistantLODLights>();
public List<RenderablePathBatch> RenderPathBatches = new List<RenderablePathBatch>();
public List<RenderableWaterQuad> RenderWaterQuads = new List<RenderableWaterQuad>();
@@ -94,6 +98,10 @@ namespace CodeWalker.Rendering
get
{
long u = 0;
if (DefScene != null)
{
u += DefScene.VramUsage;
}
if (HDR != null)
{
u += HDR.VramUsage;
@@ -163,6 +171,9 @@ namespace CodeWalker.Rendering
bsd.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;
bsd.RenderTarget[0].SourceAlphaBlend = BlendOption.Zero;
bsd.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha;
bsd.RenderTarget[1] = bsd.RenderTarget[0];
bsd.RenderTarget[2] = bsd.RenderTarget[0];
bsd.RenderTarget[3] = bsd.RenderTarget[0];
bsDefault = new BlendState(device, bsd);
bsd.AlphaToCoverageEnable = true;
@@ -198,6 +209,8 @@ namespace CodeWalker.Rendering
dsEnabled = new DepthStencilState(device, dsd);
dsd.DepthWriteMask = DepthWriteMask.Zero;
dsDisableWrite = new DepthStencilState(device, dsd);
dsd.DepthComparison = Comparison.LessEqual;
dsDisableWriteRev = new DepthStencilState(device, dsd);
dsd.DepthComparison = Comparison.Always;
dsDisableComp = new DepthStencilState(device, dsd);
dsd.IsDepthEnabled = false;
@@ -212,6 +225,7 @@ namespace CodeWalker.Rendering
disposed = true;
dsEnabled.Dispose();
dsDisableWriteRev.Dispose();
dsDisableWrite.Dispose();
dsDisableComp.Dispose();
dsDisableAll.Dispose();
@@ -235,6 +249,13 @@ namespace CodeWalker.Rendering
Cable.Dispose();
Water.Dispose();
if (DefScene != null)
{
DefScene.Dispose();
DefScene = null;
}
if (HDR != null)
{
HDR.Dispose();
@@ -286,6 +307,16 @@ namespace CodeWalker.Rendering
HDR.Dispose();
HDR = null;
}
if (deferred && (DefScene == null))
{
DefScene = new DeferredScene(DXMan);
DefScene.OnWindowResize(DXMan);
}
if (!deferred && (DefScene != null))
{
DefScene.Dispose();
DefScene = null;
}
foreach (var bucket in RenderBuckets)
@@ -295,10 +326,16 @@ namespace CodeWalker.Rendering
RenderBoundGeoms.Clear();
RenderInstBatches.Clear();
RenderLODLights.Clear();
RenderDistLODLights.Clear();
RenderPathBatches.Clear();
RenderWaterQuads.Clear();
if (DefScene != null)
{
DefScene.Clear(context);
}
if (HDR != null)
{
HDR.Clear(context);
@@ -312,6 +349,12 @@ namespace CodeWalker.Rendering
Skydome.EnableHDR = hdr;
Clouds.EnableHDR = hdr;
Basic.Deferred = deferred;
Cable.Deferred = deferred;
Water.Deferred = deferred;
Terrain.Deferred = deferred;
TreesLod.Deferred = deferred;
}
@@ -384,7 +427,11 @@ namespace CodeWalker.Rendering
}
if (HDR != null)
if (DefScene != null)
{
DefScene.SetPrimary(context);
}
else if (HDR != null)
{
HDR.SetPrimary(context);
}
@@ -459,22 +506,6 @@ namespace CodeWalker.Rendering
context.OutputMerger.BlendState = bsDefault;
}
if (RenderDistLODLights.Count > 0) //LOD lights pass
{
context.Rasterizer.State = rsSolidDblSided;
context.OutputMerger.BlendState = bsAdd; //additive blend for distant lod lights...
context.OutputMerger.DepthStencilState = dsDisableWrite;
DistLights.SetShader(context);
DistLights.SetSceneVars(context, Camera, Shadowmap, GlobalLights);
for (int i = 0; i < RenderDistLODLights.Count; i++)
{
DistLights.RenderBatch(context, RenderDistLODLights[i]);
}
DistLights.UnbindResources(context);
context.OutputMerger.BlendState = bsDefault;
context.OutputMerger.DepthStencilState = dsEnabled;
}
@@ -505,6 +536,9 @@ namespace CodeWalker.Rendering
Water.UnbindResources(context);
}
//TODO: needs second gbuffer pass?
Basic.DecalMode = true;
for (int i = 0; i < RenderBuckets.Count; i++) //alphablended and glass pass
{
@@ -525,6 +559,54 @@ namespace CodeWalker.Rendering
if (DefScene != null)
{
if (HDR != null)
{
HDR.SetPrimary(context);
}
else
{
DXMan.SetDefaultRenderTarget(context);
}
DefScene.RenderLights(context, camera, Shadowmap, GlobalLights);
if (RenderLODLights.Count > 0) //LOD lights pass
{
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, RenderLODLights);
}
}
Basic.Deferred = false;
if (RenderDistLODLights.Count > 0) //distant LOD lights pass
{
context.Rasterizer.State = rsSolidDblSided;
context.OutputMerger.BlendState = bsAdd; //additive blend for distant lod lights...
context.OutputMerger.DepthStencilState = dsDisableWrite;
DistLights.SetShader(context);
DistLights.SetSceneVars(context, Camera, Shadowmap, GlobalLights);
for (int i = 0; i < RenderDistLODLights.Count; i++)
{
DistLights.RenderBatch(context, RenderDistLODLights[i]);
}
DistLights.UnbindResources(context);
context.OutputMerger.BlendState = bsDefault;
context.OutputMerger.DepthStencilState = dsEnabled;
}
if (RenderBoundGeoms.Count > 0) //collision meshes pass
{
ClearDepth(context); //draw over everything else
@@ -550,6 +632,8 @@ namespace CodeWalker.Rendering
Basic.Deferred = deferred;
RenderedGeometries = GeometryCount;
}
@@ -696,7 +780,7 @@ namespace CodeWalker.Rendering
{
Basic.RenderMode = WorldRenderMode.VertexColour;
Basic.SetShader(context);
Basic.SetSceneVars(context, Camera, Shadowmap, GlobalLights);
Basic.SetSceneVars(context, Camera, /*Shadowmap*/ null, GlobalLights);//should this be using shadows??
Basic.SetInputLayout(context, VertexType.Default);
GeometryCount += batch.Count;
@@ -764,6 +848,10 @@ namespace CodeWalker.Rendering
{
RenderInstBatches.Add(batch);
}
public void Enqueue(RenderableLODLights lights)
{
RenderLODLights.Add(lights);
}
public void Enqueue(RenderableDistantLODLights lights)
{
RenderDistLODLights.Add(lights);
@@ -880,6 +968,10 @@ namespace CodeWalker.Rendering
{
Width = w;
Height = h;
if (DefScene != null)
{
DefScene.OnWindowResize(DXMan);
}
if (HDR != null)
{
HDR.OnWindowResize(DXMan);
+6 -1
View File
@@ -145,6 +145,7 @@ namespace CodeWalker.Rendering
VertexShader basicvscapsule;
VertexShader basicvscylinder;
PixelShader basicps;
PixelShader basicpsdef;
GpuVarsBuffer<BasicShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<BasicShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<BasicShaderVSModelVars> VSModelVars;
@@ -174,6 +175,7 @@ namespace CodeWalker.Rendering
public int RenderTextureSamplerCoord = 1;
public ShaderParamNames RenderTextureSampler = ShaderParamNames.DiffuseSampler;
public bool SpecularEnable = true;
public bool Deferred = false;
Matrix3_s[] defaultBoneMatrices;
bool defaultBoneMatricesBound = false;
@@ -209,6 +211,7 @@ namespace CodeWalker.Rendering
byte[] vscapsulebytes = File.ReadAllBytes("Shaders\\BasicVS_Capsule.cso");
byte[] vscylinderbytes = File.ReadAllBytes("Shaders\\BasicVS_Cylinder.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\BasicPS.cso");
byte[] psdefbytes = File.ReadAllBytes("Shaders\\BasicPS_Deferred.cso");
basicvspnct = new VertexShader(device, vspnctbytes);
basicvspnctt = new VertexShader(device, vspncttbytes);
@@ -235,6 +238,7 @@ namespace CodeWalker.Rendering
basicvscapsule = new VertexShader(device, vscapsulebytes);
basicvscylinder = new VertexShader(device, vscylinderbytes);
basicps = new PixelShader(device, psbytes);
basicpsdef = new PixelShader(device, psdefbytes);
VSSceneVars = new GpuVarsBuffer<BasicShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<BasicShaderVSEntityVars>(device);
@@ -491,7 +495,7 @@ namespace CodeWalker.Rendering
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(basicps);
context.PixelShader.Set(Deferred ? basicpsdef : basicps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
@@ -1035,6 +1039,7 @@ namespace CodeWalker.Rendering
ClothVertices.Dispose();
basicps.Dispose();
basicpsdef.Dispose();
basicvspnct.Dispose();
basicvspnctt.Dispose();
basicvspncttt.Dispose();
+6 -1
View File
@@ -67,6 +67,7 @@ namespace CodeWalker.Rendering
VertexShader vs;
PixelShader ps;
PixelShader psdef;
GpuVarsBuffer<CableShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<CableShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<CableShaderVSModelVars> VSModelVars;
@@ -80,6 +81,7 @@ namespace CodeWalker.Rendering
public int RenderTextureCoordIndex = 1;
public int RenderTextureSamplerCoord = 1;
public ShaderParamNames RenderTextureSampler = ShaderParamNames.DiffuseSampler;
public bool Deferred = false;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
@@ -88,9 +90,11 @@ namespace CodeWalker.Rendering
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\CableVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\CablePS.cso");
byte[] psdefbytes = File.ReadAllBytes("Shaders\\CablePS_Deferred.cso");
vs = new VertexShader(device, vsbytes);
ps = new PixelShader(device, psbytes);
psdef = new PixelShader(device, psdefbytes);
VSSceneVars = new GpuVarsBuffer<CableShaderVSSceneVars>(device);
@@ -137,7 +141,7 @@ namespace CodeWalker.Rendering
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(ps);
context.PixelShader.Set(Deferred ? psdef : ps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
@@ -344,6 +348,7 @@ namespace CodeWalker.Rendering
ps.Dispose();
psdef.Dispose();
vs.Dispose();
disposed = true;
+375
View File
@@ -0,0 +1,375 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Device = SharpDX.Direct3D11.Device;
using Buffer = SharpDX.Direct3D11.Buffer;
using MapFlags = SharpDX.Direct3D11.MapFlags;
using SharpDX.Direct3D11;
using System.IO;
using CodeWalker.GameFiles;
using CodeWalker.World;
using SharpDX;
using SharpDX.DXGI;
using SharpDX.Mathematics.Interop;
namespace CodeWalker.Rendering
{
public struct DeferredLightVSVars
{
public Matrix ViewProj;
public Vector4 CameraPos;
public uint LightType; //0=directional, 1=Point, 2=Spot, 4=Capsule
public uint IsLOD; //useful or not?
public uint Pad0;
public uint Pad1;
}
public struct DeferredLightPSVars
{
public ShaderGlobalLightParams GlobalLights;
public Matrix ViewProjInv;
public Vector4 CameraPos;
public uint EnableShadows;
public uint RenderMode;//0=default, 1=normals, 2=tangents, 3=colours, 4=texcoords, 5=diffuse, 6=normalmap, 7=spec, 8=direct
public uint RenderModeIndex; //colour/texcoord index
public uint RenderSamplerCoord; //which texcoord to use in single texture mode
public uint LightType; //0=directional, 1=Point, 2=Spot, 4=Capsule
public uint IsLOD; //useful or not?
public uint Pad0;
public uint Pad1;
}
public class DeferredScene
{
public GpuMultiTexture GBuffers; // diffuse, normals, specular, irradiance
SamplerState SampleStatePoint;
SamplerState SampleStateLinear;
BlendState BlendState;
long WindowSizeVramUsage = 0;
int Width = 0;
int Height = 0;
ViewportF Viewport;
VertexShader LightVS;
PixelShader LightPS;
UnitCone LightCone;
UnitSphere LightSphere;
UnitCapsule LightCapsule;
UnitQuad LightQuad;
InputLayout LightQuadLayout;
GpuVarsBuffer<DeferredLightVSVars> LightVSVars;
GpuVarsBuffer<DeferredLightPSVars> LightPSVars;
public long VramUsage
{
get
{
return WindowSizeVramUsage;
}
}
public DeferredScene(DXManager dxman)
{
var device = dxman.device;
byte[] bLightVS = File.ReadAllBytes("Shaders\\LightVS.cso");
byte[] bLightPS = File.ReadAllBytes("Shaders\\LightPS.cso");
LightVS = new VertexShader(device, bLightVS);
LightPS = new PixelShader(device, bLightPS);
LightCone = new UnitCone(device, bLightVS, 4, false);
LightSphere = new UnitSphere(device, bLightVS, 4, true);
LightCapsule = new UnitCapsule(device, bLightVS, 4, false);
LightQuad = new UnitQuad(device, true);
LightQuadLayout = new InputLayout(device, bLightVS, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0),
});
LightVSVars = new GpuVarsBuffer<DeferredLightVSVars>(device);
LightPSVars = new GpuVarsBuffer<DeferredLightPSVars>(device);
TextureAddressMode a = TextureAddressMode.Clamp;
Color4 b = new Color4(0.0f, 0.0f, 0.0f, 0.0f);
Comparison c = Comparison.Always;
SampleStatePoint = DXUtility.CreateSamplerState(device, a, b, c, Filter.MinMagMipPoint, 0, 1.0f, 1.0f, 0.0f);
SampleStateLinear = DXUtility.CreateSamplerState(device, a, b, c, Filter.MinMagMipLinear, 0, 1.0f, 1.0f, 0.0f);
BlendState = DXUtility.CreateBlendState(device, false, BlendOperation.Add, BlendOption.One, BlendOption.Zero, BlendOperation.Add, BlendOption.One, BlendOption.Zero, ColorWriteMaskFlags.All);
}
public void Dispose()
{
DisposeBuffers();
if (BlendState != null)
{
BlendState.Dispose();
BlendState = null;
}
if (SampleStateLinear != null)
{
SampleStateLinear.Dispose();
SampleStateLinear = null;
}
if (SampleStatePoint != null)
{
SampleStatePoint.Dispose();
SampleStatePoint = null;
}
if (LightVSVars != null)
{
LightVSVars.Dispose();
LightVSVars = null;
}
if (LightPSVars != null)
{
LightPSVars.Dispose();
LightPSVars = null;
}
if (LightQuadLayout != null)
{
LightQuadLayout.Dispose();
LightQuadLayout = null;
}
if (LightQuad != null)
{
LightQuad.Dispose();
LightQuad = null;
}
if (LightCone != null)
{
LightCone.Dispose();
LightCone = null;
}
if (LightSphere != null)
{
LightSphere.Dispose();
LightSphere = null;
}
if (LightCapsule != null)
{
LightCapsule.Dispose();
LightCapsule = null;
}
if (LightPS != null)
{
LightPS.Dispose();
LightPS = null;
}
if (LightVS != null)
{
LightVS.Dispose();
LightVS = null;
}
}
public void OnWindowResize(DXManager dxman)
{
DisposeBuffers();
var device = dxman.device;
int uw = Width = dxman.backbuffer.Description.Width;
int uh = Height = dxman.backbuffer.Description.Height;
Viewport = new ViewportF();
Viewport.Width = (float)uw;
Viewport.Height = (float)uh;
Viewport.MinDepth = 0.0f;
Viewport.MaxDepth = 1.0f;
Viewport.X = 0.0f;
Viewport.Y = 0.0f;
GBuffers = new GpuMultiTexture(device, uw, uh, 4, Format.R8G8B8A8_UNorm, true, Format.D32_Float);
WindowSizeVramUsage += GBuffers.VramUsage;
}
public void DisposeBuffers()
{
if (GBuffers != null)
{
GBuffers.Dispose();
GBuffers = null;
}
WindowSizeVramUsage = 0;
}
public void Clear(DeviceContext context)
{
//Color4 clearColour = new Color4(0.2f, 0.4f, 0.6f, 0.0f);
Color4 clearColour = new Color4(0.0f, 0.0f, 0.0f, 0.0f);
GBuffers.Clear(context, clearColour);
}
public void ClearDepth(DeviceContext context)
{
GBuffers.ClearDepth(context);
}
public void SetPrimary(DeviceContext context)
{
GBuffers.SetRenderTargets(context);
context.Rasterizer.SetViewport(Viewport);
}
public void RenderLights(DeviceContext context, Camera camera, Shadowmap globalShadows, ShaderGlobalLights globalLights)
{
uint rendermode = 0;
uint rendermodeind = 1;
//first full-screen directional light pass, for sun/moon
//discard pixels where scene depth is 0, since nothing was rendered there
//blend mode: overwrite
context.VertexShader.Set(LightVS);
context.PixelShader.Set(LightPS);
LightVSVars.Vars.ViewProj = Matrix.Identity; //Matrix.Transpose(camera.ViewProjMatrix);
LightVSVars.Vars.CameraPos = Vector4.Zero; //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.GlobalLights = globalLights.Params;
LightPSVars.Vars.ViewProjInv = Matrix.Transpose(camera.ViewProjInvMatrix);
LightPSVars.Vars.CameraPos = Vector4.Zero; //new Vector4(camera.Position, 0.0f);
LightPSVars.Vars.EnableShadows = (globalShadows != null) ? 1u : 0u;
LightPSVars.Vars.RenderMode = rendermode;
LightPSVars.Vars.RenderModeIndex = rendermodeind;
LightPSVars.Vars.RenderSamplerCoord = 0;// (uint)RenderTextureSamplerCoord;
LightPSVars.Vars.LightType = 0;
LightPSVars.Vars.IsLOD = 0;
LightPSVars.Vars.Pad0 = 0;
LightPSVars.Vars.Pad1 = 0;
LightPSVars.Update(context);
LightPSVars.SetPSCBuffer(context, 0);
context.PixelShader.SetShaderResources(0, GBuffers.DepthSRV);
context.PixelShader.SetShaderResources(2, GBuffers.SRVs);
if (globalShadows != null)
{
globalShadows.SetFinalRenderResources(context);
}
context.InputAssembler.InputLayout = LightQuadLayout;
LightQuad.Draw(context);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
context.PixelShader.SetShaderResources(0, null, null, null);
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
//blend mode: additive
context.VertexShader.Set(LightVS);
context.PixelShader.Set(LightPS);
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;
//LightPSVars.Vars.GlobalLights = globalLights.Params;
LightPSVars.Vars.ViewProjInv = Matrix.Transpose(camera.ViewProjInvMatrix);
LightPSVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f);
LightPSVars.Vars.EnableShadows = 0;// (globalShadows != null) ? 1u : 0u;
LightPSVars.Vars.RenderMode = 0;// rendermode;
LightPSVars.Vars.RenderModeIndex = 1;// rendermodeind;
LightPSVars.Vars.RenderSamplerCoord = 0;// (uint)RenderTextureSamplerCoord;
LightPSVars.Vars.LightType = 0;
LightPSVars.Vars.IsLOD = 0;
LightPSVars.Vars.Pad0 = 0;
LightPSVars.Vars.Pad1 = 0;
context.PixelShader.SetShaderResources(0, GBuffers.DepthSRV);
context.PixelShader.SetShaderResources(2, GBuffers.SRVs);
//if (globalShadows != null)
//{
// globalShadows.SetFinalRenderResources(context);
//}
foreach (var rll in lodlights)
{
if (rll.PointsBuffer != null)
{
context.VertexShader.SetShaderResources(0, rll.PointsBuffer.SRV);
context.PixelShader.SetShaderResources(6, rll.PointsBuffer.SRV);
LightVSVars.Vars.LightType = 1;
LightVSVars.Update(context);
LightVSVars.SetVSCBuffer(context, 0);
LightPSVars.Vars.LightType = 1;
LightPSVars.Update(context);
LightPSVars.SetPSCBuffer(context, 0);
LightSphere.DrawInstanced(context, rll.PointsBuffer.StructCount);
}
if (rll.SpotsBuffer != null)
{
context.VertexShader.SetShaderResources(0, rll.SpotsBuffer.SRV);
context.PixelShader.SetShaderResources(6, rll.SpotsBuffer.SRV);
LightVSVars.Vars.LightType = 2;
LightVSVars.Update(context);
LightVSVars.SetVSCBuffer(context, 0);
LightPSVars.Vars.LightType = 2;
LightPSVars.Update(context);
LightPSVars.SetPSCBuffer(context, 0);
LightCone.DrawInstanced(context, rll.SpotsBuffer.StructCount);
}
if (rll.CapsBuffer != null)
{
context.VertexShader.SetShaderResources(0, rll.CapsBuffer.SRV);
context.PixelShader.SetShaderResources(6, rll.CapsBuffer.SRV);
LightVSVars.Vars.LightType = 4;
LightVSVars.Update(context);
LightVSVars.SetVSCBuffer(context, 0);
LightPSVars.Vars.LightType = 4;
LightPSVars.Update(context);
LightPSVars.SetPSCBuffer(context, 0);
LightCapsule.DrawInstanced(context, rll.CapsBuffer.StructCount);
}
}
context.VertexShader.Set(null);
context.PixelShader.Set(null);
context.PixelShader.SetShaderResources(0, null, null, null);
context.PixelShader.SetSamplers(0, null, null);
}
}
}
+6 -1
View File
@@ -78,6 +78,7 @@ namespace CodeWalker.Rendering
VertexShader pnctttxvs;
VertexShader pncttxvs;
PixelShader terrainps;
PixelShader terrainpsdef;
GpuVarsBuffer<TerrainShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<TerrainShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<TerrainShaderVSModelVars> VSModelVars;
@@ -93,6 +94,7 @@ namespace CodeWalker.Rendering
public int RenderTextureCoordIndex = 1;
public int RenderTextureSamplerCoord = 1;
public ShaderParamNames RenderTextureSampler = ShaderParamNames.DiffuseSampler;
public bool Deferred = false;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
@@ -107,6 +109,7 @@ namespace CodeWalker.Rendering
byte[] vspnctttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCTTTX.cso");
byte[] vspncttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCTTX.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\TerrainPS.cso");
byte[] psdefbytes = File.ReadAllBytes("Shaders\\TerrainPS_Deferred.cso");
pncctvs = new VertexShader(device, vspncct);
pnccttvs = new VertexShader(device, vspncctt);
@@ -116,6 +119,7 @@ namespace CodeWalker.Rendering
pnctttxvs = new VertexShader(device, vspnctttx);
pncttxvs = new VertexShader(device, vspncttx);
terrainps = new PixelShader(device, psbytes);
terrainpsdef = new PixelShader(device, psdefbytes);
VSSceneVars = new GpuVarsBuffer<TerrainShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<TerrainShaderVSEntityVars>(device);
@@ -259,7 +263,7 @@ namespace CodeWalker.Rendering
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(terrainps);
context.PixelShader.Set(Deferred ? terrainpsdef : terrainps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
@@ -639,6 +643,7 @@ namespace CodeWalker.Rendering
PSGeomVars.Dispose();
terrainps.Dispose();
terrainpsdef.Dispose();
pncctvs.Dispose();
pnccttvs.Dispose();
pnccttxvs.Dispose();
+14 -8
View File
@@ -59,8 +59,9 @@ namespace CodeWalker.Rendering
{
bool disposed = false;
VertexShader basicvs;
PixelShader basicps;
VertexShader vs;
PixelShader ps;
PixelShader psdef;
GpuVarsBuffer<TreesLodShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<TreesLodShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<TreesLodShaderVSModelVars> VSModelVars;
@@ -71,14 +72,18 @@ namespace CodeWalker.Rendering
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public bool Deferred = false;
public TreesLodShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\TreesLodVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\TreesLodPS.cso");
byte[] psdefbytes = File.ReadAllBytes("Shaders\\TreesLodPS_Deferred.cso");
basicvs = new VertexShader(device, vsbytes);
basicps = new PixelShader(device, psbytes);
vs = new VertexShader(device, vsbytes);
ps = new PixelShader(device, psbytes);
psdef = new PixelShader(device, psdefbytes);
VSSceneVars = new GpuVarsBuffer<TreesLodShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<TreesLodShaderVSEntityVars>(device);
@@ -112,8 +117,8 @@ namespace CodeWalker.Rendering
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(basicvs);
context.PixelShader.Set(basicps);
context.VertexShader.Set(vs);
context.PixelShader.Set(Deferred ? psdef : ps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
@@ -311,8 +316,9 @@ namespace CodeWalker.Rendering
PSSceneVars.Dispose();
PSEntityVars.Dispose();
basicps.Dispose();
basicvs.Dispose();
psdef.Dispose();
ps.Dispose();
vs.Dispose();
disposed = true;
}
+6 -1
View File
@@ -84,6 +84,7 @@ namespace CodeWalker.Rendering
VertexShader vspnct;
VertexShader vspnctx;
PixelShader ps;
PixelShader psdef;
GpuVarsBuffer<WaterShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<WaterShaderVSEntityVars> VSEntityVars;
@@ -107,6 +108,7 @@ namespace CodeWalker.Rendering
public double CurrentRealTime = 0;
public float CurrentElapsedTime = 0;
public bool SpecularEnable = true;
public bool Deferred = false;
public RenderableTexture waterbump { get; set; }
@@ -124,6 +126,7 @@ namespace CodeWalker.Rendering
byte[] vspnctbytes = File.ReadAllBytes("Shaders\\WaterVS_PNCT.cso");
byte[] vspnctxbytes = File.ReadAllBytes("Shaders\\WaterVS_PNCTX.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\WaterPS.cso");
byte[] psdefbytes = File.ReadAllBytes("Shaders\\WaterPS_Deferred.cso");
vspt = new VertexShader(device, vsptbytes);
@@ -131,6 +134,7 @@ namespace CodeWalker.Rendering
vspnct = new VertexShader(device, vspnctbytes);
vspnctx = new VertexShader(device, vspnctxbytes);
ps = new PixelShader(device, psbytes);
psdef = new PixelShader(device, psdefbytes);
VSSceneVars = new GpuVarsBuffer<WaterShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<WaterShaderVSEntityVars>(device);
@@ -213,7 +217,7 @@ namespace CodeWalker.Rendering
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(ps);
context.PixelShader.Set(Deferred ? psdef : ps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
@@ -552,6 +556,7 @@ namespace CodeWalker.Rendering
PSGeomVars.Dispose();
ps.Dispose();
psdef.Dispose();
vspt.Dispose();
vspct.Dispose();
vspnct.Dispose();
+129
View File
@@ -421,4 +421,133 @@ namespace CodeWalker.Rendering
}
public class GpuMultiTexture //multiple texture and render targets (depth).
{
public Texture2D[] Textures;
public Texture2D Depth;
public RenderTargetView[] RTVs;
public DepthStencilView DSV;
public ShaderResourceView[] SRVs;
public ShaderResourceView DepthSRV;
public int VramUsage;
public bool UseDepth;
public int Count;
public void Init(Device device, int w, int h, int count, Format f, bool depth, Format df)
{
Count = count;
VramUsage = 0;
UseDepth = depth;
ResourceUsage u = ResourceUsage.Default;
BindFlags b = BindFlags.RenderTarget | BindFlags.ShaderResource;
RenderTargetViewDimension rtvd = RenderTargetViewDimension.Texture2D;
ShaderResourceViewDimension srvd = ShaderResourceViewDimension.Texture2D;// D3D11_SRV_DIMENSION_TEXTURE2D;
int fs = DXUtility.ElementSize(f);
int wh = w * h;
BindFlags db = BindFlags.DepthStencil | BindFlags.ShaderResource;// D3D11_BIND_DEPTH_STENCIL;
DepthStencilViewDimension dsvd = DepthStencilViewDimension.Texture2D;
Textures = new Texture2D[count];
RTVs = new RenderTargetView[count];
SRVs = new ShaderResourceView[count];
for (int i = 0; i < count; i++)
{
Textures[i] = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, 1, 0, u, b, 0, 0);
RTVs[i] = DXUtility.CreateRenderTargetView(device, Textures[i], f, rtvd, 0, 0, 0);
SRVs[i] = DXUtility.CreateShaderResourceView(device, Textures[i], f, srvd, 1, 0, 0, 0);
VramUsage += (wh * fs);
}
if (depth)
{
Format dtexf = Format.R32_Typeless;
Format dsrvf = Format.R32_Float;
switch (df)
{
case Format.D16_UNorm:
dtexf = Format.R16_Typeless;
dsrvf = Format.R16_UNorm;
break;
case Format.D24_UNorm_S8_UInt:
dtexf = Format.R24G8_Typeless;
dsrvf = Format.R24_UNorm_X8_Typeless;
break;
case Format.D32_Float:
dtexf = Format.R32_Typeless;
dsrvf = Format.R32_Float;
break;
case Format.D32_Float_S8X24_UInt:
dtexf = Format.R32G8X24_Typeless;//is this right? who uses this anyway??
dsrvf = Format.R32_Float_X8X24_Typeless;
break;
}
Depth = DXUtility.CreateTexture2D(device, w, h, 1, 1, dtexf, 1, 0, u, db, 0, 0);
DSV = DXUtility.CreateDepthStencilView(device, Depth, df, dsvd);
DepthSRV = DXUtility.CreateShaderResourceView(device, Depth, dsrvf, srvd, 1, 0, 0, 0);
VramUsage += (wh * DXUtility.ElementSize(df));
}
}
public void Dispose()
{
for (int i = 0; i < Count; i++)
{
SRVs[i].Dispose();
RTVs[i].Dispose();
Textures[i].Dispose();
}
SRVs = null;
RTVs = null;
Textures = null;
if (DSV != null)
{
DSV.Dispose();
DSV = null;
}
if (DepthSRV != null)
{
DepthSRV.Dispose();
DepthSRV = null;
}
if (Depth != null)
{
Depth.Dispose();
Depth = null;
}
}
public GpuMultiTexture(Device device, int w, int h, int count, Format f, bool depth, Format df)
{
Init(device, w, h, count, f, depth, df);
}
public GpuMultiTexture(Device device, int w, int h, int count, Format f)
{
Init(device, w, h, count, f, false, Format.Unknown);
}
public void Clear(DeviceContext context, Color4 colour)
{
for (int i = 0; i < Count; i++)
{
context.ClearRenderTargetView(RTVs[i], colour);
}
if (UseDepth)
{
context.ClearDepthStencilView(DSV, DepthStencilClearFlags.Depth, 0.0f, 0);
}
}
public void ClearDepth(DeviceContext context)
{
if (!UseDepth) return;
context.ClearDepthStencilView(DSV, DepthStencilClearFlags.Depth, 0.0f, 0);
}
public void SetRenderTargets(DeviceContext context)
{
context.OutputMerger.SetRenderTargets(UseDepth ? DSV : null, RTVs);
}
}
}
+3 -3
View File
@@ -33,7 +33,7 @@ namespace CodeWalker.Rendering
}
}
public UnitCapsule(Device device, byte[] vsbytes, int detail)
public UnitCapsule(Device device, byte[] vsbytes, int detail, bool invert = false)
{
InputLayout = new InputLayout(device, vsbytes, new[]
@@ -208,8 +208,8 @@ namespace CodeWalker.Rendering
foreach (var tri in curtris)
{
idata.Add((uint)tri.v1);
idata.Add((uint)tri.v2);
idata.Add((uint)tri.v3);
idata.Add((uint)(invert ? tri.v3 : tri.v2));
idata.Add((uint)(invert ? tri.v2 : tri.v3));
}
+152
View File
@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using Device = SharpDX.Direct3D11.Device;
using Buffer = SharpDX.Direct3D11.Buffer;
using SharpDX.DXGI;
namespace CodeWalker.Rendering
{
public class UnitCone
{
private Buffer VertexBuffer { get; set; }
private Buffer IndexBuffer { get; set; }
private InputLayout InputLayout { get; set; }
private VertexBufferBinding vbbinding;
private int indexcount;
private struct SphTri
{
public int v1;
public int v2;
public int v3;
public SphTri(int i1, int i2, int i3)
{
v1 = i1;
v2 = i2;
v3 = i3;
}
}
public UnitCone(Device device, byte[] vsbytes, int detail, bool invert = false)
{
InputLayout = new InputLayout(device, vsbytes, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 16, 0),
});
List<Vector4> verts = new List<Vector4>();
Dictionary<Vector4, int> vdict = new Dictionary<Vector4, int>();
List<SphTri> curtris = new List<SphTri>();
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, 0.0f, 0.0f, 1.0f));//bottom end
verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 1.0f));//bottom normal
int nlons = detail * 4;
int lastlon = nlons - 1;
float latrng = 1.0f / (detail);
float lonrng = 1.0f / (nlons);
float twopi = (float)(2.0 * Math.PI);
for (int lon = 0; lon < nlons; lon++)
{
float tlon = lon * lonrng;
float rlon = tlon * twopi;
float lonx = (float)Math.Sin(rlon);
float lonz = (float)Math.Cos(rlon);
verts.Add(new Vector4(lonx, 0.0f, lonz, 1.0f));//2
verts.Add(new Vector4(lonx, 0.0f, lonz, 0.0f));//side normal
verts.Add(new Vector4(lonx, 0.0f, lonz, 1.0f));//3
verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 0.0f));//bottom normal
}
for (int lon = 0; lon < nlons; lon++)
{
int i0 = 2 + lon * 2;
int i1 = i0 + 2;
if (lon == lastlon)
{
i1 = 2;
}
curtris.Add(new SphTri(0, i0, i1)); //fill the cone
curtris.Add(new SphTri(1, i1+1, i0+1)); //bottom cap triangles
}
List<uint> idata = new List<uint>();
foreach (var tri in curtris)
{
idata.Add((uint)tri.v1);
idata.Add((uint)(invert ? tri.v2 : tri.v3));
idata.Add((uint)(invert ? tri.v3 : tri.v2));
}
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, verts.ToArray());
vbbinding = new VertexBufferBinding(VertexBuffer, 32, 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;
}
}
}
}
+3 -3
View File
@@ -33,7 +33,7 @@ namespace CodeWalker.Rendering
}
}
public UnitSphere(Device device, byte[] vsbytes, int detail)
public UnitSphere(Device device, byte[] vsbytes, int detail, bool invert = false)
{
InputLayout = new InputLayout(device, vsbytes, new[]
@@ -121,8 +121,8 @@ namespace CodeWalker.Rendering
foreach (var tri in curtris)
{
idata.Add((uint)tri.v1);
idata.Add((uint)tri.v2);
idata.Add((uint)tri.v3);
idata.Add((uint)(invert ? tri.v3 : tri.v2));
idata.Add((uint)(invert ? tri.v2 : tri.v3));
}