first commit

This commit is contained in:
Leonid Pershin
2026-05-07 21:38:27 +03:00
commit 84fb173ea8
3949 changed files with 564326 additions and 0 deletions
@@ -0,0 +1,74 @@
/*
This file is specifically licensed with Mozilla Public License Version 2.0.
You can get a copy from https://www.mozilla.org/MPL/2.0/
*/
float manualDeterminant(mat2 matrix) {
return matrix[0].x * matrix[1].y - matrix[0].y * matrix[1].x;
}
mat2 inverseM(mat2 m) {
#if MC_VERSION >= 11700
return inverse(m);
#else
mat2 adj;
adj[0][0] = m[1][1];
adj[0][1] = -m[0][1];
adj[1][0] = -m[1][0];
adj[1][1] = m[0][0];
return adj / manualDeterminant(m);
#endif
}
vec4 textureAF(sampler2D texSampler, vec2 uv) {
vec2 spriteDimensions = vec2(spriteBounds.z - spriteBounds.x, spriteBounds.w - spriteBounds.y);
mat2 J = inverseM(mat2(dFdx(uv), dFdy(uv)));
J = transpose(J)*J;
float d = manualDeterminant(J), t = J[0][0]+J[1][1],
D = sqrt(abs(t*t-4.001*d)), // using 4.001 instead of 4.0 fixes a rare texture glitch with square texture atlas
V = (t-D)/2.0, v = (t+D)/2.0,
M = 1.0/sqrt(V), m = 1./sqrt(v);
vec2 A = M * normalize(vec2(-J[0][1], J[0][0]-V));
float lod = 0.0;
#if ANISOTROPIC_FILTER >= 8 && defined GBUFFERS_TERRAIN
#if MC_VERSION < 12111
// Excluding cutout blocks because cutout mipmaps suck in older mc versions
if (texture2DLod(texSampler, uv, 10000.0).a == 1.0)
#endif
// Fix257062 - Checking if absMidCoordPos is fine or else miplevel will be broken. This can be an issue for flowing lava.
if (absMidCoordPos.x > 0.0001 && absMidCoordPos.y > 0.0001)
lod = miplevel * 0.4;
#endif
float samplesDiv2 = ANISOTROPIC_FILTER / 2.0;
vec2 ADivSamples = A / ANISOTROPIC_FILTER;
vec4 filteredColor = vec4(0.0);
float totalModifiedAlpha = 0.0;
vec4 spriteBoundsM = mix(spriteBounds, vec4(midCoord, midCoord), 0.0001); // Fixes some mods causing issues with cutout blocks
for (float i = -samplesDiv2 + 0.5; i < samplesDiv2; i++) {
vec2 sampleUV = uv + ADivSamples * i;
sampleUV = clamp(sampleUV, spriteBoundsM.xy, spriteBoundsM.zw);
vec4 colorSample = texture2DLod(texSampler, sampleUV, lod);
colorSample.a = sqrt(colorSample.a); // Tweak to make cutout blocks look fuller in the distance
#if !defined POM || !defined POM_ALLOW_CUTOUT
float modifiedAlpha = colorSample.a;
#else
// To avoid NaNs because we don't discard low alpha if POM_ALLOW_CUTOUT is enabled (see 6WIR4HT23)
float modifiedAlpha = max(colorSample.a, 0.00001);
#endif
totalModifiedAlpha += modifiedAlpha;
filteredColor.rgb += colorSample.rgb * modifiedAlpha;
filteredColor.a += colorSample.a;
}
filteredColor.rgb /= totalModifiedAlpha;
filteredColor.a /= ANISOTROPIC_FILTER;
return filteredColor;
}
@@ -0,0 +1,33 @@
#define ENTITY_GN_AND_CT
#define COATED_TEXTURE_MULT 100 //[25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 110 120 130 140 150 160 170 180 190 200]
#define COATED_TEXTURE_RES 64 //[16 32 64 80 96 112 128 144 160 176 192 208 224 240 256 320 384 448 512]
const float packSizeNT = COATED_TEXTURE_RES;
void CoatTextures(inout vec3 color, float noiseFactor, vec3 playerPos, bool doTileRandomisation) {
#ifndef ENTITY_GN_AND_CT
#if defined GBUFFERS_ENTITIES || defined GBUFFERS_HAND
return;
#endif
#endif
#ifndef SAFER_GENERATED_NORMALS
vec2 noiseCoord = floor(midCoordPos / 16.0 * packSizeNT * atlasSizeM) / packSizeNT / 3.0;
#else
vec2 offsetR = max(absMidCoordPos.x, absMidCoordPos.y) * vec2(float(atlasSizeM.y) / float(atlasSizeM.x), 1.0);
vec2 noiseCoord = floor(midCoordPos / 2.0 * packSizeNT / offsetR) / packSizeNT / 3.0;
#endif
if (doTileRandomisation) {
vec3 floorWorldPos = floor(playerPos + cameraPosition + 0.001);
noiseCoord += 0.84 * (floorWorldPos.xz + floorWorldPos.y);
}
float noiseTexture = texture2DLod(noisetex, noiseCoord, 0.0).r;
noiseTexture = noiseTexture + 0.6;
float colorBrightness = dot(color, color) * 0.3;
#define COATED_TEXTURE_MULT_M COATED_TEXTURE_MULT * 0.0027
noiseFactor *= COATED_TEXTURE_MULT_M * max0(1.0 - colorBrightness);
noiseFactor *= max(1.0 - miplevel * 0.25, 0.0);
noiseTexture = pow(noiseTexture, noiseFactor);
color *= noiseTexture;
}
@@ -0,0 +1,115 @@
ivec3[6] glassOffsets = ivec3[](
ivec3( 1, 0, 0),
ivec3(-1, 0, 0),
ivec3( 0, 1, 0),
ivec3( 0,-1, 0),
ivec3( 0, 0, 1),
ivec3( 0, 0,-1)
);
ivec3[12] glassCornerOffsets = ivec3[](
ivec3( 1, 1, 0),
ivec3( 1,-1, 0),
ivec3(-1, 1, 0),
ivec3(-1,-1, 0),
ivec3( 0, 1, 1),
ivec3( 0, 1,-1),
ivec3( 0,-1, 1),
ivec3( 0,-1,-1),
ivec3( 1, 0, 1),
ivec3( 1, 0,-1),
ivec3(-1, 0, 1),
ivec3(-1, 0,-1)
);
vec2 GetModifiedMidCoord() {
float epsilon1 = 0.00001;
vec2 midCoord = texCoord - signMidCoordPos * absMidCoordPos;
return midCoord - epsilon1;
}
void DoSimpleConnectedGlass(inout vec4 color) {
color = texture2DLod(tex, GetModifiedMidCoord() - 0.125 * absMidCoordPos, 0);
}
#ifdef GBUFFERS_WATER
void DoConnectedGlass(inout vec4 colorP, inout vec4 color, inout bool noGeneratedNormals, vec3 playerPos, vec3 worldGeoNormal, uint voxelID, bool isPane) {
vec3 worldGeoNormalM = vec3( // Fixes Iris 1.8 normal precision issues causing the coordinates to be imperfect
round(worldGeoNormal.x),
round(worldGeoNormal.y),
round(worldGeoNormal.z)
);
vec3 playerPosM = playerPos - worldGeoNormalM * 0.25;
vec3 voxelPos = SceneToVoxel(playerPosM);
if (CheckInsideVoxelVolume(voxelPos)) {
#if IRIS_VERSION >= 10800
float epsilon2 = 0.0;
#else
float epsilon2 = 0.001;
#endif
float pixelOffset = 0.5 / (absMidCoordPos.y * atlasSize.y);
float pixelOffsetPlus = pixelOffset + epsilon2;
float pixelOffsetMinus = pixelOffset - epsilon2;
colorP = texture2DLod(tex, texCoord, 0);
vec4 colorPvanilla = colorP;
vec2 midCoordM = GetModifiedMidCoord();
vec3 worldPos = playerPosM + cameraPositionBestFract;
vec3 floorWorldPos = floor(worldPos);
// Remove edges
for (int i = 0; i < 6; i++) {
uint voxel = GetVoxelVolume(ivec3(voxelPos) + glassOffsets[i]);
if (voxel == voxelID) {
if (floor(worldPos + glassOffsets[i] * pixelOffsetPlus) != floorWorldPos) {
colorP = texture2DLod(tex, midCoordM, 0);
}
#ifdef GENERATED_NORMALS
if (floor(worldPos + glassOffsets[i] * pixelOffsetPlus * 1.25) != floorWorldPos) {
noGeneratedNormals = true;
}
#endif
}
}
// Fixes the connections by restoring the edges that aren't connected
for (int i = 0; i < 6; i++) {
uint voxel = GetVoxelVolume(ivec3(voxelPos) + glassOffsets[i]);
if (voxel != voxelID) {
//if (floor(worldPos + glassOffsets[i] * 0.0625) != floorWorldPos) {
if (floor(worldPos + glassOffsets[i] * pixelOffsetMinus) != floorWorldPos) {
colorP = colorPvanilla;
}
}
}
if (isPane) {
// Fixes lines between layers of glass panes
if (NdotU > 0.9) {
uint voxel = GetVoxelVolume(ivec3(voxelPos) + ivec3(0, 1, 0));
if (voxel == voxelID) discard;
}
if (NdotU < -0.9) {
uint voxel = GetVoxelVolume(ivec3(voxelPos) - ivec3(0, 1, 0));
if (voxel == voxelID) discard;
}
}
#ifdef CONNECTED_GLASS_CORNER_FIX
// Restores corners
for (int i = 0; i < 12; i++) {
uint voxel = GetVoxelVolume(ivec3(voxelPos) + glassCornerOffsets[i]);
if ((voxel != voxelID) && (!isPane || voxel > 0u)) {
if (floor((worldPos - glassCornerOffsets[i] * (1.0 - pixelOffsetMinus))) == floorWorldPos) {
colorP = colorPvanilla;
}
}
}
#endif
color = colorP * vec4(glColor.rgb, 1.0);
}
}
#endif
@@ -0,0 +1,35 @@
#ifndef INCLUDE_CUSTOM_EMISSION
#define INCLUDE_CUSTOM_EMISSION
float GetCustomEmission(vec4 specularMap, vec2 texCoordM) {
#if CUSTOM_EMISSION_INTENSITY > 0
#if RP_MODE == 2 || RP_MODE == 1 && IPBR_EMISSIVE_MODE == 2 // seuspbr
float emission = specularMap.b;
#elif RP_MODE == 3 || RP_MODE == 1 && IPBR_EMISSIVE_MODE == 3 // labPBR
float emission = specularMap.a < 1.0 ? specularMap.a : 0.0;
vec4 specularMapL0 = texture2DLod(specular, texCoordM, 0);
float emissionL0 = specularMapL0.a < 1.0 ? specularMapL0.a : 0.0;
emission = min(emission, emissionL0); // Fixes issues caused by mipmaps
#endif
return emission * 0.03 * CUSTOM_EMISSION_INTENSITY;
#else
return 0.0;
#endif
}
#ifdef IPBR
float GetCustomEmissionForIPBR(inout vec4 color, float emission) {
vec4 specularMapCheck = texture2DLod(specular, texCoord, 1000.0);
if (specularMapCheck.a == 0.0) return emission;
color = texture2D(tex, texCoord);
vec4 specularMap = texture2D(specular, texCoord);
float customEmission = GetCustomEmission(specularMap, texCoord);
return customEmission;
}
#endif
#endif //INCLUDE_CUSTOM_EMISSION
@@ -0,0 +1,96 @@
#define ENTITY_GN_AND_CT
#define GENERATED_NORMAL_MULT 100 //[25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 110 120 130 140 150 160 170 180 190 200 250 300 400]
#define GENERATED_NORMAL_ENTITY_MULT 0 //[0 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 110 120 130 140 150 160 170 180 190 200 250 300 400]
#define NORMAL_RES 128 //[16 32 64 80 96 112 128 144 160 176 192 208 224 240 256 320 384 448 512]
const float normalThreshold = 0.05;
const float normalClamp = 0.2;
const float packSizeGN = 128.0;
#ifdef GBUFFERS_ENTITIES
#if GENERATED_NORMAL_ENTITY_MULT > 0
const float normalMult = GENERATED_NORMAL_ENTITY_MULT * 0.025;
#else
const float normalMult = GENERATED_NORMAL_MULT * 0.025;
#endif
#elif !defined GBUFFERS_HAND
const float normalMult = GENERATED_NORMAL_MULT * 0.025;
#else
const float normalMult = GENERATED_NORMAL_MULT * 0.015;
#endif
float GetDif(float lOriginalAlbedo, vec2 offsetCoord) {
#ifndef GBUFFERS_WATER
float lNearbyAlbedo = length(texture2D(tex, offsetCoord).rgb);
#else
vec4 textureSample = texture2D(tex, offsetCoord);
float lNearbyAlbedo = length(textureSample.rgb * textureSample.a * 1.5);
#endif
#ifdef GBUFFERS_ENTITIES
lOriginalAlbedo = abs(lOriginalAlbedo - 1.0);
lNearbyAlbedo = abs(lNearbyAlbedo - 1.0);
#endif
float dif = lOriginalAlbedo - lNearbyAlbedo;
#ifdef GBUFFERS_ENTITIES
dif = -dif;
#endif
#ifndef GBUFFERS_WATER
if (dif > 0.0) dif = max(dif - normalThreshold, 0.0);
else dif = min(dif + normalThreshold, 0.0);
#endif
return clamp(dif, -normalClamp, normalClamp);
}
void GenerateNormals(inout vec3 normalM, vec3 color) {
#ifndef ENTITY_GN_AND_CT
#if defined GBUFFERS_ENTITIES || defined GBUFFERS_HAND
return;
#endif
#endif
vec2 absMidCoordPos2 = absMidCoordPos * 2.0;
float lOriginalAlbedo = length(color.rgb);
float normalMult = max0(1.0 - mipDelta) * normalMult;
#ifndef SAFER_GENERATED_NORMALS
vec2 offsetR = 16.0 / atlasSizeM;
#else
vec2 offsetR = max(absMidCoordPos2.x, absMidCoordPos2.y) * vec2(float(atlasSizeM.y) / float(atlasSizeM.x), 1.0);
#endif
offsetR /= NORMAL_RES;
vec2 midCoord = texCoord - midCoordPos;
vec2 maxOffsetCoord = midCoord + absMidCoordPos;
vec2 minOffsetCoord = midCoord - absMidCoordPos;
if (normalMult > 0.0) {
vec3 normalMap = vec3(0.0, 0.0, 1.0);
vec2 offsetCoord = texCoord + vec2( 0.0, offsetR.y);
if (offsetCoord.y < maxOffsetCoord.y)
normalMap.y += GetDif(lOriginalAlbedo, offsetCoord);
offsetCoord = texCoord + vec2( offsetR.x, 0.0);
if (offsetCoord.x < maxOffsetCoord.x)
normalMap.x += GetDif(lOriginalAlbedo, offsetCoord);
offsetCoord = texCoord + vec2( 0.0,-offsetR.y);
if (offsetCoord.y > minOffsetCoord.y)
normalMap.y -= GetDif(lOriginalAlbedo, offsetCoord);
offsetCoord = texCoord + vec2(-offsetR.x, 0.0);
if (offsetCoord.x > minOffsetCoord.x)
normalMap.x -= GetDif(lOriginalAlbedo, offsetCoord);
normalMap.xy *= normalMult;
normalMap.xy = clamp(normalMap.xy, vec2(-1.0), vec2(1.0));
if (normalMap.xy != vec2(0.0, 0.0))
normalM = clamp(normalize(normalMap * tbnMatrix), vec3(-1.0), vec3(1.0));
}
}
@@ -0,0 +1,104 @@
bool intersectsAABB(vec3 ro, vec3 rd, vec3 aabbMin, vec3 aabbMax) {
vec3 t0 = (aabbMin - ro) / rd;
vec3 t1 = (aabbMax - ro) / rd;
vec3 tMin = min(t0, t1);
vec3 tMax = max(t0, t1);
float m0 = max(max(tMin.x, tMin.y), tMin.z);
float m1 = min(min(tMax.x, tMax.y), tMax.z);
return m1 > max0(m0);
}
bool intersectsParallelogram(vec3 ro, vec3 rd, vec3 v0, vec3 v1, vec3 v2, float tMin, out float t, out vec2 uv, inout vec3 normal) {
vec3 a = v1 - v0, n = cross(a, v2 - v0);
t = dot(v0 - ro, n) / dot(n, rd);
if (t < 0.0 || t > tMin) return false;
vec3 b = v2 - v1;
vec3 c = ro + rd * t - v0;
uv = vec2(dot(c, a) / dot(a, a), dot(c, b) / dot(b, b));
if (uv.x < 0.0 || uv.y < 0.0 || uv.x > 1.0 || uv.y > 1.0) return false;
normal = normalize(n);
return true;
}
void CheckQuadAt(int i, vec3 playerPos, vec3 rayDir, inout vec3 albedo, inout float tMin, inout vec3 normal, inout float emissionOut) {
int i0 = 3 * i, i1 = 3 * i + 1, i2 = 3 * i + 2;
vec3 v0 = playerVerticesSSBO.vertexPositions[i0];
vec3 v1 = playerVerticesSSBO.vertexPositions[i1];
vec3 v2 = playerVerticesSSBO.vertexPositions[i2];
float t;
vec2 uv;
vec3 colorP;
vec3 color;
float emission = 0.0;
float smoothnessD, smoothnessG;
if (intersectsParallelogram(playerPos, rayDir, v0, v1, v2, tMin, t, uv, normal)) {
vec2 texCoord0 = playerVerticesSSBO.vertexData[i0];
vec2 texCoord1 = playerVerticesSSBO.vertexData[i1];
vec2 texCoord2 = playerVerticesSSBO.vertexData[i2];
vec2 quadTexCoord = mix(texCoord0, texCoord1, uv.x) + uv.y * (texCoord2 - texCoord1);
vec4 playerAtlasSample = texelFetch(playerAtlas_sampler, ivec2(64 * quadTexCoord), 0);
vec3 colorP = playerAtlasSample.rgb;
vec3 color = playerAtlasSample.rgb;
#ifdef SPACEAGLE17
#include "/lib/materials/specificMaterials/others/SpacEagle17.glsl"
#endif
if (playerAtlasSample.a > 0.2) {albedo = color * (emission * 0.2 + 1.0); tMin = t; emissionOut = emission;}
}
}
bool rayTracePlayer(vec3 playerPos, vec3 rayDir, float wsrTraceLength, out vec3 albedo, out vec3 normal, out float emission) {
float tMin = wsrTraceLength;
vec3 aabbPos = playerPos * 1000.0;
// Head
if (intersectsAABB(aabbPos, rayDir, playerVerticesSSBO.bounds.headMin, playerVerticesSSBO.bounds.headMax)) {
for (int i = 0; i < 12; i++) {
CheckQuadAt(i, playerPos, rayDir, albedo, tMin, normal, emission);
}
}
// Right Hand
if (intersectsAABB(aabbPos, rayDir, playerVerticesSSBO.bounds.rightHandMin, playerVerticesSSBO.bounds.rightHandMax)) {
for (int i = 12; i < 24; i++) {
CheckQuadAt(i, playerPos, rayDir, albedo, tMin, normal, emission);
}
}
// Left Leg
if (intersectsAABB(aabbPos, rayDir, playerVerticesSSBO.bounds.leftLegMin, playerVerticesSSBO.bounds.leftLegMax)) {
for (int i = 24; i < 36; i++) {
CheckQuadAt(i, playerPos, rayDir, albedo, tMin, normal, emission);
}
}
// Left Hand
if (intersectsAABB(aabbPos, rayDir, playerVerticesSSBO.bounds.leftHandMin, playerVerticesSSBO.bounds.leftHandMax)) {
for (int i = 36; i < 48; i++) {
CheckQuadAt(i, playerPos, rayDir, albedo, tMin, normal, emission);
}
}
// Right leg
if (intersectsAABB(aabbPos, rayDir, playerVerticesSSBO.bounds.rightLegMin, playerVerticesSSBO.bounds.rightLegMax)) {
for (int i = 48; i < 60; i++) {
CheckQuadAt(i, playerPos, rayDir, albedo, tMin, normal, emission);
}
}
// Torso
if (intersectsAABB(aabbPos, rayDir, playerVerticesSSBO.bounds.torsoMin, playerVerticesSSBO.bounds.torsoMax)) {
for (int i = 60; i < 72; i++) {
CheckQuadAt(i, playerPos, rayDir, albedo, tMin, normal, emission);
}
}
return tMin < wsrTraceLength;
}
@@ -0,0 +1,121 @@
#include "/lib/util/dither.glsl"
vec2 vTexCoord = signMidCoordPos * 0.5 + 0.5;
#include "/lib/util/dFdxdFdy.glsl"
vec4 ReadNormal(vec2 coord) {
coord = fract(coord) * vTexCoordAM.pq + vTexCoordAM.st;
return textureGrad(normals, coord, dcdx, dcdy);
}
vec2 GetParallaxCoord(float parallaxFade, float dither, inout vec2 newCoord, inout float texDepth, inout vec3 traceCoordDepth) {
float invParallaxQuality = 1.0 / POM_QUALITY;
vec4 normalMap = ReadNormal(vTexCoord.st);
vec2 normalMapM = normalMap.xy * 2.0 - 1.0;
float normalCheck = normalMapM.x + normalMapM.y;
float minHeight = 1.0 - invParallaxQuality;
if (viewVector.z >= 0.0 || normalMap.a >= minHeight || normalCheck <= -1.999) return vTexCoord.st;
vec2 interval = viewVector.xy * 0.25 * (1.0 - parallaxFade) * POM_DEPTH / (-viewVector.z * POM_QUALITY);
float i = 0.0;
vec2 localCoord;
#if defined GBUFFERS_TERRAIN || defined GBUFFERS_BLOCK
if (texDepth <= 1.0 - i * invParallaxQuality) {
localCoord = vTexCoord.st + i * interval;
texDepth = ReadNormal(localCoord).a;
i = dither;
}
#endif
for (; i < POM_QUALITY && texDepth <= 1.0 - i * invParallaxQuality; i++) {
localCoord = vTexCoord.st + i * interval;
texDepth = ReadNormal(localCoord).a;
}
float pI = float(max(i - 1, 0));
traceCoordDepth.xy -= pI * interval;
traceCoordDepth.z -= pI * invParallaxQuality;
localCoord = fract(vTexCoord.st + pI * interval);
newCoord = localCoord * vTexCoordAM.pq + vTexCoordAM.st;
return localCoord;
}
float GetParallaxShadow(float parallaxFade, float dither, float height, vec2 coord, vec3 lightVec, mat3 tbn) {
float parallaxshadow = 1.0;
vec3 parallaxdir = tbn * lightVec;
parallaxdir.xy *= 1.0 * POM_DEPTH; // Angle
for (int i = 0; i < 4 && parallaxshadow >= 0.01; i++) {
float stepLC = 0.025 * (i + dither);
float currentHeight = height + parallaxdir.z * stepLC;
vec2 parallaxCoord = fract(coord + parallaxdir.xy * stepLC) * vTexCoordAM.pq + vTexCoordAM.st;
float offsetHeight = textureGrad(normals, parallaxCoord, dcdx, dcdy).a;
parallaxshadow *= clamp(1.0 - (offsetHeight - currentHeight) * 4.0, 0.0, 1.0);
}
return mix(parallaxshadow, 1.0, parallaxFade);
}
// Big thanks to null511 for slope normals
vec3 GetParallaxSlopeNormal(vec2 texCoord, float traceDepth, vec3 viewDir) {
vec2 atlasPixelSize = 1.0 / atlasSize;
float atlasAspect = atlasSize.x / atlasSize.y;
vec2 atlasCoord = fract(texCoord) * vTexCoordAM.pq + vTexCoordAM.st;
vec2 tileSize = atlasSize * vTexCoordAM.pq;
vec2 tilePixelSize = 1.0 / tileSize;
vec2 tex_snapped = floor(atlasCoord * atlasSize) * atlasPixelSize;
vec2 tex_offset = atlasCoord - (tex_snapped + 0.5 * atlasPixelSize);
vec2 stepSign = sign(tex_offset);
vec2 viewSign = sign(viewDir.xy);
bool dir = abs(tex_offset.x * atlasAspect) < abs(tex_offset.y);
vec2 tex_x, tex_y;
if (dir) {
tex_x = texCoord - vec2(tilePixelSize.x * viewSign.x, 0.0);
tex_y = texCoord + vec2(0.0, stepSign.y * tilePixelSize.y);
}
else {
tex_x = texCoord + vec2(tilePixelSize.x * stepSign.x, 0.0);
tex_y = texCoord - vec2(0.0, viewSign.y * tilePixelSize.y);
}
float height_x = ReadNormal(tex_x).a;
float height_y = ReadNormal(tex_y).a;
if (dir) {
if (!(traceDepth > height_y && viewSign.y != stepSign.y)) {
if (traceDepth > height_x) return vec3(-viewSign.x, 0.0, 0.0);
if (abs(viewDir.y) > abs(viewDir.x))
return vec3(0.0, -viewSign.y, 0.0);
else
return vec3(-viewSign.x, 0.0, 0.0);
}
return vec3(0.0, -viewSign.y, 0.0);
}
else {
if (!(traceDepth > height_x && viewSign.x != stepSign.x)) {
if (traceDepth > height_y) return vec3(0.0, -viewSign.y, 0.0);
if (abs(viewDir.y) > abs(viewDir.x))
return vec3(0.0, -viewSign.y, 0.0);
else
return vec3(-viewSign.x, 0.0, 0.0);
}
return vec3(-viewSign.x, 0.0, 0.0);
}
}
@@ -0,0 +1,107 @@
void AddBackgroundReflection(inout vec4 reflection, vec3 color, vec3 playerPos, vec3 normalM, vec3 normalMR, vec3 viewPos, vec3 nViewPos, vec3 nViewPosR,
vec3 shadowMult, float RVdotU, float RVdotS, float z0, float dither, float skyLightFactor, float smoothness, float highlightMult) {
#ifdef OVERWORLD
#if defined COMPOSITE || WATER_REFLECT_QUALITY >= 2
vec3 skyReflection = GetSky(RVdotU, RVdotS, dither, isEyeInWater == 0, true);
#else
vec3 skyReflection = GetLowQualitySky(RVdotU, RVdotS, dither, isEyeInWater == 0, true);
#endif
#ifdef ATM_COLOR_MULTS
skyReflection *= atmColorMult;
#endif
#ifdef MOON_PHASE_INF_ATMOSPHERE
skyReflection *= moonPhaseInfluence;
#endif
#ifdef COMPOSITE
skyReflection *= skyLightFactor;
#else
float specularHighlight = GGX(normalM, nViewPos, lightVec, max(dot(normalM, lightVec), 0.0), smoothness);
skyReflection += specularHighlight * highlightColor * shadowMult * highlightMult * invRainFactor;
#if WATER_REFLECT_QUALITY >= 1
#ifdef SKY_EFFECT_REFLECTION
float cloudLinearDepth = 1.0;
float skyFade = 1.0;
vec3 auroraBorealis = vec3(0.0);
vec3 nightNebula = vec3(0.0);
#if AURORA_STYLE > 0
auroraBorealis = GetAuroraBorealis(nViewPosR, RVdotU, dither);
skyReflection += auroraBorealis;
#endif
#if NIGHT_NEBULAE == 1
nightNebula += GetNightNebula(nViewPosR, RVdotU, RVdotS);
skyReflection += nightNebula;
#endif
vec2 starCoord = GetStarCoord(nViewPos, 0.5);
#ifdef PIXELATED_WATER_REFLECTIONS
vec3 absPlayerPos = abs(playerPos);
float sizeDecider = -clamp01(pow2(min1(length(absPlayerPos) / 10))) + 1.0; // The effect will only be around the player
float starSize = mix(1.0, 2.0, step(0.2, sizeDecider));
#else
float starSize = 1.0;
#endif
#if STAR_BRIGHTNESS != 3
vec3 starColor = GetStars(starCoord, RVdotU, RVdotS, 1.0 * starSize, 0.0);
#define ADD_STAR_LAYER_OW1 (STAR_LAYER_OW == 1 || STAR_LAYER_OW == 3)
#define ADD_STAR_LAYER_OW2 (STAR_LAYER_OW == 2 || STAR_LAYER_OW == 3)
#if ADD_STAR_LAYER_OW1
starColor = max(starColor, GetStars(starCoord, RVdotU, RVdotS, 0.66 * starSize, 0.0));
#endif
#if ADD_STAR_LAYER_OW2
starColor = max(starColor, GetStars(starCoord, RVdotU, RVdotS, 2.2 * starSize, 0.45));
#endif
skyReflection += starColor;
#endif
#ifdef VL_CLOUDS_ACTIVE
vec3 worldNormalMR = normalize(mat3(gbufferModelViewInverse) * normalMR);
vec3 cameraPosOffset = 2.0 * worldNormalMR * dot(playerPos, worldNormalMR);
vec3 RPlayerPos = normalize(mat3(gbufferModelViewInverse) * nViewPosR);
float RlViewPos = 100000.0;
vec4 clouds = GetClouds(cloudLinearDepth, skyFade, cameraPosOffset, RPlayerPos,
viewPos, RlViewPos, RVdotS, RVdotU, dither, auroraBorealis, nightNebula, sunVec);
skyReflection = mix(skyReflection, clouds.rgb, clouds.a);
#endif
#endif
skyReflection = mix(color * 0.5, skyReflection, skyLightFactor);
#else
skyReflection = mix(color, skyReflection, skyLightFactor * 0.5);
#endif
#endif
#elif defined END
#ifdef COMPOSITE
#ifdef END_BEAMS
vec3 skyReflection = (endSkyColor + 0.4 * DrawEnderBeams(RVdotU, playerPos, nViewPosR)) * skyLightFactor;
#else
vec3 skyReflection = endSkyColor * skyLightFactor;
#endif
#else
vec3 skyReflection = endSkyColor * shadowMult;
#endif
#ifdef ATM_COLOR_MULTS
skyReflection *= atmColorMult;
#endif
#else
vec3 skyReflection = vec3(0.0);
#endif
#if WORLD_SPACE_REFLECTIONS_INTERNAL > 0 && defined COMPOSITE && (BLOCK_REFLECT_QUALITY >= 2 || WATER_REFLECT_QUALITY >= 2)
vec4 wsrReflection = getWSR(playerPos, normalMR, nViewPosR, RVdotU, RVdotS, z0, dither);
reflection = mix(wsrReflection, vec4(reflection.rgb, 1.0), reflection.a);
refDist = min(refDist, length(wsrHitPos - playerPos));
#endif
reflection.rgb = mix(skyReflection, reflection.rgb, reflection.a);
}
@@ -0,0 +1,43 @@
vec4 sampleBlurFilteredReflection(vec4 centerCol, float dither, float z0) {
vec4 texture4 = texture2D(colortex4, texCoord);
vec3 texture6 = texelFetch(colortex6, texelCoord, 0).rgb;
float smoothnessD = texture6.r;
//float linearZ0 = GetLinearDepth(z0);
const float spatialFactor = 2.5; // higher = smoother in space
const float spatialFactorM = 2.0 * spatialFactor * spatialFactor;
vec4 sum = vec4(0.0);
float wsum = 0.0;
vec2 texelSize = (3.0 + 6.0 * dither) / view; // 1 pixel range doesn't seem to be enough to smooth things out
texelSize *= 1.0 - 0.75 * pow2(pow2(pow2(smoothnessD)));
int k = 2;
for (int dy = -k; dy <= k; dy++) {
for (int dx = -k; dx <= k; dx++) {
vec2 offset = vec2(float(dx), float(dy)) * texelSize;
vec2 sampleCoord = texCoord + offset;
vec4 sampleCol = texture2D(colortex7, sampleCoord);
// Skip step if normals are too different
vec4 texture1Sample = texture2D(colortex1, sampleCoord);
if (length(texture4.rgb - texture1Sample.rgb) > 0.1) continue;
// Skip if depth is too different (costs performance for a tiny fix)
#ifdef REFLECTION_BLUR_DEPTH_CHECK
if (abs(GetLinearDepth(texture2D(depthtex0, sampleCoord).r) - linearZ0) * far > 2.0) continue;
#endif
// Spatial weight (gaussian)
float spatialDist2 = float(dx*dx + dy*dy);
float w_s = exp(-spatialDist2 / spatialFactorM);
float w = w_s;
sum += sampleCol * w;
wsum += w_s;
}
}
return sum / wsum;
}
@@ -0,0 +1,290 @@
#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;
}
@@ -0,0 +1,43 @@
float GetApproxDistance(float depth) {
return near * far / (far - depth * far);
}
vec2 DoRefraction(inout vec3 color, inout float z0, inout float z1, vec3 viewPos, float lViewPos) {
// Prep
if (int(texelFetch(colortex6, texelCoord, 0).g * 255.1) != 241) return texCoord.xy;
float fovScale = gbufferProjection[1][1];
vec3 playerPos = ViewToPlayer(viewPos.xyz);
vec3 worldPos = playerPos.xyz + cameraPosition.xyz;
vec2 worldPosRM = worldPos.xz * 0.02 + worldPos.y * 0.01 + 0.01 * frameTimeCounter;
vec2 refractNoise = texture2DLod(noisetex, worldPosRM, 0.0).rb - vec2(0.5);
refractNoise *= WATER_REFRACTION_INTENSITY * fovScale / (3.0 + lViewPos);
#if WATER_STYLE < 3
refractNoise *= 0.015;
#else
refractNoise *= 0.02;
#endif
// Check
float approxDif = GetApproxDistance(z1) - GetApproxDistance(z0);
refractNoise *= clamp(approxDif, 0.0, 1.0);
vec2 refractCoord = texCoord.xy + refractNoise;
if (int(texture2D(colortex6, refractCoord).g * 255.1) != 241) return texCoord.xy;
float z0check = texture2D(depthtex0, refractCoord).r;
float z1check = texture2D(depthtex1, refractCoord).r;
float approxDifCheck = GetApproxDistance(z1check) - GetApproxDistance(z0check);
refractNoise *= clamp(approxDifCheck, 0.0, 1.0);
// Sample
refractCoord = texCoord.xy + refractNoise;
color = texture2D(colortex0, refractCoord).rgb;
z0 = texture2D(depthtex0, refractCoord).r;
z1 = texture2D(depthtex1, refractCoord).r;
return refractCoord;
}
@@ -0,0 +1,19 @@
const float packSizeSW = 16.0;
void DoSnowyWorld(inout vec4 color, inout float smoothnessG, inout float highlightMult, inout float smoothnessD, inout float emission,
vec3 playerPos, vec2 lmCoord, float snowFactor, float snowMinNdotU, float NdotU, int subsurfaceMode) {
float snowFactorM = snowFactor * 1000.0 * max(NdotU - 0.9, snowMinNdotU) * max0(lmCoord.y - 0.9) * (0.9 - clamp(lmCoord.x, 0.8, 0.9));
if (snowFactorM <= 0.0001) return;
vec3 worldPos = playerPos + cameraPosition;
vec2 noiseCoord = floor(packSizeSW * worldPos.xz + 0.001) / packSizeSW;
noiseCoord += floor(packSizeSW * worldPos.y + 0.001) / packSizeSW;
float noiseTexture = dot(vec2(0.25, 0.75), texture2DLod(noisetex, noiseCoord * 0.45, 0.0).rg);
vec3 snowColor = mix(vec3(0.65, 0.8, 0.85), vec3(1.0, 1.0, 1.0), noiseTexture * 0.75 + 0.125);
color.rgb = mix(color.rgb, snowColor + color.rgb * emission * 0.2, snowFactorM);
smoothnessG = mix(smoothnessG, 0.25 + 0.25 * noiseTexture, snowFactorM);
highlightMult = mix(highlightMult, 2.0 - subsurfaceMode * 0.666, snowFactorM);
smoothnessD = mix(smoothnessD, 0.0, snowFactorM);
emission *= 1.0 - snowFactorM * 0.85;
}
@@ -0,0 +1,149 @@
float random (in float x) { return fract(sin(x)*1e4);}
float random (in vec2 st) {return fract(sin(dot(st.xy, vec2(12.9898,78.233)))* 43758.5453123);}
vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}
vec4 hash4( vec2 p ) { return fract(sin(vec4( 1.0+dot(p,vec2(37.0,17.0)),
2.0+dot(p,vec2(11.0,47.0)),
3.0+dot(p,vec2(41.0,29.0)),
4.0+dot(p,vec2(23.0,31.0))))*103.0); }
vec4 textureNoTile( sampler2D samp, in vec2 uv )
{
vec2 iuv = floor( uv );
vec2 fuv = fract( uv );
// #ifdef USEHASH
// // generate per-tile transform (needs GL_NEAREST_MIPMAP_LINEARto work right)
// vec4 ofa = texture( samp, (iuv + vec2(0.5,0.5))/256.0 );
// vec4 ofb = texture( samp, (iuv + vec2(1.5,0.5))/256.0 );
// vec4 ofc = texture( samp, (iuv + vec2(0.5,1.5))/256.0 );
// vec4 ofd = texture( samp, (iuv + vec2(1.5,1.5))/256.0 );
// #else
// generate per-tile transform
vec4 ofa = hash4( iuv + vec2(0.0,0.0) );
vec4 ofb = hash4( iuv + vec2(1.0,0.0) );
vec4 ofc = hash4( iuv + vec2(0.0,1.0) );
vec4 ofd = hash4( iuv + vec2(1.0,1.0) );
//#endif
vec2 ddx = dFdx( uv );
vec2 ddy = dFdy( uv );
// transform per-tile uvs
ofa.zw = sign(ofa.zw-0.5);
ofb.zw = sign(ofb.zw-0.5);
ofc.zw = sign(ofc.zw-0.5);
ofd.zw = sign(ofd.zw-0.5);
// uv's, and derivarives (for correct mipmapping)
vec2 uva = uv*ofa.zw + ofa.xy; vec2 ddxa = ddx*ofa.zw; vec2 ddya = ddy*ofa.zw;
vec2 uvb = uv*ofb.zw + ofb.xy; vec2 ddxb = ddx*ofb.zw; vec2 ddyb = ddy*ofb.zw;
vec2 uvc = uv*ofc.zw + ofc.xy; vec2 ddxc = ddx*ofc.zw; vec2 ddyc = ddy*ofc.zw;
vec2 uvd = uv*ofd.zw + ofd.xy; vec2 ddxd = ddx*ofd.zw; vec2 ddyd = ddy*ofd.zw;
// fetch and blend
vec2 b = smoothstep(0.25,0.75,fuv);
return mix( mix( textureGrad( samp, uva, ddxa, ddya ),
textureGrad( samp, uvb, ddxb, ddyb ), b.x ),
mix( textureGrad( samp, uvc, ddxc, ddyc ),
textureGrad( samp, uvd, ddxd, ddyd ), b.x), b.y );
}
vec3 voronoi( in vec2 x, float rnd ) {
vec2 n = floor(x);
vec2 f = fract(x);
// first pass: regular voronoi
vec2 mg, mr;
float md = 8.0;
for (int j=-1; j<=1; j++ ) {
for (int i=-1; i<=1; i++ ) {
vec2 g = vec2(float(i),float(j));
vec2 o = random2( n + g )*rnd;
o = 0.5 + 0.5*sin( frameTimeCounter + 6.2831*o );
vec2 r = g + o - f;
float d = dot(r,r);
if( d<md ) {
md = d;
mr = r;
mg = g;
}
}
}
// second pass: distance to borders
md = 8.0;
for (int j=-2; j<=2; j++ ) {
for (int i=-2; i<=2; i++ ) {
vec2 g = mg + vec2(float(i),float(j));
vec2 o = random2(n + g)*rnd;
o = 0.5 + 0.5*sin( frameTimeCounter + 6.2831*o );
vec2 r = g + o - f;
if( dot(mr-r,mr-r)>0.00001 )
md = min( md, dot( 0.5*(mr+r), normalize(r-mr) ) );
}
}
return vec3( md, mr );
}
vec3 waterMaskFunc(vec3 worldPos, const float water_scroll_speed, vec3 waterColor, int mat, vec3 normal) {
const float foam_speed = 0.05;
const float water_warp = 0.005;
vec3 water_color = vec3(0);
if (mat == 10049) { // Water Cauldron
water_color = saturateColors(waterColor, 0.3) * 0.7;
} else {
water_color = mix(waterColor * 0.4, vec3(0.22, 0.22, 0.22), 0.5);
}
//pixelated coord to created pixelated visual
vec3 uv = worldPos;
uv = (uv-.5)*.25+.5;
float pixelWaterSize = 16;
uv = floor(uv * (pixelWaterSize * 4)) / (pixelWaterSize * 4);
float d = dot(uv.xz-0.5,uv.xz-0.5);
vec3 c = voronoi(5.0*uv.xz, pow(d,.6) );
vec2 water_pos = vec2(frameTimeCounter) * water_scroll_speed;
vec3 foamNoise = textureNoTile(noisetex, uv.xz + vec2(frameTimeCounter) * foam_speed).xyz;
vec3 result = vec3(0.0);
// borders
vec3 waterMask = mix(vec3(1.00), vec3(0.0), smoothstep( 0.04, 0.06, c.x ));
vec3 foam = waterMask * vec3(foamNoise.y - 0.55);
foam = clamp(foam, vec3(0.02), vec3(1.0));
foam *= 1.3;
//not regular structure water
float water_sample = floor(texture2DLod(noisetex, uv.xz * 0.25 + foamNoise.xz * water_warp + water_pos, 0.0).r * 16) / 16;
vec3 water = mix(water_color, vec3(0.001), water_sample * float(foam));
// small particles in water
// Grid
vec2 st = uv.xz;
st *= vec2(100.0,100.);
vec2 ipos = floor(st); // integer
vec2 vel = vec2(frameTimeCounter); // time
vel *= vec2(-1.,0.); // direction
vel *= (step(1.0, mod(ipos.y,5.024))-0.5)*2.; // Oposite directions
vel *= vec2(-1.,0.); // direction
vel *= random(ipos.y); // random speed
//Creating particles
vec3 pixelParticle = vec3(1.0);
pixelParticle *= random(floor(vec2(st.x*0.32, st.y)+vel));
float mixFactor = clamp((sin(frameTimeCounter*0.1) + 1.0)*0.5, 0.005, 0.15);
pixelParticle = smoothstep(0.0,mixFactor,pixelParticle);
pixelParticle = (1.0 - pixelParticle) * (foamNoise.y - 0.55);
pixelParticle = clamp(pixelParticle, vec3(0.02), vec3(1.0));
result = foam * 2.0 + pixelParticle * 2.0 + water;
//result = vec3(foamNoise.y - 0.55);
return result;
}
@@ -0,0 +1,243 @@
#include "/lib/shaderSettings/wavingBlocks.glsl"
#if COLORED_LIGHTING_INTERNAL > 0
#include "/lib/voxelization/lightVoxelization.glsl"
#endif
vec3 GetRawWave(in vec3 pos, float wind) {
float magnitude = sin(wind * 0.0027 + pos.x + pos.y) * 0.04 + 0.04;
float d0 = sin(wind * 0.0127);
float d1 = sin(wind * 0.0089);
float d2 = sin(wind * 0.0114);
vec3 wave;
wave.x = magnitude * sin(wind*0.0224 + d1 + d2 + pos.x - pos.z + pos.y);
wave.y = magnitude * sin(wind*0.0015 + d2 + d0 + pos.x);
wave.z = magnitude * sin(wind*0.0063 + d0 + d1 - pos.x + pos.z + pos.y);
return wave;
}
vec3 GetWave(in vec3 pos, float waveSpeed) {
float wind = frameTimeCounter * waveSpeed * WAVING_SPEED;
vec3 wave = GetRawWave(pos, wind);
#define WAVING_I_RAIN_MULT_M WAVING_I_RAIN_MULT * 0.01
#if WAVING_I_RAIN_MULT > 100
float windRain = frameTimeCounter * waveSpeed * WAVING_I_RAIN_MULT_M * WAVING_SPEED;
vec3 waveRain = GetRawWave(pos, windRain);
wave = mix(wave, waveRain, rainFactor);
#endif
float wavingIntensity = WAVING_I * mix(1.0, WAVING_I_RAIN_MULT_M, rainFactor);
return wave * wavingIntensity;
}
void DoWave_Foliage(inout vec3 playerPos, vec3 worldPos, float waveMult) {
worldPos.y *= 0.5;
vec3 wave = GetWave(worldPos, 170.0);
wave.x = wave.x * 3.0;
wave.y = 0.0;
wave.z = wave.z * 8.0 + wave.y * 4.0;
#ifdef NO_WAVING_INDOORS
#ifndef WAVE_EVERYTHING
wave *= clamp(lmCoord.y - 0.87, 0.0, 0.1);
#else
wave *= 0.1;
#endif
#else
wave *= 0.1;
#endif
playerPos.xyz += wave * waveMult;
}
void DoWave_Leaves(inout vec3 playerPos, vec3 worldPos, float waveMult) {
worldPos *= vec3(0.75, 0.375, 0.75);
vec3 wave = GetWave(worldPos, 170.0);
wave *= vec3(4.0, 3.0, 8.0);
wave *= 1.0 - inSnowy; // Leaves with snow on top look wrong
#if defined NO_WAVING_INDOORS && !defined WAVE_EVERYTHING
wave *= clamp(lmCoord.y - 0.87, 0.0, 0.1);
#else
wave *= 0.1;
#endif
playerPos.xyz += wave * waveMult;
}
void DoWave_Water(inout vec3 playerPos, vec3 worldPos) {
float waterWaveTime = frameTimeCounter * 6.0 * WAVING_SPEED;
worldPos.xz *= 14.0;
float wave = sin(waterWaveTime * 0.7 - worldPos.z * 0.14 + worldPos.x * 0.07);
wave += sin(waterWaveTime * 0.5 - worldPos.z * 0.10 + worldPos.x * 0.05);
#if defined NO_WAVING_INDOORS && !defined WAVE_EVERYTHING
wave *= clamp(lmCoord.y - 0.87, 0.0, 0.1);
#else
wave *= 0.1;
#endif
playerPos.y += wave * 0.125 - 0.05;
#if defined GBUFFERS_WATER && WATER_STYLE == 1
normal = mix(normal, tangent, wave * 0.01);
#endif
}
void DoWave_Lava(inout vec3 playerPos, vec3 worldPos) {
if (fract(worldPos.y + 0.005) > 0.06) {
float lavaWaveTime = frameTimeCounter * 3.0 * WAVING_SPEED;
worldPos.xz *= 14.0;
float wave = sin(lavaWaveTime * 0.7 - worldPos.z * 0.14 + worldPos.x * 0.07);
wave += sin(lavaWaveTime * 0.5 - worldPos.z * 0.05 + worldPos.x * 0.10);
#if defined NETHER && defined WAVIER_LAVA
if (worldPos.y > 30 && worldPos.y < 32) wave *= 4.5;
else wave *= 2.0;
#endif
playerPos.y += wave * 0.0125;
}
}
void DoWave(inout vec3 playerPos, int mat) {
vec3 worldPos = playerPos.xyz + cameraPosition.xyz;
#if defined GBUFFERS_TERRAIN || defined SHADOW
#ifdef WAVING_FOLIAGE
if (mat == 10003 || mat == 10005 || mat == 10029 || mat == 10025 // Grounded Foliage
#ifdef DO_MORE_FOLIAGE_WAVING
|| mat == 10769 // Torchflower
|| mat == 10976 // Open Eye Blossom
#endif
) {
if (gl_MultiTexCoord0.t < mc_midTexCoord.t || fract(worldPos.y + 0.21) > 0.26)
DoWave_Foliage(playerPos.xyz, worldPos, 1.0);
}
else if (mat == 10021 || mat == 10023 || mat == 10027) { // Upper Layer Foliage
DoWave_Foliage(playerPos.xyz, worldPos, 1.0);
}
#ifdef DO_MORE_FOLIAGE_WAVING
else if (mat == 10972) { // Firefly Bush
if (gl_MultiTexCoord0.t < mc_midTexCoord.t || fract(worldPos.y + 0.21) > 0.26) {
vec3 wave = GetWave(worldPos, 170.0);
wave.x = wave.x * 8.0 + wave.y * 4.0;
wave.y = 0.0;
wave.z = wave.z * 3.0;
playerPos.xyz += wave * 0.1 * eyeBrightnessM; // lmCoord.y is unreliable for firefly bushes
}
}
#endif
#if defined WAVING_LEAVES_ENABLED || defined WAVING_LAVA || defined WAVING_LILY_PAD
else
#endif
#endif
#ifdef WAVING_LEAVES_ENABLED
if (mat == 10007 || mat == 10009 || mat == 10011) { // Leaves
DoWave_Leaves(playerPos.xyz, worldPos, 1.0);
} else if (mat == 10013 || mat == 10923) { // Vine
// Reduced waving on vines to prevent clipping through blocks
DoWave_Leaves(playerPos.xyz, worldPos, 0.75);
}
#if defined NETHER || defined DO_NETHER_VINE_WAVING_OUTSIDE_NETHER
else if (mat == 10884 || mat == 10885) { // Weeping Vines, Twisting Vines
float waveMult = 1.0;
#if COLORED_LIGHTING_INTERNAL > 0
vec3 playerPosP = playerPos + vec3(0.0, 0.1, 0.0);
vec3 voxelPosP = SceneToVoxel(playerPosP);
vec3 playerPosN = playerPos - vec3(0.0, 0.1, 0.0);
vec3 voxelPosN = SceneToVoxel(playerPosN);
if (CheckInsideVoxelVolume(voxelPosP)) {
int voxelP = int(GetVoxelVolume(ivec3(voxelPosP)));
int voxelN = int(GetVoxelVolume(ivec3(voxelPosN)));
if (voxelP != 0 && voxelP != 65 || voxelN != 0 && voxelN != 65) // not air, not weeping vines
waveMult = 0.0;
}
#endif
DoWave_Foliage(playerPos.xyz, worldPos, waveMult);
}
#endif
#ifdef WAVING_SUGAR_CANE
if (mat == 10039) { // Sugar Cane
float waveMult = 0.75;
#if COLORED_LIGHTING_INTERNAL > 0
vec3 voxelPosP = SceneToVoxel(playerPos - vec3(0.0, 0.1, 0.0));
if (CheckInsideVoxelVolume(voxelPosP)) {
int voxelP = int(texelFetch(voxel_sampler, ivec3(voxelPosP), 0).r);
if (voxelP != 0) // not air
waveMult = 0.0;
}
#endif
DoWave_Foliage(playerPos.xyz, worldPos, waveMult);
}
#endif
#if defined WAVING_LAVA || defined WAVING_LILY_PAD
else
#endif
#endif
#ifdef WAVING_LAVA
if (mat == 10068 || mat == 10070) { // Lava
DoWave_Lava(playerPos.xyz, worldPos);
#ifdef GBUFFERS_TERRAIN
// G8FL735 Fixes Optifine-Iris parity. Optifine has 0.9 gl_Color.rgb on a lot of versions
glColorRaw.rgb = min(glColorRaw.rgb, vec3(0.9));
#endif
}
#ifdef WAVING_LILY_PAD
else
#endif
#endif
#ifdef WAVING_LILY_PAD
if (mat == 10489) { // Lily Pad
DoWave_Water(playerPos.xyz, worldPos);
}
#endif
#endif
#if defined GBUFFERS_WATER || defined SHADOW || defined GBUFFERS_TERRAIN
#ifdef WAVING_WATER_VERTEX
#if defined WAVING_ANYTHING_TERRAIN && defined SHADOW
else
#endif
if (mat == 32000) { // Water
if (fract(worldPos.y + 0.005) > 0.06)
DoWave_Water(playerPos.xyz, worldPos);
}
#endif
#endif
}
void DoInteractiveWave(inout vec3 playerPos, int mat) {
float strength = 2.0;
if (mat == 10003 || mat == 10023 || mat == 10015) { // Flowers
strength = 1.0;
}
if (length(playerPos) < 2.0) playerPos.xz += playerPos.xz * max(5.0 / max(length(playerPos * vec3(8.0, 2.0, 8.0) - vec3(0.0, 2.0, 0.0)), 2.0) -0.625, 0.0) * clamp(2.0 / length(playerPos) - 1.0, 0.0, 1.0) * strength; // Emin's code from v4 + smooth transition by me
}
void DoWaveEverything(inout vec3 playerPos) {
vec3 worldPos = playerPos.xyz + cameraPosition.xyz;
DoWave_Leaves(playerPos.xyz, worldPos, 1.0);
DoWave_Foliage(playerPos.xyz, worldPos, 1.0);
}
@@ -0,0 +1,390 @@
#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);
}