#version 430 core

layout(r32ui, binding = 0) uniform uimage2D fragmentOffset;
layout(rgba16f, binding = 1) uniform writeonly image2D fragmentNormal;
layout(r32f, binding = 2) uniform writeonly image2D fragmentDepth;
layout(r16ui, binding = 3) uniform writeonly uimage2D fragmentStencil;

layout(pixel_center_integer) in vec4 gl_FragCoord;
layout(early_fragment_tests) in;

uniform uint volumeProbeBit;
uniform uint pitch;
uniform uint alignment;

#define REDUCE_FACTOR $REDUCE_FACTOR$

void WriteNormal(vec3 normal)
{
  uint index = imageAtomicAdd(fragmentOffset, ivec2(gl_FragCoord.xy), 1) - alignment;
  ivec2 pos = ivec2(index % (pitch / REDUCE_FACTOR), index / (pitch / REDUCE_FACTOR)) * REDUCE_FACTOR + ivec2(gl_FragCoord.xy) % REDUCE_FACTOR;
  imageStore(fragmentNormal, pos, vec4(normal, 0.0));
  imageStore(fragmentDepth, pos, vec4(clamp(gl_FragCoord.z, 0.0, 1.0)));
  imageStore(fragmentStencil, pos, uvec4(volumeProbeBit));
};

in vec3 position;

void main()
{
  vec3 normal = cross(dFdx(position), dFdy(position));
  if (gl_FragCoord.z < 0.0) discard;
  WriteNormal(normalize(normal));
}
