@vs vs
vec4 position(mat4 transformProjection, vec4 vertexPosition) {return transformProjection*vertexPosition; }
@end
@fs fs
#define voxelIndex(x, y, z) ((((z * 2) + y) * 2) + x)
layout (location = 0) out vec4 out0;
layout (location = 1) out vec4 out1;
layout (location = 2) out vec4 out2;
layout (location = 3) out vec4 out3;
layout (location = 4) out vec4 out4;
layout (location = 5) out vec4 out5;

uniform sampler3D volume;
uniform int mip;
uniform float z;

uniform sampler3D normal1;
uniform sampler3D normal2;
uniform sampler3D normal3;
uniform sampler3D normal4;
uniform sampler3D normal5;
uniform sampler3D normal6;

uniform sampler3D volume1;
uniform sampler3D volume2;
uniform sampler3D volume3;
uniform sampler3D volume4;
uniform sampler3D volume5;
uniform sampler3D volume6;

void fetchVoxels(out vec4 voxels[8], const in sampler3D t, ivec3 pos, int level){
 voxels = vec4[8](
 texelFetch(t, pos + ivec3(0, 0, 0), level), // 0
 texelFetch(t, pos + ivec3(1, 0, 0), level), // 1
 texelFetch(t, pos + ivec3(0, 1, 0), level), // 2
 texelFetch(t, pos + ivec3(1, 1, 0), level), // 3
 texelFetch(t, pos + ivec3(0, 0, 1), level), // 4
 texelFetch(t, pos + ivec3(1, 0, 1), level), // 5
 texelFetch(t, pos + ivec3(0, 1, 1), level), // 6
 texelFetch(t, pos + ivec3(1, 1, 1), level) // 7
 );
}

// Converts a color from sRGB gamma to linear light gamma
vec4 toLinear(vec4 sRGB)
{
    bvec4 cutoff = lessThan(sRGB, vec4(0.04045));
    vec4 higher = pow((sRGB + vec4(0.055))/vec4(1.055), vec4(2.4));
    vec4 lower = sRGB/vec4(12.92);

    return mix(higher, lower, cutoff);
}

void main() {

  int level = max(0,mip-2);
  ivec3 uvw = ivec3(ivec2(gl_FragCoord.xy), z) << 1;
  ivec3 xyz = uvw>>1;
  vec4 voxels[8];
  vec4 vx;
  vec3 vn;
  {
  // +x
  fetchVoxels(voxels, volume1, uvw, level);
  vx=(
    (voxels[voxelIndex(0, 0, 0)] + (voxels[voxelIndex(1, 0, 0)] * (1.0 - voxels[voxelIndex(0, 0, 0)].w))) +
    (voxels[voxelIndex(0, 1, 0)] + (voxels[voxelIndex(1, 1, 0)] * (1.0 - voxels[voxelIndex(0, 1, 0)].w))) +
    (voxels[voxelIndex(0, 0, 1)] + (voxels[voxelIndex(1, 0, 1)] * (1.0 - voxels[voxelIndex(0, 0, 1)].w))) +
    (voxels[voxelIndex(0, 1, 1)] + (voxels[voxelIndex(1, 1, 1)] * (1.0 - voxels[voxelIndex(0, 1, 1)].w)))) ;
  }
  vn=texelFetch(normal1,xyz,mip-1).xyz*2-1;
  vx.rgb*=clamp(dot(vn,vec3(-1,0,0)),0,1);
  vx.rgb/=vx.a;
  out0 = vx;
  {
  // +y
  fetchVoxels(voxels, volume2, uvw, level);
  vx=(
    (voxels[voxelIndex(0, 0, 0)] + (voxels[voxelIndex(0, 1, 0)] * (1.0 - voxels[voxelIndex(0, 0, 0)].w))) +
    (voxels[voxelIndex(1, 0, 0)] + (voxels[voxelIndex(1, 1, 0)] * (1.0 - voxels[voxelIndex(1, 0, 0)].w))) +
    (voxels[voxelIndex(0, 0, 1)] + (voxels[voxelIndex(0, 1, 1)] * (1.0 - voxels[voxelIndex(0, 0, 1)].w))) +
    (voxels[voxelIndex(1, 0, 1)] + (voxels[voxelIndex(1, 1, 1)] * (1.0 - voxels[voxelIndex(1, 0, 1)].w)))) ;
  }
  vn=texelFetch(normal2,xyz,mip-1).xyz*2-1;
  vx.rgb*=clamp(dot(vn,vec3(0,-1,0)),0,1);
  vx.rgb/=vx.a;
  out1 = vx;
  {
  // +z
  fetchVoxels(voxels, volume3, uvw, level);
  vx=(
    (voxels[voxelIndex(0, 0, 0)] + (voxels[voxelIndex(0, 0, 1)] * (1.0 - voxels[voxelIndex(0, 0, 0)].w))) +
    (voxels[voxelIndex(1, 0, 0)] + (voxels[voxelIndex(1, 0, 1)] * (1.0 - voxels[voxelIndex(1, 0, 0)].w))) +
    (voxels[voxelIndex(0, 1, 0)] + (voxels[voxelIndex(0, 1, 1)] * (1.0 - voxels[voxelIndex(0, 1, 0)].w))) +
    (voxels[voxelIndex(1, 1, 0)] + (voxels[voxelIndex(1, 1, 1)] * (1.0 - voxels[voxelIndex(1, 1, 0)].w)))) ;
  }
  vn=texelFetch(normal3,xyz,mip-1).xyz*2-1;
  vx.rgb*=clamp(dot(vn,vec3(0,0,-1)),0,1);
  vx.rgb/=vx.a;
  out2 = vx;
  {
  // -x
  fetchVoxels(voxels, volume4, uvw, level);
  vx=(
    (voxels[voxelIndex(1, 0, 0)] + (voxels[voxelIndex(0, 0, 0)] * (1.0 - voxels[voxelIndex(1, 0, 0)].w))) +
    (voxels[voxelIndex(1, 1, 0)] + (voxels[voxelIndex(0, 1, 0)] * (1.0 - voxels[voxelIndex(1, 1, 0)].w))) +
    (voxels[voxelIndex(1, 0, 1)] + (voxels[voxelIndex(0, 0, 1)] * (1.0 - voxels[voxelIndex(1, 0, 1)].w))) +
    (voxels[voxelIndex(1, 1, 1)] + (voxels[voxelIndex(0, 1, 1)] * (1.0 - voxels[voxelIndex(1, 1, 1)].w)))) ;
  }
  vn=texelFetch(normal4,xyz,mip-1).xyz*2-1;
  vx.rgb*=clamp(dot(vn,vec3(1,0,0)),0,1);
  vx.rgb/=vx.a;
  out3 = vx;
  {
  // -y
  fetchVoxels(voxels, volume5, uvw, level);
  vx=(
    (voxels[voxelIndex(0, 1, 0)] + (voxels[voxelIndex(0, 0, 0)] * (1.0 - voxels[voxelIndex(0, 1, 0)].w))) +
    (voxels[voxelIndex(1, 1, 0)] + (voxels[voxelIndex(1, 0, 0)] * (1.0 - voxels[voxelIndex(1, 1, 0)].w))) +
    (voxels[voxelIndex(0, 1, 1)] + (voxels[voxelIndex(0, 0, 1)] * (1.0 - voxels[voxelIndex(0, 1, 1)].w))) +
    (voxels[voxelIndex(1, 0, 1)] + (voxels[voxelIndex(1, 0, 1)] * (1.0 - voxels[voxelIndex(1, 1, 1)].w)))) ;
  }
  vn=texelFetch(normal5,xyz,mip-1).xyz*2-1;
  vx.rgb*=clamp(dot(vn,vec3(0,1,0)),0,1);
  vx.rgb/=vx.a;
  out4 = vx;
  {
  // -z
  fetchVoxels(voxels, volume6, uvw, level);
  vx=(
    (voxels[voxelIndex(0, 0, 1)] + (voxels[voxelIndex(0, 0, 0)] * (1.0 - voxels[voxelIndex(0, 0, 1)].w))) +
    (voxels[voxelIndex(1, 0, 1)] + (voxels[voxelIndex(1, 0, 0)] * (1.0 - voxels[voxelIndex(1, 0, 1)].w))) +
    (voxels[voxelIndex(0, 1, 1)] + (voxels[voxelIndex(0, 1, 0)] * (1.0 - voxels[voxelIndex(0, 1, 1)].w))) +
    (voxels[voxelIndex(1, 1, 1)] + (voxels[voxelIndex(1, 1, 0)] * (1.0 - voxels[voxelIndex(1, 1, 1)].w)))) ;
  }
  vn=texelFetch(normal6,xyz,mip-1).xyz*2-1;
  vx.rgb*=clamp(dot(vn,vec3(0,0,1)),0,1);
  vx.rgb/=vx.a;
  out5 = vx;
}
@end

