// Copyright © 2026 Gaijin Entertainment // // Free to use, copy, modify and share, including for personal use and monetized streams, videos and other online content. // // The shader itself (including modified versions) may not be sold, sublicensed or commercially distributed as a standalone product. // // No rights to Gaijin trademarks, game titles, artwork or other IP are granted. Provided "as is", without warranty. const float SEED = 0.0; const float PI = 3.14159265358979; vec4 kal_march(vec3 rayDir, mat2 worldRot, float marchTime) { vec4 accumulated = vec4(0.0, 0.0, 0.0, 0.0); vec3 rayPos = vec3(0.0, 0.0, 0.0); float rayDist = 0.0, stepSize = 0.0; for (float i = 1.0; i <= 30.0; i += 1.0) { rayPos = rayDir * rayDist; rayPos.z -= 10.0; vec2 rotatedXZ = worldRot * vec2(rayPos.x, rayPos.z); rayPos.x = rotatedXZ.x; rayPos.z = rotatedXZ.y; for (stepSize = 0.04; stepSize < 3.0; stepSize += stepSize) { rayPos += cos(2.0 * marchTime + rayPos.yzx / 10.0) * 0.6; rayPos -= abs(dot(sin(0.03 * rayPos.z + marchTime + rayPos / stepSize / 3.2), vec3(stepSize, stepSize, stepSize))); } rayPos.xy /= 4.0; stepSize = 0.08 + 0.5 * abs(length(rayPos) - 30.0); rayDist += stepSize; accumulated += vec4(3.9, 2.0, 1.0, 0.0) / stepSize * rayDist + 10.0 * (1.0 + cos(i * 0.4 + vec4(2.0, 1.0, 0.0, 0.0))) / stepSize; } return accumulated; } void mainImage(out vec4 fragColor, in vec2 fragCoord) { vec2 pos = vec2(fragCoord.x, iResolution.y - fragCoord.y); vec2 resolution = iResolution.xy; float time = iTime; vec2 uv = (pos.xy * 2.0 - resolution) / resolution.y; float stepDuration = 4.0; float firstStepDuration = 15.0; float animDuration = 0.5; float rotPerStep = PI / 3.0; bool inFirstStep = time < firstStepDuration; float stepIndex = inFirstStep ? 0.0 : (1.0 + floor((time - firstStepDuration) / stepDuration)); float localTime = inFirstStep ? time : fract((time - firstStepDuration) / stepDuration) * stepDuration; float currentStepDur = inFirstStep ? firstStepDuration : stepDuration; float animProgress = clamp((localTime - (currentStepDur - animDuration)) / animDuration, 0.0, 1.0); float easedProgress = animProgress * animProgress * animProgress; float rotationPhase = sin(animProgress * PI); float mirrorAngle = mix(stepIndex * rotPerStep, (stepIndex + 1.0) * rotPerStep, easedProgress); float segments = 3.0; float radius = length(uv); float period = 2.0 * PI / segments; float foldAngle = atan(uv.y, uv.x) + PI * 0.5 + mirrorAngle; foldAngle = mod(foldAngle, period); foldAngle = abs(foldAngle - period * 0.5); uv = radius * vec2(cos(foldAngle - mirrorAngle * 2.0), sin(foldAngle - mirrorAngle * 2.0)); uv *= mix(1.0, 1.25, rotationPhase); float slowTime = time / 20.0 + SEED; vec4 rotCos = cos(slowTime + vec4(0.0, 33.0, 11.0, 0.0)); mat2 worldRot = mat2(rotCos.x, rotCos.y, rotCos.z, rotCos.w); float brightness = 1.5; float flashDuration = 0.4; float flashFade = 1.0 - smoothstep(0.0, flashDuration, localTime); float aberration = mix(0.003, 0.02, flashFade); float marchTime = time / 4.0 + SEED; float cloudScale = 0.45; float fov = 0.8; vec2 uvScaled = uv * cloudScale; vec4 sampleR = kal_march(normalize(vec3(uvScaled + vec2(0.0, aberration), fov)), worldRot, marchTime); vec4 sampleGB = kal_march(normalize(vec3(uvScaled, fov)), worldRot, marchTime); vec4 color = vec4(sampleR.r, sampleGB.g, sampleGB.b, 1.0); vec3 edgeHue = vec3(0.0, 1.0, 0.65); float edgeStrength = 0.7; float edgeBlend = clamp(smoothstep(0.0, 0.6, length(uv) / 2.0) * edgeStrength, 0.0, 1.0); vec4 edgeColor = vec4(color.b * edgeHue.r, color.g * edgeHue.g, color.r * edgeHue.b, 1.0); color = mix(color, edgeColor, edgeBlend); color = tanh(color * color / 9e8); vec3 shadowLift = vec3(0.02, 0.01, 0.0); color.rgb = color.rgb + shadowLift * (1.0 - color.rgb); float startFade = smoothstep(0.0, 3.0, time); float vigInnerRadius = mix(0.4, 0.1, rotationPhase); float vigOuterRadius = mix(1.8, 1.3, rotationPhase); float vignetteMask = 1.0 - smoothstep(vigInnerRadius, vigOuterRadius, radius); color *= vignetteMask; color *= brightness; color *= 1.0 + flashFade; color *= startFade; vec3 radiance = color.rgb; vec4 load = vec4(radiance, 1.0); fragColor = load; }