/*
=============
EmitSkyPolys
=============
*/
void EmitSkyPolysMulti (msurface_t *fa)
{
	glpoly_t	*p;
	float		*v;
	int			i;
	float	s, ss, t, tt;
	vec3_t	dir;
	float	length;

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	GL_Bind (solidskytexture);

	GL_EnableMultitexture();
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
	GL_Bind (alphaskytexture);

	for (p=fa->polys ; p ; p=p->next)
	{
		glBegin (GL_POLYGON);
		for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
		{
			VectorSubtract (v, r_origin, dir);
			dir[2] *= 3;	// flatten the sphere

			length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
			length = sqrt (length);
			length = 6*63/length;

			dir[0] *= length;
			dir[1] *= length;

			s = (realtime*8 + dir[0]) * (1.0/128);
			t = (realtime*8 + dir[1]) * (1.0/128);

			ss = (realtime*16 + dir[0]) * (1.0/128);
			tt = (realtime*16 + dir[1]) * (1.0/128);

			qglMTexCoord2fARB (GL_TEXTURE0_ARB, s, t);
			qglMTexCoord2fARB (GL_TEXTURE1_ARB, ss, tt);
			glVertex3fv (v);
		}
		glEnd ();
	}
	GL_DisableMultitexture();
}

/*
=============
EmitSkyPolys
=============
*/
void EmitSkyPolys (msurface_t *fa)
{
	glpoly_t	*p;
	float		*v;
	int			i;
	float	s, t;
	vec3_t	dir;
	float	length;

	for (p=fa->polys ; p ; p=p->next)
	{
		glBegin (GL_POLYGON);
		for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
		{
			VectorSubtract (v, r_origin, dir);
			dir[2] *= 3;	// flatten the sphere

			length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
			length = sqrt (length);
			length = 6*63/length;

			dir[0] *= length;
			dir[1] *= length;

			s = (speedscale + dir[0]) * (1.0/128);
			t = (speedscale + dir[1]) * (1.0/128);

			glTexCoord2f (s, t);
			glVertex3fv (v);
		}
		glEnd ();
	}
}

/*
===============
EmitBothSkyLayers

Does a sky warp on the pre-fragmented glpoly_t chain
This will be called for brushmodels, the world
will have them chained together.
===============
*/
void EmitBothSkyLayers (msurface_t *fa)
{
	GL_DisableMultitexture();
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	if (gl_mtexable) {
		EmitSkyPolysMulti (fa);
		return;
	}

	GL_Bind (solidskytexture);
	speedscale = realtime*8;
	speedscale -= (int)speedscale & ~127 ;

	EmitSkyPolys (fa);

	glEnable (GL_BLEND);
	GL_Bind (alphaskytexture);
	speedscale = realtime*16;
	speedscale -= (int)speedscale & ~127 ;

	EmitSkyPolys (fa);

	glDisable (GL_BLEND);
}
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
	msurface_t	*removelink, *fa;

	GL_DisableMultitexture();
	if ((r_skydetail.value==1)&&(oldsky!=1)){
		R_DrawSkyBoxChain (s);
		return;
	}

	if (gl_mtexable) {
		for ( ; s ; s=s->texturechain, removelink->texturechain=NULL)
		{
			EmitSkyPolysMulti (s);
			removelink=s;
		}
		return;
	}

	// used when gl_texsort is on
	GL_Bind(solidskytexture);
	speedscale = realtime*8;
	speedscale -= (int)speedscale & ~127 ;

	for (fa=s ; fa ; fa=fa->texturechain)
		EmitSkyPolys (fa);

	glEnable (GL_BLEND);
	GL_Bind (alphaskytexture);
	speedscale = realtime*16;
	speedscale -= (int)speedscale & ~127 ;

	for ( ; s ; s=s->texturechain, removelink->texturechain=NULL)
	{
		EmitSkyPolys (fa);
		removelink=s;
	}

	glDisable (GL_BLEND);
}

/*
=============
EmitWaterPolys

Does a water warp on the pre-fragmented glpoly_t chain
JHL:HACK; modified to render two layers...
=============
*/
void EmitWaterPolys (msurface_t *fa)
{
	glpoly_t	*p;
	float		*v;
	int			i;
	float		s, t, os, ot;
	vec3_t		nv;	//qmb :water wave

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable (GL_BLEND);
	glColor4f (1,1,1,r_wateralpha.value);

	for (p=fa->polys ; p ; p=p->next)
	{
		glBegin (GL_POLYGON);
		for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
		{
			os = v[3];
			ot = v[4];

			s = os + turbsin[(int)((ot*0.125+cl.time) * TURBSCALE) & 255];
			s *= (1.0/64);

			t = ot + turbsin[(int)((os*0.125+cl.time) * TURBSCALE) & 255];
			t *= (1.0/64);

			VectorCopy(v, nv);

			if (r_wave.value)
				nv[2] = v[2] + r_wave.value *sin(v[0]*0.02+cl.time)*sin(v[1]*0.02+cl.time)*sin(v[2]*0.02+cl.time);

			glTexCoord2f (s, t);
			glVertex3fv (nv);
		}
		glEnd ();
	}

	glColor4f(1, 1, 1, r_wateralpha.value);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	if (gl_dualwater.value){
		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
		glColor4f(1, 1, 1, r_wateralpha.value*0.5);

		for (p=fa->polys ; p; p=p->next)
		{
			glBegin (GL_POLYGON);
			for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
			{
				os = v[3];
				ot = v[4];

				s = os + turbsin[(int)((ot*0.25+(cl.time*2)) * TURBSCALE) & 255];
				s *= (0.5/64)*(-1);

				t = ot + turbsin[(int)((os*0.25+(cl.time*2)) * TURBSCALE) & 255];
				t *= (0.5/64)*(-1);
		
				VectorCopy(v, nv);

				//qmb :water wave
				if (r_wave.value)
					nv[2] = v[2] + r_wave.value *sin(v[0]*0.02+cl.time)*sin(v[1]*0.02+cl.time)*sin(v[2]*0.02+cl.time);

				glTexCoord2f (s, t);
				glVertex3fv (nv);
			}
			glEnd ();
		}
		
	}
		glDisable (GL_BLEND);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glColor4f (1,1,1,1);

}

/*
=============
EmitWaterPolys

Does a water warp on the pre-fragmented glpoly_t chain
JHL:HACK; modified to render two layers...
=============
*/
void EmitWaterPolysMulti (msurface_t *fa)
{
	glpoly_t	*p;
	float		*v;
	int			i;
	float		s, ss, t, tt, os, ot;
	vec3_t		nv;	//qmb :water wave
	//Texture shader
	float		args[4] = {0.05f,0.0f,0.0f,0.02f};

	/*
	args[0] = gl_test0.value;
	args[1] = gl_test1.value;
	args[2] = gl_test2.value;
	args[3] = gl_test3.value;
	*/

	GL_DisableMultitexture();
	GL_Bind (fa->texinfo->texture->gl_texturenum);

	/*
	Texture Shader waterwarp
	Damn this looks fantastic

	WHY texture shaders? because I can!
	- MrG
	*/
	if (gl_shader) {
		if (!dst_texture)
			CreateDSTTex();
		glBindTexture(GL_TEXTURE_2D,dst_texture);
		glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
		
		GL_EnableMultitexture();
		glBindTexture(GL_TEXTURE_2D,fa->texinfo->texture->gl_texturenum);
		glEnable(GL_TEXTURE_2D);

		glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
		glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
		glTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
		glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);

		// use this so that the new water isnt so bright anymore
		// We wont bother check for the extensions availabiliy, as the hardware required
		// to make it this far definately supports this as well
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);

		glEnable(GL_TEXTURE_SHADER_NV);
	}else {
		GL_EnableMultitexture();
		GL_Bind (fa->texinfo->texture->gl_texturenum);

		if (gl_combine)
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
		else
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	}

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable (GL_BLEND);
	glColor4f (1,1,1,r_wateralpha.value);

	for (p=fa->polys ; p ; p=p->next)
	{
		glBegin (GL_POLYGON);
		for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
		{
			os = v[3];
			ot = v[4];

			s = os + turbsin[(int)((ot*0.125+cl.time) * TURBSCALE) & 255];
			s *= (1.0/64);

			ss = os + turbsin[(int)((ot*0.25+(cl.time*2)) * TURBSCALE) & 255];
			ss *= (0.5/64)*(-1);

			t = ot + turbsin[(int)((os*0.125+cl.time) * TURBSCALE) & 255];
			t *= (1.0/64);

			tt = ot + turbsin[(int)((os*0.25+(cl.time*2)) * TURBSCALE) & 255];
			tt *= (0.5/64)*(-1);

			VectorCopy(v, nv);

			if (r_wave.value)
				nv[2] = v[2] + r_wave.value *sin(v[0]*0.02+cl.time)*sin(v[1]*0.02+cl.time)*sin(v[2]*0.02+cl.time);

			qglMTexCoord2fARB (GL_TEXTURE0_ARB, s, t);
			qglMTexCoord2fARB (GL_TEXTURE1_ARB, ss, tt);

			glVertex3fv (nv);
		}
		glEnd ();
	}
	glColor4f (1,1,1,1);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable (GL_BLEND);
	GL_DisableMultitexture();
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

	if (gl_combine) { // MrG - texture shader waterwarp
		glDisable(GL_TEXTURE_SHADER_NV);
	}
}

/*
================
R_DrawWaterChain
================
*/
void R_DrawWaterChain (msurface_t *s)
{
	msurface_t *removelink;

	if ((r_wateralpha.value == 0)||!s)
		return;

	GL_Bind (s->texinfo->texture->gl_texturenum);

	for ( ; s ; s=s->texturechain, removelink->texturechain=NULL) {
		if (gl_mtexable)
			EmitWaterPolysMulti (s);
		else
			EmitWaterPolys (s);
		removelink=s;
	}
}