| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <AnKi/Shaders/Common.hlsl>
- #include <AnKi/Shaders/Include/MiscRendererTypes.h>
- /// Flags to fine tune the probe selection in sampleClipmapCommon
- enum SampleClipmapFlag : U32
- {
- kSampleClipmapFlagAccurateClipmapSelection = 1 << 0,
- kSampleClipmapFlagBiasSamplePointTowardsCamera = 1 << 1,
- kSampleClipmapFlagBiasSamplePointSurfaceNormal = 1 << 2,
- kSampleClipmapFlagInvalidProbeRejection = 1 << 3,
- kSampleClipmapFlagChebyshevOcclusion = 1 << 4,
- kSampleClipmapFlagBackfacingProbeRejection = 1 << 5,
- kSampleClipmapFlagUsePreviousFrame = 1 << 6,
- kSampleClipmapFlagFullQuality = kSampleClipmapFlagAccurateClipmapSelection | kSampleClipmapFlagInvalidProbeRejection
- | kSampleClipmapFlagChebyshevOcclusion | kSampleClipmapFlagBackfacingProbeRejection,
- kSampleClipmapFlagNone = 0
- };
- F32 computeClipmapFade(IndirectDiffuseClipmapConstants consts, U32 clipmapIdx, Vec3 cameraPos, Vec3 worldPos, SampleClipmapFlag flags)
- {
- Vec3 aabbMin;
- Vec3 aabbMax;
- if(flags & kSampleClipmapFlagUsePreviousFrame)
- {
- aabbMin = consts.m_previousFrameAabbMins[clipmapIdx].xyz;
- aabbMax = consts.m_previousFrameAabbMins[clipmapIdx].xyz + consts.m_sizes[clipmapIdx].xyz;
- }
- else
- {
- aabbMin = consts.m_aabbMins[clipmapIdx].xyz;
- aabbMax = consts.m_aabbMins[clipmapIdx].xyz + consts.m_sizes[clipmapIdx].xyz;
- }
- const Vec3 distances = select(worldPos > cameraPos, aabbMax - cameraPos, cameraPos - aabbMin);
- Vec3 a = abs(worldPos - cameraPos) / distances;
- a = min(1.0, a);
- a = pow(a, 32.0);
- a = 1.0 - a;
- F32 fade = a.x * a.y * a.z;
- return fade;
- }
- Bool insideClipmap(IndirectDiffuseClipmapConstants consts, U32 clipmapIdx, Vec3 worldPos, SampleClipmapFlag flags)
- {
- Vec3 aabbMin;
- Vec3 aabbMax;
- if(flags & kSampleClipmapFlagUsePreviousFrame)
- {
- aabbMin = consts.m_previousFrameAabbMins[clipmapIdx].xyz;
- aabbMax = consts.m_previousFrameAabbMins[clipmapIdx].xyz + consts.m_sizes[clipmapIdx].xyz;
- }
- else
- {
- aabbMin = consts.m_aabbMins[clipmapIdx].xyz;
- aabbMax = consts.m_aabbMins[clipmapIdx].xyz + consts.m_sizes[clipmapIdx].xyz;
- }
- return (all(worldPos < aabbMax) && all(worldPos > aabbMin));
- }
- U16 findClipmapOnPosition(IndirectDiffuseClipmapConstants consts, Vec3 cameraPos, Vec3 worldPos, F32 randFactor, SampleClipmapFlag flags)
- {
- for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
- {
- const F32 fade = computeClipmapFade(consts, i, cameraPos, worldPos, flags);
- if(fade > randFactor)
- {
- return i;
- }
- }
- return kIndirectDiffuseClipmapCount;
- }
- U16 findClipmapOnPositionCheap(IndirectDiffuseClipmapConstants consts, Vec3 worldPos, SampleClipmapFlag flags)
- {
- for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
- {
- if(insideClipmap(consts, i, worldPos, flags))
- {
- return i;
- }
- }
- return kIndirectDiffuseClipmapCount;
- }
- struct SampleClipmapsArgs
- {
- SampleClipmapFlag m_flags;
- U32 m_primaryVolume; // 0: Irradiance, 1: radiance, 2: avgIrradiance
- F32 m_clipmapSelectionRandFactor;
- Vec3 m_samplePoint;
- Vec3 m_normal;
- Vec3 m_cameraPos;
- };
- Vec3 computeBiasedSamplePoint(Vec3 samplePoint, Vec3 normal, Vec3 cameraPos, SampleClipmapFlag flags, F32 bias)
- {
- constexpr SampleClipmapFlag bothBiases = kSampleClipmapFlagBiasSamplePointTowardsCamera | kSampleClipmapFlagBiasSamplePointSurfaceNormal;
- if(flags & bothBiases)
- {
- Vec3 biasDir = 0.0;
- if(flags & kSampleClipmapFlagBiasSamplePointTowardsCamera)
- {
- biasDir = normalize(cameraPos - samplePoint);
- }
- if(flags & kSampleClipmapFlagBiasSamplePointSurfaceNormal)
- {
- biasDir += normal;
- }
- if((flags & bothBiases) == bothBiases)
- {
- // Normalize if both biases have been applied
- biasDir = normalize(biasDir);
- }
- return samplePoint + biasDir * bias;
- }
- else
- {
- return samplePoint;
- }
- }
- /// Find out the clipmap for a given sample point and sample the probes in the volumes.
- Vec3 sampleClipmapCommon(SampleClipmapsArgs args, SamplerState linearAnyRepeatSampler, IndirectDiffuseClipmapConstants consts)
- {
- const SampleClipmapFlag flags = args.m_flags;
- #if 1
- const U16 clipmapIdx = (flags & kSampleClipmapFlagAccurateClipmapSelection)
- ? findClipmapOnPosition(consts, args.m_cameraPos, args.m_samplePoint, args.m_clipmapSelectionRandFactor, flags)
- : findClipmapOnPositionCheap(consts, args.m_samplePoint, flags);
- #else
- U16 clipmapIdx = 0;
- if(!insideClipmap(consts, clipmapIdx, args.m_samplePoint, flags))
- {
- clipmapIdx = 10;
- }
- #endif
- #if 0
- if(clipmapIdx == 0)
- {
- return Vec3(1, 0, 0);
- }
- else if(clipmapIdx == 1)
- {
- return Vec3(0, 1, 0);
- }
- else if(clipmapIdx == 2)
- {
- return Vec3(0, 0, 1);
- }
- else
- {
- return Vec3(1, 0, 1);
- }
- #endif
- if(clipmapIdx >= kIndirectDiffuseClipmapCount)
- {
- return 0.0;
- }
- const Vec3 clipmapSize = consts.m_sizes[clipmapIdx].xyz;
- const Vec3 probeCountsf = consts.m_probeCounts;
- const IndirectDiffuseClipmapTextures textures = consts.m_textures[clipmapIdx];
- const Vec3 probeSize = clipmapSize / probeCountsf;
- const Vec3 fakeVolumeSize = probeCountsf; // Volume size without the octahedron
- const Vec3 biasedWorldPos = computeBiasedSamplePoint(args.m_samplePoint, args.m_normal, args.m_cameraPos, flags, min3(probeSize) * 0.2);
- const Bool primaryVolumesHaveOctMap = args.m_primaryVolume != 2;
- const F32 octahedronSize =
- (primaryVolumesHaveOctMap) ? ((args.m_primaryVolume == 0) ? textures.m_irradianceOctMapSize : textures.m_radianceOctMapSize) : 1.0;
- const Vec3 realVolumeSize = probeCountsf.xzy * Vec3(octahedronSize + 2.0, octahedronSize + 2.0, 1.0);
- const F32 distMomentsOctSize = textures.m_distanceMomentsOctMapSize;
- const Vec3 distMomentsRealVolumeSize = probeCountsf.xzy * Vec3(distMomentsOctSize + 2.0, distMomentsOctSize + 2.0, 1.0);
- const Vec3 samplePointUvw = frac(biasedWorldPos / clipmapSize);
- const Vec3 icoord = floor(samplePointUvw * fakeVolumeSize - 0.5);
- const Vec3 fcoord = frac(samplePointUvw * fakeVolumeSize - 0.5);
- const Vec3 firstProbePosition = floor((biasedWorldPos - probeSize / 2.0) / probeSize) * probeSize + probeSize / 2.0;
- F32 weightSum = 0.0;
- Vec3 value = 0.0;
- for(U32 i = 0u; i < 8u; ++i)
- {
- const Vec3 xyz = Vec3(UVec3(i, i >> 1u, i >> 2u) & 1u);
- Vec3 coords = icoord + xyz;
- // Repeat
- coords = select(coords >= 0.0, coords, fakeVolumeSize + coords);
- coords = select(coords < fakeVolumeSize, coords, coords - fakeVolumeSize);
- if(flags & kSampleClipmapFlagInvalidProbeRejection)
- {
- const Bool valid = TEX(getBindlessTextureNonUniformIndex3DVec4(textures.m_probeValidityTexture), coords.xzy).x > 0.8;
- if(!valid)
- {
- continue;
- }
- }
- // Reject probes outside the current clipmap
- const Vec3 probePosition = firstProbePosition + xyz * probeSize;
- if(!insideClipmap(consts, clipmapIdx, probePosition, flags))
- {
- continue;
- }
- // Filtering weight
- const Vec3 w3 = select(xyz == 0.0, 1.0 - fcoord, fcoord);
- F32 w = w3.x * w3.y * w3.z;
- // Normal weight
- if(flags & kSampleClipmapFlagBackfacingProbeRejection)
- {
- const Vec3 dir = normalize(probePosition - args.m_samplePoint);
- const F32 wNormal = (dot(dir, args.m_normal) + 1.0) * 0.5;
- w *= (wNormal * wNormal) + 0.2;
- }
- // Chebyshev occlusion
- if(flags & kSampleClipmapFlagChebyshevOcclusion)
- {
- Vec3 uvw = coords.xzy;
- uvw.xy *= distMomentsOctSize + 2.0;
- uvw.xy += 1.0;
- uvw.xy += octahedronEncode(normalize(biasedWorldPos - probePosition)) * distMomentsOctSize;
- uvw.z += 0.5;
- uvw /= distMomentsRealVolumeSize;
- const Vec2 distMoments =
- getBindlessTextureNonUniformIndex3DVec4(textures.m_distanceMomentsTexture).SampleLevel(linearAnyRepeatSampler, uvw, 0.0);
- const F32 variance = abs(distMoments.x * distMoments.x - distMoments.y);
- const F32 posToProbeDist = length(biasedWorldPos - probePosition);
- F32 chebyshevWeight = 1.0;
- if(posToProbeDist > distMoments.x) // occluded
- {
- // v must be greater than 0, which is guaranteed by the if condition above.
- const F32 v = posToProbeDist - distMoments.x;
- chebyshevWeight = variance / (variance + (v * v));
- // Increase the contrast in the weight
- chebyshevWeight = chebyshevWeight * chebyshevWeight * chebyshevWeight;
- chebyshevWeight = max(chebyshevWeight, 0.05);
- }
- w *= chebyshevWeight;
- }
- // Compute the actual coords and sample
- U32 bindlessIndex;
- switch(args.m_primaryVolume)
- {
- case 0:
- bindlessIndex = textures.m_irradianceTexture;
- break;
- case 1:
- bindlessIndex = textures.m_radianceTexture;
- break;
- default:
- bindlessIndex = textures.m_averageIrradianceTexture;
- }
- Vec3 v;
- if(primaryVolumesHaveOctMap)
- {
- Vec3 uvw = coords.xzy;
- uvw.xy *= octahedronSize + 2.0;
- uvw.xy += 1.0;
- uvw.xy += octahedronEncode(args.m_normal) * octahedronSize;
- uvw.z += 0.5;
- uvw /= realVolumeSize;
- v = getBindlessTextureNonUniformIndex3DVec4(bindlessIndex).SampleLevel(linearAnyRepeatSampler, uvw, 0.0);
- }
- else
- {
- v = TEX(getBindlessTextureNonUniformIndex3DVec4(bindlessIndex), coords.xzy);
- }
- value += v * w;
- weightSum += w;
- }
- if(weightSum > kEpsilonF32)
- {
- value /= weightSum;
- }
- else
- {
- value = 0.0;
- }
- return value;
- }
- Vec3 sampleClipmapIrradiance(Vec3 samplePoint, Vec3 normal, Vec3 cameraPos, IndirectDiffuseClipmapConstants consts,
- SamplerState linearAnyRepeatSampler, SampleClipmapFlag flags, F32 randFactor = 0.5)
- {
- SampleClipmapsArgs args;
- args.m_primaryVolume = 0;
- args.m_flags = flags;
- args.m_cameraPos = cameraPos;
- args.m_clipmapSelectionRandFactor = randFactor;
- args.m_normal = normal;
- args.m_samplePoint = samplePoint;
- return sampleClipmapCommon(args, linearAnyRepeatSampler, consts);
- }
- Vec3 sampleClipmapRadiance(Vec3 samplePoint, Vec3 normal, Vec3 cameraPos, IndirectDiffuseClipmapConstants consts, SamplerState linearAnyRepeatSampler,
- SampleClipmapFlag flags, F32 randFactor = 0.5)
- {
- SampleClipmapsArgs args;
- args.m_primaryVolume = 1;
- args.m_flags = flags;
- args.m_cameraPos = cameraPos;
- args.m_clipmapSelectionRandFactor = randFactor;
- args.m_normal = normal;
- args.m_samplePoint = samplePoint;
- return sampleClipmapCommon(args, linearAnyRepeatSampler, consts);
- }
- Vec3 sampleClipmapAvgIrradianceCheap(Vec3 samplePoint, Vec3 cameraPos, IndirectDiffuseClipmapConstants consts, F32 randFactor,
- SamplerState linearAnyRepeatSampler, SampleClipmapFlag flags)
- {
- const U16 clipmapIdx = (flags & kSampleClipmapFlagAccurateClipmapSelection)
- ? findClipmapOnPosition(consts, cameraPos, samplePoint, randFactor, flags)
- : findClipmapOnPositionCheap(consts, samplePoint, flags);
- if(clipmapIdx >= kIndirectDiffuseClipmapCount)
- {
- return 0.0;
- }
- const Vec3 clipmapSize = consts.m_sizes[clipmapIdx].xyz;
- const Vec3 probeCountsf = consts.m_probeCounts;
- const Vec3 probeSize = clipmapSize / probeCountsf;
- const Vec3 biasedWorldPos = computeBiasedSamplePoint(samplePoint, 0.0, cameraPos, flags, min3(probeSize) * 0.2);
- const Vec3 samplePointUvw = (biasedWorldPos / clipmapSize).xzy;
- return getBindlessTextureNonUniformIndex3DVec4(consts.m_textures[clipmapIdx].m_averageIrradianceTexture)
- .SampleLevel(linearAnyRepeatSampler, samplePointUvw, 0.0)
- .xyz;
- }
- Vec3 sampleClipmapAvgIrradiance(Vec3 samplePoint, Vec3 normal, Vec3 cameraPos, IndirectDiffuseClipmapConstants consts,
- SamplerState linearAnyRepeatSampler, SampleClipmapFlag flags, F32 randFactor = 0.5)
- {
- const SampleClipmapFlag requireManualTrilinearFiltering =
- kSampleClipmapFlagInvalidProbeRejection | kSampleClipmapFlagBackfacingProbeRejection | kSampleClipmapFlagChebyshevOcclusion;
- if(flags & requireManualTrilinearFiltering)
- {
- SampleClipmapsArgs args;
- args.m_primaryVolume = 2;
- args.m_flags = flags;
- args.m_cameraPos = cameraPos;
- args.m_clipmapSelectionRandFactor = randFactor;
- args.m_normal = normal;
- args.m_samplePoint = samplePoint;
- return sampleClipmapCommon(args, linearAnyRepeatSampler, consts);
- }
- else
- {
- return sampleClipmapAvgIrradianceCheap(samplePoint, cameraPos, consts, randFactor, linearAnyRepeatSampler, flags);
- }
- }
|