feat: initial commit

This commit is contained in:
lucasdpt
2026-06-14 01:24:29 +02:00
commit 0d40f88ab2
5815 changed files with 703860 additions and 0 deletions
@@ -0,0 +1,267 @@
#if !defined AURORA_BOREALIS_GLSL
#define AURORA_BOREALIS_GLSL
#ifdef ATM_COLOR_MULTS
#include "/lib/colors/colorMultipliers.glsl"
#endif
#include "/lib/util/colorConversion.glsl"
#define AURORA_CONDITION 3 //[-1 0 1 2 3 4]
#define AURORA_COLOR_PRESET 0 //[-1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14] // 0 is manual and default, 1 is daily, 2 is monthly and 3 is one color preset same with all numbers after
#define AURORA_UP_R 112 //[0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120 124 128 132 136 140 144 148 152 156 160 164 168 172 176 180 184 188 192 196 200 204 208 212 216 220 224 228 232 236 240 244 248 252 255]
#define AURORA_UP_G 36 //[0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120 124 128 132 136 140 144 148 152 156 160 164 168 172 176 180 184 188 192 196 200 204 208 212 216 220 224 228 232 236 240 244 248 252 255]
#define AURORA_UP_B 192 //[0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120 124 128 132 136 140 144 148 152 156 160 164 168 172 176 180 184 188 192 196 200 204 208 212 216 220 224 228 232 236 240 244 248 252 255]
#define AURORA_UP_I 33 //[0 3 5 8 10 13 15 18 20 23 25 28 30 33 35 38 40 43 45 48 50 53 55 58 60 63 65 68 70 73 75 78 80 83 85 88 90 93 95 98 100]
#define AURORA_DOWN_R 96 //[0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120 124 128 132 136 140 144 148 152 156 160 164 168 172 176 180 184 188 192 196 200 204 208 212 216 220 224 228 232 236 240 244 248 252 255]
#define AURORA_DOWN_G 255 //[0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120 124 128 132 136 140 144 148 152 156 160 164 168 172 176 180 184 188 192 196 200 204 208 212 216 220 224 228 232 236 240 244 248 252 255]
#define AURORA_DOWN_B 192 //[0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120 124 128 132 136 140 144 148 152 156 160 164 168 172 176 180 184 188 192 196 200 204 208 212 216 220 224 228 232 236 240 244 248 252 255]
#define AURORA_DOWN_I 33 //[0 3 5 8 10 13 15 18 20 23 25 28 30 33 35 38 40 43 45 48 50 53 55 58 60 63 65 68 70 73 75 78 80 83 85 88 90 93 95 98 100]
#define AURORA_SIZE 1.00 //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 2.05 2.10 2.15 2.20 2.25 2.30 2.35 2.40 2.45 2.50 2.55 2.60 2.65 2.70 2.75 2.80 2.85 2.90 2.95 3.00]
#define AURORA_DRAW_DISTANCE 0.65 //[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00]
#define RANDOM_AURORA 0 //[0 1 2 3 4 5 6 7 8 9]
//#define RGB_AURORA
#define AURORA_CLOUD_INFLUENCE_INTENSITY 1.00 //[0.00 0.25 0.50 0.75 1.00 1.25 1.50 1.75 2.00 2.50 3.00]
#define AURORA_TERRAIN_INFLUENCE_INTENSITY 1.00 //[0.00 0.25 0.50 0.75 1.00 1.25 1.50]
#define AURORA_NOISE_SCALE 1.00 //[0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 2.05 2.10 2.15 2.20 2.25 2.30 2.35 2.40 2.45 2.50 2.55 2.60 2.65 2.70 2.75 2.80 2.85 2.90 2.95 3.00 3.05 3.10 3.15 3.20 3.25 3.30 3.35 3.40 3.45 3.50 3.55 3.60 3.65 3.70 3.75 3.80 3.85 3.90 3.95 4.00 4.05 4.10 4.15 4.20 4.25 4.30 4.35 4.40 4.45 4.50 4.55 4.60 4.65 4.70 4.75 4.80 4.85 4.90 4.95 5.00]
#define AURORA_PATTERN_WARP 0 //[0 1 2 3 4 5 6 7 8 9 10]
#define AURORA_SATURATION 10 //[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
#define AURORA_COLOR_MIX_POWER 2.0 //[0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0]
float GetAuroraVisibility(in float VdotU, float VdotUAmount) {
float visibility = sqrt1(clamp01(mix(1.0, VdotU, VdotUAmount) * (AURORA_DRAW_DISTANCE * 1.125 + 0.75) - 0.225)) - sunVisibility - maxBlindnessDarkness;
#ifdef CLEAR_SKY_WHEN_RAINING
visibility -= rainFactor * 0.5;
#else
visibility -= rainFactor;
#endif
visibility *= 1.0 - VdotU * 0.9 * VdotUAmount;
#if AURORA_CONDITION == 1 || AURORA_CONDITION == 3
visibility -= moonPhase;
#endif
#if AURORA_CONDITION == 2 || AURORA_CONDITION == 3
visibility *= inSnowy;
#endif
#if AURORA_CONDITION == 4
visibility = max(visibility * inSnowy, visibility - moonPhase);
#endif
#if AURORA_CONDITION == -1 // Always except new moon
visibility *= clamp01(max(moonPhase, 1) % 4);
#endif
#if RANDOM_AURORA > 0
float randomValue = hash11(float(worldDay));
if (randomValue > RANDOM_AURORA * 0.1) {
visibility = -1.0; // Disable aurora this day
}
#endif
return visibility;
}
vec3 auroraUpA[] = vec3[](
vec3(112.0, 36.0, 192.0), // [1] [2] Complementary
vec3(112.0, 80.0, 255.0), // [3] Legacy Complementary (v4)
vec3(168.0, 36.0, 88.0), // [4] permafrost
vec3(255.0, 68.0, 124.0), // [5] Blossoming Lights (Pink)
vec3(72.0, 96.0, 192.0), // [6] Nebula
vec3(24.0, 255.0, 140.0), // [7] Celestial Dance
vec3(255.0, 220.0, 255.0), // [8] Green Flash
vec3(64.0, 255.0, 255.0), // [9] Ethereal Lights
vec3(0.0, 20.0, 60.0), // [10] Glacial Blessing
vec3(132.0, 0.0, 200.0), // [11] Mythical Lights
vec3(120.0, 212.0, 56.0), // [12] watermelon
vec3(0.0, 255.0, 255.0), // [13] blood bath
vec3(255.0, 80.0, 112.0) // [14] Ghost
);
vec3 auroraDownA[] = vec3[](
vec3(96.0, 255.0, 192.0), // [1] [2] Complementary
vec3(80.0, 255.0, 180.0), // [3] Legacy Complementary (v4)
vec3(60.0, 184.0, 152.0), // [4] permafrost
vec3(160.0, 96.0, 255.0), // [5] Blossoming Lights (Pink)
vec3(172.0, 44.0, 88.0), // [6] Nebula
vec3(108.0, 72.0, 255.0), // [7] Celestial Dance
vec3(68.0, 255.0, 72.0), // [8] Green Flash
vec3(128.0, 64.0, 128.0), // [9] Ethereal Lights
vec3(0.0, 24.0, 36.0), // [10] Glacial Blessing
vec3(56.0, 168.0, 255.0), // [11] Mythical Lights
vec3(176.0, 88.0, 72.0), // [12] watermelon
vec3(180.0, 0.0, 0.0), // [13] blood bath
vec3(80.0, 255.0, 180.0) // [14] Ghost
);
vec2 warpAuroraCoords(vec2 coord, float warpAmount) {
float angle = texture2D(noisetex, coord * 0.5).r * 6.28318 * warpAmount;
float strength = texture2D(noisetex, coord * 0.7 + 0.5).r * warpAmount;
vec2 offset = vec2(cos(angle), sin(angle)) * strength;
return coord + offset;
}
void GetAuroraColor(in vec2 wpos, out vec3 auroraUp, out vec3 auroraDown) {
#ifdef RGB_AURORA
auroraUp = getRainbowColor(wpos, 0.06);
auroraDown = getRainbowColor(wpos, 0.05);
#elif AURORA_COLOR_PRESET == 0
auroraUp = vec3(AURORA_UP_R, AURORA_UP_G, AURORA_UP_B);
auroraDown = vec3(AURORA_DOWN_R, AURORA_DOWN_G, AURORA_DOWN_B);
#elif AURORA_COLOR_PRESET == -1
float randomValue = hash11(float(worldDay));
randomValue = pow(randomValue, 0.7); // Bias towards higher values (more transitions)
float transitionsPerNight = min(randomValue * 2.0, 1.75);
float idx, frac = modf(nightFactor * transitionsPerNight, idx);
int dayOffset = worldDay % auroraUpA.length();
int colorsCount = auroraUpA.length();
int i0 = (int(idx) + dayOffset) % colorsCount;
int i1 = (i0 + 1) % colorsCount;
// Interpolate in OKLab color space for perceptually uniform transitions
vec3 oklabUp0 = rgb2oklab(auroraUpA[i0] / 255.0);
vec3 oklabUp1 = rgb2oklab(auroraUpA[i1] / 255.0);
vec3 oklabDown0 = rgb2oklab(auroraDownA[i0] / 255.0);
vec3 oklabDown1 = rgb2oklab(auroraDownA[i1] / 255.0);
auroraUp = oklab2rgb(mix(oklabUp0, oklabUp1, frac)) * 255.0;
auroraDown = oklab2rgb(mix(oklabDown0, oklabDown1, frac)) * 255.0;
#else
#if AURORA_COLOR_PRESET == 1
int p = worldDay % auroraUpA.length();
#elif AURORA_COLOR_PRESET == 2
int p = worldDay % (auroraUpA.length() * 8) / 8;
#else
const int p = AURORA_COLOR_PRESET - 2;
#endif
auroraUp = auroraUpA[p];
auroraDown = auroraDownA[p];
#endif
auroraUp = max(auroraUp, vec3(0.001));
auroraDown = max(auroraDown, vec3(0.001));
auroraUp *= (AURORA_UP_I * 0.093 + 3.1) / GetLuminance(auroraUp);
auroraDown *= (AURORA_DOWN_I * 0.245 + 8.15) / GetLuminance(auroraDown);
#if AURORA_SATURATION != 10
auroraUp = rgb2hsv(auroraUp);
auroraUp.g *= AURORA_SATURATION * 0.1;
auroraUp = hsv2rgb(auroraUp);
auroraDown = rgb2hsv(auroraDown);
auroraDown.g *= AURORA_SATURATION * 0.1;
auroraDown = hsv2rgb(auroraDown);
#endif
}
vec3 getAuroraAmbientColor(vec3 color, vec3 viewPos, float multiplier, float influence, float VdotUAmount) {
float visibility = GetAuroraVisibility(0.5, VdotUAmount);
if (visibility > 0) {
vec3 wpos = (gbufferModelViewInverse * vec4(viewPos, 1.0)).xyz;
wpos.xz /= (abs(wpos.y) + length(wpos.xz));
vec3 auroraUp, auroraDown;
GetAuroraColor(wpos.xz, auroraUp, auroraDown);
vec3 auroraColor = mix(auroraUp, auroraDown, 0.8);
#ifdef COMPOSITE1
visibility *= influence;
return mix(color, auroraColor, visibility);
#endif
auroraColor *= multiplier;
visibility *= influence;
#ifdef DEFERRED1
return mix(color, saturateColors(auroraColor, 0.8) * visibility * 0.45, visibility);
#endif
float luminanceColor = GetLuminance(color);
vec3 newColor = mix(color, mix(color, vec3(luminanceColor), 0.88), visibility);
newColor *= mix(vec3(1.0), auroraColor * luminanceColor * 10.0, visibility);
return clamp01(newColor);
// return mix(color, color * auroraColor, visibility); // old, keep it for now
}
return color;
}
vec3 GetAuroraBorealis(vec3 viewPos, float VdotU, float dither) {
float visibility = GetAuroraVisibility(VdotU, 1.0);
if (visibility > 0.0) {
vec3 aurora = vec3(0.0);
vec3 wpos = mat3(gbufferModelViewInverse) * viewPos;
wpos.xz /= wpos.y;
vec2 cameraPositionM = cameraPosition.xz * 0.0075;
cameraPositionM.x += syncedTime * 0.04;
#ifdef DEFERRED1
int sampleCount = 25;
int sampleCountP = sampleCount + 5;
#else
int sampleCount = 10;
int sampleCountP = sampleCount + 10;
#endif
float ditherM = dither + 5.0;
float auroraAnimate = frameTimeCounter * 0.001;
vec3 auroraUp, auroraDown;
GetAuroraColor(wpos.xz, auroraUp, auroraDown);
for (int i = 0; i < sampleCount; i++) {
float current = pow2((i + ditherM) / sampleCountP);
vec2 planePos = wpos.xz * (AURORA_SIZE * 0.8 + current) * 11.0 * AURORA_NOISE_SCALE + cameraPositionM;
#if AURORA_STYLE == 1
planePos = floor(planePos) * 0.0007;
#if AURORA_PATTERN_WARP > 0
planePos = warpAuroraCoords(planePos, AURORA_PATTERN_WARP * 0.0057);
#endif
float noise = texture2DLod(noisetex, planePos, 0.0).b;
noise = pow2(pow2(pow2(pow2(1.0 - 2.0 * abs(noise - 0.5)))));
noise *= pow1_5(texture2DLod(noisetex, planePos * 100.0 + auroraAnimate, 0.0).b);
#else
planePos *= 0.0007;
#if AURORA_PATTERN_WARP > 0
planePos = warpAuroraCoords(planePos, AURORA_PATTERN_WARP * 0.0082);
#endif
float noise = texture2DLod(noisetex, planePos, 0.0).r;
noise = pow2(pow2(pow2(pow2(1.0 - 2.0 * abs(noise - 0.5)))));
noise *= texture2DLod(noisetex, planePos * 3.0 + auroraAnimate, 0.0).b;
noise *= texture2DLod(noisetex, planePos * 5.0 - auroraAnimate, 0.0).b;
#endif
float currentM = 1.0 - current;
aurora += noise * currentM * mix(auroraUp, auroraDown, pow(pow2(currentM), AURORA_COLOR_MIX_POWER));
}
#if AURORA_STYLE == 1
aurora *= 1.3;
#else
aurora *= 1.8;
#endif
#ifdef ATM_COLOR_MULTS
aurora *= sqrtAtmColorMult; // C72380KD - Reduced atmColorMult impact on some things
#endif
return aurora * visibility / sampleCount;
}
return vec3(0.0);
}
#endif
@@ -0,0 +1,68 @@
vec3 GetBedrockNoise(vec3 viewPos, float VdotU, float dither) {
float eyeAltitude1 = eyeAltitude * 0.005;
float visibility = clamp01(-VdotU * 1.875 - 0.225) * (1.0 - maxBlindnessDarkness);
visibility *= 1.0 + VdotU * 0.75;
float distanceAboveBedrock = bedrockLevel - eyeAltitude;
float fadeStart = 180.0;
float fadeWidth = 50.0;
float noiseHeight = 2.0 / (1.0 + exp(-(fadeStart - distanceAboveBedrock) / fadeWidth));
visibility *= -eyeAltitude1 * 3.0 + (bedrockLevel / 66.6) + 2.0;
if (visibility >= 0.0) {
vec3 wpos = (gbufferModelViewInverse * vec4(viewPos, 1.0)).xyz;
wpos /= (abs(wpos.y) + length(wpos.xz) * 0.5);
vec2 cameraPositionM = cameraPosition.xz * 0.0075;
cameraPositionM.x += frameTimeCounter * 0.004;
float VdotUM = 1.0 - VdotU * VdotU;
// Star calculation
vec2 starCoord = noiseHeight * wpos.xz * 0.2 + cameraPositionM * 0.1;
starCoord = floor(starCoord * 1024.0) / 1024.0;
float star = GetStarNoise(starCoord.xy) *
GetStarNoise(starCoord.xy+0.1) *
GetStarNoise(starCoord.xy+0.23);
star = max0((star - 0.4) * 6.0);
star *= star;
vec3 stars = star * vec3(0.1765, 0.1569, 0.1804) * (VdotUM + 0.3);
float wind = fract(frameTimeCounter * 0.0125);
const int sampleCount = 1;
const int sampleCountP = sampleCount + 5;
float ditherM = dither + 5.0;
vec3 spots = vec3(0.0);
for (int i = 0; i < sampleCount; i++) {
float current = pow2((i + ditherM) / sampleCountP);
float currentM = 1.0 - current;
vec2 planePos = wpos.xz * (0.5 + current) * noiseHeight;
planePos = (planePos * 0.5 + cameraPositionM * 0.5) * 20.0;
float noiseSpots = texture2DLod(noisetex, floor(planePos) * 0.1, 0.0).g;
vec3 noise = texture2DLod(noisetex, vec2(noiseSpots) + wind * 0.3, 0.0).b * vec3(0.3);
spots += noise * currentM * 6.0;
}
#ifdef OVERWORLD
spots = (spots - 0.5) * 1.5 + 0.5; // contrast
#else
spots = (spots - 0.5) * 3.5 + 0.5; // contrast
#endif
spots += stars;
float clampedNoiseHeight = clamp01(noiseHeight);
return spots * visibility / sampleCount * clampedNoiseHeight + clampedNoiseHeight - 1.0;
}
return vec3(0.0);
}
@@ -0,0 +1,46 @@
#ifndef INCLUDE_CLOUD_COORD
#define INCLUDE_CLOUD_COORD
#include "/lib/shaderSettings/clouds.glsl"
const float cloudNarrowness = CLOUD_NARROWNESS;
// Thanks to SixthSurge
vec2 GetRoundedCloudCoord(vec2 pos, float cloudRoundness) { // cloudRoundness is meant to be 0.125 for clouds and 0.35 for cloud shadows
vec2 coord = pos.yx + 0.5;
#ifdef ROTATE_REIMAGINED_CLOUDS_90_NEW
coord = coord.yx;
#endif
vec2 signCoord = sign(coord);
coord = abs(coord) + 1.0;
vec2 i, f = modf(coord, i);
f = smoothstep(0.5 - cloudRoundness, 0.5 + cloudRoundness, f);
coord = i + f;
return (coord - 0.5) * signCoord / 256.0;
}
vec3 ModifyTracePos(vec3 tracePos, int cloudAltitude) {
#if CLOUD_SPEED_MULT == 100
float wind = syncedTime;
#else
#define CLOUD_SPEED_MULT_M CLOUD_SPEED_MULT * 0.01
float wind = frameTimeCounter * CLOUD_SPEED_MULT_M;
#endif
if (cloudAltitude != cloudAlt1i) {
wind *= CLOUD_LAYER2_SPEED_MULT;
}
#if CLOUD_DIRECTION == 1
tracePos.x -= wind;
tracePos.z += cloudAltitude * 64.0;
#else
tracePos.z -= wind;
tracePos.x += cloudAltitude * 64.0;
#endif
tracePos.xz *= cloudNarrowness;
return tracePos.xyz;
}
#endif
@@ -0,0 +1,198 @@
#include "/lib/shaderSettings/clouds.glsl"
#if CLOUD_UNBOUND_SIZE_MULT != 100
#define CLOUD_UNBOUND_SIZE_MULT_M CLOUD_UNBOUND_SIZE_MULT * 0.01
#endif
#include "/lib/colors/lightAndAmbientColors.glsl"
#include "/lib/colors/cloudColors.glsl"
#include "/lib/atmospherics/sky.glsl"
float InterleavedGradientNoiseForClouds() {
float n = 52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y);
#ifdef TAA
return fract(n + goldenRatio * mod(float(frameCounter), 3600.0));
#else
return fract(n);
#endif
}
#if SHADOW_QUALITY > -1
vec3 GetShadowOnCloudPosition(vec3 tracePos, vec3 cameraPos) {
vec3 wpos = PlayerToShadow(tracePos - cameraPos);
float distb = sqrt(wpos.x * wpos.x + wpos.y * wpos.y);
float distortFactor = 1.0 - shadowMapBias + distb * shadowMapBias;
vec3 shadowPosition = vec3(vec2(wpos.xy / distortFactor), wpos.z * 0.2);
return shadowPosition * 0.5 + 0.5;
}
bool GetShadowOnCloud(vec3 tracePos, vec3 cameraPos, int cloudAltitude, float lowerPlaneAltitude, float higherPlaneAltitude) {
const float cloudShadowOffset = 0.5;
vec3 shadowPosition0 = GetShadowOnCloudPosition(tracePos, cameraPos);
if (length(shadowPosition0.xy * 2.0 - 1.0) < 1.0) {
float shadowsample0 = shadow2D(shadowtex0, shadowPosition0).z;
if (shadowsample0 == 0.0) return true;
}
return false;
}
#endif
#ifdef CLOUDS_REIMAGINED
#include "/lib/atmospherics/clouds/reimaginedClouds.glsl"
#endif
#ifdef CLOUDS_UNBOUND
#include "/lib/atmospherics/clouds/unboundClouds.glsl"
#endif
vec4 GetClouds(inout float cloudLinearDepth, float skyFade, vec3 cameraPosOffset, vec3 playerPos, vec3 viewPos,
float lViewPos, float VdotS, float VdotU, float dither, vec3 auroraBorealis, vec3 nightNebula, vec3 sunVec) {
vec4 clouds = vec4(0.0);
vec3 nPlayerPos = normalize(playerPos);
float lViewPosM = lViewPos < renderDistance * 1.5 ? lViewPos - 1.0 : 1000000000.0;
float skyMult0 = pow2(skyFade * 3.333333 - 2.333333);
#if IRIS_VERSION >= 10800
#ifdef CLOUDS_REIMAGINED
float modFactor = 1.0 / cloudNarrowness * 256.0;
#else
#if CLOUD_UNBOUND_SIZE_MULT == 100
float modFactor = 1.0 / cloudNarrowness;
#else
float modFactor = 1.0 / (cloudNarrowness * CLOUD_UNBOUND_SIZE_MULT_M);
#endif
#endif
int modFactorM = int(modFactor);
vec2 cameraPositionBIM = cameraPositionInt.xz - modFactorM * (cameraPositionInt.xz / modFactorM);
vec3 cameraPos = vec3(
cameraPositionBIM.x + cameraPositionBestFract.x,
cameraPosition.y,
cameraPositionBIM.y + cameraPositionBestFract.z
);
#if defined CLOUDS_UNBOUND && defined DOUBLE_UNBOUND_CLOUDS
float layer2ScaleFactor = CLOUD_UNBOUND_LAYER2_SIZE * 10.0 / CLOUD_UNBOUND_SIZE_MULT;
#if CLOUD_UNBOUND_SIZE_MULT == 100
float modFactor2 = 1.0 / (cloudNarrowness * layer2ScaleFactor);
#else
float modFactor2 = 1.0 / (cloudNarrowness * CLOUD_UNBOUND_SIZE_MULT_M * layer2ScaleFactor);
#endif
int modFactorM2 = int(modFactor2);
vec2 cameraPositionBIM2 = cameraPositionInt.xz - modFactorM2 * (cameraPositionInt.xz / modFactorM2);
vec3 cameraPos2 = vec3(
cameraPositionBIM2.x + cameraPositionBestFract.x,
cameraPosition.y,
cameraPositionBIM2.y + cameraPositionBestFract.z
);
#endif
#else
vec3 cameraPos = cameraPosition;
#if defined CLOUDS_UNBOUND && defined DOUBLE_UNBOUND_CLOUDS
vec3 cameraPos2 = cameraPosition;
#endif
#endif
cameraPos += cameraPosOffset;
#if defined CLOUDS_UNBOUND && defined DOUBLE_UNBOUND_CLOUDS
cameraPos2 += cameraPosOffset;
#endif
#ifdef CLOUDS_REIMAGINED
float thresholdF = 4000.0;
#else
float thresholdF = 4000.0;
#endif
//float thresholdMix = pow2(clamp01(VdotU * 15.0));
//thresholdF = mix(far, thresholdF, thresholdMix * 0.5 + 0.5);
thresholdF *= CLOUD_RENDER_DISTANCE;
#if RAINBOW_CLOUD != 0
vec3 wpos = normalize((gbufferModelViewInverse * vec4(viewPos, 1.0)).xyz);
wpos /= (abs(wpos.y) + length(wpos.xz));
vec3 rainbowColor = getRainbowColor(wpos.xz * rainbowCloudDistribution * 0.35, 0.05);
cloudRainColor *= rainbowColor;
cloudAmbientColor *= rainbowColor;
cloudLightColor *= rainbowColor;
#endif
#ifdef CLOUDS_REIMAGINED
cloudAmbientColor *= 1.0 - 0.25 * rainFactor;
#endif
vec3 cloudColorMult = vec3(1.0);
#if CLOUD_R != 100 || CLOUD_G != 100 || CLOUD_B != 100
cloudColorMult *= vec3(CLOUD_R, CLOUD_G, CLOUD_B) * 0.01;
#endif
cloudAmbientColor *= cloudColorMult;
cloudLightColor *= cloudColorMult;
#if defined CLOUDS_REIMAGINED && defined DOUBLE_REIM_CLOUDS
int maxCloudAlt = max(cloudAlt1i, cloudAlt2i);
int minCloudAlt = min(cloudAlt1i, cloudAlt2i);
if (abs(cameraPos.y - minCloudAlt) < abs(cameraPos.y - maxCloudAlt)) {
clouds = GetVolumetricClouds(minCloudAlt, thresholdF, cloudLinearDepth, skyFade, skyMult0,
cameraPos, nPlayerPos, lViewPosM, VdotS, VdotU, dither, sunVec, viewPos);
if (clouds.a == 0.0) {
clouds = GetVolumetricClouds(maxCloudAlt, thresholdF, cloudLinearDepth, skyFade, skyMult0,
cameraPos, nPlayerPos, lViewPosM, VdotS, VdotU, dither, sunVec, viewPos);
}
} else {
clouds = GetVolumetricClouds(maxCloudAlt, thresholdF, cloudLinearDepth, skyFade, skyMult0,
cameraPos, nPlayerPos, lViewPosM, VdotS, VdotU, dither, sunVec, viewPos);
if (clouds.a == 0.0) {
clouds = GetVolumetricClouds(minCloudAlt, thresholdF, cloudLinearDepth, skyFade, skyMult0,
cameraPos, nPlayerPos, lViewPosM, VdotS, VdotU, dither, sunVec, viewPos);
}
}
#elif defined CLOUDS_UNBOUND && defined DOUBLE_UNBOUND_CLOUDS
float cloudLinearDepth1 = 1.0;
float cloudLinearDepth2 = 1.0;
//The order of calculating the clouds actually matters here
vec4 clouds1 = GetVolumetricClouds(cloudAlt1i, thresholdF, cloudLinearDepth1, skyFade, skyMult0,
cameraPos, nPlayerPos, lViewPosM, VdotS, VdotU, dither, sunVec, viewPos);
vec4 clouds2 = GetVolumetricClouds(cloudAlt2i, thresholdF, cloudLinearDepth2, skyFade, skyMult0,
cameraPos2, nPlayerPos, lViewPosM, VdotS, VdotU, dither, sunVec, viewPos);
if (clouds1.a * clouds2.a < 1e-36)
clouds = clouds1 * sign(max(0.0, clouds1.a - 1e-36)) + clouds2 * sign(max(0.0, clouds2.a - 1e-36));
else {
if (cloudLinearDepth1 < cloudLinearDepth2)
clouds = vec4(mix(clouds2.rgb, clouds1.rgb, clouds1.w), mix(clouds2.w, 1.0, clouds1.w));
else
clouds = vec4(mix(clouds1.rgb, clouds2.rgb, clouds2.w), mix(clouds1.w, 1.0, clouds2.w));
}
cloudLinearDepth = min(clouds1.a > 0.5 ? cloudLinearDepth1 : 1.0, clouds2.a > 0.5 ? cloudLinearDepth2 : 1.0);
#else
clouds = GetVolumetricClouds(cloudAlt1i, thresholdF, cloudLinearDepth, skyFade, skyMult0,
cameraPos, nPlayerPos, lViewPosM, VdotS, VdotU, dither, sunVec, viewPos) ;
#endif
#ifdef ATM_COLOR_MULTS
clouds.rgb *= sqrtAtmColorMult; // C72380KD - Reduced atmColorMult impact on some things
#endif
#ifdef MOON_PHASE_INF_ATMOSPHERE
clouds.rgb *= moonPhaseInfluence;
#endif
#if AURORA_STYLE > 0
clouds.rgb += auroraBorealis * 0.1;
#endif
#if NIGHT_NEBULAE == 1
clouds.rgb += nightNebula * 0.2;
#endif
return clouds;
}
@@ -0,0 +1,236 @@
#include "/lib/shaderSettings/cloudsAndLighting.glsl"
#include "/lib/atmospherics/clouds/cloudCoord.glsl"
#ifdef DOUBLE_REIM_CLOUDS
const float cloudStretch = CLOUD_STRETCH * 4.2;
const float L2cloudStretch = cloudStretch * CLOUD_REIMAGINED_LAYER2_HEIGHT;
const float cloudTallness = cloudStretch * 2.0;
#else
const float cloudStretch = CLOUD_STRETCH * 4.2;
const float cloudTallness = cloudStretch * 2.0;
#endif
const float cloudRoundness = CLOUD_ROUNDNESS;
bool GetCloudNoise(vec3 tracePos, inout vec3 tracePosM, int cloudAltitude) {
tracePosM = ModifyTracePos(tracePos, cloudAltitude);
vec2 coord = GetRoundedCloudCoord(tracePosM.xz, cloudRoundness);
#ifdef DEFERRED1
float noise = texture2D(colortex3, coord).b;
#else
float noise = texture2D(gaux4, coord).b;
#endif
float threshold = clamp(abs(cloudAltitude - tracePos.y) / cloudStretch, 0.001, 0.999);
threshold = pow2(pow2(pow2(threshold)));
return noise > threshold * 0.5 + 0.25;
}
float Get2DCloudSample(vec2 pos) {
#ifdef DEFERRED1
return texture2D(colortex3, GetRoundedCloudCoord(pos, cloudRoundness)).b;
#else
return texture2D(gaux4, GetRoundedCloudCoord(pos, cloudRoundness)).b;
#endif
}
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);
// Use local variables to avoid modifying globals
float localCloudStretch = cloudStretch;
float localCloudTallness = cloudTallness;
#ifdef DOUBLE_REIM_CLOUDS
if (cloudAltitude != cloudAlt1i) { // second layer
localCloudStretch = L2cloudStretch;
localCloudTallness = 2.0 * localCloudStretch;
}
#endif
float higherPlaneAltitude = cloudAltitude + localCloudStretch;
float lowerPlaneAltitude = cloudAltitude - localCloudStretch;
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;
#if CLOUD_QUALITY_INTERNAL == 1 || !defined DEFERRED1
int sampleCount = max(int(planeDistanceDif) / 16, 6);
#elif CLOUD_QUALITY_INTERNAL == 2
int sampleCount = max(int(planeDistanceDif) / 8, 12);
#elif CLOUD_QUALITY_INTERNAL == 3 || CLOUD_QUALITY_INTERNAL == 4
int sampleCount = max(int(planeDistanceDif), 12);
#endif
float stepMult = planeDistanceDif / sampleCount;
vec3 traceAdd = nPlayerPos * stepMult;
vec3 tracePos = cameraPos + minPlaneDistance * nPlayerPos;
tracePos += traceAdd * dither;
tracePos.y -= traceAdd.y;
#ifdef FIX_AMD_REFLECTION_CRASH
sampleCount = min(sampleCount, 30); //BFARC
#endif
#ifdef AURORA_INFLUENCE
cloudAmbientColor = getAuroraAmbientColor(cloudAmbientColor, viewPos, 0.032, AURORA_CLOUD_INFLUENCE_INTENSITY, 0.75);
#endif
for (int i = 0; i < sampleCount; i++) {
tracePos += traceAdd;
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;
}
vec3 tracePosM;
if (GetCloudNoise(tracePos, tracePosM, cloudAltitude)) {
float lightMult = 1.0;
#if SHADOW_QUALITY > -1
float shadowLength = shadowDistance * 0.9166667; //consistent08JJ622
if (shadowLength > lTracePos)
if (GetShadowOnCloud(tracePos, cameraPos, cloudAltitude, lowerPlaneAltitude, higherPlaneAltitude)) {
#ifdef CLOUD_CLOSED_AREA_CHECK
if (eyeBrightness.y != 240) continue;
else
#endif
lightMult = 0.25;
}
#endif
#ifdef INVERTED_CLOUD_SHADING
float cloudShading = (higherPlaneAltitude - tracePos.y) / localCloudTallness;
#else
float cloudShading = 1.0 - (higherPlaneAltitude - tracePos.y) / localCloudTallness;
#endif
cloudShading = pow(max0(cloudShading), max0(CLOUD_SHADING_AMOUNT * 0.1 - 0.2));
float VdotSM1 = max0(sunVisibility > 0.5 ? VdotS : - VdotS);
#if CLOUD_QUALITY_INTERNAL >= 2
#ifdef DEFERRED1
float cloudShadingM = 1.0 - pow2(cloudShading);
#else
float cloudShadingM = 1.0 - cloudShading;
#endif
float gradientNoise = InterleavedGradientNoiseForClouds();
vec3 cLightPos = tracePosM;
vec3 cLightPosAdd = normalize(ViewToPlayer(lightVec * 1000000000.0)) * vec3(0.08);
cLightPosAdd *= shadowTime;
float light = 2.0;
cLightPos += (1.0 + gradientNoise) * cLightPosAdd;
light -= Get2DCloudSample(cLightPos.xz) * cloudShadingM;
cLightPos += gradientNoise * cLightPosAdd;
light -= Get2DCloudSample(cLightPos.xz) * cloudShadingM;
float VdotSM2 = VdotSM1 * shadowTime * 0.25;
VdotSM2 += 0.5 * cloudShading + 0.08;
cloudShading = VdotSM2 * light * lightMult;
#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 = 1.0 - smoothstep(-20.0, 0.0, cameraPos.y - cloudAltitude);
float sunPlaneIntersect = (cloudAltitude - cameraPos.y) / worldLightVec.y;
vec2 posVector = cameraPos.xz + worldLightVec.xz * sunPlaneIntersect - tracePos.xz;
float moonVisibility = abs(1.0 - moonPhase / 4.0);
float sunMult = mix(moonVisibility, 0.75, sunVisibility);
float falloff = exp((1.0 - max0(1.0 - length(posVector) / cloudLightRadius)) * -6.0) * aboveFade * sunMult;
float sunCloudMult = clamp01(falloff * 2.5 * mix(1.0, (lTracePos - minPlaneDistance) / (maxPlaneDistance - minPlaneDistance), 0.6));
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 * sunCloudMult * 0.11 * visibilityFactor;
cloudShading += sunCloudMult * 1.5 * 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
#ifdef AURORA_INFLUENCE
cloudLightColor = getAuroraAmbientColor(cloudLightColor, viewPos, 0.1, AURORA_CLOUD_INFLUENCE_INTENSITY, 0.75);
#endif
vec3 colorSample = cloudAmbientColor * 0.95 * (1.0 - 0.35 * cloudShading) + cloudLightColor * (0.1 + cloudShading);
#ifdef RAIN_ATMOSPHERE
// Lightning flashes around lightning bolt position
vec3 lightningPos = getLightningPos(tracePos - cameraPos, lightningBoltPosition.xyz, false);
vec2 lightningAdd = lightningFlashEffect(lightningPos, vec3(1.0), 450.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.005);
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 cloudFogFactor = pow2(clamp(distanceRatio, 0.0, 1.0)) * 0.75;
float nightCloudRemove = NIGHT_CLOUD_UNBOUND_REMOVE * (1.0 - sunVisibility) * -1 + 1.0; // mapped to 1 to 0 range
#if defined DOUBLE_REIM_CLOUDS && CLOUD_REIMAGINED_LAYER2_TRANSPARENCY != 20
if (cloudAltitude != cloudAlt1i) { // second layer uses custom transparency
cloudMult *= (CLOUD_REIMAGINED_LAYER2_TRANSPARENCY * 0.05) * nightCloudRemove;
} else {
cloudMult *= CLOUD_TRANSPARENCY * nightCloudRemove;
}
#else
cloudMult *= CLOUD_TRANSPARENCY * nightCloudRemove;
#endif
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);
colorSample *= pow2(1.0 - maxBlindnessDarkness);
float cloudDistanceFactor = clamp(distanceRatio, 0.0, 0.75);
//float distanceRatioNew = (2000 - lTracePosXZ) / 2000;
//float cloudDistanceFactorNew = clamp(distanceRatioNew, 0.5, 0.75);
//volumetricClouds.a = pow(cloudDistanceFactor * 1.33333, 0.5 + 10.0 * pow(abs(VdotSM1), 90.0)) * cloudMult;
volumetricClouds.a = sqrt(cloudDistanceFactor * 1.33333) * cloudMult;
volumetricClouds.rgb = colorSample;
cloudLinearDepth = sqrt(lTracePos / renderDistance);
break;
}
}
return volumetricClouds;
}
@@ -0,0 +1,376 @@
#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;
}
@@ -0,0 +1,296 @@
#ifndef ENDCRYSTAL_SAMPLER_DEFINE
uniform isampler2D endcrystal_sampler;
#endif
const float healing_boundRadius = 6.0;
const float healing_ballRadius = 3.5;
const float healing_beamRadius = 0.6;
const float vortex_cylinderRadius = 3.0;
const float vortex_ballRadius = 5.0;
const float death_radius = 70.0;
#ifndef INCLUDE_ENDER_BEAMS
#ifdef GBUFFERS_WATER
float vlFactor = 0.5;
#endif
#endif
vec3 beamPurple = normalize(endColorBeam * endColorBeam * endColorBeam) * (2.5 - 1.0 * vlFactor) * E_BEAM_I;
vec3 endDragonColM = sqrt(endOrangeCol);
vec3 beamColM = sqrt(beamPurple);
float GetBallRadius(float state) {
return vortex_ballRadius * (1.0 + 4.0 * sqrt(1.0 - state));
}
float VortexWidth(float x, float ballRadius) {
if (x > 0.5 * ballRadius) {
float expScale = sqrt(0.75) * ballRadius - vortex_cylinderRadius;
return vortex_cylinderRadius + expScale * exp( -sqrt(1.0/3.0) / expScale * (x - 0.5 * ballRadius));
} else if (x > -ballRadius) {
return sqrt(pow2(ballRadius) - pow2(x));
}
return 0.0;
}
vec4 SampleEndCrystalVortex(vec3 relPos, vec2 state, vec2 noiseOffset) {
float thisBallRadius = GetBallRadius(state.x);
float beamFactor = smoothstep(-thisBallRadius, thisBallRadius, relPos.y);
float featureWidth = VortexWidth(relPos.y, thisBallRadius);
vec2 horizontalScaledPos = featureWidth > 0.0 ? relPos.xz / featureWidth : vec2(2.0);
float featureDist = length(horizontalScaledPos);
if (length(relPos.xz) > featureWidth) {
return vec4(0);
}
float beamStrength = 2.5 * beamFactor * (cos(featureDist * 3.1416) * 0.5 + 0.5) * pow2(max(0.0, 1 - pow2(0.005 / (0.9 * state.x + 0.1) / pow2(pow2(state.y)) * relPos.y))) * state.x;
float spiralStrength = 200 * beamFactor * pow(featureDist, 7) * pow2(1.0 - featureDist) * pow2(max(0.0, 1 - pow2(0.02 / (0.6 * state.x * state.x + 0.4) / state.y * relPos.y)));
float spiralAngle = (0.4 / vortex_cylinderRadius * relPos.y - 0.2 * pow2(min(0.0, -2.5 + relPos.y / thisBallRadius))) / (state.x + 0.2);
vec2 spiralPos = mat2(cos(spiralAngle), -sin(spiralAngle), sin(spiralAngle), cos(spiralAngle)) * horizontalScaledPos;
vec4 beamNoise = texture2DLod(noisetex, noiseOffset + 5.0 / noiseTextureResolution * horizontalScaledPos, 0.0);
vec4 beamNoise2 = texture2DLod(noisetex, noiseOffset + 5.0 / noiseTextureResolution * vec2(relPos.y * 0.02 + 2.7 * beamNoise.gb - 3.6 * frameTimeCounter * 0.5), 0.0);
vec4 spiralNoise = texture2DLod(noisetex, noiseOffset + 5.0 / noiseTextureResolution * spiralPos, 0.0);
vec4 spiralNoise2 = texture2DLod(noisetex, noiseOffset + 20.0 / noiseTextureResolution * spiralPos, 0.0);
return vec4(beamStrength * beamNoise.r * beamNoise2.r * endDragonColM + spiralStrength * pow2(spiralNoise.r) * (0.5 + spiralNoise2.r) * beamColM, beamStrength + spiralStrength) * 0.3;
}
vec4 SingleEndCrystalVortex(vec3 start, vec3 direction, vec3 center, vec2 state, float dither) {
const float stepSize = 0.5;
float invHorizontalDirLen = 1.0 / length(direction.xz);
float thisBallRadius = GetBallRadius(state.x);
float closestProgress = clamp(
dot(center.xz - start.xz, direction.xz) * pow2(invHorizontalDirLen),
-thisBallRadius * invHorizontalDirLen,
1.0 + thisBallRadius * invHorizontalDirLen);
vec3 closestPos = start + closestProgress * direction;
float closestDist = length(closestPos.xz - center.xz);
if (closestDist > thisBallRadius) {
return vec4(0);
}
float startProgress = closestProgress - sqrt((thisBallRadius * thisBallRadius - closestDist * closestDist)) * invHorizontalDirLen;
float endProgress = min(1.0, 2 * closestProgress - startProgress);
startProgress = max(0.0, startProgress);
vec2 noiseOffset = (center.xz + cameraPosition.xz + vec2(3.0, 1.6) * frameTimeCounter) * 0.005;
vec4 colour = vec4(0);
float dist = startProgress + dither * invHorizontalDirLen * stepSize;
for (int k = 0; k < 100; k++) {
if (dist > endProgress) break;
colour += SampleEndCrystalVortex(start + dist * direction - center, state, noiseOffset);
dist += invHorizontalDirLen * stepSize;
}
return colour * stepSize * smoothstep(0.0, 1.0, state.x);
}
float EndCrystalBeamWidth(float x, float len) {
x = 0.5 * len - abs(x - 0.5 * len);
if (x <= -healing_ballRadius) return 0.0;
if (x < 0.5 * healing_ballRadius) return sqrt(pow2(healing_ballRadius) - pow2(x));
float expScale = sqrt(0.75) * healing_ballRadius - healing_beamRadius;
return healing_beamRadius + expScale * exp( -sqrt(1.0/3.0) / expScale * (x - 0.5 * healing_ballRadius));
}
vec4 SampleEndCrystalBeam(vec3 relPos, float len) {
float beamWidth = EndCrystalBeamWidth(relPos.x, len);
if (beamWidth > 0.0001) {
float beamFactor = smoothstep(0.0, 2.0 * healing_ballRadius, 0.5 * len - abs(relPos.x - 0.5 * len));
float noisyTime = frameTimeCounter + 0.4 * texture2DLod(noisetex, vec2(3.0 / noiseTextureResolution, frameTimeCounter / (0.45 * noiseTextureResolution)), 0.0).r;
relPos.yz /= beamWidth;
float strength = 0.0;
vec3 healBeamColor = vec3(0);
for (int k = 0; k < 3; k++) {
vec2 noiseCoords = vec2(0.2 / noiseTextureResolution * relPos.x, 0 + vec2(k, 6 * k) / noiseTextureResolution);
vec4 zapNoise0 = texture2DLod(noisetex, noiseCoords + floor(8.0 * noisyTime) / noiseTextureResolution, 0.0);
vec4 zapNoise1 = texture2DLod(noisetex, 3.3 * noiseCoords + floor(8.0 * noisyTime) / noiseTextureResolution, 0.0);
vec4 zapNoise2 = texture2DLod(noisetex, 6.8 * noiseCoords + (15.0 * frameTimeCounter) / noiseTextureResolution, 0.0);
vec2 thisRelPos = relPos.yz + beamFactor / beamWidth * (6.0 * zapNoise0.rb + 1.6 * zapNoise1.rb + 1.2 * zapNoise2.rb - (3.0 + 0.8 + 0.6));
vec4 sideNoise = texture2DLod(noisetex, (7.0 * thisRelPos.xy) / noiseTextureResolution, 0.0);
vec3 colorNoise = texture2DLod(noisetex, 4.0 * noiseCoords + floor(12.0 * noisyTime) / noiseTextureResolution, 0.0).rgb;
float centerDist0 = length(thisRelPos.xy);
float centerDist = centerDist0 - 1.2;
strength = max(strength, clamp( -centerDist, 0.0, 0.2) * pow2(max(0.0, 1.0 - pow2((centerDist0 - 1.0) * beamWidth * 0.5))) * mix(1.0, sideNoise.b, beamWidth / healing_ballRadius));
healBeamColor = mix(clamp01(saturateColors(beamColM, 0.8) - sideNoise.rgb * 0.08), saturateColors(beamColM, 1.3) * 1.3, colorNoise);
}
return strength / beamWidth * vec4(healBeamColor * 0.5, 1.0) + 0.2 * beamFactor * exp(-6.0 * dot(relPos.yz, relPos.yz)) * vec4(endDragonColM * 2.2, 1.0);
}
return vec4(0.0);
}
vec4 EndCrystalBeam(vec3 start, vec3 direction, vec3 startPos, vec3 endPos, float dither) {
vec3 startDiff = start - startPos;
vec3 beamDirection = endPos - startPos;
mat3 rotMat;
rotMat[0] = normalize(beamDirection);
rotMat[1] = normalize(cross(beamDirection, vec3(-2e-4, 1, 1e-5)));
rotMat[2] = cross(rotMat[0], rotMat[1]);
start *= rotMat;
startPos *= rotMat;
beamDirection *= rotMat;
direction *= rotMat;
const float stepSize = 0.5;
float invHorizontalDirLen = 1.0 / length(direction.yz);
float closestProgress = clamp(
dot(startPos.yz - start.yz, direction.yz) * pow2(invHorizontalDirLen),
-healing_boundRadius * invHorizontalDirLen,
1.0 + healing_boundRadius * invHorizontalDirLen);
vec3 closestPos = start + closestProgress * direction;
float closestDist = length(closestPos.yz - startPos.yz);
if (closestDist > healing_boundRadius) {
return vec4(0);
}
float startProgress = closestProgress - sqrt((healing_boundRadius * healing_boundRadius - closestDist * closestDist)) * invHorizontalDirLen;
float endProgress = min(1.0, 2 * closestProgress - startProgress);
startProgress = max(0.0, startProgress);
vec4 colour = vec4(0);
float dist = startProgress + dither * invHorizontalDirLen * stepSize;
for (int k = 0; k < 100; k++) {
if (dist > endProgress) break;
colour += SampleEndCrystalBeam(start + dist * direction - startPos, beamDirection.x);
dist += invHorizontalDirLen * stepSize;
}
return 3.0 * log(length(colour) * stepSize + 1.0) * normalize(colour + 0.0000001);
}
float GetDragonDeathFactor(float dragonDeathTime) {
return 0.02 * dragonDeathTime * exp(0.1 * dragonDeathTime);
}
vec4 SampleDeathBuildup(vec3 relPos, float dragonDeathTime) {
float effectFactor = GetDragonDeathFactor(dragonDeathTime);
float effectRadius = death_radius * effectFactor;
float sizeNoiseFactor = 1.0 + 0.3 * texture2DLod(noisetex, vec2(0.2, dragonDeathTime * 5.0 / noiseTextureResolution), 0.0).r;
float centerDist = length(relPos) / effectRadius;
relPos *= sizeNoiseFactor;
float angle = centerDist * 5.0 / log(dragonDeathTime * 0.6 + 1.0);
mat2 rotMat = mat2(
cos(angle), sin(angle),
-sin(angle), cos(angle)
);
relPos.xz = rotMat * relPos.xz;
vec2 val = pow(fract(hash23(floor(0.8 * relPos + 2.7 * sign(relPos) * exp(0.3 * dragonDeathTime)))), vec2(40.0 * pow2(centerDist))) * (1.0 - centerDist);
return 0.1 * (vec4(beamColM, 1.0) * (val.x + 0.4 * exp(-8.0 * pow2(centerDist))) + vec4(endDragonColM, 1.0) * (val.y + 0.1 * exp(-3.0 * pow2(centerDist))));
}
vec4 DragonDeathAnimation(vec3 start, vec3 direction, vec3 dragonPos, float dragonDeathTime, float dragonDeathFactor, float dither) {
float dirLen = length(direction);
float closestProgress = dot(dragonPos - start, direction) / pow2(dirLen);
vec4 colour = vec4(0);
if (dragonDeathFactor >= 0.99) {
float effectRadius = death_radius * GetDragonDeathFactor(dragonDeathTime);
vec3 closestPos = start + closestProgress * direction;
float closestDist = length(closestPos - dragonPos);
if (closestDist >= effectRadius) return vec4(0.0);
float stepSize = 0.5 / dirLen;
float startProgress = closestProgress - sqrt(pow2(effectRadius) - pow2(closestDist)) / dirLen;
float endProgress = min(1.0, 2.0 * closestProgress - startProgress);
startProgress = max(0.0, startProgress);
float dist = startProgress + stepSize * dither;
for (int k = 0; k < 150; k++) {
if (dist > endProgress) break;
colour += SampleDeathBuildup(start + dist * direction - dragonPos, dragonDeathTime);
dist += stepSize;
}
colour *= stepSize * dirLen;
} else {
vec3 closestPos = start + clamp(closestProgress, 0.0, 1.0) * direction;
float closestDist = length(dragonPos - closestPos);
colour = vec4(endDragonColM + 0.5 * beamColM, 1.0) * (0.4 * death_radius * (1.0 - exp(-dirLen/(4.0 * death_radius))) * exp(-10.0 * (1.0 - dragonDeathFactor) - closestDist * closestDist / (death_radius * death_radius)) * dragonDeathFactor);
}
return colour;
}
vec4 EndCrystalVortices(vec3 start, vec3 direction, float dither) {
vec4 color = vec4(0);
#if END_CRYSTAL_VORTEX_INTERNAL / 2 == 1 || DRAGON_DEATH_EFFECT_INTERNAL > 0
ivec4 rawDragonPos = ivec4(
texelFetch(endcrystal_sampler, ivec2(35, 5), 0).r,
texelFetch(endcrystal_sampler, ivec2(35, 6), 0).r,
texelFetch(endcrystal_sampler, ivec2(35, 7), 0).r,
texelFetch(endcrystal_sampler, ivec2(35, 8), 0).r
);
vec3 dragonPos = rawDragonPos.xyz != ivec3(0) ? 0.0001 * rawDragonPos.xyz : vec3(0.5, 80.5, 0.5) - cameraPosition;
#endif
#if END_CRYSTAL_VORTEX_INTERNAL / 2 == 1
vec3[15] healBeamEndPositions;
int isTarget = 0;
int healBeamCount = 15;
for (int k = 0; k < 15; k++) {
ivec4 rawPos = ivec4(
texelFetch(endcrystal_sampler, ivec2(20 + k, 5), 0).r,
texelFetch(endcrystal_sampler, ivec2(20 + k, 6), 0).r,
texelFetch(endcrystal_sampler, ivec2(20 + k, 7), 0).r,
texelFetch(endcrystal_sampler, ivec2(20 + k, 8), 0).r
);
if (rawPos.w == 0) {
healBeamCount = k;
break;
}
healBeamEndPositions[k] = vec3(rawPos.xyz) / rawPos.w;
isTarget |= (length(healBeamEndPositions[k].xz + cameraPosition.xz - 0.5) < 4.5 || length(dragonPos - healBeamEndPositions[k]) < 5.0) ? 1 << k : 0;
}
#endif
#if END_CRYSTAL_VORTEX_INTERNAL % 2 == 1
for (int k = 0; k < 20; k++) {
if (texelFetch(endcrystal_sampler, ivec2(k, 8), 0).r <= 0) continue;
ivec4 rawPos = ivec4(
texelFetch(endcrystal_sampler, ivec2(k, 5), 0).r,
texelFetch(endcrystal_sampler, ivec2(k, 6), 0).r,
texelFetch(endcrystal_sampler, ivec2(k, 7), 0).r,
texelFetch(endcrystal_sampler, ivec2(k, 8), 0).r
);
if (rawPos.w <= 0) {
continue;
}
int age = texelFetch(endcrystal_sampler, ivec2(k, 9), 0).r;
vec3 pos = rawPos.xyz * 0.0001;
#if END_CRYSTAL_VORTEX_INTERNAL / 2 == 1
for (int i = 0; i < healBeamCount; i++) {
isTarget |= length(pos - healBeamEndPositions[i]) < 4.5 ? 1<<(i+15) : 0;
}
#endif
vec2 state = vec2(clamp(rawPos.w / 15000.0, 0.0, 1.0), 1.00001 - exp(-0.0001 * age));
if (length(pos) > min(shadowDistance, far) * 0.9 && state.x < 0.999) {
state.y = state.x;
state.x = 1.0;
}
vec4 thisVortexCol = pow2(SingleEndCrystalVortex(start, direction, pos, state, dither));
color += thisVortexCol;
}
#endif
#if END_CRYSTAL_VORTEX_INTERNAL / 2 == 1
for (int k = 0; k < healBeamCount; k++) {
for (int l = k+1; l < healBeamCount; l++) {
if (
((isTarget >> k & 1) == 0 ^^ (isTarget >> l & 1) == 0)
#if END_CRYSTAL_VORTEX_INTERNAL % 2 == 1
&& ((isTarget >> k + 15 & 1) == 0 ^^ (isTarget >> l + 15 & 1) == 0)
#endif
) {
vec3 pos0 = healBeamEndPositions[k];
vec3 pos1 = healBeamEndPositions[l];
if (pos0.y > pos1.y) {
vec3 tmp = pos0;
pos0 = pos1;
pos1 = tmp;
}
color += pow2(EndCrystalBeam(start, direction, pos0, pos1, dither));
}
}
}
#endif
#if DRAGON_DEATH_EFFECT_INTERNAL > 0
int isDying = texelFetch(endcrystal_sampler, ivec2(35, 0), 0).r;
float dragonDeathTime = 0.0001 * rawDragonPos.w;
float dragonDeathFactor = 0.0001 * isDying;
// dragonDeathTime = mod(frameTimeCounter, 22.0);
// dragonDeathFactor = 2.2 - 0.1 * dragonDeathTime;
// dragonPos = vec3(0, 80, 0) - cameraPosition;
if (dragonDeathFactor > 0.001) {
color += pow2(DragonDeathAnimation(start, direction, dragonPos, dragonDeathTime, dragonDeathFactor, dither));
}
#endif
return sqrt(color) * (1.0 - maxBlindnessDarkness);
}
@@ -0,0 +1,46 @@
vec3 DrawEndFlash(vec3 nViewPos, float VdotU, float dither) {
vec3 worldEndFlashPosition = mat3(gbufferModelViewInverse) * endFlashPosition;
worldEndFlashPosition = normalize(worldEndFlashPosition);
vec3 nViewPosWorld = mat3(gbufferModelViewInverse) * nViewPos;
nViewPosWorld = normalize(nViewPosWorld);
vec3 horizontalEndPos = normalize(vec3(worldEndFlashPosition.x, 0.0, worldEndFlashPosition.z));
vec3 horizontalViewPos = normalize(vec3(nViewPosWorld.x, 0.0, nViewPosWorld.z));
float horizDirFactor = pow(max0(dot(horizontalEndPos, horizontalViewPos)), 0.2);
float dirFactor = pow(max0(dot(worldEndFlashPosition, nViewPosWorld)), 10.0);
float verticalDist = abs(nViewPosWorld.y - worldEndFlashPosition.y);
float verticalFalloff = exp(-pow2(verticalDist * 5.5));
float endFlashFactor = endFlashIntensity * dirFactor * verticalFalloff;
if (endFlashFactor < 0.001) return vec3(0.0);
float time = frameTimeCounter * 0.05;
float pulse = sin(time * 3.0) * 0.5 + 0.5;
vec2 noiseCoord = horizontalViewPos.xz * 0.5 + time * 0.05;
float noise1 = texture2DLod(noisetex, noiseCoord, 0).r;
float noise2 = texture2DLod(noisetex, noiseCoord * 2.7 - time * 0.17, 0).g;
float noise3 = texture2DLod(noisetex, noiseCoord * 0.5 + time * 0.05, 0).b;
float rayFactor = pow(noise1 * noise2, 1.5) * 2.0;
float stripeFactor = pow(horizDirFactor, 2.0 + 4.0 * pulse);
// Inner core and wave animations
float radius = 1.0 + sin(time * 2.0) * 0.1;
float distFromCenter = length(dot(horizontalEndPos, horizontalViewPos));
float waveFront = smoothstep(0.0, 0.2, 1.0 - abs(distFromCenter - radius) * (4.0 + pulse * 4.0));
float core = pow(horizDirFactor, 1.0 + pulse * 2.0) * (1.0 + noise3 * 0.5);
float flashIntensity = mix(core, waveFront, 0.5) * endFlashFactor * (0.6 + rayFactor * 0.8);
flashIntensity *= stripeFactor;
vec3 orangeColor = mix(endOrangeCol, vec3(1.0), 0.3) * (1.2 + noise2 * 1.3);
vec3 finalColor = saturateColors(orangeColor, 0.8) * flashIntensity * 0.7;
return finalColor;
}
@@ -0,0 +1,63 @@
#ifndef ENDCRYSTAL_SAMPLER_DEFINE
uniform isampler2D endcrystal_sampler;
#endif
vec2 RayAABoxIntersection(vec2 start, vec2 dir, vec2 lower, vec2 upper) {
dir += 0.000001 * vec2(equal(dir, vec2(0)));
vec2 front = mix(upper, lower, 0.5 * sign(dir) + 0.5);
vec2 back = mix(lower, upper, 0.5 * sign(dir) + 0.5);
vec2 front_iscts = (front - start) / dir;
vec2 back_iscts = (back - start) / dir;
float front_isct = max(front_iscts.x, front_iscts.y);
float back_isct = min(back_iscts.x , back_iscts.y );
return front_isct < back_isct ? vec2(front_isct, back_isct) : vec2(-1);
}
vec4 GetEndPortalBeamNoise(vec3 relPos) {
float colMixFactor = texture2DLod(noisetex, (relPos.xz + 0.1 * frameTimeCounter * vec2(-0.5, 1.5)) * 10.0 / noiseTextureResolution, 0.0).r;
float strengthMul = texture2DLod(noisetex, (relPos.xz + 0.1 * frameTimeCounter * vec2(1.5, -1.0)) * 5.0 / noiseTextureResolution + 0.2, 0.0).r;
colMixFactor = pow2(pow2(colMixFactor));
strengthMul = pow2(strengthMul);
vec3 col = mix(vec3(0.1137, 0.5569, 0.5255), vec3(0.3725, 0.8863, 0.749), colMixFactor);
float strength
= float(relPos.y > 0 && relPos.y < 2)
* (2 - relPos.y)
/ (3 * relPos.y*relPos.y*relPos.y + 1)
* (strengthMul + 0.5);
return pow2(vec4(col, 1) * strength);
}
vec4 GetEndPortalBeam(vec3 start, vec3 dir) {
if (texelFetch(endcrystal_sampler, ivec2(35, 4), 0).r == 1) {
ivec4 rawPortalPos = ivec4(
texelFetch(endcrystal_sampler, ivec2(35, 5), 0).r,
texelFetch(endcrystal_sampler, ivec2(35, 6), 0).r,
texelFetch(endcrystal_sampler, ivec2(35, 7), 0).r,
texelFetch(endcrystal_sampler, ivec2(35, 8), 0).r
);
if (rawPortalPos.w > 0) {
vec3 portalPos = floor(vec3(rawPortalPos.xyz) / max(1, rawPortalPos.w) + 0.5) + 0.5 - cameraPositionFract;
vec2 iscts = RayAABoxIntersection(start.xz, dir.xz, portalPos.xz - 1.49, portalPos.xz + 1.49);
int validIsctCount = 0;
vec3[2] isctPositions;
for (int k = 0; k < 2; k++) {
if (iscts[k] > 0.0 && iscts[k] < 1.0) {
isctPositions[validIsctCount++] = start + iscts[k] * dir;
}
}
vec4 col = vec4(0.0);
for (int k = 0; k < validIsctCount; k++) {
col += GetEndPortalBeamNoise(isctPositions[k] - portalPos);
}
vec3 absDir = abs(dir);
float maxDir = max(absDir.x, max(absDir.y, absDir.z));
float transition = 1.0 - pow3(min1(maxDir / mix(40, 10, maxBlindnessDarkness) * 2.0)); // fade to 0 when close to the range limit (32 blocks)
col *= transition;
return col;
}
}
return vec4(0.0);
}
@@ -0,0 +1,88 @@
#ifndef INCLUDE_ENDER_BEAMS
#define INCLUDE_ENDER_BEAMS
#include "/lib/colors/lightAndAmbientColors.glsl"
vec2 wind = vec2(syncedTime * 0.00);
float BeamNoise(vec2 planeCoord, vec2 wind) {
float noise = texture2DLod(noisetex, planeCoord * 0.175 - wind * 0.0625, 0.0).b;
noise+= texture2DLod(noisetex, planeCoord * 0.04375 + wind * 0.0375, 0.0).b * 5.0;
return noise;
}
vec3 DrawEnderBeams(float VdotU, vec3 playerPos, vec3 nViewPos) {
int sampleCount = 8;
float beamMult = 1.0;
float beamPow = 3.0;
float beamPurpleReducer = vlFactor;
float beamOrangeIncreaser = vlFactor;
float VdotUM = 1.0 - pow2(VdotU);
float VdotUM2 = sqrt(VdotUM) + 0.15 * smoothstep1(pow2(pow2(1.0 - abs(VdotU))));
#if defined IS_IRIS && MC_VERSION >= 12109 && EP_END_FLASH % 2 == 0
vec3 worldEndFlashPosition = mat3(gbufferModelViewInverse) * endFlashPosition;
worldEndFlashPosition = normalize(vec3(worldEndFlashPosition.x, 0.0, worldEndFlashPosition.z));
vec3 nViewPosWorld = mat3(gbufferModelViewInverse) * nViewPos;
vec3 nViewPosWorldM = normalize(vec3(nViewPosWorld.x, 0.0, nViewPosWorld.z));
float endFlashDirectionFactor = pow(max0(dot(worldEndFlashPosition, nViewPosWorldM)), 12.0);
float endFlashFactor = endFlashIntensity * endFlashDirectionFactor;
beamOrangeIncreaser = mix(beamOrangeIncreaser, 1.0, endFlashFactor);
beamPurpleReducer = mix(beamPurpleReducer, 1.6, endFlashFactor);
beamPow = mix(beamPow, 0.7, endFlashFactor * (pow(VdotUM, 8.0) * 0.75 + 0.25 * pow(1.0 - abs(VdotU) * 0.1 - 0.9 * pow2(VdotU), 30.0)));
//beamPow = max(beamPow, 0.0001); // fix NaNs
VdotUM = mix(VdotUM, sqrt2(VdotUM), endFlashFactor);
#endif
vec3 beamPurple = normalize(endColorBeam * endColorBeam * endColorBeam) * (2.5 - beamPurpleReducer) * E_BEAM_I;
vec3 beamOrange = endOrangeCol * (300.0 + 700.0 * beamOrangeIncreaser);
vec4 beams = vec4(0.0);
float gradientMix = 1.0;
for (int i = 0; i < sampleCount; i++) {
vec2 planeCoord = playerPos.xz + cameraPosition.xz;
planeCoord *= (1.0 + i * 6.0 / sampleCount) * 0.0014;
float noise = BeamNoise(planeCoord, wind);
#ifndef BEAMS_NEAR_PLAYER
noise = max(0.75 - 1.0 / abs(noise - (4.0 + VdotUM * 2.0)), 0.0) * 3.0;
#else
noise = max(0.75 - 1.0 / abs(noise - (4.0 + dot(upVec, upVec) * 2.0)), 0.0) * 3.0;
#endif
if (noise > 0.0) {
noise *= 0.65;
float fireNoise = texture2DLod(noisetex, abs(planeCoord * 0.2) - wind, 0.0).b;
noise *= 0.5 * fireNoise + 0.75;
//noise = max0(noise); // fix NaNs
noise = pow(noise, 1.75) * 2.9 / sampleCount;
#ifndef BEAMS_NEAR_PLAYER
noise *= VdotUM2;
#endif
vec3 beamColor = beamPurple;
beamColor += beamOrange * pow2(pow2(fireNoise - 0.5));
beamColor *= gradientMix / sampleCount;
noise *= exp2(-6.0 * i / float(sampleCount));
beams += vec4(noise * beamColor, noise);
}
gradientMix += 1.0;
}
#ifdef RAIN_ATMOSPHERE
beams.rgb += 0.2 * isLightningActive();
#endif
beamMult *= pow(beams.a, beamPow) * 3.5;
beams.rgb = sqrt(beams.rgb) * beamMult;
if(any(isnan(beams.rgb))) beams.rgb = vec3(0.0);
return beams.rgb;
}
#endif //INCLUDE_ENDER_BEAMS
@@ -0,0 +1,48 @@
#include "/lib/shaderSettings/enderStars.glsl"
vec3 GetEnderStars(vec3 viewPos, float VdotU, float sizeMult, float starAmount) {
vec3 wpos = normalize((gbufferModelViewInverse * vec4(viewPos * 1000.0, 1.0)).xyz);
vec3 starCoord = 0.65 * wpos / (abs(wpos.y) + length(wpos.xz));
vec2 starCoord2 = starCoord.xz * 0.5 / (END_STAR_SIZE * sizeMult);
starCoord2 += VdotU < 0.0 ? 100.0 : 0.0;
const float starFactor = 1024.0;
vec2 fractPart = fract(starCoord2 * starFactor);
starCoord2 = floor(starCoord2 * starFactor) / starFactor;
float star = GetStarNoise(starCoord2.xy) * GetStarNoise(starCoord2.xy+0.1) * GetStarNoise(starCoord2.xy+0.23);
#if END_STAR_AMOUNT == 0
star = max0(star - 0.77);
#elif END_STAR_AMOUNT == 2
star = max0((star + 0.15) * 0.9 - 0.7);
#elif END_STAR_AMOUNT == 3
star = max0((star + 0.4) * 0.8 - 0.7);
#elif END_STAR_AMOUNT == 4
star = max0((star + 0.5) * 0.8 - 0.7);
#else
star = max0(star - 0.7);
#endif
star *= getStarEdgeFactor(fractPart, STAR_ROUNDNESS_END / 10.0, STAR_SOFTNESS_END);
star = max0(star - starAmount * 0.1);
star *= star;
vec3 starColor = GetStarColor(starCoord2,
endSkyColor,
vec3(STAR_COLOR_1_END_R, STAR_COLOR_1_END_G, STAR_COLOR_1_END_B),
vec3(STAR_COLOR_2_END_R, STAR_COLOR_2_END_G, STAR_COLOR_2_END_B),
vec3(STAR_COLOR_3_END_R, STAR_COLOR_3_END_G, STAR_COLOR_3_END_B),
float(STAR_COLOR_VARIATION_END));
vec3 enderStars = star * starColor * 3000.0 * END_STAR_BRIGHTNESS;
float VdotUM1 = abs(VdotU);
float VdotUM2 = pow2(1.0 - VdotUM1);
enderStars *= VdotUM1 * VdotUM1 * (VdotUM2 + 0.015) + 0.015;
#if END_TWINKLING_STARS > 0
enderStars *= getTwinklingStars(starCoord2, float(END_TWINKLING_STARS));
#endif
return enderStars;
}
@@ -0,0 +1,46 @@
#include "/lib/shaderSettings/bloom.glsl"
#ifdef CAVE_FOG
#include "/lib/atmospherics/fog/caveFactor.glsl"
#endif
const float rainBloomAdd = 8.0;
const float nightBloomAdd = 3.0;
const float caveBloomAdd = 14.0;
const float waterBloomAdd = 14.0;
#ifdef BORDER_FOG
const float netherBloomAdd = 14.0;
#else
const float netherBloomAdd = 3.0;
#endif
float GetBloomFog(float lViewPos) {
#ifdef OVERWORLD
float bloomFog = pow2(pow2(1.0 - exp(-lViewPos * (0.02 + 0.04 * float(isEyeInWater == 1)))));
float bloomFogMult;
if (isEyeInWater != 1) {
bloomFogMult = (rainFactor2 * rainBloomAdd + nightBloomAdd * (1.0 - sunFactor)) * eyeBrightnessM;
#ifdef CAVE_FOG
bloomFogMult += GetCaveFactor() * caveBloomAdd;
#endif
} else {
bloomFogMult = waterBloomAdd;
}
#elif defined NETHER
float farM = min(renderDistance, NETHER_VIEW_LIMIT); // consistency9023HFUE85JG
float bloomFog = lViewPos / clamp(farM, 96.0, 256.0);
bloomFog *= bloomFog * bloomFog;
bloomFog = 1.0 - exp(-8.0 * bloomFog);
bloomFog *= float(isEyeInWater == 0);
float bloomFogMult = netherBloomAdd;
#else
float bloomFog = 0.0;
float bloomFogMult = 0.0;
#endif
bloomFogMult *= BLOOM_STRENGTH * 8.33333;
return 1.0 + bloomFog * bloomFogMult;
}
@@ -0,0 +1,21 @@
#ifndef INCLUDE_CAVE_FACTOR
#define INCLUDE_CAVE_FACTOR
#define CAVE_FOG_R_NEW 0.13 // [0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.50 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.60 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.70 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.80 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.90 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.00]
#define CAVE_FOG_G_NEW 0.13 // [0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.50 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.60 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.70 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.80 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.90 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.00]
#define CAVE_FOG_B_NEW 0.15 // [0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.50 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.60 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.70 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.80 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.90 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1.00]
#define CAVE_FOG_I 1.00 //[0.20 0.25 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.0]
float GetCaveFactor() {
return clamp(1.0 - cameraPosition.y / oceanAltitude, 0.0, 1.0 - eyeBrightnessM);
}
vec3 caveFogColorRaw = vec3(CAVE_FOG_R_NEW, CAVE_FOG_G_NEW, CAVE_FOG_B_NEW) * CAVE_FOG_I;
#if CAVE_LIGHTING < 100
vec3 caveFogColor = caveFogColorRaw * 0.7;
#elif CAVE_LIGHTING == 100
vec3 caveFogColor = caveFogColorRaw * (0.7 + 0.3 * vsBrightness); // Default
#elif CAVE_LIGHTING > 100
vec3 caveFogColor = caveFogColorRaw;
#endif
#endif
@@ -0,0 +1,78 @@
vec3 GetColoredLightFog(vec3 nPlayerPos, vec3 translucentMult, float lViewPos, float lViewPos1, float dither, float vlFactor) {
vec3 lightFog = vec3(0.0);
float stepMult = 8.0;
#ifdef CAVE_SMOKE
float caveFactor = GetCaveFactor() * (1.0 - clamp01(isEyeInWater));
#endif
float maxDist = min(effectiveACTdistance * 0.5, far);
int sampleCount = int(maxDist / stepMult + 0.001);
vec3 traceAdd = nPlayerPos * stepMult;
vec3 tracePos = traceAdd * dither;
for (int i = 0; i < sampleCount; i++) {
tracePos += traceAdd;
float lTracePos = length(tracePos);
if (lTracePos > lViewPos1) break;
if (any(greaterThan(abs(tracePos * 2.0), vec3(voxelVolumeSize)))) break;
vec3 voxelPos = SceneToVoxel(tracePos);
voxelPos = clamp01(voxelPos / vec3(voxelVolumeSize));
vec4 lightVolume = GetLightVolume(voxelPos);
vec3 lightSample = lightVolume.rgb;
#if defined END && END_CENTER_LIGHTING > 0 && MC_VERSION >= 10900 && defined END_CENTER_LIGHTING_AFFECT_BLOCKLIGHT
vec3 endCenterCol = saturateColors(vec3(END_CENTER_LIGHTING_R, END_CENTER_LIGHTING_G, END_CENTER_LIGHTING_B), 1.1);
vec3 endCenterPos = vec3(0.5, 60.5, 0.5) - (tracePos + cameraPositionBest);
endCenterPos.y *= 0.66; // Make it a pill-shaped point light
float rawDistance = length(endCenterPos);
float endCenterLightDist = exp(-rawDistance * 0.62) * 100;
lightSample = mix(lightSample, clamp01(saturateColors(endCenterCol, 1.3)), clamp01(endCenterLightDist) * (1.0 - vlFactor));
#endif
float lTracePosM = length(
vec3(
tracePos.x,
#if COLORED_LIGHTING_INTERNAL <= 512
tracePos.y * 2.0,
#elif COLORED_LIGHTING_INTERNAL == 768
tracePos.y * 3.0,
#elif COLORED_LIGHTING_INTERNAL == 1024
tracePos.y * 4.0,
#endif
tracePos.z
)
);
lightSample *= max0(1.0 - lTracePosM / maxDist);
lightSample *= pow2(min1(lTracePos * 0.03125));
#ifdef CAVE_SMOKE
if (caveFactor > 0.00001) {
vec3 smokePos = 0.0025 * (tracePos + cameraPosition);
vec3 smokeWind = frameTimeCounter * vec3(0.006, 0.003, 0.0);
float smoke = Noise3D(smokePos + smokeWind)
* Noise3D(smokePos * 3.0 - smokeWind)
* Noise3D(smokePos * 9.0 + smokeWind);
smoke = smoothstep1(smoke);
lightSample *= mix(1.0, smoke * 16.0, caveFactor);
lightSample += caveFogColor * pow2(smoke) * 0.05 * caveFactor;
}
#endif
if (lTracePos > lViewPos) lightSample *= translucentMult;
lightFog += lightSample;
}
#ifdef NETHER
lightFog *= netherColor * 5.0;
#endif
lightFog *= 1.0 - maxBlindnessDarkness;
lightFog = pow(lightFog / sampleCount, vec3(0.25));
return lightFog;
}
@@ -0,0 +1,18 @@
#if !defined END_CENTER_FOG
#define END_CENTER_FOG
float doEndCenterFog(vec3 ro, vec3 rayDir, float wsdist, float falloff) { // Thanks to FoZy STYLE
vec3 d = ro - vec3(0.5, 60.5, 0.5); // Light source vector
d.y *= 0.7;
rayDir.y *= 0.7;
float a = falloff * dot(rayDir, rayDir);
float b = 2.0 * falloff * dot(rayDir, d);
float c = 1.0 + falloff * dot(d, d);
float sqrtDiscr = max(0.001, sqrt(4.0 * a * c - b * b));
float upper = (2.0 * a * wsdist + b) / sqrtDiscr;
float lower = b / sqrtDiscr;
return 2.0 * (atan(upper) - atan(lower)) / sqrtDiscr;
}
#endif
@@ -0,0 +1,277 @@
#include "/lib/shaderSettings/mainFog.glsl"
#ifdef ATM_COLOR_MULTS
#include "/lib/colors/colorMultipliers.glsl"
#endif
#ifdef MOON_PHASE_INF_ATMOSPHERE
#include "/lib/colors/moonPhaseInfluence.glsl"
#endif
#ifdef BORDER_FOG
#ifdef OVERWORLD
#include "/lib/atmospherics/sky.glsl"
#elif defined NETHER || defined END
#include "/lib/colors/skyColors.glsl"
#endif
void DoBorderFog(inout vec4 color, inout float skyFade, float lPos, float VdotU, float VdotS, float dither) {
#ifdef OVERWORLD
float fog = lPos / renderDistance;
fog = pow2(pow2(fog));
#ifndef DISTANT_HORIZONS
fog = pow2(pow2(fog));
#endif
fog = 1.0 - exp(-BORDER_FOG_DISTANCE_OVERWORLD * fog);
#endif
#ifdef NETHER
float farM = min(renderDistance, NETHER_VIEW_LIMIT); // consistency9023HFUE85JG
float fog = lPos / farM;
fog = fog * 0.3 + 0.7 * pow(fog * BORDER_FOG_DISTANCE_NETHER / 3, 256.0 / max(farM, 256.0));
#endif
#ifdef END
float fog = lPos / renderDistance;
fog = pow2(pow2(fog));
fog = 1.0 - exp(-BORDER_FOG_DISTANCE_END * fog);
#endif
#ifdef IRIS_FEATURE_FADE_VARIABLE
#if defined GBUFFERS_WATER || defined DEFERRED1
float chunkFadeM = mix(1.0, chunkFade, pow2(clamp01(lPos * 0.015))); // don't do fade very close to the player
fog = mix(1.0, fog, chunkFadeM);
#endif
#endif
if (fog > 0.0) {
fog = clamp(fog, 0.0, 1.0);
#ifdef OVERWORLD
vec3 fogColorM = GetSky(VdotU, VdotS, dither, true, false);
#define BORDER_FOG_DENSITY BORDER_FOG_DENSITY_OVERWORLD
#elif defined NETHER
vec3 fogColorM = netherColor;
#define BORDER_FOG_DENSITY BORDER_FOG_DENSITY_NETHER
#else
vec3 fogColorM = endSkyColor;
#define BORDER_FOG_DENSITY BORDER_FOG_DENSITY_END
#endif
#ifdef ATM_COLOR_MULTS
fogColorM *= atmColorMult;
#endif
#ifdef MOON_PHASE_INF_ATMOSPHERE
fogColorM *= moonPhaseInfluence;
#endif
fog *= BORDER_FOG_DENSITY;
color = mix(color, vec4(fogColorM, 0.0), fog);
#ifndef GBUFFERS_WATER
skyFade = fog;
#else
skyFade = fog * (1.0 - isEyeInWater);
#endif
}
}
#endif
#ifdef CAVE_FOG
#include "/lib/atmospherics/fog/caveFactor.glsl"
void DoCaveFog(inout vec4 color, float lViewPos) {
float fog = GetCaveFactor() * (0.9 - 0.9 * exp(- lViewPos * 0.015 * CAVE_FOG_DENSITY));
color = mix(color, vec4(caveFogColor, 0.0), fog);
}
#endif
#ifdef ATMOSPHERIC_FOG
#include "/lib/colors/lightAndAmbientColors.glsl"
#include "/lib/colors/skyColors.glsl"
// SRATA: Atm. fog starts reducing above this altitude
// CRFTM: Atm. fog continues reducing for this meters
#ifdef OVERWORLD
#define atmFogSRATA ATM_FOG_ALTITUDE + 0.1
#ifndef DISTANT_HORIZONS
float atmFogCRFTM = 60.0;
#else
float atmFogCRFTM = 90.0;
#endif
vec3 GetAtmFogColor(float altitudeFactorRaw, float VdotS) {
vec3 atmFogColor = vec3(ATMOSPHERIC_FOG_R_NEW, ATMOSPHERIC_FOG_G_NEW, ATMOSPHERIC_FOG_B_NEW) * ATMOSPHERIC_FOG_I;
#ifdef RADIOACTIVE_ATMOSPHERIC_FOG
atmFogColor *= GetLuminance(atmFogColor) * 10;
#endif
float nightFogMult = 2.5 - 0.625 * max(pow2(pow2(altitudeFactorRaw)), rainFactor);
float dayNightFogBlend = pow(invNightFactor, 4.0 - VdotS - 2.5 * sunVisibility2);
return atmFogColor * mix(
nightUpSkyColor * (nightFogMult - dayNightFogBlend * nightFogMult),
dayDownSkyColor * (0.9 + 0.3 * noonFactor),
dayNightFogBlend
);
}
#else
float atmFogSRATA = 55.1;
float atmFogCRFTM = 30.0;
#endif
float GetAtmFogAltitudeFactor(float altitude) {
float altitudeFactor = pow2(1.0 - clamp(altitude - atmFogSRATA, 0.0, atmFogCRFTM) / atmFogCRFTM);
#ifndef LIGHTSHAFTS_ACTIVE
altitudeFactor = mix(altitudeFactor, 1.0, rainFactor * 0.2);
#endif
return altitudeFactor;
}
void DoAtmosphericFog(inout vec4 color, vec3 playerPos, float lViewPos, float VdotS) {
#ifndef DISTANT_HORIZONS
float renDisFactor = min1(192.0 / renderDistance);
#if ATM_FOG_DISTANCE != 100
#define ATM_FOG_DISTANCE_M 100.0 / ATM_FOG_DISTANCE;
renDisFactor *= ATM_FOG_DISTANCE_M;
#endif
float fog = 1.0 - exp(-pow(lViewPos * (0.001 - 0.0007 * rainFactor), 2.0 - rainFactor2) * lViewPos * renDisFactor);
#else
float fog = pow2(1.0 - exp(-max0(lViewPos - 40.0) * (0.7 + 0.7 * rainFactor) / ATM_FOG_DISTANCE));
#endif
float atmFogA = 1.0;
atmFogA *= ATMOSPHERIC_FOG_DENSITY * ATM_FOG_MULT;
fog *= atmFogA - 0.1 - 0.15 * invRainFactor;
float altitudeFactorRaw = GetAtmFogAltitudeFactor(playerPos.y + cameraPosition.y);
#ifndef DISTANT_HORIZONS
float altitudeFactor = altitudeFactorRaw * 0.9 + 0.1;
#else
float altitudeFactor = altitudeFactorRaw * 0.8 + 0.2;
#endif
#ifdef OVERWORLD
altitudeFactor *= 1.0 - 0.75 * GetAtmFogAltitudeFactor(cameraPosition.y) * invRainFactor;
#if defined SPECIAL_BIOME_WEATHER || RAIN_STYLE == 2
if (isEyeInWater == 0) {
#if RAIN_STYLE == 2
float factor = 1.0;
#else
float factor = max(inSnowy, inDry);
#endif
float fogFactor = 4.0;
#ifdef SPECIAL_BIOME_WEATHER
fogFactor += 2.0 * inDry;
#endif
fogFactor *= 0.5 + 0.5 * sunVisibility;
float fogIntense = pow2(1.0 - exp(-lViewPos * fogFactor / ATM_FOG_DISTANCE));
fog = mix(fog, fogIntense / altitudeFactor, 0.8 * rainFactor * factor);
}
#endif
#ifdef CAVE_FOG
fog *= 0.2 + 0.8 * sqrt2(eyeBrightnessM);
fog *= 1.0 - GetCaveFactor();
#else
fog *= eyeBrightnessM;
#endif
#else
fog *= 0.5;
#endif
fog *= altitudeFactor;
if (fog > 0.0) {
fog = clamp(fog, 0.0, 1.0);
#ifdef OVERWORLD
vec3 fogColorM = GetAtmFogColor(altitudeFactorRaw, VdotS);
#else
vec3 fogColorM = endSkyColor * 1.5;
#endif
#ifdef ATM_COLOR_MULTS
fogColorM *= atmColorMult;
#endif
#ifdef MOON_PHASE_INF_ATMOSPHERE
fogColorM *= moonPhaseInfluence;
#endif
color = mix(color, vec4(fogColorM, 0.0), fog);
}
}
#endif
#include "/lib/atmospherics/fog/waterFog.glsl"
void DoWaterFog(inout vec4 color, float lViewPos) {
float fog = GetWaterFog(lViewPos);
color = mix(color, vec4(waterFogColor, 0), fog);
}
void DoLavaFog(inout vec4 color, float lViewPos) {
float fog = (lViewPos * 3.0 - gl_Fog.start) * gl_Fog.scale;
#ifdef LESS_LAVA_FOG
fog = sqrt(fog) * 0.4;
#endif
fog = 1.0 - exp(-fog);
fog = clamp(fog, 0.0, 1.0);
color = mix(color, vec4(fogColor * 5.0, 0.0), fog);
}
void DoPowderSnowFog(inout vec4 color, float lViewPos) {
float fog = lViewPos;
#ifdef LESS_LAVA_FOG
fog = sqrt(fog) * 0.4;
#endif
fog *= fog;
fog = 1.0 - exp(-fog);
fog = clamp(fog, 0.0, 1.0);
color = mix(color, vec4(fogColor, 0.0), fog);
}
void DoBlindnessFog(inout vec4 color, float lViewPos) {
float fog = lViewPos * 0.3 * blindness;
fog *= fog;
fog = 1.0 - exp(-fog);
fog = clamp(fog, 0.0, 1.0);
color *= 1.0 - fog;
}
void DoDarknessFog(inout vec4 color, float lViewPos) {
float fog = lViewPos * 0.075 * darknessFactor;
fog *= fog;
fog *= fog;
color *= exp(-fog);
}
void DoFog(inout vec4 color, inout float skyFade, float lViewPos, vec3 playerPos, float VdotU, float VdotS, float dither, bool isReflection, float lBlockPos) {
#ifdef CAVE_FOG
DoCaveFog(color, lViewPos);
#endif
#ifdef ATMOSPHERIC_FOG
float lViewPosAtm = lViewPos;
// Reduce fog if the reflecting block is already behind fog, and fogging the reflection would result in too much fog
if (isReflection) lViewPosAtm *= 0.2 + 0.8 * sqrt1(max0(1.0 - lBlockPos / lViewPos));
DoAtmosphericFog(color, playerPos, lViewPosAtm, VdotS);
#endif
#ifdef BORDER_FOG
DoBorderFog(color, skyFade, max(length(playerPos.xz), abs(playerPos.y)), VdotU, VdotS, dither);
#endif
if (isEyeInWater == 1) DoWaterFog(color, lViewPos);
else if (isEyeInWater == 2) DoLavaFog(color, lViewPos);
else if (isEyeInWater == 3) DoPowderSnowFog(color, lViewPos);
if (blindness > 0.00001) DoBlindnessFog(color, lViewPos);
if (darknessFactor > 0.00001) DoDarknessFog(color, lViewPos);
}
@@ -0,0 +1,19 @@
#ifndef INCLUDE_WATER_FOG
#define INCLUDE_WATER_FOG
float GetWaterFog(float lViewPos) {
#if WATER_FOG_MULT != 100
#define WATER_FOG_MULT_M WATER_FOG_MULT * 0.01;
lViewPos *= WATER_FOG_MULT_M;
#endif
#if LIGHTSHAFT_QUALI > 0 && SHADOW_QUALITY > -1
float fog = lViewPos / 48.0;
fog *= fog;
#else
float fog = lViewPos / 32.0;
#endif
return 1.0 - exp(-fog);
}
#endif
@@ -0,0 +1,43 @@
vec3 GetNetherNoise(vec3 viewPos, float VdotU, float dither) {
float visibility = clamp01(VdotU * 1.875 - 0.225);
visibility *= 1.0 - VdotU * 0.75 - maxBlindnessDarkness;
if (visibility > 0.0) {
vec3 spots = vec3(0.0);
float eyeAltitude1 = eyeAltitude * 0.005;
float noiseHeightFactor = max(0.0, 1.5 - eyeAltitude1 / (eyeAltitude1 + 1.0));
noiseHeightFactor *= noiseHeightFactor;
float noiseHeight = noiseHeightFactor * 0.5;
vec3 wpos = (gbufferModelViewInverse * vec4(viewPos, 1.0)).xyz;
wpos.xz /= wpos.y;
vec2 cameraPositionM = cameraPosition.xz * 0.0075;
cameraPositionM.x += frameTimeCounter * 0.004;
int sampleCount = 10;
int sampleCountP = sampleCount + 5;
float ditherM = dither + 5.0;
float wind = fract(frameTimeCounter * 0.0125);
for (int i = 0; i < sampleCount; i++) {
float current = pow2((i + ditherM) / sampleCountP);
vec2 planePos = wpos.xz * (0.8 + current) * noiseHeight;
planePos = (planePos * 0.5 + cameraPositionM * 0.5) * 1.5;
float noiseSpots = texture2DLod(noisetex, planePos * 0.5, 0.0).g;
vec3 noise = texture2DLod(noisetex, vec2(noiseSpots) + wind, 0.0).g * netherColor * 2.5 - netherColor * 1.3;
float currentM = 1.0 - current;
spots += noise * currentM * 6.0;
}
#ifdef RAIN_ATMOSPHERE
spots += 2.0 * isLightningActive();
#endif
return spots * visibility / sampleCount;
}
return vec3(0.0);
}
@@ -0,0 +1,78 @@
vec4 GetNetherStorm(vec3 color, vec3 translucentMult, vec3 nPlayerPos, vec3 playerPos, float lViewPos, float lViewPos1, float dither) {
if (isEyeInWater != 0) return vec4(0.0);
vec4 netherStorm = vec4(1.0, 1.0, 1.0, 0.0);
#ifdef BORDER_FOG
float maxDist = min(renderDistance, NETHER_VIEW_LIMIT); // consistency9023HFUE85JG
#else
float maxDist = renderDistance;
#endif
#ifndef LOW_QUALITY_NETHER_STORM
int sampleCount = int(maxDist / 8.0 + 0.001);
vec3 traceAdd = nPlayerPos * maxDist / sampleCount;
vec3 tracePos = cameraPosition;
tracePos += traceAdd * dither;
#else
int sampleCount = int(maxDist / 16.0 + 0.001);
vec3 traceAdd = 0.75 * nPlayerPos * maxDist / sampleCount;
vec3 tracePos = cameraPosition;
tracePos += traceAdd * dither;
tracePos += traceAdd * sampleCount * 0.25;
#endif
vec3 translucentMultM = pow(translucentMult, vec3(1.0 / sampleCount));
for (int i = 0; i < sampleCount; i++) {
tracePos += traceAdd;
vec3 tracedPlayerPos = tracePos - cameraPosition;
float lTracePos = length(tracedPlayerPos);
if (lTracePos > lViewPos1) break;
vec3 wind = vec3(frameTimeCounter * 0.002);
vec3 tracePosM = tracePos * 0.001;
tracePosM.y += tracePosM.x;
tracePosM += Noise3D(tracePosM - wind) * 0.01;
tracePosM = tracePosM * vec3(2.0, 0.5, 2.0);
float traceAltitudeM = abs(tracePos.y - NETHER_STORM_LOWER_ALT);
if (tracePos.y < NETHER_STORM_LOWER_ALT) traceAltitudeM *= 10.0;
traceAltitudeM = 1.0 - min1(abs(traceAltitudeM) / NETHER_STORM_HEIGHT);
for (int h = 0; h < 4; h++) {
float stormSample = pow2(Noise3D(tracePosM + wind));
stormSample *= traceAltitudeM;
stormSample = pow2(pow2(stormSample));
stormSample *= sqrt1(max0(1.0 - lTracePos / maxDist));
netherStorm.a += stormSample;
tracePosM *= 2.0;
wind *= -2.0;
}
#ifdef RAIN_ATMOSPHERE
vec3 lightningPos = getLightningPos(tracePos - cameraPosition, lightningBoltPosition.xyz, false);
vec2 lightningAdd = lightningFlashEffect(lightningPos, vec3(1.0), 150.0, 0.0, 0) * isLightningActive() * 8.0;
netherStorm.rgb += lightningAdd.y;
#endif
if (lTracePos > lViewPos) netherStorm.rgb *= translucentMultM;
}
#ifdef LOW_QUALITY_NETHER_STORM
netherStorm.a *= 1.8;
#endif
netherStorm.a = min1(netherStorm.a * NETHER_STORM_I);
netherStorm.rgb *= netherColor * 3.0 * (1.0 - maxBlindnessDarkness);
//if (netherStorm.a > 0.98) netherStorm.rgb = vec3(1,0,1);
//netherStorm.a *= 1.0 - max0(netherStorm.a - 0.98) * 50.0;
return netherStorm;
}
@@ -0,0 +1,199 @@
#include "/lib/atmospherics/stars.glsl"
// Nebula implementation by flytrap https://godotshaders.com/shader/2d-nebula-shader/
#include "/lib/shaderSettings/stars.glsl"
#include "/lib/shaderSettings/nightNebula.glsl"
#ifndef HQ_NIGHT_NEBULA
const int OCTAVE = 5;
#else
const int OCTAVE = 8;
#endif
const float timescale = 5.0;
const float zoomScale = NEBULA_ZOOM_LEVEL;
const vec4 CLOUD1_COL = vec4(NEBULA_R_1, NEBULA_G_1, NEBULA_B_1, 0.4);
const vec4 CLOUD2_COL = vec4(NEBULA_R_2, NEBULA_G_2, NEBULA_B_2, 0.2);
const vec4 CLOUD3_COL = vec4(NEBULA_R_3, NEBULA_G_3, NEBULA_B_3, 1.0);
float sinM(float x) {
return sin(mod(x, 2.0 * pi));
}
float cosM(float x) {
return cos(mod(x, 2.0 * pi));
}
float rand(vec2 inCoord){
return fract(sinM(dot(inCoord, vec2(23.53, 44.0))) * 42350.45);
}
float perlin(vec2 inCoord){
vec2 i = floor(inCoord);
vec2 j = fract(inCoord);
vec2 coord = smoothstep(0.0, 1.0, j);
float a = rand(i);
float b = rand(i + vec2(1.0, 0.0));
float c = rand(i + vec2(0.0, 1.0));
float d = rand(i + vec2(1.0, 1.0));
return mix(mix(a, b, coord.x), mix(c, d, coord.x), coord.y);
}
float fbmCloud(vec2 inCoord, float minimum){
float value = 0.0;
float scale = NEBULA_AMOUNT * 0.1 + 0.45;
for (int i = 0; i < OCTAVE; i++){
value += perlin(inCoord) * scale;
inCoord *= 2.0;
scale *= 0.5;
}
return smoothstep(0.0, 1.0, (smoothstep(minimum, 1.0, value) - minimum) / (1.0 - minimum));
}
float fbmCloud2(vec2 inCoord, float minimum){
float value = 0.0;
float scale = (NEBULA_AMOUNT + 0.1) * 0.25 + 0.35;
for (int i = 0; i < OCTAVE; i++){
value += perlin(inCoord) * scale;
inCoord *= 2.0;
scale *= 0.5;
}
return (smoothstep(minimum, 1.0, value) - minimum) / (1.0 - minimum);
}
vec2 warpCoords(vec2 coord, float warpAmount) {
float angle = perlin(coord * 0.5) * 6.28318 * warpAmount;
float strength = perlin(coord * 0.7 + 0.5) * warpAmount;
vec2 offset = vec2(cos(angle), sin(angle)) * strength;
return coord + offset;
}
vec3 GetNightNebula(vec3 viewPos, float VdotU, float VdotS) {
float VdotUFactor = max0(VdotU);
float starsAroundSun = 1.0;
#ifdef CELESTIAL_BOTH_HEMISPHERES
VdotUFactor = VdotU;
#ifdef SUN_MOON_HORIZON
starsAroundSun = max0(sign(VdotU));
#endif
#endif
float originalVdotUFactor = VdotUFactor;
float horizonPower = NEBULA_HORIZON_STRENGTH * 0.05 + 0.5;
#if NEBULA_HORIZON_STRENGTH < 10
VdotUFactor = pow(VdotUFactor, horizonPower);
#endif
float nebulaFactor = pow2(VdotUFactor * min1(nightFactor * 2.0));
#if NEBULA_HORIZON_STRENGTH < 10
float brightnessCompensation = 1.0 - (1.0 - horizonPower) * 0.5 * max0(originalVdotUFactor);
nebulaFactor *= brightnessCompensation;
#endif
#ifdef CLEAR_SKY_WHEN_RAINING
nebulaFactor *= min1(invRainFactor + 0.4);
#else
nebulaFactor *= invRainFactor;
#endif
nebulaFactor -= maxBlindnessDarkness;
#if NEBULA_MOON_CONDITION == 1
if (moonPhase != 4) return vec3(0.0);
#elif NEBULA_MOON_CONDITION == 2
if (moonPhase != 0) return vec3(0.0);
#elif NEBULA_MOON_CONDITION == 3
if (moonPhase == 0 || moonPhase == 4) return vec3(0.0);
#elif NEBULA_MOON_CONDITION == 4
nebulaFactor *= step(0.5, hash11(float(worldDay) + float(moonPhase) * 37.0));
#elif NEBULA_MOON_CONDITION == 5
nebulaFactor *= clamp01(max(moonPhase, 1) % 4);
#endif
if (nebulaFactor < 0.001) return vec3(0.0);
vec2 UV = GetStarCoord(viewPos, 0.75);
float TIME = syncedTime * 0.003 + 15.0;
float timescaled = TIME * timescale;
float sinTime = sinM(0.07 * timescaled);
float cosTime06 = cosM(0.06 * timescaled);
float cosTime07 = cosM(0.07 * timescaled);
float tide = 0.05 * sinM(TIME);
float tide2 = 0.06 * cosM(0.3 * TIME);
vec4 nebulaTexture = vec4(vec3(0.0), 0.5 + 0.2 * sinM(0.23 * TIME + UV.x - UV.y));
#if PIXELATED_NEBULA > 0
float pixelFactor = PIXELATED_NEBULA * 2.0;
vec2 baseUV = floor(UV * pixelFactor) / pixelFactor;
#else
vec2 baseUV = UV;
#endif
vec2 scaledUV = baseUV * zoomScale;
vec2 cloudUV2 = vec2(scaledUV.x + 0.03 * timescaled * sinTime, scaledUV.y + 0.03 * timescaled * cosTime06);
vec2 cloudUV3 = vec2(scaledUV.x + 0.027 * timescaled * sinTime, scaledUV.y + 0.025 * timescaled * cosTime06);
vec2 cloudUV4 = vec2(scaledUV.x + 0.021 * timescaled * sinTime, scaledUV.y + 0.021 * timescaled * cosTime07);
#if NEBULA_PATTERN_WARP > 0
cloudUV2 = warpCoords(cloudUV2, NEBULA_PATTERN_WARP * 0.1);
cloudUV3 = warpCoords(cloudUV3, NEBULA_PATTERN_WARP * 0.1);
cloudUV4 = warpCoords(cloudUV4, NEBULA_PATTERN_WARP * 0.1);
#endif
nebulaTexture += fbmCloud2(cloudUV3, 0.24 + tide) * CLOUD1_COL;
nebulaTexture += fbmCloud(cloudUV2 * 0.9, 0.33 - tide) * CLOUD2_COL;
nebulaTexture = mix(nebulaTexture, CLOUD3_COL, fbmCloud(vec2(0.9 * cloudUV4.x, 0.9 * cloudUV4.y), 0.25 + tide2));
nebulaFactor *= 1.0 - pow2(pow2(pow2(abs(VdotS)))) * starsAroundSun;
nebulaTexture.a *= min1(pow2(pow2(nebulaTexture.a))) * nebulaFactor;
float starFactor = 1024.0;
UV /= STAR_SIZE * (0.75 + 0.25 * NEBULA_STAR_SIZE);
vec2 starCoord = floor(UV * 0.25 * starFactor) / starFactor;
vec2 fractPart = fract(UV * 0.25 * starFactor);
float starAmount = (2.0 - NEBULA_STAR_AMOUNT) * 0.1;
float starIntensity = GetStarNoise(starCoord) * GetStarNoise(starCoord + 0.1) - (starAmount + 0.5);
starIntensity *= getStarEdgeFactor(fractPart, STAR_ROUNDNESS_OW / 10.0, STAR_SOFTNESS_OW);
#if TWINKLING_STARS > 0
starIntensity *= getTwinklingStars(starCoord * 4, float(TWINKLING_STARS));
#endif
float starGlow = pow2(clamp(starIntensity, 0.0, 0.3 + starAmount)) * starBrightness * NEBULA_STAR_BRIGHTNESS;
#ifdef NEBULA_ONLY_STARS
nebulaTexture.a = step(0.15, nebulaTexture.a);
nebulaTexture.rgb = vec3(3.0 * starGlow);
#else
nebulaTexture.rgb *= 1.5 + 10.0 * starGlow;
#endif
#if NIGHT_NEBULA_I != 100
#define NIGHT_NEBULA_IM NIGHT_NEBULA_I * 0.01
nebulaTexture.a *= NIGHT_NEBULA_IM;
#endif
#if NEBULA_SATURATION != 10
nebulaTexture.rgb = rgb2hsv(nebulaTexture.rgb);
nebulaTexture.g *= NEBULA_SATURATION * 0.1;
nebulaTexture.rgb = hsv2rgb(nebulaTexture.rgb);
#endif
#ifdef ATM_COLOR_MULTS
nebulaTexture.rgb *= sqrtAtmColorMult; // C72380KD - Reduced atmColorMult impact on some things
#endif
return max(nebulaTexture.rgb * nebulaTexture.a, vec3(0.0));
}
@@ -0,0 +1,64 @@
#include "/lib/colors/lightAndAmbientColors.glsl"
vec3 beamCol = normalize(ColorBeam) * 3.0 * (2.5 - 1.0 * vlFactor) * OVERWORLD_BEAMS_INTENSITY;
vec2 wind = vec2(syncedTime * 0.0056);
float BeamNoise(vec2 planeCoord, vec2 wind) {
float noise = texture2DLod(noisetex, planeCoord * 0.275 - wind * 0.0625, 0.0).b;
noise+= texture2DLod(noisetex, planeCoord * 0.34375 + wind * 0.0575, 0.0).b * 10.0;
return noise;
}
vec4 DrawOverworldBeams(float VdotU, vec3 playerPos, vec3 viewPos) {
float visibility = 1.0 - sunVisibility - maxBlindnessDarkness;
#if OVERWORLD_BEAMS_CONDITION == 0
visibility -= moonPhase;
#endif
if (visibility > 0.0) {
vec3 result = vec3(0.0);
int sampleCount = 8;
float VdotUM = 1.0 - VdotU * VdotU;
float VdotUM2 = VdotUM + smoothstep1(pow2(pow2(1.0 - abs(VdotU)))) * 0.2;
vec4 beams = vec4(0.0);
float gradientMix = 1.0;
#ifdef AURORA_INFLUENCE
beamCol = getAuroraAmbientColor(beamCol, viewPos, 1.0, AURORA_CLOUD_INFLUENCE_INTENSITY, 0.85) * OVERWORLD_BEAMS_INTENSITY;
#endif
for(int i = 0; i < sampleCount; i++) {
vec2 planeCoord = (playerPos.xz + cameraPosition.xz) * (1.0 + i * 6.0 / sampleCount) * 0.0014;
float noise = BeamNoise(planeCoord, wind);
noise = max(0.92 - 1.0 / abs(noise - (2.5 + VdotUM * 2.0)), 0.0) * 2.5;
if (noise > 0.0) {
noise *= 0.55;
float fireNoise = texture2DLod(noisetex, abs(planeCoord * 0.2) - wind, 0.0).b;
noise *= 0.5 * fireNoise + 0.75;
noise = noise * noise * 3.0 / sampleCount;
noise *= mix(1.0, sqrt3(VdotUM2), 0.25);
vec3 beamColor = beamCol;
beamColor *= gradientMix / sampleCount;
noise *= exp2(-6.0 * i / float(sampleCount));
beams += vec4(noise * beamColor, noise);
}
gradientMix += 1.0;
}
beams.rgb *= beams.a * beams.a * beams.a * 5000.0;
beams.rgb *= sqrt(beams.rgb);
result = sqrt(beams.rgb);
if(any(isnan(result.rgb))) result.rgb = vec3(0.0);
return vec4(result * visibility / sampleCount, beams.a);
}
return vec4(1.0);
}
@@ -0,0 +1,64 @@
#define RAINBOW_DIAMETER 1.00 //[0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 2.05 2.10 2.15 2.20 2.25 2.30 2.35 2.40 2.45 2.50 2.55 2.60 2.65 2.70 2.75 2.80 2.85 2.90 2.95 3.00 3.05 3.10 3.15 3.20 3.25 3.30 3.35 3.40 3.45 3.50 3.55 3.60 3.65 3.70 3.75 3.80 3.85 3.90 3.95 4.00 4.25 4.50 4.75 5.00 5.25 5.50 5.75 6.00 6.25 6.50 6.75 7.00 7.50 8.00]
vec3 GetRainbow(vec3 translucentMult, vec3 nViewPos, float z0, float z1, float lViewPos, float lViewPos1, float VdotL, float VdotU, float dither) {
vec3 rainbow = vec3(0.0);
float rainbowTime = min1(max0(SdotU - 0.1) / 0.15);
rainbowTime = clamp(rainbowTime - pow2(pow2(pow2(noonFactor))) * 8.0, 0.0, 0.85);
#if RAINBOWS == 1 // After Rain
rainbowTime *= sqrt2(max0(wetness - 0.333) * 1.5) * invRainFactor * inRainy;
#endif
if (rainbowTime > 0.001) {
float rainbowLength = far * 0.9;
if (z1 == 1.0) lViewPos1 = rainbowLength;
float cloudLinearDepth = texelFetch(colortex5, texelCoord, 0).a;
float cloudDisMult = pow2(cloudLinearDepth + OSIEBCA * dither);
lViewPos1 *= cloudDisMult;
#if RAINBOW_STYLE == 1
float pixelScale = 45.0;
vec3 shadowDir = mat3(shadowModelView) * mat3(gbufferModelViewInverse) * nViewPos;
shadowDir.z += 0.0065 * (dither - 0.5); // Blurs the pixelation
shadowDir /= abs(shadowDir.z); // Corrects distortion
shadowDir.xy = floor(shadowDir.xy * pixelScale) / pixelScale;
VdotL = shadowDir.z * inversesqrt(dot(shadowDir, shadowDir));
#endif
float rainbowCoord = clamp01(1.0 - (VdotL + 0.75) / (0.0625 * RAINBOW_DIAMETER));
float rainbowFactor = rainbowCoord * (1.0 - rainbowCoord);
rainbowFactor = pow2(pow2(rainbowFactor * 3.7));
rainbowFactor *= pow2(min1(lViewPos1 / rainbowLength));
rainbowFactor *= rainbowTime;
rainbowFactor *= 1.0 - GetCaveFactor();
if (rainbowFactor > 0.0) {
float rainbowCoordM = pow(rainbowCoord, 1.4 + max(rainbowCoord - 0.5, 0.0) * 1.6);
rainbowCoordM = smoothstep(0.0, 1.0, rainbowCoordM) * 0.85;
rainbowCoordM += (dither - 0.5) * 0.1;
rainbow += clamp(abs(mod(rainbowCoordM * 6.0 + vec3(-0.55,4.3,2.2) ,6.0)-3.0)-1.0, 0.0, 1.0);
rainbowCoordM += 0.1;
rainbow += clamp(abs(mod(rainbowCoordM * 6.0 + vec3(-0.55,4.3,2.2) ,6.0)-3.0)-1.0, 0.0, 1.0);
rainbowCoordM -= 0.2;
rainbow += clamp(abs(mod(rainbowCoordM * 6.0 + vec3(-0.55,4.3,2.2) ,6.0)-3.0)-1.0, 0.0, 1.0);
rainbow /= 3.0;
rainbow.r += pow2(max(rainbowCoord - 0.5, 0.0)) * (max(1.0 - rainbowCoord, 0.0)) * 26.0;
rainbow = pow(rainbow, vec3(2.2)) * vec3(0.25, 0.075, 0.25) * 3.0;
if (z1 > z0 && lViewPos < rainbowLength)
rainbow *= mix(translucentMult, vec3(1.0), lViewPos / rainbowLength);
if (isEyeInWater != 0) rainbow *= sqrt1(VdotU);
rainbow *= rainbowFactor;
}
}
return rainbow;
}
@@ -0,0 +1,121 @@
// Shooting stars implementation based on https://www.shadertoy.com/view/ttVXDy and also based on https://github.com/OUdefie17/Photon-GAMS
#define SHOOTING_STARS_SIZE 0.50 //[0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75]
#define SHOOTING_STARS_SPEED 8.0 //[4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5 10.0 10.5 11.0 11.5 12.0 12.5 13.0 13.5 14.0 14.5 15.0]
#define SHOOTING_STARS_CHANCE 0.5 //[0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0]
#define SHOOTING_STARS_COUNT 4 //[1 2 3 4 5 6 7 8 9 10]
#define SHOOTING_STARS_LINE_THICKNESS 0.60 //[0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00]
#define SHOOTING_STARS_TRAIL_LENGTH 0.60 //[0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85]
// Calculate distance from point p to line segment from a to b
float DistLine(vec2 p, vec2 a, vec2 b) {
vec2 pa = p - a;
vec2 ba = b - a;
float t = clamp01(dot(pa, ba) / dot(ba, ba));
return length(pa - ba * t);
}
// Draw a line with smooth edges
float DrawLine(vec2 p, vec2 a, vec2 b) {
float d = DistLine(p, a, b);
float m = smoothstep(SHOOTING_STARS_LINE_THICKNESS * 0.01, 0.00001, d);
float d2 = length(a - b);
m *= smoothstep(1.0, 0.5, d2) + smoothstep(0.04, 0.03, abs(d2 - 0.75));
return m;
}
// Generate a single shooting star
float ShootingStar(vec2 uv, vec2 startPos, vec2 direction) {
vec2 id = floor(uv * 0.5);
float h = hash12(id);
float newMoonVisibility = 1.0 - abs(moonPhase - 4) / 4.0;
float moonPhaseFactor = mix(0.8, 1.5, newMoonVisibility);
if (h >= pow1_5(SHOOTING_STARS_CHANCE * 0.065) * moonPhaseFactor) return 0.0;
vec2 gv = fract(uv * 0.5) * 2.0 - 1.0;
float line = DrawLine(gv, startPos, startPos + direction * 0.9);
vec2 toStart = gv - startPos;
float alongTrail = dot(toStart, direction);
float trail = smoothstep(SHOOTING_STARS_TRAIL_LENGTH, -0.1, alongTrail);
float headBrightness = 1.0 + 3.0 / (1.0 + pow2((alongTrail - 1.0) * 8.0));
return line * trail * headBrightness;
}
vec3 GetShootingStars(vec2 starCoord, float VdotU, float VdotS) {
float starsAroundSun = 1.0;
#ifdef CELESTIAL_BOTH_HEMISPHERES
float starBelowHorizonBrightness = 1.0;
float horizonFactor = exp(-pow(VdotU / 0.1, 2.0));
#ifdef SUN_MOON_HORIZON
starsAroundSun = max0(sign(VdotU));
#endif
#else
if (VdotU < 0.0) return vec3(0.0);
float starBelowHorizonBrightness = min1(VdotU * 3.0);
float horizonFactor = 0.0;
#endif
float visibility = max0(1.0 - 1.0 / (1.0 + abs(VdotS) * 1000.0) * starsAroundSun) * starBelowHorizonBrightness - horizonFactor * 0.5;
#ifndef DAYLIGHT_STARS
visibility *= pow2(pow2(invNoonFactor2)) * (1.0 - 0.5 * sunVisibility);
#endif
#ifdef CLEAR_SKY_WHEN_RAINING
visibility *= min1(invRainFactor + 0.4);
#else
visibility *= invRainFactor;
#endif
if (visibility <= 0.01) return vec3(0.0);
vec2 uv = starCoord * 6.0 * (1.0 - SHOOTING_STARS_SIZE);
float speed = frameTimeCounter * SHOOTING_STARS_SPEED;
vec2 startPositions[10] = vec2[](
vec2(-0.4, 0.3),
vec2(0.2, 0.4),
vec2(-0.1, -0.3),
vec2(0.3, -0.2),
vec2(-0.3, 0.1),
vec2(0.5, 0.2),
vec2(-0.5, -0.1),
vec2(0.1, 0.5),
vec2(-0.2, -0.4),
vec2(0.4, -0.3)
);
vec2 directions[10] = vec2[](
vec2(0.7071, 0.7071),
vec2(0.7071, -0.7071),
vec2(-1.0, 0.0),
vec2(1.0, 0.0),
vec2(0.5299, 0.8480),
vec2(-0.6000, 0.8000),
vec2(0.9134, -0.4067),
vec2(-0.8000, -0.6000),
vec2(0.3015, 0.9535),
vec2(-0.2000, -0.9798)
);
float stars = 0.0;
int dayIndex = int(worldDay) % 10;
vec2 todayDirection = directions[dayIndex];
for (int i = 0; i < SHOOTING_STARS_COUNT; i++) {
float offsetAngle = (hash12(vec2(i, worldDay)) - 0.5) * 0.66;
vec2 starDirection = rotate(offsetAngle) * todayDirection;
vec2 offsetUV = uv + starDirection * speed * (0.8 + 0.04 * float(i));
stars += ShootingStar(offsetUV, startPositions[i], starDirection);
}
vec3 shootingStarColor = vec3(0.38, 0.4, 0.5) * 2.0 * starBrightness;
float intensity = min(stars * visibility * 10.0, 1.0);
return shootingStarColor * intensity;
}
@@ -0,0 +1,161 @@
#ifndef INCLUDE_SKY
#define INCLUDE_SKY
#define SUN_GLARE_AMOUNT 10 // [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30]
#define MOON_GLARE_AMOUNT 10 // [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30]
#include "/lib/colors/lightAndAmbientColors.glsl"
#include "/lib/colors/skyColors.glsl"
#ifdef CAVE_FOG
#include "/lib/atmospherics/fog/caveFactor.glsl"
#endif
vec3 GetSky(float VdotU, float VdotS, float dither, bool doGlare, bool doGround) {
// Prepare variables
float nightFactorSqrt2 = sqrt2(nightFactor);
float nightFactorM = sqrt2(nightFactorSqrt2) * 0.4;
float VdotSM1 = pow2(max(VdotS, 0.0));
float VdotSM2 = pow2(VdotSM1);
float VdotSM3 = pow2(pow2(max(-VdotS, 0.0)));
float VdotSML = sunVisibility > 0.5 ? VdotS : -VdotS;
float VdotUmax0 = max(VdotU, 0.0);
float VdotUmax0M = 1.0 - pow2(VdotUmax0);
// Prepare colors
vec3 upColor = mix(nightUpSkyColor * (1.5 - 0.5 * nightFactorSqrt2 + nightFactorM * VdotSM3 * 1.5), dayUpSkyColor, sunFactor);
vec3 middleColor = mix(nightMiddleSkyColor * (3.0 - 2.0 * nightFactorSqrt2), dayMiddleSkyColor * (1.0 + VdotSM2 * 0.3), sunFactor);
vec3 downColor = mix(nightDownSkyColor, dayDownSkyColor, (sunFactor + sunVisibility) * 0.5);
// Mix the colors
// Set sky gradient
float scatteredGroundMixerMult = 1.0;
float VdotUM1 = pow2(1.0 - VdotUmax0);
VdotUM1 = pow(VdotUM1, 1.0 - VdotSM2 * 0.4);
VdotUM1 = mix(VdotUM1, 1.0, rainFactor2 * 0.15);
vec3 finalSky = mix(upColor, middleColor, VdotUM1);
// Add sunset color
float VdotUM2 = pow2(1.0 - abs(VdotU));
VdotUM2 = VdotUM2 * VdotUM2 * (3.0 - 2.0 * VdotUM2);
VdotUM2 *= (0.7 - nightFactorM + VdotSM1 * (0.3 + nightFactorM)) * invNoonFactor * sunFactor;
finalSky = mix(finalSky, sunsetDownSkyColorP * (1.0 + VdotSM1 * 0.3), VdotUM2 * invRainFactor);
// Add sky ground with fake light scattering
float VdotUM3 = min(max0(-VdotU + 0.08) / 0.35, 1.0);
VdotUM3 = smoothstep1(VdotUM3);
vec3 scatteredGroundMixer = vec3(VdotUM3 * VdotUM3, sqrt1(VdotUM3), sqrt3(VdotUM3));
scatteredGroundMixer = mix(vec3(VdotUM3), scatteredGroundMixer, 0.75 - 0.5 * rainFactor);
finalSky = mix(finalSky, downColor, scatteredGroundMixer * scatteredGroundMixerMult);
//
// Sky Ground
if (doGround)
finalSky *= smoothstep1(pow2(1.0 + min(VdotU, 0.0)));
// Apply Underwater Fog
if (isEyeInWater == 1)
finalSky = mix(finalSky * 3.0, waterFogColor, VdotUmax0M);
// Sun/Moon Glare
#if SUN_GLARE_AMOUNT > 0 || MOON_GLARE_AMOUNT > 0
if (doGlare) {
if (0.0 < VdotSML) {
float glareScatter = 3.0 * (2.0 - clamp01(VdotS * 1000.0));
#ifndef SUN_MOON_DURING_RAIN
glareScatter *= 1.0 - 0.75 * rainFactor2;
#endif
float VdotSM4 = pow(abs(VdotS), glareScatter);
float visfactor = 0.075;
float glare = visfactor / (1.0 - (1.0 - visfactor) * VdotSM4) - visfactor;
glare *= 0.7;
float glareWaterFactor = isEyeInWater * sunVisibility;
vec3 glareColor = mix(vec3(0.38, 0.4, 0.5) * 0.3, vec3(1.5, 0.7, 0.3) + vec3(0.0, 0.5, 0.5) * noonFactor, sunVisibility);
#if BLOOD_MOON > 0
glareColor = mix(glareColor, vec3(0.6314, 0.0431, 0.0431), getBloodMoon(sunVisibility));
#endif
glareColor = glareColor + glareWaterFactor * vec3(7.0);
#ifdef SUN_MOON_DURING_RAIN
glare *= 1.0 - 0.6 * rainFactor;
#else
glare *= 1.0 - 0.8 * rainFactor;
#endif
#if RAIN_STYLE == 1
float glareDesaturateFactor = 0.5 * rainFactor;
#elif RAIN_STYLE == 2
float glareDesaturateFactor = rainFactor;
#endif
glareColor = mix(glareColor, vec3(GetLuminance(glareColor)), glareDesaturateFactor);
glare *= mix(MOON_GLARE_AMOUNT * 0.1, SUN_GLARE_AMOUNT * 0.1, sunVisibility);
finalSky += glare * shadowTime * glareColor;
}
}
#endif
#ifdef CAVE_FOG
// Apply Cave Fog
finalSky = mix(finalSky, caveFogColor, GetCaveFactor() * VdotUmax0M);
#endif
// Dither to fix banding
finalSky += (dither - 0.5) / 128.0;
#if RETRO_LOOK == 1
finalSky = vec3(0.0);
#elif RETRO_LOOK ==2
finalSky = mix(finalSky, vec3(0.0), nightVision);
#endif
return finalSky;
}
vec3 GetLowQualitySky(float VdotU, float VdotS, float dither, bool doGlare, bool doGround) {
// Prepare variables
float VdotUmax0 = max(VdotU, 0.0);
float VdotUmax0M = 1.0 - pow2(VdotUmax0);
// Prepare colors
vec3 upColor = mix(nightUpSkyColor, dayUpSkyColor, sunFactor);
vec3 middleColor = mix(nightMiddleSkyColor, dayMiddleSkyColor, sunFactor);
// Mix the colors
// Set sky gradient
float VdotUM1 = pow2(1.0 - VdotUmax0);
VdotUM1 = mix(VdotUM1, 1.0, rainFactor2 * 0.2);
vec3 finalSky = mix(upColor, middleColor, VdotUM1);
// Add sunset color
float VdotUM2 = pow2(1.0 - abs(VdotU));
VdotUM2 *= invNoonFactor * sunFactor * (0.8 + 0.2 * VdotS);
finalSky = mix(finalSky, sunsetDownSkyColorP * (shadowTime * 0.6 + 0.2), VdotUM2 * invRainFactor);
//
// Sky Ground
finalSky *= pow2(pow2(1.0 + min(VdotU, 0.0)));
// Apply Underwater Fog
if (isEyeInWater == 1)
finalSky = mix(finalSky, waterFogColor, VdotUmax0M);
// Sun/Moon Glare
finalSky *= 1.0 + mix(nightFactor, 0.5 + 0.7 * noonFactor, VdotS * 0.5 + 0.5) * pow2(pow2(pow2(VdotS)));
#ifdef CAVE_FOG
// Apply Cave Fog
finalSky = mix(finalSky, caveFogColor, GetCaveFactor() * VdotUmax0M);
#endif
#if RETRO_LOOK == 1 || RETRO_LOOK == 2
finalSky = vec3(0.0);
#endif
return finalSky;
}
#endif //INCLUDE_SKY
@@ -0,0 +1,94 @@
#if !defined STARS_FILE_INCLUDED
#define STARS_FILE_INCLUDED
#include "/lib/colors/skyColors.glsl"
#include "/lib/shaderSettings/stars.glsl"
vec2 GetStarCoord(vec3 viewPos, float sphereness) {
vec3 wpos = normalize((gbufferModelViewInverse * vec4(viewPos * 1000.0, 1.0)).xyz);
float ySign = sign(wpos.y);
float yMagnitude = abs(wpos.y);
vec3 adjustedWpos = vec3(wpos.x, yMagnitude, wpos.z);
vec3 starCoord = adjustedWpos / (adjustedWpos.y + length(adjustedWpos.xz) * sphereness);
if (ySign >= 0.0) {
starCoord.x += 0.006 * syncedTime; // Top hemisphere (original direction)
} else {
starCoord.x = starCoord.x - 0.006 * syncedTime + 0.37; // Bottom hemisphere with offset
starCoord.z += 0.21;
}
return starCoord.xz;
}
vec3 GetStars(vec2 starCoord, float VdotU, float VdotS, float sizeMult, float starAmount) {
#if NIGHT_STAR_AMOUNT == 0
return vec3(0.0, 0.0, 0.0);
#endif
float starsAroundSun = 1.0;
#ifdef CELESTIAL_BOTH_HEMISPHERES
float starBelowHorizonBrightness = 1.0;
float horizonFactor = exp(-pow(VdotU / 0.1, 2.0));
#ifdef SUN_MOON_HORIZON
starsAroundSun = max0(sign(VdotU));
#endif
#else
if (VdotU < 0.0) return vec3(0.0);
float starBelowHorizonBrightness = min1(VdotU * 3.0);
float horizonFactor = 0.0;
#endif
starCoord *= 0.2 / (STAR_SIZE * sizeMult);
const float starFactor = 1024.0;
vec2 fractPart = fract(starCoord * starFactor);
starCoord = floor(starCoord * starFactor) / starFactor;
float star = GetStarNoise(starCoord.xy) * GetStarNoise(starCoord.xy+0.1) * GetStarNoise(starCoord.xy+0.23);
#if NIGHT_STAR_AMOUNT == 1
star -= 0.82;
star *= 2.0;
#elif NIGHT_STAR_AMOUNT == 2
star -= 0.7;
#elif NIGHT_STAR_AMOUNT == 3
star -= 0.62;
star *= 0.75;
#elif NIGHT_STAR_AMOUNT == 4
star -= 0.52;
star *= 0.55;
#endif
star = max0(star - starAmount * 0.1);
star *= getStarEdgeFactor(fractPart, STAR_ROUNDNESS_OW / 10.0, STAR_SOFTNESS_OW);
star *= star;
star *= max0(1.0 - pow(abs(VdotS) * 1.002, 100.0) * starsAroundSun) * starBelowHorizonBrightness - horizonFactor * 0.5;
#ifndef DAYLIGHT_STARS
star *= pow2(pow2(invNoonFactor2)) * (1.0 - 0.5 * sunVisibility);
#endif
#ifdef CLEAR_SKY_WHEN_RAINING
star *= min1(invRainFactor + 0.4);
#else
star *= invRainFactor;
#endif
vec3 starColor = GetStarColor(starCoord,
vec3(0.38, 0.4, 0.5),
vec3(STAR_COLOR_1_OW_R, STAR_COLOR_1_OW_G, STAR_COLOR_1_OW_B),
vec3(STAR_COLOR_2_OW_R, STAR_COLOR_2_OW_G, STAR_COLOR_2_OW_B),
vec3(STAR_COLOR_3_OW_R, STAR_COLOR_3_OW_G, STAR_COLOR_3_OW_B),
float(STAR_COLOR_VARIATION_OW));
vec3 stars = 40.0 * star * starColor * starBrightness;
#if TWINKLING_STARS > 0
stars *= getTwinklingStars(starCoord, float(TWINKLING_STARS));
#endif
return stars;
}
#endif
@@ -0,0 +1,375 @@
// Volumetric tracing from Robobo1221, highly modified
#include "/lib/shaderSettings/volumetricLight.glsl"
#include "/lib/shaderSettings/endBeams.glsl"
#include "/lib/shaderSettings/endFlash.glsl"
#include "/lib/colors/lightAndAmbientColors.glsl"
//#define BEDROCK_NOISE
float GetDepth(float depth) {
return 2.0 * near * far / (far + near - (2.0 * depth - 1.0) * (far - near));
}
float GetDistX(float dist) {
return (far * (dist - near)) / (dist * (far - near));
}
vec4 DistortShadow(vec4 shadowpos, float distortFactor) {
shadowpos.xy *= 1.0 / distortFactor;
shadowpos.z = shadowpos.z * 0.2;
shadowpos = shadowpos * 0.5 + 0.5;
return shadowpos;
}
vec4 GetVolumetricLight(inout vec3 color, inout float vlFactor, vec3 translucentMult, float lViewPos0, float lViewPos1, vec3 nViewPos, float VdotL, float VdotU, vec2 texCoord, float z0, float z1, float dither) {
vec4 volumetricLight = vec4(0.0);
#if defined BEDROCK_NOISE && defined OVERWORLD
if ((cameraPosition.y < bedrockLevel) && (eyeBrightnessM < 0.4)) return vec4(0.0);
#endif
float vlMult = 1.0 - maxBlindnessDarkness;
#if SHADOW_QUALITY > -1
// Optifine for some reason doesn't provide correct shadowMapResolution if Shadow Quality isn't 1x
vec2 shadowMapResolutionM = textureSize(shadowtex0, 0);
#endif
#ifdef IRIS_FEATURE_FADE_VARIABLE
vec3 texture6 = texelFetch(colortex6, texelCoord, 0).rgb;
float chunkFade = texture6.b > 0.50001 ? (1.0 - texture6.b) * 2.0 : 1.0;
float chunkFadeM = mix(1.0, chunkFade, pow2(clamp01(lViewPos0 * 0.015))); // don't do fade very close to the player
lViewPos1 = mix(far, lViewPos1, chunkFadeM);
#endif
#ifdef OVERWORLD
vec3 vlColor = lightColor;
vec3 vlColorReducer = vec3(1.0);
float vlSceneIntensity = isEyeInWater != 1 ? vlFactor : 1.0;
#ifdef SPECIAL_BIOME_WEATHER
vlSceneIntensity = mix(vlSceneIntensity, 1.0, inDry * rainFactor);
vlColor *= 1.0 + 0.6 * inDry * rainFactor;
#endif
if (sunVisibility < 0.5) {
vlSceneIntensity = 0.0;
float vlMultNightModifier = (0.3 + 0.4 * rainFactor2 + 0.5 * max0(far - lViewPos1) / far);
#ifdef SPECIAL_PALE_GARDEN_LIGHTSHAFTS
vlMultNightModifier = mix(vlMultNightModifier, 1.0, inPaleGarden);
#endif
vlMult *= vlMultNightModifier;
vlColor = normalize(pow(vlColor, vec3(1.0 - max0(1.0 - 1.5 * nightFactor) + rainFactor)));
vlColor *= 0.0766 + 0.0766 * vsBrightness;
} else {
vlColorReducer = 1.0 / sqrt(vlColor);
}
#if BLOOD_MOON > 0
vec3 hsvVlColor = rgb2hsv(vlColor);
vlColor = mix(vlColor, hsv2rgb(vec3(0, max(0.8, hsvVlColor.y), hsvVlColor.z * 1.7)), getBloodMoon(sunVisibility));
#endif
#ifdef SPECIAL_PALE_GARDEN_LIGHTSHAFTS
vlSceneIntensity = mix(vlSceneIntensity, 1.0, inPaleGarden);
vlMult *= 1.0 + (3.0 * inPaleGarden) * (1.0 - sunVisibility);
#endif
float rainyNight = (1.0 - sunVisibility) * rainFactor;
float VdotLM = max((VdotL + 1.0) / 2.0, 0.0);
float VdotUmax0 = max(VdotU, 0.0);
float VdotUM = mix(pow2(1.0 - VdotUmax0), 1.0, 0.5 * vlSceneIntensity);
VdotUM = smoothstep1(VdotUM);
VdotUM = pow(VdotUM, min(lViewPos1 / far, 1.0) * (3.0 - 2.0 * vlSceneIntensity));
vlMult *= mix(VdotUM * VdotLM, 1.0, 0.4 * rainyNight) * vlTime;
vlMult *= mix(invNoonFactor2 * 0.875 + 0.125, 1.0, max(vlSceneIntensity, rainFactor2));
#if LIGHTSHAFT_QUALI == 4
int sampleCount = vlSceneIntensity < 0.5 ? 30 : 50;
#elif LIGHTSHAFT_QUALI == 3
int sampleCount = vlSceneIntensity < 0.5 ? 15 : 30;
#elif LIGHTSHAFT_QUALI == 2
int sampleCount = vlSceneIntensity < 0.5 ? 10 : 20;
#elif LIGHTSHAFT_QUALI == 1
int sampleCount = vlSceneIntensity < 0.5 ? 6 : 12;
#endif
#ifndef TAA
sampleCount *= 2;
#endif
#ifdef LIGHTSHAFT_SMOKE
float totalSmoke = 0.0;
#endif
#else
translucentMult = sqrt(translucentMult); // Because we pow2() the vl result in composite for the End dimension
float vlSceneIntensity = 0.0;
#ifndef LOW_QUALITY_ENDER_NEBULA
int sampleCount = 16;
#else
int sampleCount = 10;
#endif
#endif
float addition = 1.0;
float maxDist = mix(max(far, 96.0) * 0.55, 80.0, vlSceneIntensity);
#if WATER_FOG_MULT != 100
if (isEyeInWater == 1) {
#define WATER_FOG_MULT_M WATER_FOG_MULT * 0.01;
maxDist /= WATER_FOG_MULT_M;
}
#endif
float distMult = maxDist / (sampleCount + addition);
float sampleMultIntense = isEyeInWater != 1 ? 1.0 : 0.85;
float viewFactor = 1.0 - 0.7 * pow2(dot(nViewPos.xy, nViewPos.xy));
float depth0 = GetDepth(z0);
float depth1 = GetDepth(z1);
#ifdef END
if (z0 == 1.0) depth0 = 1000.0;
if (z1 == 1.0) depth1 = 1000.0;
#endif
// Fast but inaccurate perspective distortion approximation
maxDist *= viewFactor;
distMult *= viewFactor;
#ifdef IRIS_FEATURE_FADE_VARIABLE
depth1 = mix(depth1, far, pow2(pow2(1.0 - chunkFadeM)));
#endif
#ifdef OVERWORLD
float maxCurrentDist = min(depth1, maxDist);
#else
float maxCurrentDist = min(depth1, far);
#endif
for (int i = 0; i < sampleCount; i++) {
float currentDist = (i + dither) * distMult + addition;
if (currentDist > maxCurrentDist) break;
vec4 viewPos = gbufferProjectionInverse * (vec4(texCoord, GetDistX(currentDist), 1.0) * 2.0 - 1.0);
viewPos /= viewPos.w;
vec4 wpos = gbufferModelViewInverse * viewPos;
vec3 playerPos = wpos.xyz / wpos.w;
#if defined END && defined END_BEAMS
playerPos *= 512.0 / far;
vec4 enderBeamSample = vec4(DrawEnderBeams(VdotU, playerPos, nViewPos), 1.0);
enderBeamSample /= sampleCount;
#endif
#if defined OVERWORLD && defined OVERWORLD_BEAMS
vec4 overworldBeamSample = DrawOverworldBeams(VdotU, playerPos, viewPos.xyz);
#endif
float shadowSample = 1.0;
vec3 vlSample = vec3(1.0);
#if SHADOW_QUALITY > -1
wpos = shadowModelView * wpos;
wpos = shadowProjection * wpos;
wpos /= wpos.w;
float distb = sqrt(wpos.x * wpos.x + wpos.y * wpos.y);
float distortFactor = 1.0 - shadowMapBias + distb * shadowMapBias;
vec4 shadowPosition = DistortShadow(wpos,distortFactor);
//shadowPosition.z += 0.0001;
#ifdef OVERWORLD
float percentComplete = currentDist / maxDist;
float sampleMult = mix(percentComplete * 3.0, sampleMultIntense, max(rainFactor, vlSceneIntensity));
if (currentDist < 5.0) sampleMult *= smoothstep1(clamp(currentDist / 5.0, 0.0, 1.0));
sampleMult /= sampleCount;
#endif
if (length(shadowPosition.xy * 2.0 - 1.0) < 1.0) {
// 28A3DK6 We need to use texelFetch here or a lot of Nvidia GPUs can't get a valid value
shadowSample = texelFetch(shadowtex0, ivec2(shadowPosition.xy * shadowMapResolutionM), 0).x;
shadowSample = clamp((shadowSample-shadowPosition.z)*65536.0,0.0,1.0);
vlSample = vec3(shadowSample);
#ifdef END_FLASH_SHADOW_INTERNAL
vlSample = mix(vec3(1.0), vlSample, endFlashIntensity);
#endif
#if SHADOW_QUALITY >= 1
if (shadowSample == 0.0) {
float testsample = shadow2D(shadowtex1, shadowPosition.xyz).z;
if (testsample == 1.0) {
vec3 colsample = texture2D(shadowcolor1, shadowPosition.xy).rgb * 4.0;
colsample *= colsample;
vlSample = colsample;
shadowSample = 1.0;
#ifdef OVERWORLD
vlSample *= vlColorReducer;
#endif
}
} else {
#ifdef OVERWORLD
// For water-tinting the water surface when observed from below the surface
if (translucentMult != vec3(1.0) && currentDist > depth0) {
vec3 tinter = vec3(1.0);
if (isEyeInWater == 1) {
vec3 translucentMultM = translucentMult * 2.8;
tinter = pow(translucentMultM, vec3(sunVisibility * 3.0 * clamp01(playerPos.y * 0.03)));
} else {
tinter = 0.1 + 0.9 * pow2(pow2(translucentMult * 1.7));
}
vlSample *= mix(vec3(1.0), tinter, clamp01(oceanAltitude - cameraPosition.y));
}
#endif
if (isEyeInWater == 1 && translucentMult == vec3(1.0)) vlSample = vec3(0.0);
}
#endif
}
#endif
if (currentDist > depth0) vlSample *= translucentMult;
#ifdef OVERWORLD
#ifdef LIGHTSHAFT_SMOKE
vec3 smokePos = 0.0015 * (playerPos + cameraPosition);
vec3 smokeWind = frameTimeCounter * vec3(0.0, 0.001, -0.002);
float smoke = 0.65 * Noise3D(smokePos + smokeWind)
+ 0.25 * Noise3D((smokePos - smokeWind) * 3.0)
+ 0.10 * Noise3D((smokePos + smokeWind) * 9.0);
smoke = smoothstep1(smoothstep1(smoothstep1(smoke)));
totalSmoke += smoke * shadowSample * sampleMult;
#endif
vec4 volumetricLightAdd = vec4(vlSample, shadowSample) * sampleMult;
#ifdef OVERWORLD_BEAMS
volumetricLight += volumetricLightAdd * mix(vec4(1.0), overworldBeamSample, overworldBeamSample.a);
#else
volumetricLight += volumetricLightAdd;
#endif
#else
#ifdef END_BEAMS
volumetricLight += vec4(vlSample, shadowSample) * enderBeamSample;
#endif
#endif
}
#ifdef LIGHTSHAFT_SMOKE
volumetricLight *= pow(totalSmoke / volumetricLight.a, min(1.0 - volumetricLight.a, 0.5));
volumetricLight.rgb /= pow(0.5, 1.0 - volumetricLight.a);
#endif
// Decision of Intensity for Scene Aware Light Shafts //
#if defined OVERWORLD && LIGHTSHAFT_BEHAVIOUR == 1 && SHADOW_QUALITY >= 1
if (viewWidth + viewHeight - gl_FragCoord.x - gl_FragCoord.y < 1.5) {
if (frameCounter % int(0.06666 / frameTimeSmooth + 0.5) == 0) { // Change speed is not too different above 10 fps
int salsX = 5;
int salsY = 5;
float heightThreshold = 6.0;
vec2 viewM = 1.0 / vec2(salsX, salsY);
float salsSampleSum = 0.0;
int salsSampleCount = 0;
for (float i = 0.25; i < salsX; i++) {
for (float h = 0.45; h < salsY; h++) {
vec2 coord = 0.3 + 0.4 * viewM * vec2(i, h);
ivec2 icoord = ivec2(coord * shadowMapResolutionM);
float salsSample = texelFetch(shadowtex0, icoord, 0).x; // read 28A3DK6
if (salsSample < 0.55) {
float sampledHeight = texture2D(shadowcolor1, coord).a;
if (sampledHeight > 0.0) {
sampledHeight = max0(sampledHeight - 0.25) / 0.05; // consistencyMEJHRI7DG
salsSampleSum += sampledHeight;
salsSampleCount++;
}
}
}
}
float salsCheck = salsSampleSum / salsSampleCount;
int reduceAmount = 2;
int skyCheck = 0;
for (float i = 0.1; i < 1.0; i += 0.2) {
skyCheck += int(texelFetch(depthtex0, ivec2(view.x * i, view.y * 0.9), 0).x == 1.0);
}
if (skyCheck >= 4) {
salsCheck = 0.0;
reduceAmount = 3;
}
if (salsCheck > heightThreshold) {
vlFactor = min(vlFactor + OSIEBCA, 1.0);
} else {
vlFactor = max(vlFactor - OSIEBCA * reduceAmount, 0.0);
}
}
} else vlFactor = 0.0;
//if (gl_FragCoord.y < 50) color.rgb = vec3(1,0,1) * float(salsCheck / heightThreshold > gl_FragCoord.x / 1920.0);
/*for (float i = 0.25; i < salsX; i++) {
for (float h = 0.45; h < salsY; h++) {
if (length(texCoord - (0.3 + 0.4 * viewM * vec2(i, h))) < 0.01) return vec4(1,0,1,1);
}
}*/
#endif
#ifdef OVERWORLD
vlColor = pow(vlColor, vec3(0.5 + (0.5 + LIGHTSHAFT_SUNSET_SATURATION * sunVisibility) * invNoonFactor * invRainFactor + 0.3 * rainFactor));
vlColor *= 1.0 - (0.3 + 0.3 * noonFactor) * rainFactor - 0.5 * rainyNight + sunVisibility * pow2(invNoonFactor) * invRainFactor;
#if LIGHTSHAFT_DAY_I != 100 || LIGHTSHAFT_NIGHT_I != 100 || LIGHTSHAFT_RAIN_I != 100
#define LIGHTSHAFT_DAY_IM LIGHTSHAFT_DAY_I * 0.01
#define LIGHTSHAFT_NIGHT_IM LIGHTSHAFT_NIGHT_I * 0.01
#define LIGHTSHAFT_RAIN_IM LIGHTSHAFT_RAIN_I * 0.01
if (isEyeInWater == 0) {
#if LIGHTSHAFT_DAY_I != 100 || LIGHTSHAFT_NIGHT_I != 100
vlColor.rgb *= mix(LIGHTSHAFT_NIGHT_IM, LIGHTSHAFT_DAY_IM, sunVisibility);
#endif
#if LIGHTSHAFT_RAIN_I != 100
vlColor.rgb *= mix(1.0, LIGHTSHAFT_RAIN_IM, rainFactor);
#endif
}
#endif
volumetricLight.rgb *= vlColor;
#endif
volumetricLight.rgb *= vlMult;
volumetricLight = max(volumetricLight, vec4(0.0));
#if defined DISTANT_HORIZONS && defined OVERWORLD
if (isEyeInWater == 0) {
float lViewPosM = lViewPos0;
if (z0 >= 1.0) {
float z0DH = texelFetch(dhDepthTex, texelCoord, 0).r;
vec4 screenPosDH = vec4(texCoord, z0DH, 1.0);
vec4 viewPosDH = dhProjectionInverse * (screenPosDH * 2.0 - 1.0);
viewPosDH /= viewPosDH.w;
lViewPosM = length(viewPosDH.xyz);
}
lViewPosM = min(lViewPosM, renderDistance * 0.6);
float dhVlStillIntense = max(max(vlSceneIntensity, rainFactor), nightFactor * 0.5);
volumetricLight *= mix(0.0003 * lViewPosM, 1.0, dhVlStillIntense);
}
#endif
#ifdef END
#ifndef DISTANT_HORIZONS
volumetricLight *= sqrt1(min1(lViewPos1 * 2.0 / 512.0));
#else
volumetricLight *= min1(lViewPos1 * 3.0 / renderDistance);
#endif
#endif
#if RETRO_LOOK == 1
volumetricLight *= vec4(0.0);
#elif RETRO_LOOK == 2
volumetricLight *= mix(vec4(1.0), vec4(0.0), nightVision);
#endif
return volumetricLight;
}