#version 330 compatibility
#include "includes.glsl"
#extension GL_ARB_shader_image_load_store : enable

uniform sampler2D gtexture;
uniform sampler2D normals;
uniform sampler2D specular;
uniform ivec2 atlasSize;
layout(rgba8) uniform image2D colorimg7; // BlockLight locations
layout(rgba8) uniform image2D colorimg8; // Textures
layout(rgba8) uniform image2D colorimg9; // Specular

in vec2 texcoord;
in vec4 glcolor;
in vec3 Normal;
in vec3 ViewDir;
in vec2 TexSize;
in mat3 TBN;
flat in ivec2 VoxelCoord;
flat in ivec3 OffsetPos;
flat in float Dist;

int TextureRes = int(ceil(TexSize*vec2(atlasSize)/16.)*16.);

vec2 TextureSize = float(TextureRes)/vec2(atlasSize);
vec2 pixsize = TextureSize/TextureRes;

/* DRAWBUFFERS:056 */
layout(location = 0) out vec4 color;
layout(location = 1) out vec4 ScreenNormals;
layout(location = 2) out vec4 SpecularTex;

vec2 performParallax(in vec3 TexDir, out float Height){
	float CurrentHeight = 1.0;
	vec2 Coord = texcoord;
	vec2 CoordOffset = floor(texcoord/TextureSize)*TextureSize;
    for (int i=0; i<ParallaxSamples; i++){
        float Depth = CurrentHeight-texture(normals, Coord).a;
        float Step = -abs(Depth) / (float(1<<(i+1)) * Depth);
        int ParallaxSteps = int( ceil(1024.*length(TexDir.xy) / (float(1<<(i+1)) * pow(Dist, 2.))) );
        for (int l=0; l<ParallaxSteps; l++){
            if (-Depth*abs(Step)/Step < abs(Step/(ParallaxSteps*2.0))) break;
            CurrentHeight += Step/float(ParallaxSteps);
            Coord += TexDir.xy*Step*float(ParallaxDepth)/(-float(ParallaxSteps)*20.);
            Coord = mod(Coord-CoordOffset, TextureSize)+CoordOffset;
            Depth = CurrentHeight-texture(normals, Coord).a;
        }
        if (abs(Depth) < .0001) break;
    }
    
	Coord += 0.5*pixsize*TexDir.xy;
    Coord = mod(Coord-CoordOffset, TextureSize)+CoordOffset;

    Height = CurrentHeight;
	return Coord;
}

void main() {
    vec2 parallaxCoord = texcoord;
    float ParallaxHeight = 1.0;
    #ifdef POM
        if (texture(normals, texcoord).a < 1.0-Dist/100. && Dist<(ParallaxRenderDist)) parallaxCoord = performParallax(normalize(ViewDir * TBN), ParallaxHeight);
    #endif
    color = texture(gtexture, parallaxCoord)*glcolor;

    vec2 NormalTex = texture(normals, parallaxCoord).xy; // z component is AO
    vec3 ScrNorm = Normal;
    if (NormalMapStrength != 0.0) ScrNorm = normalize(TBN * vec3(NormalTex*2.0-1.0, (1./NormalMapStrength)*sqrt(1.0 - dot(NormalTex, NormalTex))));
    ScreenNormals = vec4(ScrNorm*0.5 + 0.5,1.);

    //Data Structure for Specular: r: Roughness, g: Reflectance, b: lumenosity, a: unuse
        //LabPBR: red: Smoothness, green: reflectance, blue: porosity, alpha: emission
        //SuesPBR: red: Smoothness, green: reflectance, blue: Emission, alpha: 
    vec4 Data = texture(specular, texcoord);
    SpecularTex = vec4(pow(1.0-(Data.r), 1.0), Data.g, Data.a*float(Data.a!=1.0), 1); //LabPBR

    vec4 WriteData;
    //if (length(mod(parallaxCoord/TextureSize, 1.0)-.5) > .4) return;

    WriteData = imageLoad(colorimg8, VoxelCoord);
    WriteData.rgb = (WriteData.rgb*0.95) + (color.rgb*0.05);
    imageStore(colorimg8, VoxelCoord, vec4(WriteData.rgb, 1));

    WriteData = imageLoad(colorimg9, VoxelCoord);
    WriteData.rgb = (WriteData.rgb*0.95) + (SpecularTex.rgb*0.05);
    imageStore(colorimg9, VoxelCoord, vec4(WriteData.rg, 0, 1));

    /*if (SpecularTex.b > 0.2){
        for (int i=0; i<LightsBinSize; i++){
            ivec2 ReadLoc = ivec2(i%viewWidth, i/viewWidth);
            if (imageLoad(colorimg7, ReadLoc).x == 0.0) {
                imageStore(colorimg7, ReadLoc, vec4(vec3(OffsetPos)/100., Data.a));
                break;
            }
            
        }
    }*/

	if (color.a<.1){
		discard;
	}
}