377 lines
16 KiB
GLSL
377 lines
16 KiB
GLSL
#include "/lib/shaderSettings/cloudsAndLighting.glsl"
|
|
const float cloudStretchModified = max(0.25, float(CLOUD_STRETCH) * 1.9 - 0.9);
|
|
#if CLOUD_QUALITY_INTERNAL == 1 || !defined DEFERRED1
|
|
const float cloudStretchRaw = 11.0 * cloudStretchModified;
|
|
#elif CLOUD_QUALITY_INTERNAL == 2
|
|
const float cloudStretchRaw = 16.0 * cloudStretchModified;
|
|
#elif CLOUD_QUALITY_INTERNAL == 3
|
|
const float cloudStretchRaw = 18.0 * cloudStretchModified;
|
|
#elif CLOUD_QUALITY_INTERNAL == 4
|
|
const float cloudStretchRaw = 20.0 * cloudStretchModified;
|
|
#endif
|
|
|
|
#ifdef DOUBLE_UNBOUND_CLOUDS
|
|
const float L2cloudStretch = cloudStretchRaw * CLOUD_UNBOUND_LAYER2_HEIGHT / CLOUD_STRETCH;
|
|
|
|
#if CLOUD_UNBOUND_SIZE_MULT <= 100
|
|
float cloudStretch = cloudStretchRaw;
|
|
#else
|
|
float cloudStretch = cloudStretchRaw / float(CLOUD_UNBOUND_SIZE_MULT_M);
|
|
#endif
|
|
|
|
float cloudTallness = cloudStretch * 2.0;
|
|
#else
|
|
#if CLOUD_UNBOUND_SIZE_MULT <= 100
|
|
const float cloudStretch = cloudStretchRaw;
|
|
#else
|
|
const float cloudStretch = cloudStretchRaw / float(CLOUD_UNBOUND_SIZE_MULT_M);
|
|
#endif
|
|
const float cloudTallness = cloudStretch * 2.0;
|
|
#endif
|
|
|
|
#if CLOUD_QUALITY > 1
|
|
const float cloudNarrowness = 0.00012;
|
|
#else
|
|
const float cloudNarrowness = 0.00006;
|
|
#endif
|
|
|
|
|
|
float GetCloudNoise(vec3 tracePos, int cloudAltitude, float lTracePosXZ, float cloudPlayerPosY) {
|
|
vec3 tracePosM = tracePos.xyz * cloudNarrowness;
|
|
float wind = 0.0006;
|
|
float noise = 0.0;
|
|
float currentPersist = 1.0;
|
|
float total = 0.0;
|
|
|
|
#if CLOUD_SPEED_MULT == 100
|
|
#define CLOUD_SPEED_MULT_M CLOUD_SPEED_MULT * 0.01
|
|
wind *= syncedTime;
|
|
#else
|
|
#define CLOUD_SPEED_MULT_M CLOUD_SPEED_MULT * 0.01
|
|
wind *= frameTimeCounter * CLOUD_SPEED_MULT_M;
|
|
#endif
|
|
|
|
#if CLOUD_UNBOUND_SIZE_MULT != 100
|
|
tracePosM *= CLOUD_UNBOUND_SIZE_MULT_M;
|
|
wind *= CLOUD_UNBOUND_SIZE_MULT_M;
|
|
#endif
|
|
|
|
#ifdef DOUBLE_UNBOUND_CLOUDS
|
|
if (cloudAltitude != cloudAlt1i) {
|
|
tracePosM *= CLOUD_UNBOUND_LAYER2_SIZE * 10.0 / CLOUD_UNBOUND_SIZE_MULT;
|
|
wind *= CLOUD_UNBOUND_LAYER2_SIZE * 30.0 * CLOUD_LAYER2_SPEED_MULT / CLOUD_UNBOUND_SIZE_MULT;
|
|
}
|
|
#endif
|
|
|
|
#if CLOUD_QUALITY_INTERNAL == 1
|
|
int sampleCount = 2;
|
|
float persistance = 0.6;
|
|
float noiseMult = 0.95;
|
|
wind *= 0.5;
|
|
#elif CLOUD_QUALITY_INTERNAL == 2 || !defined DEFERRED1
|
|
int sampleCount = 4;
|
|
float persistance = 0.5;
|
|
float noiseMult = 1.14;
|
|
#elif CLOUD_QUALITY_INTERNAL == 3
|
|
int sampleCount = 4;
|
|
float persistance = 0.5;
|
|
float noiseMult = 1.0;
|
|
#elif CLOUD_QUALITY_INTERNAL == 4
|
|
int sampleCount = 5;
|
|
float persistance = 0.5;
|
|
float noiseMult = 1.05;
|
|
#endif
|
|
|
|
#ifndef DEFERRED1
|
|
noiseMult *= 1.2;
|
|
#endif
|
|
|
|
#if CLOUD_DIRECTION == 1
|
|
tracePosM.xz = tracePosM.zx;
|
|
#endif
|
|
|
|
for (int i = 0; i < sampleCount; i++) {
|
|
#if CLOUD_QUALITY_INTERNAL >= 2
|
|
noise += Noise3D(tracePosM - vec3(0.0, 0.0, wind)) * currentPersist;
|
|
#else
|
|
noise += texture2DLod(noisetex, tracePosM.xz - vec2(0.0, wind), 0.0).b * currentPersist;
|
|
#endif
|
|
total += currentPersist;
|
|
|
|
tracePosM *= 3.0;
|
|
wind *= 0.5;
|
|
currentPersist *= persistance;
|
|
}
|
|
noise = pow2(noise / total);
|
|
|
|
#define CLOUD_BASE_ADD 0.8
|
|
//#define CLOUD_FAR_ADD -0.005
|
|
#define CLOUD_ABOVE_ADD 0.1
|
|
|
|
float nightCloudRemove = NIGHT_CLOUD_UNBOUND_REMOVE * (1.0 - sunVisibility) * -0.65 + 1.0; // mapped to 1 to 0.65 range
|
|
|
|
float seasonCloudAdd = 0.0;
|
|
#if SEASONS > 0
|
|
float autumnOnlyForests = 1.0;
|
|
#ifdef AUTUMN_CONDITION
|
|
autumnOnlyForests = inForest;
|
|
#endif
|
|
float autumnWinterTime = autumnTime + winterTime;
|
|
#if SNOW_CONDITION != 2
|
|
autumnWinterTime *= mix(inSnowy + autumnOnlyForests, inSnowy, winterTime); // make only appear in cold biomes during winter
|
|
#endif
|
|
#if SNOW_CONDITION == 0
|
|
autumnWinterTime *= mix(rainFactor + autumnOnlyForests, rainFactor, winterTime); // make only appear in rain during winter
|
|
#endif
|
|
seasonCloudAdd += mix(0.0, 0.35, autumnWinterTime);
|
|
seasonCloudAdd += mix(0.0, -0.2, summerTime);
|
|
#endif
|
|
|
|
noiseMult *= CLOUD_BASE_ADD
|
|
//+ CLOUD_FAR_ADD * sqrt(lTracePosXZ + 10.0) // more/less clouds far away
|
|
+ CLOUD_ABOVE_ADD * clamp01(-cloudPlayerPosY / cloudTallness) // more clouds when camera is above them
|
|
+ CLOUD_UNBOUND_RAIN_ADD * rainFactor + seasonCloudAdd; // more clouds during rain and seasons
|
|
|
|
#ifdef DOUBLE_UNBOUND_CLOUDS
|
|
if (cloudAltitude != cloudAlt1i)
|
|
noise *= noiseMult * CLOUD_UNBOUND_LAYER2_AMOUNT * nightCloudRemove;
|
|
else
|
|
#endif
|
|
noise *= noiseMult * CLOUD_UNBOUND_AMOUNT * nightCloudRemove;
|
|
|
|
float threshold = clamp(abs(cloudAltitude - tracePos.y) / cloudStretch, 0.001, 0.999);
|
|
threshold = pow2(pow2(pow2(threshold)));
|
|
return noise - (threshold * 0.2 + 0.25);
|
|
}
|
|
|
|
vec4 GetVolumetricClouds(int cloudAltitude, float distanceThreshold, inout float cloudLinearDepth, float skyFade, float skyMult0, vec3 cameraPos, vec3 nPlayerPos, float lViewPosM, float VdotS, float VdotU, float dither, vec3 sunVec, vec3 viewPos) {
|
|
vec4 volumetricClouds = vec4(0.0);
|
|
|
|
#ifdef DOUBLE_UNBOUND_CLOUDS
|
|
float L1cloudStretch = cloudStretch;
|
|
|
|
if (cloudAltitude != cloudAlt1i) { // second layer
|
|
cloudStretch = L2cloudStretch;
|
|
cloudTallness = 2.0 * cloudStretch;
|
|
}
|
|
#endif
|
|
|
|
float higherPlaneAltitude = cloudAltitude + cloudStretch;
|
|
float lowerPlaneAltitude = cloudAltitude - cloudStretch;
|
|
|
|
float lowerPlaneDistance = (lowerPlaneAltitude - cameraPos.y) / nPlayerPos.y;
|
|
float higherPlaneDistance = (higherPlaneAltitude - cameraPos.y) / nPlayerPos.y;
|
|
float minPlaneDistance = min(lowerPlaneDistance, higherPlaneDistance);
|
|
minPlaneDistance = max(minPlaneDistance, 0.0);
|
|
float maxPlaneDistance = max(lowerPlaneDistance, higherPlaneDistance);
|
|
if (maxPlaneDistance < 0.0) return vec4(0.0);
|
|
float planeDistanceDif = maxPlaneDistance - minPlaneDistance;
|
|
|
|
#ifndef DEFERRED1
|
|
float stepMult = 64.0;
|
|
#elif CLOUD_QUALITY_INTERNAL == 1
|
|
float stepMult = 16.0;
|
|
#elif CLOUD_QUALITY_INTERNAL == 2
|
|
float stepMult = 32.0;
|
|
#elif CLOUD_QUALITY_INTERNAL == 3
|
|
float stepMult = 16.0;
|
|
#elif CLOUD_QUALITY_INTERNAL == 4
|
|
float stepMult = 24.0;
|
|
#endif
|
|
|
|
#if defined DOUBLE_UNBOUND_CLOUDS && (CLOUD_UNBOUND_LAYER2_SIZE > 10 || CLOUD_UNBOUND_SIZE_MULT > 100)
|
|
if (cloudAltitude != cloudAlt1i) {
|
|
#if CLOUD_UNBOUND_LAYER2_SIZE > 10
|
|
stepMult = stepMult / sqrt(CLOUD_UNBOUND_LAYER2_SIZE * 0.1);
|
|
#endif
|
|
} else {
|
|
#if CLOUD_UNBOUND_SIZE_MULT > 100
|
|
stepMult = stepMult / sqrt(float(CLOUD_UNBOUND_SIZE_MULT_M));
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
|
|
#if CLOUD_UNBOUND_SIZE_MULT > 100
|
|
stepMult = stepMult / sqrt(float(CLOUD_UNBOUND_SIZE_MULT_M));
|
|
#endif
|
|
|
|
#endif
|
|
|
|
int sampleCount = int(planeDistanceDif / stepMult + dither + 1);
|
|
vec3 traceAdd = nPlayerPos * stepMult;
|
|
vec3 tracePos = cameraPos + minPlaneDistance * nPlayerPos;
|
|
tracePos += traceAdd * dither;
|
|
tracePos.y -= traceAdd.y;
|
|
|
|
float firstHitPos = 0.0;
|
|
float VdotSM1 = max0(sunVisibility > 0.5 ? VdotS : - VdotS);
|
|
float VdotSM1M = VdotSM1 * invRainFactor;
|
|
float VdotSM2 = pow2(VdotSM1) * abs(sunVisibility - 0.5) * 2.0;
|
|
float VdotSM3 = VdotSM2 * (2.5 + rainFactor) + 1.5 * rainFactor;
|
|
float VdotSM4 = pow(VdotSM1M, 100.0) * sunVisibility;
|
|
|
|
#ifdef FIX_AMD_REFLECTION_CRASH
|
|
sampleCount = min(sampleCount, 30); //BFARC
|
|
#endif
|
|
|
|
#ifdef AURORA_INFLUENCE
|
|
cloudLightColor = getAuroraAmbientColor(cloudLightColor, viewPos, 0.06, AURORA_CLOUD_INFLUENCE_INTENSITY, 0.75);
|
|
cloudAmbientColor = getAuroraAmbientColor(cloudAmbientColor, viewPos, 0.03, AURORA_CLOUD_INFLUENCE_INTENSITY, 0.75);
|
|
#endif
|
|
|
|
for (int i = 0; i < sampleCount; i++) {
|
|
tracePos += traceAdd;
|
|
|
|
if (abs(tracePos.y - cloudAltitude) > cloudStretch) break;
|
|
|
|
vec3 cloudPlayerPos = tracePos - cameraPos;
|
|
float lTracePos = length(cloudPlayerPos);
|
|
float lTracePosXZ = length(cloudPlayerPos.xz);
|
|
float cloudMult = 1.0;
|
|
if (lTracePosXZ > distanceThreshold) break;
|
|
if (lTracePos > lViewPosM) {
|
|
if (skyFade < 0.7) continue;
|
|
else cloudMult = skyMult0;
|
|
}
|
|
|
|
float cloudNoise = GetCloudNoise(tracePos, cloudAltitude, lTracePosXZ, cloudPlayerPos.y);
|
|
|
|
if (cloudNoise > 0.00001) {
|
|
#if defined DOUBLE_UNBOUND_CLOUDS
|
|
//Fixes overlapping clouds
|
|
|
|
if (CLOUD_UNBOUND_LAYER2_HEIGHT > CLOUD_STRETCH){
|
|
if (cloudAltitude == cloudAlt1i) {
|
|
if (abs(tracePos.y - cloudAlt2i) < L2cloudStretch)
|
|
continue;
|
|
}
|
|
} else {
|
|
if (cloudAltitude != cloudAlt1i) {
|
|
if (abs(tracePos.y - cloudAlt1i) < L1cloudStretch)
|
|
continue;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined CLOUD_CLOSED_AREA_CHECK && SHADOW_QUALITY > -1
|
|
float shadowLength = shadowDistance * 0.9166667; //consistent08JJ622
|
|
if (shadowLength < lTracePos)
|
|
if (GetShadowOnCloud(tracePos, cameraPos, cloudAltitude, lowerPlaneAltitude, higherPlaneAltitude)) {
|
|
if (eyeBrightness.y != 240) continue;
|
|
}
|
|
#endif
|
|
|
|
if (firstHitPos < 1.0) {
|
|
firstHitPos = lTracePos;
|
|
#if CLOUD_QUALITY_INTERNAL == 1 && defined DEFERRED1
|
|
tracePos.y += 4.0 * (texture2DLod(noisetex, tracePos.xz * cloudNarrowness * 16.0, 0.0).r - 0.5);
|
|
#endif
|
|
}
|
|
|
|
#if defined DOUBLE_UNBOUND_CLOUDS && CLOUD_UNBOUND_LAYER2_TRANSPARENCY != 20
|
|
float opacityFactor = cloudAltitude != cloudAlt1i
|
|
? min1(cloudNoise * 8.0) * (CLOUD_UNBOUND_LAYER2_TRANSPARENCY * 0.05)
|
|
: min1(cloudNoise * 8.0) * CLOUD_TRANSPARENCY;
|
|
#else
|
|
float opacityFactor = min1(cloudNoise * 8.0) * CLOUD_TRANSPARENCY;
|
|
#endif
|
|
|
|
#ifdef INVERTED_CLOUD_SHADING
|
|
float cloudShading = (higherPlaneAltitude - tracePos.y) / cloudTallness;
|
|
#else
|
|
float cloudShading = 1.0 - (higherPlaneAltitude - tracePos.y) / cloudTallness;
|
|
#endif
|
|
|
|
cloudShading *= 1.0 + 0.2 * VdotSM3 * (1.0 - opacityFactor) + VdotSM4;
|
|
#if CLOUD_SHADING_AMOUNT != 10
|
|
cloudShading = pow(max0(cloudShading), CLOUD_SHADING_AMOUNT * 0.1);
|
|
#endif
|
|
|
|
#ifdef AURORA_INFLUENCE
|
|
cloudLightColor = getAuroraAmbientColor(cloudLightColor, viewPos, 0.1, AURORA_CLOUD_INFLUENCE_INTENSITY, 0.75);
|
|
#endif
|
|
|
|
#if CLOUD_SUN_MOON_SHADING > 0
|
|
float visibilityFactor = 1.0;
|
|
#if CLOUD_SUN_MOON_SHADING == 1
|
|
visibilityFactor = 1.0 - sunVisibility;
|
|
#elif CLOUD_SUN_MOON_SHADING == 2
|
|
visibilityFactor = sunVisibility;
|
|
#endif
|
|
|
|
if (visibilityFactor > 0.0) {
|
|
vec3 worldLightVec = mat3(gbufferModelViewInverse) * sunVec;
|
|
float cloudLightRadius = 375.0;
|
|
|
|
float aboveFade = clamp01(1.0 - (cameraPos.y - cloudAltitude) / (cloudTallness * 3.0));
|
|
float radiusFactor = mix(cloudLightRadius * 8.0, cloudLightRadius, aboveFade);
|
|
float moonVisibility = abs(1.0 - moonPhase / 4.0);
|
|
float sunMult = mix(moonVisibility, 0.85, sunVisibility);
|
|
|
|
float sunPlaneIntersect = (cloudAltitude - cameraPos.y) / worldLightVec.y;
|
|
vec2 posVector = cameraPos.xz + worldLightVec.xz * sunPlaneIntersect - tracePos.xz;
|
|
float falloff = exp((1.0 - max0(1.0 - length(posVector) / radiusFactor)) * -6.0) * aboveFade * sunMult;
|
|
|
|
float sunShadingFactor = clamp01(falloff * mix(1.0, 2.0, aboveFade) * mix(1.0, (lTracePos - minPlaneDistance) / (maxPlaneDistance - minPlaneDistance), 0.75));
|
|
|
|
vec3 bloodMoonCloudColor = vec3(1.0);
|
|
#if BLOOD_MOON > 0
|
|
bloodMoonCloudColor = mix(bloodMoonCloudColor, vec3(0.302, 0.0078, 0.0078) * 5, getBloodMoon(sunVisibility));
|
|
#endif
|
|
|
|
cloudLightColor += bloodMoonCloudColor * sunShadingFactor * 0.3 * visibilityFactor;
|
|
cloudShading += sunShadingFactor * 0.45 * visibilityFactor;
|
|
}
|
|
#endif
|
|
|
|
#if BLOOD_MOON > 0
|
|
vec3 hsvCloudLightColor = rgb2hsv(cloudLightColor);
|
|
cloudLightColor = mix(cloudLightColor, hsv2rgb(vec3(0, max(0.66, hsvCloudLightColor.y), hsvCloudLightColor.z)), getBloodMoon(sunVisibility));
|
|
#endif
|
|
|
|
vec3 colorSample = cloudAmbientColor * (0.4 + 0.6 * cloudShading) + cloudLightColor * cloudShading;
|
|
//vec3 colorSample = 2.5 * cloudLightColor * pow2(cloudShading); // <-- Used this to take the Unbound logo
|
|
|
|
#ifdef RAIN_ATMOSPHERE
|
|
// Lightning flashes around lightning bolt position
|
|
vec3 lightningPos = getLightningPos(tracePos - cameraPos, lightningBoltPosition.xyz, false);
|
|
vec2 lightningAdd = lightningFlashEffect(lightningPos, vec3(1.0), 550.0, 0.0, 0) * isLightningActive() * 10.0;
|
|
colorSample += lightningAdd.y;
|
|
|
|
// Thunderstorm cloud highlights (randomly appear in stormy weather)
|
|
float highlightBoost = getThunderstormCloudHighlights(tracePos, cameraPos.xz, lTracePos, minPlaneDistance, maxPlaneDistance, 0.004);
|
|
colorSample += highlightBoost;
|
|
#endif
|
|
|
|
vec3 cloudSkyColor = GetSky(VdotU, VdotS, dither, isEyeInWater == 0, false);
|
|
#ifdef ATM_COLOR_MULTS
|
|
cloudSkyColor *= sqrtAtmColorMult; // C72380KD - Reduced atmColorMult impact on some things
|
|
#endif
|
|
float distanceRatio = (distanceThreshold - lTracePosXZ) / distanceThreshold;
|
|
float cloudDistanceFactor = clamp(distanceRatio, 0.0, 0.8) * 1.25;
|
|
float cloudFogFactor = pow2(pow1_5(clamp(distanceRatio, 0.0, 1.0)));
|
|
float skyMult1 = 1.0 - 0.2 * (1.0 - skyFade) * max(sunVisibility2, nightFactor);
|
|
float skyMult2 = 1.0 - 0.33333 * skyFade;
|
|
colorSample = mix(cloudSkyColor, colorSample * skyMult1, cloudFogFactor * skyMult2 * 0.72);
|
|
colorSample *= pow2(1.0 - maxBlindnessDarkness);
|
|
|
|
volumetricClouds.rgb = mix(volumetricClouds.rgb, colorSample, 1.0 - min1(volumetricClouds.a));
|
|
volumetricClouds.a += opacityFactor * pow(cloudDistanceFactor, 0.5 + 10.0 * pow(abs(VdotSM1M), 90.0)) * cloudMult;
|
|
|
|
if (volumetricClouds.a > 0.9) {
|
|
volumetricClouds.a = 1.0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef DOUBLE_UNBOUND_CLOUDS
|
|
if (volumetricClouds.a > 0.5)
|
|
#endif
|
|
{ cloudLinearDepth = sqrt(firstHitPos / renderDistance); }
|
|
|
|
return volumetricClouds;
|
|
}
|