uniform mat4 modelView;
uniform mat4 modelViewProj;
uniform mat4 billboard;
uniform vec4 flipTCoordsAndFogDensity;
uniform vec4 fogColor;
uniform vec4 billboardColor;
uniform vec4 fade;
uniform mat4 basis;

void main()
{
    vec3 eyePosition = (modelView * gl_Vertex).xyz;
    float fogDistance = length(eyePosition);
    float fogExponent = clamp(fogDistance * flipTCoordsAndFogDensity.y, 0.0, 1.0);
    float fogFactor = clamp(exp(-abs(fogExponent)), 0.0, 1.0);
    vec4 preFadedColor;

    if (billboardColor.w > 0.0)
    {
        preFadedColor.xyz = mix(fogColor.xyz, billboardColor.xyz, fogFactor);
        preFadedColor.w = billboardColor.w;
    }
    else
    {
        preFadedColor = mix(fogColor, gl_Color, fogFactor);
    }

    vec4 texCoord = gl_MultiTexCoord0.xyzw;

	float voxelFade = 1.0;
	if (fade.z > 0.0) {
		if (texCoord.w > 0.0) {
			voxelFade = abs(texCoord.w) * (fade.w - fade.z);
		} else if (texCoord.w < 0.0) {
			voxelFade = 1.0 - abs(texCoord.w) * (fade.w - fade.z);	
		}
		voxelFade = clamp(voxelFade, 0.0, 1.0);
	}

    gl_FrontColor = mix(vec4(0.0, 0.0, 0.0, 0.0), preFadedColor, fade.xxxx * voxelFade * (1.0 - fogExponent * fogExponent));

    vec4 vertPos = vec4(abs(texCoord.x) * sign(texCoord.y), abs(texCoord.x) * sign(texCoord.z), 0.0, 1.0);

    vec4 rotatedPos;

    float angle = abs(texCoord.z) + abs(texCoord.y) * sign(texCoord.x) * fade.w;
	angle = mod(angle, 3.14159265 * 2.0);
    float cosLength = cos(angle);
    float sinLength = sin(angle);

    rotatedPos.x = (cosLength * vertPos.x + -sinLength * vertPos.y);
    rotatedPos.y = (sinLength * vertPos.x + cosLength * vertPos.y);
    rotatedPos.z = 0.0;
    rotatedPos.w = 1.0;
    
    vec4 vert = gl_Vertex * basis;

    mat4 xlate = mat4(1.0, 0.0, 0.0, 0.0,
                      0.0, 1.0, 0.0, 0.0,
                      0.0, 0.0, 1.0, 0.0,
                      vert.x, vert.y, vert.z, 1.0);

    mat4 xlatebb = (xlate * billboard);
    mat4 mvb = (modelViewProj * xlatebb);
    gl_Position = (mvb * rotatedPos);

    gl_TexCoord[0] = vec4(0.5 * sign(texCoord.y) + 0.5,
                          0.5 * sign(texCoord.z) * flipTCoordsAndFogDensity.x + 0.5,
                          0.0, 1.0);

}
