91 lines
3.8 KiB
C#
91 lines
3.8 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using TerraFX.Interop.DirectX;
|
|
|
|
namespace Auspex.Rendering.Direct3D;
|
|
|
|
internal sealed class FullscreenPassShader : IDisposable
|
|
{
|
|
public struct Constants
|
|
{
|
|
public float MaxAlpha;
|
|
|
|
public float ClipNativeUI;
|
|
}
|
|
|
|
private unsafe ID3D11Buffer* _constantBuffer;
|
|
|
|
private unsafe ID3D11VertexShader* _vs;
|
|
|
|
private unsafe ID3D11PixelShader* _ps;
|
|
|
|
public unsafe FullscreenPassShader(FrameRenderContext ctx)
|
|
{
|
|
ReadOnlySpan<byte> source = "struct Constants\n{\n float maxAlpha;\n float clipNativeUI;\n};\nConstants k : register(b0);\n\nTexture2D<float4> inputTexture : register(t0);\nTexture2D<float4> maskTexture : register(t1);\n\nSamplerState TextureSampler\n{\n Filter = MIN_MAG_MIP_POINT;\n AddressU = CLAMP;\n AddressV = CLAMP;\n};\n\nstruct VSOutput\n{\n float4 pos : SV_POSITION;\n float2 uv: TEXCOORD;\n};\n\nVSOutput vs(uint id : SV_VertexID)\n{\n VSOutput output;\n\tfloat2 uv = float2((id << 1) & 2, id & 2);\n\toutput.pos = float4(uv * float2(2, -2) + float2(-1, 1), 0, 1);\n output.uv = uv;\n return output;\n}\n\nfloat4 ps(VSOutput input) : SV_Target\n{\n float4 color = inputTexture.Sample(TextureSampler, input.uv);\n if (color.a > 0)\n {\n color.rgb /= color.a;\n }\n float maskAlpha = 1;\n if (k.clipNativeUI > 0.5)\n {\n float4 mask = maskTexture.Sample(TextureSampler, input.uv);\n // Apply mask alpha squared\n // (I don't think this is mathematically correct but it looks better)\n maskAlpha = 1 - mask.a;\n maskAlpha *= maskAlpha;\n }\n color.a = min(color.a, k.maxAlpha) * maskAlpha;\n return color;\n}"u8;
|
|
TriangleFillShader.CompileShader(source, "vs"u8, "vs_5_0"u8, out var blob, "FSP VS");
|
|
TriangleFillShader.CompileShader(source, "ps"u8, "ps_5_0"u8, out var blob2, "FSP PS");
|
|
ID3D11VertexShader* vs = default(ID3D11VertexShader*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), null, &vs));
|
|
_vs = vs;
|
|
ID3D11PixelShader* ps = default(ID3D11PixelShader*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreatePixelShader(blob2->GetBufferPointer(), blob2->GetBufferSize(), null, &ps));
|
|
_ps = ps;
|
|
D3D11_BUFFER_DESC d3D11_BUFFER_DESC = new D3D11_BUFFER_DESC
|
|
{
|
|
ByteWidth = 16u,
|
|
Usage = D3D11_USAGE.D3D11_USAGE_DEFAULT,
|
|
BindFlags = 4u
|
|
};
|
|
ID3D11Buffer* constantBuffer = default(ID3D11Buffer*);
|
|
Marshal.ThrowExceptionForHR(ctx.Device->CreateBuffer(&d3D11_BUFFER_DESC, null, &constantBuffer));
|
|
_constantBuffer = constantBuffer;
|
|
blob->Release();
|
|
blob2->Release();
|
|
}
|
|
|
|
public unsafe void Dispose()
|
|
{
|
|
if (_constantBuffer != null)
|
|
{
|
|
_constantBuffer->Release();
|
|
_constantBuffer = null;
|
|
}
|
|
if (_vs != null)
|
|
{
|
|
_vs->Release();
|
|
_vs = null;
|
|
}
|
|
if (_ps != null)
|
|
{
|
|
_ps->Release();
|
|
_ps = null;
|
|
}
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
public unsafe void UpdateConstants(FrameRenderContext ctx, Constants consts)
|
|
{
|
|
ctx.Context->UpdateSubresource((ID3D11Resource*)_constantBuffer, 0u, null, &consts, 0u, 0u);
|
|
}
|
|
|
|
public unsafe void Bind(FrameRenderContext ctx)
|
|
{
|
|
ctx.Context->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY.D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
ctx.Context->VSSetShader(_vs, null, 0u);
|
|
ctx.Context->PSSetShader(_ps, null, 0u);
|
|
ID3D11Buffer* constantBuffer = _constantBuffer;
|
|
ctx.Context->PSSetConstantBuffers(0u, 1u, &constantBuffer);
|
|
ctx.Context->GSSetShader(null, null, 0u);
|
|
}
|
|
|
|
public unsafe void Draw(FrameRenderContext ctx, ID3D11ShaderResourceView* baseSRV, ID3D11ShaderResourceView* maskSRV)
|
|
{
|
|
ctx.Context->PSSetShaderResources(0u, 1u, &baseSRV);
|
|
ctx.Context->PSSetShaderResources(1u, 1u, &maskSRV);
|
|
Bind(ctx);
|
|
ctx.Context->Draw(3u, 0u);
|
|
ID3D11ShaderResourceView* ptr = null;
|
|
ctx.Context->PSSetShaderResources(0u, 1u, &ptr);
|
|
ctx.Context->PSSetShaderResources(1u, 1u, &ptr);
|
|
}
|
|
}
|