391 lines
17 KiB
GLSL
391 lines
17 KiB
GLSL
#extension GL_ARB_shader_image_load_store : enable
|
|
|
|
#include "/lib/voxelization/reflectionVoxelization.glsl"
|
|
#include "/lib/lighting/minimumLighting.glsl"
|
|
#include "/lib/shaderSettings/mainLighting.glsl"
|
|
|
|
#if WORLD_SPACE_PLAYER_REF == 1
|
|
#include "/lib/materials/materialMethods/playerRayTracer.glsl"
|
|
#endif
|
|
|
|
#ifdef AURORA_INFLUENCE
|
|
#include "/lib/atmospherics/auroraBorealis.glsl"
|
|
#endif
|
|
|
|
#if defined OVERWORLD || defined END
|
|
#ifndef GBUFFERS_WATER
|
|
#include "/lib/lighting/shadowSampling.glsl"
|
|
#if defined DO_PIXELATION_EFFECTS && defined PIXELATED_SHADOWS
|
|
#include "/lib/misc/pixelation.glsl"
|
|
#endif
|
|
#endif
|
|
|
|
#if SHADOW_SMOOTHING == 4 || SHADOW_QUALITY == 0
|
|
const float offset = 0.00098;
|
|
#elif SHADOW_SMOOTHING == 3
|
|
const float offset = 0.00075;
|
|
#elif SHADOW_SMOOTHING == 2
|
|
const float offset = 0.0005;
|
|
#elif SHADOW_SMOOTHING == 1
|
|
const float offset = 0.0003;
|
|
#endif
|
|
#endif
|
|
|
|
#if HELD_LIGHTING_MODE >= 1
|
|
#include "/lib/lighting/heldLighting.glsl"
|
|
#endif
|
|
|
|
#ifdef CLOUD_SHADOWS
|
|
#include "/lib/lighting/cloudShadows.glsl"
|
|
#endif
|
|
|
|
#ifdef LIGHT_COLOR_MULTS
|
|
#include "/lib/colors/colorMultipliers.glsl"
|
|
#endif
|
|
#ifdef MOON_PHASE_INF_LIGHT
|
|
#include "/lib/colors/moonPhaseInfluence.glsl"
|
|
#endif
|
|
|
|
vec2 getLocalTexCoord(vec3 local, vec3 normal) {
|
|
vec3 absNormal = abs(normal);
|
|
return 1.0 - local.zy * absNormal.x - local.xz * absNormal.y - local.xy * absNormal.z;
|
|
}
|
|
|
|
float getVoxelSpaceAO(vec3 playerPos, ivec3 normal, vec2 localTexCoord) {
|
|
ivec3 voxelPos = ivec3(playerToSceneVoxel(playerPos + normal * 0.5));
|
|
ivec3 absNormal = ivec3(abs(normal));
|
|
ivec3 right = ivec3(0, 0, 1) * absNormal.x + ivec3(1, 0, 0) * absNormal.y + ivec3(1, 0, 0) * absNormal.z;
|
|
ivec3 up = ivec3(0, 1, 0) * absNormal.x + ivec3(0, 0, 1) * absNormal.y + ivec3(0, 1, 0) * absNormal.z;
|
|
|
|
vec2 centerFactorPos = sqrt1(2.0 * clamp01(0.5 - localTexCoord));
|
|
vec2 centerFactorNeg = sqrt1(2.0 * clamp01(localTexCoord - 0.5));
|
|
ivec3 voxel0 = voxelPos + right;
|
|
ivec3 voxel1 = voxelPos - right;
|
|
ivec3 voxel2 = voxelPos + up;
|
|
ivec3 voxel3 = voxelPos - up;
|
|
|
|
float occlusion0 = mix(0.0, float(checkVoxelAt(voxel0)), centerFactorPos.x);
|
|
float occlusion1 = mix(0.0, float(checkVoxelAt(voxel1)), centerFactorNeg.x);
|
|
float occlusion2 = mix(0.0, float(checkVoxelAt(voxel2)), centerFactorPos.y);
|
|
float occlusion3 = mix(0.0, float(checkVoxelAt(voxel3)), centerFactorNeg.y);
|
|
|
|
return 1.0 - (occlusion0 + occlusion1 + occlusion2 + occlusion3) * 0.25;
|
|
}
|
|
|
|
vec4 getShadedReflection(ivec3 voxelPos, vec3 oldPlayerPos, vec3 playerPos, vec3 rayDir, vec3 normal, float dither) {
|
|
faceData faceData = getFaceData(voxelPos, normal);
|
|
if (faceData.textureBounds.z < 1e-6) return vec4(-1.0);
|
|
|
|
vec2 localTexCoord = getLocalTexCoord(fract(playerPos + cameraPositionBestFract), normal);
|
|
|
|
vec2 textureSizeAtlas = textureSize(textureAtlas, 0);
|
|
vec2 textureRadVec2 = faceData.textureBounds.z * vec2(1.0, textureSizeAtlas.x / textureSizeAtlas.y);
|
|
vec2 textureCoord = faceData.textureBounds.xy + 2.0 * textureRadVec2 * localTexCoord;
|
|
|
|
float virtualDist = length(playerPos - oldPlayerPos) + length(oldPlayerPos);
|
|
float textureFactor = length(textureRadVec2 * textureSizeAtlas) * 3.0;
|
|
float lod = 0.5 * log2(virtualDist * textureFactor / gbufferProjection[0][0] / abs(dot(normal, rayDir)) / viewHeight / REFLECTION_RES);
|
|
|
|
vec4 color = texture2DLod(textureAtlas, textureCoord, lod) * vec4(faceData.glColor, 1.0);
|
|
|
|
#if MC_VERSION >= 12111 && IRIS_VERSION < 11005
|
|
// stupid fake lods because custom texture lods broke with Iris in newer mc versions
|
|
vec2 lodCoordSpan = localTexCoord / pow(2.0, int(1.5 + pow2(max0(lod)) + 0.0 * dither));
|
|
|
|
vec2 lodCoord1 = faceData.textureBounds.xy + 2.0 * textureRadVec2 * (0.5 + lodCoordSpan);
|
|
vec2 lodCoord2 = faceData.textureBounds.xy + 2.0 * textureRadVec2 * (0.25 + lodCoordSpan);
|
|
vec2 lodCoord3 = faceData.textureBounds.xy + 2.0 * textureRadVec2 * lodCoordSpan;
|
|
vec4 lodColor1 = texture2DLod(textureAtlas, lodCoord1, lod) * vec4(faceData.glColor, 1.0);
|
|
vec4 lodColor2 = texture2DLod(textureAtlas, lodCoord2, lod) * vec4(faceData.glColor, 1.0);
|
|
vec4 lodColor3 = texture2DLod(textureAtlas, lodCoord3, lod) * vec4(faceData.glColor, 1.0);
|
|
|
|
float lodMix = clamp01(lod - 0.75 + 0.25 * dither);
|
|
color = mix(color, 0.333333 * (lodColor1 + lodColor2 + lodColor3), lodMix);
|
|
if (dot(color.rgb, vec3(0.333333)) - 0.5 < 0.49) color.a = mix(color.a, 1.0, lodMix);
|
|
//
|
|
#endif
|
|
|
|
if (color.a < 0.0041) return vec4(-1.0); // Note that the cutout parts of leaves have a color.a of about 0.004
|
|
|
|
int mat = int(texelFetch(wsr_sampler, voxelPos, 0).r);
|
|
|
|
bool noSmoothLighting = false, noDirectionalShading = false, isFoliage = false;
|
|
int subsurfaceMode = 0;
|
|
float emission = 0.0, NdotU = normal.y, NdotE = normal.x, snowMinNdotU = 0.0;
|
|
vec2 lmCoordM = vec2(1.0);
|
|
vec3 shadowMult = vec3(1.0), maRecolor = vec3(0.0);
|
|
float skyLightCheck = 0.0;
|
|
float overlayNoiseIntensity = 1.0, snowNoiseIntensity = 1.0, sandNoiseIntensity = 1.0, mossNoiseIntensity = 1.0, overlayNoiseTransparentOverwrite = 0.0, overlayNoiseEmission = 1.0, lavaNoiseIntensity = LAVA_NOISE_INTENSITY;
|
|
vec3 normalM = normal, geoNormal = normal;
|
|
#ifdef IPBR
|
|
float lViewPos = length(playerPos);
|
|
vec4 glColor = vec4(faceData.glColor, 1.0);
|
|
vec2 absMidCoordPos = vec2(textureRadVec2);
|
|
vec2 midCoord = faceData.textureBounds.xy + 2.0 * textureRadVec2 * vec2(0.5);
|
|
vec2 signMidCoordPos = localTexCoord * 2.0 - 1.0;
|
|
bool noVanillaAO = false, centerShadowBias = false, noGeneratedNormals = false, doTileRandomisation = true;
|
|
float smoothnessD = 0.0, materialMask = 0.0;
|
|
float smoothnessG = 0.0, highlightMult = 1.0, noiseFactor = 1.0, snowFactor = 1.0, noPuddles = 0.0;
|
|
vec2 lmCoord = faceData.lightmap;
|
|
float IPBRMult = 1.0;
|
|
|
|
#define DURING_WORLDSPACE_REF
|
|
#ifndef IPBR_COMPAT_MODE
|
|
#define IPBR_COMPAT_MODE
|
|
#endif
|
|
#undef DISTANT_LIGHT_BOKEH
|
|
#include "/lib/materials/materialHandling/terrainIPBR.glsl"
|
|
#undef DURING_WORLDSPACE_REF
|
|
#else
|
|
if (mat == 10007 || mat == 10009 || mat == 10011) { // Leaves
|
|
#include "/lib/materials/specificMaterials/terrain/leaves.glsl"
|
|
}
|
|
#endif
|
|
|
|
float NdotL = dot(normal, mat3(gbufferModelViewInverse) * lightVec);
|
|
#ifdef SIDE_SHADOWING
|
|
float lightingNdotL = max0(NdotL + 0.4) * 0.714;
|
|
|
|
#ifdef END
|
|
lightingNdotL = sqrt3(lightingNdotL);
|
|
#endif
|
|
#else
|
|
float lightingNdotL = max0(NdotL);
|
|
#endif
|
|
|
|
#ifndef NETHER
|
|
vec3 shadow = shadowMult;
|
|
if (lightingNdotL > 0.0001) {
|
|
float shadowLength = shadowDistance * 0.9166667 - length(playerPos); //consistent08JJ622
|
|
if (shadowLength > 0.000001) {
|
|
float distanceBias = 0.12 + 0.0008 * pow(dot(playerPos, playerPos), 0.75);
|
|
vec3 bias = normal * distanceBias * (2.0 - 0.95 * max0(NdotL));
|
|
|
|
#if SHADOW_QUALITY == 0
|
|
int shadowSamples = 0; // We don't use SampleTAAFilteredShadow on Shadow Quality 0
|
|
#elif SHADOW_QUALITY == 1
|
|
int shadowSamples = 1;
|
|
#else
|
|
int shadowSamples = 2;
|
|
#endif
|
|
shadow = GetShadow(GetShadowPos(playerPos + bias), faceData.lightmap.y, offset, shadowSamples, false);
|
|
}
|
|
}
|
|
shadow *= dot(shadow, vec3(0.33333));
|
|
#else
|
|
vec3 shadow = vec3(1.0);
|
|
#endif
|
|
|
|
#ifdef CLOUD_SHADOWS
|
|
shadow *= GetCloudShadow(playerPos);
|
|
#endif
|
|
|
|
faceData.lightmap = pow2(pow2(faceData.lightmap));
|
|
float AO = max(0.8, getVoxelSpaceAO(playerPos, ivec3(normal), localTexCoord));
|
|
float directionalShading = noDirectionalShading ? 1.0 : (NdotU + 1.0) * 0.25 + 0.5;
|
|
|
|
vec3 centerPlayerPos = floor(playerPos + cameraPosition + normal * 0.01) - cameraPosition + 0.5;
|
|
vec3 playerPosM = mix(centerPlayerPos, playerPos, (AO - 0.8) / 0.2);
|
|
vec3 voxelPosM = SceneToVoxel(playerPosM);
|
|
voxelPosM = clamp01(voxelPosM / vec3(voxelVolumeSize));
|
|
vec4 lightVolume = GetLightVolume(voxelPosM);
|
|
lightVolume = max(lightVolume, vec4(0.000001));
|
|
vec3 specialLighting = 0.8 * pow(GetLuminance(lightVolume.rgb), 0.25) * DoLuminanceCorrection(pow(lightVolume.rgb, vec3(0.3)));
|
|
if (noSmoothLighting == true) specialLighting *= 0.6;
|
|
|
|
vec3 minLighting = 0.8 * sqrt(GetMinimumLighting(faceData.lightmap.y, playerPos));
|
|
|
|
#if HELD_LIGHTING_MODE >= 1
|
|
vec3 heldLighting = GetHeldLighting(playerPos, color.rgb, emission, geoNormal, normalM, vec3(0));
|
|
specialLighting = sqrt(pow2(specialLighting) + sqrt(heldLighting));
|
|
#endif
|
|
|
|
#ifdef AURORA_INFLUENCE
|
|
ambientColor = getAuroraAmbientColor(ambientColor, rayDir, 0.035, AURORA_TERRAIN_INFLUENCE_INTENSITY, 0.9);
|
|
#endif
|
|
|
|
#ifdef OVERWORLD
|
|
float ambientMult = 0.9 * faceData.lightmap.y;
|
|
float lightMult = (1.1 + 0.25 * subsurfaceMode) * lightingNdotL * shadowTime;
|
|
lightMult *= 1.0 + abs(NdotE) * 0.25;
|
|
specialLighting *= 1.0 - faceData.lightmap.y * sunFactor;
|
|
#else
|
|
float ambientMult = 1.0;
|
|
float lightMult = 1.0 * lightingNdotL * shadowTime;
|
|
#endif
|
|
|
|
vec3 sceneLighting = ambientMult * ambientColor + lightMult * lightColor * shadow;
|
|
#ifdef LIGHT_COLOR_MULTS
|
|
lightColorMult = GetLightColorMult();
|
|
sceneLighting *= lightColorMult;
|
|
#endif
|
|
#ifdef MOON_PHASE_INF_LIGHT
|
|
sceneLighting *= moonPhaseInfluence;
|
|
#endif
|
|
|
|
vec3 lighting = sceneLighting + specialLighting * XLIGHT_I + minLighting;
|
|
lighting = lighting * AO * directionalShading + emission * 0.8;
|
|
|
|
vec3 fadeout = smoothstep(0.0, 32.0, 0.5 * sceneVoxelVolumeSize - abs(playerPos));
|
|
fadeout = sqrt3(fadeout) * 0.9 + 0.1;
|
|
float alphaFade = min(fadeout.x, min(fadeout.y, fadeout.z));
|
|
|
|
return vec4(color.rgb * lighting + maRecolor, alphaFade);
|
|
}
|
|
|
|
vec3 wsrHitPos = vec3(-100000);
|
|
|
|
vec4 traceHighLOD(vec3 rayDir, vec3 stepDir, vec3 stepSizes, vec3 oldPlayerPos, vec3 newPlayerPos, vec3 voxelPos, float RVdotU, float RVdotS, float dither) {
|
|
vec3 nextDist = (stepDir * 0.5 + 0.5 - fract(voxelPos)) / rayDir;
|
|
float closestDist = 0.0;
|
|
|
|
const float maxSteps = 14;
|
|
for (int i = 0; i < maxSteps; i++) {
|
|
closestDist = min(nextDist.x, min(nextDist.y, nextDist.z));
|
|
vec3 stepAxis = vec3(lessThanEqual(nextDist, vec3(closestDist)));
|
|
voxelPos += stepAxis * stepDir;
|
|
nextDist += stepAxis * stepSizes;
|
|
|
|
if (!CheckInsideSceneVoxelVolume(voxelPos)) return vec4(0.0);
|
|
|
|
if (checkVoxelAt(ivec3(voxelPos))) {
|
|
vec3 normal = -stepAxis * stepDir;
|
|
vec3 intersection = newPlayerPos + rayDir * closestDist;
|
|
vec4 reflection = getShadedReflection(ivec3(voxelPos), oldPlayerPos, intersection, rayDir, normal, dither);
|
|
if (reflection.a < -0.5) continue;
|
|
|
|
wsrHitPos = intersection;
|
|
|
|
vec3 fadeout = smoothstep(0.0, 32.0, 0.5 * sceneVoxelVolumeSize - abs(oldPlayerPos));
|
|
fadeout = sqrt3(fadeout) * 0.9 + 0.1;
|
|
reflection *= min(fadeout.x, min(fadeout.y, fadeout.z));
|
|
|
|
float skyFade = 0.0;
|
|
float reflectionPrevAlpha = reflection.a;
|
|
|
|
DoFog(reflection, skyFade, length(intersection), intersection, RVdotU, RVdotS, dither, true, length(oldPlayerPos));
|
|
|
|
reflection.a = reflectionPrevAlpha * (1.0 - skyFade);
|
|
|
|
return reflection;
|
|
}
|
|
}
|
|
|
|
return vec4(-1.0);
|
|
}
|
|
|
|
vec4 traceLowLOD(vec3 rayDir ,vec3 stepDir, vec3 stepSizes, vec3 playerPos, vec3 voxelPos, vec3 normalOffset, float RVdotU, float RVdotS, float dither) {
|
|
float lodScale = 4.0;
|
|
vec3 lodVoxelPos = voxelPos / lodScale;
|
|
|
|
vec3 nextDist = (stepDir * 0.5 + 0.5 - fract(lodVoxelPos)) / rayDir;
|
|
float closestDistPrevious = 0.0;
|
|
float closestDist = 0.0;
|
|
|
|
float maxSteps = length(vec3(sceneVoxelVolumeSize)) / lodScale;
|
|
for (int i = 0; i < maxSteps; i++) {
|
|
if (any(greaterThan(lodVoxelPos, vec3(sceneVoxelVolumeSize) / lodScale)) || any(lessThan(lodVoxelPos, vec3(0.0))))
|
|
return vec4(0.0);
|
|
|
|
if (checkLodVoxelAt(ivec3(lodVoxelPos))) {
|
|
vec3 newPlayerPos = playerPos + rayDir * closestDistPrevious * lodScale;
|
|
|
|
// Fixes surfaces reflecting themselves at a distance with lower resolutions, but it can cause some rare artifacts
|
|
if (i <= 2) newPlayerPos += normalOffset * 0.06;
|
|
|
|
vec3 newVoxelPos = playerToSceneVoxel(newPlayerPos);
|
|
vec4 try = traceHighLOD(rayDir, stepDir, stepSizes, playerPos, newPlayerPos, newVoxelPos, RVdotU, RVdotS, dither);
|
|
if (try.a > -0.5) return try;
|
|
}
|
|
|
|
closestDistPrevious = closestDist;
|
|
closestDist = min(nextDist.x, min(nextDist.y, nextDist.z));
|
|
vec3 stepAxis = vec3(lessThanEqual(nextDist, vec3(closestDist)));
|
|
lodVoxelPos += stepAxis * stepDir;
|
|
nextDist += stepAxis * stepSizes;
|
|
}
|
|
|
|
return vec4(0.0);
|
|
}
|
|
|
|
vec4 getWSR(vec3 playerPos, vec3 normalMR, vec3 nViewPosR, float RVdotU, float RVdotS, float z0, float dither) {
|
|
vec3 normalOffset = normalize(mat3(gbufferModelViewInverse) * normalMR);
|
|
vec3 voxelPos = playerToSceneVoxel(playerPos);
|
|
|
|
// Fixes slabs, stairs, dirt paths, and farmlands reflecting themselves
|
|
if (z0 == z1 && z0 > 0.56) {
|
|
vec3 playerPosFractAdded = playerPos + cameraPositionBestFract + 256.0;
|
|
vec3 normalOffsetM = normalOffset * (0.04 - 0.01 * dither);
|
|
ivec3 voxelPosCheck1 = ivec3(playerPosFractAdded - normalOffsetM);
|
|
ivec3 voxelPosCheck2 = ivec3(playerPosFractAdded + normalOffsetM);
|
|
if (voxelPosCheck1 == voxelPosCheck2) playerPos += normalOffset * 0.5;
|
|
}
|
|
|
|
vec3 rayDir = mat3(gbufferModelViewInverse) * nViewPosR;
|
|
|
|
if (CheckInsideSceneVoxelVolume(voxelPos)) {
|
|
vec3 stepDir = sign(rayDir);
|
|
vec3 stepSizes = 1.0 / abs(rayDir);
|
|
vec4 wsrResult = traceLowLOD(rayDir, stepDir, stepSizes, playerPos, voxelPos, normalOffset, RVdotU, RVdotS, dither);
|
|
|
|
#if WORLD_SPACE_PLAYER_REF == 1
|
|
if (!is_invisible && z0 > 0.56) {
|
|
float wsrTraceLength = length(wsrHitPos - playerPos);
|
|
vec3 albedo;
|
|
vec3 normal;
|
|
float emission;
|
|
|
|
#ifdef SPACEAGLE17
|
|
if (isSneaking < 0.5 || !(heldItemId == 45014 || heldItemId2 == 45014))
|
|
#endif
|
|
if (rayTracePlayer(playerPos - 0.01 * rayDir, rayDir, wsrTraceLength, albedo, normal, emission)) {
|
|
vec2 lmCoord = eyeBrightness / 240.0;
|
|
|
|
#ifdef OVERWORLD
|
|
float ambientMult = 1.5 * lmCoord.y;
|
|
float lightMult = 0.2 * pow2(pow2(lmCoord.y));
|
|
#else
|
|
float ambientMult = 1.5;
|
|
float lightMult = 0.0;
|
|
#endif
|
|
|
|
vec3 voxelPosM = SceneToVoxel(vec3(0.0));
|
|
voxelPosM = clamp01(voxelPosM / vec3(voxelVolumeSize));
|
|
vec4 lightVolume = GetLightVolume(voxelPosM);
|
|
lightVolume = max(lightVolume, vec4(0.000001));
|
|
vec3 specialLighting = pow(GetLuminance(lightVolume.rgb), 0.25) * DoLuminanceCorrection(pow(lightVolume.rgb, vec3(0.25)));
|
|
|
|
#if HELD_LIGHTING_MODE >= 1
|
|
float tempEmission;
|
|
vec3 heldLighting = GetHeldLighting(playerPos, vec3(999999.0), tempEmission, vec3(0), vec3(0), vec3(0));
|
|
specialLighting = sqrt(pow2(specialLighting) + sqrt(heldLighting));
|
|
#endif
|
|
|
|
vec3 minLighting = 0.8 * sqrt(GetMinimumLighting(lmCoord.y, playerPos));
|
|
|
|
vec3 sceneLighting = ambientMult * ambientColor + lightMult * lightColor;
|
|
#ifdef LIGHT_COLOR_MULTS
|
|
lightColorMult = GetLightColorMult();
|
|
sceneLighting *= lightColorMult;
|
|
#endif
|
|
#ifdef MOON_PHASE_INF_LIGHT
|
|
sceneLighting *= moonPhaseInfluence;
|
|
#endif
|
|
|
|
vec3 lighting = sceneLighting + specialLighting * (1.0 - lmCoord.y * sunFactor) * XLIGHT_I + minLighting + emission;
|
|
|
|
vec3 fadeout = smoothstep(0.0, 32.0, 0.5 * sceneVoxelVolumeSize - abs(playerPos));
|
|
fadeout = sqrt3(fadeout) * 0.9 + 0.1;
|
|
float alphaFade = min(fadeout.x, min(fadeout.y, fadeout.z));
|
|
|
|
return vec4(albedo * lighting, alphaFade);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return wsrResult;
|
|
}
|
|
|
|
return vec4(0.0);
|
|
}
|