Files
Eclipse-Shader/shaders/lib/specular.glsl
T

2429 lines
103 KiB
GLSL

float invLinZ (float lindepth){
return -((2.0*near/lindepth)-far-near)/(far-near);
}
float DH_invLinZ (float lindepth){
return -((2.0*dhVoxyNearPlane/lindepth)-dhVoxyFarPlane-dhVoxyNearPlane)/(dhVoxyFarPlane-dhVoxyNearPlane);
}
float linZ(float depth) {
return (2.0 * near) / (far + near - depth * (far - near));
}
float linZ2(float depth, float near, float far) {
return (2.0 * near) / (far + near - depth * (far - near));
}
void frisvad(in vec3 n, out vec3 f, out vec3 r){
if(n.z < -0.9) {
f = vec3(0.,-1,0);
r = vec3(-1, 0, 0);
} else {
float a = 1./(1.+n.z);
float b = -n.x*n.y*a;
f = vec3(1. - n.x*n.x*a, b, -n.x) ;
r = vec3(b, 1. - n.y*n.y*a , -n.y);
}
}
mat3 CoordBase(vec3 n){
vec3 x,y;
frisvad(n,x,y);
return mat3(x,y,n);
}
vec2 R2_Sample(int n){
vec2 alpha = vec2(0.75487765, 0.56984026);
return fract(alpha * n);
}
float fma2(float a,float b,float c){
return a * b + c;
}
vec3 SampleVNDFGGX(
vec3 viewerDirection, // Direction pointing towards the viewer, oriented such that +Z corresponds to the surface normal
float alpha, // Roughness parameter along X and Y of the distribution
vec2 xy // Pair of uniformly distributed numbers in [0, 1)
) {
// Transform viewer direction to the hemisphere configuration
viewerDirection = normalize(vec3( alpha * 0.5 * viewerDirection.xy, viewerDirection.z));
// Sample a reflection direction off the hemisphere
const float tau = 6.2831853; // 2 * pi
float phi = tau * xy.x;
float cosTheta = fma2(1.0 - xy.y, 1.0 + viewerDirection.z, -viewerDirection.z);
float sinTheta = sqrt(clamp(1.0 - cosTheta * cosTheta, 0.0, 1.0));
sinTheta = clamp(sinTheta,0.0,1.0);
cosTheta = clamp(cosTheta,sinTheta*0.5,1.0);
vec3 reflected = vec3(vec2(cos(phi), sin(phi)) * sinTheta, cosTheta);
// Evaluate halfway direction
// This gives the normal on the hemisphere
vec3 halfway = reflected + viewerDirection;
// Transform the halfway direction back to hemiellispoid configuation
// This gives the final sampled normal
return normalize(vec3(alpha * halfway.xy, halfway.z));
}
vec3 GGX(vec3 n, vec3 v, vec3 l, float r, vec3 f0, vec3 metalAlbedoTint) {
r = max(pow(r,2.5), 0.0001);
vec3 h = normalize(l + v);
float hn = inversesqrt(dot(h, h));
float dotLH = clamp(dot(h,l)*hn,0.,1.);
float dotNH = clamp(dot(h,n)*hn,0.,1.) ;
float dotNL = clamp(dot(n,l),0.,1.);
float dotNHsq = dotNH*dotNH;
float denom = dotNHsq * r - dotNHsq + 1.;
float D = r / (3.141592653589793 * denom * denom);
vec3 F = (f0 + (1. - f0) * exp2((-5.55473*dotLH-6.98316)*dotLH)) * metalAlbedoTint;
float k2 = .25 * r;
return dotNL * D * F / (dotLH*dotLH*(1.0-k2)+k2);
}
float shlickFresnelRoughness(float XdotN, float roughness){
float shlickFresnel = clamp(1.0 + XdotN,0.0,1.0);
float curves = exp(-4.0*pow(1.0-(roughness),2.5));
float brightness = exp(-3.0*pow(1.0-sqrt(roughness),3.50));
shlickFresnel = pow(1.0-pow(1.0-shlickFresnel, mix(1.0, 1.9, curves)),mix(5.0, 2.6, curves));
shlickFresnel = mix(0.0, mix(1.0,0.065, brightness) , clamp(shlickFresnel,0.0,1.0));
return shlickFresnel;
}
float invertLinearizeDepthFast(const in float z) {
return (far * (z - near)) / (z * (far - near));
}
vec3 rayTraceSpeculars(vec3 dir, vec3 position, float dither, float quality, const bool hand, inout float reflectionLength, inout bool depthCheck){
const float biasAmount = 0.0001;
float _near = near; float _far = far;
vec3 clipPosition = toClipSpace3_DH(position, false);
float rayLength = ((position.z + dir.z * _far*sqrt(3.)) > -_near) ? (-_near -position.z) / dir.z : _far*sqrt(3.);
vec3 direction = toClipSpace3_DH(position + dir*rayLength, false) - clipPosition; //convert to clip space
vec3 reflectedTC = vec3((direction.xy + clipPosition.xy) * RENDER_SCALE, 0.999999);
#if FORWARD_SSR_QUALITY == 1
return reflectedTC;
#endif
//get at which length the ray intersects with the edge of the screen
vec3 maxLengths = (step(0.0, direction) - clipPosition) / direction;
float mult = min(min(maxLengths.x, maxLengths.y), maxLengths.z);
vec3 stepv = direction * mult / quality;
clipPosition.xy *= RENDER_SCALE;
stepv.xy *= RENDER_SCALE;
vec3 spos = clipPosition + stepv*(dither*0.5+0.5);
spos += vec3(0.5*texelSize,0.0); // small offsets to reduce artifacts from precision differences.
#if defined DEFERRED_SPECULAR && defined TAA
spos.xy += TAA_Offset*texelSize*0.5/RENDER_SCALE;
#endif
float minZ = spos.z - 0.00025 / linZ2(spos.z, _near, _far);
float maxZ = spos.z;
#if (defined VOXY && defined VOXY_REFLECTIONS) || (defined DISTANT_HORIZONS && defined DH_SCREENSPACE_REFLECTIONS)
const float biasAmount2 = 0.00005;
_near = dhVoxyNearPlane;
_far = dhVoxyFarPlane;
vec3 clipPosition2 = toClipSpace3_DH(position, true);
float rayLength2 = ((position.z + dir.z * _far*sqrt(3.)) > -_near) ? (-_near -position.z) / dir.z : _far*sqrt(3.);
vec3 direction2 = toClipSpace3_DH(position + dir*rayLength2, true) - clipPosition2; //convert to clip space
//get at which length the ray intersects with the edge of the screen
vec3 maxLengths2 = (step(0.0, direction2) - clipPosition2) / direction2;
float mult2 = min(min(maxLengths2.x, maxLengths2.y), maxLengths2.z);
vec3 stepv2 = direction2 * mult2 / quality;
clipPosition2.xy *= RENDER_SCALE;
stepv2.xy *= RENDER_SCALE;
vec3 spos2 = clipPosition2 + stepv2*(dither*0.5+0.5);
spos2 += vec3(0.5*texelSize,0.0); // small offsets to reduce artifacts from precision differences.
#if defined DEFERRED_SPECULAR && defined TAA
spos2.xy += TAA_Offset*texelSize*0.5/RENDER_SCALE;
#endif
float minZ2 = spos2.z - 0.00025 / linZ2(spos2.z, _near, _far);
float maxZ2 = spos2.z;
#endif
vec3 hitPos = vec3(1.1);
for (int i = 0; i <= int(quality); i++) {
#if DEFERRED_SSR_QUALITY != 1
#if (defined VOXY && defined VOXY_REFLECTIONS) || (defined DISTANT_HORIZONS && defined DH_SCREENSPACE_REFLECTIONS)
if(!hand && (spos.x < 0 || spos.x > 1 || spos.y < 0 || spos.y > 1) && (spos2.x < 0 || spos2.x > 1 || spos2.y < 0 || spos2.y > 1)) return vec3(1.1);
#else
if(!hand && (spos.x < 0 || spos.x > 1 || spos.y < 0 || spos.y > 1)) return vec3(1.1);
#endif
#endif
#ifdef QUARTER_RES_SSR
float sampleDepth = texelFetch(colortex4, ivec2(spos.xy/texelSize/4.0),0).a/65000.0;
float sp = invLinZ(sqrt(sampleDepth));
#else
#ifdef FULLRESDEPTH
float sp = texelFetch(depthtex0, ivec2(spos.xy/texelSize),0).r;
#else
float sp = texelFetch(depthtex1, ivec2(spos.xy/texelSize),0).r;
#endif
#endif
#if (defined VOXY && defined VOXY_REFLECTIONS) || (defined DISTANT_HORIZONS && defined DH_SCREENSPACE_REFLECTIONS)
if (sp >= 1.0){
#ifdef FULLRESDEPTH
sp = texelFetch(dhVoxyDepthTex, ivec2(spos2.xy/texelSize),0).r;
#else
sp = texelFetch(dhVoxyDepthTex1, ivec2(spos2.xy/texelSize),0).r;
#endif
if(sp < max(minZ2, maxZ2) && sp > min(minZ2, maxZ2)) {
hitPos = vec3(spos2.xy/RENDER_SCALE, sp);
depthCheck = true;
break;
}
} else
#endif
{
if(sp < max(minZ, maxZ) && sp > min(minZ, maxZ)) {
hitPos = vec3(spos.xy/RENDER_SCALE, sp);
break;
}
}
minZ = maxZ - biasAmount / linZ2(spos.z, near, far);
maxZ += stepv.z;
spos += stepv;
#if (defined VOXY && defined VOXY_REFLECTIONS) || (defined DISTANT_HORIZONS && defined DH_SCREENSPACE_REFLECTIONS)
minZ2 = maxZ2 - biasAmount2 / linZ2(spos2.z, dhVoxyNearPlane, dhVoxyFarPlane);
maxZ2 += stepv2.z;
spos2 += stepv2;
#endif
reflectionLength += 1.0 / quality;
}
#if DEFERRED_SSR_QUALITY == 1
return reflectedTC;
#endif
if(hand) return reflectedTC;
return hitPos;
}
vec3 toScreenSpace2(vec3 p, bool depthCheck) {
#if (defined VOXY && defined VOXY_REFLECTIONS) || (defined DISTANT_HORIZONS && defined DH_SCREENSPACE_REFLECTIONS)
mat4 matrix = gbufferProjectionInverse;
if(depthCheck) matrix = dhVoxyProjectionInverse;
#else
mat4 matrix = gbufferProjectionInverse;
#endif
vec4 iProjDiag = vec4(matrix[0].x, matrix[1].y, matrix[2].zw);
vec3 p3 = p * 2. - 1.;
vec4 fragposition = iProjDiag * p3.xyzz + matrix[3];
return fragposition.xyz / fragposition.w;
}
#if defined VOXEL_REFLECTIONS && defined IS_LPV_ENABLED && defined adjnjawudiuwad
uint GetVoxelBlock(const in ivec3 voxelPos) {
return imageLoad(imgVoxelMask, voxelPos).r % 2000u;
}
int voxelIndex(ivec3 voxelPos) {
return voxelPos.x + voxelPos.y * int(VoxelSize) + voxelPos.z * int(VoxelSize*VoxelSize);
}
int voxelNormalIndex(vec3 voxelNormal) {
return clamp(int(abs(voxelNormal.x)*(voxelNormal.x*0.5+0.5) + abs(voxelNormal.y)*(voxelNormal.y*0.5+2.5) + abs(voxelNormal.z)*(voxelNormal.z*0.5+4.5) + 0.5), 0, 5);
}
vec2 decodeVec2_16(float a){
const vec2 constant1 = 4294967294. / vec2( 65536., 4294967295.);
const float constant2 = 65536. / 65535.;
return fract( a * constant1 ) * constant2 ;
}
void GetVoxelData(const in ivec3 voxelPos, inout vec2 texcoord, inout vec3 tintColor, in vec3 voxelNormal, inout vec2 lightmap) {
vec4 blockTexture = voxelData[voxelIndex(voxelPos)][voxelNormalIndex(voxelNormal)];
texcoord = decodeVec2_16(blockTexture.x);
lightmap = decodeVec2(blockTexture.y);
lightmap = min(max(lightmap - 0.05,0.0)*1.06,1.0);
vec2 RGtint = decodeVec2(blockTexture.b);
tintColor = vec3(RGtint.r, blockTexture.a, RGtint.g);
}
void GetTexCoord(const in ivec3 voxelPos, inout vec2 texcoord, in vec3 voxelNormal) {
texcoord = decodeVec2_16(voxelData[voxelIndex(voxelPos)][voxelNormalIndex(voxelNormal)].x);
}
float getVoxelEmission(vec3 Albedo) {
vec3 hsv = RgbToHsv(Albedo);
float emissive = smoothstep(0.05, 0.15, hsv.y) * pow(hsv.z, 3.5);
return emissive * 0.5;
}
void voxelEmission(
inout vec3 Lighting,
vec3 Albedo,
float Emission
){
if( Emission < 254.5/255.0) Lighting = mix(Lighting, Albedo * 5.0 * Emissive_Brightness, pow(Emission, Emissive_Curve));
}
vec2 CleanVoxelSample(
int samples, float totalSamples, float noise
){
// this will be used to make 1 full rotation of the spiral. the mulitplication is so it does nearly a single rotation, instead of going past where it started
float variance = noise * 0.897;
// for every sample input, it will have variance applied to it.
float variedSamples = float(samples) + variance;
// for every sample, the sample position must change its distance from the origin.
// otherwise, you will just have a circle.
float spiralShape = sqrt(variedSamples / (totalSamples + variance));
float shape = 2.26; // this is very important. 2.26 is very specific
float theta = variedSamples * (PI * shape);
float x = cos(theta) * spiralShape;
float y = sin(theta) * spiralShape;
return vec2(x, y);
}
float ComputeVoxelShadowMap(inout vec3 directLightColor, vec3 playerPos, float maxDistFade, float noise, in vec3 geoNormals){
// if(maxDistFade <= 0.0) return 1.0;
// setup shadow projection
#ifdef OVERWORLD_SHADER
#ifdef CUSTOM_MOON_ROTATION
vec3 projectedShadowPosition = mat3(customShadowMatrixSSBO) * playerPos + customShadowMatrixSSBO[3].xyz;
#else
vec3 projectedShadowPosition = mat3(shadowModelView) * playerPos + shadowModelView[3].xyz;
#endif
applyShadowBias(projectedShadowPosition, playerPos, geoNormals);
projectedShadowPosition = diagonal3(shadowProjection) * projectedShadowPosition + shadowProjection[3].xyz;
// un-distort
#ifdef DISTORT_SHADOWMAP
float distortFactor = calcDistort(projectedShadowPosition.xy);
projectedShadowPosition.xy *= distortFactor;
#else
float distortFactor = 1.0;
#endif
projectedShadowPosition.z += shadowProjection[3].z * 0.0012;
#else
float distortFactor = 1.0;
#endif
#if defined END_ISLAND_LIGHT && defined END_SHADER
vec4 shadowPos = customShadowMatrixSSBO * vec4(playerPos, 1.0);
applyShadowBias(shadowPos.xyz, playerPos, geoNormals);
shadowPos = customShadowPerspectiveSSBO * shadowPos;
vec3 projectedShadowPosition = shadowPos.xyz / shadowPos.w;
#endif
// hamburger
projectedShadowPosition = projectedShadowPosition * vec3(0.5,0.5,0.5/6.0) + vec3(0.5);
float shadowmap = 0.0;
vec3 translucentTint = vec3(0.0);
#ifdef BASIC_SHADOW_FILTER
int samples = int(SHADOW_FILTER_SAMPLE_COUNT * 0.5);
#ifdef END_SHADER
float rdMul = 52.0*d0k;
#else
float rdMul = 2.4*distortFactor*d0k;
#endif
for(int i = 0; i < samples; i++){
vec2 offsetS = CleanVoxelSample(i, samples - 1, noise) * rdMul;
projectedShadowPosition.xy += offsetS;
#else
int samples = 1;
#endif
#ifdef TRANSLUCENT_COLORED_SHADOWS
// determine when opaque shadows are overlapping translucent shadows by getting the difference of opaque depth and translucent depth
float shadowDepthDiff = pow(clamp((texture(shadowtex1, projectedShadowPosition).x - projectedShadowPosition.z) * 2.0,0.0,1.0),2.0);
// get opaque shadow data to get opaque data from translucent shadows.
float opaqueShadow = texture(shadowtex0, projectedShadowPosition).x;
shadowmap += max(opaqueShadow, shadowDepthDiff);
// get translucent shadow data
vec4 translucentShadow = texture(shadowcolor0, projectedShadowPosition.xy);
// this curve simply looked the nicest. it has no other meaning.
float shadowAlpha = pow(1.0 - pow(translucentShadow.a,5.0),0.2);
// normalize the color to remove luminance, and keep the hue. remove all opaque color.
// mulitply shadow alpha to shadow color, but only on surfaces facing the lightsource. this is a tradeoff to protect subsurface scattering's colored shadow tint from shadow bias on the back of the caster.
translucentShadow.rgb = max(normalize(translucentShadow.rgb + 0.0001), max(opaqueShadow, 1.0-shadowAlpha)) * shadowAlpha;
// make it such that full alpha areas that arent in a shadow have a value of 1.0 instead of 0.0
translucentTint += mix(translucentShadow.rgb, vec3(1.0), opaqueShadow*shadowDepthDiff);
#else
shadowmap += texture(shadow, projectedShadowPosition).x;
#endif
#ifdef BASIC_SHADOW_FILTER
}
#endif
#ifdef TRANSLUCENT_COLORED_SHADOWS
// tint the lightsource color with the translucent shadow color
directLightColor *= mix(vec3(1.0), translucentTint.rgb / samples, maxDistFade);
#endif
float shadowResult = shadowmap / samples;
#ifdef END_SHADER
float r = length(projectedShadowPosition.xy - vec2(0.5));
if (r < 0.5 && abs(projectedShadowPosition.z) < 1.0) {
shadowResult *= smoothstep(0.5, 0.25, r);
} else {
shadowResult = 0.0;
}
#endif
return shadowResult;
// return mix(1.0, shadowmap / samples, maxDistFade);
}
bool planeIntersect(inout vec3 currPos, in float worldOffset, inout vec3 voxelPos, in vec3 reflectedVector, inout vec3 stepAxis, in vec3 normal)
{
float denom = dot(reflectedVector, normal);
if (abs(denom) < 1e-6) return false;
float t = -(dot(currPos, normal) - worldOffset) / denom;
if (t > 0.0 && t < 2.0) {
vec3 hitPos = currPos + t * reflectedVector;
if (all(equal(ivec3(voxelPos), ivec3(GetLpvPosition(hitPos))))) {
currPos = hitPos;
stepAxis = normal;
return true;
}
}
return false;
}
bool AABBintersection(inout vec3 currPos, const vec3 reflectedVector, const vec3 stepSizes, const vec3 boxMin, const vec3 boxMax, inout vec3 stepAxis) {
vec3 t1 = (boxMin - currPos) * stepSizes;
vec3 t2 = (boxMax - currPos) * stepSizes;
vec3 tmin = min(t1, t2);
vec3 tmax = max(t1, t2);
float tmin0 = max(max(tmin.x, tmin.y), tmin.z);
float tmax0 = min(min(tmax.x, tmax.y), tmax.z);
bool hit = tmin0 < tmax0 && tmin0 > 0.0;
float fHit = float(hit);
vec3 entryDist = abs(tmin - vec3(tmin0));
vec3 normal = step(entryDist, vec3(0.0));
stepAxis = mix(stepAxis, normal, fHit);
currPos = mix(currPos, currPos + tmin0 * reflectedVector, fHit);
return hit;
}
struct RayHit {
bool hit;
float t;
vec3 currPos;
vec3 stepAxis;
};
RayHit AABBintersection2(const vec3 currPos, const vec3 reflectedVector, const vec3 stepSizes, const vec3 boxMin, const vec3 boxMax, const in vec3 stepAxis) {
vec3 t1 = (boxMin - currPos) * stepSizes;
vec3 t2 = (boxMax - currPos) * stepSizes;
vec3 tmin = min(t1, t2);
vec3 tmax = max(t1, t2);
float tmin0 = max(max(tmin.x, tmin.y), tmin.z);
float tmax0 = min(min(tmax.x, tmax.y), tmax.z);
bool hit = tmin0 < tmax0 && tmin0 > 0.0;
float fHit = float(hit);
RayHit result;
result.hit = hit;
result.t = tmin0;
vec3 entryDist = abs(tmin - vec3(tmin0));
vec3 normal = step(entryDist, vec3(0.0));
result.stepAxis = mix(stepAxis, normal, fHit);
result.currPos = mix(currPos, currPos + tmin0 * reflectedVector, fHit);
return result;
}
void sortIntersectionCutout(const in RayHit RayHit1, const in RayHit RayHit2, const in vec3 stepDir, const in vec2 gtexSize, const in vec2 texCoordOffset, const in vec3 voxelPos, inout bool hit, inout vec3 shiftedCurrPos, inout vec3 stepAxis) {
bool useFirst = (RayHit1.hit && (!RayHit2.hit || RayHit1.t < RayHit2.t));
RayHit firstHit = useFirst ? RayHit1 : RayHit2;
RayHit secondHit = useFirst ? RayHit2 : RayHit1;
vec2 _texcoord;
vec3 voxelNormal = -firstHit.stepAxis * stepDir;
GetTexCoord(ivec3(voxelPos), _texcoord, voxelNormal);
vec3 wPos = firstHit.currPos + cameraPosition;
vec2 sampleDir = firstHit.stepAxis.x * fract(wPos.zy) + firstHit.stepAxis.y * fract(wPos.xz) + firstHit.stepAxis.z * fract(wPos.xy);
_texcoord = mix(_texcoord + vec2(0, texCoordOffset.y), _texcoord - vec2(0, texCoordOffset.y), sampleDir);
_texcoord = mix(_texcoord + vec2(texCoordOffset.x, 0), _texcoord - vec2(texCoordOffset.x, 0), sampleDir);
#ifdef IRIS_FEATURE_TEXTURE_FILTERING
float sampleAlpha = sampleNearest(gtexture, _texcoord, gtexSize).a;
#else
float sampleAlpha = texture(gtexture, _texcoord).a;
#endif
firstHit = sampleAlpha > 0.1 ? firstHit : secondHit;
hit = firstHit.hit;
float fHit = float(hit);
shiftedCurrPos = mix(shiftedCurrPos, firstHit.currPos, fHit);
stepAxis = mix(stepAxis, firstHit.stepAxis, fHit);
}
void sortIntersectionOpaque(inout RayHit RayHit1, const in RayHit RayHit2, inout bool hit, inout vec3 shiftedCurrPos, inout vec3 stepAxis) {
bool useFirst = (RayHit1.hit && (!RayHit2.hit || RayHit1.t < RayHit2.t));
RayHit firstHit = useFirst ? RayHit1 : RayHit2;
RayHit secondHit = useFirst ? RayHit2 : RayHit1;
RayHit1 = firstHit;
hit = firstHit.hit;
float fHit = float(hit);
shiftedCurrPos = mix(shiftedCurrPos, firstHit.currPos, fHit);
stepAxis = mix(stepAxis, firstHit.stepAxis, fHit);
}
void fenceIntersection(inout vec3 shiftedCurrPos, const in vec3 reflectedVector, const in vec3 invReflectedVector, inout bool hit, const in vec3 floorOffsetWorldPos, const in vec3 floorOffsetWorldPos1, const in vec3 floorOffsetWorldPos2, inout vec3 stepAxis) {
RayHit hit1 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.375,0.001,0.375), floorOffsetWorldPos + vec3(0.625,0.999,0.625), stepAxis);
RayHit hit2 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos1, floorOffsetWorldPos2, stepAxis);
RayHit hit3 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos1 - vec3(0.0, 0.375, 0.0), floorOffsetWorldPos2 - vec3(0.0, 0.375, 0.0), stepAxis);
sortIntersectionOpaque(hit1, hit2, hit, shiftedCurrPos, stepAxis);
sortIntersectionOpaque(hit1, hit3, hit, shiftedCurrPos, stepAxis);
}
void fenceIntersection2(inout vec3 shiftedCurrPos, const in vec3 reflectedVector, const in vec3 invReflectedVector, inout bool hit, const in vec3 floorOffsetWorldPos, const in vec3 floorOffsetWorldPos1, const in vec3 floorOffsetWorldPos2, const in vec3 floorOffsetWorldPos3, const in vec3 floorOffsetWorldPos4, inout vec3 stepAxis) {
RayHit hit1 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.375,0.001,0.375), floorOffsetWorldPos + vec3(0.625,0.999,0.625), stepAxis);
RayHit hit2 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos1, floorOffsetWorldPos2, stepAxis);
RayHit hit3 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos1 - vec3(0.0, 0.375, 0.0), floorOffsetWorldPos2 - vec3(0.0, 0.375, 0.0), stepAxis);
RayHit hit4 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos3, floorOffsetWorldPos4, stepAxis);
RayHit hit5 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos3 - vec3(0.0, 0.375, 0.0), floorOffsetWorldPos4 - vec3(0.0, 0.375, 0.0), stepAxis);
sortIntersectionOpaque(hit1, hit2, hit, shiftedCurrPos, stepAxis);
sortIntersectionOpaque(hit1, hit3, hit, shiftedCurrPos, stepAxis);
sortIntersectionOpaque(hit1, hit4, hit, shiftedCurrPos, stepAxis);
sortIntersectionOpaque(hit1, hit5, hit, shiftedCurrPos, stepAxis);
}
#ifdef END_SHADER
const vec3 WsunVec = vec3(0.0, 1.0, 0.0);
#endif
bool traceQuarterVoxel(in vec3 reflectedVector, in vec3 invReflectedVector, in vec3 stepSizes, in vec3 voxelPos, in vec3 stepDir, in vec3 nextDist, in vec3 currPos) {
vec3 quarterVoxelPos = voxelPos / 4.0;
vec3 originalQuarterVoxelPos = quarterVoxelPos;
vec3 quarterNextDist = 4.0*((stepDir * 0.5 + 0.5) - fract(quarterVoxelPos)) * invReflectedVector;
// vec3 oldVoxelPos = quarterVoxelPos;
vec3 quarterCurrPos = currPos;
// vec3 oldCurrPos = currPos;
for (int i = 0; i < LpvSize/4; i++) {
float closestDist = min(min(quarterNextDist.x, quarterNextDist.y), quarterNextDist.z);
quarterCurrPos += reflectedVector * closestDist;
vec3 stepAxis = step(quarterNextDist, vec3(closestDist));
stepAxis.yz *= (1.0 - stepAxis.x);
stepAxis.z *= (1.0 - stepAxis.y);
quarterVoxelPos += stepAxis * stepDir;
if (clamp(quarterVoxelPos, ivec3(0), ivec3(VoxelSize3/4u)) != quarterVoxelPos) break;
uint blockID = imageLoad(imgQuarterVoxelMask, ivec3(quarterVoxelPos)).r;
if(blockID > 0u && quarterVoxelPos != originalQuarterVoxelPos) {
// voxelPos = oldVoxelPos * 4.0;
// currPos = oldCurrPos;
return true;
}
quarterNextDist += 4.0 * stepSizes * stepAxis - closestDist;
// oldVoxelPos = quarterVoxelPos;
// oldCurrPos = quarterCurrPos;
}
return false;
}
#endif
#if defined VOXEL_REFLECTIONS
vec4 voxelReflection(
vec3 reflectedVector,
vec3 flatNormal,
vec3 normal,
vec3 origin,
float noise,
inout float backgroundReflectMask
) {
// vec3 invReflectedVector = 1.0 / reflectedVector;
// vec3 stepSizes = abs(invReflectedVector);
// vec3 voxelPos = GetLpvPosition(origin - 0.000055*normal);
// vec3 originalVoxelPos = voxelPos;
// vec3 stepDir = sign(reflectedVector);
// vec3 nextDist = (stepDir * 0.5 + 0.5 - fract(voxelPos)) * invReflectedVector;
// vec3 currPos = origin;
//#ifdef OVERWORLD_SHADER
vec3 DirectLightColor = lightSourceColorSSBO / 1400.0;
vec3 AmbientLightColor = averageSkyCol_CloudsSSBO / 900.0;
#ifdef USE_CUSTOM_DIFFUSE_LIGHTING_COLORS
DirectLightColor = luma(DirectLightColor) * vec3(DIRECTLIGHT_DIFFUSE_R,DIRECTLIGHT_DIFFUSE_G,DIRECTLIGHT_DIFFUSE_B);
AmbientLightColor = luma(AmbientLightColor) * vec3(INDIRECTLIGHT_DIFFUSE_R,INDIRECTLIGHT_DIFFUSE_G,INDIRECTLIGHT_DIFFUSE_B);
#endif
AmbientLightColor *= ambient_brightness;
//#endif
// vec2 gtexSize = vec2(1.0) / textureSize(gtexture, 0);
// vec2 texCoordOffset = vec2(TEXTURE_RESOLUTION * 0.5) * gtexSize;
vec4 color = vec4(0.0);
//bool quarterHit = traceQuarterVoxel(reflectedVector, invReflectedVector, stepSizes, voxelPos, stepDir, nextDist, currPos);
// uint traceDist = LpvSize;
// if(!quarterHit) {
// traceDist = 6u;
// }
// for (uint i = 0; i < traceDist; i++) {
// float closestDist = min(min(nextDist.x, nextDist.y), nextDist.z);
// currPos += reflectedVector * closestDist;
//
// vec3 stepAxis = step(nextDist, vec3(closestDist));
// stepAxis.yz *= (1.0 - stepAxis.x);
// stepAxis.z *= (1.0 - stepAxis.y);
//
// voxelPos += stepAxis * stepDir;
// if (clamp(voxelPos, ivec3(0), ivec3(VoxelSize3-1u)) != voxelPos) break;
//
// uint blockID = GetVoxelBlock(ivec3(voxelPos));
//
// vec3 shiftedCurrPos = currPos;
// vec3 originalStepAxis = stepAxis;
//
// #ifdef DEFERRED_SPECULAR
// bool hit = blockID != BLOCK_EMPTY && blockID != 80 && voxelPos != originalVoxelPos && blockID != BLOCK_LPV_IGNORE;
// #else
// bool hit = blockID != BLOCK_EMPTY && blockID != BLOCK_WATER && blockID != 80 && voxelPos != originalVoxelPos && blockID != BLOCK_LPV_IGNORE;
// #endif
//
// #ifdef MIRROR_IRON
// if (blockID == 504) {
// traceDist = LpvSize;
// hit = false;
// vec3 voxelNormal = -originalStepAxis * stepDir;
// reflectedVector = reflect(reflectedVector, voxelNormal);
// invReflectedVector = 1.0 / reflectedVector;
// stepSizes = abs(invReflectedVector);
// voxelPos = GetLpvPosition(currPos - 0.000055*voxelNormal);
// originalVoxelPos = voxelPos;
// stepDir = sign(reflectedVector);
// nextDist = (stepDir * 0.5 + 0.5 - fract(voxelPos)) * invReflectedVector;
// } else
// #endif
// {
// nextDist += stepSizes * originalStepAxis - closestDist;
// }
//
// if(!hit) continue;
//
// vec3 offsetWorldPos = shiftedCurrPos + cameraPosition + stepAxis*stepDir*0.00015;
// vec3 fractOffsetWorldPos = fract(offsetWorldPos);
// vec3 floorOffsetWorldPos = floor(offsetWorldPos) - cameraPosition;
// vec3 worldPosSampleOffset = vec3(0.0);
//
// // I hope nobody ever looks at this shit
// if(blockID >= 12 && blockID < 424) {
// if(blockID >= 22 && blockID < 38) {
// if(blockID == 22) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.375,0.001,0.375), floorOffsetWorldPos + vec3(0.625,0.999,0.625), stepAxis);
// else if(blockID == 23) fenceIntersection(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.375), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), stepAxis);
// else if(blockID == 24) fenceIntersection(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.625, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// else if(blockID == 25) fenceIntersection(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.625), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.999), stepAxis);
// else if(blockID == 26) fenceIntersection(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.375, 0.9375, 0.5625), stepAxis);
// else if(blockID == 27) fenceIntersection(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.999), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), stepAxis);
// else if(blockID == 28) fenceIntersection(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// else if(blockID == 29) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.375), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), floorOffsetWorldPos + vec3(0.625, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// else if(blockID == 30) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.375), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.375, 0.9375, 0.5625), stepAxis);
// else if(blockID == 31) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.625), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.999), floorOffsetWorldPos + vec3(0.625, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// else if(blockID == 32) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.625), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.999), floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.375, 0.9375, 0.5625), stepAxis);
// else if(blockID == 33) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.375), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// else if(blockID == 34) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.999), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), floorOffsetWorldPos + vec3(0.625, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// else if(blockID == 35) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.625), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.999), floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// else if(blockID == 36) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.375, 0.9375, 0.5625), floorOffsetWorldPos + vec3(0.4375, 0.75, 0.999), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), stepAxis);
// else if(blockID == 37) fenceIntersection2(shiftedCurrPos, reflectedVector, invReflectedVector, hit, floorOffsetWorldPos, floorOffsetWorldPos + vec3(0.4375, 0.75, 0.999), floorOffsetWorldPos + vec3(0.5625, 0.9375, 0.001), floorOffsetWorldPos + vec3(0.001, 0.75, 0.4375), floorOffsetWorldPos + vec3(0.999, 0.9375, 0.5625), stepAxis);
// }
// else if(blockID == BLOCK_TORCH || blockID == BLOCK_REDSTONE_TORCH_LIT || blockID == BLOCK_COPPER_TORCH || blockID == BLOCK_SOUL_TORCH || blockID == BLOCK_UNLIT_REDSTONE_TORCH) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5625,0.0,0.5625), floorOffsetWorldPos + vec3(0.4375,0.625,0.4375), stepAxis);
// worldPosSampleOffset.y = 0.1875;
// }
// else if(blockID == BLOCK_LANTERN || blockID == BLOCK_SOUL_LANTERN || blockID == BLOCK_COPPER_LANTERN) {
// RayHit hit1 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.3125,0.001,0.3125), floorOffsetWorldPos + vec3(0.6875,0.4375,0.6875), stepAxis);
// RayHit hit2 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.375,0.4375,0.375), floorOffsetWorldPos + vec3(0.625,0.5625,0.625), stepAxis);
//
// sortIntersectionOpaque(hit1, hit2, hit, shiftedCurrPos, stepAxis);
//
// // thank you mojank for making the texture layout different on all three lantern types
// worldPosSampleOffset.y = 0.28125;
// #if MC_VERSION >= 12111
// if(blockID == BLOCK_LANTERN){
// worldPosSampleOffset.xz = vec2(-0.0625);
// } else if(blockID == BLOCK_SOUL_LANTERN){
// worldPosSampleOffset.xz = vec2(-0.1875);
// } else if(blockID == BLOCK_COPPER_LANTERN){
// worldPosSampleOffset.xz = vec2(0.0625);
// }
// worldPosSampleOffset.z = mix(worldPosSampleOffset.z, 0.0, abs(stepAxis.y));
// #else
// if(blockID == BLOCK_LANTERN || blockID == BLOCK_SOUL_LANTERN){
// worldPosSampleOffset.xz = vec2(0.0625);
// worldPosSampleOffset.z = mix(worldPosSampleOffset.z, 0.0, abs(stepAxis.y));
// }
// #endif
// }
// else if(blockID >= 12 && blockID <= 178) {
// if (blockID == 178 || blockID >= 12 && blockID <= 21 || blockID == BLOCK_GROUND_WAVING || blockID >= BLOCK_SSS_STRONG3 && blockID <= 88) {
// RayHit hit1 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0, 0.0, 0.4999), floorOffsetWorldPos + vec3(1.0, 1.0, 0.5001), stepAxis);
// RayHit hit2 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.4999, 0.0, 0.0), floorOffsetWorldPos + vec3(0.5001, 1.0, 1.0), stepAxis);
//
// sortIntersectionCutout(hit1, hit2, stepDir, gtexSize, texCoordOffset, voxelPos, hit, shiftedCurrPos, stepAxis);
// }
// else if(blockID == BLOCK_CACTUS) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0625,0.0,0.0625), floorOffsetWorldPos + vec3(0.9375,0.9999,0.9375), stepAxis);
// else if(blockID == BLOCK_BUTTON_FLOOR_NORTH_SOUTH) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.3125,0.0,0.375), floorOffsetWorldPos + vec3(0.6875,0.125,0.625), stepAxis);
// worldPosSampleOffset.y = 0.5;
// }
// else if(blockID == BLOCK_BUTTON_FLOOR_EAST_WEST) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.375,0.0,0.3125), floorOffsetWorldPos + vec3(0.625,0.125,0.6875), stepAxis);
// worldPosSampleOffset.y = 0.5;
// }
// else if(blockID == BLOCK_BUTTON_WALL_NORTH) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.6875,0.625,0.875), floorOffsetWorldPos + vec3(0.3125,0.375,1.0), stepAxis);
// else if(blockID == BLOCK_BUTTON_WALL_EAST) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.125,0.625,0.6875), floorOffsetWorldPos + vec3(0.0,0.375,0.3125), stepAxis);
// else if(blockID == BLOCK_BUTTON_WALL_SOUTH) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.6875,0.625,0.125), floorOffsetWorldPos + vec3(0.3125,0.375,0.0), stepAxis);
// else if(blockID == BLOCK_BUTTON_WALL_WEST) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.875,0.375,0.3125), floorOffsetWorldPos + vec3(1.0,0.625,0.6875), stepAxis);
// else if(blockID == BLOCK_BUTTON_CEILING_NORTH_SOUTH) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.3125,1.0,0.375), floorOffsetWorldPos + vec3(0.6875,0.875 ,0.625), stepAxis);
// else if(blockID == BLOCK_BUTTON_CEILING_EAST_WEST) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.375,1.0,0.3125), floorOffsetWorldPos + vec3(0.625,0.875,0.6875), stepAxis);
// else if(blockID == BLOCK_LEVER) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.375,1.0,0.3125), floorOffsetWorldPos + vec3(0.625,0.875,0.6875), stepAxis);
// } else if(blockID >= 401 && blockID < 424) {
// if(blockID >= 401 && blockID < 416) {
// if(blockID == BLOCK_CARPET && fractOffsetWorldPos.y > 0.0625) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,0.0), floorOffsetWorldPos + vec3(1.0,0.0625,1.0), stepAxis);
// else if(blockID == BLOCK_PRESSURE_PLATE) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0625,0.0,0.0625), floorOffsetWorldPos + vec3(0.9375,0.0625,0.9375), stepAxis);
// else if (blockID == 407) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001,0.9999,0.0001), floorOffsetWorldPos + vec3(0.9999,0.5,0.9999), stepAxis);
// worldPosSampleOffset.y = -0.25;
// }
// else if (blockID == 408) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001,0.0001,0.0001), floorOffsetWorldPos + vec3(0.9999,0.5,0.9999), stepAxis);
// worldPosSampleOffset.y = 0.25;
// }
// else if (blockID == BLOCK_SNOW_LAYERS && fractOffsetWorldPos.y > 0.125) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos, floorOffsetWorldPos + vec3(1.0,0.125,1.0), stepAxis);
// else if (blockID == BLOCK_TRAPDOOR_BOTTOM) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001,0.0001,0.0001), floorOffsetWorldPos + vec3(0.9999,0.1875,0.9999), stepAxis);
// worldPosSampleOffset.y = 0.40625;
// }
// else if (blockID == BLOCK_TRAPDOOR_TOP && fractOffsetWorldPos.y < 0.8125) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,1.0,0.0), floorOffsetWorldPos + vec3(1.0,0.8125,1.0), stepAxis);
// else if (blockID == BLOCK_TRAPDOOR_N || blockID == BLOCK_DOOR_N) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.9999,0.9999,0.8125), floorOffsetWorldPos + vec3(0.0001,0.0001,0.9999), stepAxis);
//
// if(blockID == BLOCK_DOOR_N) {
// worldPosSampleOffset.z = mix(-0.5, -0.40625, abs(stepAxis.y));
// } else {
// worldPosSampleOffset.z = mix(0.5, -0.40625, abs(stepAxis.y));
// }
// }
// else if ((blockID == BLOCK_TRAPDOOR_E || blockID == BLOCK_DOOR_E)) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.1875,0.9999,0.9999), floorOffsetWorldPos + vec3(0.0001,0.0001,0.0001), stepAxis);
//
// if(blockID == BLOCK_DOOR_E) {
// worldPosSampleOffset.x = mix(-0.5, 0.0, abs(stepAxis.y));
// worldPosSampleOffset.z = mix(0.0, -0.40625, abs(stepAxis.y));
// } else {
// worldPosSampleOffset.x = mix(0.5, 0.0, abs(stepAxis.y));
// worldPosSampleOffset.z = mix(0.0, 0.40625, abs(stepAxis.y));
// }
// }
// else if (blockID == BLOCK_TRAPDOOR_S || blockID == BLOCK_DOOR_S) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.9999,0.9999,0.1875), floorOffsetWorldPos + vec3(0.0001,0.0001,0.0001), stepAxis);
//
// if(blockID == BLOCK_DOOR_S) {
// worldPosSampleOffset.z = mix(-0.5, 0.34375, abs(stepAxis.y));
// } else {
// worldPosSampleOffset.z = mix(0.5, 0.40625, abs(stepAxis.y));
// }
// }
// else if (blockID == BLOCK_TRAPDOOR_W || blockID == BLOCK_DOOR_W) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.8125,0.9999,0.9999), floorOffsetWorldPos + vec3(0.9999,0.0001,0.0001), stepAxis);
//
// if(blockID == BLOCK_DOOR_W) {
// worldPosSampleOffset.x = mix(-0.5, 0.0, abs(stepAxis.y));
// worldPosSampleOffset.z = mix(0.0, -0.40625, abs(stepAxis.y));
// } else {
// worldPosSampleOffset.x = mix(0.5, 0.0, abs(stepAxis.y));
// worldPosSampleOffset.z = mix(0.0, 0.40625, abs(stepAxis.y));
// }
// }
// }
// else if (blockID >= 416 && blockID < 424) {
// if(blockID == 416 && fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.z > 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,1.0), floorOffsetWorldPos + vec3(1.0,0.5,0.5), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.5,0.5), floorOffsetWorldPos + vec3(1.0,1.0,0.0), stepAxis) || hit;
// } else if(blockID == 417 && fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.x < 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.0,0.0), floorOffsetWorldPos + vec3(0.0,0.5,1.0), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.5,0.0), floorOffsetWorldPos + vec3(1.0,1.0,1.0), stepAxis) || hit;
// } else if(blockID == 418 && fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.z < 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,0.0), floorOffsetWorldPos + vec3(1.0,0.5,0.5), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.5,0.5), floorOffsetWorldPos + vec3(1.0,1.0,1.0), stepAxis) || hit;
// } else if(blockID == 419) {
// if(fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.x > 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.0,0.0), floorOffsetWorldPos + vec3(1.0,0.5,1.0), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.5,0.0), floorOffsetWorldPos + vec3(0.0,1.0,1.0), stepAxis) || hit;
// }
//
// worldPosSampleOffset.y = -0.25;
// worldPosSampleOffset.z = mix(0.0, -0.25, abs(stepAxis.y));
//
// } else if(blockID == 420 && fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.x < 0.5 && fractOffsetWorldPos.z < 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,0.0), floorOffsetWorldPos + vec3(0.5,0.5,0.5), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.5,0.5), floorOffsetWorldPos + vec3(0.5,1.0,1.0), stepAxis) || hit;
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.5,0.0), floorOffsetWorldPos + vec3(1.0,1.0,0.5), stepAxis) || hit;
// } else if(blockID == 421 && fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.x > 0.5 && fractOffsetWorldPos.z < 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.0,0.0), floorOffsetWorldPos + vec3(1.0,0.5,0.5), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(1.0,0.5,0.5), floorOffsetWorldPos + vec3(0.5,1.0,1.0), stepAxis) || hit;
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,1.0,0.5), floorOffsetWorldPos + vec3(0.0,0.5,0.0), stepAxis) || hit;
// } else if(blockID == 422) {
// if(fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.x > 0.5 && fractOffsetWorldPos.z > 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.0,0.5), floorOffsetWorldPos + vec3(1.0,0.5,1.0), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,0.5,0.5), floorOffsetWorldPos + vec3(0.0,1.0,1.0), stepAxis) || hit;
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,1.0,0.5), floorOffsetWorldPos + vec3(1.0,0.5,0.0), stepAxis) || hit;
// }
//
// worldPosSampleOffset.y = -0.25;
// worldPosSampleOffset.z = mix(0.0, -0.25, abs(stepAxis.y));
// } else if(blockID == 423 && fractOffsetWorldPos.y > 0.5 && fractOffsetWorldPos.x < 0.5 && fractOffsetWorldPos.z > 0.5) {
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,0.5), floorOffsetWorldPos + vec3(0.5,0.5,1.0), stepAxis);
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,1.0,0.5), floorOffsetWorldPos + vec3(0.5,0.5,0.0), stepAxis) || hit;
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.5,1.0,0.5), floorOffsetWorldPos + vec3(1.0,0.5,1.0), stepAxis) || hit;
// }
// }
// } else if (blockID >= 267 && blockID <= 291) {
// if(blockID == BLOCK_HOPPER) {
// RayHit hit1 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.25, 0.25, 0.25), floorOffsetWorldPos + vec3(0.75, 0.625, 0.75), stepAxis);
// RayHit hit2 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001, 0.625, 0.0001), floorOffsetWorldPos + vec3(0.9999, 0.9999, 0.125), stepAxis);
// RayHit hit3 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001, 0.625, 0.0001), floorOffsetWorldPos + vec3(0.125, 0.9999, 0.9999), stepAxis);
// RayHit hit4 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.875, 0.625, 0.0001), floorOffsetWorldPos + vec3(0.9999, 0.9999, 0.9999), stepAxis);
// RayHit hit5 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001, 0.625, 0.875), floorOffsetWorldPos + vec3(0.9999, 0.9999, 0.9999), stepAxis);
// RayHit hit6 = AABBintersection2(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001, 0.625, 0.0001), floorOffsetWorldPos + vec3(0.9999, 0.6875, 0.9999), stepAxis);
//
// sortIntersectionOpaque(hit1, hit2, hit, shiftedCurrPos, stepAxis);
// sortIntersectionOpaque(hit1, hit3, hit, shiftedCurrPos, stepAxis);
// sortIntersectionOpaque(hit1, hit4, hit, shiftedCurrPos, stepAxis);
// sortIntersectionOpaque(hit1, hit5, hit, shiftedCurrPos, stepAxis);
// sortIntersectionOpaque(hit1, hit6, hit, shiftedCurrPos, stepAxis);
// worldPosSampleOffset.y = -0.34375;
//
// worldPosSampleOffset.z = mix(0.0, -0.34375, abs(stepAxis.y));
// }
// if(blockID == BLOCK_ENCHANTING_TABLE) {
// worldPosSampleOffset.y = 0.125;
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001,0.0001,0.0001), floorOffsetWorldPos + vec3(0.9999,0.75,0.9999), stepAxis);
// }
// else if(blockID == BLOCK_END_PORTAL_FRAME) {
// worldPosSampleOffset.y = 0.09375;
// hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0001,0.0001,0.0001), floorOffsetWorldPos + vec3(0.9999,0.8125,0.9999), stepAxis);
// }
// else if(blockID == BLOCK_GLOW_LICHEN_NORTH || blockID == BLOCK_SCULK_VEIN_NORTH || blockID == BLOCK_VINE_NORTH) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,0.0001), floorOffsetWorldPos + vec3(1.0,1.0,0.001), stepAxis);
// else if(blockID == BLOCK_GLOW_LICHEN_EAST || blockID == BLOCK_SCULK_VEIN_EAST || blockID == BLOCK_VINE_EAST) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.999,0.0,0.0), floorOffsetWorldPos + vec3(0.9999,1.0,1.0), stepAxis);
// else if(blockID == BLOCK_GLOW_LICHEN_SOUTH || blockID == BLOCK_SCULK_VEIN_SOUTH || blockID == BLOCK_VINE_SOUTH) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,0.999), floorOffsetWorldPos + vec3(1.0,1.0,0.9999), stepAxis);
// else if(blockID == BLOCK_GLOW_LICHEN_WEST || blockID == BLOCK_SCULK_VEIN_WEST || blockID == BLOCK_VINE_WEST) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.001,1.0,1.0), floorOffsetWorldPos + vec3(0.0001,0.0,0.0), stepAxis);
// else if(blockID == BLOCK_GLOW_LICHEN_UP || blockID == BLOCK_SCULK_VEIN_UP || blockID == BLOCK_VINE_UP) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.999,0.0), floorOffsetWorldPos + vec3(1.0,0.9999,1.0), stepAxis);
// else if(blockID == BLOCK_GLOW_LICHEN_DOWN || blockID == BLOCK_SCULK_VEIN_DOWN) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0001,0.0), floorOffsetWorldPos + vec3(1.0,0.001,1.0), stepAxis);
// else if (blockID == BLOCK_DAYLIGHT_DETECTOR && fractOffsetWorldPos.y > 0.375) hit = AABBintersection(shiftedCurrPos, reflectedVector, invReflectedVector, floorOffsetWorldPos + vec3(0.0,0.0,0.0), floorOffsetWorldPos + vec3(1.0,0.375,1.0), stepAxis);
// } else if (blockID >= 319 && blockID < 335) {
//
//
// }
// }
//
// // if(length(currPos) > 50) return vec4(10.0);
// // if(hit) return vec4(0.0,0.0,0.0,1.0);
//
// if(hit){
// vec2 texcoord;
// vec3 tint;
// vec3 voxelNormal = -stepAxis * stepDir;
//
// vec2 lightmap;
// GetVoxelData(ivec3(voxelPos), texcoord, tint, voxelNormal, lightmap);
//
// vec3 wPos = shiftedCurrPos + cameraPosition;
// vec3 fractWpos = fract(wPos);
// fractWpos += worldPosSampleOffset;
// vec2 sampleDir = stepAxis.x * fractWpos.zy + stepAxis.y * fractWpos.xz + stepAxis.z * fractWpos.xy;
// texcoord = mix(texcoord + vec2(0, texCoordOffset.y), texcoord - vec2(0, texCoordOffset.y), sampleDir);
// texcoord = mix(texcoord + vec2(texCoordOffset.x, 0), texcoord - vec2(texCoordOffset.x, 0), sampleDir);
//
// #ifdef IRIS_FEATURE_TEXTURE_FILTERING
// vec4 sampleColor = sampleNearest(gtexture, texcoord, gtexSize);
// #else
// vec4 sampleColor = texture(gtexture, texcoord);
// #endif
//
// if(sampleColor.a > 0.1){
// vec3 albedo = sampleColor.rgb;
// albedo *= tint;
//
// albedo = toLinear(albedo);
//
// //#if defined OVERWORLD_SHADER
//
// float SkylightDir = voxelNormal.y;
//
// SkylightDir = SkylightDir*0.5+0.5;
//
// float skylight = mix(0.08 + 0.92*(1.0-lightmap.y), 1.0, SkylightDir);
//
// vec3 Indirect_lighting = 0.525*doIndirectLighting(AmbientLightColor * skylight, vec3(1.0), lightmap.y);
// //#endif
//
// vec3 lpvPos = GetLpvPosition(shiftedCurrPos);
//
// #ifdef MAIN_SHADOW_PASS
// float smoothSkylight;
// Indirect_lighting += doBlockLightLighting(vec3(TORCH_R,TORCH_G,TORCH_B), lightmap.x, shiftedCurrPos, lpvPos, vec3(0.0), false, noise, voxelNormal, false);
// #else
// Indirect_lighting += doBlockLightLighting(vec3(TORCH_R,TORCH_G,TORCH_B), lightmap.x, shiftedCurrPos, lpvPos);
// #endif
//
// // vec3 AO = vec3(pow(1.0 - vanillaAO*vanillaAO,5.0));
// // Indirect_lighting *= AO;
//
// float shadowMapFalloff = smoothstep(0.0, 1.0, min(max(1.0 - length(shiftedCurrPos) / (shadowDistance+16),0.0)*5.0,1.0));
// float sh = ComputeVoxelShadowMap(DirectLightColor, shiftedCurrPos, shadowMapFalloff, noise, voxelNormal);
//
// float lightLeakFix = clamp(pow(eyeBrightnessSmooth.y/240. + lightmap.y,2.0) ,0.0,1.0);
// sh *= lightLeakFix;
//
// #ifdef OVERWORLD_SHADER
// sh *= GetCloudShadow(wPos, WsunVec);
// #endif
//
// float NdotL;
//
// if(blockID == BLOCK_SSS_STRONG || blockID == BLOCK_SSS_STRONG3 || blockID == BLOCK_AIR_WAVING || blockID == BLOCK_SSS_STRONG_2 ||
// blockID == BLOCK_GROUND_WAVING || blockID == BLOCK_GROUND_WAVING_VERTICAL ||
// blockID == BLOCK_GRASS_SHORT || blockID == BLOCK_GRASS_TALL_UPPER || blockID == BLOCK_GRASS_TALL_LOWER ||
// blockID == BLOCK_SSS_WEAK || blockID == BLOCK_CACTUS || blockID == BLOCK_SSS_WEAK_2 ||
// blockID == BLOCK_CELESTIUM || (blockID >= 269 && blockID <= 274) || blockID == BLOCK_SNOW_LAYERS || blockID == BLOCK_CARPET ||
// blockID == BLOCK_AMETHYST_BUD_MEDIUM || blockID == BLOCK_AMETHYST_BUD_LARGE || blockID == BLOCK_AMETHYST_CLUSTER ||
// blockID == BLOCK_BAMBOO || blockID == BLOCK_SAPLING || (blockID >= BLOCK_VINE_NORTH && blockID <= BLOCK_VINE_UP) || blockID == BLOCK_VINE_OTHER)
// {
// NdotL = 1.0;
// } else {
// NdotL = clamp((-15.0 + dot(voxelNormal, WsunVec)*255.0) / 240.0, 0.0, 1.0);
// }
//
// vec3 finalColor = albedo * (Indirect_lighting + DirectLightColor * sh * NdotL);
//
// float EMISSIVE = 0.0;
//
// // normal block lightsources
// if(blockID >= 100 && blockID < 282) {
// EMISSIVE = 0.5;
//
// if(blockID == 266 || (blockID >= 276 && blockID <= 281)) EMISSIVE = 0.2; // sculk stuff
//
// else if(blockID == 195) EMISSIVE = 2.3; // glow lichen
//
// else if(blockID == 185) EMISSIVE = 1.5; // crying obsidian
//
// else if(blockID == 105) EMISSIVE = 2.0; // brewing stand
//
// else if(blockID == 236) EMISSIVE = 1.0; // respawn anchor
//
// else if(blockID == 101) EMISSIVE = 0.7; // large amethyst bud
//
// else if(blockID == 103) EMISSIVE = 1.0; // amethyst cluster
//
// else if(blockID == 244) EMISSIVE = 1.5; // soul fire
//
// EMISSIVE *= getVoxelEmission(albedo);
//
// voxelEmission(finalColor, albedo, EMISSIVE);
// }
//
// #if EMISSIVE_ORES > 0
// if(blockID == 502) {
// EMISSIVE = EMISSIVE_ORES_STRENGTH;
//
// EMISSIVE *= getVoxelEmission(albedo);
//
// voxelEmission(finalColor, albedo, EMISSIVE);
// }
// #endif
//
// sampleColor.a *= (1.0 - color.a);
//
// color.rgb += finalColor * sampleColor.a;
//
// color.a += sampleColor.a;
//
// // if(dot(reflectedVector, normal) < 0.0) return vec4(color.rgb, 1.0);
// #if defined DEFERRED_SPECULAR
// if(blockID == BLOCK_WATER) {
// if(abs(voxelNormal.y) > 0.1){
// vec3 waterPos = (wPos).xzy;
//
// vec3 bump = normalize(getWaveNormal(waterPos, shiftedCurrPos));
//
// float bumpmult = WATER_WAVE_STRENGTH;
//
// bump = bump * vec3(bumpmult, bumpmult, bumpmult) + vec3(0.0f, 0.0f, 1.0f - bumpmult);
//
// voxelNormal.xz = bump.xy;
// }
// vec3 backgroundReflection = skyCloudsFromTex(reflect(reflectedVector, voxelNormal), colortex4).rgb / 1200.0;
//
// const float f0 = 0.02;
// float normalDotEye = dot(voxelNormal, reflectedVector);
// float fresnel = pow(clamp(1.0 + normalDotEye, 0.0, 1.0),5.0);
//
// fresnel = mix(f0, 1.0, fresnel);
//
// color.rgb = mix(color.rgb, backgroundReflection * min(max(lightmap.y-0.5,0.0)/0.4,1.0), fresnel);
// // color.rgb += SunReflection*SSR_HIT_SKY_MASK;
//
// // color.a = color.a + (1.0-color.a) * fresnel;
// return vec4(color.rgb, 1.0);
// }
// #endif
//
// if(color.a > 0.99) return vec4(color.rgb, 1.0);
// }
// }
//
// // if(hit) return color; // vec4(0.2, 0.87, 0.2, 1.0);
// }
backgroundReflectMask = 1.0;
return color;
}
#endif
#if defined OVERWORLD_SHADER || defined END_ISLAND_LIGHT && defined END_SHADER
vec2 CleanPhotonicsSample(
int samples, float totalSamples, float noise
){
// this will be used to make 1 full rotation of the spiral. the mulitplication is so it does nearly a single rotation, instead of going past where it started
float variance = noise * 0.897;
// for every sample input, it will have variance applied to it.
float variedSamples = float(samples) + variance;
// for every sample, the sample position must change its distance from the origin.
// otherwise, you will just have a circle.
float spiralShape = sqrt(variedSamples / (totalSamples + variance));
float shape = 2.26; // this is very important. 2.26 is very specific
float theta = variedSamples * (PI * shape);
float x = cos(theta) * spiralShape;
float y = sin(theta) * spiralShape;
return vec2(x, y);
}
float ComputePhotonicsShadowMap(inout vec3 directLightColor, vec3 playerPos, float maxDistFade, float noise, in vec3 geoNormals){
// if(maxDistFade <= 0.0) return 1.0;
// setup shadow projection
#ifdef OVERWORLD_SHADER
#ifdef CUSTOM_MOON_ROTATION
vec3 projectedShadowPosition = mat3(customShadowMatrixSSBO) * playerPos + customShadowMatrixSSBO[3].xyz;
#else
vec3 projectedShadowPosition = mat3(shadowModelView) * playerPos + shadowModelView[3].xyz;
#endif
applyShadowBias(projectedShadowPosition, playerPos, geoNormals);
projectedShadowPosition = diagonal3(shadowProjection) * projectedShadowPosition + shadowProjection[3].xyz;
// un-distort
#ifdef DISTORT_SHADOWMAP
float distortFactor = calcDistort(projectedShadowPosition.xy);
projectedShadowPosition.xy *= distortFactor;
#else
float distortFactor = 1.0;
#endif
projectedShadowPosition.z += shadowProjection[3].z * 0.0012;
#else
float distortFactor = 1.0;
#endif
#if defined END_ISLAND_LIGHT && defined END_SHADER
vec4 shadowPos = customShadowMatrixSSBO * vec4(playerPos, 1.0);
applyShadowBias(shadowPos.xyz, playerPos, geoNormals);
shadowPos = customShadowPerspectiveSSBO * shadowPos;
vec3 projectedShadowPosition = shadowPos.xyz / shadowPos.w;
#endif
// hamburger
projectedShadowPosition = projectedShadowPosition * vec3(0.5,0.5,0.5/6.0) + vec3(0.5);
float shadowmap = 0.0;
vec3 translucentTint = vec3(0.0);
#ifdef BASIC_SHADOW_FILTER
int samples = int(SHADOW_FILTER_SAMPLE_COUNT * 0.5);
#ifdef END_SHADER
float rdMul = 52.0*d0k;
#else
float rdMul = 2.4*distortFactor*d0k;
#endif
for(int i = 0; i < samples; i++){
vec2 offsetS = CleanPhotonicsSample(i, samples - 1, noise) * rdMul;
projectedShadowPosition.xy += offsetS;
#else
int samples = 1;
#endif
#ifdef TRANSLUCENT_COLORED_SHADOWS
// determine when opaque shadows are overlapping translucent shadows by getting the difference of opaque depth and translucent depth
float shadowDepthDiff = pow(clamp((texture(shadowtex1, projectedShadowPosition).x - projectedShadowPosition.z) * 2.0,0.0,1.0),2.0);
// get opaque shadow data to get opaque data from translucent shadows.
float opaqueShadow = texture(shadowtex0, projectedShadowPosition).x;
shadowmap += max(opaqueShadow, shadowDepthDiff);
// get translucent shadow data
vec4 translucentShadow = texture(shadowcolor0, projectedShadowPosition.xy);
// this curve simply looked the nicest. it has no other meaning.
float shadowAlpha = pow(1.0 - pow(translucentShadow.a,5.0),0.2);
// normalize the color to remove luminance, and keep the hue. remove all opaque color.
// mulitply shadow alpha to shadow color, but only on surfaces facing the lightsource. this is a tradeoff to protect subsurface scattering's colored shadow tint from shadow bias on the back of the caster.
translucentShadow.rgb = max(normalize(translucentShadow.rgb + 0.0001), max(opaqueShadow, 1.0-shadowAlpha)) * shadowAlpha;
// make it such that full alpha areas that arent in a shadow have a value of 1.0 instead of 0.0
translucentTint += mix(translucentShadow.rgb, vec3(1.0), opaqueShadow*shadowDepthDiff);
#else
shadowmap += texture(shadow, projectedShadowPosition).x;
#endif
#ifdef BASIC_SHADOW_FILTER
}
#endif
#ifdef TRANSLUCENT_COLORED_SHADOWS
// tint the lightsource color with the translucent shadow color
directLightColor *= mix(vec3(1.0), translucentTint.rgb / samples, maxDistFade);
#endif
float shadowResult = shadowmap / samples;
#ifdef END_SHADER
float r = length(projectedShadowPosition.xy - vec2(0.5));
if (r < 0.5 && abs(projectedShadowPosition.z) < 1.0) {
shadowResult *= smoothstep(0.5, 0.25, r);
} else {
shadowResult = 0.0;
}
#endif
return shadowResult;
// return mix(1.0, shadowmap / samples, maxDistFade);
}
#endif
#if defined PHOTONICS_INCLUDED && defined PHOTONICS && defined VOXEL_REFLECTIONS
struct translucentHit {
vec3 hitNormal;
vec3 hitPos;
vec4 hitColor;
int hitID;
float skylight;
};
void trace_wsr(inout RayJob job, bool transparency, inout translucentHit[10] translucentHitRays, inout uint translucentHits, out int block_id, out float skylightmap) {
job.direction = normalize(job.direction);
vec3 direction_inv = 1.0f / job.direction;
float t0 = intersects_world(direction_inv, 16.0f * job.origin);
if (t0 == -1.0f) {
job.result_position = vec3(47823934.0f) - world_offset;
return;
}
vec3 position = job.origin * 16.0f + (t0 + 0.03f) * job.direction;
// vec3 position = 16.0f * job.origin;
vec3 ray_direction_sign = sign(job.direction);
ivec3 intersection_index = ivec3(7.5f * ray_direction_sign + vec3(7.5f, 12.5f, 17.5f));
vec3 skipDelta = ray_direction_sign * 0.00001f;
ivec3 intersection_offset = max(ivec3(ray_direction_sign), 0);
int t_min = -1;
int block_index = -1;
block_id = -1;
int voxel_index = 0;
ivec3 new_index = ivec3(0);
ivec3 old_index = ivec3(0);
ivec3 entries = ivec3(0);
result_tint_color = vec3(1f);
int previous_block_id = -1;
for (int i = RAY_ITERATION_COUNT; !(ray_iteration_bound_reached = i < 0); i--) {
// debug += vec3(0.1f);
ivec3 w = ivec3(position); // TODO: maybe use uvec3, no negative check neccessary
// ivec3 block_position = w >> 4;
if (!is_inside(position)) // outside of world?
return;
// if ((job.result_hit = block_position == ray_target)) { // ray target reached?
// break;
// }
// if (ray_constraint != ivec3(-9999) && block_position != ray_constraint)
// return;
int scale = 0;
int entry = 0;
new_index.x = get_world_index((w >> 8) & 31);
if (new_index.x != old_index.x) { // TODO: CRITICAL! UBOs are too tiny for 32x32x32
entries.x = root_array[new_index.x];
}
if (entries.x < 0) { // found chunk?
ivec3 block_pos = (w >> 4) & 15;
new_index.y = -entries.x + get_index(block_pos);
if (new_index.y != old_index.y) {
entries.y = cb_array[new_index.y];
if (entries.y < 0) { // found block
int block_data = -entries.y;
block_index = block_data & 0xfff;
block_index = block_index * (ph_byte_size / 4);
ph_result_sky_brightness = block_data >> 12;
block_id = cb_array[block_index];
voxel_index = block_index + 2;
} else {
block_index = -1;
}
}
if (block_index != -1) { // found block
ivec3 voxel_pos = w & 15;
new_index.z = voxel_index + get_index(voxel_pos);
if (new_index.z != old_index.z) {
entries.z = cb_array[new_index.z];
//if (breakOnEmpty && entries.z == 519536640) {
// job.result_hit = true;
// entries.z = -0;
//
// break;
//}
}
if (entries.z < 0) { // found bloxel
#ifdef MIRROR_IRON
if(block_id == 504) {
vec3 normal = vec3(0.0);
normal[t_min] = sign(-ray_direction_sign[t_min]);
job.direction = reflect(job.direction, normal);
direction_inv = 1.0f / job.direction;
ray_direction_sign = sign(job.direction);
intersection_index = ivec3(7.5f * ray_direction_sign + vec3(7.5f, 12.5f, 17.5f));
skipDelta = ray_direction_sign * 0.00001f;
intersection_offset = max(ivec3(ray_direction_sign), 0);
} else
#endif
{
if ((-entries.z & 0x7f000000) == 0 || block_id == 85 || block_id == 13) {
job.result_hit = true;
break;
}
vec4 color = unpack_color(-entries.z);
if (previous_block_id != block_id) {
if (color.a > 0.01 && translucentHits < 10u) {
vec3 hitnormal = vec3(0.0);
if (t_min != -1) hitnormal[t_min] = sign(-ray_direction_sign[t_min]);
translucentHitRays[translucentHits].hitNormal = hitnormal;
translucentHitRays[translucentHits].hitPos = vec3(position / 16.0f);
translucentHitRays[translucentHits].hitColor = color;
translucentHitRays[translucentHits].hitID = block_id;
translucentHitRays[translucentHits].skylight = get_result_sky_light(hitnormal) / 15.0;
translucentHits += 1u;
}
previous_block_id = block_id;
}
}
scale = 4;
entry = to_fake_air_entry(block_pos);
} else { scale = 0; entry = entries.z; }
} else { scale = 4; entry = entries.y; previous_block_id = -1;}
} else { scale = 8; entry = entries.x; }
old_index = new_index;
ivec3 intersection = (((ivec3(entry) >> intersection_index) & 31) + intersection_offset) << scale;
scale += 4;
scale += int(scale == 8 + 4);
intersection += w & (-1 << scale);
vec3 t = (intersection - position) * direction_inv;
t_min = int(t.x >= t.y);
t_min = t.z < t[t_min] ? 2 : t_min;
position += t[t_min] * job.direction;
// "push precision" into lower decimal values to fight rounding errors
position[t_min] = (intersection[t_min] * 0.01f + skipDelta[t_min]) * 100.0f;
}
// lightEmittance = unpackUnorm4x8(cb_array[-entries.y / 4097]).xyz;
job.result_color = vec3((-entries.z >> 0) & 0xff, (-entries.z >> 8) & 0xff, (-entries.z >> 16) & 0xff) / 0xff;
job.result_position = vec3(position / 16.0f);
if (t_min != -1)
job.result_normal[t_min] = sign(-ray_direction_sign[t_min]);
// job.result_color = debug;
ray_target = ivec3(-1);
skylightmap = get_result_sky_light(job.result_normal) / 15.0;
}
#endif
uniform float skyLightLevelSmooth;
vec3 doBlockLightLightingVoxel(
vec3 lightColor, float lightmap,
vec3 playerPos, vec3 lpvPos
){
lightmap = clamp(lightmap,0.0,1.0);
float lightmapBrightspot = min(max(lightmap-0.7,0.0)*3.3333,1.0);
lightmapBrightspot *= lightmapBrightspot*lightmapBrightspot;
float lightmapLight = 1.0-sqrt(1.0-lightmap);
lightmapLight *= lightmapLight;
float lightmapCurve = mix(lightmapLight, 2.5, lightmapBrightspot);
vec3 blockLight = lightmapCurve * lightColor;
#if defined IS_LPV_ENABLED && defined MC_GL_ARB_shader_image_load_store
vec4 lpvSample = SampleLpvLinear(lpvPos);
#ifdef VANILLA_LIGHTMAP_MASK
lpvSample.rgb *= lightmapCurve;
#endif
// create a smooth falloff at the edges of the voxel volume.
const float fadeLength = 10.0; // in meters
vec3 cubicRadius = clamp(min(((LpvSize3-1.0) - lpvPos)/fadeLength, lpvPos/fadeLength), 0.0, 1.0);
float voxelRangeFalloff = cubicRadius.x*cubicRadius.y*cubicRadius.z;
voxelRangeFalloff = 1.0 - pow(1.0-pow(voxelRangeFalloff,1.5),3.0);
// outside the voxel volume, lerp to vanilla lighting as a fallback
blockLight = mix(blockLight, lpvSample.rgb + lightColor * 2.5 * min(max(lightmap-0.999,0.0)/(1.0-0.999),1.0), voxelRangeFalloff);
#ifdef Hand_Held_lights
// create handheld lightsources
if (heldItemId > 0){
float lightRange = 0.0;
vec3 handLightCol = GetHandLight(heldItemId, playerPos, lightRange);
blockLight += handLightCol;
}
if (heldItemId2 > 0){
float lightRange2 = 0.0;
vec3 handLightCol2 = GetHandLight(heldItemId2, playerPos, lightRange2);
blockLight += handLightCol2;
}
#endif
#endif
return blockLight * TORCH_AMOUNT;
}
#if defined PHOTONICS_INCLUDED && defined PHOTONICS && defined VOXEL_REFLECTIONS
#if defined OVERWORLD_SHADER
uniform float caveDetection;
#define TIMEOFDAYFOG
#include "/lib/climate_settings.glsl"
#include "/lib/overworld_fog.glsl"
vec4 raymarchWSR_LPV(
in vec3 origin,
in vec3 endPos,
in float dither
){
#if (!defined LPV_VL_FOG_ILLUMINATION || !defined IS_LPV_ENABLED) && (!defined FLASHLIGHT_FOG_ILLUMINATION || !defined FLASHLIGHT)
return vec4(0.0,0.0,0.0,1.0);
#endif
if(length(origin-endPos) < 0.001) return vec4(0.0,0.0,0.0,1.0);
const int SAMPLECOUNT = 3;
float mult = float(VL_SAMPLES) / float(SAMPLECOUNT) * 1.15;
float minimumDensity = 0.000025;
// if(eyeInWater) minimumDensity = 0.00006;
const float fadeLength = 10.0; // in blocks
vec3 LPVrayStartPos = endPos-origin - gbufferModelViewInverse[3].xyz;
// ensure the max marching distance is the voxel distance, or the render distance if the voxels go farther than it
float LPVRayLength = length(LPVrayStartPos);
#if LPV_SIZE == 8
LPVrayStartPos *= min(LPVRayLength, min(256.0,far))/LPVRayLength;
#elif LPV_SIZE == 7
LPVrayStartPos *= min(LPVRayLength, min(128.0,far))/LPVRayLength;
#elif LPV_SIZE == 6
LPVrayStartPos *= min(LPVRayLength, min(64.0,far))/LPVRayLength;
#endif
LPVRayLength = length(LPVrayStartPos);
vec3 rayProgress = vec3(0.0);
vec4 color = vec4(0.0,0.0,0.0,1.0);
const float expFactor = 11.0;
for (int i = 0; i < SAMPLECOUNT; i++) {
float d = (pow(expFactor, float(i+dither)/float(SAMPLECOUNT))/expFactor - 1.0/expFactor)/(1.0-1.0/expFactor);
float dd = pow(expFactor, float(i+dither)/float(SAMPLECOUNT)) * log(expFactor) / float(SAMPLECOUNT)/(expFactor-1.0);
rayProgress = gbufferModelViewInverse[3].xyz + d*LPVrayStartPos + origin;
float density;
float _minimumDensity = minimumDensity;
#ifdef OVERWORLD_SHADER
if(caveDetection < 0.9999) density = cloudVol(rayProgress + cameraPosition, 0.0) * (1.0 - caveDetection);
_minimumDensity += caveDetection * minimumDensity;
#elif defined NETHER_SHADER
vec3 progressW = rayProgress + cameraPosition;
density = cloudVol(progressW);
float dist = length(rayProgress);
float clearArea = 1.0 - min(max(1.0 - dist / 24.0,0.0),1.0);
float plumeDensity = min(density * pow(min(max(100.0-progressW.y,0.0)/30.0,1.0),4.0), pow(clamp(1.0 - dist/far,0.0,1.0),5.0));
plumeDensity *= NETHER_PLUME_DENSITY;
float ceilingSmokeDensity = 0.001 * pow(min(max(progressW.y-40.0,0.0)/50.0,1.0),3.0);
ceilingSmokeDensity *= NETHER_CEILING_SMOKE_DENSITY;
density = plumeDensity + ceilingSmokeDensity;
#elif defined END_SHADER
float volumeDensity = fogShape(rayProgress + cameraPosition);
float clearArea = 1.0-min(max(1.0 - length(rayProgress) / 100,0.0),1.0);
density = min(volumeDensity, clearArea*clearArea * END_STORM_DENSTIY);
#endif
density = max(density/1000.0, _minimumDensity)*mult;
// density = 0.0001;
float volumeCoeff = exp(-dd*density*LPVRayLength);
#if defined IS_LPV_ENABLED && defined LPV_VL_FOG_ILLUMINATION
vec3 lpvPos = GetLpvPosition(rayProgress);
vec3 cubicRadius = clamp(min(((LpvSize3-1.0) - lpvPos)/fadeLength, lpvPos/fadeLength), 0.0, 1.0);
float LpvFadeF = cubicRadius.x*cubicRadius.y*cubicRadius.z;
if(LpvFadeF < 0.01) break;
vec3 sampleColor = SampleLpvLinear(lpvPos).rgb;
#ifdef VANILLA_LIGHTMAP_MASK
vec3 lighting = sampleColor * LPV_VL_FOG_ILLUMINATION_BRIGHTNESS * 25. * exp(-10 * (1.0-luma(sampleColor)));
#else
vec3 lighting = sampleColor * LPV_VL_FOG_ILLUMINATION_BRIGHTNESS * 25. * exp(-5 * (1.0-luma(sampleColor)));
#endif
// if(eyeInWater) lighting *= 2.5;
#ifdef LPV_VL_FOG_ILLUMINATION_HANDHELD
float lightRange = 0.0;
vec3 handLightCol = GetHandLight(heldItemId, rayProgress, lightRange);
vec3 handLightCol2 = GetHandLight(heldItemId2, rayProgress, lightRange);
lighting += (handLightCol + handLightCol2) * TORCH_AMOUNT * LPV_VL_FOG_ILLUMINATION_BRIGHTNESS * 0.04;
#endif
color.rgb += (lighting - lighting * volumeCoeff) * color.a;
#endif
#if defined FLASHLIGHT && defined FLASHLIGHT_FOG_ILLUMINATION
// vec3 shiftedViewPos = mat3(gbufferModelView)*(progressW-cameraPosition) + vec3(-0.25, 0.2, 0.0);
// vec3 shiftedPlayerPos = mat3(gbufferModelViewInverse) * shiftedViewPos;
vec3 shiftedViewPos;
vec3 shiftedPlayerPos;
float forwardOffset;
#ifdef VIVECRAFT
if (vivecraftIsVR) {
forwardOffset = 0.0;
shiftedPlayerPos = (rayProgress) + ( vivecraftRelativeMainHandPos);
shiftedViewPos = shiftedPlayerPos * mat3(vivecraftRelativeMainHandRot);
} else
#endif
{
forwardOffset = 0.5;
shiftedViewPos = mat3(gbufferModelView)*(rayProgress) + vec3(-0.25, 0.2, 0.0);
shiftedPlayerPos = mat3(gbufferModelViewInverse) * shiftedViewPos;
}
vec2 scaledViewPos = shiftedViewPos.xy / max(-shiftedViewPos.z - forwardOffset, 1e-7);
float linearDistance = length(shiftedPlayerPos);
float shiftedLinearDistance = length(scaledViewPos);
float lightFalloff = 1.0 - clamp(1.0-linearDistance/FLASHLIGHT_RANGE, -0.999,1.0);
lightFalloff = max(exp(-10.0 * FLASHLIGHT_BRIGHTNESS_FALLOFF_MULT * lightFalloff),0.0);
float projectedCircle = clamp(1.0 - shiftedLinearDistance*FLASHLIGHT_SIZE,0.0,1.0);
vec3 flashlightGlow = 25.0 * vec3(FLASHLIGHT_R,FLASHLIGHT_G,FLASHLIGHT_B) * lightFalloff * projectedCircle * FLASHLIGHT_BRIGHTNESS_MULT;
color.rgb += (flashlightGlow - flashlightGlow * volumeCoeff) * color.a;
#endif
color.a *= volumeCoeff;
}
return color;
}
vec4 raymarchWSRfog(
const in vec3 origin,
const in vec3 endPos,
const in vec2 dither,
const in vec3 LightColor,
const in vec3 AmbientColor,
const in vec3 AveragedAmbientColor,
const in int SAMPLECOUNT
){
#ifndef TOGGLE_VL_FOG
return vec4(0.0,0.0,0.0,1.0);
#endif
if(length(origin-endPos) < 0.001) return vec4(0.0,0.0,0.0,1.0);
float mult = float(VL_SAMPLES) / float(SAMPLECOUNT) * 1.15;
//project pixel position into projected shadowmap space
vec3 dVWorld = endPos-origin - gbufferModelViewInverse[3].xyz;
float rayLength = length(dVWorld);
vec3 rayDir = normalize(endPos-origin);
float maxLength = min(rayLength, far)/rayLength;
dVWorld *= maxLength;
float dL = length(dVWorld)/8.0;
const float expFactor = 11.0;
/// ------------- COLOR/LIGHTING STUFF ------------- \\\
vec3 color = vec3(0.0);
vec3 finalAbsorbance = vec3(1.0);
float totalAbsorbance = 1.0;
// float fogAbsorbance = 1.0;
// float atmosphereAbsorbance = 1.0;
vec3 atmosphereAbsorbance = vec3(1.0);
float SdotV = dot(WsunVec, rayDir);
///// ----- fog lighting
//Mie phase + somewhat simulates multiple scattering (Horizon zero down cloud approx)
float sunPhase = fogPhase(SdotV)*5.0;
float skyPhase = 0.5 + pow(1.0-pow(1.0-clamp(rayDir.y*0.5+0.5,0.0,1.0),2.0),5.0)*2.0;
float rayL = phaseRayleigh(SdotV);
vec3 rC = vec3(sky_coefficientRayleighR*1e-6, sky_coefficientRayleighG*1e-5, sky_coefficientRayleighB*1e-5) ;
vec3 mC = vec3(fog_coefficientMieR*1e-6, fog_coefficientMieG*1e-6, fog_coefficientMieB*1e-6);
#if defined EXCLUDE_WRITE_TO_LUT && defined USE_CUSTOM_FOG_LIGHTING_COLORS
LightColor = dot(LightColor,vec3(0.21, 0.72, 0.07)) * vec3(DIRECTLIGHT_FOG_R,DIRECTLIGHT_FOG_G,DIRECTLIGHT_FOG_B);
AmbientColor = dot(AmbientColor,vec3(0.21, 0.72, 0.07)) * vec3(INDIRECTLIGHT_FOG_R,INDIRECTLIGHT_FOG_G,INDIRECTLIGHT_FOG_B);
#endif
vec3 skyLightPhased = AmbientColor;
vec3 LightSourcePhased = LightColor;
skyLightPhased *= skyPhase;
LightSourcePhased *= sunPhase;
#ifdef AMBIENT_LIGHT_ONLY
LightSourcePhased = vec3(0.0);
#endif
#ifdef PER_BIOME_ENVIRONMENT
vec3 biomeDirect = LightSourcePhased;
vec3 biomeIndirect = skyLightPhased;
float inBiome = BiomeVLFogColors(biomeDirect, biomeIndirect);
#endif
float inACave = 1.0 - caveDetection;
float lightLevelZero = pow(clamp(eyeBrightnessSmooth.y/240.0 ,0.0,1.0),3.0);
// SkyLightColor *= lightLevelZero*0.9 + 0.1;
// vec3 finalsceneColor = vec3(0.0);
for (int i = 0; i < SAMPLECOUNT; i++) {
float d = (pow(expFactor, float(i+dither.y)/float(SAMPLECOUNT))/expFactor - 1.0/expFactor)/(1-1.0/expFactor);
float dd = pow(expFactor, float(i+dither.x)/float(SAMPLECOUNT)) * log(expFactor) / float(SAMPLECOUNT)/(expFactor-1.0);
// #ifdef VOLUMETRIC_CLOUDS
// // check if the fog intersects clouds
// if(length(d*dVWorld) > cloudPlaneDistance) break;
// #endif
vec3 progressP = gbufferModelViewInverse[3].xyz + d*dVWorld + origin;
vec3 progressW = progressP + cameraPosition;
//------------------------------------
//------ SAMPLE SHADOWS FOR FOG EFFECTS
//------------------------------------
#ifdef CUSTOM_MOON_ROTATION
vec3 fragposition = mat3(customShadowMatrixSSBO) * progressP + customShadowMatrixSSBO[3].xyz;
#else
vec3 fragposition = mat3(shadowModelView) * progressP + shadowModelView[3].xyz;
#endif
fragposition = diagonal3(shadowProjection) * fragposition + shadowProjection[3].xyz;
#if defined DISTORT_SHADOWMAP && defined OVERWORLD_SHADER
float distortFactor = calcDistort(fragposition.xy);
#else
float distortFactor = 1.0;
#endif
vec3 shadowPos = vec3(fragposition.xy * distortFactor, fragposition.z);
vec3 sh = vec3(1.0);
if (abs(shadowPos.x) < 1.0-0.5/2048. && abs(shadowPos.y) < 1.0-0.5/2048.){
shadowPos = shadowPos*vec3(0.5,0.5,0.5/6.0)+0.5;
#ifdef TRANSLUCENT_COLORED_SHADOWS
sh = vec3(texture(shadowtex0, shadowPos).x);
if(texture(shadowtex1, shadowPos).x > shadowPos.z && sh.x < 1.0){
vec4 translucentShadow = texture(shadowcolor0, shadowPos.xy);
if(translucentShadow.a < 0.9) sh = normalize(translucentShadow.rgb+0.0001);
}
#else
sh = vec3(texture(shadow, shadowPos).x);
#endif
}
sh *= GetCloudShadow(progressW, WsunVec);
#ifdef PER_BIOME_ENVIRONMENT
float maxDistance = inBiome * min(max(1.0 - length(d*dVWorld.xz)/(32*8),0.0)*2.0,1.0);
float fogDensity = cloudVol(progressW, maxDistance) * inACave * mult;
#else
float fogDensity = cloudVol(progressW, 0.0) * inACave * mult;
#endif
//------------------------------------
//------ MAIN FOG EFFECT
//------------------------------------
float fogVolumeCoeff = exp(-fogDensity*dd*dL); // this is like beer-lambert law or something
#ifdef PER_BIOME_ENVIRONMENT
vec3 indirectLight = mix(skyLightPhased, biomeIndirect, maxDistance);
vec3 DirectLight = mix(LightSourcePhased, biomeDirect, maxDistance) * sh;
#else
vec3 indirectLight = skyLightPhased;
vec3 DirectLight = LightSourcePhased * sh;
#endif
vec3 Lightning = Iris_Lightningflash_VLfog(progressP);
vec3 lighting = DirectLight + indirectLight + 0.0025 * Lightning;
color += (lighting - lighting * fogVolumeCoeff) * totalAbsorbance;
// kill fog absorbance when in caves.
totalAbsorbance *= mix(1.0, fogVolumeCoeff, lightLevelZero);
if(totalAbsorbance < 0.01) break;
//------------------------------------
//------ ATMOSPHERE HAZE EFFECT
//------------------------------------
// maximum range for atmosphere haze, basically.
float planetVolume = smoothstep(1.0 - exp(clamp(1.0 - length(progressP) / (16.0*150.0), 0.0,1.0) * -10.0), 0.0, progressP.y-500.0);
// just air
vec2 airCoef = exp2(-max(progressW.y-SEA_LEVEL,0.0)/vec2(8.0e3, 1.2e3)*vec2(6.0,7.0)) * 192.0 * Haze_amount * planetVolume;
// Pbr for air, yolo mix between mie and rayleigh for water droplets
vec3 rL = rC*airCoef.x;
vec3 m = mC*(airCoef.y+min(Haze_amount*1.25,1.0));
vec3 airDensity = rL + m;
// calculate the atmosphere haze seperately and purely additive to color, do not contribute to absorbtion.
vec3 atmosphereVolumeCoeff = exp(-airDensity*dd*dL);
// vec3 Atmosphere = LightSourcePhased * sh * (rayL*rL + sunPhase*m) + AveragedAmbientColor * (rL+m);
vec3 Atmosphere = (LightSourcePhased * sh * (rayL*rL + sunPhase*m) + AveragedAmbientColor * airDensity * (lightLevelZero*0.99 + 0.01)) * inACave;
color += (Atmosphere - Atmosphere * atmosphereVolumeCoeff) / (airDensity+1e-6) * atmosphereAbsorbance;
atmosphereAbsorbance *= atmosphereVolumeCoeff;
// totalAbsorbance *= dot(atmosphereVolumeCoeff,vec3(0.33333));
}
// sceneColor = finalsceneColor;
// atmosphereAlpha = atmosphereAbsorbance;
return vec4(color, totalAbsorbance);
}
vec4 WSRwaterVolumetrics(vec3 origin, vec3 endPos, vec2 dither, vec3 ambient, vec3 lightSource, vec3 LPV){
if(length(origin-endPos) < 0.001) return vec4(0.0,0.0,0.0,1.0);
const int SAMPLECOUNT = 3;
float lightSourceCheck = float(sunElevation > 1e-5)*2.0 - 1.0;
vec3 waterCoefs = vec3(Water_Absorb_R, Water_Absorb_G, Water_Absorb_B);
vec3 scatterCoef = Dirt_Amount * vec3(Dirt_Scatter_R, Dirt_Scatter_G, Dirt_Scatter_B) / 3.14;
//project pixel position into projected shadowmap space
vec3 dVWorld = endPos-origin - gbufferModelViewInverse[3].xyz;
float rayLength = length(dVWorld);
float maxLength = min(rayLength, far)/rayLength;
dVWorld *= maxLength;
vec3 absorbance = vec3(1.0);
vec3 vL = vec3(0.0);
#ifdef OVERWORLD_SHADER
vec3 rayDir = normalize(endPos-origin);
float VdotL = dot(WsunVec, rayDir);
float phase = fogPhase(VdotL) * 5.0;
#else
const float phase = 0.0;
#endif
float thing = -normalize(dVWorld).y;
thing = clamp(thing + 0.333,0.0,1.0);
thing = pow(1.0-pow(1.0-thing,2.0),2.0);
thing *= 15.0;
const float expFactor = 11.0;
for (int i=0;i<SAMPLECOUNT;i++) {
float d = (pow(expFactor, float(i+dither.x)/float(SAMPLECOUNT))/expFactor - 1.0/expFactor)/(1-1.0/expFactor); // exponential step position (0-1)
float dd = pow(expFactor, float(i+dither.y)/float(SAMPLECOUNT)) * log(expFactor) / float(SAMPLECOUNT)/(expFactor-1.0); //step length (derivative)
vec3 progressP = gbufferModelViewInverse[3].xyz + d*dVWorld;
vec3 progressW = progressP + cameraPosition;
float distanceFromWaterSurface = max(-(progressW.y - waterEnteredAltitude),0.0);
vec3 sh = vec3(1.0);
#ifdef OVERWORLD_SHADER
#ifdef CUSTOM_MOON_ROTATION
vec3 fragposition = mat3(customShadowMatrixSSBO) * progressP + customShadowMatrixSSBO[3].xyz;
#else
vec3 fragposition = mat3(shadowModelView) * progressP + shadowModelView[3].xyz;
#endif
fragposition = diagonal3(shadowProjection) * fragposition + shadowProjection[3].xyz;
#if defined DISTORT_SHADOWMAP && defined OVERWORLD_SHADER
float distortFactor = calcDistort(fragposition.xy);
#else
float distortFactor = 1.0;
#endif
vec3 spPos = vec3(fragposition.xy * distortFactor, fragposition.z);
vec3 pos = vec3(spPos.xy*distortFactor, spPos.z);
if (abs(pos.x) < 1.0-0.5/2048. && abs(pos.y) < 1.0-0.5/2048){
pos = pos*vec3(0.5,0.5,0.5/6.0)+0.5;
// sh = texture( shadow, pos).x;
#ifdef TRANSLUCENT_COLORED_SHADOWS
sh = vec3(texture(shadowtex0, pos).x);
if(texture(shadowtex1, pos).x > pos.z && sh.x < 1.0){
vec4 translucentShadow = texture(shadowcolor0, pos.xy);
if(translucentShadow.a < 0.9) sh = normalize(translucentShadow.rgb+0.0001);
}
#else
sh = vec3(texture(shadow, pos).x);
#endif
}
sh *= GetCloudShadow(progressW, WsunVec * lightSourceCheck);
#endif
float bubble = exp2(-10.0 * clamp(1.0 - length(d*dVWorld) / 16.0, 0.0,1.0));
float caustics = max(max(waterCaustics(progressW, WsunVec, -(progressW.y - waterEnteredAltitude)), phase*0.5) * mix(0.5, 1.5, bubble), phase);
vec3 sunAbsorbance = exp(-waterCoefs * (distanceFromWaterSurface/abs(WsunVec.y)));
vec3 WaterAbsorbance = exp(-waterCoefs * (distanceFromWaterSurface + thing));
vec3 Directlight = lightSource * sh * phase * caustics * sunAbsorbance;
vec3 _ambient = ambient;
// #ifdef BIOME_TINT_WATER
// _ambient *= sqrt(fogColor);
// Directlight *= pow(fogColor, vec3(0.01,0.01,3.75));
// #endif
#ifdef OVERWORLD_SHADER
float horizontalDist = length((progressP.xz) - lightningBoltPosition.xz);
if (horizontalDist < 250.0 && lightningBoltPosition.w > 0.0) {
float lightningIntensity = exp(-horizontalDist * 0.02) * lightningFlash;
_ambient = mix(_ambient, vec3(1.3,1.5,3.0) * sh, lightningIntensity);
}
#endif
vec3 Indirectlight = _ambient * WaterAbsorbance;
#if defined LPV_VL_FOG_ILLUMINATION && defined IS_LPV_ENABLED && defined LPV_VL_FOG_ILLUMINATION_HANDHELD_WATER
float lightRange = 0.0;
vec3 handLightCol = GetHandLight(heldItemId, progressP, lightRange);
vec3 handLightCol2 = GetHandLight(heldItemId2, progressP, lightRange);
Indirectlight += (handLightCol + handLightCol2) * TORCH_AMOUNT * (LPV_VL_FOG_ILLUMINATION_BRIGHTNESS / 100.0) * 0.2 * exp(-waterCoefs * (length(progressP) + 0.05 * thing));
#endif
vec3 light = (Indirectlight + Directlight + LPV) * scatterCoef;
vec3 volumeCoeff = exp(-waterCoefs * length(dd*dVWorld));
vL += (light - light * volumeCoeff) / waterCoefs * absorbance;
absorbance *= volumeCoeff;
}
return vec4(vL, dot(absorbance,vec3(0.333333)));
}
#endif
float getPhotonicsEmission(vec3 Albedo) {
vec3 hsv = RgbToHsv(Albedo);
float emissive = smoothstep(0.05, 0.15, hsv.y) * pow(hsv.z, 3.5);
return emissive * 0.5;
}
void photonicsEmission(
inout vec3 Lighting,
vec3 Albedo,
float Emission
){
if( Emission < 254.5/255.0) Lighting = mix(Lighting, Albedo * 5.0 * Emissive_Brightness, pow(Emission, Emissive_Curve));
}
void photonicsReflectionShading(inout vec4 color, const in vec3 normal, const in vec3 worldPos, const in float noise, in vec3 DirectLightColor, const in vec3 AmbientLightColor, const in int blockID, const in float skylightmap) {
float SkylightDir = normal.y;
SkylightDir = SkylightDir*0.5+0.5;
vec2 lightmap = vec2(0.0, skylightmap);
if(abs(blockID-197) <= 1 || blockID == 242) lightmap.x = 1.0;
float skylight = mix(0.08 + 0.92*(1.0-lightmap.y), 1.0, SkylightDir);
vec3 Indirect_lighting = doIndirectLighting(AmbientLightColor * skylight, vec3(1.0), lightmap.y);
vec3 playerPosition = worldPos-cameraPosition;
Indirect_lighting += doBlockLightLightingVoxel(vec3(TORCH_R,TORCH_G,TORCH_B), lightmap.x, playerPosition, GetLpvPosition(playerPosition));
float shadowMapFalloff = smoothstep(0.0, 1.0, min(max(1.0 - length(playerPosition) / (shadowDistance+16),0.0)*5.0,1.0));
float sh = 1.0;
#if defined OVERWORLD_SHADER || defined END_ISLAND_LIGHT && defined END_SHADER
sh = ComputePhotonicsShadowMap(DirectLightColor, playerPosition, shadowMapFalloff, noise, normal);
float lightLeakFix = clamp(pow(eyeBrightnessSmooth.y/240. + lightmap.y, 2.0), 0.0, 1.0);
sh *= lightLeakFix;
#endif
#ifdef OVERWORLD_SHADER
sh *= GetCloudShadow(worldPos, WsunVec);
float NdotL = clamp((-15.0 + dot(normal, WsunVec)*255.0) / 240.0, 0.0, 1.0);
if(blockID == BLOCK_SSS_STRONG || blockID == BLOCK_SSS_STRONG3 || blockID == BLOCK_AIR_WAVING || blockID == BLOCK_SSS_STRONG_2 ||
blockID == BLOCK_GROUND_WAVING || blockID == BLOCK_GROUND_WAVING_VERTICAL ||
blockID == BLOCK_GRASS_SHORT || blockID == BLOCK_GRASS_TALL_UPPER || blockID == BLOCK_GRASS_TALL_LOWER ||
blockID == BLOCK_SSS_WEAK || blockID == BLOCK_CACTUS || blockID == BLOCK_SSS_WEAK_2 ||
blockID == BLOCK_CELESTIUM || (blockID >= 269 && blockID <= 274) || blockID == BLOCK_SNOW_LAYERS || blockID == BLOCK_CARPET ||
blockID == BLOCK_AMETHYST_BUD_MEDIUM || blockID == BLOCK_AMETHYST_BUD_LARGE || blockID == BLOCK_AMETHYST_CLUSTER ||
blockID == BLOCK_BAMBOO || blockID == BLOCK_SAPLING || blockID == BLOCK_VINE || blockID == BLOCK_VINE_OTHER)
{
NdotL = mix(NdotL, 1.0, 0.25);
}
#else
float NdotL = 1.0;
#endif
vec3 albedo = color.rgb;
color.rgb *= Indirect_lighting + DirectLightColor * sh * NdotL;
float EMISSIVE = 0.0;
// normal block lightsources
if(blockID >= 100 && blockID < 282) {
EMISSIVE = 0.5;
if(blockID == 266 || (blockID >= 276 && blockID <= 281)) EMISSIVE = 0.2; // sculk stuff
else if(blockID == 195) EMISSIVE = 2.3; // glow lichen
else if(blockID == 185) EMISSIVE = 1.5; // crying obsidian
else if(blockID == 105) EMISSIVE = 2.0; // brewing stand
else if(blockID == 236) EMISSIVE = 1.0; // respawn anchor
else if(blockID == 101) EMISSIVE = 0.7; // large amethyst bud
else if(blockID == 103) EMISSIVE = 1.0; // amethyst cluster
else if(blockID == 244) EMISSIVE = 1.5; // soul fire
EMISSIVE *= getPhotonicsEmission(albedo);
EMISSIVE = clamp(EMISSIVE, 0.0, 1.0);
photonicsEmission(color.rgb, albedo, EMISSIVE);
}
#if EMISSIVE_ORES > 0
if(blockID == 502) {
EMISSIVE = EMISSIVE_ORES_STRENGTH;
EMISSIVE *= getPhotonicsEmission(albedo);
EMISSIVE = clamp(EMISSIVE, 0.0, 1.0);
photonicsEmission(color.rgb, albedo, EMISSIVE);
}
#endif
}
#endif
vec4 photonicsReflection(
vec3 reflectedVector,
vec3 origin,
vec2 noise,
vec3 flatNormal,
inout float backgroundReflectMask,
inout vec3 backgroundTint
) {
vec4 color = vec4(0.0);
#if defined PHOTONICS_INCLUDED && defined PHOTONICS && defined VOXEL_REFLECTIONS
RayJob ray = RayJob(
cameraPosition + origin - world_offset + 0.005f * flatNormal,
reflectedVector,
vec3(0), vec3(0), vec3(0), false
);
translucentHit[10] translucentHitRays;
uint translucentHits;
int blockID = 0;
translucentHitRays[0].hitColor = vec4(0.0);
float skylightmap = 0.0;
trace_wsr(ray, true, translucentHitRays, translucentHits, blockID, skylightmap);
bool hitTranslucent = translucentHits > 0u;
if(!hitTranslucent && !ray.result_hit) return color;
vec3 DirectLightColor = lightSourceColorSSBO / 1400.0;
vec3 AmbientLightColor = averageSkyCol_CloudsSSBO;
vec3 indirectLightColor = skyGroundColSSBO / 1200.0;
vec3 indirectLight = AmbientLightColor * skyLightLevelSmooth * ambient_brightness / 1200.0;
float minimumLightAmount = 0.02*nightVision + 0.001 * mix(MIN_LIGHT_AMOUNT_INSIDE, MIN_LIGHT_AMOUNT, clamp(skyLightLevelSmooth, 0.0, 1.0));
indirectLight += vec3(1.0) * minimumLightAmount;
vec3 indirectLight_fog = indirectLightColor * ambient_brightness;
indirectLight_fog += vec3(1.0) * (0.02*nightVision + 0.001 * mix(MIN_LIGHT_AMOUNT_INSIDE, MIN_LIGHT_AMOUNT, skyLightLevelSmooth));
#ifdef USE_CUSTOM_DIFFUSE_LIGHTING_COLORS
DirectLightColor = luma(DirectLightColor) * vec3(DIRECTLIGHT_DIFFUSE_R,DIRECTLIGHT_DIFFUSE_G,DIRECTLIGHT_DIFFUSE_B);
AmbientLightColor = luma(AmbientLightColor) * vec3(INDIRECTLIGHT_DIFFUSE_R,INDIRECTLIGHT_DIFFUSE_G,INDIRECTLIGHT_DIFFUSE_B);
#endif
AmbientLightColor *= ambient_brightness / 900.0;
vec3 endPosW = ray.result_position + world_offset;
vec3 endPos = endPosW - cameraPosition;
for (uint i = 0; i < translucentHits; i++) {
vec4 sampleColor = translucentHitRays[i].hitColor;
// return vec4(sampleColor.rgb, 1.0);
sampleColor.rgb = toLinear(sampleColor.rgb);
photonicsReflectionShading(sampleColor, translucentHitRays[i].hitNormal, translucentHitRays[i].hitPos + world_offset, noise.y, DirectLightColor, AmbientLightColor, translucentHitRays[i].hitID, translucentHitRays[i].skylight);
sampleColor.a *= (1.0 - color.a);
color.rgb += sampleColor.rgb * sampleColor.a;
color.a += sampleColor.a;
if(color.a > 0.995) return color;
}
backgroundTint = mix(normalize(translucentHitRays[0].hitColor.rgb+1e-7), vec3(1.0), min(max(0.1-translucentHitRays[0].hitColor.a,0.0) * 10.0,1.0));
if (ray.result_hit) {
vec4 sampleColor = vec4(toLinear(ray.result_color), 1.0);
photonicsReflectionShading(sampleColor, ray.result_normal, endPosW, noise.y, DirectLightColor, AmbientLightColor, blockID, skylightmap);
#if defined VOXEL_REFLECTIONS_FOG && defined OVERWORLD_SHADER
if(hitTranslucent && isEyeInWater != 1) {
vec4 fog = raymarchWSRfog(translucentHitRays[0].hitPos + world_offset - cameraPosition, endPos, noise, DirectLightColor, indirectLight_fog, indirectLight, 3);
sampleColor.rgb = sampleColor.rgb * fog.a;
sampleColor.rgb += fog.rgb;
}
#endif
sampleColor.rgb *= backgroundTint;
sampleColor.a *= (1.0 - color.a);
color.rgb += sampleColor.rgb * sampleColor.a;
color.a += sampleColor.a;
} else {
backgroundReflectMask = 1.0-color.a;
}
#if defined VOXEL_REFLECTIONS_FOG && defined OVERWORLD_SHADER
if(hitTranslucent && isEyeInWater != 1) endPos = translucentHitRays[0].hitPos + world_offset - cameraPosition;
#ifdef VOXEL_REFLECTIONS_LPV_FOG
vec4 LPVfog = raymarchWSR_LPV(origin, endPos, noise.x);
#endif
vec4 fog;
if(isEyeInWater == 1) {
fog = WSRwaterVolumetrics(origin, endPos, noise, DirectLightColor, indirectLight, LPVfog.rgb);
} else {
fog = raymarchWSRfog(origin, endPos, noise, DirectLightColor, indirectLight_fog, indirectLight, 4);
}
#ifdef VOXEL_REFLECTIONS_LPV_FOG
fog.a *= LPVfog.a;
fog.rgb = fog.rgb * LPVfog.a + LPVfog.rgb;
#endif
color.rgb = color.rgb * fog.a;
color.rgb += fog.rgb;
#endif
#endif
return color;
}
vec4 getEnvironmentReflections(
vec3 reflectedVector,
vec3 flatNormal,
vec3 normal,
vec3 origin,
vec3 viewPos,
vec2 noise,
bool isHand,
float roughness,
inout float backgroundReflectMask,
inout vec3 backgroundTint
#ifdef FORWARD_SPECULAR
,bool isWater
#endif
){
vec4 reflection = vec4(0.0);
float reflectionLength = 0.0;
float quality = 1.0f;
#ifdef FORWARD_SPECULAR
quality = float(FORWARD_SSR_QUALITY);
#endif
#ifdef DEFERRED_SPECULAR
quality = float(DEFERRED_SSR_QUALITY);
#endif
vec3 raytracePos = vec3(0.0);
bool depthCheck = false;
// if (raytracePos.z > 1.001 || distance(gl_FragCoord.xy*texelSize, raytracePos.xy) < 0.002) return reflection;
#if defined VOXEL_REFLECTIONS && defined PHOTONICS && defined PHOTONICS_INCLUDED
// raytracePos = rayTraceSpeculars(mat3(gbufferModelView) * reflectedVector, viewPos, noise, quality, isHand, reflectionLength, depthCheck);
//if(raytracePos.z > 1.0)
{
if(dot(reflectedVector, flatNormal) < 0.0) return reflection;
return photonicsReflection(reflectedVector, origin, noise, flatNormal, backgroundReflectMask, backgroundTint);
}
#else
raytracePos = rayTraceSpeculars(mat3(gbufferModelView) * reflectedVector, viewPos, noise.y, quality, isHand, reflectionLength, depthCheck);
if (raytracePos.z > 1.00001) return reflection;
#endif
// use higher LOD as the reflection goes on, to blur it. this helps denoise a little.
reflectionLength = min(max(reflectionLength - 0.1, 0.0)/0.9, 1.0);
float LOD = mix(0.0, 6.0*(1.0-exp(-15.0*sqrt(roughness))), 1.0-pow(1.0-reflectionLength,5.0));
#if (defined VOXY && defined VOXY_REFLECTIONS) || (defined DISTANT_HORIZONS && defined DH_SCREENSPACE_REFLECTIONS)
mat4 projMatrix = gbufferPreviousProjection;
if(depthCheck) projMatrix = dhVoxyProjectionPrev;
#else
mat4 projMatrix = gbufferPreviousProjection;
#endif
vec3 previousPosition = mat3(gbufferModelViewInverse) * toScreenSpace2(raytracePos, depthCheck) + gbufferModelViewInverse[3].xyz + (cameraPosition - previousCameraPosition);
previousPosition = mat3(gbufferPreviousModelView) * previousPosition + gbufferPreviousModelView[3].xyz;
previousPosition.xy = projMAD(projMatrix, previousPosition).xy / -previousPosition.z * 0.5 + 0.5;
if (previousPosition.x > 0.0 && previousPosition.y > 0.0 && previousPosition.x < 1.0 && previousPosition.y < 1.0) {
if(raytracePos.z > 0.9999999) backgroundReflectMask = 1.0;
#if defined OVERWORLD_SHADER
reflection.a = raytracePos.z > 0.9999999 ? (isHand || isEyeInWater == 1 ? 1.0 : 0.0) : 1.0;
#else
reflection.a = 1.0;
#endif
#ifdef FORWARD_SPECULAR
// vec2 clampedRes = max(vec2(viewWidth,viewHeight),vec2(1920.0,1080.));
// vec2 resScale = vec2(1920.,1080.)/clampedRes;
// vec2 bloomTileUV = (((previousPosition.xy/texelSize)*2.0 + 0.5)*texelSize/2.0) / clampedRes*vec2(1920.,1080.);
// reflection.rgb = texture(colortex6, bloomTileUV / 4.0).rgb;
reflection.rgb = texture(colortex5, previousPosition.xy).rgb;
#else
reflection.rgb = textureLod(colortex5, previousPosition.xy, LOD).rgb;
#endif
}
// reflection.rgb = vec3(LOD/6);
// vec2 clampedRes = max(vec2(viewWidth,viewHeight),vec2(1920.0,1080.));
// vec2 resScale = vec2(1920.,1080.)/clampedRes;
// vec2 bloomTileUV = (((previousPosition.xy/texelSize)*2.0 + 0.5)*texelSize/2.0) / clampedRes*vec2(1920.,1080.);
// vec2 bloomTileoffsetUV[6] = vec2[](
// bloomTileUV / 4.,
// bloomTileUV / 8. + vec2(0.25*resScale.x+2.5*texelSize.x, .0),
// bloomTileUV / 16. + vec2(0.375*resScale.x+4.5*texelSize.x, .0),
// bloomTileUV / 32. + vec2(0.4375*resScale.x+6.5*texelSize.x, .0),
// bloomTileUV / 64. + vec2(0.46875*resScale.x+8.5*texelSize.x, .0),
// bloomTileUV / 128. + vec2(0.484375*resScale.x+10.5*texelSize.x, .0)
// );
// // reflectLength = pow(1-pow(1-reflectLength,2),5) * 6;
// reflectLength = (exp(-4*(1-reflectLength))) * 6;
// Reflections.rgb = texture(colortex6, bloomTileoffsetUV[0]).rgb;
return reflection;
}
float getReflectionVisibility(float f0, float roughness){
// the goal is to determine if the reflection is even visible.
// if it reaches a point in smoothness or reflectance where it is not visible, allow it to interpolate to diffuse lighting.
#if ROUGHNESS_THRESHOLD < 1
return 0.0;
#else
float thresholdValue = ROUGHNESS_THRESHOLD/100.0;
// the visibility gradient should only happen for dialectric materials. because metal is always shiny i guess or something
float dialectrics = max(f0*255.0 - 26.0,0.0)/229.0;
float value = 0.35; // so to a value you think is good enough.
float thresholdA = min(max( (1.0-dialectrics) - value, 0.0)/value, 1.0);
// use perceptual smoothness instead of linear roughness. it just works better i guess
float smoothness = 1.0-sqrt(roughness);
value = thresholdValue; // this one is typically want you want to scale.
float thresholdB = min(max(smoothness - value, 0.0)/value, 1.0);
// preserve super smooth reflections. if thresholdB's value is really high, then fully smooth, low f0 materials would be removed (like water).
value = 0.1; // super low so only the smoothest of materials are includes.
float thresholdC = 1.0-min(max(value - (1.0-smoothness), 0.0)/value, 1.0);
float visibilityGradient = max(thresholdA*thresholdC - thresholdB,0.0);
// a curve to make the gradient look smooth/nonlinear. just preference
visibilityGradient = 1.0-visibilityGradient;
visibilityGradient *=visibilityGradient;
visibilityGradient = 1.0-visibilityGradient;
visibilityGradient *=visibilityGradient;
return visibilityGradient;
#endif
}
// derived from N and K from labPBR wiki https://shaderlabs.org/wiki/LabPBR_Material_Standard
// using ((1.0 - N)^2 + K^2) / ((1.0 + N)^2 + K^2)
const vec3 HCM_F0 [8] = vec3[](
vec3(0.531228825312, 0.51235724246, 0.495828545714),// iron
vec3(0.944229966045, 0.77610211732, 0.373402004593),// gold
vec3(0.912298031535, 0.91385063144, 0.919680580954),// Aluminum
vec3(0.55559681715, 0.55453707574, 0.554779427513),// Chrome
vec3(0.925952196272, 0.72090163805, 0.504154241735),// Copper
vec3(0.632483812932, 0.62593707362, 0.641478899539),// Lead
vec3(0.678849234658, 0.64240055565, 0.588409633571),// Platinum
vec3(0.961999998804, 0.94946811207, 0.922115710997) // Silver
);
vec3 specularReflections(
in vec3 viewPos, // toScreenspace(vec3(screenUV, depth)
in vec3 playerPos,
in vec3 NplayerPos, // normalized
in vec3 lightVec, // light direction in world space
in vec2 noise, // x = bluenoise y = interleaved gradient noise
in vec3 flatNormal,
in vec3 normal, // normals in world space
in float roughness, // red channel of specular texture _S
in float f0, // green channel of specular texture _S
in vec3 albedo,
in vec3 diffuseLighting,
in vec3 lightColor, // should contain the light's color and shadows.
in float lightmap, // in anything other than world0, this should be 1.0;
in bool isHand // mask for the hand
#ifdef FORWARD_SPECULAR
, bool isWater
, inout float reflectanceForAlpha
#endif
,in vec4 flashLight_stuff
){
lightmap = min(max(lightmap-0.9,0.0)/0.1,1.0);
lightmap *= lightmap; lightmap = 1.0-lightmap;
lightmap *= lightmap; lightmap = 1.0-lightmap;
roughness = 1.0 - roughness;
roughness *= roughness;
f0 = f0 == 0.0 ? 0.02 : f0;
// if(isHand){
// f0 = 1.0;
// roughness = 0.0;
// }
bool isMetal = f0 > 229.5/255.0;
// get reflected vector
mat3 basis = CoordBase(normal);
vec3 viewDir = -NplayerPos*basis;
#if defined FORWARD_ROUGH_REFLECTION || defined DEFERRED_ROUGH_REFLECTION
vec3 samplePoints = SampleVNDFGGX(viewDir, roughness, noise.xy);
vec3 reflectedVector_L = basis * reflect(-normalize(viewDir), samplePoints);
reflectedVector_L = isHand ? reflect(NplayerPos, normal) : reflectedVector_L;
#else
vec3 reflectedVector_L = reflect(NplayerPos, normal);
#endif
float VdotN = dot(-normalize(viewDir), vec3(0.0,0.0,1.0));
float shlickFresnel = shlickFresnelRoughness(VdotN, roughness);
// F0 < 230 dialectrics
// F0 >= 230 hardcoded metal f0
// F0 == 255 use albedo for f0
albedo = f0 == 1.0 ? sqrt(albedo) : albedo;
vec3 metalAlbedoTint = isMetal ? albedo : vec3(1.0);
// get F0 values for hardcoded metals.
vec3 hardCodedMetalsF0 = f0 == 1.0 ? albedo : HCM_F0[int(clamp(f0*255.0 - 229.5,0.0,7.0))];
vec3 reflectance = isMetal ? hardCodedMetalsF0 : vec3(f0);
vec3 F0 = (reflectance + (1.0-reflectance) * shlickFresnel) * metalAlbedoTint;
#if defined FORWARD_SPECULAR
reflectanceForAlpha = clamp(dot(F0, vec3(0.3333333)), 0.0,1.0);
#if defined SNELLS_WINDOW
if(isEyeInWater == 1 && isWater){
// emulate how mojang did snells window in vibrant visuals because it works nicely tbh
float snellsWindow = min(max(0.54 - clamp(1.0 + VdotN,0,1),0.)/0.1,1.);
snellsWindow = 1.0-snellsWindow*snellsWindow;
snellsWindow *= snellsWindow*snellsWindow;
reflectanceForAlpha = f0 + (1.0-f0) * snellsWindow;
}
#endif
#endif
vec3 specularReflections = diffuseLighting;
float reflectionVisibilty = getReflectionVisibility(f0, roughness);
vec4 enviornmentReflection = vec4(0.0);
float backgroundReflectMask = lightmap;
#if (defined DEFERRED_BACKGROUND_REFLECTION || defined FORWARD_BACKGROUND_REFLECTION) || (DEFERRED_SSR_QUALITY > 0 || FORWARD_SSR_QUALITY > 0)
if(reflectionVisibilty < 1.0){
#if defined DEFERRED_BACKGROUND_REFLECTION || defined FORWARD_BACKGROUND_REFLECTION
#if !defined OVERWORLD_SHADER
vec3 backgroundReflection = volumetricsFromTex(reflectedVector_L, colortex4, roughness).rgb / 1200.0;
#else
//vec2 p = sphereToCarte(reflectedVector_L);
vec3 backgroundReflection = skyCloudsFromTex(reflectedVector_L, colortex4).rgb / 1200.0;
//vec3 backgroundReflection = imageLoad(reflectionSphere, ivec2(p)).rgb;
#if defined SNELLS_WINDOW
if(isEyeInWater == 1) backgroundReflection *= exp(-vec3(Water_Absorb_R, Water_Absorb_G, Water_Absorb_B) * 15.0)*2.0;
#endif
#endif
#endif
#if DEFERRED_SSR_QUALITY > 0 || FORWARD_SSR_QUALITY > 0
vec3 backgroundTint = vec3(1.0);
enviornmentReflection = getEnvironmentReflections(reflectedVector_L, flatNormal, normal, playerPos, viewPos, noise, isHand, roughness, backgroundReflectMask, backgroundTint
#ifdef FORWARD_SPECULAR
,isWater
#endif
);
#ifdef VOXEL_REFLECTIONS
backgroundReflection *= backgroundTint;
#endif
// darkening for metals.
vec3 DarkenedDiffuseLighting = isMetal ? diffuseLighting * (1.0-enviornmentReflection.a) * (1.0-lightmap) : diffuseLighting;
#else
// darkening for metals.
vec3 DarkenedDiffuseLighting = isMetal ? diffuseLighting * (1.0-lightmap) : diffuseLighting;
#endif
// composite all the different reflections together
#if defined DEFERRED_BACKGROUND_REFLECTION || defined FORWARD_BACKGROUND_REFLECTION
specularReflections = mix(DarkenedDiffuseLighting, backgroundReflection, backgroundReflectMask);
#endif
#if DEFERRED_SSR_QUALITY > 0 || FORWARD_SSR_QUALITY > 0
specularReflections = mix(specularReflections, enviornmentReflection.rgb, enviornmentReflection.a);
#endif
specularReflections = mix(DarkenedDiffuseLighting, specularReflections, F0);
// lerp back to diffuse lighting if the reflection has not been deemed visible enough
specularReflections = mix(specularReflections, diffuseLighting, reflectionVisibilty);
}
#endif
#if defined OVERWORLD_SHADER && SUN_SPECULAR_MULT > 0
vec3 lightSourceReflection = backgroundReflectMask*SUN_SPECULAR_MULT * lightColor * GGX(normal, -NplayerPos, lightVec, roughness, reflectance, metalAlbedoTint);
#if DEFERRED_SSR_QUALITY > 0 || FORWARD_SSR_QUALITY > 0
specularReflections += mix(lightSourceReflection, vec3(0.0), enviornmentReflection.a);
#else
specularReflections += lightSourceReflection*backgroundReflectMask;
#endif
#endif
#if defined FLASHLIGHT_SPECULAR && (defined DEFERRED_SPECULAR || defined FORWARD_SPECULAR)
vec3 flashLightReflection = vec3(FLASHLIGHT_R,FLASHLIGHT_G,FLASHLIGHT_B) * flashLight_stuff.a * GGX(normal, -flashLight_stuff.xyz, -flashLight_stuff.xyz, roughness, reflectance, metalAlbedoTint);
specularReflections += flashLightReflection;
#endif
return specularReflections;
}