291 lines
13 KiB
GLSL
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;
|
|
}
|