| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- #define CLIP_POS 1
- #define NO_ANIMATION 1
- #include "$ENGINE$\PerCameraData.bslinc"
- #include "$ENGINE$\PerObjectData.bslinc"
- #include "$ENGINE$\VertexInput.bslinc"
- #if MSAA_MODE != 0
- #define MSAA_COUNT 2
- #endif
- #include "$ENGINE$\DepthInput.bslinc"
- #include "$ENGINE$\MaskInput.bslinc"
- #include "$ENGINE$\GBufferOutput.bslinc"
- shader Surface
- {
- mixin PerCameraData;
- mixin PerObjectData;
- mixin VertexInput;
- mixin GBufferOutput;
- mixin DepthInput;
- mixin MaskInput;
- variations
- {
- [name("Blend mode"),show]
- BLEND_MODE =
- {
- [name("Transparent")] 0,
- [name("Stain")] 1,
- [name("Normals")] 2,
- [name("Emissive")] 3
- };
- INSIDE_GEOMETRY = { true, false };
- // 0 - None
- // 1 - Resolve single sample only
- // 2 - Resolve all samples
- MSAA_MODE = { 0, 1, 2 };
- };
-
- blend
- {
- independant = true;
-
- // Scene color
- target
- {
- enabled = true;
- color = { srcA, srcIA, add };
- alpha = { zero, one, add };
-
- #if BLEND_MODE != 3
- writemask = empty;
- #endif
- };
-
- // Albedo
- target
- {
- enabled = true;
-
- #if BLEND_MODE == 1
- color = { dstRGB, zero, add };
- #else
- color = { srcA, srcIA, add };
- #endif
-
- alpha = { zero, one, add };
-
- #if BLEND_MODE != 0
- #if BLEND_MODE != 1
- writemask = empty;
- #endif
- #endif
- };
-
- // Normal
- target
- {
- enabled = true;
- color = { srcA, srcIA, add };
- alpha = { zero, one, add };
-
- #if BLEND_MODE == 3
- writemask = empty;
- #endif
- };
-
- // Metallic & roughness
- target
- {
- enabled = true;
- color = { srcA, srcIA, add };
- alpha = { zero, one, add };
-
- #if BLEND_MODE != 0
- #if BLEND_MODE != 1
- writemask = empty;
- #endif
- #endif
- };
-
- // Velocity
- target
- {
- enabled = true;
- writemask = empty;
- };
- };
-
- depth
- {
- write = false;
-
- #if INSIDE_GEOMETRY
- read = false;
- #else
- read = true;
- #endif
- };
-
- raster
- {
- #if INSIDE_GEOMETRY
- cull = cw;
- #else
- cull = ccw;
- #endif
- };
-
- #if MSAA_MODE > 0
- stencil
- {
- enabled = true;
- readmask = 0x80;
-
- #if INSIDE_GEOMETRY
- back = { keep, keep, keep, eq };
- #else
- front = { keep, keep, keep, eq };
- #endif
-
- #if MSAA_MODE == 1
- reference = 0;
- #else
- reference = 0x80;
- #endif
- };
- #endif
-
- code
- {
- [alias(gOpacityTex)]
- SamplerState gOpacitySamp;
-
- Texture2D gOpacityTex = white;
-
- #if BLEND_MODE == 3
- [alias(gEmissiveMaskTex)]
- SamplerState gEmissiveMaskSamp;
-
- Texture2D gEmissiveMaskTex = black;
- #endif
-
- #if BLEND_MODE != 3
- [alias(gNormalTex)]
- SamplerState gNormalSamp;
-
- Texture2D gNormalTex = normal;
- #endif
-
- #if BLEND_MODE == 0 || BLEND_MODE == 1
- [alias(gAlbedoTex)]
- SamplerState gAlbedoSamp;
-
- [alias(gRoughnessTex)]
- SamplerState gRoughnessSamp;
-
- [alias(gMetalnessTex)]
- SamplerState gMetalnessSamp;
-
- Texture2D gAlbedoTex = white;
- Texture2D gRoughnessTex = white;
- Texture2D gMetalnessTex = black;
- #endif
- cbuffer MaterialParams
- {
- float2 gUVOffset = { 0.0f, 0.0f };
- float2 gUVTile = { 1.0f, 1.0f };
-
- #if BLEND_MODE == 3
- [color][hdr]
- float3 gEmissiveColor = { 1.0f, 1.0f, 1.0f };
- #endif
-
- #if BLEND_MODE == 0 || BLEND_MODE == 1
- [spriteuv(gAlbedoTex)]
- float4 gSpriteUV;
- #endif
- };
-
- [internal]
- cbuffer DecalParams
- {
- float4x4 gWorldToDecal;
- float3 gDecalNormal;
- float gNormalTolerance;
- float gFlipDerivatives;
- uint gLayerMask;
- }
-
- float3x3 getWorldToTangent(float3 N, float3 p, float2 uv)
- {
- float3 dp1 = ddx(p);
- float3 dp2 = ddy(p);
- float2 duv1 = ddx(uv);
- float2 duv2 = ddy(uv);
- float3 dp2perp = cross(dp2, N);
- float3 dp1perp = cross(N, dp1);
- float3 T = dp2perp * duv1.x + dp1perp * duv2.x;
- float3 B = dp2perp * duv1.y + dp1perp * duv2.y;
- float invmax = rsqrt(max(dot(T,T), dot(B,B)));
- return float3x3(T * invmax, B * invmax, N);
- }
- struct DecalVStoFS
- {
- float4 position : SV_Position;
- float4 clipPos : TEXCOORD0;
- };
-
- DecalVStoFS vsmain(VertexInput_PO input)
- {
- DecalVStoFS output;
-
- float4 worldPosition = getVertexWorldPosition(input);
-
- output.position = mul(gMatViewProj, worldPosition);
- output.clipPos = output.position;
-
- return output;
- }
-
- void fsmain(
- in DecalVStoFS input,
- in float4 screenPos : SV_Position,
- #if MSAA_MODE == 2
- uint sampleIdx : SV_SampleIndex,
- #endif
- out float4 OutSceneColor : SV_Target0,
- out float4 OutGBufferA : SV_Target1,
- out float4 OutGBufferB : SV_Target2,
- out float4 OutGBufferC : SV_Target3)
- {
- #if MSAA_MODE == 0
- float deviceZ = gDepthBufferTex.Load(int3(screenPos.xy, 0)).r;
- uint layer = (uint)(gMaskTex.Load(int3(screenPos.xy, 0)).r * 256.0f);
- #elif MSAA_MODE == 1
- float deviceZ = gDepthBufferTex.Load(screenPos.xy, 0).r;
- uint layer = (uint)(gMaskTex.Load(screenPos.xy, 0).r * 256.0f);
- #else
- float deviceZ = gDepthBufferTex.Load(screenPos.xy, sampleIdx).r;
- uint layer = (uint)(gMaskTex.Load(screenPos.xy, sampleIdx).r * 256.0f);
- #endif
-
- if(layer < 32 && (gLayerMask & (1 << layer)) == 0)
- discard;
-
- float depth = convertFromDeviceZ(deviceZ);
- float2 ndcPos = input.clipPos.xy / input.clipPos.w;
-
- // x, y are now in clip space, z, w are in view space
- // We multiply them by a special inverse view-projection matrix, that had the projection entries that effect
- // z, w eliminated (since they are already in view space)
- // Note: Multiply by depth should be avoided if using ortographic projection
- float4 mixedSpacePos = float4(ndcPos.xy * -depth, depth, 1);
- float4 worldPosition4D = mul(gMatScreenToWorld, mixedSpacePos);
- float3 worldPosition = worldPosition4D.xyz / worldPosition4D.w;
-
- float4 decalPos = mul(gWorldToDecal, float4(worldPosition, 1.0f));
- float3 decalUV = (decalPos.xyz + 1.0f) * 0.5f;
-
- float alpha = 0.0f;
- if(any(decalUV < 0.0f) || any(decalUV > 1.0f))
- {
- #ifdef METAL
- // 'discard' is causing artifacts on Metal
- OutSceneColor = 0;
- OutGBufferA = 0;
- OutGBufferB = 0;
- OutGBufferC = 0;
- return;
- #else
- discard;
- #endif
- }
- float3 worldNormal = normalize(cross(ddy(worldPosition), ddx(worldPosition))) * gFlipDerivatives;
- if(dot(worldNormal, gDecalNormal) > gNormalTolerance)
- discard;
-
- float3x3 worldToTangent = getWorldToTangent(worldNormal, worldPosition, decalUV.xy);
-
- float2 uv = (decalUV.xy * gUVTile + gUVOffset);
- #if BLEND_MODE == 0 || BLEND_MODE == 1
- uv = uv * gSpriteUV.zw + gSpriteUV.xy;
- #endif
- float opacity = gOpacityTex.Sample(gOpacitySamp, uv);
- #if BLEND_MODE == 3
- OutSceneColor = float4(gEmissiveColor * gEmissiveMaskTex.Sample(gEmissiveMaskSamp, uv).x, opacity);
- #elif BLEND_MODE == 2
- float3 normal = normalize(gNormalTex.Sample(gNormalSamp, uv) * 2.0f - float3(1, 1, 1));
- // Flip multiplication order since we need to transform with tangentToWorld, which is the transpose
- worldNormal = mul(normal, worldToTangent);
- OutGBufferB = float4(worldNormal * 0.5f + 0.5f, opacity);
- #else
- float4 albedo = gAlbedoTex.Sample(gAlbedoSamp, uv);
- opacity *= albedo.a;
- OutGBufferA = float4(albedo.xyz, opacity);
- float3 normal = normalize(gNormalTex.Sample(gNormalSamp, uv) * 2.0f - float3(1, 1, 1));
- // Flip multiplication order since we need to transform with tangentToWorld, which is the transpose
- worldNormal = mul(normal, worldToTangent);
- OutGBufferB = float4(worldNormal * 0.5f + 0.5f, opacity);
- float roughness = gRoughnessTex.Sample(gRoughnessSamp, uv).x;
- float metalness = gMetalnessTex.Sample(gMetalnessSamp, uv).x;
- OutGBufferC = float4(roughness, metalness, 0.0f, opacity);
- #endif
- }
- };
- };
|