Files
Eclipse-Shader/shaders/dimensions/composite2.fsh
T

599 lines
21 KiB
GLSL

#include "/lib/settings.glsl"
#include "/lib/SSBOs.glsl"
#ifdef OVERWORLD_SHADER
in DATA {
flat vec3 WsunVec;
flat vec3 WmoonVec;
};
#endif
#define DEFERRED_SPECULAR
#define DEFERRED_SSR_QUALITY 30 // [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 200 300 400 500]
uniform sampler2D noisetex;
uniform sampler2D depthtex0;
uniform sampler2D depthtex1;
#ifdef DISTANT_HORIZONS
uniform sampler2D dhDepthTex;
uniform sampler2D dhDepthTex1;
#define dhVoxyDepthTex dhDepthTex
#define dhVoxyDepthTex1 dhDepthTex1
#endif
#ifdef VOXY
uniform sampler2D vxDepthTexOpaque;
uniform sampler2D vxDepthTexTrans;
#define dhVoxyDepthTex vxDepthTexTrans
#define dhVoxyDepthTex1 vxDepthTexOpaque
#endif
uniform sampler2D colortex0;
uniform sampler2D colortex1;
uniform sampler2D colortex2;
uniform sampler2D colortex3;
uniform sampler2D colortex4;
uniform sampler2D colortex5;
uniform sampler2D colortex6;
uniform sampler2D colortex7;
uniform sampler2D colortex8;
uniform sampler2D colortex9;
uniform sampler2D colortex10;
uniform sampler2D colortex11;
uniform sampler2D colortex12;
uniform sampler2D colortex13;
uniform sampler2D colortex14;
uniform sampler2D colortex15;
uniform vec2 texelSize;
uniform float viewHeight;
uniform float viewWidth;
uniform float nightVision;
uniform float fogEnd;
uniform vec3 fogColor;
uniform vec3 sunVec;
uniform float frameTimeCounter;
uniform int frameCounter;
uniform float far;
uniform float near;
uniform float farPlane;
uniform float dhVoxyNearPlane;
uniform float dhVoxyFarPlane;
uniform mat4 gbufferModelViewInverse;
uniform mat4 gbufferModelView;
uniform mat4 gbufferPreviousModelView;
uniform mat4 gbufferProjectionInverse;
uniform mat4 gbufferProjection;
uniform mat4 gbufferPreviousProjection;
uniform vec3 cameraPosition;
uniform vec3 previousCameraPosition;
uniform int hideGUI;
uniform int dhVoxyRenderDistance;
uniform int isEyeInWater;
uniform ivec2 eyeBrightnessSmooth;
uniform ivec2 eyeBrightness;
uniform float rainStrength;
uniform float blindness;
uniform float darknessFactor;
uniform float darknessLightFactor;
uniform float caveDetection;
uniform float sunElevation;
#include "/lib/res_params.glsl"
#define diagonal3(m) vec3((m)[0].x, (m)[1].y, m[2].z)
#define projMAD(m, v) (diagonal3(m) * (v) + (m)[3].xyz)
vec3 toScreenSpace(vec3 p) {
vec4 iProjDiag = vec4(gbufferProjectionInverse[0].x, gbufferProjectionInverse[1].y, gbufferProjectionInverse[2].zw);
vec3 p3 = p * 2. - 1.;
vec4 fragposition = iProjDiag * p3.xyzz + gbufferProjectionInverse[3];
return fragposition.xyz / fragposition.w;
}
float linearize(float dist) {
return (2.0 * near) / (far + near - dist * (far - near));
}
vec3 toClipSpace3Prev(vec3 viewSpacePosition) {
return projMAD(gbufferPreviousProjection, viewSpacePosition) / -viewSpacePosition.z * 0.5 + 0.5;
}
vec3 bilateralUpsample2(vec2 fragcoord, sampler2D colortex, out float outerEdgeResults, float referenceDepth, sampler2D depth, bool hand){
vec3 colorSum = vec3(0.0);
float edgeSum = 0.0;
const float threshold = 0.005;
const int samples = 5;
vec2 coord = fragcoord - 1.5;
vec2 UV = coord;
const ivec2 SCALE = ivec2(1.0);
ivec2 UV_COLOR = ivec2(UV);
ivec2 UV_NOISE = ivec2(gl_FragCoord.xy*texelSize + 1);
const ivec2 OFFSET[5] = ivec2[5](
ivec2(-1,-1),
ivec2( 1, 1),
ivec2(-1, 1),
ivec2( 1,-1),
ivec2( 0, 0)
// ,ivec2( 0, 1),
// ivec2( 0,-1),
// ivec2( 1, 0),
// ivec2(-1, 0)
);
for(int i = 0; i < samples; i++) {
float offsetDepth = linearize(texelFetch(depth, UV_COLOR + (OFFSET[i] + UV_NOISE), 0).r);
float edgeDiff = abs(offsetDepth - referenceDepth) < threshold ? 1.0 : 1e-7;
outerEdgeResults = max(outerEdgeResults, abs(referenceDepth - offsetDepth));
vec3 offsetColor = texelFetch(colortex, UV_COLOR + OFFSET[i] + UV_NOISE, 0).rgb;
colorSum += offsetColor*edgeDiff;
edgeSum += edgeDiff;
}
outerEdgeResults = outerEdgeResults > (hand ? 0.005 : referenceDepth*0.05 + 0.1) ? 1.0 : 0.0;
return colorSum / edgeSum;
}
vec3 VLTemporalFiltering2(vec2 texcoord, vec3 playerPosIn, in float referenceDepth, sampler2D depth, bool hand, vec3 currentFrame, float roughness){
// get previous frames position stuff for UV
vec3 playerPos = playerPosIn + (cameraPosition - previousCameraPosition);
vec3 previousPosition = mat3(gbufferPreviousModelView) * playerPos + gbufferPreviousModelView[3].xyz;
previousPosition = toClipSpace3Prev(previousPosition);
vec2 velocity = previousPosition.xy - texcoord;
previousPosition.xy = texcoord + velocity;
// return vec4(outerEdgeResults,0,0,1);
// return upsampledCurrentFrame;
if (previousPosition.x < 0.0 || previousPosition.y < 0.0 || previousPosition.x > 1.0 || previousPosition.y > 1.0 || hand) return currentFrame.rgb;
// to fill pixel gaps in geometry edges, do a bilateral upsample.
// pass a mask to only show upsampled color around the edges of blocks. this is so it doesnt blur reprojected results.
float outerEdgeResults = 0.0;
vec3 upsampledCurrentFrame = bilateralUpsample2(gl_FragCoord.xy , colortex0, outerEdgeResults, referenceDepth, depth, hand);
//return currentFrame;
// vec4 upsampledCurrentFrame = BilateralUpscale(colortex0, depth, gl_FragCoord.xy - 1.5, referenceDepth);
// /*
vec4 frameHistoryTex = texture(colortex12, previousPosition.xy*RENDER_SCALE);
float prevDepth = frameHistoryTex.a;
float linPrevDepth = linearize(previousPosition.z);
vec3 frameHistory = frameHistoryTex.rgb;
vec3 reprojectFrame = currentFrame.rgb;
if(!(frameHistory.r == 0.0 && frameHistory.g == 0.0 && frameHistory.b == 0.0) && (abs(prevDepth-linPrevDepth) < max(linPrevDepth * 0.02, 0.001))) {
vec3 col1 = texture(colortex0, texcoord + vec2( texelSize.x, texelSize.y)).rgb;
vec3 col2 = texture(colortex0, texcoord + vec2( texelSize.x, -texelSize.y)).rgb;
vec3 col3 = texture(colortex0, texcoord + vec2(-texelSize.x, -texelSize.y)).rgb;
vec3 col4 = texture(colortex0, texcoord + vec2(-texelSize.x, texelSize.y)).rgb;
vec3 col5 = texture(colortex0, texcoord + vec2( 0.0, texelSize.y)).rgb;
vec3 col6 = texture(colortex0, texcoord + vec2( 0.0, -texelSize.y)).rgb;
vec3 col7 = texture(colortex0, texcoord + vec2(-texelSize.x, 0.0)).rgb;
vec3 col8 = texture(colortex0, texcoord + vec2( texelSize.x, 0.0)).rgb;
vec3 colMax = max(currentFrame.rgb,max(col1,max(col2,max(col3, max(col4, max(col5, max(col6, max(col7, col8))))))));
vec3 colMin = min(currentFrame.rgb,min(col1,min(col2,min(col3, min(col4, min(col5, min(col6, min(col7, col8))))))));
vec3 clampedFrameHistory = clamp(frameHistory, colMin, colMax);
float blendingFactor = mix(0.025, 1.0, smoothstep(0.05, 0.25, length(cameraPosition-previousCameraPosition)));
blendingFactor = mix(1.0, blendingFactor, smoothstep(0.0, 0.1, roughness));
reprojectFrame = mix(clampedFrameHistory, currentFrame.rgb, blendingFactor);
}
// return clamp(reprojectFrame,0.0,65000.0);
return clamp(mix(reprojectFrame, upsampledCurrentFrame, outerEdgeResults),0.0,65000.0);
// */
}
float blueNoise(){
#ifdef TAA
return fract(texelFetch(noisetex, ivec2(gl_FragCoord.xy)%512, 0).a + 1.0/1.6180339887 * frameCounter);
#else
return fract(texelFetch(noisetex, ivec2(gl_FragCoord.xy)%512, 0).a + 1.0/1.6180339887);
#endif
}
float interleaved_gradientNoise_temporal(){
// #ifdef TAA
// return fract(52.9829189*fract(0.06711056*gl_FragCoord.x + 0.00583715*gl_FragCoord.y ) + 1.0/1.6180339887 * frameCounter);
// #else
// return fract(52.9829189*fract(0.06711056*gl_FragCoord.x + 0.00583715*gl_FragCoord.y ) + 1.0/1.6180339887);
// #endif
vec2 coord = gl_FragCoord.xy;
#ifdef TAA
coord += (frameCounter%40000) * 2.0;
#endif
return fract(52.9829189*fract(0.06711056*coord.x + 0.00583715*coord.y ) + 1.0/1.6180339887);
}
vec2 decodeVec2(float a){
const vec2 constant1 = 65535. / vec2( 256., 65536.);
const float constant2 = 256. / 255.;
return fract( a * constant1 ) * constant2 ;
}
vec3 decode (vec2 encn){
vec3 n = vec3(0.0);
encn = encn * 2.0 - 1.0;
n.xy = abs(encn);
n.z = 1.0 - n.x - n.y;
n.xy = n.z <= 0.0 ? (1.0 - n.yx) * sign(encn) : encn;
return clamp(normalize(n.xyz),-1.0,1.0);
}
vec3 toLinear(vec3 sRGB){
return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878);
}
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;
}
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);
}
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);
}
#ifdef IEXT_ENABLED
uniform bool IEXT_KEY_0;
#endif
vec4 calculateFlashlightData(in vec3 viewPos, bool hand){
#ifdef IEXT_ENABLED
if(IEXT_KEY_0) return vec4(0.0);
#endif
vec4 flashLightSpecularData = vec4(0.0);
if(hand){
return flashLightSpecularData;
}
// vec3 shiftedViewPos = viewPos + vec3(-0.25, 0.2, 0.0);
// vec3 shiftedPlayerPos = mat3(gbufferModelViewInverse) * shiftedViewPos + gbufferModelViewInverse[3].xyz + (cameraPosition - previousCameraPosition) * 3.0;
// shiftedViewPos = mat3(gbufferPreviousModelView) * shiftedPlayerPos + gbufferPreviousModelView[3].xyz;
vec3 shiftedViewPos;
vec3 shiftedPlayerPos;
float forwardOffset;
#ifdef VIVECRAFT
if (vivecraftIsVR) {
forwardOffset = 0.0;
shiftedPlayerPos = mat3(gbufferModelViewInverse) * viewPos + gbufferModelViewInverse[3].xyz + vivecraftRelativeMainHandPos;
shiftedViewPos = shiftedPlayerPos * mat3(vivecraftRelativeMainHandRot);
} else
#endif
{
forwardOffset = 0.5;
shiftedViewPos = viewPos + vec3(-0.25, 0.2, 0.0);
shiftedPlayerPos = mat3(gbufferModelViewInverse) * shiftedViewPos + gbufferModelViewInverse[3].xyz + (cameraPosition - previousCameraPosition) * 3.0;
shiftedViewPos = mat3(gbufferPreviousModelView) * shiftedPlayerPos + gbufferPreviousModelView[3].xyz;
}
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 flashLightSpecular = lightFalloff * exp2(-7.0*shiftedLinearDistance*shiftedLinearDistance) * FLASHLIGHT_BRIGHTNESS_MULT;
flashLightSpecularData = vec4(normalize(shiftedPlayerPos), flashLightSpecular);
return flashLightSpecularData;
}
#if defined IS_LPV_ENABLED || defined PHOTONICS && defined PHOTONICS && !defined PH_ENABLE_HANDHELD_LIGHT
uniform bool firstPersonCamera;
uniform vec3 relativeEyePosition;
uniform int heldItemId;
uniform int heldItemId2;
uniform sampler3D texLpv1;
uniform sampler3D texLpv2;
#include "/lib/util.glsl"
#include "/lib/hsv.glsl"
#include "/lib/lpv_common.glsl"
#include "/lib/lpv_render.glsl"
#include "/lib/blocks.glsl"
#include "/lib/lpv_blocks.glsl"
vec3 GetHandLight(const in int itemId, const in vec3 playerPos, inout float lightRange) {
vec3 lightFinal = vec3(0.0);
uint blockData = imageLoad(imgBlockData, itemId).r;
vec4 lightColorRange = unpackUnorm4x8(blockData);
lightRange = lightColorRange.a * 255.0;
if (lightRange > 0.0) {
vec3 lightColor = srgbToLinear(lightColorRange.rgb);
float lightDist = length(playerPos+relativeEyePosition)*0.7;
float falloff = pow(1.0 - lightDist / lightRange, 3.0);
lightFinal = lightColor * max(falloff, 0.0);
}
return lightFinal;
}
#ifdef BELTBORNE_LANTERNS
uniform int IEXT_beltborne_lanterns_Id;
#endif
#endif
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
}
/* RENDERTARGETS:12,3 */
void main() {
vec2 texcoord = gl_FragCoord.xy*texelSize;
float depth = texelFetch(depthtex1, ivec2(gl_FragCoord.xy),0).x;
// bool hand = depth < 0.56;
float z = depth;
#if defined DISTANT_HORIZONS || defined VOXY
float DH_depth1 = 1.0;
float swappedDepth;
if(z >= 1.0) {
DH_depth1 = texelFetch(dhVoxyDepthTex1,ivec2(gl_FragCoord.xy),0).x;
swappedDepth = DH_depth1;
} else {
swappedDepth = z;
}
#else
float DH_depth1 = 1.0;
float swappedDepth = z;
#endif
bool isSky = swappedDepth >= 1.0;
gl_FragData[0] = vec4(0.0);
vec3 FINAL_COLOR = texture(colortex3, texcoord).rgb;
if(!isSky) {
float frDepth = linearize(z);
gl_FragData[0].a = frDepth;
vec4 data = texelFetch(colortex1, ivec2(gl_FragCoord.xy), 0);
vec4 dataUnpacked0 = vec4(decodeVec2(data.x),decodeVec2(data.y)); // albedo, masks
vec4 dataUnpacked1 = vec4(decodeVec2(data.z),decodeVec2(data.w)); // normals, lightmaps
float opaqueMasks = dataUnpacked1.w;
bool hand = abs(opaqueMasks-0.75) < 0.01;
bool entities = abs(opaqueMasks-0.45) < 0.01;
bool opaqueParticles = abs(opaqueMasks-0.85) <0.01;
#ifdef SHADER_GRASS
bool isShaderGrass = abs(opaqueMasks-0.80) < 0.01;
#else
const bool isShaderGrass = false;
#endif
vec3 viewPos = toScreenSpace(vec3(texcoord/RENDER_SCALE, z));
vec3 playerPos = mat3(gbufferModelViewInverse) * viewPos;
vec3 NplayerPos = normalize(playerPos);
playerPos += gbufferModelViewInverse[3].xyz;
// 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[8](
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 albedo = toLinear(vec3(dataUnpacked0.xz,dataUnpacked1.x));
vec2 lightmap = dataUnpacked1.yz;
vec4 stuff = texelFetch(colortex8, ivec2(gl_FragCoord.xy), 0);
vec3 normal = decode(stuff.xy);
vec2 speculars = stuff.zw;
float roughness = speculars.r;
float f0 = speculars.g;
roughness = 1.0 - roughness;
roughness *= roughness;
f0 = f0 == 0.0 ? 0.02 : f0;
bool isMetal = f0 > 229.5/255.0;
// get reflected vector
mat3 basis = CoordBase(normal);
vec3 viewDir = -NplayerPos*basis;
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;
vec4 currentFrame = texture(colortex0, texcoord);
float alpha = getReflectionVisibility(f0, roughness);
vec3 denoisedReflections = currentFrame.rgb;
if(roughness > 0.005 && alpha < 0.9999 && !hand && !entities && !opaqueParticles
#if defined DISTANT_HORIZONS || defined VOXY
&& z < 1.0
#endif
) {
denoisedReflections = VLTemporalFiltering2(texcoord, playerPos, frDepth, depthtex1, hand, currentFrame.rgb, roughness);
gl_FragData[0].rgb = denoisedReflections;
}
denoisedReflections.rgb = mix(FINAL_COLOR, denoisedReflections.rgb, F0);
FINAL_COLOR = mix(denoisedReflections.rgb, FINAL_COLOR, alpha);
#if defined OVERWORLD_SHADER && SUN_SPECULAR_MULT > 0
vec3 lightSourceReflection = SUN_SPECULAR_MULT * texture(colortex15, texcoord).rgb * GGX(normal, -NplayerPos, WsunVec, roughness, reflectance, metalAlbedoTint);
FINAL_COLOR += lightSourceReflection;
#endif
#if defined FLASHLIGHT_SPECULAR && (defined DEFERRED_SPECULAR || defined FORWARD_SPECULAR)
vec4 flashlightData = calculateFlashlightData(viewPos, hand);
vec3 flashLightReflection = vec3(FLASHLIGHT_R,FLASHLIGHT_G,FLASHLIGHT_B) * flashlightData.a * GGX(normal, -flashlightData.xyz, -flashlightData.xyz, roughness, reflectance, metalAlbedoTint);
FINAL_COLOR += flashLightReflection;
#endif
#if defined Hand_Held_lights && defined IS_LPV_ENABLED
if(!hand && firstPersonCamera && !isShaderGrass) {
if (heldItemId > 0){
vec3 shiftedViewPos = viewPos + vec3(-0.25, 0.2, 0.0);
vec3 shiftedPlayerPos = mat3(gbufferModelViewInverse) * shiftedViewPos + gbufferModelViewInverse[3].xyz + (cameraPosition - previousCameraPosition);
float lightRange = 0.0;
vec3 handLightCol = GetHandLight(heldItemId, shiftedPlayerPos, lightRange);
if(lightRange > 0.0) {
vec3 handheldReflection1 = handLightCol * GGX(normal, -shiftedPlayerPos, -shiftedPlayerPos, roughness, reflectance, metalAlbedoTint);
FINAL_COLOR += handheldReflection1;
}
}
if (heldItemId2 > 0){
vec3 shiftedViewPos = viewPos + vec3(0.25, 0.2, 0.0);
vec3 shiftedPlayerPos = mat3(gbufferModelViewInverse) * shiftedViewPos + gbufferModelViewInverse[3].xyz + (cameraPosition - previousCameraPosition);
float lightRange = 0.0;
vec3 handLightCol = GetHandLight(heldItemId2, shiftedPlayerPos, lightRange);
if(lightRange > 0.0) {
vec3 handheldReflection1 = handLightCol * GGX(normal, -shiftedPlayerPos, -shiftedPlayerPos, roughness, reflectance, metalAlbedoTint);
FINAL_COLOR += handheldReflection1;
}
}
#ifdef BELTBORNE_LANTERNS
if (IEXT_beltborne_lanterns_Id > 0){
vec3 shiftedViewPos = viewPos + vec3(0.15, 0.2, 0.0);
vec3 shiftedPlayerPos = mat3(gbufferModelViewInverse) * shiftedViewPos + gbufferModelViewInverse[3].xyz + (cameraPosition - previousCameraPosition);
float lightRange = 0.0;
vec3 handLightCol = GetHandLight(IEXT_beltborne_lanterns_Id, shiftedPlayerPos, lightRange);
if(lightRange > 0.0) {
vec3 handheldReflection1 = handLightCol * GGX(normal, -shiftedPlayerPos, -shiftedPlayerPos, roughness, reflectance, metalAlbedoTint);
FINAL_COLOR += handheldReflection1;
}
}
#endif
}
#endif
}
gl_FragData[1].rgb = FINAL_COLOR;
}