| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma anki technique comp
- #include <AnKi/Shaders/PackFunctions.hlsl>
- #include <AnKi/Shaders/Functions.hlsl>
- #include <AnKi/Shaders/ClusteredShadingFunctions.hlsl>
- #include <AnKi/Shaders/Include/MiscRendererTypes.h>
- RWTexture2D<Vec4> g_gbuffer0Tex : register(u0);
- RWTexture2D<Vec4> g_gbuffer1Tex : register(u1);
- RWTexture2D<Vec4> g_gbuffer2Tex : register(u2);
- Texture2D<Vec4> g_depthTex : register(t0);
- StructuredBuffer<Decal> g_decals : register(t1);
- StructuredBuffer<Cluster> g_clusters : register(t2);
- ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
- SamplerState g_linearAnyClampSampler : register(s0);
- [numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
- {
- UVec2 viewportSize;
- g_depthTex.GetDimensions(viewportSize.x, viewportSize.y);
- if(any(svDispatchThreadId >= viewportSize))
- {
- return;
- }
- // Get worldPos
- const F32 depth = g_depthTex[svDispatchThreadId].r;
- const Vec2 ndc = uvToNdc(Vec2(svDispatchThreadId) / Vec2(viewportSize));
- const Vec4 worldPos4 = mul(g_globalConstants.m_matrices.m_invertedViewProjectionJitter, Vec4(ndc, depth, 1.0));
- const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
- // Get the cluster. Make sure it's dynamically uniform because we are accessing bindless textures later on
- Cluster cluster = getClusterFragCoord<true>(g_clusters, g_globalConstants, Vec3(svDispatchThreadId, depth));
- // Make the decalsMask uniform across the wave because we are accessing bindless textures later on
- U32 decalsMask = cluster.m_decalsMask[0];
- for(U32 i = 1; i < kMaxVisibleDecals / 32; ++i)
- {
- decalsMask |= cluster.m_decalsMask[i];
- }
- if(decalsMask == 0)
- {
- return;
- }
- GbufferInfo<F16> gbuffer = (GbufferInfo<F16>)0;
- unpackGBufferNoVelocity<F16>(g_gbuffer0Tex[svDispatchThreadId], g_gbuffer1Tex[svDispatchThreadId], g_gbuffer2Tex[svDispatchThreadId], gbuffer);
- HVec3 diffuse = gbuffer.m_diffuse;
- F16 roughness = gbuffer.m_roughness;
- F16 metalness = gbuffer.m_metallic;
- U32 idx;
- [loop] while((idx = iterateDecals(cluster)) != kMaxU32)
- {
- const Decal decal = g_decals[idx];
- // Project pos to decal space
- const Vec4 texCoords4 = mul(decal.m_textureMatrix, Vec4(worldPos, 1.0));
- const F32 depth = texCoords4.z / texCoords4.w;
- const Vec2 uv = texCoords4.xy / texCoords4.w;
- if(any(Vec3(uv, depth) < 0.0) || any(Vec3(uv, depth) > 1.0))
- {
- // Outside the volume
- continue;
- }
- // Fade a bit when approaching depth 0 or 1
- const F16 edgeFactor = 1.0 - pow(abs(2.0 * depth - 1.0), 8.0);
- F16 factor = edgeFactor;
- // Do diffuse
- if(decal.m_diffuseTexture != kMaxU32)
- {
- const HVec4 col = getBindlessTexture2DVec4(decal.m_diffuseTexture).SampleLevel(g_linearAnyClampSampler, uv, 0.0);
- factor *= col.a;
- diffuse = lerp(diffuse, col.rgb, factor * decal.m_diffuseBlendFactor);
- }
- // Do metal roughness
- if(decal.m_roughnessMetalnessTexture != kMaxU32)
- {
- const HVec3 col = getBindlessTexture2DVec4(decal.m_roughnessMetalnessTexture).SampleLevel(g_linearAnyClampSampler, uv, 0.0).gba;
- if(decal.m_diffuseTexture == kMaxU32)
- {
- // Can't use the diffuse tex for alpha. Try the alpha from the roughness/metal texture
- factor *= col.z;
- }
- roughness = lerp(roughness, col.x, factor * decal.m_roughnessMetalnessFactor);
- metalness = lerp(metalness, col.y, factor * decal.m_roughnessMetalnessFactor);
- }
- }
- if(any(diffuse != gbuffer.m_diffuse) || roughness != gbuffer.m_roughness || metalness != gbuffer.m_metallic)
- {
- gbuffer.m_diffuse = diffuse;
- gbuffer.m_roughness = roughness;
- gbuffer.m_metallic = metalness;
- const GBufferPixelOut gbufferOut = packGBuffer(gbuffer);
- g_gbuffer0Tex[svDispatchThreadId] = gbufferOut.m_rt0;
- g_gbuffer1Tex[svDispatchThreadId] = gbufferOut.m_rt1;
- g_gbuffer2Tex[svDispatchThreadId] = gbufferOut.m_rt2;
- }
- }
|