

ivec3 GetVoxelIndex(const in vec3 playerPos)
{
    vec3 cameraOffset = fract(cameraPosition);
    return ivec3(floor(playerPos + cameraOffset) + VoxelSize3 / 2u);
}

void SetVoxelBlock(const in vec3 playerPos, const in uint blockId)
{

    ivec3 voxelPos = GetVoxelIndex(playerPos);
    if (clamp(voxelPos, ivec3(0), ivec3(VoxelSize - 1u)) != voxelPos)
        return;
    /*
        vec2 texSize = textureSize(tex, 0);
        vec2 texelSize = 1.0 / texSize;
        vec2 uv0 = mc_midTexCoord.xy;
        vec2 uv1 = gl_MultiTexCoord0.xy;
        vec3 color_current0 = vec3(0.0);
        vec3 color_current1 = vec3(0.0);
        vec3 color_current = vec3(0.0);
        vec3 color_prev = vec3(0.0);

        color_prev = unpackUnorm4x8(imageLoad(imgVoxelColor, int(blockId)).r).rgb;
        float delta = 0.005;
        // Loop to sample the texture 9 times
        for (int x = -1; x <= 1; ++x)
        {
            for (int y = -1; y <= 1; ++y)
            {
                vec2 uv2 = uv1 + vec2(x, y) * delta;
                vec2 uv3 = uv0 + vec2(x, y) * delta;
                // Clamp uv2 to be within the bounds of uv1
                uv2 = clamp(uv2, vec2(0.0), vec2(1.0));
                color_current0 += texture(tex, uv2).rgb;
                color_current1 += texture(tex, uv3).rgb;
            }
        }

        // Average the color
        color_current0 /= 9.0;
        color_current1 /= 9.0;
        color_current = mix(color_current0, color_current1, 0.75);

        vec3 lightColor = mix(color_current, color_prev, 0.99);

        uint lightColor_mixed = packUnorm4x8(vec4(lightColor.rgb, 0.0));

        imageStore(imgVoxelColor, int(blockId), uvec4(lightColor_mixed, 0u, 0u, 0u));


    */
    imageStore(imgVoxelMask, voxelPos, uvec4(blockId));
}

void PopulateShadowVoxel(const in vec3 playerPos)
{
    uint voxelId = 0u;
    vec3 originPos = playerPos;

    if (
        renderStage == MC_RENDER_STAGE_TERRAIN_SOLID || renderStage == MC_RENDER_STAGE_TERRAIN_TRANSLUCENT ||
        renderStage == MC_RENDER_STAGE_TERRAIN_CUTOUT || renderStage == MC_RENDER_STAGE_TERRAIN_CUTOUT_MIPPED)
    {
        voxelId = uint(mc_Entity.x + 0.5);

#ifdef IRIS_FEATURE_BLOCK_EMISSION_ATTRIBUTE
        // if (voxelId == 0u && at_midBlock.w > 0) voxelId = uint(BLOCK_LIGHT_1 + at_midBlock.w - 1);
        if (at_midBlock.w > 0)
            voxelId = uint(max(mc_Entity.x, 100) + at_midBlock.w - 1);
#endif

        if (voxelId == 0u)
            voxelId = 1u;

        originPos += at_midBlock.xyz / 64.0;
    }

#ifdef LPV_ENTITY_LIGHTS
    if (
        ((renderStage == MC_RENDER_STAGE_ENTITIES && (currentRenderedItemId > 0 || entityId > 0)) || renderStage == MC_RENDER_STAGE_BLOCK_ENTITIES))
    {
        voxelId = uint(mc_Entity.x + 0.5);

        if (renderStage == MC_RENDER_STAGE_BLOCK_ENTITIES)
        {
            if (blockEntityId > 0 && blockEntityId < 500)
                voxelId = uint(blockEntityId);
        }
        else if (currentRenderedItemId > 0 && currentRenderedItemId < 1200)
        {
            if (entityId != ENTITY_ITEM_FRAME && entityId != ENTITY_PLAYER)
                voxelId = uint(currentRenderedItemId);
        }
        else
        {
            switch (entityId)
            {
            case ENTITY_BLAZE:
            case ENTITY_END_CRYSTAL:
            // case ENTITY_FIREBALL_SMALL:
            case ENTITY_GLOW_SQUID:
            case ENTITY_MAGMA_CUBE:
            case ENTITY_SPECTRAL_ARROW:
            case ENTITY_TNT:
                voxelId = uint(entityId);
                break;
            }
        }
    }
#endif

    if (voxelId > 0u)
        SetVoxelBlock(originPos, voxelId);
}