|
|
@@ -1,192 +0,0 @@
|
|
|
-// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
|
|
|
-// All rights reserved.
|
|
|
-// Code licensed under the BSD License.
|
|
|
-// http://www.anki3d.org/LICENSE
|
|
|
-
|
|
|
-#pragma anki mutator ENABLE_SHADOWS 0 1
|
|
|
-
|
|
|
-#pragma anki input const UVec2 FB_SIZE
|
|
|
-#pragma anki input const UVec3 CLUSTER_COUNT
|
|
|
-#pragma anki input const U32 NOISE_MAP_SIZE
|
|
|
-
|
|
|
-#pragma anki start vert
|
|
|
-#include <shaders/QuadVert.glsl>
|
|
|
-#pragma anki end
|
|
|
-
|
|
|
-#pragma anki start frag
|
|
|
-#include <shaders/Common.glsl>
|
|
|
-#include <shaders/Functions.glsl>
|
|
|
-
|
|
|
-#define LIGHT_TEX_BINDING 3
|
|
|
-#define LIGHT_UBO_BINDING 0
|
|
|
-#define LIGHT_SS_BINDING 0
|
|
|
-#define LIGHT_SET 0
|
|
|
-#define LIGHT_LIGHTS
|
|
|
-#define LIGHT_COMMON_UNIS
|
|
|
-#include <shaders/ClusteredShadingCommon.glsl>
|
|
|
-
|
|
|
-layout(location = 0) in Vec2 in_uv;
|
|
|
-
|
|
|
-layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_msDepthRt;
|
|
|
-layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2DArray u_noiseTex;
|
|
|
-layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_historyRt;
|
|
|
-
|
|
|
-layout(std140, ANKI_UBO_BINDING(0, 3), row_major) uniform ubo0_
|
|
|
-{
|
|
|
- Vec4 u_linearizeNoiseTexOffsetLayer;
|
|
|
- Vec4 u_fogParticleColorPad1;
|
|
|
-};
|
|
|
-
|
|
|
-#define u_linearize UNIFORM(u_linearizeNoiseTexOffsetLayer.xy)
|
|
|
-#define u_noiseYOffset UNIFORM(u_linearizeNoiseTexOffsetLayer.z)
|
|
|
-#define u_noiseLayer UNIFORM(u_linearizeNoiseTexOffsetLayer.w)
|
|
|
-#define u_fogParticleColor UNIFORM(u_fogParticleColorPad1.rgb)
|
|
|
-
|
|
|
-layout(location = 0) out Vec3 out_color;
|
|
|
-
|
|
|
-const U32 MAX_ITERATIONS = 256u;
|
|
|
-const F32 JITTER_DISTANCE = 10.0; // In meters
|
|
|
-const F32 HISTORY_FEEDBACK = 1.0 / 16.0;
|
|
|
-
|
|
|
-// Return the diffuse color without taking into account the diffuse term of the particles.
|
|
|
-Vec3 computeLightColor(Vec3 fragPos, U32 idxOffset)
|
|
|
-{
|
|
|
- Vec3 color = Vec3(0.0);
|
|
|
-
|
|
|
- // Skip decals
|
|
|
- U32 count = u_lightIndices[idxOffset];
|
|
|
- idxOffset += count + 1u;
|
|
|
-
|
|
|
- // Point lights
|
|
|
- count = u_lightIndices[idxOffset++];
|
|
|
- U32 idxOffsetEnd = idxOffset + count;
|
|
|
- ANKI_LOOP while(idxOffset < idxOffsetEnd)
|
|
|
- {
|
|
|
- PointLight light = u_pointLights[u_lightIndices[idxOffset++]];
|
|
|
-
|
|
|
- Vec3 frag2Light = light.m_posRadius.xyz - fragPos;
|
|
|
- F32 factor = computeAttenuationFactor(light.m_posRadius.w, frag2Light);
|
|
|
-
|
|
|
-#if ENABLE_SHADOWS
|
|
|
- if(light.m_diffuseColorTileSize.w >= 0.0)
|
|
|
- {
|
|
|
- factor *= computeShadowFactorOmni(
|
|
|
- frag2Light, light.m_radiusPad1.x, light.m_atlasTiles, light.m_diffuseColorTileSize.w, u_shadowTex);
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- color += light.m_diffuseColorTileSize.rgb * factor;
|
|
|
- }
|
|
|
-
|
|
|
- // Spot lights
|
|
|
- count = u_lightIndices[idxOffset++];
|
|
|
- idxOffsetEnd = idxOffset + count;
|
|
|
- ANKI_LOOP while(idxOffset < idxOffsetEnd)
|
|
|
- {
|
|
|
- SpotLight light = u_spotLights[u_lightIndices[idxOffset++]];
|
|
|
-
|
|
|
- Vec3 frag2Light = light.m_posRadius.xyz - fragPos;
|
|
|
- F32 factor = computeAttenuationFactor(light.m_posRadius.w, frag2Light);
|
|
|
-
|
|
|
- Vec3 l = normalize(frag2Light);
|
|
|
-
|
|
|
- factor *=
|
|
|
- computeSpotFactor(l, light.m_outerCosInnerCos.x, light.m_outerCosInnerCos.y, light.m_lightDirRadius.xyz);
|
|
|
-
|
|
|
-#if ENABLE_SHADOWS
|
|
|
- F32 shadowmapLayerIdx = light.m_diffuseColorShadowmapId.w;
|
|
|
- if(shadowmapLayerIdx >= 0.0)
|
|
|
- {
|
|
|
- factor *= computeShadowFactorSpot(light.m_texProjectionMat, fragPos, light.m_lightDirRadius.w, u_shadowTex);
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- color += light.m_diffuseColorShadowmapId.rgb * factor;
|
|
|
- }
|
|
|
-
|
|
|
- return color;
|
|
|
-}
|
|
|
-
|
|
|
-Vec3 readHistory(Vec3 worldPos, out F32 historyFeedback)
|
|
|
-{
|
|
|
- Vec4 v4 = u_prevViewProjMat * Vec4(worldPos, 1.0);
|
|
|
- Vec2 ndc = v4.xy / v4.w;
|
|
|
-
|
|
|
- Vec2 oldUv = NDC_TO_UV(ndc);
|
|
|
- Vec3 history = textureLod(u_historyRt, oldUv, 0.0).rgb;
|
|
|
-
|
|
|
- // Compute the history blend. If clip falls outside NDC then it's 1.0 (use only current fog term) and if it's
|
|
|
- // inside NDC then use the HISTORY_FEEDBACK value
|
|
|
- Vec2 posNdc = abs(ndc);
|
|
|
- historyFeedback = max(posNdc.x, posNdc.y);
|
|
|
- historyFeedback = min(floor(historyFeedback), 1.0 - HISTORY_FEEDBACK);
|
|
|
- historyFeedback += HISTORY_FEEDBACK;
|
|
|
-
|
|
|
- return history;
|
|
|
-}
|
|
|
-
|
|
|
-void main()
|
|
|
-{
|
|
|
- F32 depth = textureLod(u_msDepthRt, in_uv, 0.0).r;
|
|
|
- Vec2 ndc = UV_TO_NDC(in_uv);
|
|
|
-
|
|
|
- // Compute some cluster stuff
|
|
|
- U32 i = U32(in_uv.x * F32(CLUSTER_COUNT.x));
|
|
|
- U32 j = U32(in_uv.y * F32(CLUSTER_COUNT.y));
|
|
|
- U32 ij = j * CLUSTER_COUNT.x + i;
|
|
|
-
|
|
|
- // Get a rand jitter distance
|
|
|
- Vec3 noiseTexUv = Vec3(Vec2(FB_SIZE) / Vec2(NOISE_MAP_SIZE) * in_uv + Vec2(0.0, u_noiseYOffset), u_noiseLayer);
|
|
|
- F32 randFactor = texture(u_noiseTex, noiseTexUv).r;
|
|
|
- F32 randDistance = JITTER_DISTANCE * randFactor;
|
|
|
-
|
|
|
- // Get world position
|
|
|
- Vec4 worldPos4 = u_invViewProjMat * Vec4(ndc, depth, 1.0);
|
|
|
- Vec3 worldPos = worldPos4.xyz / worldPos4.w;
|
|
|
-
|
|
|
- // Compute the distances from the camera
|
|
|
- F32 maxDistFromTheCamera = length(worldPos - u_cameraPos);
|
|
|
-
|
|
|
- worldPos4 = u_invViewProjMat * Vec4(ndc, EPSILON, 1.0);
|
|
|
- Vec3 nearWorldPos = worldPos4.xyz / worldPos4.w;
|
|
|
- F32 minDistFromTheCamera = length(nearWorldPos - u_cameraPos);
|
|
|
-
|
|
|
- // Ray march
|
|
|
- Vec3 crntColor = Vec3(0.0);
|
|
|
- const F32 FRACTION = 1.0 / F32(MAX_ITERATIONS - 1u);
|
|
|
- ANKI_LOOP for(F32 f = FRACTION; f < 1.0; f += FRACTION)
|
|
|
- {
|
|
|
- // Compute new world pos
|
|
|
- F32 f2 = f * f; // Higher detail closer to the camera
|
|
|
- F32 distFromTheCamera = (u_far - minDistFromTheCamera - JITTER_DISTANCE) * f;
|
|
|
- distFromTheCamera += minDistFromTheCamera + randDistance;
|
|
|
-
|
|
|
- if(distFromTheCamera >= maxDistFromTheCamera)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- Vec3 newWorldPos = u_cameraPos + normalize(worldPos - u_cameraPos) * distFromTheCamera;
|
|
|
-
|
|
|
- // Compute cluster idx
|
|
|
- U32 k = computeClusterK(u_clustererMagic, newWorldPos);
|
|
|
- U32 clusterIdx = k * (CLUSTER_COUNT.x * CLUSTER_COUNT.y) + ij;
|
|
|
- U32 lightIdxOffset = u_clusters[clusterIdx];
|
|
|
-
|
|
|
- // Do lighting
|
|
|
- crntColor += computeLightColor(newWorldPos, lightIdxOffset);
|
|
|
- }
|
|
|
-
|
|
|
- crntColor *= diffuseLambert(u_fogParticleColor);
|
|
|
-
|
|
|
- // Read history
|
|
|
- F32 historyFeedback;
|
|
|
- Vec3 history = readHistory(worldPos, historyFeedback);
|
|
|
-
|
|
|
- // Fix ghosting
|
|
|
- history = max(history, crntColor);
|
|
|
-
|
|
|
- // Blend
|
|
|
- out_color = mix(history, crntColor, historyFeedback);
|
|
|
-}
|
|
|
-#pragma anki end
|