R26_dev8 - First public commit

This commit is contained in:
dexyfex
2017-09-21 20:33:05 +10:00
Unverified
commit a8243c3e0e
391 changed files with 157678 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
using SharpDX.Direct3D11;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.Rendering
{
public interface DXForm
{
//unfortunately this can't be made a base class for the main render forms, because the
//form designer causes an error when inheriting from a form in the same project, if
//the architecture is set to x64. really annoying!
//So, i've used an interface instead, since really just some of the form properties
//and a couple of extra methods (these callbacks) are needed by DXManager.
Form Form { get; }
void InitScene(Device device);
void CleanupScene();
void RenderScene(DeviceContext context);
void BuffersResized(int w, int h);
}
}
+337
View File
@@ -0,0 +1,337 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using Color = SharpDX.Color;
using Device = SharpDX.Direct3D11.Device;
using Buffer = SharpDX.Direct3D11.Buffer;
using DriverType = SharpDX.Direct3D.DriverType;
using System.Threading;
using System.Windows.Forms;
using SharpDX;
using SharpDX.Direct3D;
namespace CodeWalker.Rendering
{
public class DXManager
{
private DXForm dxform;
public Device device { get; private set; }
public DeviceContext context { get; private set; }
public SwapChain swapchain { get; private set; }
public Texture2D backbuffer { get; private set; }
public Texture2D depthbuffer { get; private set; }
public RenderTargetView targetview { get; private set; }
public DepthStencilView depthview { get; private set; }
private volatile bool Running = false;
private volatile bool Rendering = false;
private volatile bool Resizing = false;
private object syncroot = new object(); //for thread safety
public int multisamplecount { get; private set; } = 4; //should be a setting..
public int multisamplequality { get; private set; } = 0; //should be a setting...
public Color clearcolour { get; private set; } = new Color(0.2f, 0.4f, 0.6f, 1.0f); //gross
private System.Drawing.Size beginSize;
private ViewportF Viewport;
private bool autoStartLoop = false;
public bool Init(DXForm form, bool autostart = true)
{
dxform = form;
autoStartLoop = autostart;
try
{
SwapChainDescription scd = new SwapChainDescription()
{
BufferCount = 2,
Flags = SwapChainFlags.None,
IsWindowed = true,
ModeDescription = new ModeDescription(
form.Form.ClientSize.Width,
form.Form.ClientSize.Height,
new Rational(0, 0),
Format.R8G8B8A8_UNorm),
OutputHandle = form.Form.Handle,
SampleDescription = new SampleDescription(multisamplecount, multisamplequality),
SwapEffect = SwapEffect.Discard,
Usage = Usage.RenderTargetOutput
};
FeatureLevel[] levels = new FeatureLevel[] { FeatureLevel.Level_10_0 };
DeviceCreationFlags flags = DeviceCreationFlags.None;
//#if DEBUG
// flags = DeviceCreationFlags.Debug;
//#endif
Device dev = null;
SwapChain sc = null;
bool success = false;
try
{
Device.CreateWithSwapChain(DriverType.Hardware, flags, levels, scd, out dev, out sc);
success = true;
}
catch { }
if (!success)
{
multisamplecount = 1;
multisamplequality = 0;
scd.SampleDescription = new SampleDescription(1, 0); //try no AA
try
{
Device.CreateWithSwapChain(DriverType.Hardware, flags, levels, scd, out dev, out sc);
success = true;
}
catch { }
}
if (!success)
{
throw new Exception("CodeWalker was unable to initialise the graphics device. Please ensure your system meets the minimum requirements and that your graphics drivers and DirectX are up to date.");
}
device = dev;
swapchain = sc;
var factory = swapchain.GetParent<Factory>(); //ignore windows events...
factory.MakeWindowAssociation(form.Form.Handle, WindowAssociationFlags.IgnoreAll);
context = device.ImmediateContext;
CreateRenderBuffers();
dxform.Form.Load += Dxform_Load;
dxform.Form.FormClosing += Dxform_FormClosing;
dxform.Form.ClientSizeChanged += Dxform_ClientSizeChanged;
dxform.Form.ResizeBegin += DxForm_ResizeBegin;
dxform.Form.ResizeEnd += DxForm_ResizeEnd;
if (autostart)
{
dxform.InitScene(device);
}
return true;
}
catch (Exception ex)
{
MessageBox.Show("Unable to initialise DirectX11.\n" + ex.ToString());
return false;
}
}
private void Cleanup()
{
Running = false;
int count = 0;
while (Rendering && (count < 1000))
{
Thread.Sleep(1); //try to gracefully exit...
count++;
}
dxform.CleanupScene();
//dipose of all objects
if (depthview != null) depthview.Dispose();
if (depthbuffer != null) depthbuffer.Dispose();
if (targetview != null) targetview.Dispose();
if (backbuffer != null) backbuffer.Dispose();
if (swapchain != null) swapchain.Dispose();
if (device != null) device.Dispose();
GC.Collect();
}
private void CreateRenderBuffers()
{
if (targetview != null) targetview.Dispose();
if (backbuffer != null) backbuffer.Dispose();
if (depthview != null) depthview.Dispose();
if (depthbuffer != null) depthbuffer.Dispose();
backbuffer = Texture2D.FromSwapChain<Texture2D>(swapchain, 0);
targetview = new RenderTargetView(device, backbuffer);
depthbuffer = new Texture2D(device, new Texture2DDescription()
{
Format = Format.D32_Float,
ArraySize = 1,
MipLevels = 1,
Width = backbuffer.Description.Width,
Height = backbuffer.Description.Height,
SampleDescription = new SampleDescription(multisamplecount, 0),
Usage = ResourceUsage.Default,
BindFlags = BindFlags.DepthStencil,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
});
depthview = new DepthStencilView(device, depthbuffer);
Viewport.Width = (float)backbuffer.Description.Width;
Viewport.Height = (float)backbuffer.Description.Height;
Viewport.MinDepth = 0.0f;
Viewport.MaxDepth = 1.0f;
Viewport.X = 0;
Viewport.Y = 0;
}
private void Resize()
{
if (Resizing) return;
Monitor.Enter(syncroot);
int width = dxform.Form.ClientSize.Width;
int height = dxform.Form.ClientSize.Height;
if (targetview != null) targetview.Dispose();
if (backbuffer != null) backbuffer.Dispose();
swapchain.ResizeBuffers(1, width, height, Format.Unknown, SwapChainFlags.AllowModeSwitch);
CreateRenderBuffers();
Monitor.Exit(syncroot);
dxform.BuffersResized(width, height);
}
private void Dxform_Load(object sender, EventArgs e)
{
if (autoStartLoop)
{
StartRenderLoop();
}
}
private void Dxform_FormClosing(object sender, FormClosingEventArgs e)
{
Cleanup();
}
private void Dxform_ClientSizeChanged(object sender, EventArgs e)
{
Resize();
}
private void DxForm_ResizeBegin(object sender, EventArgs e)
{
beginSize = dxform.Form.ClientSize;
Resizing = true;
}
private void DxForm_ResizeEnd(object sender, EventArgs e)
{
Resizing = false;
if (dxform.Form.ClientSize != beginSize)
{
Resize();
}
}
public void Start()
{
dxform.InitScene(device);
StartRenderLoop();
}
private void StartRenderLoop()
{
Running = true;
new Thread(new ThreadStart(RenderLoop)).Start();
}
private void RenderLoop()
{
while (Running)
{
while (Resizing)
{
swapchain.Present(1, PresentFlags.None); //just flip buffers when resizing; don't draw
}
while (dxform.Form.WindowState == FormWindowState.Minimized)
{
Thread.Sleep(10); //don't hog CPU when minimised
if (dxform.Form.IsDisposed) return; //if closed while minimised
}
Rendering = true;
if(!Monitor.TryEnter(syncroot, 50))
{
Thread.Sleep(10); //don't hog CPU when not able to render...
continue;
}
bool ok = true;
try
{
context.OutputMerger.SetRenderTargets(depthview, targetview);
context.Rasterizer.SetViewport(0, 0, dxform.Form.ClientSize.Width, dxform.Form.ClientSize.Height);
}
catch (Exception ex)
{
MessageBox.Show("Error setting main render target!\n" + ex.ToString());
ok = false;
}
if (ok)
{
if (dxform.Form.IsDisposed)
{
Monitor.Exit(syncroot);
Rendering = false;
return; //the form was closed... stop!!
}
dxform.RenderScene(context);
try
{
swapchain.Present(1, PresentFlags.None);
}
catch (Exception ex)
{
MessageBox.Show("Error presenting swap chain!\n" + ex.ToString());
}
}
Monitor.Exit(syncroot);
Rendering = false;
}
}
public void ClearRenderTarget(DeviceContext ctx)
{
ctx.ClearRenderTargetView(targetview, clearcolour);
ctx.ClearDepthStencilView(depthview, DepthStencilClearFlags.Depth, 1.0f, 0);
}
public void ClearDepth(DeviceContext ctx)
{
ctx.ClearDepthStencilView(depthview, DepthStencilClearFlags.Depth, 1.0f, 0);
}
public void SetDefaultRenderTarget(DeviceContext ctx)
{
ctx.OutputMerger.SetRenderTargets(depthview, targetview);
ctx.Rasterizer.SetViewport(Viewport);
//ctx.Rasterizer.State = RasterizerStateSolid;
}
}
}
+463
View File
@@ -0,0 +1,463 @@
using SharpDX.Direct3D11;
using SharpDX.DXGI;
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 Resource = SharpDX.Direct3D11.Resource;
using MapFlags = SharpDX.Direct3D11.MapFlags;
using SharpDX.Mathematics.Interop;
using SharpDX.Direct3D;
namespace CodeWalker.Rendering
{
public static class DXUtility
{
public static Buffer CreateBuffer(Device device, int size, ResourceUsage usage, BindFlags bindFlags, CpuAccessFlags cpuAccessFlags, ResourceOptionFlags miscFlags, int structByteStride)
{
BufferDescription desc = new BufferDescription();
desc.SizeInBytes = size;
desc.Usage = usage;
desc.BindFlags = bindFlags;
desc.CpuAccessFlags = cpuAccessFlags;
desc.OptionFlags = miscFlags;
desc.StructureByteStride = structByteStride;
Buffer b = new Buffer(device, desc);
//D3D11_SUBRESOURCE_DATA srd;
//srd.pSysMem = data;
//ComPtr<ID3D11Buffer> b;
//Try(DXManager::GetDevice()->CreateBuffer(&desc, data != nullptr? &srd : nullptr, &b), name);
//DXManager::AddVramUsage(size);
return b;
}
public static Texture2D CreateTexture2D(Device device, int width, int height, int mipLevels, int arraySize, Format format, int sampleCount, int sampleQuality, ResourceUsage usage, BindFlags bindFlags, CpuAccessFlags cpuAccessFlags, ResourceOptionFlags miscFlags)
{
Texture2DDescription td = new Texture2DDescription();
td.Width = width;
td.Height = height;
td.MipLevels = mipLevels;
td.ArraySize = arraySize;
td.Format = format;
td.SampleDescription = new SampleDescription(sampleCount, sampleQuality);
td.Usage = usage;
td.BindFlags = bindFlags;
td.CpuAccessFlags = cpuAccessFlags;
td.OptionFlags = miscFlags;
Texture2D t = new Texture2D(device, td);
return t;
}
//static ComPtr<ID3D11Texture2D> CreateTexture2D(UINT width, UINT height, UINT mipLevels, UINT arraySize, DXGI_FORMAT format, UINT sampleCount, UINT sampleQuality, D3D11_USAGE usage, UINT bindFlags, UINT cpuAccessFlags, UINT miscFlags, const void* data, const string& name)
//{
// D3D11_TEXTURE2D_DESC td;
// td.Width = width;
// td.Height = height;
// td.MipLevels = mipLevels;
// td.ArraySize = arraySize;
// td.Format = format;
// td.SampleDesc.Count = sampleCount;
// td.SampleDesc.Quality = sampleQuality;
// td.Usage = usage;
// td.BindFlags = bindFlags;
// td.CPUAccessFlags = cpuAccessFlags;
// td.MiscFlags = miscFlags;
// D3D11_SUBRESOURCE_DATA srd;
// srd.pSysMem = data;
// srd.SysMemPitch = 1;
// srd.SysMemSlicePitch = 0;
// ComPtr<ID3D11Texture2D> t;
// Try(DXManager::GetDevice()->CreateTexture2D(&td, data != nullptr ? &srd : nullptr, &t), name);
// DXManager::AddVramUsage(ElementSize(format) * width * height * arraySize);
// return t;
//}
public static SamplerState CreateSamplerState(Device device, TextureAddressMode addressU, TextureAddressMode addressV, TextureAddressMode addressW, RawColor4 border, Comparison comparisonFunc, Filter filter, int maxAnisotropy, float maxLOD, float minLOD, float mipLODBias)
{
SamplerStateDescription smpDesc = new SamplerStateDescription();
smpDesc.AddressU = addressU;
smpDesc.AddressV = addressV;
smpDesc.AddressW = addressW;
smpDesc.BorderColor = border;
smpDesc.ComparisonFunction = comparisonFunc;
smpDesc.Filter = filter;
smpDesc.MaximumAnisotropy = maxAnisotropy;
smpDesc.MaximumLod = maxLOD;
smpDesc.MinimumLod = minLOD;
smpDesc.MipLodBias = mipLODBias;
SamplerState smp = new SamplerState(device, smpDesc);
return smp;
}
public static SamplerState CreateSamplerState(Device device, TextureAddressMode address, RawColor4 border, Comparison comparisonFunc, Filter filter, int maxAnisotropy, float maxLOD, float minLOD, float mipLODBias)
{
return CreateSamplerState(device, address, address, address, border, comparisonFunc, filter, maxAnisotropy, maxLOD, minLOD, mipLODBias);
}
public static ShaderResourceView CreateShaderResourceView(Device device, Resource resource, Format format, ShaderResourceViewDimension viewDimension, int mipLevels, int mostDetailedMip, int arraySize, int firstArraySlice)
{
ShaderResourceViewDescription srvd = new ShaderResourceViewDescription();
srvd.Format = format;
srvd.Dimension = viewDimension;
switch (viewDimension)
{
case ShaderResourceViewDimension.Buffer:// D3D11_SRV_DIMENSION_BUFFER:
srvd.Buffer.ElementOffset = mipLevels;
srvd.Buffer.ElementWidth = ElementSize(format);
srvd.Buffer.ElementCount = arraySize;
srvd.Buffer.FirstElement = firstArraySlice;
break;
case ShaderResourceViewDimension.Texture2D:// D3D11_SRV_DIMENSION_TEXTURE2D:
srvd.Texture2D.MipLevels = mipLevels;
srvd.Texture2D.MostDetailedMip = mostDetailedMip;
break;
case ShaderResourceViewDimension.Texture2DArray:// D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
srvd.Texture2DArray.MipLevels = mipLevels;
srvd.Texture2DArray.MostDetailedMip = mostDetailedMip;
srvd.Texture2DArray.ArraySize = arraySize;
srvd.Texture2DArray.FirstArraySlice = firstArraySlice;
break;
case ShaderResourceViewDimension.TextureCube:// D3D11_SRV_DIMENSION_TEXTURECUBE:
srvd.TextureCube.MipLevels = mipLevels;
srvd.TextureCube.MostDetailedMip = mostDetailedMip;
break;
case ShaderResourceViewDimension.Texture3D:// D3D11_SRV_DIMENSION_TEXTURE3D:
srvd.Texture3D.MipLevels = mipLevels;
srvd.Texture3D.MostDetailedMip = mostDetailedMip;
break;
default:
throw new Exception(); //not implemented....
}
ShaderResourceView srv = new ShaderResourceView(device, resource, srvd);
return srv;
}
public static UnorderedAccessView CreateUnorderedAccessView(Device device, Resource resource, Format format, UnorderedAccessViewDimension viewDimension, int firstElement, int numElements, UnorderedAccessViewBufferFlags flags, int mipSlice)
{
UnorderedAccessViewDescription uavd = new UnorderedAccessViewDescription();
uavd.Format = format;
uavd.Dimension = viewDimension;
switch(viewDimension)
{
case UnorderedAccessViewDimension.Texture1D:
uavd.Texture1D.MipSlice = mipSlice;
break;
case UnorderedAccessViewDimension.Texture1DArray:
uavd.Texture1DArray.MipSlice = mipSlice;
uavd.Texture1DArray.ArraySize = numElements;
uavd.Texture1DArray.FirstArraySlice = firstElement;
break;
case UnorderedAccessViewDimension.Texture2D:
uavd.Texture2D.MipSlice = mipSlice;
break;
case UnorderedAccessViewDimension.Texture2DArray:
uavd.Texture2DArray.MipSlice = mipSlice;
uavd.Texture2DArray.ArraySize = numElements;
uavd.Texture2DArray.FirstArraySlice = firstElement;
break;
case UnorderedAccessViewDimension.Texture3D:
uavd.Texture3D.MipSlice = mipSlice;
uavd.Texture3D.WSize = numElements;
uavd.Texture3D.FirstWSlice = firstElement;
break;
case UnorderedAccessViewDimension.Buffer:
uavd.Buffer.ElementCount = numElements;
uavd.Buffer.FirstElement = firstElement;
uavd.Buffer.Flags = flags;
break;
case UnorderedAccessViewDimension.Unknown:
default:
return null;
}
var uav = new UnorderedAccessView(device, resource, uavd);
return uav;
}
public static RenderTargetView CreateRenderTargetView(Device device, Resource renderTarget, Format format, RenderTargetViewDimension viewDimension, int mipSlice, int arraySize, int firstArraySlice)
{
RenderTargetView rtv;
RenderTargetViewDescription rtvd = new RenderTargetViewDescription();
rtvd.Format = format;
rtvd.Dimension = viewDimension;
switch(viewDimension)
{
case RenderTargetViewDimension.Buffer:// D3D11_RTV_DIMENSION_BUFFER:
rtvd.Buffer.ElementOffset = mipSlice;
rtvd.Buffer.ElementWidth = arraySize* ElementSize(format);// arraySize; //assume square buffer... is this the width?
rtvd.Buffer.FirstElement = 0*ElementSize(format);//firstArraySlice;
rtvd.Buffer.ElementCount = arraySize;//*arraySize*ElementSize(format); //does this represent the height??
break;
case RenderTargetViewDimension.Texture2D:// D3D11_RTV_DIMENSION_TEXTURE2D:
rtvd.Texture2D.MipSlice = mipSlice;
break;
case RenderTargetViewDimension.Texture2DArray:// D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
rtvd.Texture2DArray.MipSlice = mipSlice;
rtvd.Texture2DArray.ArraySize = arraySize;
rtvd.Texture2DArray.FirstArraySlice = firstArraySlice;
break;
case RenderTargetViewDimension.Texture2DMultisampled:// D3D11_RTV_DIMENSION_TEXTURE2DMS:
break;
case RenderTargetViewDimension.Texture2DMultisampledArray:// D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
rtvd.Texture2DMSArray.ArraySize = arraySize;
rtvd.Texture2DMSArray.FirstArraySlice = firstArraySlice;
break;
case RenderTargetViewDimension.Texture3D:// D3D11_RTV_DIMENSION_TEXTURE3D:
rtvd.Texture3D.MipSlice = mipSlice;
rtvd.Texture3D.DepthSliceCount = arraySize;
rtvd.Texture3D.FirstDepthSlice = firstArraySlice;
break;
}
rtv = new RenderTargetView(device, renderTarget, rtvd);
return rtv;
}
public static DepthStencilView CreateDepthStencilView(Device device, Texture2D depthStencil, Format format, DepthStencilViewDimension viewDimension)
{
DepthStencilViewDescription dsvd = new DepthStencilViewDescription();
dsvd.Format = format;
dsvd.Flags = 0;
dsvd.Dimension = viewDimension;
dsvd.Texture2D.MipSlice = 0;
DepthStencilView dsv = new DepthStencilView(device, depthStencil, dsvd);
return dsv;
}
public static DepthStencilView CreateDepthStencilView(Device device, Texture2D depthStencil, Format format, int arraySlice)
{
DepthStencilViewDescription dsvd = new DepthStencilViewDescription();
dsvd.Format = format;
dsvd.Flags = 0;
dsvd.Dimension = DepthStencilViewDimension.Texture2DArray;// D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
dsvd.Texture2DArray.ArraySize = 1;
dsvd.Texture2DArray.FirstArraySlice = arraySlice;
dsvd.Texture2DArray.MipSlice = 0;
DepthStencilView dsv = new DepthStencilView(device, depthStencil, dsvd);
return dsv;
}
public static DepthStencilState CreateDepthStencilState(Device device, bool depthEnable, DepthWriteMask writeMask, Comparison func, bool stencilEnable, byte stencilReadMask, byte stencilWriteMask, DepthStencilOperationDescription frontFace, DepthStencilOperationDescription backFace)
{
DepthStencilStateDescription dsd;
dsd.IsDepthEnabled = depthEnable;
dsd.DepthWriteMask = writeMask;
dsd.DepthComparison = func;
dsd.IsStencilEnabled = stencilEnable;
dsd.StencilReadMask = stencilReadMask;
dsd.StencilWriteMask = stencilWriteMask;
dsd.FrontFace = frontFace;
dsd.BackFace = backFace;
DepthStencilState s = new DepthStencilState(device, dsd);
return s;
}
public static DepthStencilState CreateDepthStencilState(Device device, bool depthEnable, DepthWriteMask writeMask)
{
DepthStencilOperationDescription frontFace = new DepthStencilOperationDescription();
DepthStencilOperationDescription backFace = new DepthStencilOperationDescription();
bool stencil = false;//depthEnable;
byte rm = 0;
byte wm = 0;
if (stencil)
{
rm = 0xFF;
wm = 0xFF;
// Stencil operations if pixel is front-facing
frontFace.FailOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP;
frontFace.DepthFailOperation = StencilOperation.Increment;// D3D11_STENCIL_OP_INCR;
frontFace.PassOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP;
frontFace.Comparison = Comparison.Always;// D3D11_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing
backFace.FailOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP;
backFace.DepthFailOperation = StencilOperation.Decrement;// D3D11_STENCIL_OP_DECR;
backFace.PassOperation = StencilOperation.Keep;// D3D11_STENCIL_OP_KEEP;
backFace.Comparison = Comparison.Always;// D3D11_COMPARISON_ALWAYS;
}
return CreateDepthStencilState(device, depthEnable, writeMask, Comparison.LessEqual, stencil, rm, wm, frontFace, backFace);
}
public static RasterizerState CreateRasterizerState(Device device, FillMode fillMode, CullMode cullMode, bool depthClipEnable, bool scissorEnable, bool multisampleEnable, int depthBias, float depthBiasClamp, float slopeScaledDepthBias)
{
RasterizerStateDescription drd = new RasterizerStateDescription();
drd.FillMode = fillMode; //D3D11_FILL_MODE FillMode;
drd.CullMode = cullMode;//D3D11_CULL_MODE CullMode;
drd.IsFrontCounterClockwise = false; //BOOL FrontCounterClockwise;
drd.DepthBias = depthBias; //INT DepthBias;
drd.DepthBiasClamp = depthBiasClamp;//FLOAT DepthBiasClamp;
drd.SlopeScaledDepthBias = slopeScaledDepthBias;//FLOAT SlopeScaledDepthBias;
drd.IsDepthClipEnabled = depthClipEnable;//BOOL DepthClipEnable;
drd.IsScissorEnabled = scissorEnable;//BOOL ScissorEnable;
drd.IsMultisampleEnabled = multisampleEnable;//BOOL MultisampleEnable;
drd.IsAntialiasedLineEnabled = false;//BOOL AntialiasedLineEnable;
RasterizerState rs = new RasterizerState(device, drd);
return rs;
}
public static RasterizerState CreateRasterizerState(Device device, FillMode fillMode, CullMode cullMode, bool depthClipEnable, bool scissorEnable, bool multisampleEnable)
{
return CreateRasterizerState(device, fillMode, cullMode, depthClipEnable, scissorEnable, multisampleEnable, 0, 0.0f, 0.0f);
}
public static RasterizerState CreateRasterizerState(Device device, FillMode fillMode, CullMode cullMode, bool depthClipEnable, bool multisampleEnable)
{
return CreateRasterizerState(device, fillMode, cullMode, depthClipEnable, false, multisampleEnable);
}
public static RasterizerState CreateRasterizerState(Device device, bool depthClipEnable, bool multisampleEnable)
{
return CreateRasterizerState(device, FillMode.Solid, CullMode.Back, depthClipEnable, false, multisampleEnable);
}
public static BlendState CreateBlendState(Device device, bool blendEnable, BlendOperation op, BlendOption src, BlendOption dst, BlendOperation opAlpha, BlendOption srcAlpha, BlendOption dstAlpha, ColorWriteMaskFlags writeMask)
{
BlendStateDescription bsd = new BlendStateDescription();
//ZeroMemory(&bsd, sizeof(bsd));
bsd.RenderTarget[0].IsBlendEnabled = blendEnable;
bsd.RenderTarget[0].BlendOperation = op;
bsd.RenderTarget[0].SourceBlend = src;
bsd.RenderTarget[0].DestinationBlend = dst;
bsd.RenderTarget[0].AlphaBlendOperation = opAlpha;
bsd.RenderTarget[0].SourceAlphaBlend = srcAlpha;
bsd.RenderTarget[0].DestinationAlphaBlend = dstAlpha;
bsd.RenderTarget[0].RenderTargetWriteMask = writeMask;
BlendState bs = new BlendState(device, bsd);
return bs;
}
public static int ElementSize(Format format)
{
//FormatHelper.SizeOfInBytes?
switch (format)
{
case Format.R32G32B32A32_Typeless:
case Format.R32G32B32A32_Float:
case Format.R32G32B32A32_UInt:
case Format.R32G32B32A32_SInt:
return 16;
case Format.R32G32B32_Typeless:
case Format.R32G32B32_Float:
case Format.R32G32B32_UInt:
case Format.R32G32B32_SInt:
return 12;
case Format.R16G16B16A16_Typeless:
case Format.R16G16B16A16_Float:
case Format.R16G16B16A16_UNorm:
case Format.R16G16B16A16_UInt:
case Format.R16G16B16A16_SNorm:
case Format.R16G16B16A16_SInt:
case Format.R32G32_Typeless:
case Format.R32G32_Float:
case Format.R32G32_UInt:
case Format.R32G32_SInt:
case Format.R32G8X24_Typeless:
case Format.D32_Float_S8X24_UInt:
case Format.R32_Float_X8X24_Typeless:
case Format.X32_Typeless_G8X24_UInt:
return 8;
case Format.R10G10B10A2_Typeless:
case Format.R10G10B10A2_UNorm:
case Format.R10G10B10A2_UInt:
case Format.R11G11B10_Float:
case Format.R8G8B8A8_Typeless:
case Format.R8G8B8A8_UNorm:
case Format.R8G8B8A8_UNorm_SRgb:
case Format.R8G8B8A8_UInt:
case Format.R8G8B8A8_SNorm:
case Format.R8G8B8A8_SInt:
case Format.R16G16_Typeless:
case Format.R16G16_Float:
case Format.R16G16_UNorm:
case Format.R16G16_UInt:
case Format.R16G16_SNorm:
case Format.R16G16_SInt:
case Format.R32_Typeless:
case Format.D32_Float:
case Format.R32_Float:
case Format.R32_UInt:
case Format.R32_SInt:
case Format.R24G8_Typeless:
case Format.D24_UNorm_S8_UInt:
case Format.R24_UNorm_X8_Typeless:
case Format.X24_Typeless_G8_UInt:
case Format.B8G8R8A8_UNorm:
case Format.B8G8R8X8_UNorm:
return 4;
case Format.R8G8_Typeless:
case Format.R8G8_UNorm:
case Format.R8G8_UInt:
case Format.R8G8_SNorm:
case Format.R8G8_SInt:
case Format.R16_Typeless:
case Format.R16_Float:
case Format.D16_UNorm:
case Format.R16_UNorm:
case Format.R16_UInt:
case Format.R16_SNorm:
case Format.R16_SInt:
case Format.B5G6R5_UNorm:
case Format.B5G5R5A1_UNorm:
return 2;
case Format.R8_Typeless:
case Format.R8_UNorm:
case Format.R8_UInt:
case Format.R8_SNorm:
case Format.R8_SInt:
case Format.A8_UNorm:
return 1;
// Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx
case Format.BC2_Typeless:
case Format.BC2_UNorm:
case Format.BC2_UNorm_SRgb:
case Format.BC3_Typeless:
case Format.BC3_UNorm:
case Format.BC3_UNorm_SRgb:
case Format.BC5_Typeless:
case Format.BC5_UNorm:
case Format.BC5_SNorm:
return 16;
// Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx
case Format.R1_UNorm:
case Format.BC1_Typeless:
case Format.BC1_UNorm:
case Format.BC1_UNorm_SRgb:
case Format.BC4_Typeless:
case Format.BC4_UNorm:
case Format.BC4_SNorm:
return 8;
// Compressed format; http://msdn2.microsoft.com/en-us/library/bb694531(VS.85).aspx
case Format.R9G9B9E5_Sharedexp:
return 4;
// These are compressed, but bit-size information is unclear.
case Format.R8G8_B8G8_UNorm:
case Format.G8R8_G8B8_UNorm:
return 4;
case Format.Unknown:
default:
return 0;
}
}
}
}
File diff suppressed because it is too large Load Diff
+376
View File
@@ -0,0 +1,376 @@
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 CodeWalker.World;
using System.Collections.Concurrent;
using CodeWalker.GameFiles;
using System.Threading;
using CodeWalker.Properties;
namespace CodeWalker.Rendering
{
public class RenderableCache
{
public DateTime LastUpdate = DateTime.Now;
public DateTime LastUnload = DateTime.Now;
public double CacheTime = Settings.Default.GPUCacheTime;// 10.0; //seconds to keep something that's not used
public double UnloadTime = Settings.Default.GPUCacheFlushTime;// 0.1; //seconds between running unload cycles
public int MaxItemsPerLoop = 1; //to keep things flowing
public bool ItemsStillPending = false; //whether or not we need another content thread loop
public long TotalGraphicsMemoryUse
{
get
{
//return (GeometryCacheUse + TextureCacheUse + BoundCompCacheUse + InstanceCacheUse);
return (renderables.CacheUse + textures.CacheUse + boundcomps.CacheUse + instbatches.CacheUse);
}
}
public int LoadedRenderableCount
{
get
{
return renderables.CurrentLoadedCount;// loadedRenderables.Count;
}
}
public int LoadedTextureCount
{
get
{
return textures.CurrentLoadedCount;// loadedTextures.Count;
}
}
public int MemCachedRenderableCount
{
get
{
return renderables.CurrentCacheCount;// cacheRenderables.Count;
}
}
public int MemCachedTextureCount
{
get
{
return textures.CurrentCacheCount;// cacheTextures.Count;
}
}
private RenderableCacheLookup<DrawableBase, Renderable> renderables = new RenderableCacheLookup<DrawableBase, Renderable>(Settings.Default.GPUGeometryCacheSize, Settings.Default.GPUCacheTime);
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<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
private object updateSyncRoot = new object();
private Device currentDevice;
public void OnDeviceCreated(Device device)
{
currentDevice = device;
}
public void OnDeviceDestroyed()
{
currentDevice = null;
renderables.Clear();
textures.Clear();
boundcomps.Clear();
instbatches.Clear();
distlodlights.Clear();
pathbatches.Clear();
waterquads.Clear();
}
public void ContentThreadProc()
{
if (currentDevice == null) return; //can't do anything with no device
Monitor.Enter(updateSyncRoot);
//load the queued items if possible
int renderablecount = renderables.LoadProc(currentDevice, MaxItemsPerLoop);
int texturecount = textures.LoadProc(currentDevice, MaxItemsPerLoop);
int boundcompcount = boundcomps.LoadProc(currentDevice, MaxItemsPerLoop);
int instbatchcount = instbatches.LoadProc(currentDevice, MaxItemsPerLoop);
int distlodlightcount = distlodlights.LoadProc(currentDevice, MaxItemsPerLoop);
int pathbatchcount = pathbatches.LoadProc(currentDevice, MaxItemsPerLoop);
int waterquadcount = waterquads.LoadProc(currentDevice, MaxItemsPerLoop);
ItemsStillPending = (renderablecount >= MaxItemsPerLoop) ||
(texturecount >= MaxItemsPerLoop) ||
(boundcompcount >= MaxItemsPerLoop) ||
(instbatchcount >= MaxItemsPerLoop) ||
(distlodlightcount >= MaxItemsPerLoop) ||
(pathbatchcount >= MaxItemsPerLoop) ||
(waterquadcount >= MaxItemsPerLoop);
//todo: change this to unload only when necessary (ie when something is loaded)
var now = DateTime.Now;
var deltat = (now - LastUpdate).TotalSeconds;
var unloadt = (now - LastUnload).TotalSeconds;
if ((unloadt > UnloadTime) && (deltat < 0.25)) //don't try the unload on every loop... or when really busy
{
//unload items that haven't been used in longer than the cache period.
renderables.UnloadProc();
textures.UnloadProc();
boundcomps.UnloadProc();
instbatches.UnloadProc();
distlodlights.UnloadProc();
pathbatches.UnloadProc();
waterquads.UnloadProc();
LastUnload = DateTime.Now;
}
LastUpdate = DateTime.Now;
Monitor.Exit(updateSyncRoot);
}
public void RenderThreadSync()
{
renderables.RenderThreadSync();
textures.RenderThreadSync();
boundcomps.RenderThreadSync();
instbatches.RenderThreadSync();
distlodlights.RenderThreadSync();
pathbatches.RenderThreadSync();
waterquads.RenderThreadSync();
}
public Renderable GetRenderable(DrawableBase drawable)
{
return renderables.Get(drawable);
}
public RenderableTexture GetRenderableTexture(Texture texture)
{
return textures.Get(texture);
}
public RenderableBoundComposite GetRenderableBoundComp(BoundComposite boundcomp)
{
return boundcomps.Get(boundcomp);
}
public RenderableInstanceBatch GetRenderableInstanceBatch(YmapGrassInstanceBatch batch)
{
return instbatches.Get(batch);
}
public RenderableDistantLODLights GetRenderableDistantLODLights(YmapDistantLODLights lights)
{
return distlodlights.Get(lights);
}
public RenderablePathBatch GetRenderablePathBatch(BasePathData pathdata)
{
return pathbatches.Get(pathdata);
}
public RenderableWaterQuad GetRenderableWaterQuad(WaterQuad quad)
{
return waterquads.Get(quad);
}
public void Invalidate(BasePathData path)
{
lock (updateSyncRoot)
{
pathbatches.Invalidate(path);
}
}
}
public abstract class RenderableCacheItem<TKey>
{
public TKey Key;
public volatile bool IsLoaded = false;
public volatile bool LoadQueued = false;
public long LastUseTime = 0;
//public DateTime LastUseTime { get; set; }
public long DataSize { get; set; }
public abstract void Init(TKey key);
public abstract void Load(Device device);
public abstract void Unload();
}
public class RenderableCacheLookup<TKey, TVal> where TVal: RenderableCacheItem<TKey>, new()
{
private ConcurrentStack<TVal> itemsToLoad = new ConcurrentStack<TVal>();
private ConcurrentStack<TVal> itemsToUnload = new ConcurrentStack<TVal>();
private LinkedList<TVal> loadeditems = new LinkedList<TVal>();
private Dictionary<TKey, TVal> cacheitems = new Dictionary<TKey, TVal>();
public long CacheLimit;
public long CacheUse = 0;
public double CacheTime;
public int LoadedCount = 0;//temporary, per loop
public RenderableCacheLookup(long limit, double time)
{
CacheLimit = limit;
CacheTime = time;
}
public int CurrentLoadedCount
{
get
{
return loadeditems.Count;
}
}
public int CurrentCacheCount
{
get
{
return cacheitems.Count;
}
}
public void Clear()
{
TVal item;
while (itemsToLoad.TryPop(out item))
{ }
foreach (TVal rnd in loadeditems)
{
rnd.Unload();
}
loadeditems.Clear();
cacheitems.Clear();
while (itemsToUnload.TryPop(out item))
{ }
}
public int LoadProc(Device device, int maxitemsperloop)
{
TVal item;
LoadedCount = 0;
while (itemsToLoad.TryPop(out item))
{
if (item.IsLoaded) continue; //don't load it again...
LoadedCount++;
long gcachefree = CacheLimit - CacheUse;
if (gcachefree > item.DataSize)
{
try
{
item.Load(device);
loadeditems.AddLast(item);
Interlocked.Add(ref CacheUse, item.DataSize);
}
catch //(Exception ex)
{
//todo: error handling...
}
}
else
{
item.LoadQueued = false; //can try load it again later..
}
if (LoadedCount >= maxitemsperloop) break;
}
return LoadedCount;
}
public void UnloadProc()
{
//unload items that haven't been used in longer than the cache period.
var now = DateTime.Now;
var rnode = loadeditems.First;
while (rnode != null)
{
var lu = DateTime.FromBinary(Interlocked.Read(ref rnode.Value.LastUseTime));
if ((now - lu).TotalSeconds > CacheTime)
{
var nextnode = rnode.Next;
itemsToUnload.Push(rnode.Value);
loadeditems.Remove(rnode);
rnode = nextnode;
}
else
{
rnode = rnode.Next;
}
}
}
public void RenderThreadSync()
{
TVal item;
while (itemsToUnload.TryPop(out item))
{
if ((item.Key != null) && (cacheitems.ContainsKey(item.Key)))
{
cacheitems.Remove(item.Key);
}
item.Unload();
item.LoadQueued = false;
Interlocked.Add(ref CacheUse, -item.DataSize);
}
}
public TVal Get(TKey key)
{
if (key == null) return null;
TVal item = null;
if (!cacheitems.TryGetValue(key, out item))
{
item = new TVal();
item.Init(key);
cacheitems.Add(key, item);
}
Interlocked.Exchange(ref item.LastUseTime, DateTime.Now.ToBinary());
if ((!item.IsLoaded) && (!item.LoadQueued))// ||
{
item.LoadQueued = true;
itemsToLoad.Push(item);
}
return item;
}
public void Invalidate(TKey key)
{
if (key == null) return;
TVal item = null;
if (!cacheitems.TryGetValue(key, out item)) return;
if (item == null) return;
if ((item.Key != null) && (cacheitems.ContainsKey(item.Key)))
{
cacheitems.Remove(item.Key);
item.Unload();
item.LoadQueued = false;
Interlocked.Add(ref CacheUse, -item.DataSize);
Interlocked.Exchange(ref item.LastUseTime, DateTime.Now.AddHours(-1).ToBinary());
loadeditems.Remove(item);//slow...
}
}
}
}
File diff suppressed because it is too large Load Diff
+885
View File
@@ -0,0 +1,885 @@
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.IO;
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;
using CodeWalker.GameFiles;
using CodeWalker.World;
namespace CodeWalker.Rendering
{
public struct BasicShaderVSSceneVars
{
public Matrix ViewProj;
public Vector4 WindVector;
}
public struct BasicShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
public uint HasSkeleton;
public uint HasTransforms;
public uint TintPaletteIndex;
public uint Pad1;
public Vector3 Scale;
public uint IsInstanced;
}
public struct BasicShaderVSModelVars
{
public Matrix Transform;
}
public struct BasicShaderVSGeomVars
{
public uint EnableTint;
public float TintYVal;
public uint IsDecal;
public uint EnableWind;
public Vector4 WindOverrideParams;
}
public struct BasicShaderPSSceneVars
{
public ShaderGlobalLightParams GlobalLights;
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 struct BasicShaderPSGeomVars
{
public uint EnableTexture;
public uint EnableTint;
public uint EnableNormalMap;
public uint EnableSpecMap;
public uint EnableDetailMap;
public uint IsDecal;
public uint IsEmissive;
public uint IsDistMap;
public float bumpiness;
public float AlphaScale;
public float HardAlphaBlend;
public float useTessellation;
public Vector4 detailSettings;
public Vector3 specMapIntMask;
public float specularIntensityMult;
public float specularFalloffMult;
public float specularFresnel;
public float wetnessMultiplier;
public uint SpecOnly;
}
public struct BasicShaderInstGlobalMatrix
{
public Vector4 Row1;
public Vector4 Row2;
public Vector4 Row3;
}
public struct BasicShaderInstGlobals
{
public BasicShaderInstGlobalMatrix M0;
public BasicShaderInstGlobalMatrix M1;
public BasicShaderInstGlobalMatrix M2;
public BasicShaderInstGlobalMatrix M3;
public BasicShaderInstGlobalMatrix M4;
public BasicShaderInstGlobalMatrix M5;
public BasicShaderInstGlobalMatrix M6;
public BasicShaderInstGlobalMatrix M7;
}
public struct BasicShaderInstLocals
{
public Vector3 vecBatchAabbMin;
public float instPad0;
public Vector3 vecBatchAabbDelta;
public float instPad1;
public Vector4 vecPlayerPos;
public Vector2 _vecCollParams;
public Vector2 instPad2;
public Vector4 fadeAlphaDistUmTimer;
public Vector4 uMovementParams;
public Vector4 _fakedGrassNormal;
public Vector3 gScaleRange;
public float instPad3;
public Vector4 gWindBendingGlobals;
public Vector2 gWindBendScaleVar;
public float gAlphaTest;
public float gAlphaToCoverageScale;
public Vector3 gLodFadeInstRange;
public uint gUseComputeShaderOutputBuffer;
}
public class BasicShader : Shader, IDisposable
{
bool disposed = false;
VertexShader basicvspnct;
VertexShader basicvspncct;
VertexShader basicvspncctt;
VertexShader basicvspnccttt;
VertexShader basicvspnctx;
VertexShader basicvspncctx;
VertexShader basicvspncttx;
VertexShader basicvspnccttx;
VertexShader basicvspnctttx;
VertexShader basicvspncctttx;
VertexShader basicvsbox;
VertexShader basicvssphere;
VertexShader basicvscapsule;
VertexShader basicvscylinder;
PixelShader basicps;
GpuVarsBuffer<BasicShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<BasicShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<BasicShaderVSModelVars> VSModelVars;
GpuVarsBuffer<BasicShaderVSGeomVars> VSGeomVars;
GpuVarsBuffer<BasicShaderPSSceneVars> PSSceneVars;
GpuVarsBuffer<BasicShaderPSGeomVars> PSGeomVars;
GpuVarsBuffer<BasicShaderInstGlobals> InstGlobalVars;
GpuVarsBuffer<BasicShaderInstLocals> InstLocalVars;
SamplerState texsampler;
SamplerState texsampleranis;
SamplerState texsamplertnt;
SamplerState texsamplertntyft;
UnitCube cube; //for collision box render
UnitSphere sphere; //for collision sphere render
UnitCapsule capsule; //for collision capsule render
UnitCylinder cylinder; //for collision cylinder render
public bool AnisotropicFilter = false;
public bool DecalMode = false;
public float AlphaScale = 1.0f;
public Vector4 WindVector = Vector4.Zero;
public WorldRenderMode RenderMode = WorldRenderMode.Default;
public int RenderVertexColourIndex = 1;
public int RenderTextureCoordIndex = 1;
public int RenderTextureSamplerCoord = 1;
public MetaName RenderTextureSampler = MetaName.DiffuseSampler;
public bool SpecularEnable = true;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public BasicShader(Device device)
{
byte[] vspnctbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCT.cso");
byte[] vspncctbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCT.cso");
byte[] vspnccttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTT.cso");
byte[] vspncctttbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTT.cso");
byte[] vspnctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTX.cso");
byte[] vspncctxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTX.cso");
byte[] vspncttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTTX.cso");
byte[] vspnccttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTX.cso");
byte[] vspnctttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCTTTX.cso");
byte[] vspncctttxbytes = File.ReadAllBytes("Shaders\\BasicVS_PNCCTTTX.cso");
byte[] vsboxbytes = File.ReadAllBytes("Shaders\\BasicVS_Box.cso");
byte[] vsspherebytes = File.ReadAllBytes("Shaders\\BasicVS_Sphere.cso");
byte[] vscapsulebytes = File.ReadAllBytes("Shaders\\BasicVS_Capsule.cso");
byte[] vscylinderbytes = File.ReadAllBytes("Shaders\\BasicVS_Cylinder.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\BasicPS.cso");
basicvspnct = new VertexShader(device, vspnctbytes);
basicvspncct = new VertexShader(device, vspncctbytes);
basicvspncctt = new VertexShader(device, vspnccttbytes);
basicvspnccttt = new VertexShader(device, vspncctttbytes);
basicvspnctx = new VertexShader(device, vspnctxbytes);
basicvspncctx = new VertexShader(device, vspncctxbytes);
basicvspncttx = new VertexShader(device, vspncttxbytes);
basicvspnccttx = new VertexShader(device, vspnccttxbytes);
basicvspnctttx = new VertexShader(device, vspnctttxbytes);
basicvspncctttx = new VertexShader(device, vspncctttxbytes);
basicvsbox = new VertexShader(device, vsboxbytes);
basicvssphere = new VertexShader(device, vsspherebytes);
basicvscapsule = new VertexShader(device, vscapsulebytes);
basicvscylinder = new VertexShader(device, vscylinderbytes);
basicps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<BasicShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<BasicShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<BasicShaderVSModelVars>(device);
VSGeomVars = new GpuVarsBuffer<BasicShaderVSGeomVars>(device);
PSSceneVars = new GpuVarsBuffer<BasicShaderPSSceneVars>(device);
PSGeomVars = new GpuVarsBuffer<BasicShaderPSGeomVars>(device);
InstGlobalVars = new GpuVarsBuffer<BasicShaderInstGlobals>(device);
InstLocalVars = new GpuVarsBuffer<BasicShaderInstLocals>(device);
InitInstGlobalVars();
//supported layouts - requires Position, Normal, Colour, Texcoord
layouts.Add(VertexType.Default, new InputLayout(device, vspnctbytes, VertexTypeDefault.GetLayout()));
layouts.Add(VertexType.PNCH2, new InputLayout(device, vspnctbytes, VertexTypePNCH2.GetLayout()));
layouts.Add(VertexType.PCCNCT, new InputLayout(device, vspncctbytes, VertexTypePCCNCT.GetLayout()));
layouts.Add(VertexType.PCCNCCT, new InputLayout(device, vspncctbytes, VertexTypePCCNCCT.GetLayout()));
layouts.Add(VertexType.PNCCT, new InputLayout(device, vspncctbytes, VertexTypePNCCT.GetLayout()));
layouts.Add(VertexType.PNCCTT, new InputLayout(device, vspnccttbytes, VertexTypePNCCTT.GetLayout()));
layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vspncctttbytes, VertexTypePNCCTTTT.GetLayout()));
//normalmap layouts - requires Position, Normal, Colour, Texcoord, Tangent (X)
layouts.Add(VertexType.DefaultEx, new InputLayout(device, vspnctxbytes, VertexTypeDefaultEx.GetLayout()));
layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vspnctxbytes, VertexTypePCCH2H4.GetLayout()));
layouts.Add(VertexType.PCCNCTX, new InputLayout(device, vspncctxbytes, VertexTypePCCNCTX.GetLayout()));
layouts.Add(VertexType.PCCNCCTX, new InputLayout(device, vspncctxbytes, VertexTypePCCNCCTX.GetLayout()));
layouts.Add(VertexType.PNCCTX, new InputLayout(device, vspncctxbytes, VertexTypePNCCTX.GetLayout()));
layouts.Add(VertexType.PNCTTX, new InputLayout(device, vspncttxbytes, VertexTypePNCTTX.GetLayout()));
layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vspnccttxbytes, VertexTypePNCCTTX.GetLayout()));
layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vspnccttxbytes, VertexTypePNCCTTX_2.GetLayout()));
layouts.Add(VertexType.PCCNCCTTX, new InputLayout(device, vspnccttxbytes, VertexTypePCCNCCTTX.GetLayout()));
layouts.Add(VertexType.PNCTTTX, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTX.GetLayout()));
layouts.Add(VertexType.PNCTTTX_2, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTX_2.GetLayout()));
layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTX_3.GetLayout()));
layouts.Add(VertexType.PNCTTTTX, new InputLayout(device, vspnctttxbytes, VertexTypePNCTTTTX.GetLayout()));
layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vspncctttxbytes, VertexTypePNCCTTTX.GetLayout()));
layouts.Add(VertexType.PCCNCTT, new InputLayout(device, vspnccttbytes, VertexTypePCCNCTT.GetLayout()));
layouts.Add(VertexType.PCCNCTTX, new InputLayout(device, vspnccttxbytes, VertexTypePCCNCTTX.GetLayout()));
layouts.Add(VertexType.PCCNCTTT, new InputLayout(device, vspncctttbytes, VertexTypePCCNCTTT.GetLayout()));
layouts.Add(VertexType.PNCTT, new InputLayout(device, vspnctbytes, VertexTypePNCTT.GetLayout()));
layouts.Add(VertexType.PNCTTT, new InputLayout(device, vspnctbytes, VertexTypePNCTTT.GetLayout()));
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsampleranis = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.Anisotropic,
MaximumAnisotropy = 8,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsamplertnt = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Clamp,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.White,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipPoint,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsamplertntyft = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.White,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipPoint,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
cube = new UnitCube(device, vsboxbytes, false, false, true);
sphere = new UnitSphere(device, vsspherebytes, 4);
capsule = new UnitCapsule(device, vscapsulebytes, 4);
cylinder = new UnitCylinder(device, vscylinderbytes, 8);
}
private void InitInstGlobalVars()
{
var m0 = Matrix3x3.RotationZ(0.00f * (float)Math.PI);
var m1 = Matrix3x3.RotationZ(0.25f * (float)Math.PI);
var m2 = Matrix3x3.RotationZ(0.50f * (float)Math.PI);
var m3 = Matrix3x3.RotationZ(0.75f * (float)Math.PI);
var m4 = Matrix3x3.RotationZ(1.00f * (float)Math.PI);
var m5 = Matrix3x3.RotationZ(1.25f * (float)Math.PI);
var m6 = Matrix3x3.RotationZ(1.50f * (float)Math.PI);
var m7 = Matrix3x3.RotationZ(1.75f * (float)Math.PI);
InstGlobalVars.Vars.M0.Row1 = new Vector4(m0.Row1, 1);
InstGlobalVars.Vars.M0.Row2 = new Vector4(m0.Row2, 1);
InstGlobalVars.Vars.M0.Row3 = new Vector4(m0.Row3, 1);
InstGlobalVars.Vars.M1.Row1 = new Vector4(m1.Row1, 1);
InstGlobalVars.Vars.M1.Row2 = new Vector4(m1.Row2, 1);
InstGlobalVars.Vars.M1.Row3 = new Vector4(m1.Row3, 1);
InstGlobalVars.Vars.M2.Row1 = new Vector4(m2.Row1, 1);
InstGlobalVars.Vars.M2.Row2 = new Vector4(m2.Row2, 1);
InstGlobalVars.Vars.M2.Row3 = new Vector4(m2.Row3, 1);
InstGlobalVars.Vars.M3.Row1 = new Vector4(m3.Row1, 1);
InstGlobalVars.Vars.M3.Row2 = new Vector4(m3.Row2, 1);
InstGlobalVars.Vars.M3.Row3 = new Vector4(m3.Row3, 1);
InstGlobalVars.Vars.M4.Row1 = new Vector4(m4.Row1, 1);
InstGlobalVars.Vars.M4.Row2 = new Vector4(m4.Row2, 1);
InstGlobalVars.Vars.M4.Row3 = new Vector4(m4.Row3, 1);
InstGlobalVars.Vars.M5.Row1 = new Vector4(m5.Row1, 1);
InstGlobalVars.Vars.M5.Row2 = new Vector4(m5.Row2, 1);
InstGlobalVars.Vars.M5.Row3 = new Vector4(m5.Row3, 1);
InstGlobalVars.Vars.M6.Row1 = new Vector4(m6.Row1, 1);
InstGlobalVars.Vars.M6.Row2 = new Vector4(m6.Row2, 1);
InstGlobalVars.Vars.M6.Row3 = new Vector4(m6.Row3, 1);
InstGlobalVars.Vars.M7.Row1 = new Vector4(m7.Row1, 1);
InstGlobalVars.Vars.M7.Row2 = new Vector4(m7.Row2, 1);
InstGlobalVars.Vars.M7.Row3 = new Vector4(m7.Row3, 1);
}
private void SetVertexShader(DeviceContext context, VertexType type)
{
VertexShader vs = basicvspnct;
switch (type)
{
case VertexType.Default:
case VertexType.PNCH2:
case VertexType.PNCTT:
case VertexType.PNCTTT:
vs = basicvspnct;
break;
case VertexType.PCCNCT:
case VertexType.PCCNCCT:
case VertexType.PNCCT:
vs = basicvspncct;
break;
case VertexType.PNCCTT://not used?
case VertexType.PCCNCTT:
vs = basicvspncctt;
break;
case VertexType.PNCCTTTT://not used?
case VertexType.PCCNCTTT:
vs = basicvspnccttt;
break;
case VertexType.DefaultEx:
case VertexType.PCCH2H4:
vs = basicvspnctx;
break;
case VertexType.PCCNCTX:
case VertexType.PCCNCCTX:
case VertexType.PNCCTX:
vs = basicvspncctx;
break;
case VertexType.PNCTTX:
vs = basicvspncttx;
break;
case VertexType.PNCCTTX://not used?
case VertexType.PNCCTTX_2://not used?
case VertexType.PCCNCCTTX://not used?
case VertexType.PCCNCTTX:
vs = basicvspnccttx;
break;
case VertexType.PNCTTTX:
case VertexType.PNCTTTX_2:
case VertexType.PNCTTTX_3:
case VertexType.PNCTTTTX: //not using last texcoords!
vs = basicvspnctttx;
break;
case VertexType.PNCCTTTX://not used?
vs = basicvspncctttx;
break;
default:
break;
}
context.VertexShader.Set(vs);
}
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(basicps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
InputLayout l;
if (layouts.TryGetValue(type, out l))
{
SetVertexShader(context, type);
context.InputAssembler.InputLayout = l;
return true;
}
return false;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
uint rendermode = 0;
uint rendermodeind = 1;
SpecularEnable = lights.SpecularEnabled;
switch (RenderMode)
{
case WorldRenderMode.VertexNormals:
rendermode = 1;
break;
case WorldRenderMode.VertexTangents:
rendermode = 2;
break;
case WorldRenderMode.VertexColour:
rendermode = 3;
rendermodeind = (uint)RenderVertexColourIndex;
break;
case WorldRenderMode.TextureCoord:
rendermode = 4;
rendermodeind = (uint)RenderTextureCoordIndex;
break;
case WorldRenderMode.SingleTexture:
rendermode = 8;//direct mode
break;
}
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Vars.WindVector = WindVector;
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
PSSceneVars.Vars.GlobalLights = lights.Params;
PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u;
PSSceneVars.Vars.RenderMode = rendermode;
PSSceneVars.Vars.RenderModeIndex = rendermodeind;
PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord;
PSSceneVars.Update(context);
PSSceneVars.SetPSCBuffer(context, 0);
if (shadowmap != null)
{
shadowmap.SetFinalRenderResources(context);
}
if (!InstGlobalVars.Flag) //on the first frame, update the instance globals
{
InstGlobalVars.Update(context);
InstGlobalVars.Flag = true;
}
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Vars.Scale = rend.Scale;
VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0;
VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0;
VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex;
VSEntityVars.Vars.IsInstanced = 0;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (!model.UseTransform) return;
VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
VSModelVars.Update(context);
VSModelVars.SetVSCBuffer(context, 3);
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
RenderableTexture texture = null;
RenderableTexture tintpal = null;
RenderableTexture bumptex = null;
RenderableTexture spectex = null;
RenderableTexture detltex = null;
bool isdistmap = false;
float tntpalind = 0.0f;
if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0))
{
if (RenderMode == WorldRenderMode.Default)
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
if (itex == null) continue;
switch (ihash)
{
case MetaName.DiffuseSampler:
texture = itex;
break;
case MetaName.BumpSampler:
bumptex = itex;
break;
case MetaName.SpecSampler:
spectex = itex;
break;
case MetaName.DetailSampler:
detltex = itex;
break;
case MetaName.TintPaletteSampler:
tintpal = itex;
if (tintpal.Key != null)
{
//this is slightly dodgy but VSEntityVars should have the correct value in it...
tntpalind = (VSEntityVars.Vars.TintPaletteIndex + 0.5f) / tintpal.Key.Height;
}
break;
case MetaName.distanceMapSampler:
texture = itex;
isdistmap = true;
break;
case MetaName.heightSampler:
case MetaName.EnvironmentSampler:
break;
case MetaName.FlowSampler:
case MetaName.FogSampler:
case MetaName.FoamSampler:
if (texture == null) texture = itex;
break;
default:
if (texture == null) texture = itex;
break;
}
}
}
else if (RenderMode == WorldRenderMode.SingleTexture)
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
if (ihash == RenderTextureSampler)
{
texture = itex;
break;
}
}
}
}
bool usediff = ((texture != null) && (texture.ShaderResourceView != null));
bool usebump = ((bumptex != null) && (bumptex.ShaderResourceView != null));
bool usespec = ((spectex != null) && (spectex.ShaderResourceView != null));
bool usedetl = ((detltex != null) && (detltex.ShaderResourceView != null));
bool usetint = ((tintpal != null) && (tintpal.ShaderResourceView != null));
uint tintflag = 0;
if (usetint) tintflag = 1;
uint windflag = geom.EnableWind ? 1u : 0u;
uint emflag = geom.IsEmissive ? 1u : 0u;
var shaderName = geom.DrawableGeom.Shader.Name;
var shaderFile = geom.DrawableGeom.Shader.FileName;
switch (shaderFile.Hash)
{
case 2245870123: //trees_normal_diffspec_tnt.sps
case 3334613197: //trees_tnt.sps
case 1229591973://{trees_normal_spec_tnt.sps}
if (usetint) tintflag = 2; //use 2nd vertex colour channel for tint...
break;
case 3880384844://{decal_spec_only.sps}w
case 600733812://{decal_amb_only.sps}
case 2842248626://{spec_decal.sps}
case 2457676400://{reflect_decal.sps}
case 2706821972://{mirror_decal.sps}
//if (RenderMode == WorldRenderMode.Default) usediff = false;
break;
}
uint pstintflag = tintflag;
if (VSEntityVars.Vars.IsInstanced>0)
{
pstintflag = 1;
switch (shaderFile.Hash)
{
case 916743331: //{grass_batch.sps}
windflag = 1;
break;
case 3833671083://{normal_spec_batch.sps}
windflag = 0;
break;
default:
break;
}
}
PSGeomVars.Vars.EnableTexture = usediff ? 1u : 0u;
PSGeomVars.Vars.EnableTint = pstintflag;
PSGeomVars.Vars.EnableNormalMap = usebump ? 1u : 0u;
PSGeomVars.Vars.EnableSpecMap = usespec ? 1u : 0u;
PSGeomVars.Vars.EnableDetailMap = usedetl ? 1u : 0u;
PSGeomVars.Vars.IsDecal = DecalMode ? 1u : 0u;
PSGeomVars.Vars.IsEmissive = emflag;
PSGeomVars.Vars.IsDistMap = isdistmap ? 1u : 0u;
PSGeomVars.Vars.bumpiness = geom.bumpiness;
PSGeomVars.Vars.AlphaScale = isdistmap ? 1.0f : AlphaScale;
PSGeomVars.Vars.HardAlphaBlend = 0.0f; //todo: cutouts flag!
PSGeomVars.Vars.useTessellation = 0.0f;
PSGeomVars.Vars.detailSettings = geom.detailSettings;
PSGeomVars.Vars.specMapIntMask = geom.specMapIntMask;
PSGeomVars.Vars.specularIntensityMult = SpecularEnable ? geom.specularIntensityMult : 0.0f;
PSGeomVars.Vars.specularFalloffMult = geom.specularFalloffMult;
PSGeomVars.Vars.specularFresnel = geom.specularFresnel;
PSGeomVars.Vars.wetnessMultiplier = geom.wetnessMultiplier;
PSGeomVars.Vars.SpecOnly = geom.SpecOnly ? 1u : 0u;
PSGeomVars.Update(context);
PSGeomVars.SetPSCBuffer(context, 2);
VSGeomVars.Vars.EnableTint = tintflag;
VSGeomVars.Vars.TintYVal = tntpalind;
VSGeomVars.Vars.IsDecal = DecalMode ? 1u : 0u;
VSGeomVars.Vars.EnableWind = windflag;
VSGeomVars.Vars.WindOverrideParams = geom.WindOverrideParams;
VSGeomVars.Update(context);
VSGeomVars.SetVSCBuffer(context, 4);
context.VertexShader.SetSampler(0, geom.IsFragment ? texsamplertntyft : texsamplertnt);
context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler);
if (usediff)
{
texture.SetPSResource(context, 0);
}
if (usebump)
{
bumptex.SetPSResource(context, 2);
}
if (usespec)
{
spectex.SetPSResource(context, 3);
}
if (usedetl)
{
detltex.SetPSResource(context, 4);
}
if (usetint)
{
tintpal.SetVSResource(context, 0);
}
}
public void SetInstanceVars(DeviceContext context, RenderableInstanceBatch batch)
{
var gb = batch.Key;
VSEntityVars.Vars.CamRel = new Vector4(gb.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = Quaternion.Identity;
VSEntityVars.Vars.Scale = Vector3.One;
VSEntityVars.Vars.HasSkeleton = 0;
VSEntityVars.Vars.HasTransforms = 0;
VSEntityVars.Vars.TintPaletteIndex = 0;
VSEntityVars.Vars.IsInstanced = 1;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
InstGlobalVars.SetVSCBuffer(context, 5);
InstLocalVars.Vars.vecBatchAabbMin = gb.AABBMin;
InstLocalVars.Vars.vecBatchAabbDelta = gb.AABBMax - gb.AABBMin;
InstLocalVars.Vars.vecPlayerPos = new Vector4(gb.Position - gb.CamRel, 1.0f);
InstLocalVars.Vars._vecCollParams = new Vector2(2.0f, -3.0f);//range, offset
InstLocalVars.Vars.fadeAlphaDistUmTimer = new Vector4(0.0f);
InstLocalVars.Vars.uMovementParams = new Vector4(0.0f);
InstLocalVars.Vars._fakedGrassNormal = new Vector4(Vector3.Normalize(-gb.CamRel), 0.0f);
InstLocalVars.Vars.gScaleRange = gb.Batch.ScaleRange;
InstLocalVars.Vars.gWindBendingGlobals = new Vector4(WindVector.X, WindVector.Y, 1.0f, 1.0f);
InstLocalVars.Vars.gWindBendScaleVar = new Vector2(WindVector.Z, WindVector.W);
InstLocalVars.Vars.gAlphaTest = 0.0f;
InstLocalVars.Vars.gAlphaToCoverageScale = 1.0f;
InstLocalVars.Vars.gLodFadeInstRange = new Vector3(gb.Batch.LodInstFadeRange, gb.Batch.LodFadeStartDist, gb.Batch.lodDist);
InstLocalVars.Vars.gUseComputeShaderOutputBuffer = 0;
InstLocalVars.Update(context);
InstLocalVars.SetVSCBuffer(context, 6);
context.VertexShader.SetShaderResource(2, batch.GrassInstanceBuffer.SRV);
}
public void RenderBoundGeom(DeviceContext context, RenderableBoundGeometryInst inst)
{
VSEntityVars.Vars.CamRel = new Vector4(inst.Inst.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = inst.Inst.Orientation;
VSEntityVars.Vars.Scale = inst.Inst.Scale;
VSEntityVars.Vars.HasSkeleton = 0;
VSEntityVars.Vars.HasTransforms = 0; //todo! bounds transforms..?
VSEntityVars.Vars.TintPaletteIndex = 0;
VSEntityVars.Vars.IsInstanced = 0;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
PSGeomVars.Vars.EnableTexture = 0;
PSGeomVars.Vars.EnableTint = 0;
PSGeomVars.Vars.EnableNormalMap = 0;
PSGeomVars.Vars.EnableSpecMap = 0;
PSGeomVars.Vars.EnableDetailMap = 0;
PSGeomVars.Vars.IsDecal = 0;
PSGeomVars.Vars.IsEmissive = 0;
PSGeomVars.Vars.IsDistMap = 0;
PSGeomVars.Vars.bumpiness = 0;
PSGeomVars.Vars.AlphaScale = 1;
PSGeomVars.Vars.HardAlphaBlend = 0;
PSGeomVars.Vars.useTessellation = 0;
PSGeomVars.Vars.detailSettings = Vector4.Zero;
PSGeomVars.Vars.specMapIntMask = Vector3.Zero;
PSGeomVars.Vars.specularIntensityMult = 1.0f;
PSGeomVars.Vars.specularFalloffMult = 1.0f;
PSGeomVars.Vars.specularFresnel = 1.0f;
PSGeomVars.Vars.wetnessMultiplier = 0.0f;
PSGeomVars.Vars.SpecOnly = 0;
PSGeomVars.Update(context);
PSGeomVars.SetPSCBuffer(context, 2);
VSGeomVars.Vars.EnableTint = 0;
VSGeomVars.Vars.TintYVal = 0.0f;
VSGeomVars.Vars.IsDecal = 0;
VSGeomVars.Vars.EnableWind = 0;
VSGeomVars.Vars.WindOverrideParams = Vector4.Zero;
VSGeomVars.Update(context);
VSGeomVars.SetVSCBuffer(context, 4);
if (inst.Geom.VertexBuffer != null) //render the triangles
{
SetVertexShader(context, VertexType.Default);
SetInputLayout(context, VertexType.Default);
inst.Geom.RenderTriangles(context);
}
//render the boxes
if (inst.Geom.BoxBuffer != null)
{
context.VertexShader.Set(basicvsbox);
context.VertexShader.SetShaderResource(1, inst.Geom.BoxBuffer.SRV);
cube.DrawInstanced(context, inst.Geom.BoxBuffer.StructCount);
}
//render the spheres
if (inst.Geom.SphereBuffer != null)
{
context.VertexShader.Set(basicvssphere);
context.VertexShader.SetShaderResource(1, inst.Geom.SphereBuffer.SRV);
sphere.DrawInstanced(context, inst.Geom.SphereBuffer.StructCount);
}
//render the capsules
if (inst.Geom.CapsuleBuffer != null)
{
context.VertexShader.Set(basicvscapsule);
context.VertexShader.SetShaderResource(1, inst.Geom.CapsuleBuffer.SRV);
capsule.DrawInstanced(context, inst.Geom.CapsuleBuffer.StructCount);
}
//render the cylinders
if (inst.Geom.CylinderBuffer != null)
{
context.VertexShader.Set(basicvscylinder);
context.VertexShader.SetShaderResource(1, inst.Geom.CylinderBuffer.SRV);
cylinder.DrawInstanced(context, inst.Geom.CylinderBuffer.StructCount);
}
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetShaderResource(1, null);//shadowmap
context.PixelShader.SetSampler(1, null); //shadowmap
context.VertexShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(3, null);
context.PixelShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(4, null);
context.VertexShader.SetConstantBuffer(5, null);
context.VertexShader.SetConstantBuffer(6, null);
context.VertexShader.SetSampler(0, null);
context.PixelShader.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.PixelShader.SetShaderResource(2, null);
context.PixelShader.SetShaderResource(3, null);
context.PixelShader.SetShaderResource(4, null);
context.VertexShader.SetShaderResource(0, null);
context.VertexShader.SetShaderResource(1, null);
context.VertexShader.SetShaderResource(2, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
cube.Dispose();
sphere.Dispose();
capsule.Dispose();
cylinder.Dispose();
texsampler.Dispose();
texsampleranis.Dispose();
texsamplertnt.Dispose();
foreach (InputLayout layout in layouts.Values)
{
layout.Dispose();
}
layouts.Clear();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSModelVars.Dispose();
VSGeomVars.Dispose();
PSSceneVars.Dispose();
PSGeomVars.Dispose();
InstGlobalVars.Dispose();
InstLocalVars.Dispose();
basicps.Dispose();
basicvspnct.Dispose();
basicvspncct.Dispose();
basicvspncctt.Dispose();
basicvspnccttt.Dispose();
basicvspnctx.Dispose();
basicvspncctx.Dispose();
basicvspncttx.Dispose();
basicvspnccttx.Dispose();
basicvspnctttx.Dispose();
basicvspncctttx.Dispose();
basicvsbox.Dispose();
basicvssphere.Dispose();
basicvscapsule.Dispose();
basicvscylinder.Dispose();
disposed = true;
}
}
}
+239
View File
@@ -0,0 +1,239 @@
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,
}
}
+345
View File
@@ -0,0 +1,345 @@
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.IO;
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;
using CodeWalker.GameFiles;
using CodeWalker.World;
namespace CodeWalker.Rendering
{
public struct CableShaderVSSceneVars
{
public Matrix ViewProj;
}
public struct CableShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
public uint HasSkeleton;
public uint HasTransforms;
public uint TintPaletteIndex;
public uint Pad1;
public Vector3 Scale;
public uint IsInstanced;
}
public struct CableShaderVSModelVars
{
public Matrix Transform;
}
public struct CableShaderVSGeomVars
{
public uint EnableTint;
public float TintYVal;
public uint IsDecal;
public uint Pad5;
}
public struct CableShaderPSSceneVars
{
public ShaderGlobalLightParams GlobalLights;
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 struct CableShaderPSGeomVars
{
public uint EnableTexture;
public uint EnableTint;
public uint Pad100;
public uint Pad101;
}
public class CableShader : Shader, IDisposable
{
bool disposed = false;
VertexShader vs;
PixelShader ps;
GpuVarsBuffer<CableShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<CableShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<CableShaderVSModelVars> VSModelVars;
GpuVarsBuffer<CableShaderVSGeomVars> VSGeomVars;
GpuVarsBuffer<CableShaderPSSceneVars> PSSceneVars;
GpuVarsBuffer<CableShaderPSGeomVars> PSGeomVars;
SamplerState texsampler;
public WorldRenderMode RenderMode = WorldRenderMode.Default;
public int RenderVertexColourIndex = 1;
public int RenderTextureCoordIndex = 1;
public int RenderTextureSamplerCoord = 1;
public MetaName RenderTextureSampler = MetaName.DiffuseSampler;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public CableShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\CableVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\CablePS.cso");
vs = new VertexShader(device, vsbytes);
ps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<CableShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<CableShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<CableShaderVSModelVars>(device);
VSGeomVars = new GpuVarsBuffer<CableShaderVSGeomVars>(device);
PSSceneVars = new GpuVarsBuffer<CableShaderPSSceneVars>(device);
PSGeomVars = new GpuVarsBuffer<CableShaderPSGeomVars>(device);
//supported layout - requires Position, Normal, Colour, Texcoord
layouts.Add(VertexType.Default, new InputLayout(device, vsbytes, VertexTypeDefault.GetLayout()));
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
private void SetVertexShader(DeviceContext context, VertexType type)
{
switch (type)
{
case VertexType.Default:
break;
default:
break;
}
context.VertexShader.Set(vs);
}
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(ps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
InputLayout l;
if (layouts.TryGetValue(type, out l))
{
SetVertexShader(context, type);
context.InputAssembler.InputLayout = l;
return true;
}
return false;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
uint rendermode = 0;
uint rendermodeind = 1;
switch (RenderMode)
{
case WorldRenderMode.VertexNormals:
rendermode = 1;
break;
case WorldRenderMode.VertexTangents:
rendermode = 2;
break;
case WorldRenderMode.VertexColour:
rendermode = 3;
rendermodeind = (uint)RenderVertexColourIndex;
break;
case WorldRenderMode.TextureCoord:
rendermode = 4;
rendermodeind = (uint)RenderTextureCoordIndex;
break;
case WorldRenderMode.SingleTexture:
rendermode = 8;//direct mode
break;
}
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
PSSceneVars.Vars.GlobalLights = lights.Params;
PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u;
PSSceneVars.Vars.RenderMode = rendermode;
PSSceneVars.Vars.RenderModeIndex = rendermodeind;
PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord;
PSSceneVars.Update(context);
PSSceneVars.SetPSCBuffer(context, 0);
if (shadowmap != null)
{
shadowmap.SetFinalRenderResources(context);
}
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Vars.Scale = rend.Scale;
VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0;
VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0;
VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex;
VSEntityVars.Vars.IsInstanced = 0;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (!model.UseTransform) return;
VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
VSModelVars.Update(context);
VSModelVars.SetVSCBuffer(context, 3);
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
RenderableTexture texture = null; // ((geom.Textures != null) && (geom.Textures.Length > 0)) ? geom.Textures[0] : null;
if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0))
{
if (RenderMode == WorldRenderMode.Default)
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
switch (ihash)
{
case MetaName.DiffuseSampler:
texture = itex;
break;
}
}
////fallback try get first texture... eventaully remove this! (helps with water for now)
//int index = 0;
//while (((texture == null) || (texture.Texture2D == null)) && (index < geom.Textures.Length))
//{
// texture = geom.Textures[index];
// index++;
//}
}
else if (RenderMode == WorldRenderMode.SingleTexture)
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
if (ihash == RenderTextureSampler)
{
texture = itex;
break;
}
}
}
}
bool usediff = ((texture != null) && (texture.Texture2D != null) && (texture.ShaderResourceView != null));
PSGeomVars.Vars.EnableTexture = usediff ? 1u : 0u;
PSGeomVars.Vars.EnableTint = 0u;
PSGeomVars.Update(context);
PSGeomVars.SetPSCBuffer(context, 2);
VSGeomVars.Vars.EnableTint = 0u;
VSGeomVars.Vars.TintYVal = 0u;
VSGeomVars.Vars.IsDecal = 0u;
VSGeomVars.Update(context);
VSGeomVars.SetVSCBuffer(context, 4);
//context.VertexShader.SetSampler(0, texsampler);
context.PixelShader.SetSampler(0, texsampler);
//context.PixelShader.SetSampler(1, texsamplerc);
if (usediff)
{
texture.SetPSResource(context, 0);
//context.PixelShader.SetShaderResource(0, difftex.ShaderResourceView);
}
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetShaderResource(1, null);//shadowmap
context.PixelShader.SetSampler(1, null); //shadowmap
context.VertexShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(3, null);
context.PixelShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(4, null);
context.VertexShader.SetSampler(0, null);
context.PixelShader.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.VertexShader.SetShaderResource(0, null);
context.VertexShader.SetShaderResource(1, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
if (texsampler != null)
{
texsampler.Dispose();
texsampler = null;
}
foreach (InputLayout layout in layouts.Values)
{
layout.Dispose();
}
layouts.Clear();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSModelVars.Dispose();
VSGeomVars.Dispose();
PSSceneVars.Dispose();
PSGeomVars.Dispose();
ps.Dispose();
vs.Dispose();
disposed = true;
}
}
}
+356
View File
@@ -0,0 +1,356 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CodeWalker.GameFiles;
using CodeWalker.World;
using SharpDX.Direct3D11;
using System.IO;
using SharpDX;
namespace CodeWalker.Rendering
{
public struct CloudsShaderVSSceneVars
{
public Matrix ViewProj;
public Matrix ViewInv;
}
public struct CloudsShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
public Vector4 Scale;
}
public struct CloudsShaderVSModelVars
{
public Matrix Transform;
}
public struct CloudsShaderPSSceneVars
{
public Vector4 LightDirection;
public uint EnableHDR;
public uint Pad0;
public uint Pad1;
public uint Pad2;
}
public struct CloudsShaderCloudsLocals
{
public Vector3 gSkyColor; // Offset: 0 Size: 12 [unused]
public float gPad00;
public Vector3 gEastMinusWestColor; // Offset: 16 Size: 12 [unused]
public float gPad01;
public Vector3 gWestColor; // Offset: 32 Size: 12 [unused]
public float gPad02;
public Vector3 gSunDirection; // Offset: 48 Size: 12
public float gPad03;
public Vector3 gSunColor; // Offset: 64 Size: 12
public float gPad04;
public Vector3 gCloudColor; // Offset: 80 Size: 12 [unused]
public float gPad05;
public Vector3 gAmbientColor; // Offset: 96 Size: 12 [unused]
public float gPad06;
public Vector3 gBounceColor; // Offset: 112 Size: 12 [unused]
public float gPad07;
public Vector4 gDensityShiftScale; // Offset: 128 Size: 16 [unused]
public Vector4 gScatterG_GSquared_PhaseMult_Scale;// Offset: 144 Size: 16
public Vector4 gPiercingLightPower_Strength_NormalStrength_Thickness;// Offset: 160 Size: 16
public Vector3 gScaleDiffuseFillAmbient; // Offset: 176 Size: 12 [unused]
public float gPad08;
public Vector3 gWrapLighting_MSAARef; // Offset: 192 Size: 12 [unused]
public float gPad09;
public Vector4 gNearFarQMult; // Offset: 208 Size: 16 [unused]
public Vector3 gAnimCombine; // Offset: 224 Size: 12 [unused]
public float gPad10;
public Vector3 gAnimSculpt; // Offset: 240 Size: 12 [unused]
public float gPad11;
public Vector3 gAnimBlendWeights; // Offset: 256 Size: 12 [unused]
public float gPad12;
public Vector4 gUVOffsetArr0; // Offset: 272 Size: 32
public Vector4 gUVOffsetArr1; // Offset: 272 Size: 32
public Matrix gCloudViewProj; // Offset: 304 Size: 64
public Vector4 gCameraPos; // Offset: 368 Size: 16
public Vector2 gUVOffset1; // Offset: 384 Size: 8
public Vector2 gUVOffset2; // Offset: 392 Size: 8
public Vector2 gUVOffset3; // Offset: 400 Size: 8
public Vector2 gRescaleUV1; // Offset: 408 Size: 8
public Vector2 gRescaleUV2; // Offset: 416 Size: 8
public Vector2 gRescaleUV3; // Offset: 424 Size: 8
public float gSoftParticleRange; // Offset: 432 Size: 4 [unused]
public float gEnvMapAlphaScale; // Offset: 436 Size: 4 [unused]
public Vector2 cloudLayerAnimScale1; // Offset: 440 Size: 8
public Vector2 cloudLayerAnimScale2; // Offset: 448 Size: 8
public Vector2 cloudLayerAnimScale3; // Offset: 456 Size: 8
};
public class CloudsShader : Shader, IDisposable
{
bool disposed = false;
VertexShader vs;
PixelShader ps;
GpuVarsBuffer<CloudsShaderCloudsLocals> CloudsLocalVars;
GpuVarsBuffer<CloudsShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<CloudsShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<CloudsShaderVSModelVars> VSModelVars;
GpuVarsBuffer<CloudsShaderPSSceneVars> PSSceneVars;
SamplerState texsampler;
SamplerState texsampleranis;
InputLayout layout;
public bool EnableHDR { get; set; }
public bool AnisotropicFilter = false;
public CloudsShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\CloudsVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\CloudsPS.cso");
vs = new VertexShader(device, vsbytes);
ps = new PixelShader(device, psbytes);
CloudsLocalVars = new GpuVarsBuffer<CloudsShaderCloudsLocals>(device);
VSSceneVars = new GpuVarsBuffer<CloudsShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<CloudsShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<CloudsShaderVSModelVars>(device);
PSSceneVars = new GpuVarsBuffer<CloudsShaderPSSceneVars>(device);
layout = new InputLayout(device, vsbytes, VertexTypeDefaultEx.GetLayout());
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsampleranis = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.Anisotropic,
MaximumAnisotropy = 8,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
public void UpdateCloudsLocals(Clouds clouds, ShaderGlobalLights lights)
{
CloudsLocalVars.Vars.gSunDirection = lights.CurrentSunDir;
CloudsLocalVars.Vars.gSunColor = ((Vector4)lights.Params.LightDirColour).XYZ();
CloudsLocalVars.Vars.gUVOffset1 = clouds.AnimOverrides.UVOffset1;
CloudsLocalVars.Vars.gUVOffset2 = clouds.AnimOverrides.UVOffset2;
CloudsLocalVars.Vars.gUVOffset3 = clouds.AnimOverrides.UVOffset3;
CloudsLocalVars.Vars.gRescaleUV1 = clouds.AnimOverrides.RescaleUV1;
CloudsLocalVars.Vars.gRescaleUV2 = clouds.AnimOverrides.RescaleUV2;
CloudsLocalVars.Vars.gRescaleUV3 = clouds.AnimOverrides.RescaleUV3;
CloudsLocalVars.Vars.cloudLayerAnimScale1 = clouds.AnimOverrides.cloudLayerAnimScale1;
CloudsLocalVars.Vars.cloudLayerAnimScale2 = clouds.AnimOverrides.cloudLayerAnimScale2;
CloudsLocalVars.Vars.cloudLayerAnimScale3 = clouds.AnimOverrides.cloudLayerAnimScale3;
CloudsLocalVars.Vars.gUVOffsetArr0 = Vector4.Zero;
CloudsLocalVars.Vars.gUVOffsetArr1 = Vector4.Zero;
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(vs);
context.PixelShader.Set(ps);
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
CloudsLocalVars.Update(context);
CloudsLocalVars.SetVSCBuffer(context, 0);
CloudsLocalVars.SetPSCBuffer(context, 0);
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix);
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 1);
PSSceneVars.Vars.LightDirection = new Vector4(lights.Params.LightDir, 0.0f);
PSSceneVars.Vars.EnableHDR = EnableHDR ? 1u : 0u;
PSSceneVars.Update(context);
PSSceneVars.SetPSCBuffer(context, 1);
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Vars.Scale = new Vector4(rend.Scale, 1.0f);
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
//currently not used..
//if (!model.UseTransform) return;
//VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
//VSModelVars.Update(context);
//VSModelVars.SetVSCBuffer(context, 3);
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
switch (geom.DrawableGeom.Shader.FileName.Hash)
{
case 4103916155://{clouds_animsoft.sps}
case 1097000161://{clouds_altitude.sps}
case 1481470665://{clouds_soft.sps}
case 2184108982://{clouds_fast.sps}
case 4192928948://{clouds_anim.sps}
break;
default:
break;
}
RenderableTexture DensitySampler = null;
RenderableTexture NormalSampler = null;
RenderableTexture DetailDensitySampler = null;
RenderableTexture DetailNormalSampler = null;
RenderableTexture DetailDensity2Sampler = null;
RenderableTexture DetailNormal2Sampler = null;
RenderableTexture DepthMapTexSampler = null;
if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0))
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
switch (ihash)
{
case MetaName.DensitySampler:
DensitySampler = itex;
break;
case MetaName.normalSampler:
NormalSampler = itex;
break;
case MetaName.DetailDensitySampler:
DetailDensitySampler = itex;
break;
case MetaName.DetailNormalSampler:
DetailNormalSampler = itex;
break;
case MetaName.DetailDensity2Sampler:
DetailDensity2Sampler = itex;
break;
case MetaName.DetailNormal2Sampler:
DetailNormal2Sampler = itex;
break;
case MetaName.DepthMapTexSampler:
DepthMapTexSampler = itex;
break;
default:
break;
}
}
}
bool usedens = ((DensitySampler != null) && (DensitySampler.ShaderResourceView != null));
bool usenorm = ((NormalSampler != null) && (NormalSampler.ShaderResourceView != null));
bool usedden = ((DetailDensitySampler != null) && (DetailDensitySampler.ShaderResourceView != null));
bool usednrm = ((DetailNormalSampler != null) && (DetailNormalSampler.ShaderResourceView != null));
bool useddn2 = ((DetailDensity2Sampler != null) && (DetailDensity2Sampler.ShaderResourceView != null));
bool usednm2 = ((DetailNormal2Sampler != null) && (DetailNormal2Sampler.ShaderResourceView != null));
bool usedept = ((DepthMapTexSampler != null) && (DepthMapTexSampler.ShaderResourceView != null));
if (usedens)
{
DensitySampler.SetPSResource(context, 0);
}
if (usenorm)
{
NormalSampler.SetPSResource(context, 1);
}
if (usedden)
{
DetailDensitySampler.SetPSResource(context, 2);
}
if (usednrm)
{
DetailNormalSampler.SetPSResource(context, 3);
}
if (useddn2)
{
DetailDensity2Sampler.SetPSResource(context, 4);
}
if (usednm2)
{
DetailNormal2Sampler.SetPSResource(context, 5);
}
if (usedept)
{
DepthMapTexSampler.SetPSResource(context, 6);
}
context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
if (type != VertexType.DefaultEx)
{
return false;
}
context.InputAssembler.InputLayout = layout;
return true;
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null);
context.PixelShader.SetConstantBuffer(1, null);
context.VertexShader.SetConstantBuffer(2, null);
context.PixelShader.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
disposed = true;
texsampler.Dispose();
layout.Dispose();
CloudsLocalVars.Dispose();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSModelVars.Dispose();
PSSceneVars.Dispose();
ps.Dispose();
vs.Dispose();
}
}
}
+146
View File
@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CodeWalker.GameFiles;
using SharpDX;
using SharpDX.Direct3D11;
using System.IO;
using SharpDX.DXGI;
using Device = SharpDX.Direct3D11.Device;
using Buffer = SharpDX.Direct3D11.Buffer;
using MapFlags = SharpDX.Direct3D11.MapFlags;
using CodeWalker.World;
namespace CodeWalker.Rendering
{
public struct DistantLightsShaderVSSceneVars
{
public Matrix ViewProj;
public Matrix ViewInv;
public Vector3 CamPos;
public float Pad0;
}
public class DistantLightsShader : Shader
{
bool disposed = false;
VertexShader lightsvs;
PixelShader lightsps;
InputLayout layout;
SamplerState texsampler;
UnitQuad quad;
GpuVarsBuffer<DistantLightsShaderVSSceneVars> VSSceneVars;
public DistantLightsShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\DistantLightsVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\DistantLightsPS.cso");
lightsvs = new VertexShader(device, vsbytes);
lightsps = new PixelShader(device, psbytes);
layout = new InputLayout(device, vsbytes, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0),
});
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Clamp,
AddressV = TextureAddressMode.Clamp,
AddressW = TextureAddressMode.Clamp,
BorderColor = Color.Transparent,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
quad = new UnitQuad(device);
VSSceneVars = new GpuVarsBuffer<DistantLightsShaderVSSceneVars>(device);
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(lightsvs);
context.PixelShader.Set(lightsps);
SetInputLayout(context, VertexType.PT);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
context.InputAssembler.InputLayout = layout;
return true;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix);
VSSceneVars.Vars.CamPos = camera.Position;
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.VertexShader.SetShaderResource(0, null);
context.PixelShader.SetShaderResource(0, null);
context.PixelShader.SetSampler(0, null);
}
public void RenderBatch(DeviceContext context, RenderableDistantLODLights lights)
{
context.VertexShader.SetShaderResource(0, lights.InstanceBuffer.SRV);
context.PixelShader.SetShaderResource(0, lights.Texture.ShaderResourceView);
context.PixelShader.SetSampler(0, texsampler);
quad.DrawInstanced(context, lights.InstanceCount);
}
public void Dispose()
{
if (disposed) return;
VSSceneVars.Dispose();
quad.Dispose();
texsampler.Dispose();
layout.Dispose();
//VSSceneVars.Dispose();
lightsps.Dispose();
lightsvs.Dispose();
disposed = true;
}
}
}
+166
View File
@@ -0,0 +1,166 @@
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 MarkerShaderVSSceneVars
{
public Matrix ViewProj;
public Matrix ViewInv;
public Vector4 ScreenScale; //xy = 1/wh
}
public struct MarkerShaderVSMarkerVars
{
public Vector4 CamRel;
public Vector2 Size;
public Vector2 Offset;
}
public class MarkerShader : Shader, IDisposable
{
bool disposed = false;
VertexShader markervs;
PixelShader markerps;
GpuVarsBuffer<MarkerShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<MarkerShaderVSMarkerVars> VSMarkerVars;
SamplerState texsampler;
InputLayout layout;
public MarkerShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\MarkerVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\MarkerPS.cso");
markervs = new VertexShader(device, vsbytes);
markerps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<MarkerShaderVSSceneVars>(device);
VSMarkerVars = new GpuVarsBuffer<MarkerShaderVSMarkerVars>(device);
layout = new InputLayout(device, vsbytes, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0),
});
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Clamp,
AddressV = TextureAddressMode.Clamp,
AddressW = TextureAddressMode.Clamp,
BorderColor = Color.Transparent,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(markervs);
context.PixelShader.Set(markerps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
context.InputAssembler.InputLayout = layout;
return true;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix);
VSSceneVars.Vars.ScreenScale = new Vector4(0.5f / camera.Width, 0.5f / camera.Height, camera.Width, camera.Height);
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
}
public void SetMarkerVars(DeviceContext context, Vector3 camrel, Vector2 size, Vector2 offset)
{
VSMarkerVars.Vars.CamRel = new Vector4(camrel, 0.0f);
VSMarkerVars.Vars.Size = size;
VSMarkerVars.Vars.Offset = offset;
VSMarkerVars.Update(context);
VSMarkerVars.SetVSCBuffer(context, 1);
}
public void SetTexture(DeviceContext context, ShaderResourceView srv)
{
context.PixelShader.SetSampler(0, texsampler);
context.PixelShader.SetShaderResource(0, srv);
}
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.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
if (texsampler != null)
{
texsampler.Dispose();
texsampler = null;
}
layout.Dispose();
VSSceneVars.Dispose();
VSMarkerVars.Dispose();
markerps.Dispose();
markervs.Dispose();
disposed = true;
}
}
}
+246
View File
@@ -0,0 +1,246 @@
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 PathShaderVSSceneVars
{
public Matrix ViewProj;
public Vector4 CameraPos;
public Vector4 LightColour;
}
public class PathShader : Shader, IDisposable
{
bool disposed = false;
VertexShader boxvs;
PixelShader boxps;
VertexShader dynvs;
VertexShader vs;
PixelShader ps;
GpuVarsBuffer<PathShaderVSSceneVars> VSSceneVars;
InputLayout layout;
UnitCube cube;
bool UseDynamicVerts = false;
GpuCBuffer<VertexTypePC> vertices; //for selection polys/lines use
public PathShader(Device device)
{
byte[] boxvsbytes = File.ReadAllBytes("Shaders\\PathBoxVS.cso");
byte[] boxpsbytes = File.ReadAllBytes("Shaders\\PathBoxPS.cso");
byte[] dynvsbytes = File.ReadAllBytes("Shaders\\PathDynVS.cso");
byte[] vsbytes = File.ReadAllBytes("Shaders\\PathVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\PathPS.cso");
boxvs = new VertexShader(device, boxvsbytes);
boxps = new PixelShader(device, boxpsbytes);
dynvs = new VertexShader(device, dynvsbytes);
vs = new VertexShader(device, vsbytes);
ps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<PathShaderVSSceneVars>(device);
layout = new InputLayout(device, vsbytes, VertexTypePC.GetLayout());
cube = new UnitCube(device, boxvsbytes, true, false, true);
vertices = new GpuCBuffer<VertexTypePC>(device, 1000); //should be more than needed....
}
public override void SetShader(DeviceContext context)
{
if (UseDynamicVerts)
{
context.VertexShader.Set(dynvs);
//context.InputAssembler.SetVertexBuffers(0, null);
context.InputAssembler.SetIndexBuffer(null, Format.Unknown, 0);
}
else
{
context.VertexShader.Set(vs);
}
context.PixelShader.Set(ps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
if (UseDynamicVerts)
{
context.InputAssembler.InputLayout = null;
}
else
{
context.InputAssembler.InputLayout = layout;
}
return true;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f);
VSSceneVars.Vars.LightColour = new Vector4(1.0f, 1.0f, 1.0f, lights.HdrIntensity * 2.0f);
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(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 void RenderBatches(DeviceContext context, List<RenderablePathBatch> batches, Camera camera, ShaderGlobalLights lights)
{
UseDynamicVerts = false;
SetShader(context);
SetInputLayout(context, VertexType.PC);
SetSceneVars(context, camera, null, lights);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
context.InputAssembler.SetIndexBuffer(null, Format.R16_UInt, 0);
for (int i = 0; i < batches.Count; i++)
{
var pbatch = batches[i];
if (pbatch.TriangleVertexBuffer == null) continue;
if (pbatch.TriangleVertexCount == 0) continue;
context.InputAssembler.SetVertexBuffers(0, pbatch.TriangleVBBinding);
context.Draw(pbatch.TriangleVertexCount, 0);
}
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
context.InputAssembler.SetIndexBuffer(null, Format.R16_UInt, 0);
for (int i = 0; i < batches.Count; i++)
{
var pbatch = batches[i];
if (pbatch.PathVertexBuffer == null) continue;
if (pbatch.PathVertexCount == 0) continue;
context.InputAssembler.SetVertexBuffers(0, pbatch.PathVBBinding);
context.Draw(pbatch.PathVertexCount, 0);
}
context.VertexShader.Set(boxvs);
context.PixelShader.Set(boxps);
VSSceneVars.SetVSCBuffer(context, 0);
foreach (var batch in batches)
{
if (batch.NodeBuffer == null) continue;
context.VertexShader.SetShaderResource(0, batch.NodeBuffer.SRV);
cube.DrawInstanced(context, batch.Nodes.Length);
}
UnbindResources(context);
}
public void RenderTriangles(DeviceContext context, List<VertexTypePC> verts, Camera camera, ShaderGlobalLights lights)
{
UseDynamicVerts = true;
SetShader(context);
SetInputLayout(context, VertexType.PC);
SetSceneVars(context, camera, null, lights);
vertices.Clear();
foreach (var vert in verts)
{
vertices.Add(vert);
}
vertices.Update(context);
vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
context.Draw(vertices.CurrentCount, 0);
}
public void RenderLines(DeviceContext context, List<VertexTypePC> verts, Camera camera, ShaderGlobalLights lights)
{
UseDynamicVerts = true;
SetShader(context);
SetInputLayout(context, VertexType.PC);
SetSceneVars(context, camera, null, lights);
vertices.Clear();
foreach (var vert in verts)
{
vertices.Add(vert);
}
vertices.Update(context);
vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
context.Draw(vertices.CurrentCount, 0);
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.VertexShader.SetShaderResource(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
disposed = true;
VSSceneVars.Dispose();
vertices.Dispose();
layout.Dispose();
cube.Dispose();
ps.Dispose();
vs.Dispose();
dynvs.Dispose();
boxvs.Dispose();
boxps.Dispose();
}
}
}
+688
View File
@@ -0,0 +1,688 @@
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 PostProcessorReduceCSVars
{
public uint dimx;
public uint dimy;
public uint Width;
public uint Height;
}
public struct PostProcessorLumBlendCSVars
{
public Vector4 blend;
}
public struct PostProcessorFilterSampleWeights
{
public Vector4 avSampleWeights00; //[15];
public Vector4 avSampleWeights01;
public Vector4 avSampleWeights02;
public Vector4 avSampleWeights03;
public Vector4 avSampleWeights04;
public Vector4 avSampleWeights05;
public Vector4 avSampleWeights06;
public Vector4 avSampleWeights07;
public Vector4 avSampleWeights08;
public Vector4 avSampleWeights09;
public Vector4 avSampleWeights10;
public Vector4 avSampleWeights11;
public Vector4 avSampleWeights12;
public Vector4 avSampleWeights13;
public Vector4 avSampleWeights14;
public Vector4 Get(int i)
{
switch (i)
{
default:
case 0: return avSampleWeights00;
case 1: return avSampleWeights01;
case 2: return avSampleWeights02;
case 3: return avSampleWeights03;
case 4: return avSampleWeights04;
case 5: return avSampleWeights05;
case 6: return avSampleWeights06;
case 7: return avSampleWeights07;
case 8: return avSampleWeights08;
case 9: return avSampleWeights09;
case 10: return avSampleWeights10;
case 11: return avSampleWeights11;
case 12: return avSampleWeights12;
case 13: return avSampleWeights13;
case 14: return avSampleWeights14;
}
}
public void Set(int i, Vector4 v)
{
switch (i)
{
case 0: avSampleWeights00 = v; break;
case 1: avSampleWeights01 = v; break;
case 2: avSampleWeights02 = v; break;
case 3: avSampleWeights03 = v; break;
case 4: avSampleWeights04 = v; break;
case 5: avSampleWeights05 = v; break;
case 6: avSampleWeights06 = v; break;
case 7: avSampleWeights07 = v; break;
case 8: avSampleWeights08 = v; break;
case 9: avSampleWeights09 = v; break;
case 10: avSampleWeights10 = v; break;
case 11: avSampleWeights11 = v; break;
case 12: avSampleWeights12 = v; break;
case 13: avSampleWeights13 = v; break;
case 14: avSampleWeights14 = v; break;
}
}
}
public struct PostProcessorFilterBPHCSVars
{
public PostProcessorFilterSampleWeights avSampleWeights;
public uint outputwidth;
public float finverse;
public int inputsize0;
public int inputsize1;
}
public struct PostProcessorFilterVCSVars
{
public PostProcessorFilterSampleWeights avSampleWeights;
public int outputsize0;
public int outputsize1;
public int inputsize0;
public int inputsize1;
}
public struct PostProcessorFinalPSVars
{
public Vector4 invPixelCount;
}
public class PostProcessor
{
ComputeShader ReduceTo1DCS;
ComputeShader ReduceTo0DCS;
ComputeShader LumBlendCS;
ComputeShader BloomFilterBPHCS;
ComputeShader BloomFilterVCS;
PixelShader CopyPixelsPS;
VertexShader FinalPassVS;
PixelShader FinalPassPS;
UnitQuad FinalPassQuad;
InputLayout FinalPassLayout;
GpuVarsBuffer<PostProcessorReduceCSVars> ReduceCSVars;
GpuVarsBuffer<PostProcessorLumBlendCSVars> LumBlendCSVars;
GpuVarsBuffer<PostProcessorFilterBPHCSVars> FilterBPHCSVars;
GpuVarsBuffer<PostProcessorFilterVCSVars> FilterVCSVars;
GpuVarsBuffer<PostProcessorFinalPSVars> FinalPSVars;
GpuTexture Primary;
GpuBuffer<float> Reduction0;
GpuBuffer<float> Reduction1;
GpuBuffer<float> LumBlendResult;
GpuBuffer<Vector4> Bloom0;
GpuBuffer<Vector4> Bloom1;
GpuTexture Bloom;
SamplerState SampleStatePoint;
SamplerState SampleStateLinear;
BlendState BlendState;
long WindowSizeVramUsage = 0;
int Width = 0;
int Height = 0;
ViewportF Viewport;
bool Multisampled = false;
bool EnableBloom = true;
float ElapsedTime = 0.0f;
public float LumBlendSpeed = 1.0f;
bool CS_FULL_PIXEL_REDUCTION = false;
public long VramUsage
{
get
{
return WindowSizeVramUsage;
}
}
RawViewportF[] vpOld = new RawViewportF[15];
public PostProcessor(DXManager dxman)
{
var device = dxman.device;
byte[] bReduceTo1DCS = File.ReadAllBytes("Shaders\\PPReduceTo1DCS.cso");
byte[] bReduceTo0DCS = File.ReadAllBytes("Shaders\\PPReduceTo0DCS.cso");
byte[] bLumBlendCS = File.ReadAllBytes("Shaders\\PPLumBlendCS.cso");
byte[] bBloomFilterBPHCS = File.ReadAllBytes("Shaders\\PPBloomFilterBPHCS.cso");
byte[] bBloomFilterVCS = File.ReadAllBytes("Shaders\\PPBloomFilterVCS.cso");
byte[] bCopyPixelsPS = File.ReadAllBytes("Shaders\\PPCopyPixelsPS.cso");
byte[] bFinalPassVS = File.ReadAllBytes("Shaders\\PPFinalPassVS.cso");
byte[] bFinalPassPS = File.ReadAllBytes("Shaders\\PPFinalPassPS.cso");
ReduceTo1DCS = new ComputeShader(device, bReduceTo1DCS);
ReduceTo0DCS = new ComputeShader(device, bReduceTo0DCS);
LumBlendCS = new ComputeShader(device, bLumBlendCS);
BloomFilterBPHCS = new ComputeShader(device, bBloomFilterBPHCS);
BloomFilterVCS = new ComputeShader(device, bBloomFilterVCS);
CopyPixelsPS = new PixelShader(device, bCopyPixelsPS);
FinalPassVS = new VertexShader(device, bFinalPassVS);
FinalPassPS = new PixelShader(device, bFinalPassPS);
FinalPassQuad = new UnitQuad(device, true);
FinalPassLayout = new InputLayout(device, bFinalPassVS, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0),
});
ReduceCSVars = new GpuVarsBuffer<PostProcessorReduceCSVars>(device);
LumBlendCSVars = new GpuVarsBuffer<PostProcessorLumBlendCSVars>(device);
FilterBPHCSVars = new GpuVarsBuffer<PostProcessorFilterBPHCSVars>(device);
FilterVCSVars = new GpuVarsBuffer<PostProcessorFilterVCSVars>(device);
FinalPSVars = new GpuVarsBuffer<PostProcessorFinalPSVars>(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);
GetSampleWeights(ref FilterVCSVars.Vars.avSampleWeights, 3.0f, 1.25f); //init sample weights
FilterBPHCSVars.Vars.avSampleWeights = FilterVCSVars.Vars.avSampleWeights;
}
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 (FinalPSVars != null)
{
FinalPSVars.Dispose();
FinalPSVars = null;
}
if (FilterVCSVars != null)
{
FilterVCSVars.Dispose();
FilterVCSVars = null;
}
if (FilterBPHCSVars != null)
{
FilterBPHCSVars.Dispose();
FilterBPHCSVars = null;
}
if (LumBlendCSVars != null)
{
LumBlendCSVars.Dispose();
LumBlendCSVars = null;
}
if (ReduceCSVars != null)
{
ReduceCSVars.Dispose();
ReduceCSVars = null;
}
if (FinalPassLayout != null)
{
FinalPassLayout.Dispose();
FinalPassLayout = null;
}
if (FinalPassQuad != null)
{
FinalPassQuad.Dispose();
FinalPassQuad = null;
}
if (FinalPassPS != null)
{
FinalPassPS.Dispose();
FinalPassPS = null;
}
if (FinalPassVS != null)
{
FinalPassVS.Dispose();
FinalPassVS = null;
}
if (CopyPixelsPS != null)
{
CopyPixelsPS.Dispose();
CopyPixelsPS = null;
}
if (BloomFilterVCS != null)
{
BloomFilterVCS.Dispose();
BloomFilterVCS = null;
}
if (BloomFilterBPHCS != null)
{
BloomFilterBPHCS.Dispose();
BloomFilterBPHCS = null;
}
if (LumBlendCS != null)
{
LumBlendCS.Dispose();
LumBlendCS = null;
}
if (ReduceTo0DCS != null)
{
ReduceTo0DCS.Dispose();
ReduceTo0DCS = null;
}
if (ReduceTo1DCS != null)
{
ReduceTo1DCS.Dispose();
ReduceTo1DCS = null;
}
}
public void OnWindowResize(DXManager dxman)
{
DisposeBuffers();
var device = dxman.device;
int sc = dxman.multisamplecount;
int sq = dxman.multisamplequality;
Multisampled = (sc > 1);
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;
Format f = Format.R32G32B32A32_Float;
Format df = Format.D32_Float;
Primary = new GpuTexture(device, uw, uh, f, sc, sq, true, df);
WindowSizeVramUsage += Primary.VramUsage;
int rc = (int)(Math.Ceiling(uw / 8.0f) * Math.Ceiling(uh / 8.0f));
Reduction0 = new GpuBuffer<float>(device, 1, rc);
Reduction1 = new GpuBuffer<float>(device, 1, rc);
WindowSizeVramUsage += sizeof(float) * rc * 2;
LumBlendResult = new GpuBuffer<float>(device, 1, 1);
WindowSizeVramUsage += sizeof(float); //because 4 bytes matter
int tw = uw / 8;
int th = uh / 8;
rc = tw * th;
f = Format.R8G8B8A8_UNorm;
Bloom0 = new GpuBuffer<Vector4>(device, 1, rc);
Bloom1 = new GpuBuffer<Vector4>(device, 1, rc);
WindowSizeVramUsage += /*sizeof(V4F)*/ 16 * rc * 2;
Bloom = new GpuTexture(device, tw, th, f, 1, 0, false, df);
WindowSizeVramUsage += Bloom.VramUsage;
}
public void DisposeBuffers()
{
if (Bloom != null)
{
Bloom.Dispose();
Bloom = null;
}
if (Bloom0 != null)
{
Bloom0.Dispose();
Bloom0 = null;
}
if (Bloom1 != null)
{
Bloom1.Dispose();
Bloom1 = null;
}
if (LumBlendResult != null)
{
LumBlendResult.Dispose();
LumBlendResult = null;
}
if (Reduction0 != null)
{
Reduction0.Dispose();
Reduction0 = null;
}
if (Reduction1 != null)
{
Reduction1.Dispose();
Reduction1 = null;
}
if (Primary != null)
{
Primary.Dispose();
Primary = 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);
Primary.Clear(context, clearColour);
}
public void ClearDepth(DeviceContext context)
{
Primary.ClearDepth(context);
}
public void SetPrimary(DeviceContext context)
{
Primary.SetRenderTarget(context);
context.Rasterizer.SetViewport(Viewport);
}
public void Render(DXManager dxman, float elapsed)
{
ElapsedTime = elapsed;
var context = dxman.context;
if (Multisampled)
{
int sr = 0;// D3D11CalcSubresource(0, 0, 1);
context.ResolveSubresource(Primary.TextureMS, sr, Primary.Texture, sr, Format.R32G32B32A32_Float);
}
context.OutputMerger.SetRenderTargets((RenderTargetView)null);
ProcessLuminance(context);
ProcessBloom(context);
dxman.SetDefaultRenderTarget(context);
context.OutputMerger.SetBlendState(BlendState, null, 0xFFFFFFFF);
FinalPass(context);
}
private void ProcessLuminance(DeviceContext context)
{
uint dimx, dimy;
if (CS_FULL_PIXEL_REDUCTION)
{
dimx = (uint)(Math.Ceiling(Width / 8.0f));
dimx = (uint)(Math.Ceiling(dimx / 2.0f));
dimy = (uint)(Math.Ceiling(Height / 8.0f));
dimy = (uint)(Math.Ceiling(dimy / 2.0f));
}
else
{
dimx = (uint)(Math.Ceiling(81.0f / 8.0f)); //ToneMappingTexSize = (int)pow(3.0f, NUM_TONEMAP_TEXTURES-1);
dimy = dimx;
}
ReduceCSVars.Vars.dimx = dimx;
ReduceCSVars.Vars.dimy = dimy;
ReduceCSVars.Vars.Width = (uint)Width;
ReduceCSVars.Vars.Height = (uint)Height;
ReduceCSVars.Update(context);
Compute(context, ReduceTo1DCS, ReduceCSVars.Buffer, Reduction0.UAV, (int)dimx, (int)dimy, 1, Primary.SRV);
uint dim = dimx * dimy;
uint nNumToReduce = dim;
dim = (uint)(Math.Ceiling(dim / 128.0f));
if (nNumToReduce > 1)
{
for (;;)
{
ReduceCSVars.Vars.dimx = nNumToReduce;
ReduceCSVars.Vars.dimy = dim;
ReduceCSVars.Vars.Width = 0;
ReduceCSVars.Vars.Height = 0;
ReduceCSVars.Update(context);
Compute(context, ReduceTo0DCS, ReduceCSVars.Buffer, Reduction1.UAV, (int)dim, 1, 1, Reduction0.SRV);
nNumToReduce = dim;
dim = (uint)(Math.Ceiling(dim / 128.0f));
if (nNumToReduce == 1) break;
var r0 = Reduction0;
Reduction0 = Reduction1;
Reduction1 = r0;
}
}
else
{
var r0 = Reduction0;
Reduction0 = Reduction1;
Reduction1 = r0;
}
LumBlendCSVars.Vars.blend = new Vector4(Math.Min(ElapsedTime * LumBlendSpeed, 1.0f));
LumBlendCSVars.Update(context);
Compute(context, LumBlendCS, LumBlendCSVars.Buffer, LumBlendResult.UAV, 1, 1, 1, Reduction1.SRV);
}
private void ProcessBloom(DeviceContext context)
{
if (EnableBloom)
{
// Bright pass and horizontal blur
ShaderResourceView view = Primary.SRV;
ShaderResourceView[] aRViews = { view, LumBlendResult.SRV };
//BloomFilterShaderVars cbFilter;
//GetSampleWeights(cbFilter.avSampleWeights, 3.0f, 1.25f);
FilterBPHCSVars.Vars.outputwidth = (uint)(Width / 8);
if (CS_FULL_PIXEL_REDUCTION)
{
FilterBPHCSVars.Vars.finverse = 1.0f / (Width * Height);
}
else
{
FilterBPHCSVars.Vars.finverse = 1.0f / (81 * 81); //(ToneMappingTexSize*ToneMappingTexSize);
}
FilterBPHCSVars.Vars.inputsize0 = (int)Width;
FilterBPHCSVars.Vars.inputsize1 = (int)Height;
FilterBPHCSVars.Update(context);
int x = (int)(Math.Ceiling((float)FilterBPHCSVars.Vars.outputwidth / (128 - 7 * 2)));
int y = (Height / 8);
Compute(context, BloomFilterBPHCS, FilterBPHCSVars.Buffer, Bloom1.UAV, x, y, 1, view, LumBlendResult.SRV);
// Vertical blur
FilterVCSVars.Vars.outputsize0 = (int)(Width / 8);
FilterVCSVars.Vars.outputsize1 = (int)(Height / 8);
FilterVCSVars.Vars.inputsize0 = (int)(Width / 8);
FilterVCSVars.Vars.inputsize1 = (int)(Height / 8);
FilterVCSVars.Update(context);
x = Width / 8;
y = (int)(Math.Ceiling((float)FilterVCSVars.Vars.outputsize1 / (128 - 7 * 2)));
Compute(context, BloomFilterVCS, FilterVCSVars.Buffer, Bloom0.UAV, x, y, 1, Bloom1.SRV, LumBlendResult.SRV);
}
CopyPixels(context, Width / 8, Height / 8, Bloom0.SRV, Bloom.RTV);
}
private void FinalPass(DeviceContext context)
{
context.Rasterizer.SetViewport(Viewport);
context.VertexShader.Set(FinalPassVS);
context.PixelShader.Set(FinalPassPS);
context.PixelShader.SetShaderResources(0, Primary.SRV, LumBlendResult.SRV, EnableBloom ? Bloom.SRV : null);
if (CS_FULL_PIXEL_REDUCTION)
{
//pcbCS[0] = 1.0f / (Width * Height);
FinalPSVars.Vars.invPixelCount = new Vector4(1.0f / (Width * Height));
}
else
{
//pcbCS[0] = 1.0f / (81 * 81); //ToneMappingTexSize*ToneMappingTexSize
FinalPSVars.Vars.invPixelCount = new Vector4(1.0f / (81 * 81));
}
FinalPSVars.Update(context);
FinalPSVars.SetPSCBuffer(context, 0);
context.PixelShader.SetSamplers(0, SampleStatePoint, SampleStateLinear);
context.InputAssembler.InputLayout = FinalPassLayout;
FinalPassQuad.Draw(context);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
context.PixelShader.SetShaderResources(0, null, null, null);
context.PixelShader.SetSamplers(0, null, null);
}
private float GaussianDistribution(float x, float y, float rho)
{
float g = 1.0f / (float)Math.Sqrt(2.0f * 3.14159265f * rho * rho);
g *= (float)Math.Exp(-(x * x + y * y) / (2 * rho * rho));
return g;
}
private void GetSampleWeights(ref PostProcessorFilterSampleWeights w, float fDeviation, float fMultiplier)
{
// Fill the center texel
float weight = 1.0f * GaussianDistribution(0, 0, fDeviation);
w.Set(7, new Vector4(weight, weight, weight, 1.0f));
// Fill the right side
for (int i = 1; i < 8; i++)
{
weight = fMultiplier * GaussianDistribution((float)i, 0, fDeviation);
w.Set(7 - i, new Vector4(weight, weight, weight, 1.0f));
}
// Copy to the left side
for (int i = 8; i < 15; i++)
{
w.Set(i, w.Get(14 - i));
}
// Debug convolution kernel which doesn't transform input data
/*ZeroMemory( avColorWeight, sizeof(D3DXVECTOR4)*15 );
w.Set(7, new Vector4( 1, 1, 1, 1 ));*/
}
private void Compute(DeviceContext context, ComputeShader cs, Buffer constantBuffer, UnorderedAccessView unorderedAccessView, int X, int Y, int Z, params ShaderResourceView[] resourceViews)
{
context.ComputeShader.Set(cs);
context.ComputeShader.SetShaderResources(0, resourceViews);
context.ComputeShader.SetUnorderedAccessView(0, unorderedAccessView);
if (constantBuffer != null)
{
//make sure buffer is updated first...
//D3D11_MAPPED_SUBRESOURCE mappedResource;
//dc->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
//memcpy(mappedResource.pData, constantData, constantDataSize);
//dc->Unmap(constantBuffer, 0);
context.ComputeShader.SetConstantBuffer(0, constantBuffer); //dc->CSSetConstantBuffers(0, 1, &constantBuffer);
}
context.Dispatch(X, Y, Z);
ShaderResourceView[] ppSRVNULL = { null, null, null };
context.ComputeShader.SetUnorderedAccessView(0, null);
context.ComputeShader.SetShaderResources(0, 3, ppSRVNULL);
context.ComputeShader.SetConstantBuffer(0, null);
}
private void CopyPixels(DeviceContext context, int w, int h, ShaderResourceView fromSRV, RenderTargetView toRTV)
{
context.VertexShader.Set(FinalPassVS);
context.PixelShader.Set(CopyPixelsPS);
ShaderResourceView[] aRViews = { fromSRV };
context.PixelShader.SetShaderResource(0, fromSRV);
RenderTargetView[] aRTViews = { toRTV };
context.OutputMerger.SetRenderTargets(toRTV);
//D3D11_MAPPED_SUBRESOURCE mappedResource;
//dc->Map(ReduceCSVars.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
//UINT* p = (UINT*)mappedResource.pData;
//p[0] = w;
//p[1] = h;
//dc->Unmap(ReduceCSVars.Get(), 0);
//ID3D11Buffer* ppCB[1] = { ReduceCSVars.Get() };
//dc->PSSetConstantBuffers(0, 1, ppCB);
ReduceCSVars.Vars.dimx = (uint)w;
ReduceCSVars.Vars.dimy = (uint)h;
ReduceCSVars.Update(context);
ReduceCSVars.SetPSCBuffer(context, 0);
//DrawFullScreenQuad11( pd3dImmediateContext, g_pDumpBufferPS, dwWidth, dwHeight );
//ViewportF[] vpOld = new ViewportF[15];// [D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX];
//UINT nViewPorts = 1;
//dc->RSGetViewports(&nViewPorts, vpOld);
context.Rasterizer.GetViewports(vpOld);
// Setup the viewport to match the backbuffer
ViewportF vp;
vp.Width = (float)Width;
vp.Height = (float)Height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.X = 0;
vp.Y = 0;
context.Rasterizer.SetViewport(vp);
context.InputAssembler.InputLayout = FinalPassLayout;
FinalPassQuad.Draw(context);
context.Rasterizer.SetViewports(vpOld); //reverting viewports maybe not necessary...
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using CodeWalker.GameFiles;
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.World;
namespace CodeWalker.Rendering
{
public abstract class Shader
{
public abstract void SetShader(DeviceContext context);
public abstract bool SetInputLayout(DeviceContext context, VertexType type);
public abstract void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights);
public abstract void SetEntityVars(DeviceContext context, ref RenderableInst rend);
public abstract void SetModelVars(DeviceContext context, RenderableModel model);
public abstract void SetGeomVars(DeviceContext context, RenderableGeometry geom);
public abstract void UnbindResources(DeviceContext context);
//public abstract void Dispose();
}
}
+351
View File
@@ -0,0 +1,351 @@
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.IO;
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;
using CodeWalker.GameFiles;
using CodeWalker.World;
namespace CodeWalker.Rendering
{
public struct ShadowShaderVSSceneVars
{
public Matrix ViewProj;
public Vector4 WindVector;
}
public struct ShadowShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
public uint HasSkeleton;
public uint HasTransforms;
public uint TintPaletteIndex;
public uint Pad1;
public Vector3 Scale;
public uint Pad2;
}
public struct ShadowShaderVSModelVars
{
public Matrix Transform;
}
//public struct ShadowShaderVSGeomVars
//{
// public uint EnableTint;
// public float TintYVal;
// public uint IsDecal;
// public uint Pad5;
//}
public struct ShadowShaderGeomVars
{
public uint EnableTexture;
public uint EnableTint;
public uint IsDecal;
public uint EnableWind;
public Vector4 WindOverrideParams;
}
public class ShadowShader : Shader, IDisposable
{
bool disposed = false;
VertexShader shadowvs;
PixelShader shadowps;
GpuVarsBuffer<ShadowShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<ShadowShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<ShadowShaderVSModelVars> VSModelVars;
GpuVarsBuffer<ShadowShaderGeomVars> GeomVars;
SamplerState texsampler;
SamplerState texsamplerc;
//public bool DecalMode = false;
public Vector4 WindVector { get; set; }
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public ShadowShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\ShadowVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\ShadowPS.cso");
shadowvs = new VertexShader(device, vsbytes);
shadowps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<ShadowShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<ShadowShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<ShadowShaderVSModelVars>(device);
GeomVars = new GpuVarsBuffer<ShadowShaderGeomVars>(device);
//supported layouts - requires Position, Normal, Colour, Texcoord
layouts.Add(VertexType.Default, new InputLayout(device, vsbytes, VertexTypeDefault.GetLayout()));
layouts.Add(VertexType.DefaultEx, new InputLayout(device, vsbytes, VertexTypeDefaultEx.GetLayout()));
layouts.Add(VertexType.PNCCT, new InputLayout(device, vsbytes, VertexTypePNCCT.GetLayout()));
layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vsbytes, VertexTypePNCCTTTT.GetLayout()));
layouts.Add(VertexType.PCCNCCTTX, new InputLayout(device, vsbytes, VertexTypePCCNCCTTX.GetLayout()));
layouts.Add(VertexType.PCCNCCT, new InputLayout(device, vsbytes, VertexTypePCCNCCT.GetLayout()));
layouts.Add(VertexType.PNCTTTX, new InputLayout(device, vsbytes, VertexTypePNCTTTX.GetLayout()));
layouts.Add(VertexType.PNCTTTX_2, new InputLayout(device, vsbytes, VertexTypePNCTTTX_2.GetLayout()));
layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vsbytes, VertexTypePNCTTTX_3.GetLayout()));
layouts.Add(VertexType.PNCTTTTX, new InputLayout(device, vsbytes, VertexTypePNCTTTTX.GetLayout()));
layouts.Add(VertexType.PNCTTX, new InputLayout(device, vsbytes, VertexTypePNCTTX.GetLayout()));
layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vsbytes, VertexTypePNCCTTX.GetLayout()));
layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vsbytes, VertexTypePNCCTTX_2.GetLayout()));
layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vsbytes, VertexTypePNCCTTTX.GetLayout()));
layouts.Add(VertexType.PCCNCCTX, new InputLayout(device, vsbytes, VertexTypePCCNCCTX.GetLayout()));
layouts.Add(VertexType.PCCNCTX, new InputLayout(device, vsbytes, VertexTypePCCNCTX.GetLayout()));
layouts.Add(VertexType.PCCNCT, new InputLayout(device, vsbytes, VertexTypePCCNCT.GetLayout()));
layouts.Add(VertexType.PNCCTT, new InputLayout(device, vsbytes, VertexTypePNCCTT.GetLayout()));
layouts.Add(VertexType.PNCCTX, new InputLayout(device, vsbytes, VertexTypePNCCTX.GetLayout()));
layouts.Add(VertexType.PNCH2, new InputLayout(device, vsbytes, VertexTypePNCH2.GetLayout()));
layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vsbytes, VertexTypePCCH2H4.GetLayout()));
layouts.Add(VertexType.PCCNCTT, new InputLayout(device, vsbytes, VertexTypePCCNCTT.GetLayout()));
layouts.Add(VertexType.PCCNCTTX, new InputLayout(device, vsbytes, VertexTypePCCNCTTX.GetLayout()));
layouts.Add(VertexType.PCCNCTTT, new InputLayout(device, vsbytes, VertexTypePCCNCTTT.GetLayout()));
layouts.Add(VertexType.PNCTT, new InputLayout(device, vsbytes, VertexTypePNCTT.GetLayout()));
layouts.Add(VertexType.PNCTTT, new InputLayout(device, vsbytes, VertexTypePNCTTT.GetLayout()));
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsamplerc = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Clamp,
AddressV = TextureAddressMode.Clamp,
AddressW = TextureAddressMode.Clamp,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipPoint,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(shadowvs);
context.PixelShader.Set(shadowps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
InputLayout l;
if (layouts.TryGetValue(type, out l))
{
context.InputAssembler.InputLayout = l;
return true;
}
return false;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
}
public void SetSceneVars(DeviceContext context, Matrix shadowviewproj)
{
VSSceneVars.Vars.ViewProj = Matrix.Transpose(shadowviewproj);
VSSceneVars.Vars.WindVector = WindVector;
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Vars.Scale = rend.Scale;
VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0;
VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0;
VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 1);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (!model.UseTransform) return;
VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
VSModelVars.Update(context);
VSModelVars.SetVSCBuffer(context, 2);
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
RenderableTexture texture = null; // ((geom.Textures != null) && (geom.Textures.Length > 0)) ? geom.Textures[0] : null;
//RenderableTexture tintpal = null;
//float tntpalind = 0.0f;
if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0))
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
switch (ihash)
{
case MetaName.DiffuseSampler:
case MetaName.TextureSampler_layer0:
case MetaName.TextureSampler_layer1:
case MetaName.TextureSampler_layer2:
case MetaName.TextureSampler_layer3:
texture = itex;
break;
}
if (texture != null) break;
}
////try get default diffuse texture
//if ((geom.DiffuseSampler >= 0) && (geom.DiffuseSampler < geom.Textures.Length))
//{
// texture = geom.Textures[geom.DiffuseSampler];
//}
//if ((texture == null) && (geom.TextureSampler_layer0 >= 0) && (geom.TextureSampler_layer0 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer0];
//}
//if ((texture == null) && (geom.TextureSampler_layer1 >= 0) && (geom.TextureSampler_layer1 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer1];
//}
//if ((texture == null) && (geom.TextureSampler_layer2 >= 0) && (geom.TextureSampler_layer2 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer2];
//}
//if ((texture == null) && (geom.TextureSampler_layer3 >= 0) && (geom.TextureSampler_layer3 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer3];
//}
//fallback try get first texture... eventaully remove this! (helps with water for now)
int index = 0;
while (((texture == null)) && (index < geom.RenderableTextures.Length))
{
texture = geom.RenderableTextures[index];
index++;
}
//if ((geom.PaletteTexture >= 0) && (geom.PaletteTexture < geom.Textures.Length))
//{
// tintpal = geom.Textures[geom.PaletteTexture];
// if (tintpal.Texture != null)
// {
// //this is slightly dodgy but vsentvarsdata should have the correct value in it...
// tntpalind = (vsentvarsdata.TintPaletteIndex + 0.5f) / tintpal.Texture.Height;
// }
//}
}
bool usediff = ((texture != null) && (texture.ShaderResourceView != null));
uint windflag = 0;
var shaderFile = geom.DrawableGeom.Shader.FileName;
switch (shaderFile.Hash)
{
case 2245870123: //trees_normal_diffspec_tnt.sps
case 3334613197: //trees_tnt.sps
case 1229591973://{trees_normal_spec_tnt.sps}
case 2322653400://{trees.sps}
case 3192134330://{trees_normal.sps}
case 1224713457://{trees_normal_spec.sps}
case 4265705004://{trees_normal_diffspec.sps}
windflag = 1;
break;
}
GeomVars.Vars.EnableTexture = usediff ? 1u : 0u;
GeomVars.Vars.EnableTint = 0u;// usetint ? 1u : 0u;
GeomVars.Vars.IsDecal = 0u;// DecalMode ? 1u : 0u;
GeomVars.Vars.EnableWind = windflag;
GeomVars.Vars.WindOverrideParams = geom.WindOverrideParams;
GeomVars.Update(context);
GeomVars.SetPSCBuffer(context, 0);
GeomVars.SetVSCBuffer(context, 3);
context.VertexShader.SetSampler(0, texsamplerc);
context.PixelShader.SetSampler(0, texsampler);
//context.PixelShader.SetSampler(1, texsamplerc);
if (usediff)
{
texture.SetPSResource(context, 0);
}
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null);
context.VertexShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(3, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetSampler(0, null);
context.PixelShader.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
if (texsampler != null)
{
texsampler.Dispose();
texsampler = null;
}
foreach (InputLayout layout in layouts.Values)
{
layout.Dispose();
}
layouts.Clear();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSModelVars.Dispose();
GeomVars.Dispose();
shadowps.Dispose();
shadowvs.Dispose();
disposed = true;
}
}
}
+410
View File
@@ -0,0 +1,410 @@
using SharpDX;
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;
namespace CodeWalker.Rendering
{
public struct SkydomeShaderVSSceneVars
{
public Matrix ViewProj;
public Matrix ViewInv;
}
public struct SkydomeShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
}
public struct SkydomeShaderVSModelVars
{
public Matrix Transform;
}
public struct SkydomeShaderPSSceneVars
{
public Vector4 LightDirection;
public uint EnableHDR;
public uint Pad0;
public uint Pad1;
public uint Pad2;
}
public struct SkydomeShaderVSSunMoonVars
{
public Matrix ViewProj;
public Matrix ViewInv;
public Vector4 CamRel;
public Vector2 Size;
public Vector2 Offset;
}
public struct SkydomeShaderPSSunMoonVars
{
public Vector4 Colour;
}
public struct SkydomeShaderSkySystemLocals
{
public Vector4 azimuthEastColor; // Offset: 0 Size: 12
public Vector4 azimuthWestColor; // Offset: 16 Size: 12
public Vector3 azimuthTransitionColor; // Offset: 32 Size: 12
public float azimuthTransitionPosition; // Offset: 44 Size: 4
public Vector4 zenithColor; // Offset: 48 Size: 12
public Vector4 zenithTransitionColor; // Offset: 64 Size: 12
public Vector4 zenithConstants; // Offset: 80 Size: 16
public Vector4 skyPlaneColor; // Offset: 96 Size: 16 [unused]
public Vector4 skyPlaneParams; // Offset: 112 Size: 16 [unused]
public float hdrIntensity; // Offset: 128 Size: 4
public Vector3 sunColor; // Offset: 132 Size: 12
public Vector4 sunColorHdr; // Offset: 144 Size: 12
public Vector4 sunDiscColorHdr; // Offset: 160 Size: 12 [unused]
public Vector4 sunConstants; // Offset: 176 Size: 16
public Vector4 sunDirection; // Offset: 192 Size: 12
public Vector4 sunPosition; // Offset: 208 Size: 12 [unused]
public Vector4 cloudBaseMinusMidColour; // Offset: 224 Size: 12
public Vector4 cloudMidColour; // Offset: 240 Size: 12
public Vector4 cloudShadowMinusBaseColourTimesShadowStrength;// Offset: 256 Size: 12
public Vector4 cloudDetailConstants; // Offset: 272 Size: 16
public Vector4 cloudConstants1; // Offset: 288 Size: 16
public Vector4 cloudConstants2; // Offset: 304 Size: 16
public Vector4 smallCloudConstants; // Offset: 320 Size: 16
public Vector4 smallCloudColorHdr; // Offset: 336 Size: 12
public Vector4 effectsConstants; // Offset: 352 Size: 16
public float horizonLevel; // Offset: 368 Size: 4
public Vector3 speedConstants; // Offset: 372 Size: 12
public float starfieldIntensity; // Offset: 384 Size: 4
public Vector3 moonDirection; // Offset: 388 Size: 12
public Vector3 moonPosition; // Offset: 400 Size: 12 [unused]
public float moonIntensity; // Offset: 412 Size: 4 [unused]
public Vector4 lunarCycle; // Offset: 416 Size: 12
public Vector3 moonColor; // Offset: 432 Size: 12
public float noiseFrequency; // Offset: 444 Size: 4 [unused]
public float noiseScale; // Offset: 448 Size: 4 [unused]
public float noiseThreshold; // Offset: 452 Size: 4 [unused]
public float noiseSoftness; // Offset: 456 Size: 4 [unused]
public float noiseDensityOffset; // Offset: 460 Size: 4 [unused]
public Vector4 noisePhase; // Offset: 464 Size: 8 [unused]
}
public class SkydomeShader : Shader, IDisposable
{
bool disposed = false;
VertexShader skyvs;
PixelShader skyps;
VertexShader sunvs;
PixelShader sunps;
VertexShader moonvs;
PixelShader moonps;
GpuVarsBuffer<SkydomeShaderSkySystemLocals> SkyLocalVars;
GpuVarsBuffer<SkydomeShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<SkydomeShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<SkydomeShaderVSModelVars> VSModelVars;
GpuVarsBuffer<SkydomeShaderPSSceneVars> PSSceneVars;
GpuVarsBuffer<SkydomeShaderVSSunMoonVars> VSSunMoonVars;
GpuVarsBuffer<SkydomeShaderPSSunMoonVars> PSSunMoonVars;
SamplerState texsampler;
InputLayout skylayout;
InputLayout sunlayout;
InputLayout moonlayout;
UnitDisc sundisc;
UnitQuad moonquad;
public bool EnableHDR { get; set; }
public SkydomeShader(Device device)
{
byte[] skyvsbytes = File.ReadAllBytes("Shaders\\SkydomeVS.cso");
byte[] skypsbytes = File.ReadAllBytes("Shaders\\SkydomePS.cso");
byte[] sunvsbytes = File.ReadAllBytes("Shaders\\SkySunVS.cso");
byte[] sunpsbytes = File.ReadAllBytes("Shaders\\SkySunPS.cso");
byte[] moonvsbytes = File.ReadAllBytes("Shaders\\SkyMoonVS.cso");
byte[] moonpsbytes = File.ReadAllBytes("Shaders\\SkyMoonPS.cso");
skyvs = new VertexShader(device, skyvsbytes);
skyps = new PixelShader(device, skypsbytes);
sunvs = new VertexShader(device, sunvsbytes);
sunps = new PixelShader(device, sunpsbytes);
moonvs = new VertexShader(device, moonvsbytes);
moonps = new PixelShader(device, moonpsbytes);
SkyLocalVars = new GpuVarsBuffer<SkydomeShaderSkySystemLocals>(device);
VSSceneVars = new GpuVarsBuffer<SkydomeShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<SkydomeShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<SkydomeShaderVSModelVars>(device);
PSSceneVars = new GpuVarsBuffer<SkydomeShaderPSSceneVars>(device);
VSSunMoonVars = new GpuVarsBuffer<SkydomeShaderVSSunMoonVars>(device);
PSSunMoonVars = new GpuVarsBuffer<SkydomeShaderPSSunMoonVars>(device);
sundisc = new UnitDisc(device, 30, true);
sunlayout = new InputLayout(device, sunvsbytes, sundisc.GetLayout());
skylayout = new InputLayout(device, skyvsbytes, VertexTypePTT.GetLayout());
moonquad = new UnitQuad(device, true);
moonlayout = new InputLayout(device, moonvsbytes, moonquad.GetLayout());
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(skyvs);
context.PixelShader.Set(skyps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
if (type != VertexType.PTT)
{
return false;
}
context.InputAssembler.InputLayout = skylayout;
return true;
}
public void UpdateSkyLocals(Weather weather, ShaderGlobalLights lights)
{
var wv = weather.CurrentValues;
float skyhdr = EnableHDR ? wv.skyHdr : Math.Min(wv.skyHdr, 1.8f);
float sunhdr = EnableHDR ? wv.skySunHdr : Math.Min(wv.skySunHdr, 4.8f); //NO HDR - turn it down!!!
float scathdr = EnableHDR ? wv.skySunScatterInten : Math.Min(wv.skySunScatterInten, 1.8f);
Vector3 suncolhdr = wv.skySunCol * sunhdr;
Vector4 azecol = wv.skyAzimuthEastCol;
Vector4 azwcol = wv.skyAzimuthWestCol;
Vector4 aztcol = wv.skyAzimuthTransitionCol;
Vector4 zencol = wv.skyZenithCol;
Vector4 zetcol = wv.skyZenithTransitionCol;
Vector4 plncol = wv.skyPlane;
SkyLocalVars.Vars.azimuthEastColor = azecol;
SkyLocalVars.Vars.azimuthWestColor = azwcol;
SkyLocalVars.Vars.azimuthTransitionColor = aztcol.XYZ();
SkyLocalVars.Vars.azimuthTransitionPosition = wv.skyAzimuthTransition;
SkyLocalVars.Vars.zenithColor = zencol;
SkyLocalVars.Vars.zenithTransitionColor = zetcol;
SkyLocalVars.Vars.zenithConstants = wv.skyZenithTransition;
SkyLocalVars.Vars.skyPlaneColor = plncol;
SkyLocalVars.Vars.skyPlaneParams = Vector4.Zero;
SkyLocalVars.Vars.hdrIntensity = skyhdr;
SkyLocalVars.Vars.sunColor = wv.skySunCol;
SkyLocalVars.Vars.sunColorHdr = new Vector4(suncolhdr, sunhdr);
SkyLocalVars.Vars.sunDiscColorHdr = new Vector4(wv.skySunDiscCol, wv.skySunDiscSize);
//SkyLocalVars.Vars.sunConstants = new Vector4(wv.skySunMie, scathdr);
//SkyLocalVars.Vars.sunConstants.X = wv.skySunMie.X; //mie phase
//SkyLocalVars.Vars.sunConstants.Y = wv.skySunMie.Y; //mie scatter
//SkyLocalVars.Vars.sunConstants.Z = 0.5f / wv.skySunInfluenceRadius;// * 0.01f; // 0.0025f; //mie size/"range"
//SkyLocalVars.Vars.sunConstants.W = wv.skySunMie.Z;// * scathdr; //mie hdr intensity
SkyLocalVars.Vars.sunConstants.X = wv.skySunMie.X * wv.skySunMie.Y; //mie phase
SkyLocalVars.Vars.sunConstants.Y = wv.skySunMie.Y;// 1.0f /wv.skySunMie.Y;// 1.7f;// wv.skySunMie.Y; //mie scatter
SkyLocalVars.Vars.sunConstants.Z = 0.00003f * wv.skySunInfluenceRadius;// * wv.skySunMie.X;// wv.skySunMie.Z;///720.0f;// * 0.01f; // 0.0025f; //mie size/"range"
SkyLocalVars.Vars.sunConstants.W = wv.skySunMie.Z;// * scathdr; //mie intensity multiplier
SkyLocalVars.Vars.sunDirection = new Vector4(-lights.CurrentSunDir, 0);// wv.sunDirection, 0);
SkyLocalVars.Vars.sunPosition = new Vector4(-lights.CurrentSunDir, 0); //not used
SkyLocalVars.Vars.cloudBaseMinusMidColour = Vector4.Zero;
SkyLocalVars.Vars.cloudMidColour = Vector4.Zero;
SkyLocalVars.Vars.cloudShadowMinusBaseColourTimesShadowStrength = Vector4.Zero;
SkyLocalVars.Vars.cloudDetailConstants = Vector4.Zero;
SkyLocalVars.Vars.cloudConstants1 = Vector4.Zero;
SkyLocalVars.Vars.cloudConstants2 = Vector4.Zero;
SkyLocalVars.Vars.smallCloudConstants = Vector4.Zero;
SkyLocalVars.Vars.smallCloudColorHdr = Vector4.Zero;
SkyLocalVars.Vars.effectsConstants = Vector4.Zero;
SkyLocalVars.Vars.horizonLevel = 0;
SkyLocalVars.Vars.speedConstants = Vector3.Zero;
SkyLocalVars.Vars.starfieldIntensity = wv.skyStarsIten * 5.0f; //makes stars brighter....
SkyLocalVars.Vars.moonDirection = wv.moonDirection;
SkyLocalVars.Vars.moonPosition = Vector3.Zero;//need to update this?
SkyLocalVars.Vars.moonIntensity = wv.skyMoonIten;
SkyLocalVars.Vars.lunarCycle = Vector4.Zero;
SkyLocalVars.Vars.moonColor = wv.skyMoonCol;
SkyLocalVars.Vars.noiseFrequency = 0;
SkyLocalVars.Vars.noiseScale = 0;
SkyLocalVars.Vars.noiseThreshold = 0;
SkyLocalVars.Vars.noiseSoftness = 0;
SkyLocalVars.Vars.noiseDensityOffset = 0;
SkyLocalVars.Vars.noisePhase = Vector4.Zero;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
SkyLocalVars.Update(context);
SkyLocalVars.SetVSCBuffer(context, 0);
SkyLocalVars.SetPSCBuffer(context, 0);
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix);
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 1);
PSSceneVars.Vars.LightDirection = new Vector4(lights.Params.LightDir, 0.0f);
PSSceneVars.Vars.EnableHDR = EnableHDR ? 1u : 0u;
PSSceneVars.Update(context);
PSSceneVars.SetPSCBuffer(context, 1);
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (!model.UseTransform) return;
VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
VSModelVars.Update(context);
VSModelVars.SetVSCBuffer(context, 3);
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
//don't use this version
}
public void SetTextures(DeviceContext context, RenderableTexture starfield)
{
if (starfield != null)
{
context.PixelShader.SetSampler(0, texsampler);
starfield.SetPSResource(context, 0);
}
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null);
context.PixelShader.SetConstantBuffer(1, null);
context.VertexShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(3, null);
context.PixelShader.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void RenderSun(DeviceContext context, Camera camera, Weather weather, ShaderGlobalLights lights)
{
context.VertexShader.Set(sunvs);
context.PixelShader.Set(sunps);
VSSunMoonVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSunMoonVars.Vars.ViewInv = Matrix.Transpose(camera.ViewInvMatrix);
VSSunMoonVars.Vars.CamRel = new Vector4(lights.CurrentSunDir, 0);
VSSunMoonVars.Vars.Size = new Vector2(weather.CurrentValues.skySunDiscSize * 0.008f);
VSSunMoonVars.Vars.Offset = Vector2.Zero;
VSSunMoonVars.Update(context);
VSSunMoonVars.SetVSCBuffer(context, 0);
PSSunMoonVars.Vars.Colour = new Vector4(weather.CurrentValues.skySunDiscCol * weather.CurrentValues.skySunHdr, 1);
PSSunMoonVars.Update(context);
PSSunMoonVars.SetPSCBuffer(context, 0);
context.InputAssembler.InputLayout = sunlayout;
sundisc.Draw(context);
}
public void RenderMoon(DeviceContext context, Camera camera, Weather weather, ShaderGlobalLights lights, RenderableTexture moontex)
{
context.VertexShader.Set(moonvs);
context.PixelShader.Set(moonps);
Quaternion ori = Quaternion.Invert(Quaternion.LookAtRH(Vector3.Zero, lights.CurrentMoonDir, lights.MoonAxis));
Matrix omat = ori.ToMatrix();
VSSunMoonVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSunMoonVars.Vars.ViewInv = Matrix.Transpose(omat);// camera.ViewInvMatrix);
VSSunMoonVars.Vars.CamRel = new Vector4(lights.CurrentMoonDir, 0);
VSSunMoonVars.Vars.Size = new Vector2(weather.CurrentValues.skyMoonDiscSize * 0.008f);
VSSunMoonVars.Vars.Offset = Vector2.Zero;
VSSunMoonVars.Update(context);
VSSunMoonVars.SetVSCBuffer(context, 0);
PSSunMoonVars.Vars.Colour = new Vector4(weather.CurrentValues.skyMoonCol * weather.CurrentValues.skyMoonIten, weather.CurrentValues.skyMoonIten);
PSSunMoonVars.Update(context);
PSSunMoonVars.SetPSCBuffer(context, 0);
context.PixelShader.SetSampler(0, texsampler);
moontex.SetPSResource(context, 0);
context.InputAssembler.InputLayout = moonlayout;
moonquad.Draw(context);
}
public void Dispose()
{
if (disposed) return;
disposed = true;
texsampler.Dispose();
sundisc.Dispose();
moonquad.Dispose();
skylayout.Dispose();
sunlayout.Dispose();
moonlayout.Dispose();
VSSunMoonVars.Dispose();
PSSunMoonVars.Dispose();
SkyLocalVars.Dispose();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSModelVars.Dispose();
PSSceneVars.Dispose();
skyps.Dispose();
skyvs.Dispose();
sunps.Dispose();
sunvs.Dispose();
moonps.Dispose();
moonvs.Dispose();
}
}
}
+645
View File
@@ -0,0 +1,645 @@
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.IO;
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;
using CodeWalker.GameFiles;
using CodeWalker.World;
namespace CodeWalker.Rendering
{
public struct TerrainShaderVSSceneVars
{
public Matrix ViewProj;
}
public struct TerrainShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
public uint HasSkeleton;
public uint HasTransforms;
public uint TintPaletteIndex;
public uint Pad1;
public Vector3 Scale;
public uint Pad2;
}
public struct TerrainShaderVSModelVars
{
public Matrix Transform;
}
public struct TerrainShaderVSGeomVars
{
public uint EnableTint;
public float TintYVal;
public uint Pad4;
public uint Pad5;
}
public struct TerrainShaderPSSceneVars
{
public ShaderGlobalLightParams GlobalLights;
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 struct TerrainShaderPSGeomVars
{
public uint EnableTexture0;
public uint EnableTexture1;
public uint EnableTexture2;
public uint EnableTexture3;
public uint EnableTexture4;
public uint EnableTextureMask;
public uint EnableNormalMap;
public uint ShaderName;
public uint EnableTint;
public uint EnableVertexColour;
public float bumpiness;
public uint Pad102;
}
public class TerrainShader : Shader, IDisposable
{
bool disposed = false;
VertexShader pncctvs;
VertexShader pnccttvs;
VertexShader pnccttxvs;
VertexShader pncctttxvs;
VertexShader pncctxvs;
VertexShader pnctttxvs;
VertexShader pncttxvs;
PixelShader terrainps;
GpuVarsBuffer<TerrainShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<TerrainShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<TerrainShaderVSModelVars> VSModelVars;
GpuVarsBuffer<TerrainShaderVSGeomVars> VSGeomVars;
GpuVarsBuffer<TerrainShaderPSSceneVars> PSSceneVars;
GpuVarsBuffer<TerrainShaderPSGeomVars> PSGeomVars;
SamplerState texsampler;
SamplerState texsampleranis;
SamplerState texsamplertnt;
public bool AnisotropicFilter = false;
public WorldRenderMode RenderMode = WorldRenderMode.Default;
public int RenderVertexColourIndex = 1;
public int RenderTextureCoordIndex = 1;
public int RenderTextureSamplerCoord = 1;
public MetaName RenderTextureSampler = MetaName.DiffuseSampler;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public TerrainShader(Device device)
{
byte[] vspncct = File.ReadAllBytes("Shaders\\TerrainVS_PNCCT.cso");
byte[] vspncctt = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTT.cso");
byte[] vspnccttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTTX.cso");
byte[] vspncctttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTTTX.cso");
byte[] vspncctx = File.ReadAllBytes("Shaders\\TerrainVS_PNCCTX.cso");
byte[] vspnctttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCTTTX.cso");
byte[] vspncttx = File.ReadAllBytes("Shaders\\TerrainVS_PNCTTX.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\TerrainPS.cso");
pncctvs = new VertexShader(device, vspncct);
pnccttvs = new VertexShader(device, vspncctt);
pnccttxvs = new VertexShader(device, vspnccttx);
pncctttxvs = new VertexShader(device, vspncctttx);
pncctxvs = new VertexShader(device, vspncctx);
pnctttxvs = new VertexShader(device, vspnctttx);
pncttxvs = new VertexShader(device, vspncttx);
terrainps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<TerrainShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<TerrainShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<TerrainShaderVSModelVars>(device);
VSGeomVars = new GpuVarsBuffer<TerrainShaderVSGeomVars>(device);
PSSceneVars = new GpuVarsBuffer<TerrainShaderPSSceneVars>(device);
PSGeomVars = new GpuVarsBuffer<TerrainShaderPSGeomVars>(device);
//supported layouts - requires Position, Normal, Colour, Texcoord
layouts.Add(VertexType.PNCCT, new InputLayout(device, vspncct, VertexTypePNCCT.GetLayout()));
layouts.Add(VertexType.PNCCTT, new InputLayout(device, vspncctt, VertexTypePNCCTT.GetLayout()));
layouts.Add(VertexType.PNCTTX, new InputLayout(device, vspncttx, VertexTypePNCTTX.GetLayout()));
layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vspnctttx, VertexTypePNCTTTX_3.GetLayout()));
layouts.Add(VertexType.PNCCTX, new InputLayout(device, vspncctx, VertexTypePNCCTX.GetLayout()));
layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vspnccttx, VertexTypePNCCTTX.GetLayout()));
layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vspnccttx, VertexTypePNCCTTX_2.GetLayout()));
layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vspncctttx, VertexTypePNCCTTTX.GetLayout()));
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsampleranis = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.Anisotropic,
MaximumAnisotropy = 8,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsamplertnt = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.White,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipPoint,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
private void SetVertexShader(DeviceContext context, uint shaderhash)
{
//no longer used.
//PNCCT terrain_cb_w_4lyr_lod (terrain_cb_w_4lyr_lod.sps)
//PNCCTT terrain_cb_w_4lyr_2tex_blend_lod (terrain_cb_w_4lyr_2tex_blend_lod.sps)
//PNCTTX terrain_cb_w_4lyr_cm (terrain_cb_w_4lyr_cm.sps)
//PNCTTX terrain_cb_w_4lyr_cm_tnt (terrain_cb_w_4lyr_cm_tnt.sps)
//PNCTTTX_3 terrain_cb_w_4lyr_cm_pxm (terrain_cb_w_4lyr_cm_pxm.sps)
//PNCTTTX_3 terrain_cb_w_4lyr_cm_pxm_tnt (terrain_cb_w_4lyr_cm_pxm_tnt.sps)
//PNCCTX terrain_cb_w_4lyr (terrain_cb_w_4lyr.sps)
//PNCCTX terrain_cb_w_4lyr_spec (terrain_cb_w_4lyr_spec.sps)
//PNCCTTX terrain_cb_w_4lyr_2tex (terrain_cb_w_4lyr_2tex.sps)
//PNCCTTX terrain_cb_w_4lyr_2tex_blend (terrain_cb_w_4lyr_2tex_blend.sps)
//PNCCTTX_2 terrain_cb_w_4lyr_pxm (terrain_cb_w_4lyr_pxm.sps)
//PNCCTTX_2 terrain_cb_w_4lyr_pxm_spm (terrain_cb_w_4lyr_pxm_spm.sps)
//PNCCTTX_2 terrain_cb_w_4lyr_spec_pxm (terrain_cb_w_4lyr_spec_pxm.sps)
//PNCCTTTX terrain_cb_w_4lyr_2tex_pxm (terrain_cb_w_4lyr_2tex_pxm.sps)
//PNCCTTTX terrain_cb_w_4lyr_2tex_blend_pxm (terrain_cb_w_4lyr_2tex_blend_pxm.sps)
//PNCCTTTX terrain_cb_w_4lyr_2tex_blend_pxm_spm (terrain_cb_w_4lyr_2tex_blend_pxm_spm.sps)
VertexType vt = VertexType.Default;
switch (shaderhash)
{
case 295525123: //terrain_cb_w_4lyr_cm (terrain_cb_w_4lyr_cm.sps) vt: PNCTTX
case 417637541: //terrain_cb_w_4lyr_cm_tnt (terrain_cb_w_4lyr_cm_tnt.sps) vt: PNCTTX
vt = VertexType.PNCTTX;
break;
case 3965214311: //terrain_cb_w_4lyr_cm_pxm_tnt (terrain_cb_w_4lyr_cm_pxm_tnt.sps) vt: PNCTTTX_3
case 4186046662: //terrain_cb_w_4lyr_cm_pxm (terrain_cb_w_4lyr_cm_pxm.sps) vt: PNCTTTX_3
vt = VertexType.PNCTTTX; //cs6_08_struct08
break;
case 3051127652: //terrain_cb_w_4lyr (terrain_cb_w_4lyr.sps) vt: PNCCTX
case 646532852: //terrain_cb_w_4lyr_spec (terrain_cb_w_4lyr_spec.sps) vt: PNCCTX
vt = VertexType.PNCCTX; //hw1_07_grnd_c..
break;
case 2535953532: //terrain_cb_w_4lyr_2tex_blend_lod (terrain_cb_w_4lyr_2tex_blend_lod.sps) vt: PNCCTT
vt = VertexType.PNCCTT; //cs1_12_riverbed1_lod..
break;
case 137526804: //terrain_cb_w_4lyr_lod (terrain_cb_w_4lyr_lod.sps) vt: PNCCT
vt = VertexType.PNCCT; //brdgeplatform_01_lod..
break;
case 2316006813: //terrain_cb_w_4lyr_2tex_blend (terrain_cb_w_4lyr_2tex_blend.sps) vt: PNCCTTX
case 3112820305: //terrain_cb_w_4lyr_2tex (terrain_cb_w_4lyr_2tex.sps) vt: PNCCTTX
case 2601000386: //terrain_cb_w_4lyr_spec_pxm (terrain_cb_w_4lyr_spec_pxm.sps) vt: PNCCTTX_2
case 4105814572: //terrain_cb_w_4lyr_pxm (terrain_cb_w_4lyr_pxm.sps) vt: PNCCTTX_2
case 3400824277: //terrain_cb_w_4lyr_pxm_spm (terrain_cb_w_4lyr_pxm_spm.sps) vt: PNCCTTX_2
vt = VertexType.PNCCTTX; //ch2_04_land02b, ch2_06_terrain01a .. vb_35_beacha
break;
case 653544224: //terrain_cb_w_4lyr_2tex_blend_pxm_spm (terrain_cb_w_4lyr_2tex_blend_pxm_spm.sps) vt: PNCCTTTX
case 2486206885: //terrain_cb_w_4lyr_2tex_blend_pxm (terrain_cb_w_4lyr_2tex_blend_pxm.sps) vt: PNCCTTTX
case 1888432890: //terrain_cb_w_4lyr_2tex_pxm (terrain_cb_w_4lyr_2tex_pxm.sps) vt: PNCCTTTX
vt = VertexType.PNCCTTTX; //ch1_04b_vineland01..
break;
default:
break;
}
SetVertexShader(context, vt);
}
private void SetVertexShader(DeviceContext context, VertexType type)
{
VertexShader vs = pnccttxvs;
switch (type)
{
case VertexType.PNCCT: vs = pncctvs; break;
case VertexType.PNCCTT: vs = pnccttvs; break;
case VertexType.PNCTTX: vs = pncttxvs; break;
case VertexType.PNCTTTX_3: vs = pnctttxvs; break;
case VertexType.PNCCTX: vs = pncctxvs; break;
case VertexType.PNCCTTX: vs = pnccttxvs; break;
case VertexType.PNCCTTX_2: vs = pnccttxvs; break;
case VertexType.PNCCTTTX: vs = pncctttxvs; break;
}
context.VertexShader.Set(vs);
}
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(terrainps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
InputLayout l;
if (layouts.TryGetValue(type, out l))
{
SetVertexShader(context, type); //need to use the correct VS.
context.InputAssembler.InputLayout = l;
return true;
}
return false;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
uint rendermode = 0;
uint rendermodeind = 1;
switch (RenderMode)
{
case WorldRenderMode.VertexNormals:
rendermode = 1;
break;
case WorldRenderMode.VertexTangents:
rendermode = 2;
break;
case WorldRenderMode.VertexColour:
rendermode = 3;
rendermodeind = (uint)RenderVertexColourIndex;
break;
case WorldRenderMode.TextureCoord:
rendermode = 4;
rendermodeind = (uint)RenderTextureCoordIndex;
break;
case WorldRenderMode.SingleTexture:
switch (RenderTextureSampler)
{
case MetaName.DiffuseSampler:
rendermode = 5;
break;
case MetaName.BumpSampler:
rendermode = 6;
break;
case MetaName.SpecSampler:
rendermode = 7;
break;
default:
rendermode = 8;
break;
}
break;
}
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
PSSceneVars.Vars.GlobalLights = lights.Params;
PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u;
PSSceneVars.Vars.RenderMode = rendermode;
PSSceneVars.Vars.RenderModeIndex = rendermodeind;
PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord;
PSSceneVars.Update(context);
PSSceneVars.SetPSCBuffer(context, 0);
if (shadowmap != null)
{
shadowmap.SetFinalRenderResources(context);
}
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Vars.Scale = rend.Scale;
VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0;
VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0;
VSEntityVars.Vars.TintPaletteIndex = rend.TintPaletteIndex;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (!model.UseTransform) return;
VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
VSModelVars.Update(context);
VSModelVars.SetVSCBuffer(context, 3);
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
RenderableTexture texture0 = null;
RenderableTexture texture1 = null;
RenderableTexture texture2 = null;
RenderableTexture texture3 = null;
RenderableTexture texture4 = null;
RenderableTexture texturemask = null;
RenderableTexture tintpal = null;
RenderableTexture normals0 = null;
RenderableTexture normals1 = null;
RenderableTexture normals2 = null;
RenderableTexture normals3 = null;
RenderableTexture normals4 = null;
float tntpalind = 0.0f;
bool usevc = true;
if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0))
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
switch (ihash)
{
case MetaName.DiffuseSampler:
texture0 = itex;
break;
case MetaName.TextureSampler_layer0:
texture1 = itex;
break;
case MetaName.TextureSampler_layer1:
texture2 = itex;
break;
case MetaName.TextureSampler_layer2:
texture3 = itex;
break;
case MetaName.TextureSampler_layer3:
texture4 = itex;
break;
case MetaName.BumpSampler:
normals0 = itex;
break;
case MetaName.BumpSampler_layer0:
normals1 = itex;
break;
case MetaName.BumpSampler_layer1:
normals2 = itex;
break;
case MetaName.BumpSampler_layer2:
normals3 = itex;
break;
case MetaName.BumpSampler_layer3:
normals4 = itex;
break;
case MetaName.lookupSampler:
texturemask = itex;
break;
case MetaName.TintPaletteSampler:
tintpal = itex;
if (tintpal.Key != null)
{
//this is slightly dodgy but vsentvarsdata should have the correct value in it...
tntpalind = (VSEntityVars.Vars.TintPaletteIndex + 0.5f) / tintpal.Key.Height;
}
break;
}
}
//if ((geom.DiffuseSampler >= 0) && (geom.DiffuseSampler < geom.Textures.Length))
//{
// texture0 = geom.Textures[geom.DiffuseSampler];
//}
//if ((geom.TextureSampler_layer0 >= 0) && (geom.TextureSampler_layer0 < geom.Textures.Length))
//{
// texture1 = geom.Textures[geom.TextureSampler_layer0];
//}
//if ((geom.TextureSampler_layer1 >= 0) && (geom.TextureSampler_layer1 < geom.Textures.Length))
//{
// texture2 = geom.Textures[geom.TextureSampler_layer1];
//}
//if ((geom.TextureSampler_layer2 >= 0) && (geom.TextureSampler_layer2 < geom.Textures.Length))
//{
// texture3 = geom.Textures[geom.TextureSampler_layer2];
//}
//if ((geom.TextureSampler_layer3 >= 0) && (geom.TextureSampler_layer3 < geom.Textures.Length))
//{
// texture4 = geom.Textures[geom.TextureSampler_layer3];
//}
//if ((geom.BumpSampler >= 0) && (geom.BumpSampler < geom.Textures.Length))
//{
// normals0 = geom.Textures[geom.BumpSampler];
//}
//if ((geom.BumpSampler_layer0 >= 0) && (geom.BumpSampler_layer0 < geom.Textures.Length))
//{
// normals1 = geom.Textures[geom.BumpSampler_layer0];
//}
//if ((geom.BumpSampler_layer1 >= 0) && (geom.BumpSampler_layer1 < geom.Textures.Length))
//{
// normals2 = geom.Textures[geom.BumpSampler_layer1];
//}
//if ((geom.BumpSampler_layer2 >= 0) && (geom.BumpSampler_layer2 < geom.Textures.Length))
//{
// normals3 = geom.Textures[geom.BumpSampler_layer2];
//}
//if ((geom.BumpSampler_layer3 >= 0) && (geom.BumpSampler_layer3 < geom.Textures.Length))
//{
// normals4 = geom.Textures[geom.BumpSampler_layer3];
//}
//if ((geom.lookupSampler >= 0) && (geom.lookupSampler < geom.Textures.Length))
//{
// texturemask = geom.Textures[geom.lookupSampler];
//}
//if ((geom.TintPaletteSampler >= 0) && (geom.TintPaletteSampler < geom.Textures.Length))
//{
// tintpal = geom.Textures[geom.TintPaletteSampler];
// if (tintpal.Texture != null)
// {
// //this is slightly dodgy but vsentvarsdata should have the correct value in it...
// tntpalind = (vsentvarsdata.TintPaletteIndex + 0.5f) / tintpal.Texture.Height;
// }
//}
}
if (RenderMode == WorldRenderMode.SingleTexture)
{
usevc = false;
switch (RenderTextureSampler)
{
case MetaName.DiffuseSampler:
case MetaName.BumpSampler:
case MetaName.SpecSampler:
break;
default:
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
if (ihash == RenderTextureSampler)
{
texture0 = itex;
break;
}
}
//int directtexind = geom.GetTextureSamplerIndex(RenderTextureSampler);
//if ((directtexind >= 0) && (directtexind < geom.Textures.Length))
//{
// texture0 = geom.Textures[directtexind];
//}
break;
}
}
bool usediff0 = ((texture0 != null) && (texture0.ShaderResourceView != null));
bool usediff1 = ((texture1 != null) && (texture1.ShaderResourceView != null));
bool usediff2 = ((texture2 != null) && (texture2.ShaderResourceView != null));
bool usediff3 = ((texture3 != null) && (texture3.ShaderResourceView != null));
bool usediff4 = ((texture4 != null) && (texture4.ShaderResourceView != null));
bool usemask = ((texturemask != null) && (texturemask.ShaderResourceView != null));
bool usetint = ((tintpal != null) && (tintpal.ShaderResourceView != null));
bool usenm = (((normals0 != null) && (normals0.ShaderResourceView != null)) || ((normals1 != null) && (normals1.ShaderResourceView != null)));
float bumpiness = 1.0f;
if (usenm)
{
bumpiness = geom.bumpiness;
}
PSGeomVars.Vars.EnableTexture0 = usediff0 ? 1u : 0u;
PSGeomVars.Vars.EnableTexture1 = usediff1 ? 1u : 0u;
PSGeomVars.Vars.EnableTexture2 = usediff2 ? 1u : 0u;
PSGeomVars.Vars.EnableTexture3 = usediff3 ? 1u : 0u;
PSGeomVars.Vars.EnableTexture4 = usediff4 ? 1u : 0u;
PSGeomVars.Vars.EnableTextureMask = usemask ? 1u : 0u;
PSGeomVars.Vars.EnableNormalMap = usenm ? 1u : 0u;
PSGeomVars.Vars.ShaderName = geom.DrawableGeom.Shader.Name.Hash;
PSGeomVars.Vars.EnableTint = usetint ? 1u : 0u;
PSGeomVars.Vars.EnableVertexColour = usevc ? 1u : 0u;
PSGeomVars.Vars.bumpiness = bumpiness;//
PSGeomVars.Update(context);
PSGeomVars.SetPSCBuffer(context, 2);
VSGeomVars.Vars.EnableTint = usetint ? 1u : 0u;
VSGeomVars.Vars.TintYVal = tntpalind;
VSGeomVars.Update(context);
VSGeomVars.SetVSCBuffer(context, 4);
context.VertexShader.SetSampler(0, texsamplertnt);
context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler);
if (usediff0) texture0.SetPSResource(context, 0);
if (usediff1) texture1.SetPSResource(context, 2);
if (usediff2) texture2.SetPSResource(context, 3);
if (usediff3) texture3.SetPSResource(context, 4);
if (usediff4) texture4.SetPSResource(context, 5);
if (usemask) texturemask.SetPSResource(context, 6);
if (usetint) tintpal.SetVSResource(context, 0);
if (normals0 != null) normals0.SetPSResource(context, 7);
if (normals1 != null) normals1.SetPSResource(context, 8);
if (normals2 != null) normals2.SetPSResource(context, 9);
if (normals3 != null) normals3.SetPSResource(context, 10);
if (normals4 != null) normals4.SetPSResource(context, 11);
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetShaderResource(1, null);//shadowmap
context.PixelShader.SetSampler(1, null); //shadowmap
context.VertexShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(3, null);
context.PixelShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(4, null);
context.VertexShader.SetSampler(0, null);
context.PixelShader.SetSampler(0, null);
context.VertexShader.SetShaderResource(0, null);
context.PixelShader.SetShaderResource(0, null);
context.PixelShader.SetShaderResource(2, null);
context.PixelShader.SetShaderResource(3, null);
context.PixelShader.SetShaderResource(4, null);
context.PixelShader.SetShaderResource(5, null);
context.PixelShader.SetShaderResource(6, null);
context.PixelShader.SetShaderResource(7, null);
context.PixelShader.SetShaderResource(8, null);
context.PixelShader.SetShaderResource(9, null);
context.PixelShader.SetShaderResource(10, null);
context.PixelShader.SetShaderResource(11, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
if (texsampler != null)
{
texsampler.Dispose();
texsampler = null;
}
if (texsampleranis != null)
{
texsampleranis.Dispose();
texsampleranis = null;
}
if (texsamplertnt != null)
{
texsamplertnt.Dispose();
texsamplertnt = null;
}
foreach (InputLayout layout in layouts.Values)
{
layout.Dispose();
}
layouts.Clear();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSModelVars.Dispose();
VSGeomVars.Dispose();
PSSceneVars.Dispose();
PSGeomVars.Dispose();
terrainps.Dispose();
pncctvs.Dispose();
pnccttvs.Dispose();
pnccttxvs.Dispose();
pncctttxvs.Dispose();
pncctxvs.Dispose();
pnctttxvs.Dispose();
pncttxvs.Dispose();
disposed = true;
}
}
}
+320
View File
@@ -0,0 +1,320 @@
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using System;
using System.Collections.Generic;
using System.IO;
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;
using CodeWalker.GameFiles;
using CodeWalker.World;
namespace CodeWalker.Rendering
{
public struct TreesLodShaderVSSceneVars
{
public Matrix ViewProj;
}
public struct TreesLodShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
public uint HasSkeleton;
public uint HasTransforms;
public uint Pad0;
public uint Pad1;
public Vector3 Scale;
public uint Pad2;
}
public struct TreesLodShaderVSModelVars
{
public Matrix Transform;
}
public struct TreesLodShaderVSGeometryVars
{
public Vector4 AlphaTest;
public Vector4 AlphaScale;
public Vector4 UseTreeNormals;
public Vector4 treeLod2Normal;
public Vector4 treeLod2Params;
}
public struct TreesLodShaderPSSceneVars
{
public ShaderGlobalLightParams GlobalLights;
}
public struct TreesLodShaderPSEntityVars
{
public uint EnableTexture;
public uint Pad1;
public uint Pad2;
public uint Pad3;
}
public class TreesLodShader : Shader, IDisposable
{
bool disposed = false;
VertexShader basicvs;
PixelShader basicps;
GpuVarsBuffer<TreesLodShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<TreesLodShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<TreesLodShaderVSModelVars> VSModelVars;
GpuVarsBuffer<TreesLodShaderVSGeometryVars> VSGeomVars;
GpuVarsBuffer<TreesLodShaderPSSceneVars> PSSceneVars;
GpuVarsBuffer<TreesLodShaderPSEntityVars> PSEntityVars;
SamplerState texsampler;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public TreesLodShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\TreesLodVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\TreesLodPS.cso");
basicvs = new VertexShader(device, vsbytes);
basicps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<TreesLodShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<TreesLodShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<TreesLodShaderVSModelVars>(device);
VSGeomVars = new GpuVarsBuffer<TreesLodShaderVSGeometryVars>(device);
PSSceneVars = new GpuVarsBuffer<TreesLodShaderPSSceneVars>(device);
PSEntityVars = new GpuVarsBuffer<TreesLodShaderPSEntityVars>(device);
//layouts.Add(VertexType.PNCCT, new InputLayout(device, vsbytes, VertexTypePNCCT.GetLayout()));
layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vsbytes, VertexTypePNCCTTTT.GetLayout()));
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(basicvs);
context.PixelShader.Set(basicps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
InputLayout l;
if (layouts.TryGetValue(type, out l))
{
context.InputAssembler.InputLayout = l;
return true;
}
return false;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
PSSceneVars.Vars.GlobalLights = lights.Params;
PSSceneVars.Update(context);
PSSceneVars.SetPSCBuffer(context, 0);
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Vars.Scale = rend.Scale;
VSEntityVars.Vars.HasSkeleton = rend.Renderable.HasSkeleton ? 1u : 0;
VSEntityVars.Vars.HasTransforms = rend.Renderable.HasTransforms ? 1u : 0;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 1);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (!model.UseTransform) return;
VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
VSModelVars.Update(context);
VSModelVars.SetVSCBuffer(context, 2);
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
RenderableTexture texture = null; // ((geom.Textures != null) && (geom.Textures.Length > 0)) ? geom.Textures[0] : null;
//trees_lod2
//PNCCTTTT: texcoord2 seems to be 0-1 for the billboard, vertex pos is billboard root.
//param for billboard dir... (treeLod2Normal)
//trees_lod
//PNCCT:
if (geom.VertexType != VertexType.PNCCTTTT)
{ }
var shader = geom.DrawableGeom.Shader;
if (shader.Name.Hash == 1874959840)
{
int nparams = 0;
MetaName[] hashes = null;
ShaderParameter[] sparams = null;
if (shader.ParametersList != null)
{
nparams = shader.ParametersList.Hashes.Length;
hashes = shader.ParametersList.Hashes;
sparams = shader.ParametersList.Parameters;
}
for (int i = 0; i < nparams; i++)
{
var h = shader.ParametersList.Hashes[i];
switch (h)
{
case MetaName.AlphaTest: VSGeomVars.Vars.AlphaTest = (Vector4)sparams[i].Data; break;
case MetaName.AlphaScale: VSGeomVars.Vars.AlphaScale = (Vector4)sparams[i].Data; break;
case MetaName.UseTreeNormals: VSGeomVars.Vars.UseTreeNormals = (Vector4)sparams[i].Data; break;
case MetaName.treeLod2Normal: VSGeomVars.Vars.treeLod2Normal = (Vector4)sparams[i].Data; break;
case MetaName.treeLod2Params: VSGeomVars.Vars.treeLod2Params = (Vector4)sparams[i].Data; break;
}
}
}
else
{
VSGeomVars.Vars.AlphaTest = Vector4.Zero;
VSGeomVars.Vars.AlphaScale = Vector4.Zero;
VSGeomVars.Vars.UseTreeNormals = Vector4.Zero;
VSGeomVars.Vars.treeLod2Normal = Vector4.Zero;
VSGeomVars.Vars.treeLod2Params = Vector4.Zero;
}
VSGeomVars.Update(context);
VSGeomVars.SetVSCBuffer(context, 3);
if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0))
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
switch (ihash)
{
case MetaName.DiffuseSampler:
texture = itex;
break;
}
if (texture != null) break;
}
////try get default diffuse texture
//if ((geom.DiffuseSampler >= 0) && (geom.DiffuseSampler < geom.Textures.Length))
//{
// texture = geom.Textures[geom.DiffuseSampler];
//}
//if ((texture == null) && (geom.TextureSampler_layer0 >= 0) && (geom.TextureSampler_layer0 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer0];
//}
//if ((texture == null) && (geom.TextureSampler_layer1 >= 0) && (geom.TextureSampler_layer1 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer1];
//}
//if ((texture == null) && (geom.TextureSampler_layer2 >= 0) && (geom.TextureSampler_layer2 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer2];
//}
//if ((texture == null) && (geom.TextureSampler_layer3 >= 0) && (geom.TextureSampler_layer3 < geom.Textures.Length))
//{
// texture = geom.Textures[geom.TextureSampler_layer3];
//}
//fallback try get first texture...
int index = 0;
while (((texture == null) || (texture.Texture2D == null)) && (index < geom.RenderableTextures.Length))
{
texture = geom.RenderableTextures[index];
index++;
}
}
bool usediff = ((texture != null) && (texture.Texture2D != null) && (texture.ShaderResourceView != null));
PSEntityVars.Vars.EnableTexture = usediff ? 1u : 0u;
PSEntityVars.Update(context);
PSEntityVars.SetPSCBuffer(context, 1);
if (usediff)
{
context.PixelShader.SetSampler(0, texsampler);
//context.PixelShader.SetShaderResource(0, difftex.ShaderResourceView);
texture.SetPSResource(context, 0);
}
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null);
context.VertexShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(3, null);
context.PixelShader.SetConstantBuffer(1, null);
context.PixelShader.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
if (texsampler != null)
{
texsampler.Dispose();
texsampler = null;
}
foreach (InputLayout layout in layouts.Values)
{
layout.Dispose();
}
layouts.Clear();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSModelVars.Dispose();
VSGeomVars.Dispose();
PSSceneVars.Dispose();
PSEntityVars.Dispose();
basicps.Dispose();
basicvs.Dispose();
disposed = true;
}
}
}
+564
View File
@@ -0,0 +1,564 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CodeWalker.GameFiles;
using CodeWalker.World;
using SharpDX.Direct3D11;
using SharpDX;
using System.IO;
namespace CodeWalker.Rendering
{
public struct WaterShaderVSSceneVars
{
public Matrix ViewProj;
public Vector4 WaterVector;
public float ScaledTime;
public float ScnPad0;
public float ScnPad1;
public float ScnPad2;
}
public struct WaterShaderVSEntityVars
{
public Vector4 CamRel;
public Quaternion Orientation;
public Vector3 Scale;
public uint EntPad0;
}
public struct WaterShaderVSGeomVars
{
public Vector4 WaterParams;
public uint EnableFlow;
public uint ShaderMode;
public uint GeoPad1;
public uint GeoPad2;
public float RippleSpeed;
public float GeoPad3;
public float GeoPad4;
public float GeoPad5;
}
public struct WaterShaderPSSceneVars
{
public ShaderGlobalLightParams GlobalLights;
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 EnableWaterbumps;//if the waterbump textures are ready..
public uint EnableFogtex; //if the fog texture is ready
public uint ScnPad1;
public uint ScnPad2;
public Vector4 gFlowParams;
public Vector4 CameraPos;
public Vector4 WaterFogParams; //xy = base location, zw = inverse size
}
public struct WaterShaderPSGeomVars
{
public uint EnableTexture;
public uint EnableBumpMap;
public uint EnableFoamMap;
public uint ShaderMode;
public float SpecularIntensity;
public float SpecularFalloff;
public float GeoPad1;
public float GeoPad2;
public float WaveOffset; //for terrainfoam
public float WaterHeight; //for terrainfoam
public float WaveMovement; //for terrainfoam
public float HeightOpacity; //for terrainfoam
public float RippleSpeed;
public float RippleScale;
public float RippleBumpiness;
public float GeoPad3;
}
public class WaterShader : Shader
{
bool disposed = false;
VertexShader vspt;
VertexShader vspct;
VertexShader vspnct;
VertexShader vspnctx;
PixelShader ps;
GpuVarsBuffer<WaterShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<WaterShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<WaterShaderVSGeomVars> VSGeomVars;
GpuVarsBuffer<WaterShaderPSSceneVars> PSSceneVars;
GpuVarsBuffer<WaterShaderPSGeomVars> PSGeomVars;
SamplerState texsampler;
SamplerState texsampleranis;
SamplerState texsamplerflow;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public bool AnisotropicFilter = false;
public WorldRenderMode RenderMode = WorldRenderMode.Default;
public int RenderVertexColourIndex = 1;
public int RenderTextureCoordIndex = 1;
public int RenderTextureSamplerCoord = 1;
public MetaName RenderTextureSampler = MetaName.DiffuseSampler;
public double CurrentRealTime = 0;
public float CurrentElapsedTime = 0;
public bool SpecularEnable = true;
public RenderableTexture waterbump { get; set; }
public RenderableTexture waterbump2 { get; set; }
public RenderableTexture waterfog { get; set; }
//check dt1_21_reflproxy and dt1_05_reflproxy
public WaterShader(Device device)
{
byte[] vsptbytes = File.ReadAllBytes("Shaders\\WaterVS_PT.cso");
byte[] vspctbytes = File.ReadAllBytes("Shaders\\WaterVS_PCT.cso");
byte[] vspnctbytes = File.ReadAllBytes("Shaders\\WaterVS_PNCT.cso");
byte[] vspnctxbytes = File.ReadAllBytes("Shaders\\WaterVS_PNCTX.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\WaterPS.cso");
vspt = new VertexShader(device, vsptbytes);
vspct = new VertexShader(device, vspctbytes);
vspnct = new VertexShader(device, vspnctbytes);
vspnctx = new VertexShader(device, vspnctxbytes);
ps = new PixelShader(device, psbytes);
VSSceneVars = new GpuVarsBuffer<WaterShaderVSSceneVars>(device);
VSEntityVars = new GpuVarsBuffer<WaterShaderVSEntityVars>(device);
VSGeomVars = new GpuVarsBuffer<WaterShaderVSGeomVars>(device);
PSSceneVars = new GpuVarsBuffer<WaterShaderPSSceneVars>(device);
PSGeomVars = new GpuVarsBuffer<WaterShaderPSGeomVars>(device);
layouts.Add(VertexType.PT, new InputLayout(device, vsptbytes, VertexTypePT.GetLayout()));
layouts.Add(VertexType.PCT, new InputLayout(device, vspctbytes, VertexTypePCT.GetLayout()));
layouts.Add(VertexType.Default, new InputLayout(device, vspnctbytes, VertexTypeDefault.GetLayout()));
layouts.Add(VertexType.DefaultEx, new InputLayout(device, vspnctxbytes, VertexTypeDefaultEx.GetLayout()));
texsampler = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipLinear,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsampleranis = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.Black,
ComparisonFunction = Comparison.Always,
Filter = Filter.Anisotropic,
MaximumAnisotropy = 8,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
texsamplerflow = new SamplerState(device, new SamplerStateDescription()
{
AddressU = TextureAddressMode.Clamp,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
BorderColor = Color.White,
ComparisonFunction = Comparison.Always,
Filter = Filter.MinMagMipPoint,
MaximumAnisotropy = 1,
MaximumLod = float.MaxValue,
MinimumLod = 0,
MipLodBias = 0,
});
}
private void SetVertexShader(DeviceContext context, VertexType type)
{
VertexShader vs = vspnct;
switch (type)
{
case VertexType.PT:
vs = vspt;
break;
case VertexType.PCT:
vs = vspct;
break;
case VertexType.Default:
vs = vspnct;
break;
case VertexType.DefaultEx:
vs = vspnctx;
break;
default:
break;
}
context.VertexShader.Set(vs);
}
public override void SetShader(DeviceContext context)
{
context.PixelShader.Set(ps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
InputLayout l;
if (layouts.TryGetValue(type, out l))
{
SetVertexShader(context, type);
context.InputAssembler.InputLayout = l;
return true;
}
return false;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
uint rendermode = 0;
uint rendermodeind = 1;
SpecularEnable = lights.SpecularEnabled;
switch (RenderMode)
{
case WorldRenderMode.VertexNormals:
rendermode = 1;
break;
case WorldRenderMode.VertexTangents:
rendermode = 2;
break;
case WorldRenderMode.VertexColour:
rendermode = 3;
rendermodeind = (uint)RenderVertexColourIndex;
break;
case WorldRenderMode.TextureCoord:
rendermode = 4;
rendermodeind = (uint)RenderTextureCoordIndex;
break;
case WorldRenderMode.SingleTexture:
rendermode = 8;//direct mode
break;
}
float phspd = 4.0f;
float phspdi = 1.0f / phspd;
float phspdh = phspd * 0.5f;
float t = (float)(CurrentRealTime - (Math.Floor(CurrentRealTime * 0.001) * 1000.0))*1.0f;
float ta = t * 2.0f;
float tb = ta + (phspdh);
float t1 = (ta * phspdi - (float)Math.Floor(ta * phspdi)) * phspd;
float t2 = (tb * phspdi - (float)Math.Floor(tb * phspdi)) * phspd;
float s1 = ((t1 < phspdh) ? t1 : phspd - t1) * phspdi * 1.0f;
float s2 = ((t2 < phspdh) ? t2 : phspd - t2) * phspdi * 1.0f;
//float s1 = ((float)Math.Cos(t1 * phspdi * Math.PI * 2) + 1.0f) * 0.5f;
//float s2 = ((float)Math.Cos(t2 * phspdi * Math.PI * 2) + 1.0f) * 0.5f;
float gFlowX = t1*0.5f;
float gFlowY = t2*0.5f;
float gFlowZ = s1;
float gFlowW = s2;
Vector2 fogtexMin = new Vector2(-4000.0f, -4000.0f); //aka water quads min/max
Vector2 fogtexMax = new Vector2(4500.0f, 8000.0f);
Vector2 fogtexInv = 1.0f / (fogtexMax - fogtexMin);
bool usewaterbumps = (waterbump != null) && (waterbump.ShaderResourceView != null) && (waterbump2 != null) && (waterbump2.ShaderResourceView != null);
bool usefogtex = (waterfog != null) && (waterfog.ShaderResourceView != null);
VSSceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
VSSceneVars.Vars.WaterVector = Vector4.Zero;
VSSceneVars.Vars.ScaledTime = t * 0.1f;
VSSceneVars.Update(context);
VSSceneVars.SetVSCBuffer(context, 0);
PSSceneVars.Vars.GlobalLights = lights.Params;
PSSceneVars.Vars.EnableShadows = (shadowmap != null) ? 1u : 0u;
PSSceneVars.Vars.RenderMode = rendermode;
PSSceneVars.Vars.RenderModeIndex = rendermodeind;
PSSceneVars.Vars.RenderSamplerCoord = (uint)RenderTextureSamplerCoord;
PSSceneVars.Vars.EnableWaterbumps = usewaterbumps ? 1u : 0u;
PSSceneVars.Vars.EnableFogtex = usefogtex ? 1u : 0u;
PSSceneVars.Vars.gFlowParams = new Vector4(gFlowX, gFlowY, gFlowZ, gFlowW);
PSSceneVars.Vars.CameraPos = new Vector4(camera.Position, 0.0f);
PSSceneVars.Vars.WaterFogParams = new Vector4(fogtexMin, fogtexInv.X, fogtexInv.Y);
PSSceneVars.Update(context);
PSSceneVars.SetPSCBuffer(context, 0);
if (shadowmap != null)
{
shadowmap.SetFinalRenderResources(context);
}
if (usewaterbumps)
{
context.PixelShader.SetShaderResource(4, waterbump.ShaderResourceView);
context.PixelShader.SetShaderResource(5, waterbump2.ShaderResourceView);
}
if (usefogtex)
{
context.PixelShader.SetShaderResource(6, waterfog.ShaderResourceView);
}
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
VSEntityVars.Vars.CamRel = new Vector4(rend.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = rend.Orientation;
VSEntityVars.Vars.Scale = rend.Scale;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
RenderableTexture texture = null;
RenderableTexture bumptex = null;
RenderableTexture flowtex = null;
RenderableTexture foamtex = null;
RenderableTexture fogtex = null;
if ((geom.RenderableTextures != null) && (geom.RenderableTextures.Length > 0))
{
if (RenderMode == WorldRenderMode.Default)
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
if (itex == null) continue;
switch (ihash)
{
case MetaName.DiffuseSampler:
texture = itex;
break;
case MetaName.BumpSampler:
bumptex = itex;
break;
case MetaName.FlowSampler:
flowtex = itex;
break;
case MetaName.FoamSampler:
foamtex = itex;
break;
case MetaName.FogSampler:
fogtex = itex;
break;
default:
if (texture == null) texture = itex;
break;
}
}
}
else if (RenderMode == WorldRenderMode.SingleTexture)
{
for (int i = 0; i < geom.RenderableTextures.Length; i++)
{
var itex = geom.RenderableTextures[i];
var ihash = geom.TextureParamHashes[i];
if (ihash == RenderTextureSampler)
{
texture = itex;
break;
}
}
}
}
bool usediff = ((texture != null) && (texture.ShaderResourceView != null));
bool usebump = ((bumptex != null) && (bumptex.ShaderResourceView != null));
bool useflow = ((flowtex != null) && (flowtex.ShaderResourceView != null));
bool usefoam = ((foamtex != null) && (foamtex.ShaderResourceView != null));
bool usefog = ((fogtex != null) && (fogtex.ShaderResourceView != null));
uint shaderMode = 0;
var shaderFile = geom.DrawableGeom.Shader.FileName;
switch (shaderFile.Hash)
{
case 1529202445://{water_river.sps}
case 4064804434://{water_riverlod.sps}
case 2871265627://{water_riverocean.sps}
case 1507348828://{water_rivershallow.sps}
case 3945561843://{water_fountain.sps}
case 4234404348://{water_shallow.sps}
case 1077877097://{water_poolenv.sps}
break;
case 1471966282://{water_decal.sps} (should this be in decal batch?)
case 3053856997://{water_riverfoam.sps}
shaderMode = 1;
break;
case 3066724854://{water_terrainfoam.sps}
shaderMode = 2;
break;
default:
break;
}
PSGeomVars.Vars.EnableTexture = usediff ? 1u : 0u;
PSGeomVars.Vars.EnableBumpMap = usebump ? 1u : 0u;
PSGeomVars.Vars.EnableFoamMap = usefoam ? 1u : 0u;
PSGeomVars.Vars.ShaderMode = shaderMode;
PSGeomVars.Vars.SpecularIntensity = SpecularEnable ? 1.0f : 0.0f;// geom.specularIntensityMult;
PSGeomVars.Vars.SpecularFalloff = 1.0f;// geom.specularFalloffMult;
PSGeomVars.Vars.WaveOffset = geom.WaveOffset; //for terrainfoam
PSGeomVars.Vars.WaterHeight = geom.WaterHeight; //for terrainfoam
PSGeomVars.Vars.WaveMovement = geom.WaveMovement; //for terrainfoam
PSGeomVars.Vars.HeightOpacity = geom.HeightOpacity; //for terrainfoam
PSGeomVars.Vars.RippleSpeed = geom.RippleSpeed;
PSGeomVars.Vars.RippleScale = geom.RippleScale;
PSGeomVars.Vars.RippleBumpiness = geom.RippleBumpiness;
PSGeomVars.Update(context);
PSGeomVars.SetPSCBuffer(context, 2);
VSGeomVars.Vars.EnableFlow = useflow ? 1u : 0u;
VSGeomVars.Vars.ShaderMode = shaderMode;
VSGeomVars.Vars.WaterParams = Vector4.Zero;
VSGeomVars.Vars.RippleSpeed = geom.RippleSpeed;
VSGeomVars.Update(context);
VSGeomVars.SetVSCBuffer(context, 3);
context.VertexShader.SetSampler(0, texsamplerflow);
context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler);
if (usediff)
{
texture.SetPSResource(context, 0);
}
if (usebump)
{
bumptex.SetPSResource(context, 2);
}
if (usefoam)
{
foamtex.SetPSResource(context, 3);
}
if (useflow)
{
flowtex.SetVSResource(context, 0);
}
}
public void RenderWaterQuad(DeviceContext context, RenderableWaterQuad quad)
{
SetInputLayout(context, VertexType.PCT);
VSEntityVars.Vars.CamRel = new Vector4(quad.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = Quaternion.Identity;
VSEntityVars.Vars.Scale = Vector3.One;
VSEntityVars.Update(context);
VSEntityVars.SetVSCBuffer(context, 2);
PSGeomVars.Vars.EnableTexture = 0;
PSGeomVars.Vars.EnableBumpMap = 0;
PSGeomVars.Vars.EnableFoamMap = 0;
PSGeomVars.Vars.ShaderMode = 0; //normal water render
PSGeomVars.Vars.SpecularIntensity = SpecularEnable ? 4.2f : 0.0f;// geom.specularIntensityMult;
PSGeomVars.Vars.SpecularFalloff = 1600.0f;// geom.specularFalloffMult;
PSGeomVars.Vars.WaveOffset = 0.0f;// geom.WaveOffset; //for terrainfoam
PSGeomVars.Vars.WaterHeight = 0.0f;// geom.WaterHeight; //for terrainfoam
PSGeomVars.Vars.WaveMovement = 0.0f;// geom.WaveMovement; //for terrainfoam
PSGeomVars.Vars.HeightOpacity = 0.0f;// geom.HeightOpacity; //for terrainfoam
PSGeomVars.Vars.RippleSpeed = 2.1f;// geom.RippleSpeed;
PSGeomVars.Vars.RippleScale = 0.02f;// geom.RippleScale;
PSGeomVars.Vars.RippleBumpiness = 4.5f;// geom.RippleBumpiness;
PSGeomVars.Update(context);
PSGeomVars.SetPSCBuffer(context, 2);
VSGeomVars.Vars.EnableFlow = 0; //no flow for water quads...
VSGeomVars.Vars.ShaderMode = 0; //normal water
VSGeomVars.Vars.WaterParams = Vector4.Zero;
VSGeomVars.Vars.RippleSpeed = 1.0f;// geom.RippleSpeed;
VSGeomVars.Update(context);
VSGeomVars.SetVSCBuffer(context, 3);
context.VertexShader.SetSampler(0, texsamplerflow);
context.PixelShader.SetSampler(0, AnisotropicFilter ? texsampleranis : texsampler);
quad.Render(context);
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.PixelShader.SetConstantBuffer(0, null);
context.VertexShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetConstantBuffer(1, null); //shadowmap
context.PixelShader.SetShaderResource(1, null);//shadowmap
context.PixelShader.SetSampler(1, null); //shadowmap
context.VertexShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(3, null);
context.PixelShader.SetConstantBuffer(2, null);
context.VertexShader.SetConstantBuffer(4, null);
context.VertexShader.SetConstantBuffer(5, null);
context.VertexShader.SetConstantBuffer(6, null);
context.VertexShader.SetSampler(0, null);
context.PixelShader.SetSampler(0, null);
context.PixelShader.SetShaderResource(0, null);
context.PixelShader.SetShaderResource(2, null);
context.PixelShader.SetShaderResource(3, null);
context.PixelShader.SetShaderResource(4, null);
context.PixelShader.SetShaderResource(5, null);
context.VertexShader.SetShaderResource(0, null);
context.VertexShader.SetShaderResource(1, null);
context.VertexShader.SetShaderResource(2, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void Dispose()
{
if (disposed) return;
texsampler.Dispose();
texsampleranis.Dispose();
texsamplerflow.Dispose();
foreach (InputLayout layout in layouts.Values)
{
layout.Dispose();
}
layouts.Clear();
VSSceneVars.Dispose();
VSEntityVars.Dispose();
VSGeomVars.Dispose();
PSSceneVars.Dispose();
PSGeomVars.Dispose();
ps.Dispose();
vspt.Dispose();
vspct.Dispose();
vspnct.Dispose();
vspnctx.Dispose();
disposed = true;
}
}
}
+617
View File
@@ -0,0 +1,617 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CodeWalker.GameFiles;
using CodeWalker.World;
using SharpDX.Direct3D11;
using SharpDX;
using System.IO;
namespace CodeWalker.Rendering
{
public struct WidgetShaderSceneVars
{
public Matrix ViewProj;
public uint Mode; //0=Vertices, 1=Arc
public float Size; //world units
public float SegScale; //arc angle / number of segments
public float SegOffset; //angle offset of arc
public Vector3 CamRel; //center position
public uint CullBack; //culls pixels behind 0,0,0
public Color4 Colour; //colour for arc
public Vector3 Axis1; //axis 1 of arc
public float WidgetPad2;
public Vector3 Axis2; //axis 2 of arc
public float WidgetPad3;
}
public class WidgetShader : Shader
{
VertexShader vs;
PixelShader ps;
GpuVarsBuffer<WidgetShaderSceneVars> SceneVars;
GpuCBuffer<WidgetShaderVertex> Vertices;
public WidgetShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\WidgetVS.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\WidgetPS.cso");
vs = new VertexShader(device, vsbytes);
ps = new PixelShader(device, psbytes);
SceneVars = new GpuVarsBuffer<WidgetShaderSceneVars>(device);
Vertices = new GpuCBuffer<WidgetShaderVertex>(device, 150); //should be more than needed....
}
public void Dispose()
{
Vertices.Dispose();
SceneVars.Dispose();
ps.Dispose();
vs.Dispose();
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(vs);
context.PixelShader.Set(ps);
}
public override bool SetInputLayout(DeviceContext context, VertexType type)
{
context.InputAssembler.InputLayout = null;
context.InputAssembler.SetIndexBuffer(null, SharpDX.DXGI.Format.Unknown, 0);
return true;
}
public override void SetSceneVars(DeviceContext context, Camera camera, Shadowmap shadowmap, ShaderGlobalLights lights)
{
SceneVars.Vars.ViewProj = Matrix.Transpose(camera.ViewProjMatrix);
SceneVars.Update(context);
SceneVars.SetVSCBuffer(context, 0);
}
public override void SetEntityVars(DeviceContext context, ref RenderableInst rend)
{
}
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
}
public override void SetGeomVars(DeviceContext context, RenderableGeometry geom)
{
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
context.VertexShader.SetShaderResource(0, null);
context.VertexShader.Set(null);
context.PixelShader.Set(null);
}
public void DrawDefaultWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size)
{
SetShader(context);
SetInputLayout(context, VertexType.Default);
SceneVars.Vars.Mode = 0; //vertices mode
SceneVars.Vars.CamRel = camrel;
SetSceneVars(context, cam, null, null);
Vector3 xdir = ori.Multiply(Vector3.UnitX);
Vector3 ydir = ori.Multiply(Vector3.UnitY);
Vector3 zdir = ori.Multiply(Vector3.UnitZ);
Color4 xcolour = new Color4(0.8f, 0.0f, 0.0f, 1.0f);
Color4 ycolour = new Color4(0.8f, 0.0f, 0.0f, 1.0f);
Color4 zcolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f);
Vector3[] axes = { xdir, ydir, zdir };
Vector3[] sides = { ydir, xdir, xdir };
Color4[] colours = { xcolour, ycolour, zcolour };
float linestart = 0.0f * size;
float lineend = 1.0f * size;
float arrowstart = 0.9f * size;
float arrowend = 1.0f * size;
float arrowrad = 0.05f * size;
//draw lines...
Vertices.Clear();
for (int i = 0; i < 3; i++)
{
WidgetAxis sa = (WidgetAxis)(1 << i);
Color4 axcol = colours[i];
//main axis lines
Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol));
Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol));
//arrow heads
Vector3 astart = axes[i] * arrowstart;
Vector3 aend = axes[i] * arrowend;
Vector3 aside = sides[i] * arrowrad;
Vertices.Add(new WidgetShaderVertex(aend, axcol));
Vertices.Add(new WidgetShaderVertex(astart + aside, axcol));
Vertices.Add(new WidgetShaderVertex(aend, axcol));
Vertices.Add(new WidgetShaderVertex(astart - aside, axcol));
}
Vertices.Update(context);
Vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
context.Draw(Vertices.CurrentCount, 0);
UnbindResources(context);
}
public void DrawPositionWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size, WidgetAxis selax)
{
SetShader(context);
SetInputLayout(context, VertexType.Default);
SceneVars.Vars.Mode = 0; //vertices mode
SceneVars.Vars.CamRel = camrel;
SetSceneVars(context, cam, null, null);
Vector3 xdir = ori.Multiply(Vector3.UnitX);
Vector3 ydir = ori.Multiply(Vector3.UnitY);
Vector3 zdir = ori.Multiply(Vector3.UnitZ);
Color4 xcolour = new Color4(1.0f, 0.0f, 0.0f, 1.0f);
Color4 ycolour = new Color4(0.0f, 1.0f, 0.0f, 1.0f);
Color4 zcolour = new Color4(0.0f, 0.0f, 1.0f, 1.0f);
Color4 selaxcol = new Color4(1.0f, 1.0f, 0.0f, 1.0f);
Color4 selplcol = new Color4(1.0f, 1.0f, 0.0f, 0.5f);
Vector3[] axes = { xdir, ydir, zdir };
Vector3[] sides1 = { ydir, zdir, xdir };
Vector3[] sides2 = { zdir, xdir, ydir };
WidgetAxis[] sideax1 = { WidgetAxis.Y, WidgetAxis.Z, WidgetAxis.X };
WidgetAxis[] sideax2 = { WidgetAxis.Z, WidgetAxis.X, WidgetAxis.Y };
Color4[] colours = { xcolour, ycolour, zcolour };
Color4[] coloursdark = { xcolour * 0.5f, ycolour * 0.5f, zcolour * 0.5f };
for (int i = 0; i < 3; i++) coloursdark[i].Alpha = 1.0f;
float linestart = 0.2f * size;
float lineend = 1.0f * size;
float sideval = 0.4f * size;
float arrowstart = 1.0f * size;
float arrowend = 1.33f * size;
float arrowrad = 0.06f * size;
float hexx = 0.5f;
float hexy = 0.86602540378443864676372317075294f; //sqrt(0.75)
Vector2[] arrowv =
{
new Vector2(-1, 0) * arrowrad,
new Vector2(-hexx, hexy) * arrowrad,
new Vector2(hexx, hexy) * arrowrad,
new Vector2(1, 0) * arrowrad,
new Vector2(hexx, -hexy) * arrowrad,
new Vector2(-hexx, -hexy) * arrowrad,
new Vector2(-1, 0) * arrowrad
};
//draw lines...
Vertices.Clear();
for (int i = 0; i < 3; i++)
{
WidgetAxis sa = (WidgetAxis)(1 << i);
bool axsel = ((selax & sa) > 0);
Color4 axcol = axsel ? selaxcol : colours[i];
//axis side square lines
Vector3 ax = axes[i] * sideval;
Vector3 s1 = sides1[i] * sideval;
Vector3 s2 = sides2[i] * sideval;
Color4 sc1 = (axsel && ((selax & sideax1[i]) > 0)) ? selaxcol : colours[i];
Color4 sc2 = (axsel && ((selax & sideax2[i]) > 0)) ? selaxcol : colours[i];
Vertices.Add(new WidgetShaderVertex(ax, sc1));
Vertices.Add(new WidgetShaderVertex(ax + s1, sc1));
Vertices.Add(new WidgetShaderVertex(ax, sc2));
Vertices.Add(new WidgetShaderVertex(ax + s2, sc2));
//main axis lines - draw after side lines to be on top
Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol));
Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol));
}
Vertices.Update(context);
Vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
context.Draw(Vertices.CurrentCount, 0);
//draw triangles...
Vertices.Clear();
for (int i = 0; i < 3; i++)
{
//axis arrows - kind of inefficient, but meh
Vector3 aend = axes[i] * arrowend;
Vector3 astart = axes[i] * arrowstart;
for (int n = 0; n < 6; n++)
{
Vector2 a1 = arrowv[n];
Vector2 a2 = arrowv[n + 1];
Vector3 ap1 = astart + sides1[i] * a1.Y + sides2[i] * a1.X;
Vector3 ap2 = astart + sides1[i] * a2.Y + sides2[i] * a2.X;
Vertices.Add(new WidgetShaderVertex(aend, colours[i]));
Vertices.Add(new WidgetShaderVertex(ap1, colours[i]));
Vertices.Add(new WidgetShaderVertex(ap2, colours[i]));
Vertices.Add(new WidgetShaderVertex(astart, coloursdark[i]));
Vertices.Add(new WidgetShaderVertex(ap2, coloursdark[i]));
Vertices.Add(new WidgetShaderVertex(ap1, coloursdark[i]));
}
//selection planes
WidgetAxis sa = (WidgetAxis)(1 << i);
if (((selax & sa) > 0))
{
Vector3 ax = axes[i] * sideval;
for (int n = i + 1; n < 3; n++)
{
WidgetAxis tsa = (WidgetAxis)(1 << n);
if (((selax & tsa) > 0))
{
Vector3 tax = axes[n] * sideval;
Vertices.Add(new WidgetShaderVertex(Vector3.Zero, selplcol));
Vertices.Add(new WidgetShaderVertex(ax, selplcol));
Vertices.Add(new WidgetShaderVertex(tax, selplcol));
Vertices.Add(new WidgetShaderVertex(tax + ax, selplcol));
Vertices.Add(new WidgetShaderVertex(tax, selplcol));
Vertices.Add(new WidgetShaderVertex(ax, selplcol));
}
}
}
}
Vertices.Update(context);
Vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
context.Draw(Vertices.CurrentCount, 0);
UnbindResources(context);
}
public void DrawRotationWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size, WidgetAxis selax, WidgetAxis drawax)
{
SetShader(context);
SetInputLayout(context, VertexType.Default);
SceneVars.Vars.Mode = 0; //vertices mode
SceneVars.Vars.CamRel = camrel;
SetSceneVars(context, cam, null, null);
Vector3 xdir = ori.Multiply(Vector3.UnitX);
Vector3 ydir = ori.Multiply(Vector3.UnitY);
Vector3 zdir = ori.Multiply(Vector3.UnitZ);
Color4 xcolour = new Color4(1.0f, 0.0f, 0.0f, 1.0f);
Color4 ycolour = new Color4(0.0f, 1.0f, 0.0f, 1.0f);
Color4 zcolour = new Color4(0.0f, 0.0f, 1.0f, 1.0f);
Color4 icolour = new Color4(0.5f, 0.5f, 0.5f, 1.0f);
Color4 ocolour = new Color4(0.7f, 0.7f, 0.7f, 1.0f);
Color4 scolour = new Color4(1.0f, 1.0f, 0.0f, 1.0f);
Vector3[] axes = { xdir, ydir, zdir };
Vector3[] sides = { ydir, xdir, xdir };
Color4[] colours = { xcolour, ycolour, zcolour };
float linestart = 0.0f * size;
float lineend = 0.3f * size;
float ocircsize = 1.0f * size;
float icircsize = 0.75f * size;
//draw lines...
Vertices.Clear();
for (int i = 0; i < 3; i++)
{
WidgetAxis sa = (WidgetAxis)(1 << i);
bool axsel = ((selax & sa) > 0);
Color4 axcol = axsel ? colours[i] : icolour;
//main axis lines
Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol));
Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol));
}
Vertices.Update(context);
Vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
context.Draw(Vertices.CurrentCount, 0);
//linestrip for arcs and circles
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineStrip;
Vector3 sdir = Vector3.Normalize(camrel);
//if (cam.IsMapView || cam.IsOrthographic)
//{
// sdir = cam.ViewDirection;
//}
float ad1 = Math.Abs(Vector3.Dot(sdir, Vector3.UnitY));
float ad2 = Math.Abs(Vector3.Dot(sdir, Vector3.UnitZ));
Vector3 ax1 = Vector3.Normalize(Vector3.Cross(sdir, (ad1 > ad2) ? Vector3.UnitY : Vector3.UnitZ));
Vector3 ax2 = Vector3.Normalize(Vector3.Cross(sdir, ax1));
//drawing circles
int segcount = 40;
int vertcount = segcount + 1;
SceneVars.Vars.Mode = 1; //arc mode
SceneVars.Vars.SegScale = ((float)Math.PI) * 2.0f / segcount; //arc angle / number of segments
SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc
SceneVars.Vars.Axis1 = ax1; //axis 1 of arc
SceneVars.Vars.Axis2 = ax2; //axis 2 of arc
SceneVars.Vars.CullBack = 0; //culls pixels behind 0,0,0
//outer circle
if (drawax == WidgetAxis.XYZ)
{
SceneVars.Vars.Size = ocircsize; //world units
SceneVars.Vars.Colour = (selax == WidgetAxis.XYZ) ? scolour : ocolour; //colour for arc
SetSceneVars(context, cam, null, null);
context.Draw(vertcount, 0);
}
//inner circle
SceneVars.Vars.Size = icircsize; //world units
SceneVars.Vars.Colour = icolour; //colour for arc
SetSceneVars(context, cam, null, null);
context.Draw(vertcount, 0);
//drawing arcs - culling done in PS
SceneVars.Vars.Size = icircsize; //world units
SceneVars.Vars.CullBack = 1; //culls pixels behind 0,0,0
if ((drawax & WidgetAxis.X) != 0)
{
SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc
SceneVars.Vars.Axis1 = ydir; //axis 1 of arc
SceneVars.Vars.Axis2 = zdir; //axis 2 of arc
SceneVars.Vars.Colour = (selax == WidgetAxis.X) ? scolour : xcolour; //colour for arc
SetSceneVars(context, cam, null, null);
context.Draw(vertcount, 0);
}
if ((drawax & WidgetAxis.Y) != 0)
{
SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc
SceneVars.Vars.Axis1 = xdir; //axis 1 of arc
SceneVars.Vars.Axis2 = zdir; //axis 2 of arc
SceneVars.Vars.Colour = (selax == WidgetAxis.Y) ? scolour : ycolour; //colour for arc
SetSceneVars(context, cam, null, null);
context.Draw(vertcount, 0);
}
if ((drawax & WidgetAxis.Z) != 0)
{
SceneVars.Vars.SegOffset = 0.0f; //angle offset of arc
SceneVars.Vars.Axis1 = xdir; //axis 1 of arc
SceneVars.Vars.Axis2 = ydir; //axis 2 of arc
SceneVars.Vars.Colour = (selax == WidgetAxis.Z) ? scolour : zcolour; //colour for arc
SetSceneVars(context, cam, null, null);
context.Draw(vertcount, 0);
}
UnbindResources(context);
}
public void DrawScaleWidget(DeviceContext context, Camera cam, Vector3 camrel, Quaternion ori, float size, WidgetAxis selax)
{
SetShader(context);
SetInputLayout(context, VertexType.Default);
SceneVars.Vars.Mode = 0; //vertices mode
SceneVars.Vars.CamRel = camrel;
SetSceneVars(context, cam, null, null);
Vector3 xdir = ori.Multiply(Vector3.UnitX);
Vector3 ydir = ori.Multiply(Vector3.UnitY);
Vector3 zdir = ori.Multiply(Vector3.UnitZ);
Color4 xcolour = new Color4(1.0f, 0.0f, 0.0f, 1.0f);
Color4 ycolour = new Color4(0.0f, 1.0f, 0.0f, 1.0f);
Color4 zcolour = new Color4(0.0f, 0.0f, 1.0f, 1.0f);
Color4 selaxcol = new Color4(1.0f, 1.0f, 0.0f, 1.0f);
Color4 selplcol = new Color4(1.0f, 1.0f, 0.0f, 0.5f);
Vector3[] axes = { xdir, ydir, zdir };
Vector3[] sides1 = { ydir, zdir, xdir };
Vector3[] sides2 = { zdir, xdir, ydir };
WidgetAxis[] sideax1 = { WidgetAxis.Y, WidgetAxis.Z, WidgetAxis.X };
WidgetAxis[] sideax2 = { WidgetAxis.Z, WidgetAxis.X, WidgetAxis.Y };
Color4[] colours = { xcolour, ycolour, zcolour };
Color4[] coloursn = { ycolour, zcolour, xcolour };
Color4[] coloursdark = { xcolour * 0.5f, ycolour * 0.5f, zcolour * 0.5f };
for (int i = 0; i < 3; i++) coloursdark[i].Alpha = 1.0f;
float linestart = 0.0f * size;
float lineend = 1.33f * size;
float innertri = 0.7f * size;
float outertri = 1.0f * size;
float cubestart = 1.28f * size;
float cubeend = 1.33f * size;
float cubesize = 0.025f * size;
//draw lines...
Vertices.Clear();
for (int i = 0; i < 3; i++)
{
WidgetAxis sa = (WidgetAxis)(1 << i);
bool axsel = ((selax & sa) > 0);
Color4 axcol = axsel ? selaxcol : colours[i];
WidgetAxis triaxn = sideax1[i];
bool trisel = axsel && ((selax & triaxn) > 0);
Color4 tricol = trisel ? selaxcol : colours[i];
Color4 trincol = trisel ? selaxcol : coloursn[i];
Vector3 inner1 = axes[i] * innertri;
Vector3 inner2 = sides1[i] * innertri;
Vector3 innera = (inner1 + inner2) * 0.5f;
Vector3 outer1 = axes[i] * outertri;
Vector3 outer2 = sides1[i] * outertri;
Vector3 outera = (outer1 + outer2) * 0.5f;
//triangle axis lines
Vertices.Add(new WidgetShaderVertex(inner1, tricol));
Vertices.Add(new WidgetShaderVertex(innera, tricol));
Vertices.Add(new WidgetShaderVertex(innera, trincol));
Vertices.Add(new WidgetShaderVertex(inner2, trincol));
Vertices.Add(new WidgetShaderVertex(outer1, tricol));
Vertices.Add(new WidgetShaderVertex(outera, tricol));
Vertices.Add(new WidgetShaderVertex(outera, trincol));
Vertices.Add(new WidgetShaderVertex(outer2, trincol));
//main axis lines - draw after side lines to be on top
Vertices.Add(new WidgetShaderVertex(axes[i] * linestart, axcol));
Vertices.Add(new WidgetShaderVertex(axes[i] * lineend, axcol));
}
Vertices.Update(context);
Vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
context.Draw(Vertices.CurrentCount, 0);
//draw triangles...
Vertices.Clear();
for (int i = 0; i < 3; i++)
{
//axis end cubes - kind of inefficient, but meh
Vector3 cend = axes[i] * cubeend;
Vector3 cstart = axes[i] * cubestart;
Vector3 cside1 = sides1[i] * cubesize;
Vector3 cside2 = sides2[i] * cubesize;
Vector3 cv1 = cstart + cside1 - cside2;
Vector3 cv2 = cstart - cside1 - cside2;
Vector3 cv3 = cend + cside1 - cside2;
Vector3 cv4 = cend - cside1 - cside2;
Vector3 cv5 = cstart + cside1 + cside2;
Vector3 cv6 = cstart - cside1 + cside2;
Vector3 cv7 = cend + cside1 + cside2;
Vector3 cv8 = cend - cside1 + cside2;
Color4 col = colours[i];
Color4 cold = coloursdark[i];
Vertices.Add(new WidgetShaderVertex(cv1, cold));
Vertices.Add(new WidgetShaderVertex(cv2, cold));
Vertices.Add(new WidgetShaderVertex(cv5, cold));
Vertices.Add(new WidgetShaderVertex(cv5, cold));
Vertices.Add(new WidgetShaderVertex(cv2, cold));
Vertices.Add(new WidgetShaderVertex(cv6, cold));
Vertices.Add(new WidgetShaderVertex(cv3, col));
Vertices.Add(new WidgetShaderVertex(cv4, col));
Vertices.Add(new WidgetShaderVertex(cv7, col));
Vertices.Add(new WidgetShaderVertex(cv7, col));
Vertices.Add(new WidgetShaderVertex(cv4, col));
Vertices.Add(new WidgetShaderVertex(cv8, col));
Vertices.Add(new WidgetShaderVertex(cv1, col));
Vertices.Add(new WidgetShaderVertex(cv2, col));
Vertices.Add(new WidgetShaderVertex(cv3, col));
Vertices.Add(new WidgetShaderVertex(cv3, col));
Vertices.Add(new WidgetShaderVertex(cv2, col));
Vertices.Add(new WidgetShaderVertex(cv4, col));
Vertices.Add(new WidgetShaderVertex(cv5, col));
Vertices.Add(new WidgetShaderVertex(cv6, col));
Vertices.Add(new WidgetShaderVertex(cv7, col));
Vertices.Add(new WidgetShaderVertex(cv7, col));
Vertices.Add(new WidgetShaderVertex(cv6, col));
Vertices.Add(new WidgetShaderVertex(cv8, col));
Vertices.Add(new WidgetShaderVertex(cv1, col));
Vertices.Add(new WidgetShaderVertex(cv5, col));
Vertices.Add(new WidgetShaderVertex(cv3, col));
Vertices.Add(new WidgetShaderVertex(cv3, col));
Vertices.Add(new WidgetShaderVertex(cv5, col));
Vertices.Add(new WidgetShaderVertex(cv7, col));
Vertices.Add(new WidgetShaderVertex(cv2, col));
Vertices.Add(new WidgetShaderVertex(cv6, col));
Vertices.Add(new WidgetShaderVertex(cv4, col));
Vertices.Add(new WidgetShaderVertex(cv4, col));
Vertices.Add(new WidgetShaderVertex(cv6, col));
Vertices.Add(new WidgetShaderVertex(cv8, col));
//selection triangles
if (selax == WidgetAxis.XYZ)
{
//all axes - just draw inner triangle
Vertices.Add(new WidgetShaderVertex(Vector3.Zero, selplcol));
Vertices.Add(new WidgetShaderVertex(axes[i] * innertri, selplcol));
Vertices.Add(new WidgetShaderVertex(sides1[i] * innertri, selplcol));
}
else
{
WidgetAxis sa = (WidgetAxis)(1 << i);
WidgetAxis na = sideax1[i];
if (((selax & sa) > 0) && ((selax & na) > 0))
{
Vertices.Add(new WidgetShaderVertex(axes[i] * innertri, selplcol));
Vertices.Add(new WidgetShaderVertex(sides1[i] * innertri, selplcol));
Vertices.Add(new WidgetShaderVertex(axes[i] * outertri, selplcol));
Vertices.Add(new WidgetShaderVertex(axes[i] * outertri, selplcol));
Vertices.Add(new WidgetShaderVertex(sides1[i] * innertri, selplcol));
Vertices.Add(new WidgetShaderVertex(sides1[i] * outertri, selplcol));
}
}
}
Vertices.Update(context);
Vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
context.Draw(Vertices.CurrentCount, 0);
UnbindResources(context);
}
}
public struct WidgetShaderVertex
{
public Vector4 Position;
public Color4 Colour;
public WidgetShaderVertex(Vector3 p, Color4 c)
{
Position = new Vector4(p, 0.0f);
Colour = c;
}
}
}
+372
View File
@@ -0,0 +1,372 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX.DXGI;
using Device = SharpDX.Direct3D11.Device;
using Buffer = SharpDX.Direct3D11.Buffer;
using MapFlags = SharpDX.Direct3D11.MapFlags;
using SharpDX.Direct3D11;
using SharpDX;
using SharpDX.Direct3D;
namespace CodeWalker.Rendering
{
public class GpuVarsBuffer<T> where T:struct //shader vars buffer helper!
{
public int Size;
public Buffer Buffer;
public T Vars;
public bool Flag;//for external use
public GpuVarsBuffer(Device device)
{
Size = System.Runtime.InteropServices.Marshal.SizeOf<T>();// (sizeof(T));
Buffer = new Buffer(device, Size, ResourceUsage.Dynamic, BindFlags.ConstantBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0);// //DXUtility::CreateShaderVarsBuffer(Size, name);
}
public void Dispose()
{
if (Buffer != null)
{
Buffer.Dispose();
Buffer = null;
}
}
public void Update(DeviceContext context)
{
var dataBox = context.MapSubresource(Buffer, 0, MapMode.WriteDiscard, MapFlags.None);
Utilities.Write(dataBox.DataPointer, ref Vars);
context.UnmapSubresource(Buffer, 0);
}
public void SetVSCBuffer(DeviceContext context, int slot)
{
context.VertexShader.SetConstantBuffer(slot, Buffer);
}
public void SetPSCBuffer(DeviceContext context, int slot)
{
context.PixelShader.SetConstantBuffer(slot, Buffer);
}
}
public class GpuSBuffer<T> where T : struct //for static struct data as resource view
{
public int StructSize;
public int StructCount;
public int BufferSize;
public Buffer Buffer;
public ShaderResourceView SRV;
public GpuSBuffer(Device device, T[] data)
{
StructCount = data.Length;
StructSize = System.Runtime.InteropServices.Marshal.SizeOf<T>();// (sizeof(T));
BufferSize = StructCount * StructSize;
//var ds = new DataStream(new DataPointer()
Buffer = Buffer.Create<T>(device, BindFlags.ShaderResource, data, BufferSize, ResourceUsage.Default, CpuAccessFlags.None, ResourceOptionFlags.BufferStructured, StructSize);
//Buffer = new Buffer(device, BufferSize, ResourceUsage.Default, BindFlags.ShaderResource, CpuAccessFlags.None, ResourceOptionFlags.BufferStructured, StructSize);
SRV = DXUtility.CreateShaderResourceView(device, Buffer, SharpDX.DXGI.Format.Unknown, SharpDX.Direct3D.ShaderResourceViewDimension.Buffer, 0, 0, StructCount, 0);
}
public void Dispose()
{
if (SRV != null)
{
SRV.Dispose();
SRV = null;
}
if (Buffer != null)
{
Buffer.Dispose();
Buffer = null;
}
}
}
public class GpuCBuffer<T> where T : struct //Dynamic GPU buffer of items updated by CPU
{
public int StructSize;
public int StructCount;
public int BufferSize;
public int CurrentCount;
public Buffer Buffer;
public ShaderResourceView SRV;
public List<T> Data;
public T[] DataArray;
public GpuCBuffer(Device device, int count)
{
StructCount = count;
StructSize = System.Runtime.InteropServices.Marshal.SizeOf<T>();// (sizeof(T));
BufferSize = StructCount * StructSize;
//Buffer = Buffer.Create<T>(device, BindFlags.ShaderResource, null, BufferSize, ResourceUsage.Dynamic, CpuAccessFlags.Write, ResourceOptionFlags.BufferStructured, StructSize);
Buffer = new Buffer(device, BufferSize, ResourceUsage.Dynamic, BindFlags.ShaderResource, CpuAccessFlags.Write, ResourceOptionFlags.BufferStructured, StructSize);
SRV = DXUtility.CreateShaderResourceView(device, Buffer, SharpDX.DXGI.Format.Unknown, SharpDX.Direct3D.ShaderResourceViewDimension.Buffer, 0, 0, StructCount, 0);
Data = new List<T>(count);
DataArray = new T[count];
}
public void Dispose()
{
if (SRV != null)
{
SRV.Dispose();
SRV = null;
}
if (Buffer != null)
{
Buffer.Dispose();
Buffer = null;
}
}
public void Clear()
{
Data.Clear();
CurrentCount = 0;
}
public bool Add(T item)
{
if (CurrentCount < StructCount)
{
Data.Add(item);
CurrentCount++;
return true;
}
return false;
}
public void Update(DeviceContext context)
{
for (int i = 0; i < CurrentCount; i++)
{
DataArray[i] = Data[i];
}
var dataBox = context.MapSubresource(Buffer, 0, MapMode.WriteDiscard, MapFlags.None);
Utilities.Write(dataBox.DataPointer, DataArray, 0, CurrentCount);
context.UnmapSubresource(Buffer, 0);
}
public void SetVSResource(DeviceContext context, int slot)
{
context.VertexShader.SetShaderResource(slot, SRV);
}
public void SetPSResource(DeviceContext context, int slot)
{
context.PixelShader.SetShaderResource(slot, SRV);
}
}
public class GpuBuffer<T> where T : struct //Dynamic GPU buffer of items updated by compute shader
{
public int StructSize;
public int StructCount;
public int ItemTotalSize;
public int ItemCount;
public int Size;
public Buffer Buffer;
public ShaderResourceView SRV;
public UnorderedAccessView UAV;
public GpuBuffer(Device device, int itemSize, int itemCount)
{
StructSize = System.Runtime.InteropServices.Marshal.SizeOf<T>();// sizeof(T)),
StructCount = itemCount * itemSize;
ItemTotalSize = itemSize * StructSize;
ItemCount = itemCount;
Size = StructSize * itemSize * itemCount;
Buffer = DXUtility.CreateBuffer(device, Size, ResourceUsage.Default, BindFlags.ShaderResource | BindFlags.UnorderedAccess, 0, ResourceOptionFlags.BufferStructured, StructSize);
SRV = DXUtility.CreateShaderResourceView(device, Buffer, Format.Unknown, ShaderResourceViewDimension.Buffer, 0, 0, StructCount, 0);
UAV = DXUtility.CreateUnorderedAccessView(device, Buffer, Format.Unknown, UnorderedAccessViewDimension.Buffer, 0, StructCount, 0, 0);
}
public void Dispose()
{
if (UAV != null)
{
UAV.Dispose();
UAV = null;
}
if (SRV != null)
{
SRV.Dispose();
SRV = null;
}
if (Buffer != null)
{
Buffer.Dispose();
Buffer = null;
}
}
}
public class GpuTexture //texture and render targets (depth, MS).
{
public Texture2D Texture;
public Texture2D TextureMS;
public Texture2D Depth;
public Texture2D DepthMS;
public RenderTargetView RTV;
public DepthStencilView DSV;
public RenderTargetView MSRTV;
public DepthStencilView MSDSV;
public ShaderResourceView SRV;
public int VramUsage;
public bool Multisampled;
public bool UseDepth;
public void Init(Device device, int w, int h, Format f, int sc, int sq, bool depth, Format df)
{
VramUsage = 0;
Multisampled = (sc > 1);
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;// D3D11_BIND_DEPTH_STENCIL;
DepthStencilViewDimension dsvd = DepthStencilViewDimension.Texture2D;
Texture = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, 1, 0, u, b, 0, 0);
RTV = DXUtility.CreateRenderTargetView(device, Texture, f, rtvd, 0, 0, 0);
SRV = DXUtility.CreateShaderResourceView(device, Texture, f, srvd, 1, 0, 0, 0);
VramUsage += (wh * fs);
if (Multisampled)
{
b = BindFlags.RenderTarget;
rtvd = RenderTargetViewDimension.Texture2DMultisampled;
dsvd = DepthStencilViewDimension.Texture2DMultisampled;
TextureMS = DXUtility.CreateTexture2D(device, w, h, 1, 1, f, sc, sq, u, b, 0, 0);
MSRTV = DXUtility.CreateRenderTargetView(device, TextureMS, f, rtvd, 0, 0, 0);
VramUsage += (wh * fs);
if (depth)
{
DepthMS = DXUtility.CreateTexture2D(device, w, h, 1, 1, df, sc, sq, u, db, 0, 0);
MSDSV = DXUtility.CreateDepthStencilView(device, DepthMS, df, dsvd);
VramUsage += (wh * DXUtility.ElementSize(df));
}
}
else
{
if (depth)
{
Depth = DXUtility.CreateTexture2D(device, w, h, 1, 1, df, sc, sq, u, db, 0, 0);
DSV = DXUtility.CreateDepthStencilView(device, Depth, df, dsvd);
VramUsage += (wh * DXUtility.ElementSize(df));
}
}
}
public void Dispose()
{
if (SRV != null)
{
SRV.Dispose();
SRV = null;
}
if (MSDSV != null)
{
MSDSV.Dispose();
MSDSV = null;
}
if (MSRTV != null)
{
MSRTV.Dispose();
MSRTV = null;
}
if (DSV != null)
{
DSV.Dispose();
DSV = null;
}
if (RTV != null)
{
RTV.Dispose();
RTV = null;
}
if (DepthMS != null)
{
DepthMS.Dispose();
DepthMS = null;
}
if (Depth != null)
{
Depth.Dispose();
Depth = null;
}
if (TextureMS != null)
{
TextureMS.Dispose();
TextureMS = null;
}
if (Texture != null)
{
Texture.Dispose();
Texture = null;
}
}
public GpuTexture(Device device, int w, int h, Format f, int sc, int sq, bool depth, Format df)
{
Init(device, w, h, f, sc, sq, depth, df);
}
public GpuTexture(Device device, int w, int h, Format f, int sc, int sq)
{
Init(device, w, h, f, sc, sq, false, Format.Unknown);
}
public GpuTexture(Device device, int w, int h, Format f)
{
Init(device, w, h, f, 1, 0, false, Format.Unknown);
}
public void Clear(DeviceContext context, Color4 colour)
{
if (Multisampled)
{
context.ClearRenderTargetView(MSRTV, colour);
if (UseDepth)
{
context.ClearDepthStencilView(MSDSV, DepthStencilClearFlags.Depth, 1.0f, 0);
}
}
else
{
context.ClearRenderTargetView(RTV, colour);
if (UseDepth)
{
context.ClearDepthStencilView(DSV, DepthStencilClearFlags.Depth, 1.0f, 0);
}
}
}
public void ClearDepth(DeviceContext context)
{
if (!UseDepth) return;
if (Multisampled)
{
context.ClearDepthStencilView(MSDSV, DepthStencilClearFlags.Depth, 1.0f, 0);
}
else
{
context.ClearDepthStencilView(DSV, DepthStencilClearFlags.Depth, 1.0f, 0);
}
}
public void SetRenderTarget(DeviceContext context)
{
if (Multisampled)
{
context.OutputMerger.SetRenderTargets(UseDepth ? MSDSV : null, MSRTV);
}
else
{
context.OutputMerger.SetRenderTargets(UseDepth ? DSV : null, RTV);
}
}
}
}
+86
View File
@@ -0,0 +1,86 @@
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.Mathematics.Interop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.Rendering
{
public class RenderTargetSwitch
{
RenderTargetView[] OrigRenderTargetViewArr;
DepthStencilView OrigDepthStencilView;
RasterizerState OrigRasterizerState;
RawViewportF[] OrigViewports;
bool IsReset = true;
//bool ResetOnDestroy = false;
int RenderTargetCount = 1;
public void Dispose()
{
if (OrigRenderTargetViewArr != null)
{
for (int i = 0; i < RenderTargetCount; i++)
{
if (OrigRenderTargetViewArr[i] != null)
{
OrigRenderTargetViewArr[i].Dispose();
}
}
OrigRenderTargetViewArr = null;
}
if (OrigDepthStencilView != null)
{
OrigDepthStencilView.Dispose();
OrigDepthStencilView = null;
}
if (OrigRasterizerState != null)
{
OrigRasterizerState.Dispose();
OrigRasterizerState = null;
}
}
public void Set(DeviceContext context)
{
Dispose();
OrigRenderTargetViewArr = context.OutputMerger.GetRenderTargets(RenderTargetCount, out OrigDepthStencilView);
OrigViewports = context.Rasterizer.GetViewports<RawViewportF>();
OrigRasterizerState = context.Rasterizer.State;
//OrigRenderTargetViewArr = new RenderTargetView[RenderTargetCount];
//uint origNumViewports = 1;
//dc->OMGetRenderTargets(RenderTargetCount, OrigRenderTargetViewArr, &OrigDepthStencilView);
//dc->RSGetViewports(&origNumViewports, &OrigViewport);
//dc->RSGetState(&OrigRasterizerState);
IsReset = false;
}
public void Reset(DeviceContext context)
{
if (IsReset) return;
context.OutputMerger.SetRenderTargets(OrigDepthStencilView, OrigRenderTargetViewArr);
context.Rasterizer.State = OrigRasterizerState;
context.Rasterizer.SetViewports(OrigViewports);
//auto dc = DXManager::GetDeviceContext();
//dc->OMSetRenderTargets(RenderTargetCount, OrigRenderTargetViewArr, OrigDepthStencilView);
//dc->RSSetState(OrigRasterizerState);
//dc->RSSetViewports(1, &OrigViewport);
IsReset = true;
Dispose();
}
};
}
File diff suppressed because it is too large Load Diff
+268
View File
@@ -0,0 +1,268 @@
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 UnitCapsule
{
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 UnitCapsule(Device device, byte[] vsbytes, int detail)
{
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>();
//List<SphTri> nxttris = new List<SphTri>();
verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));//top end
verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 1.0f));//bottom end
//detail = nlats each hemisphere
//nlons = detail*4
int nlats = detail;
int nlons = detail * 4;
int firstlat = 1 - nlats;
int lastlat = nlats-1;
int lastlon = nlons - 1;
int vertsperlon = 2 + (nlats - 1) * 2;
float latrng = 1.0f / (detail);
float lonrng = 1.0f / (nlons);
float halfpi = (float)(0.5 * Math.PI);
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);
for (int lat = firstlat; lat < nlats; lat++)
{
float tlat = lat * latrng;
float rlat = tlat * halfpi;
float laty = (float)Math.Sin(rlat);
float latxz = (float)Math.Cos(rlat);
float hemi = (lat > 0) ? 1.0f : 0.0f;
verts.Add(new Vector4(lonx * latxz, laty, lonz * latxz, hemi));
if (lat == 0)
{
verts.Add(new Vector4(lonx * latxz, laty, lonz * latxz, 1.0f)); //split at the "equator"
}
}
}
for (int lon = 0; lon < nlons; lon++)
{
int i0 = 2 + lon * vertsperlon;//top row
int i1 = i0 + vertsperlon;
int i2 = i1 - 1;//bottom row
int i3 = i2 + vertsperlon;
if (lon == lastlon)
{
i1 = 2;
i3 = 1 + vertsperlon;
}
curtris.Add(new SphTri(0, i1, i0)); //top cap triangles
for (int lat = firstlat; lat <= lastlat; lat++)
{
int offs = lat - firstlat;
int f1 = i0 + offs;
int f2 = f1 + vertsperlon;
int f3 = f1 + 1;
if (lon == lastlon)
{
f2 = 2 + offs;
}
int f4 = f2 + 1;
curtris.Add(new SphTri(f1, f2, f3));
curtris.Add(new SphTri(f3, f2, f4)); //fill the rest
}
curtris.Add(new SphTri(1, i2, i3)); //bottom cap triangles
}
#region cube version (unfinished)
/* cube version
verts.Add(new Vector4(-1.0f, 0.0f, 0.0f, 0.0f));
verts.Add(new Vector4(1.0f, 0.0f, 0.0f, 0.0f));
verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));
verts.Add(new Vector4(0.0f, 1.0f, 0.0f, 1.0f));//bottom end
verts.Add(new Vector4(0.0f, 0.0f, -1.0f, 0.0f));
verts.Add(new Vector4(0.0f, 0.0f, 1.0f, 0.0f));
verts.Add(new Vector4(-1.0f, 0.0f, 0.0f, 1.0f));//0==6 - bottom equator split
verts.Add(new Vector4(1.0f, 0.0f, 0.0f, 1.0f));//1==7
verts.Add(new Vector4(0.0f, 0.0f, -1.0f, 1.0f));//4==8
verts.Add(new Vector4(0.0f, 0.0f, 1.0f, 1.0f));//5==9
curtris.Add(new SphTri(0, 4, 2));
curtris.Add(new SphTri(4, 1, 2));
curtris.Add(new SphTri(1, 5, 2));
curtris.Add(new SphTri(5, 0, 2));
curtris.Add(new SphTri(8, 6, 3));//split halves - Y axis
curtris.Add(new SphTri(7, 8, 3));
curtris.Add(new SphTri(9, 7, 3));
curtris.Add(new SphTri(6, 9, 3));
for (int i = 0; i < verts.Count; i++)
{
vdict[verts[i]] = i;
}
for (int i = 0; i < detail; i++)
{
nxttris.Clear();
foreach (var tri in curtris)
{
Vector4 v1 = verts[tri.v1];
Vector4 v2 = verts[tri.v2];
Vector4 v3 = verts[tri.v3];
Vector4 s1 = new Vector4(Vector3.Normalize((v1 + v2).XYZ()), v1.W);
Vector4 s2 = new Vector4(Vector3.Normalize((v2 + v3).XYZ()), v1.W);
Vector4 s3 = new Vector4(Vector3.Normalize((v3 + v1).XYZ()), v1.W);
int i1, i2, i3;
if (!vdict.TryGetValue(s1, out i1))
{
i1 = verts.Count;
verts.Add(s1);
vdict[s1] = i1;
}
if (!vdict.TryGetValue(s2, out i2))
{
i2 = verts.Count;
verts.Add(s2);
vdict[s2] = i2;
}
if (!vdict.TryGetValue(s3, out i3))
{
i3 = verts.Count;
verts.Add(s3);
vdict[s3] = i3;
}
nxttris.Add(new SphTri(tri.v1, i1, i3));
nxttris.Add(new SphTri(tri.v2, i2, i1));
nxttris.Add(new SphTri(tri.v3, i3, i2));
nxttris.Add(new SphTri(i1, i2, i3));
}
var cur = curtris;
curtris = nxttris;
nxttris = cur;
}
*/
#endregion
List<uint> idata = new List<uint>();
foreach (var tri in curtris)
{
idata.Add((uint)tri.v1);
idata.Add((uint)tri.v2);
idata.Add((uint)tri.v3);
}
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, verts.ToArray());
vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0);
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray());
indexcount = idata.Count;
}
public void Draw(DeviceContext context)
{
context.InputAssembler.InputLayout = InputLayout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexed(indexcount, 0, 0);
}
public void DrawInstanced(DeviceContext context, int count)
{
context.InputAssembler.InputLayout = InputLayout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexedInstanced(indexcount, count, 0, 0, 0);
}
public void Dispose()
{
if (VertexBuffer != null)
{
VertexBuffer.Dispose();
VertexBuffer = null;
}
if (IndexBuffer != null)
{
IndexBuffer.Dispose();
IndexBuffer = null;
}
if (InputLayout != null)
{
InputLayout.Dispose();
InputLayout = null;
}
}
}
}
+228
View File
@@ -0,0 +1,228 @@
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 UnitCube
{
private Buffer VertexBuffer { get; set; }
private Buffer IndexBuffer { get; set; }
private InputLayout InputLayout { get; set; }
private VertexBufferBinding vbbinding;
private bool issigned;
private bool islines;
private bool isnormals;
private int indexcount;
public UnitCube(Device device, byte[] vsbytes, bool signed, bool lines, bool normals)
{
issigned = signed;
islines = lines;
isnormals = normals;
if (normals)
{
InputLayout = new InputLayout(device, vsbytes, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 16, 0),
});
}
else
{
InputLayout = new InputLayout(device, vsbytes, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
});
}
if (signed)
{
if (normals)
{
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[]
{
//position (x4), normal (x3)
//-Z face
-1.0f, -1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f,
//+Z face
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f,
//-Y face
-1.0f, -1.0f, -1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f,
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f,
//+Y face
-1.0f, 1.0f, -1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f,
//-X face
-1.0f, -1.0f, -1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f,
-1.0f, -1.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f,
//+X face
1.0f, -1.0f, -1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f,
1.0f, -1.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f,
});
vbbinding = new VertexBufferBinding(VertexBuffer, 32, 0);
}
else
{
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[]
{
//position (x4)
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
});
vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0);
}
}
else
{
if (normals)
{
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[]
{
//position (x4), normal (x3)
//-Z face
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f,
0.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.0f,-1.0f,0.0f,
//+Z face
0.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,0.0f,1.0f,0.0f,
//-Y face
0.0f, 0.0f, 0.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f,
0.0f, 0.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,-1.0f,0.0f,0.0f,
//+Y face
0.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,1.0f,0.0f,0.0f,
//-X face
0.0f, 0.0f, 0.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f,
0.0f, 0.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f,0.0f,0.0f,0.0f,
//+X face
1.0f, 0.0f, 0.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f,
1.0f, 0.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.0f,0.0f,0.0f,
});
vbbinding = new VertexBufferBinding(VertexBuffer, 32, 0);
}
else
{
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[]
{
//position (x4)
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
});
vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0);
}
}
if (lines)
{
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new uint[]
{
0,1,1,3,3,2,2,0,
4,5,5,7,7,6,6,4,
0,4,1,5,3,7,2,6,
});
indexcount = 24;
}
else
{
if (normals)
{
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new uint[]
{
0,2,1,1,2,3,
4,5,6,5,7,6,
8,9,10,9,11,10,
12,14,13,13,14,15,
16,18,17,17,18,19,
20,21,22,21,23,22
});
indexcount = 36;
}
else
{
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new uint[]
{
0,2,1,1,2,3,
4,5,6,5,7,6,
//todo: other faces
});
indexcount = 12; //36..
}
}
}
public void Draw(DeviceContext context)
{
context.InputAssembler.InputLayout = InputLayout;
if (islines)
{
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList;
}
else
{
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
}
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.Format.R32_UInt, 0);
context.DrawIndexed(indexcount, 0, 0);
}
public void DrawInstanced(DeviceContext context, int count)
{
context.InputAssembler.InputLayout = InputLayout;
if (islines)
{
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList;
}
else
{
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
}
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, SharpDX.DXGI.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;
}
}
}
}
+172
View File
@@ -0,0 +1,172 @@
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 UnitCylinder
{
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 UnitCylinder(Device device, byte[] vsbytes, int detail)
{
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>();
//List<SphTri> nxttris = 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, 0.0f));//0
verts.Add(new Vector4(0.0f, -1.0f, 0.0f, 0.0f));//top normal
verts.Add(new Vector4(lonx, 0.0f, lonz, 0.0f));//1
verts.Add(new Vector4(lonx, 0.0f, lonz, 0.0f));//side normal
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 * 4;// vertsperlon;//top row
int i1 = i0 + 4;// vertsperlon;
int i2 = i0 + 3;//bottom row
int i3 = i2 + 4;// vertsperlon;
int f1 = i0 + 1;
int f2 = f1 + 4;// vertsperlon;
if (lon == lastlon)
{
i1 = 2;
i3 = 5;// 1 + vertsperlon;
f2 = 3;// + offs;
}
curtris.Add(new SphTri(0, i1, i0)); //top cap triangles
curtris.Add(new SphTri(f1, f2, f1+1));
curtris.Add(new SphTri(f1+1, f2, f2+1)); //fill the rest
curtris.Add(new SphTri(1, i2, i3)); //bottom cap triangles
}
List<uint> idata = new List<uint>();
foreach (var tri in curtris)
{
idata.Add((uint)tri.v1);
idata.Add((uint)tri.v2);
idata.Add((uint)tri.v3);
}
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;
}
}
}
}
+93
View File
@@ -0,0 +1,93 @@
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 UnitDisc
{
public int SegmentCount { get; set; }
public int IndexCount { get; set; }
public Buffer VertexBuffer { get; set; }
public Buffer IndexBuffer { get; set; }
private VertexBufferBinding vbbinding;
public UnitDisc(Device device, int segmentCount, bool invert = false)
{
SegmentCount = segmentCount;
List<Vector3> verts = new List<Vector3>();
List<uint> inds = new List<uint>();
verts.Add(Vector3.Zero);
float incr = (float)Math.PI * 2.0f / segmentCount;
for (int i = 0; i < segmentCount; i++)
{
float a = incr * i;
float px = (float)Math.Sin(a);
float py = (float)Math.Cos(a);
verts.Add(new Vector3(px, py, 0));
}
for (int i = 0; i < segmentCount; i++)
{
uint ci = (uint)((i == 0) ? segmentCount : i);
uint ni = (uint)i + 1;
inds.Add(0);
inds.Add(invert ? ni : ci);
inds.Add(invert ? ci : ni);
}
IndexCount = inds.Count;
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, verts.ToArray());
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, inds.ToArray());
vbbinding = new VertexBufferBinding(VertexBuffer, 12, 0);
}
public void Draw(DeviceContext context)
{
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 instcount)
{
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexedInstanced(IndexCount, instcount, 0, 0, 0);
}
public void Dispose()
{
if (VertexBuffer != null)
{
VertexBuffer.Dispose();
VertexBuffer = null;
}
if (IndexBuffer != null)
{
IndexBuffer.Dispose();
IndexBuffer = null;
}
}
public InputElement[] GetLayout()
{
return new[]
{
new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0),
};
}
}
}
+93
View File
@@ -0,0 +1,93 @@
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 UnitQuad
{
public Buffer VertexBuffer { get; set; }
public Buffer IndexBuffer { get; set; }
private VertexBufferBinding vbbinding;
public UnitQuad(Device device, bool invert = false)
{
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, new[]
{
//position (x4), texture (x2)
-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
//new Vector4(-1.0f, -1.0f, 0.0f, 1.0f), new Vector4(1.0f, -1.0f, 0.0f, 1.0f),
//new Vector4(-1.0f, 1.0f, 0.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
//new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.5f, -0.5f, 0.5f, 1.0f),
//new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), new Vector4(0.5f, 0.5f, 0.5f, 1.0f),
});
if (invert)
{
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new[]
{
0u,1u,2u,1u,3u,2u
});
}
else
{
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, new[]
{
0u,2u,1u,1u,2u,3u
});
}
vbbinding = new VertexBufferBinding(VertexBuffer, 24, 0);
}
public void Draw(DeviceContext context)
{
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexed(6, 0, 0);
}
public void DrawInstanced(DeviceContext context, int instcount)
{
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexedInstanced(6, instcount, 0, 0, 0);
}
public void Dispose()
{
if (VertexBuffer != null)
{
VertexBuffer.Dispose();
VertexBuffer = null;
}
if (IndexBuffer != null)
{
IndexBuffer.Dispose();
IndexBuffer = null;
}
}
public InputElement[] GetLayout()
{
return new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0),
};
}
}
}
+181
View File
@@ -0,0 +1,181 @@
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 UnitSphere
{
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 UnitSphere(Device device, byte[] vsbytes, int detail)
{
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<Vector3> verts = new List<Vector3>();
Dictionary<Vector3, int> vdict = new Dictionary<Vector3, int>();
List<SphTri> curtris = new List<SphTri>();
List<SphTri> nxttris = new List<SphTri>();
verts.Add(new Vector3(-1.0f, 0.0f, 0.0f));
verts.Add(new Vector3(1.0f, 0.0f, 0.0f));
verts.Add(new Vector3(0.0f, -1.0f, 0.0f));
verts.Add(new Vector3(0.0f, 1.0f, 0.0f));
verts.Add(new Vector3(0.0f, 0.0f, -1.0f));
verts.Add(new Vector3(0.0f, 0.0f, 1.0f));
curtris.Add(new SphTri(0, 4, 2));
curtris.Add(new SphTri(4, 1, 2));
curtris.Add(new SphTri(1, 5, 2));
curtris.Add(new SphTri(5, 0, 2));
curtris.Add(new SphTri(4, 0, 3));
curtris.Add(new SphTri(1, 4, 3));
curtris.Add(new SphTri(5, 1, 3));
curtris.Add(new SphTri(0, 5, 3));
for (int i = 0; i < verts.Count; i++)
{
vdict[verts[i]] = i;
}
for (int i = 0; i < detail; i++)
{
nxttris.Clear();
foreach (var tri in curtris)
{
Vector3 v1 = verts[tri.v1];
Vector3 v2 = verts[tri.v2];
Vector3 v3 = verts[tri.v3];
Vector3 s1 = Vector3.Normalize(v1 + v2);
Vector3 s2 = Vector3.Normalize(v2 + v3);
Vector3 s3 = Vector3.Normalize(v3 + v1);
int i1, i2, i3;
if (!vdict.TryGetValue(s1, out i1))
{
i1 = verts.Count;
verts.Add(s1);
vdict[s1] = i1;
}
if (!vdict.TryGetValue(s2, out i2))
{
i2 = verts.Count;
verts.Add(s2);
vdict[s2] = i2;
}
if (!vdict.TryGetValue(s3, out i3))
{
i3 = verts.Count;
verts.Add(s3);
vdict[s3] = i3;
}
nxttris.Add(new SphTri(tri.v1, i1, i3));
nxttris.Add(new SphTri(tri.v2, i2, i1));
nxttris.Add(new SphTri(tri.v3, i3, i2));
nxttris.Add(new SphTri(i1, i2, i3));
}
var cur = curtris;
curtris = nxttris;
nxttris = cur;
}
List<Vector4> vdata = new List<Vector4>();
foreach (var vert in verts)
{
vdata.Add(new Vector4(vert, 1.0f));
}
List<uint> idata = new List<uint>();
foreach (var tri in curtris)
{
idata.Add((uint)tri.v1);
idata.Add((uint)tri.v2);
idata.Add((uint)tri.v3);
}
VertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, vdata.ToArray());
vbbinding = new VertexBufferBinding(VertexBuffer, 16, 0);
IndexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, idata.ToArray());
indexcount = idata.Count;
}
public void Draw(DeviceContext context)
{
context.InputAssembler.InputLayout = InputLayout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexed(indexcount, 0, 0);
}
public void DrawInstanced(DeviceContext context, int count)
{
context.InputAssembler.InputLayout = InputLayout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, vbbinding);
context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
context.DrawIndexedInstanced(indexcount, count, 0, 0, 0);
}
public void Dispose()
{
if (VertexBuffer != null)
{
VertexBuffer.Dispose();
VertexBuffer = null;
}
if (IndexBuffer != null)
{
IndexBuffer.Dispose();
IndexBuffer = null;
}
if (InputLayout != null)
{
InputLayout.Dispose();
InputLayout = null;
}
}
}
}