uniform	vec2	u_tgen;
uniform	vec3	u_parmtc;
uniform	vec3	u_tcGenVectorS;
uniform	vec3	u_tcGenVectorT;
uniform	float	u_tcModParms[29];	// TR_MAX_TEXMODS * 6 + TR_MAX_TEXMODS + 1

#define	TCGEN_TEXTURE			1.0
#define	TCGEN_LIGHTMAP			2.0
#define	TCGEN_ENVIRONMENT_MAPPED	3.0
#define	TCGEN_FOG			4.0
#define	TCGEN_VECTOR			5.0

#define	GLSL_TMOD_NONE			0.0
#define	GLSL_TMOD_TURBULENT		1.0
#define	GLSL_TMOD_MATRIX		2.0

void tcGen (out vec2 st, in vec3 glVertex)
{
	// texGen
	st = vec2(0.0);		// TCGEN_BAD (default) shut up compiler :(
	if (u_tgen.x == TCGEN_TEXTURE)
		st = attr_texCoords;
	if (u_tgen.x == TCGEN_LIGHTMAP)
		st = attr_lightCoords;
	if (u_tgen.x == TCGEN_ENVIRONMENT_MAPPED)
	{	// u_parmtc = backEnd.or.viewOrigin
		vec3 viewer = normalize(u_parmtc - glVertex);
		float d = dot(attr_Normal, viewer);
		vec3 reflected = attr_Normal * 2.0 * d - viewer;
		st = 0.5 + reflected.yz * 0.5;
	}
	if (u_tgen.x == TCGEN_FOG)
	{
		st.s = dot(glVertex, u_fogDistanceVector.xyz) + u_fogDistanceVector.w;
		st.t = dot(glVertex, u_fogDepthVector.xyz) + u_fogDepthVector.w;
		if (u_eyeT < 0.0)
		{
			if (st.t < 1.0)
				st.t = 1.0/32.0;	// point is outside, so no fogging
			else
				st.t = 1.0/32.0 + 30.0/32.0 * st.t / ( st.t - u_eyeT );	// cut the distance at the fog plane
		}
		else
		{
			if (st.t < 0.0)
				st.t = 1.0/32.0;	// point is outside, so no fogging
			else
				st.t = 31.0/32.0;
		}
	}
	if (u_tgen.x == TCGEN_VECTOR)
		st = vec2( dot(glVertex, u_tcGenVectorS), dot(glVertex, u_tcGenVectorT) );

	// texMod
	int tcOffs = 0;
	while (true)
	{     
		float f = u_tcModParms[tcOffs++];
		if (f == GLSL_TMOD_NONE)
			break;
		if (f == GLSL_TMOD_MATRIX)
		{	// stupid ATI HD2600 can't parse 'a*u[t++]+b*u[t++]+u[t++]' :((
			vec2 sm = st;
			float pa, pb, pc, pd, pe, pf;
			pa = u_tcModParms[tcOffs++];
			pb = u_tcModParms[tcOffs++];
			pc = u_tcModParms[tcOffs++];
			pd = u_tcModParms[tcOffs++];
			pe = u_tcModParms[tcOffs++];
			pf = u_tcModParms[tcOffs++];
			st.s = dot(vec3(sm, 1.0), vec3(pa, pb, pc));
			st.t = dot(vec3(sm, 1.0), vec3(pd, pe, pf));
			continue;	// stupid NVidia GLSL compiler (new Detonator + old cards like 9600GT/8500GT)
		}
		if (f == GLSL_TMOD_TURBULENT)
		{
			vec2 sm;
			float now = u_tcModParms[tcOffs++];
			float amplitude = u_tcModParms[tcOffs++];
			sm.x = sin(((glVertex.x + glVertex.z) * 0.125/128.0 + now) * 2.0 * 3.14159);
			sm.y = sin((glVertex.y * 0.125/128.0 + now) * 2.0 * 3.14159);
			st += sm * amplitude;
			continue;	// stupid NVidia GLSL compiler (new Detonator + old cards like 9600GT/8500GT)
		}
	}
}
