//INIT
#version 330

#define PI      3.1415926536
#define PI_HALF 1.5707963268

uniform sampler2D RngData;
uniform sampler2D Spectrum;
uniform sampler2D Emission;
uniform sampler2D ICDF_tex;
uniform sampler2D PDF_tex;
uniform vec2 EmitterPos;
uniform vec2 EmitterDir;
uniform float EmitterPower;
uniform float SpatialSpread;
uniform vec2 AngularSpread;

in vec2 vTexCoord;

layout(location=0) out vec4 posOut;
layout(location=1) out vec4 rngOut;
layout(location=2) out vec4 rgbOut;

const vec4 q = vec4(   1225.0,    1585.0,    2457.0,    2098.0);
const vec4 r = vec4(   1112.0,     367.0,      92.0,     265.0);
const vec4 a = vec4(   3423.0,    2646.0,    1707.0,    1999.0);
const vec4 m = vec4(4194287.0, 4194277.0, 4194191.0, 4194167.0);

float rand(inout vec4 state)
{
    vec4 beta = floor(state/q);
    vec4 p = a*(state - beta*q) - beta*r;
    beta = (sign(-p)+1.0) * 0.5 * m;
    state = p + beta;
    return fract(dot(state/m, vec4(1.0, -1.0, 1.0, -1.0)));
}


void main() 
{
    vec4 state = texture2D(RngData, vTexCoord);
    float theta = AngularSpread.x + (rand(state) - 0.5)*AngularSpread.y;
    vec2 dir = vec2(cos(theta), sin(theta));
    vec2 pos = EmitterPos + (rand(state) - 0.5)*SpatialSpread*vec2(-EmitterDir.y, EmitterDir.x);

    float randL = rand( state );
    float randO = rand( state );
    
    float spectrumOffset = texture2D( ICDF_tex, vec2( randL, 0.5) ).r + randO * (1.0/256.0);
    float lambda = 360.0 + (750.0 - 360.0)*spectrumOffset;
    float pdf    = texture2D(PDF_tex, vec2(spectrumOffset, 0.5)).r;
    vec3  rgb    = EmitterPower * texture2D(Emission, vec2(spectrumOffset, 0.5)).r * texture2D(Spectrum, vec2(spectrumOffset, 0.5)).rgb / pdf;

    posOut = vec4(pos, dir);
    rngOut = state;
    rgbOut = vec4(rgb, lambda);
}
