

layout(location = 0) out vec4 gbuffer_data_0;
layout(location = 1) out vec4 gbuffer_data_1;
layout(location = 2) out vec4 ice_albedo;
vec2 encodeNormal(in vec3 normal)
{
    normal.xy /= abs(normal.x) + abs(normal.y) + abs(normal.z);
    return (normal.z <= 0.0 ? (1.0 - abs(normal.yx)) * vec2(normal.x >= 0.0 ? 1.0 : -1.0, normal.y >= 0.0 ? 1.0 : -1.0)
                            : normal.xy) *
               0.5 +
           0.5;
}
#define MIN_LIGHT_BOOST 4.0 // [0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1.0 1.05 1.1 1.15 1.2 1.25 1.3 1.35 1.4 1.45 1.5 1.55 1.6 1.65 1.7 1.75 1.8 1.85 1.9 1.95 2.0 2.05 2.1 2.15 2.2 2.25 2.3 2.35 2.4 2.45 2.5 2.55 2.6 2.65 2.7 2.75 2.8 2.85 2.9 2.95 3.0 3.05 3.1 3.15 3.2 3.25 3.3 3.35 3.4 3.45 3.5 3.55 3.6 3.65 3.7 3.75 3.8 3.85 3.9 3.95 4.0 4.05 4.1 4.15 4.2 4.25 4.3 4.35 4.4 4.45 4.5 4.55 4.6 4.65 4.7 4.75 4.8 4.85 4.9 4.95 5.0 5.05 5.1 5.15 5.2 5.25 5.3 5.35 5.4 5.45 5.5 5.55 5.6 5.65 5.7 5.75 5.8 5.85 5.9 5.95 6.0 6.05 6.1 6.15 6.2 6.25 6.3 6.35 6.4 6.45 6.5 6.55 6.6 6.65 6.7 6.75 6.8 6.85 6.9 6.95 7.0 7.05 7.1 7.15 7.2 7.25 7.3 7.35 7.4 7.45 7.5 7.55 7.6 7.65 7.7 7.75 7.8 7.85 7.9 7.95 8.0 8.05 8.1 8.15 8.2 8.25 8.3 8.35 8.4 8.45 8.5 8.55 8.6 8.65 8.7 8.75 8.8 8.85 8.9 8.95 9.0 9.05 9.1 9.15 9.2 9.25 9.3 9.35 9.4 9.45 9.5 9.55 9.6 9.65 9.7 9.75 9.8 9.85 9.9 9.95 10.0]
#define OVERWORLD
#define SHADOWS_ENABLED
const float PI = 3.141592653589793238462643383279502884197169;
const float TWO_PI = 6.283185307179586476925286766559;

vec3 worldToView(vec3 worldPos)
{
    return (gbufferModelView * vec4(worldPos, 0.0)).xyz;
}
vec3 calcAmbientLight(vec3 wNormal, vec2 lightmap, vec3 ambientUp, vec3 ambientDown, vec3 ambientRight,
                      vec3 ambientLeft, vec3 ambientB, vec3 ambientF, vec3 RSML, float diffuseSun, vec3 torch)
{
    vec3 ambientCoefs = wNormal / dot(abs(wNormal), vec3(1.0));

    vec3 clampedCoefs = max(ambientCoefs, 0.0);
    vec3 clampedCoefsNeg = max(-ambientCoefs, 0.0);

    float mixstrength = clamp(pow(shadowblend, 0.3), 0.0, 1.0);
    float oneMinusMixStrength = 1.0 - mixstrength;
    vec3 sun = sunLight;
#ifndef SHADOWS_ENABLED
    // Calculate luma (luminosity / perceived brightness)
    float luma = dot(sun.rgb, vec3(0.299, 0.587, 0.114));

    // Increase vibrance by pushing color away from gray (amplify difference from luma)
    float vibranceFactor = 1.5; // Increase this for more vibrance
    sun.rgb = mix(vec3(luma), sun.rgb, vibranceFactor);
#endif

#ifndef OVERWORLD
    sun = mix(sunLight, vec3(1), 0.5) * 0.01;

    float skymap = 1.0;
#else
    float skymap = lightmap.y;
#endif

    float skymap2 = skymap * skymap;

    // Precompute factors to minimize operations
    float diffuseSunClamped = clamp(diffuseSun, 0.5, 1.0);

    // Compute bounce lighting

    float bounceFactor = (0.15 * diffuseSunClamped) * oneMinusMixStrength + 0.25;
    vec3 bounce = sun * 0 * skymap;

#ifdef NETHER
    bounce = vec3(1, 0.25, 0.12) * 3.0;
#endif

#ifdef END
    bounce = vec3(1, 0.30, 0.12) * 1.0;
#endif

    // Adjust ambient sides based on mixstrength
    // ambientRight = ambientDown * oneMinusMixStrength + ambientRight * mixstrength;
    //   ambientLeft = ambientDown * oneMinusMixStrength + ambientLeft * mixstrength;

    // Combine ambient light components
    vec3 ambientCombined = (ambientUp * clampedCoefs.y +
                            ambientDown * clampedCoefsNeg.y +
                            ambientRight * clampedCoefs.x +
                            ambientLeft * clampedCoefsNeg.x +
                            ambientB * clampedCoefs.z +
                            ambientF * clampedCoefsNeg.z) *
                               skymap2 +
                           RSML;

    // Mix ambientCombined with bounce lighting
    ambientCombined = ambientCombined * 0.9 + bounce * 0.1;

#ifndef OVERWORLD

    ambientCombined *= 2.0;
#endif
#ifndef SHADOWS_ENABLED

    //  ambientCombined *= 2;
#endif
    // Calculate diffuse lighting
    vec3 diffuseLight = diffuseSun * sun + ambientCombined;

    // Compute darkness factors
    float darknessFactor = darknessLightFactor * darknessLightFactor * darknessLightFactor;
    diffuseLight *= (1.0 - 6.0 * darknessFactor);

    // Prepare torch and small light contributions
    vec3 torchContribution = torch * hdrMulttorch;
    float screenBrightnessTerm = 1.0 + screenBrightness * MIN_LIGHT_BOOST;
    vec3 smallLightContribution = vec3(0.002, 0.005, 0.006) * screenBrightnessTerm;

    // Sum up the light components and apply final adjustments
    vec3 light = max(diffuseLight + torchContribution + smallLightContribution + nightVision * 0.1, 0.001);
    light *= 1.0 - darknessLightFactor;

    return light;
}
vec3 calcAmbientLight(vec3 Normal, vec2 lightmap, vec3 ambientUp, float diffuseSun, vec3 torch)
{

    vec3 ambient = calcAmbientLight(Normal, lightmap.xy, ambientUp, ambientUp, ambientUp, ambientUp, ambientUp, ambientUp, vec3(0.6 * ambientUp.b * lightmap.y), diffuseSun, torch);

    return ambient;
}
float encodeVec2(vec2 a)
{
    // Ensure 'a' is within the range [0.0, 1.0]
    vec2 clamped = clamp(a, 0.0, 1.0);

    // Scale both components to an 8-bit range
    float high = ceil(clamped.x * 64); // Avoid rounding errors at the upper limit
    float low = ceil(clamped.y * 256); // Ensure full use of 8-bit range

    // Combine the two 8-bit values into a single float
    return (high * 256.0 + low) / 65536.0; // Normalize to full 16-bit range
}
vec3 toLinear(vec3 sRGB)
{
    return sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878);
}

float n2d(vec2 p)
{
    vec2 i = floor(p);
    vec2 f = p - i;

    f *= f * (3.0 - 2.0 * f);

    // Hash function to generate pseudo-random values at the four corners
    vec4 hashInput = vec4(0.0, 1.0, 113.0, 114.0) + dot(i, vec2(1.0, 113.0));
    vec4 hashed = fract(sin(mod(hashInput, 6.2831853)) * 43758.5453);

    // Matrix of the four corner values
    mat2 values = mat2(hashed.xy, hashed.zw);

    // Bilinear interpolation using the smoothed local position
    return dot(values * vec2(1.0 - f.y, f.y), vec2(1.0 - f.x, f.x));
}
vec2 HashVec(vec2 d)
{
    const vec2 k1 = vec2(123.4, 234.5);
    const vec2 k2 = vec2(234.5, 345.6);
    const float MULT = 58322.51;
    const float TIME_MULT = 2.0;

    vec2 s = sin(vec2(dot(d, k1), dot(d, k2)));
    return sin(s * MULT + frameTimeCounter * TIME_MULT);
}

float Octave(vec2 uv, float gridSize)
{
    // Precompute the scaled coordinate to avoid redundant multiplication.
    vec2 scaledUV = uv * gridSize;
    vec2 gridUV = fract(scaledUV);
    vec2 cellId = floor(scaledUV);
    vec2 smoothUV = smoothstep(0.0, 1.0, gridUV);

    // Precompute wrapped cell IDs for the four corners.
    vec2 cell00 = mod(cellId, gridSize);
    vec2 cell10 = mod(cellId + vec2(1.0, 0.0), gridSize);
    vec2 cell01 = mod(cellId + vec2(0.0, 1.0), gridSize);
    vec2 cell11 = mod(cellId + vec2(1.0, 1.0), gridSize);

    // Precompute the UV offsets for interpolation.
    vec2 uv10 = gridUV - vec2(1.0, 0.0);
    vec2 uv01 = gridUV - vec2(0.0, 1.0);
    vec2 uv11 = gridUV - vec2(1.0, 1.0);

    // Compute dot products with hashed vectors.
    float n00 = dot(HashVec(cell00), gridUV);
    float n10 = dot(HashVec(cell10), uv10);
    float n01 = dot(HashVec(cell01), uv01);
    float n11 = dot(HashVec(cell11), uv11);

    // Perform bilinear interpolation.
    float nx0 = mix(n00, n10, smoothUV.x);
    float nx1 = mix(n01, n11, smoothUV.x);
    return mix(nx0, nx1, smoothUV.y);
}

float WaterMapFast(vec2 pos)
{
    // return seaSurf(pos * 512);
    // return getWaterHeightmap(pos);

    float gradient = 0.0;
    float frequency = 8.0;
    float amplitude = 6.0;

    // Use fewer iterations for a faster approximation.
    for (int i = 0; i < 4; i++)
    {
        gradient += (Octave(pos, frequency) + 0.5) / amplitude;
        frequency *= 3.0;
        amplitude *= 1.75;
    }

    return gradient * 6.0;
}

float getWaterHeightmap(vec2 posxz)
{
    float scale = 16.0;
    posxz *= scale;

    vec2 pos = posxz;
    vec2 movement = vec2(-0.01 * frameTimeCounter * scale, 0.0);
    float caustic = 0.0;
    float weightSum = 0.0;
    const float radiance = 2.39996;
    const mat2 rotationMatrix = mat2(vec2(cos(radiance), -sin(radiance)), vec2(sin(radiance), cos(radiance)));
    for (int i = 0; i < 4; i++)
    {
        float wave = n2d((pos * vec2(3.0, 1.0) + movement) * exp(i * 1.0));
        caustic += wave * exp(-i * 1.0);
        weightSum += exp(-i * 1.0);
        pos = rotationMatrix * pos;
    }
    return caustic / weightSum;
}
mat3 tbn_from_world_normal(vec3 N)
{
    // Normalize the input normal just to be safe
    N = normalize(N);

    // Choose an arbitrary vector that is not parallel to the normal
    vec3 arbitrary = abs(N.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);

    // Compute the tangent vector as a vector orthogonal to the normal
    vec3 T = normalize(cross(arbitrary, N));

    // Compute the bitangent as the cross product of the normal and the tangent
    vec3 B = cross(N, T); // No need to normalize, it is already orthogonal

    // Construct and return the TBN matrix
    return mat3(T, B, N);
}
float interm(vec2 pxz)
{
    return texture(colortex7, pxz).r;

    // return WaterMapFast(pxz);
}
vec3 waterNormal(vec2 rawUv2, vec3 viewDir, vec3 normal0)
{
    vec2 uv = fract(rawUv2 / 128.0);

    const float MAP_RES = 512.0;
    const float TILE_SIZE_M = 128.0;                  // meters per tile
    const float INV_MAP_RES = 1.0 / MAP_RES;          // texel size in UV
    const float TEXEL_WS = TILE_SIZE_M * INV_MAP_RES; // world‐space meters per texel

    vec2 o = vec2(INV_MAP_RES, INV_MAP_RES);

    float hL = interm(uv - vec2(o.x, 0.0));
    float hR = interm(uv + vec2(o.x, 0.0));
    float hD = interm(uv - vec2(0.0, o.y));
    float hU = interm(uv + vec2(0.0, o.y));

    vec2 d = vec2(hR - hL, hU - hD) / (1.5 * TEXEL_WS);
    d = clamp(d, -1, +1) * 1.0;

    float f0 = max(0.0, 1.0 - abs(dot(viewDir, normal0)));
    float fade = f0 * (1.0 - float(isEyeInWater));

    vec3 v = vec3(-d * (1.0 - fade), 1.0);
    vec3 n = normalize(v);

    vec3 outval = n * 0.5 + 0.5;
    return outval;
    // return mix(outval, vec3(0.5, 0.5, 1.0), pow(f0, 2.0));
}
vec4 getMaterialProperties(int materialIndex)
{
    // Reflectance, Smoothness, Subsurface amounts, and Porosity
    switch (materialIndex)
    {
    case 1: // Wood
        return vec4(0.05, 0.25, 0.0, 0.04);
    case 2: // Polished Stone
        return vec4(0.2, 0.7, 0.0, 0.01);
    case 3: // Stone
        return vec4(0.05, 0.3, 0.0, 0.03);
    case 4: // Fabric
        return vec4(0.02, 0.1, 0.25, 0.0);
    case 6: // Terracotta
        return vec4(0.04, 0.35, 0.0, 0.03);
    case 7: // Crystals
        return vec4(0.7, 0.8, 0.5, 0.0);
    case 8: // Water
        return vec4(0.0, 0.0, 0.0, 0.0);
    case 9: // Ice
        return vec4(0.05, 0.7, 0.25, 0.0);
    case 10: // Glass
        return vec4(0.05, 0.7, 0.0, 0.0);
    case 11: // Dirt & Grass
        return vec4(0.05, 0.2, 0.0, 0.25);
    case 12: // Bricks
        return vec4(0.04, 0.3, 0.0, 0.07);
    case 13: // Miscellaneous
        return vec4(0.05, 0.6, 0.0, 0.01);
    case 14: // Iron
        return vec4(0.901961, 0.9, 0.0, 0.0);
    case 15: // Gold
        return vec4(0.905882, 0.9, 0.0, 0.0);
    case 16: // Copper
        return vec4(0.917647, 0.8, 0.0, 0.0);
    case 2003: // Foliage (Leaves)
    case 2013: // Foliage (Modded & Fallback)
        return vec4(0.03, 0.25, 0.5, 0.0);
    case 2001: // Foliage (Tall Flowers)
    case 2002: // Foliage (Tall Flowers)
    case 2004: // Foliage (Tall Flowers)
    case 2005: // Foliage (Other Plants)
    case 2011: // Foliage (Modded & Fallback)
        return vec4(0.03, 0.2, 0.75, 0.0);
    case 10010: // Banners
        return vec4(0.03, 0.2, 0.254, 0.0);
    default:
        return vec4(0.03, 0.1, 0.0, 0.07);
        // Default value if index is out of range
    }
}

#include "/lib/water/ssr_voxy.glsl"

vec3 toWorldSpace(vec3 p3)
{
    p3 = mat3(gbufferModelViewInverse) * p3 + gbufferModelViewInverse[3].xyz;

#ifdef PIXEL_LOCK
    p3 = floor((p3 + cameraPosition) * 16 + 0.001) / 16 - cameraPosition + 0.5 / 16;
#endif

    return p3;
}
float phaseg(float x, float g)
{
    float gg = g * g;
    return (gg * -0.25 + 0.25) * pow(-2.0 * (g * x) + (gg + 1.0), -1.5) / PI;
}

float computeSSS(float sssAmount, vec3 albedo, vec3 normal, vec3 lightPos, float avgDepth, float diffuseSun)
{
    // Adjust depth value to simulate realistic scattering (input avgDepth is derived from shadow mapping)
    avgDepth = sqrt(avgDepth);

    float lum = luma(albedo);
    vec3 diff = albedo - lum;

    // Calculate extinction factor based on albedo
    // float extinction = 1.0 - luma(albedo) * 0.85;
    float extinction = 1.0 - luma(diff) * 0.85;

    // Calculate the angle factor between the normal and light position
    float angleFactor = dot(normalize(normal), lightPos);

    // Calculate extinction factor based on depth and extinction
    float extinctionFactor = exp(-avgDepth * 11.0 * extinction);

    // Base subsurface scattering effect calculation
    float sssBase = extinctionFactor + 3.0 * pow(extinctionFactor, 1.0 / 3.0);

    // Calculate the phase factor using the angle factor
    float phaseFactor = phaseg(angleFactor, 0.75);

    // Calculate scattering using the phase factor
    float scattering = clamp((0.7 + 0.3 * PI * phaseFactor) * 1.5 / 3.0, 0.0, 1.0);

    // Calculate final subsurface scattering effect
    float sssValue = clamp(sssBase * scattering, 0.0, 1.0);

    return 1;
}

#define diagonal3(m) vec3((m)[0].x, (m)[1].y, m[2].z)
#define projMAD(m, v) (diagonal3(m) * (v) + (m)[3].xyz)
#define viewMAD(m, v) (mat3(m) * (v) + (m)[3].xyz)
vec3 nvec3(vec4 pos)
{
    return pos.xyz / pos.w;
}
vec4 nvec4(vec3 pos)
{
    return vec4(pos.xyz, 1.0);
}
vec3 toClipSpace3(vec3 viewSpacePosition)
{
    return projMAD(gbufferProjection, viewSpacePosition) / -viewSpacePosition.z * 0.5 + 0.5;
}
float ld(const float dist)
{
    return (2.0 * near) / (far + near - dist * (far - near));
}
vec2 rayTraceShadowAlt(float NdotL, vec3 lightDir, vec3 fragpos, float noise, bool sss)
{
    vec2 uv = gl_FragCoord.xy * texelSize;

    float steps = 16.0;
    float shadow = 1.0;
    float sssOut = 0.0;
    float Stepmult = (sss ? 2.0 : 3.0);

    float rayLength = ((fragpos.z + lightDir.z * 1.73205080757 * far) > -1.73205080757 * near) ? (-1.73205080757 * near - fragpos.z) / lightDir.z : 1.73205080757 * far;
    float vdepth = (texture(vxDepthTexOpaque, uv, 0).x);
    bool isvanilla = (vdepth >= 1.0);
    vec3 clipPosition0 = nvec3(vxProj * nvec4(fragpos)) * 0.5 + 0.5;
    vec3 end0 = toClipSpace3_voxy(fragpos + lightDir * rayLength);

    vec3 clipPosition1 = nvec3(gbufferProjection * nvec4(fragpos)) * 0.5 + 0.5;
    vec3 end1 = toClipSpace3(fragpos + lightDir * rayLength);

    vec3 clipPosition = clipPosition0;
    vec3 end = end0;
    if (isvanilla)
    {
        clipPosition = clipPosition1;
        end = end1;
    }

    vec3 direction = end - clipPosition;
    float len = max(abs(direction.x) / texelSize.x, abs(direction.y) / texelSize.y);
    vec3 stepv = direction.xyz / len;

    vec3 rayDir = stepv * Stepmult;

    vec3 screenPos = clipPosition + rayDir * noise;

    float minZ = screenPos.z;
    float maxZ = screenPos.z;

    for (int i = 0; i < int(steps); i++)
    {
        float samplePos0 = texture2D(depthtex0, screenPos.xy).x;
        float samplePos1 = texture2D(vxDepthTexOpaque, screenPos.xy).x;
        float samplePos = samplePos1;
        if (isvanilla)
        {
            samplePos = samplePos0;
        }

        if (samplePos < screenPos.z && (samplePos <= max(minZ, maxZ) && samplePos >= min(minZ, maxZ)))
        {

            vec2 linearZ = vec2(ld(screenPos.z), ld(samplePos));
            float threshold = abs(linearZ.x - linearZ.y) / linearZ.x;

            if (threshold < 0.05)
                shadow = 0.0;

            sssOut += 1.0 / steps;
        }

        minZ = maxZ - (sss ? 1.0 : 0.0001) / ld(samplePos);
        if (isvanilla)
        {
            maxZ += rayDir.z - 0.000002 * float(!sss);
        }
        else
        {
            maxZ += rayDir.z - mix(0.0002, 0.0, float(vdepth));
        }

        screenPos += rayDir;
    }
    return vec2(shadow, sssOut);
}

void voxy_emitFragment(VoxyFragmentParameters parameters)
{
    vec4 outcolor;

    // Get base properties
    bool iswater = (int(parameters.customId) == 8);
    bool isice = (int(parameters.customId) == 9);

    vec4 albedo = (parameters.sampledColour);
    albedo.rgb = toLinear(albedo.rgb * parameters.tinting.rgb);

    const vec3 wcolor = vec3(0.18, 0.35, 0.43);
    vec4 color = parameters.tinting;
    vec3 viewVector = toScreenSpace(gl_FragCoord.xyz * vec3(texelSize, 1.0));
    vec3 p3 = toWorldSpace(viewVector);
    vec3 normFragpos = normalize(viewVector);
    vec2 texc = gl_FragCoord.xy * texelSize;

    bool entity = bool(texture(colortex5, texc).g > 0);

#ifndef VANILLA_WATER
    outcolor = iswater ? vec4(toLinear(mix(wcolor, color.rgb, 0.25)), 0.5) : albedo;
    #ifdef DISTANT_HORIZONS
    outcolor = iswater ? vec4(mix(toLinear(wcolor), pow(color.rgb / color.a, vec3(2.0)), 0.25), 0.5) : albedo;
    #endif
#else
    outcolor = iswater ? vec4(albedo.rgb, 0.5) : albedo;

#endif
    if (isice)
        outcolor.a = 1;
    vec4 materialProps = vec4(getMaterialProperties(int(parameters.customId)));
    vec4 materialProps2 = vec4(materialProps.z, 0, materialProps.x, materialProps.y);
    // from Cortex
    vec3 normal = normalize(vec3(
                                uint((parameters.face >> 1) == 2),
                                uint((parameters.face >> 1) == 0),
                                uint((parameters.face >> 1) == 1)) *
                            (float(int(parameters.face) & 1) * 2.0 - 1.0));
    if (iswater)
    {

        mat3 TBNUP = tbn_from_world_normal(normal);
        vec3 posxz = p3 + cameraPosition;
        vec3 normalw = worldToView(normal);

        vec3 normalTex = waterNormal(posxz.xz - posxz.y, normFragpos, normalw);
        // normalTex = vec3(0.5, 0.5, 1.0);

          normal = normalize(TBNUP * (normalTex * 2.0 - 1.0));
    }
    float sssAmount = float(isice) * 0.25;
    float noise = 0.5;
    vec2 lmtexcoord = parameters.lightMap;
    float alpha0 = iswater ? 0.1 : outcolor.a;
    vec3 normalWorld = worldToView(normal);

    float diffuseSun = max(dot(normal, lightPos), 0.0) * lmtexcoord.y;
    float shading = 1.0;
    vec2 shading2 = rayTraceShadowAlt(diffuseSun, worldToView(lightPos), viewVector, noise, (sssAmount > 0.0));
    shading = mix(0.0, shading2.x, min(eyeBrightnessSmooth.y / 256 + lmtexcoord.y, 1.0));
    diffuseSun = min(diffuseSun, shading);

    if (isice)
    {
        diffuseSun = diffuseSun * shadowblend * (-0.9 * rainStrength + 1.0);
    }
    else
    {

        diffuseSun *= (1 - rainStrength * 0.9);
    }
    vec3 torch = vec3(0.0);

    float eyeBright = pow(clamp(eyeBrightnessSmooth.y / 240.0, 0.0, 1.0), 0.01);

    vec3 ambient = calcAmbientLight(normal, lmtexcoord, atmosphereUp, diffuseSun, torch);

    vec3 diffuse = ambient * outcolor.rgb * diffuseSun;
    vec3 transmission = ambient * outcolor.rgb;
    if (!isice)
    {
        outcolor.rgb = mix(transmission, diffuse, outcolor.a * outcolor.a);
    }
    else
    {
        outcolor.rgb = transmission;
    }
    outcolor = reflections(lmtexcoord.y, normal, viewVector, materialProps2, outcolor, diffuseSun, albedo.rgb, alpha0, isice);

    // outcolor = vec4(vec3(diffuseSun), outcolor.a);

    // Encode gbuffer data
    // outcolor.rgb = vec3(materialProps2.y);
    // outcolor.a = 1;
    /*
        if (sssAmount > 0.0)
        {

            float SSS2 = computeSSS(sssAmount, albedo, p3, lightPos, avgDepth, min(diffuseSun, shading)) *(lightmap.y * lightmap.y * lightmap.y * lightmap.y);
            SSS = mix(SSS, SSS2, mixamount);
        }

    */
    // outcolor = vec4(1, 0, 0, 1);
    gbuffer_data_0 = outcolor;
    gbuffer_data_1 = iswater ? vec4(1, 0, 0, 0.95) : vec4(0, 0, 1, 0.1);
}