uniform	vec4	u_gen;
uniform	vec4	u_parm0;
uniform	vec4	u_parm1;
uniform	vec4	u_parm2;
uniform	vec4	u_parma;
uniform	vec4	u_fogDistanceVector;
uniform	vec4	u_fogDepthVector;
uniform	float	u_eyeT;

#define	GLSL_CGEN_CONST				0.0
#define	GLSL_CGEN_LIGHTING_DIFFUSE		1.0
#define	GLSL_CGEN_VERTEX			2.0
#define	GLSL_CGEN_ONE_MINUS_VERTEX		3.0
#define	GLSL_CGEN_VERTEX_ALPHA			4.0
#define	GLSL_CGEN_ONE_MINUS_VERTEX_ALPHA	5.0

#define	GLSL_AGEN_CONST				0.0
#define	GLSL_AGEN_LIGHTING_SPECULAR		1.0
#define	GLSL_AGEN_VERTEX			2.0
#define	GLSL_AGEN_ONE_MINUS_VERTEX		3.0
#define	GLSL_AGEN_VERTEX_COLOR			4.0
#define	GLSL_AGEN_ONE_MINUS_VERTEX_COLOR	5.0
#define	GLSL_AGEN_PORTAL			6.0

vec4 colorGen (in vec3 glVertex, in vec4 gen, in vec4 parm0, in vec4 parm1, in vec4 parm2, in vec4 parma)
{
	vec4	col = parm0;	// default is GLSL_CGEN_CONST

	if (gen.x == GLSL_CGEN_LIGHTING_DIFFUSE)
	{	// parm0.xyz = lightDir
		// parm1 = ambientLight
		// parm2 = directedLight
		float incoming = dot(attr_Normal, parm0.xyz);
		col = vec4(parm1.rgb + max(incoming, 0.0) * parm2.rgb, 1.0);
	}
	if (gen.x == GLSL_CGEN_VERTEX)
		col = attr_Color;
	if (gen.x == GLSL_CGEN_ONE_MINUS_VERTEX)
		col = 1.0 - attr_Color;
	if (gen.x == GLSL_CGEN_VERTEX_ALPHA)
		col = vec4(attr_Color.a);
	if (gen.x == GLSL_CGEN_ONE_MINUS_VERTEX_ALPHA)
		col = 1.0 - vec4(attr_Color.a);

	if (gen.y >= GLSL_AGEN_CONST)
	{
		if (gen.y == GLSL_AGEN_CONST)
			col.a = parm0.a;
		if (gen.y == GLSL_AGEN_LIGHTING_SPECULAR)
		{	// parma.xyz = backEnd.or.viewOrigin
			vec3 lightDir = normalize(vec3(-960.0, 1980.0, 96.0) - glVertex);
			float d = dot(attr_Normal, lightDir);
			vec3 reflected = attr_Normal * 2.0 * d - lightDir;
			vec3 viewer = parma.xyz - glVertex;
			float ilength = inversesqrt(dot(viewer, viewer));
			float l = max(dot(reflected, viewer) * ilength, 0.0);
			col.a = l*l*l*l;
		}
		if (gen.y == GLSL_AGEN_VERTEX)
			col.a = attr_Color.a;
		if (gen.y == GLSL_AGEN_ONE_MINUS_VERTEX)
			col.a = 1.0 - attr_Color.a;
		if (gen.y == GLSL_AGEN_VERTEX_COLOR)
			col.a = (attr_Color.r + attr_Color.g + attr_Color.b) * 0.33333;
		if (gen.y == GLSL_AGEN_ONE_MINUS_VERTEX_COLOR)
			col.a = 1.0 - (attr_Color.r + attr_Color.g + attr_Color.b) * 0.33333;
		if (gen.y == GLSL_AGEN_PORTAL)
		{	// parma.xyz = backEnd.viewParms.or.origin
			// parma.w = 1.0 / tess.shader->portalRange
			col.a = length(glVertex - parma.xyz) * parma.w;
		}
	}

	if (gen.z != 0.0)		// ACFF_MODULATE_*
	{
		float s = dot(glVertex, u_fogDistanceVector.xyz) + u_fogDistanceVector.w;
		float t = dot(glVertex, u_fogDepthVector.xyz) + u_fogDepthVector.w;
		if (u_eyeT < 0.0)
		{
			if (t < 1.0)
				return col;	// point is outside, so no fogging
			t = 1.0/32.0 + 30.0/32.0 * t / ( t - u_eyeT );	// cut the distance at the fog plane
		}
		else
		{
			if (t < 0.0)
				return col;	// point is outside, so no fogging
			t = 31.0/32.0;
		}
		s -= 1.0/512.0;
		if ( s < 0.0 )
			return col;
		if ( t < 31.0/32.0 )
			s *= (t - 1.0/32.0) / (30.0/32.0);
		s = min(s * 8.0, 1.0);
		float f = 1.0 - sqrt(s);
		if (gen.z == 1.0)		// ACFF_MODULATE_RGB
			col.rgb *= f;
		if (gen.z == 2.0)		// ACFF_MODULATE_ALPHA
			col.a *= f;
		if (gen.z == 3.0)		// ACFF_MODULATE_RGBA
			col *= f;
	}

	col.a = clamp(col.a, 0.0, 1.0);
	return col;
}
