CodeWalker/Rendering/Shaders/BoundsShader.cs
2018-03-13 22:28:58 -04:00

240 lines
7.5 KiB
C#

using SharpDX;
using SharpDX.Direct3D11;
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 CodeWalker.GameFiles;
using System.IO;
using SharpDX.DXGI;
using CodeWalker.World;
namespace CodeWalker.Rendering
{
public struct BoundingSphereVSSceneVars
{
public Matrix ViewProj;
public Matrix ViewInv;
public float SegmentCount;
public float VertexCount;
public float Pad1;
public float Pad2;
}
public struct BoundingSphereVSSphereVars
{
public Vector3 Center;
public float Radius;
}
public struct BoundingBoxVSSceneVars
{
public Matrix ViewProj;
}
public struct BoundingBoxVSBoxVars
{
public Quaternion Orientation;
public Vector4 BBMin;
public Vector4 BBRng; //max-min
public Vector3 CamRel;
public float Pad1;
public Vector3 Scale;
public float Pad2;
}
public struct BoundsPSColourVars
{
public Vector4 Colour;
}
public class BoundsShader : Shader, IDisposable
{
bool disposed = false;
BoundsShaderMode mode = BoundsShaderMode.Sphere;
VertexShader spherevs;
VertexShader boxvs;
PixelShader boundsps;
GpuVarsBuffer<BoundingSphereVSSceneVars> VSSphereSceneVars;
GpuVarsBuffer<BoundingSphereVSSphereVars> VSSphereVars;
GpuVarsBuffer<BoundingBoxVSSceneVars> VSBoxSceneVars;
GpuVarsBuffer<BoundingBoxVSBoxVars> VSBoxVars;
GpuVarsBuffer<BoundsPSColourVars> PSColourVars;
int SegmentCount = 64;
int VertexCount = 65;
UnitCube cube;
public BoundsShader(Device device)
{
byte[] spherevsbytes = File.ReadAllBytes("Shaders\\BoundingSphereVS.cso");
byte[] boxvsbytes = File.ReadAllBytes("Shaders\\BoundingBoxVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\BoundsPS.cso");
spherevs = new VertexShader(device, spherevsbytes);
boxvs = new VertexShader(device, boxvsbytes);
boundsps = new PixelShader(device, psbytes);
VSSphereSceneVars = new GpuVarsBuffer<BoundingSphereVSSceneVars>(device);
VSSphereVars = new GpuVarsBuffer<BoundingSphereVSSphereVars>(device);
VSBoxSceneVars = new GpuVarsBuffer<BoundingBoxVSSceneVars>(device);
VSBoxVars = new GpuVarsBuffer<BoundingBoxVSBoxVars>(device);
PSColourVars = new GpuVarsBuffer<BoundsPSColourVars>(device);
cube = new UnitCube(device, boxvsbytes, false, true, false);
}
public void SetMode(BoundsShaderMode m)
{
mode = m;
}
public override void SetShader(DeviceContext context)
{
switch (mode)
{
default:
case BoundsShaderMode.Sphere:
context.VertexShader.Set(spherevs);
break;
case BoundsShaderMode.Box:
context.VertexShader.Set(boxvs);
break;
}
context.PixelShader.Set(boundsps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
//switch (mode)
//{
// default:
// case BoundsShaderMode.Sphere:
// context.InputAssembler.InputLayout = null;
// break;
// case BoundsShaderMode.Box:
// context.InputAssembler.InputLayout = cube.InputLayout;
// break;
//}
return true;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
switch (mode)
{
default:
case BoundsShaderMode.Sphere:
VSSphereSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSphereSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix);
VSSphereSceneVars.Vars.SegmentCount = (float)SegmentCount;
VSSphereSceneVars.Vars.VertexCount = (float)VertexCount;
VSSphereSceneVars.Update(context);
VSSphereSceneVars.SetVSCBuffer(context, 0);
break;
case BoundsShaderMode.Box:
VSBoxSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSBoxSceneVars.Update(context);
VSBoxSceneVars.SetVSCBuffer(context, 0);
break;
}
}
public void SetSphereVars(DeviceContext context, Vector3 center, float radius)
{
VSSphereVars.Vars.Center = center;
VSSphereVars.Vars.Radius = radius;
VSSphereVars.Update(context);
VSSphereVars.SetVSCBuffer(context, 1);
}
public void SetBoxVars(DeviceContext context, Vector3 camrel, Vector3 bbmin, Vector3 bbmax, Quaternion orientation, Vector3 scale)
{
VSBoxVars.Vars.Orientation = orientation;
VSBoxVars.Vars.BBMin = new Vector4(bbmin, 0.0f);
VSBoxVars.Vars.BBRng = new Vector4(bbmax - bbmin, 0.0f);
VSBoxVars.Vars.CamRel = camrel;
VSBoxVars.Vars.Scale = scale;
VSBoxVars.Update(context);
VSBoxVars.SetVSCBuffer(context, 1);
}
public void SetColourVars(DeviceContext context, Vector4 colour)
{
PSColourVars.Vars.Colour = colour;
PSColourVars.Update(context);
PSColourVars.SetPSCBuffer(context, 0);
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
//don't use this one
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
//don't use this
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
//don't use this
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void DrawSphere(DeviceContext context)
{
context.InputAssembler.InputLayout = null;
context.InputAssembler.SetIndexBuffer(null, Format.Unknown, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineStrip;
context.Draw(VertexCount, 0);
}
public void DrawBox(DeviceContext context)
{
cube.Draw(context);
}
public void Dispose()
{
if (disposed) return;
VSSphereSceneVars.Dispose();
VSSphereVars.Dispose();
VSBoxSceneVars.Dispose();
VSBoxVars.Dispose();
PSColourVars.Dispose();
cube.Dispose();
boundsps.Dispose();
boxvs.Dispose();
spherevs.Dispose();
disposed = true;
}
}
public enum BoundsShaderMode
{
None = 0,
Sphere = 1,
Box = 2,
}
}