Files
Reimagined/shaderpacks/Reimagined - Low/shaders/lib/materials/materialMethods/reflections.glsl
T
2026-05-07 21:38:27 +03:00

291 lines
13 KiB
GLSL

#include "/lib/misc/reprojection.glsl"
#ifdef OVERWORLD
#include "/lib/atmospherics/sky.glsl"
#include "/lib/shaderSettings/stars.glsl"
#ifdef END_PORTAL_BEAM_INTERNAL
#include "/lib/atmospherics/endPortalBeam.glsl"
#endif
#endif
#ifdef END
#include "/lib/shaderSettings/endBeams.glsl"
#ifdef COMPOSITE
#include "/lib/atmospherics/enderBeams.glsl"
#endif
#if END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0
#include "/lib/atmospherics/endCrystalVortex.glsl"
#endif
#include "/lib/atmospherics/fog/endCenterFog.glsl"
#endif
#ifdef ATM_COLOR_MULTS
#include "/lib/colors/colorMultipliers.glsl"
#endif
#ifdef MOON_PHASE_INF_ATMOSPHERE
#include "/lib/colors/moonPhaseInfluence.glsl"
#endif
#if WORLD_SPACE_REFLECTIONS_INTERNAL > 0 && defined COMPOSITE
#include "/lib/voxelization/lightVoxelization.glsl"
#include "/lib/materials/materialMethods/worldSpaceRef.glsl"
#endif
float GetApproxDistance(float depth) {
return near * far / (far - depth * far);
}
vec3 nvec3(vec4 pos) {
return pos.xyz/pos.w;
}
float refDist = far;
#include "/lib/materials/materialMethods/reflectionBackground.glsl"
vec4 GetReflection(vec3 normalM, vec3 viewPos, vec3 nViewPos, vec3 playerPos, float lViewPos, float z0,
sampler2D depthtex, float dither, float skyLightFactor, float fresnel,
float smoothness, vec3 geoNormal, vec3 color, vec3 shadowMult, float highlightMult, float enderDragonDead, vec2 texelOffset) {
// ============================== Step 1: Prepare ============================== //
#if WORLD_SPACE_REFLECTIONS_INTERNAL == -1
vec2 rEdge = vec2(0.6, 0.55);
#else
vec2 rEdge = vec2(0.525, 0.525);
#endif
vec3 normalMR = normalM;
#if defined PIXELATED_WATER_REFLECTIONS && defined GBUFFERS_WATER
playerPos = TexelSnap(playerPos, texelOffset);
viewPos = TexelSnap(viewPos, texelOffset);
nViewPos = TexelSnap(nViewPos, texelOffset);
lViewPos = TexelSnap(lViewPos, texelOffset);
fresnel = TexelSnap(fresnel, texelOffset);
#endif
#if defined GBUFFERS_WATER && WATER_STYLE == 1 && defined GENERATED_NORMALS
normalMR = normalize(mix(geoNormal, normalM, 0.05));
#endif
vec3 nViewPosR = normalize(reflect(nViewPos, normalMR));
float RVdotU = dot(nViewPosR, upVec);
float RVdotS = dot(nViewPosR, sunVec);
vec3 worldRefDir = 0.5 * far * (mat3(gbufferModelViewInverse) * nViewPosR);
#if defined GBUFFERS_WATER && WATER_STYLE >= 2
normalMR = normalize(mix(geoNormal, normalM, 0.8));
#endif
// ============================== End of Step 1 ============================== //
// ============================== Step 2: Calculate Terrain Reflection and Alpha ============================== //
#if WORLD_SPACE_REFLECTIONS_INTERNAL > 0 && defined COMPOSITE && WATER_REFLECT_QUALITY >= 1
// In COMPOSITE for translucents we just need to return WSR and that's it
if (z0 != z1) {
/*vec4 reflection;
AddBackgroundReflection(reflection, color, playerPos, normalM, normalMR, viewPos, nViewPos, nViewPosR,
shadowMult, RVdotU, RVdotS, z0, dither, skyLightFactor, smoothness, highlightMult);
return reflection;*/
vec4 reflection = getWSR(playerPos, normalMR, nViewPosR, RVdotU, RVdotS, z0, dither);
refDist = length(playerPos - wsrHitPos);
return reflection;
}
#endif
vec4 reflection = vec4(0.0);
vec3 refPos = vec3(0.0);
vec3 reflectionColor = vec3(0.0);
#if (defined COMPOSITE || WATER_REFLECT_QUALITY >= 1) && (WORLD_SPACE_REFLECTIONS_INTERNAL == -1 || WORLD_SPACE_REF_MODE == 2)
#if defined COMPOSITE || WATER_REFLECT_QUALITY >= 2 && !defined DH_WATER
// Method 1: Ray Marched Reflection //
// Ray Marching
vec3 start = viewPos + normalMR * (lViewPos * 0.025 * (1.0 - fresnel) + 0.05);
#if defined GBUFFERS_WATER && WATER_STYLE >= 2
vec3 vector = normalize(reflect(nViewPos, normalMR)); // Not using nViewPosR because normalMR changed
#else
vec3 vector = nViewPosR;
#endif
//vector = normalize(vector - 0.5 * (1.0 - smoothness) * (1.0 - fresnel) * normalMR); // reflection anisotropy test
//vector = normalize(vector - 0.075 * dither * (1.0 - pow2(pow2(fresnel))) * normalMR);
vector *= 0.5;
vec3 vectorBase = vector;
vec3 viewPosRT = viewPos + vector;
vec3 tvector = vector;
#if WORLD_SPACE_REFLECTIONS_INTERNAL == -1
int sampleCount = 30;
int refinementCount = 6;
#else
int sampleCount = 38;
int refinementCount = 10;
#endif
int sr = 0;
float dist = 0.0;
vec3 rfragpos = vec3(0.0);
float err = 9999999.0;
for (int i = 0; i < sampleCount; i++) {
refPos = nvec3(gbufferProjection * vec4(viewPosRT, 1.0)) * 0.5 + 0.5;
if (abs(refPos.x - 0.5) > rEdge.x || abs(refPos.y - 0.5) > rEdge.y) break;
rfragpos = vec3(refPos.xy, texture2D(depthtex, refPos.xy).r);
rfragpos = nvec3(gbufferProjectionInverse * vec4(rfragpos * 2.0 - 1.0, 1.0));
dist = length(start - rfragpos);
err = length(viewPosRT - rfragpos);
if (err * 0.33333 < length(vector)) {
sr++;
if (sr >= refinementCount) break;
tvector -= vector;
vector *= 0.1;
}
vector *= 2.0;
tvector += vector * (0.95 + 0.1 * dither);
viewPosRT = start + tvector;
}
float lViewPosRT = length(rfragpos);
// Finalizing Terrain Reflection and Alpha
if (
refPos.z < 0.99997
#if WORLD_SPACE_REFLECTIONS_INTERNAL > 0 && COLORED_LIGHTING_INTERNAL >= 256
&& (err < 2.0 + pow2(lViewPosRT) * 0.001 || lViewPosRT > 0.25 * COLORED_LIGHTING_INTERNAL)
#endif
) {
vec2 absPos = abs(refPos.xy - 0.5);
vec2 cdist = absPos / rEdge;
float border = clamp(1.0 - pow(max(cdist.x, cdist.y), 50.0), 0.0, 1.0);
reflection.a = border;
if (reflection.a > 0.001) {
vec2 edgeFactor = pow2(pow2(pow2(cdist)));
#if WORLD_SPACE_REFLECTIONS_INTERNAL == -1
refPos.y += (dither - 0.5) * (0.05 * (edgeFactor.x + edgeFactor.y));
#endif
#ifdef GBUFFERS_WATER
reflection = texture2D(gaux2, refPos.xy);
reflection.rgb = pow2(reflection.rgb * 2.0);
#else
float smoothnessDM = pow2(smoothness);
float lodFactor = 1.0 - exp(-0.125 * (1.0 - smoothnessDM) * dist);
float lod = log2(viewHeight / 8.0 * (1.0 - smoothnessDM) * lodFactor) * 0.45;
if (z0 <= 0.56) lod *= 2.22; // Using more lod to compensate for less roughness noise on held items
lod = max(lod - 1.0, 0.0);
reflection.rgb = texture2DLod(colortex0, refPos.xy, lod).rgb;
reflectionColor = reflection.rgb;
#endif
float skyFade = 0.0;
#ifdef GBUFFERS_WATER
float reflectionPrevAlpha = reflection.a;
DoFog(reflection, skyFade, lViewPosRT, ViewToPlayer(rfragpos.xyz), RVdotU, RVdotS, dither, true, lViewPos);
reflection.a = reflectionPrevAlpha;
//reflection.a *= 1.0 - skyFade;
#endif
edgeFactor.x = pow2(edgeFactor.x);
edgeFactor = 1.0 - edgeFactor;
float refFactor = pow(edgeFactor.x * edgeFactor.y, 2.0 + 3.0 * GetLuminance(reflection.rgb));
#if WORLD_SPACE_REFLECTIONS_INTERNAL > 0 && defined GBUFFERS_WATER
refFactor = min(refFactor, 0.1) * 10.0;
#endif
reflection.a *= refFactor;
refDist = dist;
}
float posDif = lViewPosRT - lViewPos;
reflection.a *= clamp(posDif + 3.0, 0.0, 1.0);
}
#if !defined COMPOSITE && defined DISTANT_HORIZONS
else
#endif
#endif
#if !defined COMPOSITE && (WATER_REFLECT_QUALITY < 2 || defined DISTANT_HORIZONS) || defined DH_WATER
{ // Method 2: Mirorred Image Reflection //
#if WATER_REFLECT_QUALITY < 2 && !defined DISTANT_HORIZONS
float verticalStretch = 0.013; // for potato quality reflections
#else
float verticalStretch = 0.0025; // for distant horizons reflections
#endif
vec4 clipPosR = gbufferProjection * vec4(nViewPosR + verticalStretch * viewPos, 1.0);
vec3 screenPosR = clipPosR.xyz / clipPosR.w * 0.5 + 0.5;
vec2 screenPosRM = abs(screenPosR.xy - 0.5);
if (screenPosRM.x < rEdge.x && screenPosRM.y < rEdge.y) {
vec2 edgeFactor = pow2(pow2(pow2(screenPosRM / rEdge)));
screenPosR.y += (dither - 0.5) * (0.03 * (edgeFactor.x + edgeFactor.y) + 0.004);
float z1R = texture2D(depthtex1, screenPosR.xy).x;
screenPosR.z = z1R;
vec3 viewPosR = ScreenToView(screenPosR);
float lViewPosR = length(viewPosR);
#ifdef DISTANT_HORIZONS
float z1RDH = texture2D(dhDepthTex, screenPosR.xy).x;
vec4 screenPos1DH = vec4(screenPosR.xy, z1RDH, 1.0);
vec4 viewPos1DH = dhProjectionInverse * (screenPos1DH * 2.0 - 1.0);
viewPos1DH /= viewPos1DH.w;
lViewPosR = min(lViewPosR, length(viewPos1DH.xyz));
z1R = min(z1R, z1RDH);
#endif
if (z1R < 0.9997 && lViewPos <= 2.0 + lViewPosR) {
reflection.rgb = texture2D(gaux2, screenPosR.xy).rgb;
reflection.rgb = pow2(reflection.rgb * 2.0);
edgeFactor = 1.0 - edgeFactor;
reflection.a = edgeFactor.x * pow2(edgeFactor.y);
reflection.a *= clamp01((dot(nViewPos, nViewPosR) - 0.45) * 10.0); // Fixes perpendicular ref bug
#ifdef BORDER_FOG
float fog = lViewPosR / renderDistance;
fog = pow2(pow2(fog));
#ifndef DISTANT_HORIZONS
fog = pow2(pow2(fog));
#endif
reflection.a *= exp(-3.0 * fog);
#endif
}
}
}
#endif
#endif
// ============================== End of Step 2 ============================== //
// ============================== Step 3: Add Sky or WSR Reflection ============================== //
#if defined COMPOSITE || WATER_REFLECT_QUALITY >= 1
if (reflection.a < 1.0)
#endif
{
AddBackgroundReflection(reflection, color, playerPos, normalM, normalMR, viewPos, nViewPos, nViewPosR,
shadowMult, RVdotU, RVdotS, z0, dither, skyLightFactor, smoothness, highlightMult);
}
// ============================== End of Step 3 ============================== //
#if (defined COMPOSITE || (WATER_REFLECT_QUALITY >= 2 && defined SKY_EFFECT_REFLECTION)) && (END_CRYSTAL_VORTEX_INTERNAL > 0 || DRAGON_DEATH_EFFECT_INTERNAL > 0)
reflection.rgb += EndCrystalVortices(playerPos, worldRefDir, dither).rgb;
#endif
#if (defined COMPOSITE || (WATER_REFLECT_QUALITY >= 2 && defined SKY_EFFECT_REFLECTION)) && defined END_PORTAL_BEAM_INTERNAL && !defined DH_WATER
vec4 refPosPlayer = gbufferModelViewInverse * (gbufferProjectionInverse * vec4(refPos * 2.0 - 1.0, 1.0));
refPosPlayer /= refPosPlayer.w;
reflection.rgb += sqrt(GetEndPortalBeam(playerPos, refPosPlayer.xyz * reflection.a - playerPos).rgb);
#endif
#if (defined COMPOSITE || WATER_REFLECT_QUALITY >= 2) && (WORLD_SPACE_REFLECTIONS_INTERNAL == -1 || WORLD_SPACE_REF_MODE == 2) && defined END && END_CENTER_LIGHTING > 0 && MC_VERSION >= 10900 && !defined DH_WATER
if (reflection.a < 1.0) {
float attentuation = doEndCenterFog(playerPos + cameraPositionBest, worldRefDir.xyz, length(viewPosRT - start), 0.07);
vec3 pointLightFog = vec3(END_CENTER_LIGHTING_R, END_CENTER_LIGHTING_G + 0.05, END_CENTER_LIGHTING_B) * 0.355 * END_CENTER_LIGHTING * attentuation * enderDragonDead;
reflection.rgb += sqrt(clamp01(pointLightFog - reflectionColor));
}
#endif
return reflection;
}