/*
=================
R_DrawAliasModel

=================
*/
void R_DrawAliasModel (entity_t *e)
{
    int			i;
    dmdl_t		*paliashdr;
    float		an;
    vec3_t		bbox[8];
    image_t		*skin;

    if ( !( e->flags & RF_WEAPONMODEL ) )
    {
        if ( R_CullAliasModel( bbox, e ) )
            return;
    }

    if ( e->flags & RF_WEAPONMODEL )
    {
        if ( r_lefthand->value == 2 )
            return;
    }

    paliashdr = (dmdl_t *)currentmodel->extradata;

    //
    // get lighting information
    //
    // PMM - rewrote, reordered to handle new shells & mixing
    // PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy
    //
    if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
    {
        VectorClear (shadelight);
        if (currententity->flags & RF_SHELL_HALF_DAM)
        {
            shadelight[0] = 0.56;
            shadelight[1] = 0.59;
            shadelight[2] = 0.45;
        }
        if ( currententity->flags & RF_SHELL_DOUBLE )
        {
            shadelight[0] = 0.9;
            shadelight[1] = 0.7;
        }
        if ( currententity->flags & RF_SHELL_RED )
            shadelight[0] = 1.0;
        if ( currententity->flags & RF_SHELL_GREEN )
            shadelight[1] = 1.0;
        if ( currententity->flags & RF_SHELL_BLUE )
            shadelight[2] = 1.0;
    }
    /*
    		// PMM -special case for godmode
    		if ( (currententity->flags & RF_SHELL_RED) &&
    			(currententity->flags & RF_SHELL_BLUE) &&
    			(currententity->flags & RF_SHELL_GREEN) )
    		{
    			for (i=0 ; i<3 ; i++)
    				shadelight[i] = 1.0;
    		}
    		else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
    		{
    			VectorClear (shadelight);

    			if ( currententity->flags & RF_SHELL_RED )
    			{
    				shadelight[0] = 1.0;
    				if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) )
    					shadelight[2] = 1.0;
    			}
    			else if ( currententity->flags & RF_SHELL_BLUE )
    			{
    				if ( currententity->flags & RF_SHELL_DOUBLE )
    				{
    					shadelight[1] = 1.0;
    					shadelight[2] = 1.0;
    				}
    				else
    				{
    					shadelight[2] = 1.0;
    				}
    			}
    			else if ( currententity->flags & RF_SHELL_DOUBLE )
    			{
    				shadelight[0] = 0.9;
    				shadelight[1] = 0.7;
    			}
    		}
    		else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) )
    		{
    			VectorClear (shadelight);
    			// PMM - new colors
    			if ( currententity->flags & RF_SHELL_HALF_DAM )
    			{
    				shadelight[0] = 0.56;
    				shadelight[1] = 0.59;
    				shadelight[2] = 0.45;
    			}
    			if ( currententity->flags & RF_SHELL_GREEN )
    			{
    				shadelight[1] = 1.0;
    			}
    		}
    	}
    			//PMM - ok, now flatten these down to range from 0 to 1.0.
    	//		max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2]));
    	//		if (max_shell_val > 0)
    	//		{
    	//			for (i=0; i<3; i++)
    	//			{
    	//				shadelight[i] = shadelight[i] / max_shell_val;
    	//			}
    	//		}
    	// pmm
    */
    else if ( currententity->flags & RF_FULLBRIGHT )
    {
        for (i=0 ; i<3 ; i++)
            shadelight[i] = 1.0;
    }
    else
    {
        R_LightPoint (currententity->origin, shadelight);

        // player lighting hack for communication back to server
        // big hack!
        if ( currententity->flags & RF_WEAPONMODEL )
        {
            // pick the greatest component, which should be the same
            // as the mono value returned by software
            if (shadelight[0] > shadelight[1])
            {
                if (shadelight[0] > shadelight[2])
                    r_lightlevel->value = 150*shadelight[0];
                else
                    r_lightlevel->value = 150*shadelight[2];
            }
            else
            {
                if (shadelight[1] > shadelight[2])
                    r_lightlevel->value = 150*shadelight[1];
                else
                    r_lightlevel->value = 150*shadelight[2];
            }

        }

        if ( gl_monolightmap->string[0] != '0' )
        {
            float s = shadelight[0];

            if ( s < shadelight[1] )
                s = shadelight[1];
            if ( s < shadelight[2] )
                s = shadelight[2];

            shadelight[0] = s;
            shadelight[1] = s;
            shadelight[2] = s;
        }
    }

    if ( currententity->flags & RF_MINLIGHT )
    {
        for (i=0 ; i<3 ; i++)
            if (shadelight[i] > 0.1)
                break;
        if (i == 3)
        {
            shadelight[0] = 0.1;
            shadelight[1] = 0.1;
            shadelight[2] = 0.1;
        }
    }

    if ( currententity->flags & RF_GLOW )
    {   // bonus items will pulse with time
        float	scale;
        float	min;

        scale = 0.1 * sin(r_newrefdef.time*7);
        for (i=0 ; i<3 ; i++)
        {
            min = shadelight[i] * 0.8;
            shadelight[i] += scale;
            if (shadelight[i] < min)
                shadelight[i] = min;
        }
    }

// =================
// PGM	ir goggles color override
    if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
    {
        shadelight[0] = 1.0;
        shadelight[1] = 0.0;
        shadelight[2] = 0.0;
    }
// PGM
// =================

    shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];

    an = currententity->angles[1]/180*M_PI;
    shadevector[0] = cos(-an);
    shadevector[1] = sin(-an);
    shadevector[2] = 1;
    VectorNormalize (shadevector);

    //
    // locate the proper data
    //

    c_alias_polys += paliashdr->num_tris;

    //
    // draw all the triangles
    //
    if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
        qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));

    if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
    {
        extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );

        qglMatrixMode( GL_PROJECTION );
        qglPushMatrix();
        qglLoadIdentity();
        qglScalef( -1, 1, 1 );
        MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height,  4,  4096);
        qglMatrixMode( GL_MODELVIEW );

        qglCullFace( GL_BACK );
    }

    qglPushMatrix ();
    e->angles[PITCH] = -e->angles[PITCH];				// sigh.
    e->angles[ROLL] = e->angles[ROLL] * R_RollMult();	// Knightmare- roll is backwards
    R_RotateForEntity (e, true);
    e->angles[PITCH] = -e->angles[PITCH];				// sigh.
    e->angles[ROLL] = e->angles[ROLL] * R_RollMult();	// Knightmare- roll is backwards

    // select skin
    if (currententity->skin)
        skin = currententity->skin;	// custom player skin
    else
    {
        if (currententity->skinnum >= MAX_MD2SKINS)
            skin = currentmodel->skins[0];
        else
        {
            skin = currentmodel->skins[currententity->skinnum];
            if (!skin)
                skin = currentmodel->skins[0];
        }
    }
    if (!skin)
        skin = r_notexture;	// fallback...
    GL_Bind(skin->texnum);

    // draw it

    qglShadeModel (GL_SMOOTH);

    GL_TexEnv( GL_MODULATE );
    if ( currententity->flags & RF_TRANSLUCENT )
    {
        qglEnable (GL_BLEND);
    }


    if ( (currententity->frame >= paliashdr->num_frames)
            || (currententity->frame < 0) )
    {
        ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n",
                       currentmodel->name, currententity->frame);
        currententity->frame = 0;
        currententity->oldframe = 0;
    }

    if ( (currententity->oldframe >= paliashdr->num_frames)
            || (currententity->oldframe < 0))
    {
        ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
                       currentmodel->name, currententity->oldframe);
        currententity->frame = 0;
        currententity->oldframe = 0;
    }

    if ( !r_lerpmodels->value )
        currententity->backlerp = 0;
    GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp);

    GL_TexEnv( GL_REPLACE );
    qglShadeModel (GL_FLAT);

    qglPopMatrix ();

//#if 1
    if (gl_showbbox->value)	// Knightmare- show bbox option
    {
        qglColor4f (1.0f, 1.0f, 1.0f, 1.0f);
        qglDisable( GL_CULL_FACE );
        qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
        qglDisable( GL_TEXTURE_2D );
        /*	qglBegin( GL_TRIANGLE_STRIP );
        	for ( i = 0; i < 8; i++ )
        	{
        		qglVertex3fv( bbox[i] );
        	}
        	qglEnd();*/
        qglBegin( GL_QUADS );

        qglVertex3fv( bbox[0] );
        qglVertex3fv( bbox[1] );
        qglVertex3fv( bbox[3] );
        qglVertex3fv( bbox[2] );

        qglVertex3fv( bbox[4] );
        qglVertex3fv( bbox[5] );
        qglVertex3fv( bbox[7] );
        qglVertex3fv( bbox[6] );

        qglVertex3fv( bbox[0] );
        qglVertex3fv( bbox[1] );
        qglVertex3fv( bbox[5] );
        qglVertex3fv( bbox[4] );

        qglVertex3fv( bbox[2] );
        qglVertex3fv( bbox[3] );
        qglVertex3fv( bbox[7] );
        qglVertex3fv( bbox[6] );

        qglEnd();

        qglEnable( GL_TEXTURE_2D );
        qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
        qglEnable( GL_CULL_FACE );
    }
//#endif

    if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
    {
        qglMatrixMode( GL_PROJECTION );
        qglPopMatrix();
        qglMatrixMode( GL_MODELVIEW );
        qglCullFace( GL_FRONT );
    }

    if ( currententity->flags & RF_TRANSLUCENT )
    {
        qglDisable (GL_BLEND);
    }

    if (currententity->flags & RF_DEPTHHACK)
        qglDepthRange (gldepthmin, gldepthmax);

    if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL)))
    {
        //	qglPushMatrix ();
        //	R_RotateForEntity (e, false);
        //	qglDisable (GL_TEXTURE_2D);
        //	qglEnable (GL_BLEND);
        //	qglColor4f (0, 0, 0, gl_shadowalpha->value); // was 0.5

        GL_DrawAliasShadow (e, paliashdr, currententity->frame );

        //	qglEnable (GL_TEXTURE_2D);
        //	qglDisable (GL_BLEND);
        //	qglPopMatrix ();
    }
    qglColor4f (1,1,1,1);
}
Exemple #2
0
/*
** GL_SetDefaultState
*/
void GL_SetDefaultState( void )
{
	glClearDepth( 1.0f );

	glCullFace( GL_FRONT );

	glColor4f( 1, 1, 1, 1 );

	// initialize downstream texture unit if we're running
	// in a multitexture environment
	if ( GLEW_ARB_multitexture )
	{
		GL_SelectTexture( 1 );
		GL_TextureMode( r_textureMode->string );
		GL_TextureAnisotropy( r_textureAnisotropy->value );
		GL_TexEnv( GL_MODULATE );
		glDisable( GL_TEXTURE_2D );
		GL_SelectTexture( 0 );
	}

	glEnable( GL_TEXTURE_2D );
	GL_TextureMode( r_textureMode->string );
	GL_TextureAnisotropy( r_textureAnisotropy->value );
	GL_TexEnv( GL_MODULATE );

	glShadeModel( GL_SMOOTH );
	glDepthFunc( GL_LEQUAL );

	// the vertex array is always enabled, but the color and texture
	// arrays are enabled and disabled around the compiled vertex array call
	glEnableClientState( GL_VERTEX_ARRAY );

	//
	// make sure our GL state vector is set correctly
	//
	glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE;

	glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
	glDepthMask( GL_TRUE );
	glDisable( GL_DEPTH_TEST );
	glEnable( GL_SCISSOR_TEST );
	glDisable( GL_CULL_FACE );
	glDisable( GL_BLEND );

//----(SA)  added.
#if 0

	// ATI pn_triangles
	if ( GLEW_ATI_pn_triangles )
	{
		int maxtess;

		// get max supported tesselation
		glGetIntegerv( GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI, ( GLint * ) &maxtess );
#ifdef __MACOS__
		glConfig.ATIMaxTruformTess = 7;
#else
		glConfig.ATIMaxTruformTess = maxtess;
#endif

		// cap if necessary
		if ( r_ati_truform_tess->value > maxtess )
		{
			ri.Cvar_Set( "r_ati_truform_tess", va( "%d", maxtess ) );
		}

		// set Wolf defaults
		glPNTrianglesfATI( GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, r_ati_truform_tess->value );
	}

#endif

	if ( glConfig.anisotropicAvailable )
	{
		float maxAnisotropy;

		glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy );
		glConfig.maxAnisotropy = maxAnisotropy;

		// set when rendering
//     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glConfig.maxAnisotropy);
	}

//----(SA)  end
}
Exemple #3
0
/*
 =============
 R_DrawScaledImage
 Psychospaz's code for drawing stretched crosshairs
 =============
 */
void R_DrawScaledImage (int32_t x, int32_t y, float scale, float alpha, image_t *gl)
{
    float	xoff, yoff;
    float	scale_x, scale_y;
    int32_t		i;
    vec2_t	texCoord[4], verts[4];
    
    if (scrap_dirty)
        Scrap_Upload ();
    
    // add alpha support
    if (gl->has_alpha || alpha < 1.0)
    {
        GL_Disable (GL_ALPHA_TEST);
        GL_TexEnv (GL_MODULATE);
        GL_Enable (GL_BLEND);
        GL_DepthMask (false);
    }
    
    GL_Bind (gl->texnum);
    
    scale_x = scale_y = scale;
    scale_x *= gl->replace_scale_w; // scale down if replacing a pcx image
    scale_y *= gl->replace_scale_h; // scale down if replacing a pcx image
    
    Vector2Set(texCoord[0], gl->sl, gl->tl);
    Vector2Set(texCoord[1], gl->sh, gl->tl);
    Vector2Set(texCoord[2], gl->sh, gl->th);
    Vector2Set(texCoord[3], gl->sl, gl->th);
    
    xoff = gl->width*scale_x-gl->width;
    yoff = gl->height*scale_y-gl->height;
    
    Vector2Set(verts[0], x, y);
    Vector2Set(verts[1], x+gl->width+xoff, y);
    Vector2Set(verts[2], x+gl->width+xoff, y+gl->height+yoff);
    Vector2Set(verts[3], x, y+gl->height+yoff);
    
    rb_vertex = rb_index = 0;
    indexArray[rb_index++] = rb_vertex+0;
    indexArray[rb_index++] = rb_vertex+1;
    indexArray[rb_index++] = rb_vertex+2;
    indexArray[rb_index++] = rb_vertex+0;
    indexArray[rb_index++] = rb_vertex+2;
    indexArray[rb_index++] = rb_vertex+3;
    for (i=0; i<4; i++) {
        VA_SetElem2(texCoordArray[0][rb_vertex], texCoord[i][0], texCoord[i][1]);
        VA_SetElem3(vertexArray[rb_vertex], verts[i][0], verts[i][1], 0);
        VA_SetElem4(colorArray[rb_vertex], 1.0, 1.0, 1.0, alpha);
        rb_vertex++;
    }
    RB_RenderMeshGeneric (false);
    
    if (gl->has_alpha || alpha < 1.0)
    {
        GL_DepthMask (true);
        GL_TexEnv (GL_REPLACE);
        GL_Disable (GL_BLEND);
        GL_Enable (GL_ALPHA_TEST); // add alpha support
    }
}
Exemple #4
0
void R_DrawCameraEffect (void)
{
	image_t			*image[2];
	int32_t				x, y, w, h, i, j;
	float			texparms[2][4];
	vec2_t			texCoord[4];
	vec3_t			verts[4];
	renderparms_t	cameraParms;

	image[0] = R_DrawFindPic ("/gfx/2d/screenstatic.tga");
	image[1] = R_DrawFindPic ("/gfx/2d/scanlines.tga");

	if (!image[0] || !image[1])
		return;

	x = y = 0; w = vid.width; h = vid.height;
	GL_Disable (GL_ALPHA_TEST);
	GL_TexEnv (GL_MODULATE);
	GL_Enable (GL_BLEND);
	GL_BlendFunc (GL_DST_COLOR, GL_SRC_COLOR);
	GL_DepthMask   (false);

	VectorSet(verts[0], x, y, 0);
	VectorSet(verts[1], x+w, y, 0);
	VectorSet(verts[2], x+w, y+h, 0);
	VectorSet(verts[3], x, y+h, 0);

	Vector4Set(texparms[0], 2, 2, -30, 10);
	Vector4Set(texparms[1], 1, 10, 0, 0);

	rb_vertex = rb_index = 0;
	indexArray[rb_index++] = rb_vertex+0;
	indexArray[rb_index++] = rb_vertex+1;
	indexArray[rb_index++] = rb_vertex+2;
	indexArray[rb_index++] = rb_vertex+0;
	indexArray[rb_index++] = rb_vertex+2;
	indexArray[rb_index++] = rb_vertex+3;
	rb_vertex = 4;

	for (i=0; i<2; i++)
	{
		GL_Bind (image[i]->texnum);
		Vector2Set(texCoord[0], x/image[i]->width, y/image[i]->height);
		Vector2Set(texCoord[1], (x+w)/image[i]->width, y/image[i]->height);
		Vector2Set(texCoord[2], (x+w)/image[i]->width, (y+h)/image[i]->height);
		Vector2Set(texCoord[3], x/image[i]->width, (y+h)/image[i]->height);
		Mod_SetRenderParmsDefaults (&cameraParms);
		cameraParms.scale_x = texparms[i][0];
		cameraParms.scale_y = texparms[i][1];
		cameraParms.scroll_x = texparms[i][2];
		cameraParms.scroll_y = texparms[i][3];
		RB_ModifyTextureCoords (&texCoord[0][0], &verts[0][0], 4, cameraParms);
		for (j=0; j<4; j++) {
			VA_SetElem2(texCoordArray[0][j], texCoord[j][0], texCoord[j][1]);
			VA_SetElem3(vertexArray[j], verts[j][0], verts[j][1], verts[j][2]);
			VA_SetElem4(colorArray[j], 1, 1, 1, 1);
		}
		RB_DrawArrays ();
	}
	rb_vertex = rb_index = 0;

	GL_DepthMask (true);
	GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	GL_Disable (GL_BLEND);
	GL_TexEnv (GL_REPLACE);
	GL_Enable (GL_ALPHA_TEST);
}
Exemple #5
0
static void ProjectDlightTexture( void ) {
	int		i, l;
	vec3_t	origin;
	float	*texCoords;
	byte	*colors;
	byte	clipBits[SHADER_MAX_VERTEXES];
	float	texCoordsArray[SHADER_MAX_VERTEXES][2];
	byte	colorArray[SHADER_MAX_VERTEXES][4];
	glIndex_t	hitIndexes[SHADER_MAX_INDEXES];
	int		numIndexes;
	float	scale;
	float	radius;
	int		fogging;
	vec3_t	floatColor;
	shaderStage_t *dStage;

	if ( !backEnd.refdef.num_dlights ) {
		return;
	}

	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) {
		dlight_t	*dl;

		if ( !( tess.dlightBits & ( 1 << l ) ) ) {
			continue;	// this surface definately doesn't have any of this light
		}

		texCoords = texCoordsArray[0];
		colors = colorArray[0];

		dl = &backEnd.refdef.dlights[l];
		VectorCopy( dl->transformed, origin );
		radius = dl->radius;
		scale = 1.0f / radius;

		floatColor[0] = dl->color[0] * 255.0f;
		floatColor[1] = dl->color[1] * 255.0f;
		floatColor[2] = dl->color[2] * 255.0f;

		for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) {
			vec3_t	dist;
			int		clip;
			float	modulate;

			backEnd.pc.c_dlightVertexes++;

			VectorSubtract( origin, tess.xyz[i], dist );

			int l = 1;
			int bestIndex = 0;
			float greatest = tess.normal[i][0];
			if (greatest < 0.0f)
			{
				greatest = -greatest;
			}

			if (VectorCompare(tess.normal[i], vec3_origin))
			{ //damn you terrain!
				bestIndex = 2;
			}
			else
			{
				while (l < 3)
				{
					if ((tess.normal[i][l] > greatest && tess.normal[i][l] > 0.0f) ||
						(tess.normal[i][l] < -greatest && tess.normal[i][l] < 0.0f))
					{
						greatest = tess.normal[i][l];
						if (greatest < 0.0f)
						{
							greatest = -greatest;
						}
						bestIndex = l;
					}
					l++;
				}
			}

			float dUse = 0.0f;
			const float maxScale = 1.5f;
			const float maxGroundScale = 1.4f;
			const float lightScaleTolerance = 0.1f;

			if (bestIndex == 2)
			{
				dUse = origin[2]-tess.xyz[i][2];
				if (dUse < 0.0f)
				{
					dUse = -dUse;
				}
				dUse = (radius*0.5f)/dUse;
				if (dUse > maxGroundScale)
				{
					dUse = maxGroundScale;
				}
				else if (dUse < 0.1f)
				{
					dUse = 0.1f;
				}

				if (VectorCompare(tess.normal[i], vec3_origin) ||
					tess.normal[i][0] > lightScaleTolerance ||
					tess.normal[i][0] < -lightScaleTolerance ||
					tess.normal[i][1] > lightScaleTolerance ||
					tess.normal[i][1] < -lightScaleTolerance)
				{ //if not perfectly flat, we must use a constant dist
					scale = 1.0f / radius;
				}
				else
				{
					scale = 1.0f / (radius*dUse);
				}

				texCoords[0] = 0.5f + dist[0] * scale;
				texCoords[1] = 0.5f + dist[1] * scale;
			}
			else if (bestIndex == 1)
			{
				dUse = origin[1]-tess.xyz[i][1];
				if (dUse < 0.0f)
				{
					dUse = -dUse;
				}
				dUse = (radius*0.5f)/dUse;
				if (dUse > maxScale)
				{
					dUse = maxScale;
				}
				else if (dUse < 0.1f)
				{
					dUse = 0.1f;
				}
				if (tess.normal[i][0] > lightScaleTolerance ||
					tess.normal[i][0] < -lightScaleTolerance ||
					tess.normal[i][2] > lightScaleTolerance ||
					tess.normal[i][2] < -lightScaleTolerance)
				{ //if not perfectly flat, we must use a constant dist
					scale = 1.0f / radius;
				}
				else
				{
					scale = 1.0f / (radius*dUse);
				}

				texCoords[0] = 0.5f + dist[0] * scale;
				texCoords[1] = 0.5f + dist[2] * scale;
			}
			else
			{
				dUse = origin[0]-tess.xyz[i][0];
				if (dUse < 0.0f)
				{
					dUse = -dUse;
				}
				dUse = (radius*0.5f)/dUse;
				if (dUse > maxScale)
				{
					dUse = maxScale;
				}
				else if (dUse < 0.1f)
				{
					dUse = 0.1f;
				}
				if (tess.normal[i][2] > lightScaleTolerance ||
					tess.normal[i][2] < -lightScaleTolerance ||
					tess.normal[i][1] > lightScaleTolerance ||
					tess.normal[i][1] < -lightScaleTolerance)
				{ //if not perfectly flat, we must use a constant dist
					scale = 1.0f / radius;
				}
				else
				{
					scale = 1.0f / (radius*dUse);
				}

				texCoords[0] = 0.5f + dist[1] * scale;
				texCoords[1] = 0.5f + dist[2] * scale;
			}

			clip = 0;
			if ( texCoords[0] < 0.0f ) {
				clip |= 1;
			} else if ( texCoords[0] > 1.0f ) {
				clip |= 2;
			}
			if ( texCoords[1] < 0.0f ) {
				clip |= 4;
			} else if ( texCoords[1] > 1.0f ) {
				clip |= 8;
			}
			// modulate the strength based on the height and color
			if ( dist[bestIndex] > radius ) {
				clip |= 16;
				modulate = 0.0f;
			} else if ( dist[bestIndex] < -radius ) {
				clip |= 32;
				modulate = 0.0f;
			} else {
				dist[bestIndex] = Q_fabs(dist[bestIndex]);
				if ( dist[bestIndex] < radius * 0.5f ) {
					modulate = 1.0f;
				} else {
					modulate = 2.0f * (radius - dist[bestIndex]) * scale;
				}
			}
			clipBits[i] = clip;

			colors[0] = Q_ftol(floatColor[0] * modulate);
			colors[1] = Q_ftol(floatColor[1] * modulate);
			colors[2] = Q_ftol(floatColor[2] * modulate);
			colors[3] = 255;
		}

		// build a list of triangles that need light
		numIndexes = 0;
		for ( i = 0 ; i < tess.numIndexes ; i += 3 ) {
			int		a, b, c;

			a = tess.indexes[i];
			b = tess.indexes[i+1];
			c = tess.indexes[i+2];
			if ( clipBits[a] & clipBits[b] & clipBits[c] ) {
				continue;	// not lighted
			}
			hitIndexes[numIndexes] = a;
			hitIndexes[numIndexes+1] = b;
			hitIndexes[numIndexes+2] = c;
			numIndexes += 3;
		}

		if ( !numIndexes ) {
			continue;
		}

		//don't have fog enabled when we redraw with alpha test, or it will double over
		//and screw the tri up -rww
		if (r_drawfog->value == 2 &&
			tr.world &&
			(tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs))
		{
			fogging = qglIsEnabled(GL_FOG);

			if (fogging)
			{
				qglDisable(GL_FOG);
			}
		}
		else
		{
			fogging = 0;
		}


		dStage = NULL;
		if (tess.shader && qglActiveTextureARB)
		{
			int i = 0;
			while (i < tess.shader->numUnfoggedPasses)
			{
				const int blendBits = (GLS_SRCBLEND_BITS+GLS_DSTBLEND_BITS);
				if (((tess.shader->stages[i].bundle[0].image && !tess.shader->stages[i].bundle[0].isLightmap && !tess.shader->stages[i].bundle[0].numTexMods) ||
					 (tess.shader->stages[i].bundle[1].image && !tess.shader->stages[i].bundle[1].isLightmap && !tess.shader->stages[i].bundle[1].numTexMods)) &&
					(tess.shader->stages[i].stateBits & blendBits) == 0 )
				{ //only use non-lightmap opaque stages
                    dStage = &tess.shader->stages[i];
					break;
				}
				i++;
			}
		}

		if (dStage)
		{
			GL_SelectTexture( 0 );
			GL_State(0);
			qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] );
			if (dStage->bundle[0].image && !dStage->bundle[0].isLightmap && !dStage->bundle[0].numTexMods)
			{
				R_BindAnimatedImage( &dStage->bundle[0] );
			}
			else
			{
				R_BindAnimatedImage( &dStage->bundle[1] );
			}

			GL_SelectTexture( 1 );
			qglEnable( GL_TEXTURE_2D );
			qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
			qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );
			qglEnableClientState( GL_COLOR_ARRAY );
			qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
			GL_Bind( tr.dlightImage );
			GL_TexEnv( GL_MODULATE );

			GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL);// | GLS_ATEST_GT_0);

			R_DrawElements( numIndexes, hitIndexes );

			qglDisable( GL_TEXTURE_2D );
			GL_SelectTexture(0);
		}
		else
		{
			qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
			qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );

			qglEnableClientState( GL_COLOR_ARRAY );
			qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );

			GL_Bind( tr.dlightImage );
			// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
			// where they aren't rendered
			if ( dl->additive ) {
				GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
			}
			else {
				GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
			}

			R_DrawElements( numIndexes, hitIndexes );
		}

		if (fogging)
		{
			qglEnable(GL_FOG);
		}

		backEnd.pc.c_totalIndexes += numIndexes;
		backEnd.pc.c_dlightIndexes += numIndexes;
	}
}
Exemple #6
0
/*
===================
DrawMultitextured

output = t0 * t1 or t0 + t1

t0 = most upstream according to spec
t1 = most downstream according to spec
===================
*/
static void DrawMultitextured(shaderCommands_t * input, int stage)
{
	shaderStage_t  *pStage;

	pStage = tess.xstages[stage];

	// Ridah
	if(tess.shader->noFog && pStage->isFogged)
	{
		R_FogOn();
	}
	else if(tess.shader->noFog && !pStage->isFogged)
	{
		R_FogOff();				// turn it back off
	}
	else
	{							// make sure it's on
		R_FogOn();
	}
	// done.

	GL_State(pStage->stateBits);

	// this is an ugly hack to work around a GeForce driver
	// bug with multitexture and clip planes
	if(backEnd.viewParms.isPortal)
	{
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	}

	//
	// base
	//
	GL_SelectTexture(0);
	glTexCoordPointer(2, GL_FLOAT, 0, input->svars.texcoords[0]);
	R_BindAnimatedImage(&pStage->bundle[0]);

	//
	// lightmap/secondary pass
	//
	GL_SelectTexture(1);
	glEnable(GL_TEXTURE_2D);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	if(r_lightmap->integer)
	{
		GL_TexEnv(GL_REPLACE);
	}
	else
	{
		GL_TexEnv(tess.shader->multitextureEnv);
	}

	glTexCoordPointer(2, GL_FLOAT, 0, input->svars.texcoords[1]);

	R_BindAnimatedImage(&pStage->bundle[1]);

	R_DrawElements(input->numIndexes, input->indexes);

	//
	// disable texturing on TEXTURE1, then select TEXTURE0
	//
	//glDisableClientState( GL_TEXTURE_COORD_ARRAY );
	glDisable(GL_TEXTURE_2D);

	GL_SelectTexture(0);
}
/*
=================
R_Bloom_GeneratexDiamonds
=================
*/
void R_Bloom_GeneratexDiamonds( refdef_t *fd )
{
    int			i, j;
    static float intensity;

    //set up sample size workspace
    qglViewport( 0, 0, sample_width, sample_height );
    qglMatrixMode( GL_PROJECTION );
    qglLoadIdentity ();
    qglOrtho(0, sample_width, sample_height, 0, -10, 100);
    qglMatrixMode( GL_MODELVIEW );
    qglLoadIdentity ();

    //copy small scene into r_bloomeffecttexture
    GL_Bind(r_bloomeffecttexture->texnum);
    qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);

    //start modifying the small scene corner
    qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
    GL_Enable(GL_BLEND);

    //Com_Printf("%d %d\n", r_bloom_darken->value, fd->bloomdarken);

    //darkening passes
    if( r_bloom_darken->value )
    {
        GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
        GL_TexEnv(GL_MODULATE);

        for(i=0; i< r_bloom_darken->value  ; i++) {
            R_Bloom_SamplePass( 0, 0 );
        }
        qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);
    }

    //bluring passes
    //GL_BlendFunc(GL_ONE, GL_ONE);
    GL_BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);



    if( r_bloom_diamond_size->value > 7 || r_bloom_diamond_size->value <= 3)
    {
        if( (int)r_bloom_diamond_size->value != 8 ) Cvar_SetValue( "r_bloom_diamond_size", 8 );

        for(i=0; i<r_bloom_diamond_size->value; i++) {
            for(j=0; j<r_bloom_diamond_size->value; j++) {
                intensity = /*bc mod*/(fd->bloomintensity +  r_bloom_intensity->value) * 0.3 * Diamond8x[i][j];
                if( intensity < r_bloom_threshold->value ) continue;
                qglColor4f( intensity, intensity, intensity, 1.0);
                R_Bloom_SamplePass( i-4, j-4 );
            }
        }
    } else if( r_bloom_diamond_size->value > 5 ) {

        if( r_bloom_diamond_size->value != 6 ) Cvar_SetValue( "r_bloom_diamond_size", 6 );

        for(i=0; i<r_bloom_diamond_size->value; i++) {
            for(j=0; j<r_bloom_diamond_size->value; j++) {
                intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.5 * Diamond6x[i][j];
                if( intensity < r_bloom_threshold->value ) continue;
                qglColor4f( intensity, intensity, intensity, 1.0);
                R_Bloom_SamplePass( i-3, j-3 );
            }
        }
    } else if( r_bloom_diamond_size->value > 3 ) {

        if( (int)r_bloom_diamond_size->value != 4 ) Cvar_SetValue( "r_bloom_diamond_size", 4 );

        for(i=0; i<r_bloom_diamond_size->value; i++) {
            for(j=0; j<r_bloom_diamond_size->value; j++) {
                intensity = /*bc mod*/(fd->bloomintensity + r_bloom_intensity->value) * 0.8f * Diamond4x[i][j];
                if( intensity < r_bloom_threshold->value ) continue;
                qglColor4f( intensity, intensity, intensity, 1.0);
                R_Bloom_SamplePass( i-2, j-2 );
            }
        }
    }

    qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);

    //restore full screen workspace
    qglViewport( 0, 0, vid.width, vid.height );
    qglMatrixMode( GL_PROJECTION );
    qglLoadIdentity ();
    qglOrtho(0, vid.width, vid.height, 0, -10, 100);
    qglMatrixMode( GL_MODELVIEW );
    qglLoadIdentity ();
}
Exemple #8
0
void RB_StageIteratorLightmappedMultitexture( void ) {
	shaderCommands_t *input;
	shader_t		*shader;

	input = &tess;
	shader = input->shader;

	//
	// log this call
	//
	if ( r_logFile->integer ) {
		// don't just call LogComment, or we will get
		// a call to va() every frame!
		GLimp_LogComment( va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name) );
	}

	//
	// set face culling appropriately
	//
	GL_Cull( shader->cullType );

	//
	// set color, pointers, and lock
	//
	GL_State( GLS_DEFAULT );
	qglVertexPointer( 3, GL_FLOAT, 16, input->xyz );

#ifdef REPLACE_MODE
	qglDisableClientState( GL_COLOR_ARRAY );
	qglColor3f( 1, 1, 1 );
	qglShadeModel( GL_FLAT );
#else
	qglEnableClientState( GL_COLOR_ARRAY );
	qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.constantColor255 );
#endif

	//
	// select base stage
	//
	GL_SelectTexture( 0 );

	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
	R_BindAnimatedImage( &tess.xstages[0]->bundle[0] );
	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][0] );

	//
	// configure second stage
	//
	GL_SelectTexture( 1 );
	qglEnable( GL_TEXTURE_2D );
	if ( r_lightmap->integer ) {
		GL_TexEnv( GL_REPLACE );
	} else {
		GL_TexEnv( GL_MODULATE );
	}
	R_BindAnimatedImage( &tess.xstages[0]->bundle[1] );
	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
	qglTexCoordPointer( 2, GL_FLOAT, 16, tess.texCoords[0][1] );

	//
	// lock arrays
	//
	if ( qglLockArraysEXT ) {
		qglLockArraysEXT(0, input->numVertexes);
		GLimp_LogComment( "glLockArraysEXT\n" );
	}

	R_DrawElements( input->numIndexes, input->indexes );

	//
	// disable texturing on TEXTURE1, then select TEXTURE0
	//
	qglDisable( GL_TEXTURE_2D );
	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );

	GL_SelectTexture( 0 );
#ifdef REPLACE_MODE
	GL_TexEnv( GL_MODULATE );
	qglShadeModel( GL_SMOOTH );
#endif

	// 
	// now do any dynamic lighting needed
	//
	if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE ) {
		ProjectDlightTexture();
	}

	//
	// now do fog
	//
	if ( tess.fogNum && tess.shader->fogPass ) {
		RB_FogPass();
	}

	//
	// unlock arrays
	//
	if ( qglUnlockArraysEXT ) {
		qglUnlockArraysEXT();
		GLimp_LogComment( "glUnlockArraysEXT\n" );
	}
}
Exemple #9
0
void
Draw_ScaledPic(int x, int y, float scale, float alpha, char *pic, float red, float green, float blue, qboolean fixcoords, qboolean repscale)
{
	float		xoff, yoff;
	image_t        *gl;

	gl = Draw_FindPic(pic);
	if (!gl) {
		ri.Con_Printf(PRINT_ALL, "Can't find pic: %s\n", pic);
		return;
	}
	if (scrap_dirty)
		Scrap_Upload();

	if (((gl_config.renderer == GL_RENDERER_MCD) || (gl_config.renderer & GL_RENDERER_RENDITION)) && !gl->has_alpha)
		qglDisable(GL_ALPHA_TEST);

	/* add alpha support */
	{
		qglDisable(GL_ALPHA_TEST);

		qglBindTexture(GL_TEXTURE_2D, gl->texnum);

		GL_TexEnv(GL_MODULATE);
		qglColor4f(red, green, blue, alpha);
		qglEnable(GL_BLEND);
		qglDepthMask(false);
	}

	/* NOTE: replace this with shaders as soon as they are supported */
	if (repscale)
		scale *= gl->replace_scale;	/* scale down if replacing a pcx image */

	if (fixcoords) {	/* Knightmare- whether to adjust coordinates for scaling */

		xoff = (gl->width * scale - gl->width) / 2;
		yoff = (gl->height * scale - gl->height) / 2;

		GL_Bind(gl->texnum);
		qglBegin(GL_QUADS);
		qglTexCoord2f(gl->sl, gl->tl);
		qglVertex2f(x - xoff, y - yoff);
		qglTexCoord2f(gl->sh, gl->tl);
		qglVertex2f(x + gl->width + xoff, y - yoff);
		qglTexCoord2f(gl->sh, gl->th);
		qglVertex2f(x + gl->width + xoff, y + gl->height + yoff);
		qglTexCoord2f(gl->sl, gl->th);
		qglVertex2f(x - xoff, y + gl->height + yoff);
		qglEnd();

	} else {
		xoff = gl->width * scale - gl->width;
		yoff = gl->height * scale - gl->height;

		GL_Bind(gl->texnum);
		qglBegin(GL_QUADS);
		qglTexCoord2f(gl->sl, gl->tl);
		qglVertex2f(x, y);
		qglTexCoord2f(gl->sh, gl->tl);
		qglVertex2f(x + gl->width + xoff, y);
		qglTexCoord2f(gl->sh, gl->th);
		qglVertex2f(x + gl->width + xoff, y + gl->height + yoff);
		qglTexCoord2f(gl->sl, gl->th);
		qglVertex2f(x, y + gl->height + yoff);
		qglEnd();
	}

	/* add alpha support */
	{
		qglDepthMask(true);
		GL_TexEnv(GL_REPLACE);
		qglDisable(GL_BLEND);
		qglColor4f(1, 1, 1, 1);

		qglEnable(GL_ALPHA_TEST);
	}

	if (((gl_config.renderer == GL_RENDERER_MCD) || (gl_config.renderer & GL_RENDERER_RENDITION)) && !gl->has_alpha)
		qglEnable(GL_ALPHA_TEST);
}
/*
=================
R_Bloom_GeneratexCross - alternative bluring method
=================
*/
void R_Bloom_GeneratexCross( void )
{
    int			i;
    static int		BLOOM_BLUR_RADIUS = 8;
    //static float	BLOOM_BLUR_INTENSITY = 2.5f;
    float	BLOOM_BLUR_INTENSITY;
    static float intensity;
    static float range;

    //set up sample size workspace
    qglViewport( 0, 0, sample_width, sample_height );
    qglMatrixMode( GL_PROJECTION );
    qglLoadIdentity ();
    qglOrtho(0, sample_width, sample_height, 0, -10, 100);
    qglMatrixMode( GL_MODELVIEW );
    qglLoadIdentity ();

    //copy small scene into r_bloomeffecttexture
    GL_Bind(0, r_bloomeffecttexture);
    qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);

    //start modifying the small scene corner
    qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
    GL_Enable(GL_BLEND);

    //darkening passes
    if( r_bloom_darken->value )
    {
        GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
        GL_TexEnv(GL_MODULATE);

        for(i=0; i<r_bloom_darken->value ; i++) {
            R_Bloom_SamplePass( 0, 0 );
        }
        qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);
    }

    //bluring passes
    if( BLOOM_BLUR_RADIUS ) {

        GL_BlendFunc(GL_ONE, GL_ONE);

        range = (float)BLOOM_BLUR_RADIUS;

        BLOOM_BLUR_INTENSITY = r_bloom_intensity->value;
        //diagonal-cross draw 4 passes to add initial smooth
        qglColor4f( 0.5f, 0.5f, 0.5f, 1.0);
        R_Bloom_SamplePass( 1, 1 );
        R_Bloom_SamplePass( -1, 1 );
        R_Bloom_SamplePass( -1, -1 );
        R_Bloom_SamplePass( 1, -1 );
        qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);

        for(i=-(BLOOM_BLUR_RADIUS+1); i<BLOOM_BLUR_RADIUS; i++) {
            intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range));
            if( intensity < 0.05f ) continue;
            qglColor4f( intensity, intensity, intensity, 1.0f);
            R_Bloom_SamplePass( i, 0 );
            //R_Bloom_SamplePass( -i, 0 );
        }

        qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);

        //for(i=0;i<BLOOM_BLUR_RADIUS;i++) {
        for(i=-(BLOOM_BLUR_RADIUS+1); i<BLOOM_BLUR_RADIUS; i++) {
            intensity = BLOOM_BLUR_INTENSITY/(range*2+1)*(1 - fabs(i*i)/(float)(range*range));
            if( intensity < 0.05f ) continue;
            qglColor4f( intensity, intensity, intensity, 1.0f);
            R_Bloom_SamplePass( 0, i );
            //R_Bloom_SamplePass( 0, -i );
        }

        qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height);
    }

    //restore full screen workspace
    qglViewport( 0, 0, glState.width, glState.height );
    qglMatrixMode( GL_PROJECTION );
    qglLoadIdentity ();
    qglOrtho(0, glState.width, glState.height, 0, -10, 100);
    qglMatrixMode( GL_MODELVIEW );
    qglLoadIdentity ();
}
Exemple #11
0
void R_DrawSkyBox (void)
{
#ifdef ENABLE_HYG_STARS
	R_DrawStars(); // jitstarviewer
#else
	int		i;

	if (fogenabled) // jitfog
		qgl.Disable(GL_FOG);

	if (skyrotate)
	{
		// check for no sky at all
		for (i = 0; i < 6; ++i)
		{
			if (skymins[0][i] < skymaxs[0][i] && skymins[1][i] < skymaxs[1][i])
				break;
		}

		if (i == 6)
			return;		// nothing visible
	}

	qgl.PushMatrix();
	qgl.Translatef(r_origin[0], r_origin[1], r_origin[2]);
	qgl.Rotatef(r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);

	if (fogenabled && sky_images[0] == r_whitetexture) // jitfog
	{
		qgl.Color3fv(fogcolor);
		GLSTATE_ENABLE_BLEND
		GL_TexEnv(GL_MODULATE);
	}

	for (i = 0; i < 6; ++i)
	{
		if (skyrotate)
		{
			// hack, forces full sky to draw when rotating
			skymins[0][i] = -1;
			skymins[1][i] = -1;
			skymaxs[0][i] = 1;
			skymaxs[1][i] = 1;
		}

		if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i])
			continue;

		GL_Bind(sky_images[skytexorder[i]]->texnum);

		qgl.Begin(GL_QUADS);
		MakeSkyVec(skymins[0][i], skymins[1][i], i);
		MakeSkyVec(skymins[0][i], skymaxs[1][i], i);
		MakeSkyVec(skymaxs[0][i], skymaxs[1][i], i);
		MakeSkyVec(skymaxs[0][i], skymins[1][i], i);
		qgl.End();
	}

	qgl.PopMatrix();

	if (fogenabled) // jitfog
	{
		qgl.Color3f(1, 1, 1);
		GLSTATE_DISABLE_BLEND
		qgl.Enable(GL_FOG);
	}
#endif
}
Exemple #12
0
// MPO : this is my version...
void EmitWaterPolys (msurface_t *fa)
{
	//==============================
	glpoly_t	*p;
	glpoly_t	*bp;
	float		*v;
	int			i;
	float		s;
	float		t;
	float		os;
	float		ot;
	float		scroll;
	float		rdt = r_newrefdef.time;
	float		zValue = 0.0;			// height of water
	qboolean	waterNotFlat = false;
	qboolean	flowing;
	//==============================

	if (g_drawing_refl)
		return;	// we don't want any water drawn while we are doing our reflection

	if (fa->texinfo->flags & SURF_FLOWING)
	{
		scroll = -64.0f * ((r_newrefdef.time * 0.5f) - (int)(r_newrefdef.time * 0.5f));
		flowing = true;
	}
	else
	{
		scroll = 0.0f;
		flowing = false;
	}

	// skip the water texture on transparent surfaces
	if (r_reflectivewater->value && (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)))
	{
		for (bp = fa->polys; bp; bp = bp->next)
		{
			p = bp;

			for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE)
			{
				// if it hasn't been initalized before
				if (zValue == 0.0f)
					zValue = v[2];

				// Make sure polygons are on the same plane
				// Fix for not perfectly flat water on base1 - strange ..
				else if (fabs(zValue - v[2]) > 8.0f)
					waterNotFlat = true;
			}
		}
	}

	if (waterNotFlat || !r_reflectivewater->value || !(fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)))
	{
		for (bp = fa->polys; bp; bp = bp->next)
		{
			p = bp;
			qgl.Begin(GL_TRIANGLE_FAN);
			c_brush_polys += p->numverts / 3; // jitrspeeds

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

				#if !id386
				s = os + r_turbsin[(int)((ot * 0.125f + r_newrefdef.time) * TURBSCALE) & 255];
				#else
				s = os + r_turbsin[Q_ftol(((ot * 0.125f + rdt) * TURBSCALE)) & 255];
				#endif

				s += scroll;
				s *= 0.015625f; // 1/64

				#if !id386
				t = ot + r_turbsin[(int)((os * 0.125f + rdt) * TURBSCALE) & 255];
				#else
				t = ot + r_turbsin[Q_ftol(((os * 0.125f + rdt) * TURBSCALE)) & 255];
				#endif
				t *= 0.015625f; // 1/64

				// if it hasn't been initalized before
				if (zValue == 0.0f)
					zValue = v[2];

				// Make sure polygons are on the same plane
				// Fix for not perfectly flat water on base1 - strange ..
				else if (fabs(zValue - v[2]) > 0.1f)
					waterNotFlat = true;

				qgl.TexCoord2f(s, t);
				qgl.Vertex3f(v[0], v[1], v[2]);
			}

			qgl.End();
		}
	}

	if (waterNotFlat)
		return;

	if (r_reflectivewater->value)
	{
#if 0
		//====================
		vec3_t	distanceVector;
		float	distance;
		//====================
#endif

		v = p->verts[0];
#if 0
		VectorSubtract(v, r_newrefdef.vieworg, distanceVector);
		distance = VectorLength(distanceVector);
		//R_add_refl(zValue, distance);
#endif
		R_add_refl(v[0], v[1], zValue);
		g_refl_enabled = true;
	}

	// find out which reflection we have that corresponds to the surface that we're drawing
	for (g_active_refl = 0; g_active_refl < g_num_refl; g_active_refl++)
	{
		// if we find which reflection to bind
		if (fabs(g_refl_Z[g_active_refl] - zValue) < 8.0f)
		{
			// === jitwater
			if (gl_state.fragment_program)
			{
				qgl.Enable(GL_VERTEX_PROGRAM_ARB);
				qgl.BindProgramARB(GL_VERTEX_PROGRAM_ARB, g_water_vertex_program_id);
				qgl.Enable(GL_FRAGMENT_PROGRAM_ARB);
				qgl.BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, g_water_fragment_program_id);

				GL_MBind(QGL_TEXTURE1, distort_tex->texnum);      // Distortion texture
				GL_MBind(QGL_TEXTURE2, water_normal_tex->texnum); // Normal texture
			}

			GL_MBind(QGL_TEXTURE0, g_refl_images[g_active_refl]->texnum); // Reflection texture
			// jitwater ===

			break;
		}
	}

	// if we found a reflective surface correctly, then go ahead and draw it
	if (g_active_refl != g_num_refl)
	{
		qgl.Color4f(1.0f, 1.0f, 1.0f, 1.0f);

		if (!gl_state.blend)
			qgl.Enable(GL_BLEND);

		GL_TexEnv(GL_MODULATE);
		qgl.ShadeModel(GL_SMOOTH);

		if (gl_state.fragment_program)
		{
			float w, h;
			R_GetReflTexScale(&w, &h); // Probably unnecessary
			qgl.ProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0,
				w, h, rs_realtime * (flowing ? -0.3f : 0.2f), rs_realtime * -0.2f);
			qgl.ProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 1,
				r_newrefdef.vieworg[0], r_newrefdef.vieworg[1], r_newrefdef.vieworg[2], 1.0f);
		}
		else
		{
			// Put UV coords in screen space for rendering the reflection texture.  Only need to do this when fragment programs are disabled.  It's handled in the vertex shader otherwise.
			R_LoadReflMatrix();
		}

  		// draw reflected water layer on top of regular
  		for (bp = fa->polys; bp; bp = bp->next)
  		{
			p = bp;
			qgl.Begin(GL_TRIANGLE_FAN);
			c_brush_polys += p->numverts / 3; // jitrspeeds

			for (i = 0, v = p->verts[0]; i < p->numverts; ++i, v += VERTEXSIZE)
			{
				if (gl_state.fragment_program)
				{
					qgl.MultiTexCoord3fvARB(QGL_TEXTURE0, v); // Used for world space
					qgl.MultiTexCoord3fvARB(QGL_TEXTURE1, v + 3); // Actual texture UV's.
				}
				else
				{
					vec3_t	vAngle;

					qgl.TexCoord3f(v[0], v[1] + CalcWave(v[0], v[1]), v[2]);

					if (r_newrefdef.rdflags & RDF_UNDERWATER)
					{
						VectorSubtract(v, r_newrefdef.vieworg, vAngle);
						VectorNormalize(vAngle);

						if (vAngle[2] > 0.55f)
							vAngle[2] = 0.55f;

						qgl.Color4f(1.0f, 1.0f, 1.0f, 0.9f - (vAngle[2] * 1.0f));
					}
					else
					{
						VectorSubtract(r_newrefdef.vieworg, v, vAngle);
						VectorNormalize(vAngle);

						if (vAngle[2] > 0.55f)
							vAngle[2] = 0.55f;

						qgl.Color4f(1.0f, 1.0f, 1.0f, 0.9f - (vAngle[2] * 1.0f));
					}
				}

				qgl.Vertex3f(v[0], v[1], v[2]);
			}

			qgl.End();
  		}

		R_ClearReflMatrix();

		if (!gl_state.blend)
			qgl.Disable(GL_BLEND);

		if (gl_state.fragment_program) // jitwater
		{
			qgl.Disable(GL_FRAGMENT_PROGRAM_ARB);
			qgl.Disable(GL_VERTEX_PROGRAM_ARB);
		}
    }
}
Exemple #13
0
/*
 =============
 R_DrawScaledImage
 Psychospaz's code for drawing stretched crosshairs
 =============
 */
void R_DrawScaledImage (int32_t x, int32_t y, float scale, float alpha, image_t *gl)
{
    float	xoff, yoff;
    float	scale_x, scale_y;

    const vec4_t color[4] = {
        {1.0, 1.0, 1.0, alpha},
        {1.0, 1.0, 1.0, alpha},
        {1.0, 1.0, 1.0, alpha},
        {1.0, 1.0, 1.0, alpha}
    };

    if (scrap_dirty)
        Scrap_Upload ();

    // add alpha support
    if (gl->has_alpha || alpha < 1.0)
    {
        GL_Disable (GL_ALPHA_TEST);
        GL_TexEnv (GL_MODULATE);
        GL_Enable (GL_BLEND);
        GL_DepthMask (false);
    }

    GL_Bind (gl->texnum);

    scale_x = scale_y = scale;
    scale_x *= gl->replace_scale_w; // scale down if replacing a pcx image
    scale_y *= gl->replace_scale_h; // scale down if replacing a pcx image


    xoff = gl->width*scale_x-gl->width;
    yoff = gl->height*scale_y-gl->height;

    rb_vertex = rb_index = 0;

    memcpy(indexArray, indices, sizeof(indices));
    rb_index = 6;

    VA_SetElem2(texCoordArray[0][0], gl->sl, gl->tl);
    VA_SetElem2(texCoordArray[0][1], gl->sh, gl->tl);
    VA_SetElem2(texCoordArray[0][2], gl->sh, gl->th);
    VA_SetElem2(texCoordArray[0][3], gl->sl, gl->th);


    VA_SetElem3(vertexArray[0], x, y, 0);
    VA_SetElem3(vertexArray[1], x+gl->width+xoff, y, 0);
    VA_SetElem3(vertexArray[2], x+gl->width+xoff, y+gl->height+yoff, 0);
    VA_SetElem3(vertexArray[3], x, y+gl->height+yoff, 0);

    memcpy(colorArray, color, sizeof(vec4_t) * 4);

    rb_vertex = 4;


    RB_RenderMeshGeneric (false);

    if (gl->has_alpha || alpha < 1.0)
    {
        GL_DepthMask (true);
        GL_TexEnv (GL_REPLACE);
        GL_Disable (GL_BLEND);
        GL_Enable (GL_ALPHA_TEST); // add alpha support
    }
}
Exemple #14
0
void R_DrawSkyBox (void)
{
	int		i;

#if 0
qglEnable (GL_BLEND);
GL_TexEnv( GL_MODULATE );
qglColor4f (1,1,1,0.5);
qglDisable (GL_DEPTH_TEST);
#endif

	// jkrige - skybox
	qglDisable (GL_DEPTH_TEST);
	/*if (skyrotate)
	{	// check for no sky at all
		for (i=0 ; i<6 ; i++)
			if (skymins[0][i] < skymaxs[0][i]
			&& skymins[1][i] < skymaxs[1][i])
				break;
		if (i == 6)
			return;		// nothing visible
	}*/
	// jkrige - skybox

qglPushMatrix ();
qglTranslatef (r_origin[0], r_origin[1], r_origin[2]);
qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);

	for (i=0 ; i<6 ; i++)
	{
		// jkrige - skybox
		/*if (skyrotate)
		{	// hack, forces full sky to draw when rotating
			skymins[0][i] = -1;
			skymins[1][i] = -1;
			skymaxs[0][i] = 1;
			skymaxs[1][i] = 1;
		}

		if (skymins[0][i] >= skymaxs[0][i]
		|| skymins[1][i] >= skymaxs[1][i])
			continue;*/
		// jkrige - skybox

		GL_Bind (sky_images[skytexorder[i]]->texnum);

		qglBegin (GL_QUADS);
		// jkrige - skybox
		MakeSkyVec (-1, -1, i);
		MakeSkyVec (-1, 1, i);
		MakeSkyVec (1, 1, i);
		MakeSkyVec (1, -1, i);
		//MakeSkyVec (skymins[0][i], skymins[1][i], i);
		//MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
		//MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
		//MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
		// jkrige - skybox
		qglEnd ();
	}
qglPopMatrix ();
#if 0
glDisable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,0.5);
glEnable (GL_DEPTH_TEST);
#endif

	// jkrige - skybox
	qglEnable (GL_DEPTH_TEST);
	// jkrige - skybox
}
void R_BloomBlend ( refdef_t *fd )
{
    if( !(fd->rdflags & RDF_BLOOM) || !r_bloom->value || r_showtris->value )
        return;

    if( !BLOOM_SIZE )
        R_Bloom_InitTextures();

    if( screen_texture_width < BLOOM_SIZE ||
            screen_texture_height < BLOOM_SIZE )
        return;

    //set up full screen workspace
    qglViewport ( 0, 0, vid.width, vid.height );
    GL_TexEnv (GL_REPLACE); // Knightmare added
    GL_Disable (GL_DEPTH_TEST);
    qglMatrixMode (GL_PROJECTION);
    qglLoadIdentity ();
    qglOrtho(0, vid.width, vid.height, 0, -10, 100);
    qglMatrixMode (GL_MODELVIEW);
    qglLoadIdentity ();
    GL_Disable (GL_CULL_FACE);

    GL_Disable (GL_BLEND);
    qglEnable (GL_TEXTURE_2D);

    qglColor4f (1, 1, 1, 1);

    //set up current sizes
    curView_x = fd->x;
    curView_y = fd->y;
    curView_width = fd->width;
    curView_height = fd->height;
    screenText_tcw = ((float)fd->width / (float)screen_texture_width);
    screenText_tch = ((float)fd->height / (float)screen_texture_height);
    if( fd->height > fd->width ) {
        sampleText_tcw = ((float)fd->width / (float)fd->height);
        sampleText_tch = 1.0f;
    } else {
        sampleText_tcw = 1.0f;
        sampleText_tch = ((float)fd->height / (float)fd->width);
    }
    sample_width = BLOOM_SIZE * sampleText_tcw;
    sample_height = BLOOM_SIZE * sampleText_tch;

    //copy the screen space we'll use to work into the backup texture
    GL_Bind(r_bloombackuptexture->texnum);
    qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_size * sampleText_tcw, r_screenbackuptexture_size * sampleText_tch);

    //create the bloom image
    R_Bloom_DownsampleView();
    R_Bloom_GeneratexDiamonds( fd );
    //R_Bloom_GeneratexCross();

    //restore the screen-backup to the screen
    GL_Disable(GL_BLEND);
    GL_Bind(r_bloombackuptexture->texnum);
    qglColor4f( 1, 1, 1, 1 );
    R_Bloom_Quad( 0,
                  vid.height - (r_screenbackuptexture_size * sampleText_tch),
                  r_screenbackuptexture_size * sampleText_tcw,
                  r_screenbackuptexture_size * sampleText_tch,
                  sampleText_tcw,
                  sampleText_tch );

    R_Bloom_DrawEffect( fd );

    // Knightmare added
    R_SetupGL ();
    GL_BlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    qglEnable (GL_TEXTURE_2D);
    qglColor4f(1,1,1,1);
}
/*
==================
RB_ARB_DrawInteraction

backEnd.vLight

backEnd.depthFunc must be equal for alpha tested surfaces to work right,
it is set to lessThan for blended transparent surfaces

==================
*/
static void RB_ARB_DrawInteraction(const drawInteraction_t *din)
{
	const drawSurf_t *surf = din->surf;
	const srfTriangles_t	*tri = din->surf->geo;

	// set the vertex arrays, which may not all be enabled on a given pass
	idDrawVert *ac = (idDrawVert *)vertexCache.Position(tri->ambientCache);
	qglVertexPointer(3, GL_FLOAT, sizeof(idDrawVert), ac->xyz.ToFloatPtr());
	GL_SelectTexture(0);
	qglTexCoordPointer(2, GL_FLOAT, sizeof(idDrawVert), (void *)&ac->st);

	//-----------------------------------------------------
	//
	// bump / falloff
	//
	//-----------------------------------------------------
	// render light falloff * bumpmap lighting

	//
	// draw light falloff to the alpha channel
	//
	GL_State(GLS_COLORMASK | GLS_DEPTHMASK | backEnd.depthFunc);

	qglColor3f(1, 1, 1);
	qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
	qglEnable(GL_TEXTURE_GEN_S);
	qglTexGenfv(GL_S, GL_OBJECT_PLANE, din->lightProjection[3].ToFloatPtr());
	qglTexCoord2f(0, 0.5);

// ATI R100 can't do partial texgens
#define	NO_MIXED_TEXGEN

#ifdef NO_MIXED_TEXGEN
	idVec4	plane;
	plane[0] = 0;
	plane[1] = 0;
	plane[2] = 0;
	plane[3] = 0.5;
	qglEnable(GL_TEXTURE_GEN_T);
	qglTexGenfv(GL_T, GL_OBJECT_PLANE, plane.ToFloatPtr());

	plane[0] = 0;
	plane[1] = 0;
	plane[2] = 0;
	plane[3] = 1;
	qglEnable(GL_TEXTURE_GEN_Q);
	qglTexGenfv(GL_Q, GL_OBJECT_PLANE, plane.ToFloatPtr());

#endif

	din->lightFalloffImage->Bind();

	// draw it
	RB_DrawElementsWithCounters(tri);

	qglDisable(GL_TEXTURE_GEN_S);
#ifdef NO_MIXED_TEXGEN
	qglDisable(GL_TEXTURE_GEN_T);
	qglDisable(GL_TEXTURE_GEN_Q);
#endif

#if 0
	GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK
	         | backEnd.depthFunc);
// the texccords are the non-normalized vector towards the light origin
	GL_SelectTexture(0);
	globalImages->normalCubeMapImage->Bind();
	qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	qglTexCoordPointer(3, GL_FLOAT, sizeof(lightingCache_t), ((lightingCache_t *)vertexCache.Position(tri->lightingCache))->localLightVector.ToFloatPtr());
// draw it
	RB_DrawElementsWithCounters(tri);
	return;
#endif

	// we can't do bump mapping with standard calls, so skip it
	if (glConfig.envDot3Available && glConfig.cubeMapAvailable) {
		//
		// draw the bump map result onto the alpha channel
		//
		GL_State(GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ZERO | GLS_COLORMASK | GLS_DEPTHMASK
		         | backEnd.depthFunc);

		// texture 0 will be the per-surface bump map
		GL_SelectTexture(0);
		qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
//	FIXME: matrix work!	RB_BindStageTexture( surfaceRegs, &surfaceStage->texture, surf );
		din->bumpImage->Bind();

		// texture 1 is the normalization cube map
		// the texccords are the non-normalized vector towards the light origin
		GL_SelectTexture(1);

		if (din->ambientLight) {
			globalImages->ambientNormalMap->Bind();	// fixed value
		} else {
			globalImages->normalCubeMapImage->Bind();
		}

		qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
		qglTexCoordPointer(3, GL_FLOAT, sizeof(lightingCache_t), ((lightingCache_t *)vertexCache.Position(tri->lightingCache))->localLightVector.ToFloatPtr());

		// I just want alpha = Dot( texture0, texture1 )
		GL_TexEnv(GL_COMBINE_ARB);

		qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB);
		qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
		qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
		qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
		qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
		qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);
		qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1);

		// draw it
		RB_DrawElementsWithCounters(tri);

		GL_TexEnv(GL_MODULATE);

		globalImages->BindNull();
		qglDisableClientState(GL_TEXTURE_COORD_ARRAY);

		GL_SelectTexture(0);
//		RB_FinishStageTexture( &surfaceStage->texture, surf );
	}

	//-----------------------------------------------------
	//
	// projected light / surface color for diffuse maps
	//
	//-----------------------------------------------------
	// don't trash alpha
	GL_State(GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ONE | GLS_ALPHAMASK | GLS_DEPTHMASK
	         | backEnd.depthFunc);

	// texture 0 will get the surface color texture
	GL_SelectTexture(0);

	// select the vertex color source
	if (din->vertexColor == SVC_IGNORE) {
		qglColor4fv(din->diffuseColor.ToFloatPtr());
	} else {
		// FIXME: does this not get diffuseColor blended in?
		qglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(idDrawVert), (void *)&ac->color);
		qglEnableClientState(GL_COLOR_ARRAY);

		if (din->vertexColor == SVC_INVERSE_MODULATE) {
			GL_TexEnv(GL_COMBINE_ARB);
			qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
			qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
			qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
			qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
			qglTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
			qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1);
		}
	}

	qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	// FIXME: does this not get the texture matrix?
//	RB_BindStageTexture( surfaceRegs, &surfaceStage->texture, surf );
	din->diffuseImage->Bind();

	// texture 1 will get the light projected texture
	GL_SelectTexture(1);
	qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
	qglEnable(GL_TEXTURE_GEN_S);
	qglEnable(GL_TEXTURE_GEN_T);
	qglEnable(GL_TEXTURE_GEN_Q);
	qglTexGenfv(GL_S, GL_OBJECT_PLANE, din->lightProjection[0].ToFloatPtr());
	qglTexGenfv(GL_T, GL_OBJECT_PLANE, din->lightProjection[1].ToFloatPtr());
	qglTexGenfv(GL_Q, GL_OBJECT_PLANE, din->lightProjection[2].ToFloatPtr());

	din->lightImage->Bind();

	// draw it
	RB_DrawElementsWithCounters(tri);

	qglDisable(GL_TEXTURE_GEN_S);
	qglDisable(GL_TEXTURE_GEN_T);
	qglDisable(GL_TEXTURE_GEN_Q);

	globalImages->BindNull();
	GL_SelectTexture(0);

	if (din->vertexColor != SVC_IGNORE) {
		qglDisableClientState(GL_COLOR_ARRAY);
		GL_TexEnv(GL_MODULATE);
	}

//	RB_FinishStageTexture( &surfaceStage->texture, surf );
}
Exemple #17
0
/*
===================
RB_StageIteratorLightmappedMultitexture
===================
*/
void RB_StageIteratorLightmappedMultitexture(void)
{
	shaderCommands_t *input  = &tess;
	shader_t         *shader = input->shader;

	// log this call
	if (r_logFile->integer)
	{
		// don't just call LogComment, or we will get
		// a call to va() every frame!
		GLimp_LogComment(va("--- RB_StageIteratorLightmappedMultitexture( %s ) ---\n", tess.shader->name));
	}

	// set GL fog
	SetIteratorFog();

	// set face culling appropriately
	GL_Cull(shader->cullType);

	// set color, pointers, and lock
	GL_State(GLS_DEFAULT);
	qglVertexPointer(3, GL_FLOAT, 16, input->xyz);

#ifdef REPLACE_MODE
	qglDisableClientState(GL_COLOR_ARRAY);
	qglColor3f(1, 1, 1);
	qglShadeModel(GL_FLAT);
#else
	qglEnableClientState(GL_COLOR_ARRAY);
	qglColorPointer(4, GL_UNSIGNED_BYTE, 0, tess.constantColor255);
#endif

	// select base stage
	GL_SelectTexture(0);

	qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	R_BindAnimatedImage(&tess.xstages[0]->bundle[0]);
	qglTexCoordPointer(2, GL_FLOAT, 8, tess.texCoords0);

	// configure second stage
	GL_SelectTexture(1);
	qglEnable(GL_TEXTURE_2D);
	if (r_lightmap->integer)
	{
		GL_TexEnv(GL_REPLACE);
	}
	else
	{
		GL_TexEnv(GL_MODULATE);
	}

	// modified for snooper
	if (tess.xstages[0]->bundle[1].isLightmap && (backEnd.refdef.rdflags & RDF_SNOOPERVIEW))
	{
		GL_Bind(tr.whiteImage);
	}
	else
	{
		R_BindAnimatedImage(&tess.xstages[0]->bundle[1]);
	}

	qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	qglTexCoordPointer(2, GL_FLOAT, 8, tess.texCoords1);

	// lock arrays
	if (qglLockArraysEXT)
	{
		qglLockArraysEXT(0, input->numVertexes);
		GLimp_LogComment("glLockArraysEXT\n");
	}

	R_DrawElements(input->numIndexes, input->indexes);

	// disable texturing on TEXTURE1, then select TEXTURE0
	qglDisable(GL_TEXTURE_2D);
	qglDisableClientState(GL_TEXTURE_COORD_ARRAY);

	GL_SelectTexture(0);
#ifdef REPLACE_MODE
	GL_TexEnv(GL_MODULATE);
	qglShadeModel(GL_SMOOTH);
#endif

	// now do any dynamic lighting needed
	//if ( tess.dlightBits && tess.shader->sort <= SS_OPAQUE )
	if (tess.dlightBits && tess.shader->fogPass &&
	    !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY)))
	{
		if (r_dynamiclight->integer == 2)
		{
			DynamicLightPass();
		}
		else
		{
			DynamicLightSinglePass();
		}
	}

	// now do fog
	if (tess.fogNum && tess.shader->fogPass)
	{
		RB_FogPass();
	}

	// unlock arrays
	if (qglUnlockArraysEXT)
	{
		qglUnlockArraysEXT();
		GLimp_LogComment("glUnlockArraysEXT\n");
	}
}
Exemple #18
0
/*
===================
ProjectDlightTexture

Perform dynamic lighting with another rendering pass
===================
*/
static void ProjectDlightTexture2( void ) {
	int		i, l;
	vec3_t	origin;
	byte	clipBits[SHADER_MAX_VERTEXES];
	float	texCoordsArray[SHADER_MAX_VERTEXES][2];
	float	oldTexCoordsArray[SHADER_MAX_VERTEXES][2];
	float	vertCoordsArray[SHADER_MAX_VERTEXES][4];
	unsigned int		colorArray[SHADER_MAX_VERTEXES];
	glIndex_t	hitIndexes[SHADER_MAX_INDEXES];
	int		numIndexes;
	float	radius;
	int		fogging;
	shaderStage_t *dStage;
	vec3_t	posa;
	vec3_t	posb;
	vec3_t	posc;
	vec3_t	dist;
	vec3_t	e1;
	vec3_t	e2;
	vec3_t	normal;
	float	fac,modulate;
	vec3_t	floatColor;
	byte colorTemp[4];

	int		needResetVerts=0;

	if ( !backEnd.refdef.num_dlights )
	{
		return;
	}

	for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ )
	{
		dlight_t	*dl;

		if ( !( tess.dlightBits & ( 1 << l ) ) ) {
			continue;	// this surface definately doesn't have any of this light
		}

		dl = &backEnd.refdef.dlights[l];
		VectorCopy( dl->transformed, origin );
		radius = dl->radius;

		int		clipall = 63;
		for ( i = 0 ; i < tess.numVertexes ; i++)
		{
			int		clip;
			VectorSubtract( origin, tess.xyz[i], dist );

			clip = 0;
			if (  dist[0] < -radius )
			{
				clip |= 1;
			}
			else if ( dist[0] > radius )
			{
				clip |= 2;
			}
			if (  dist[1] < -radius )
			{
				clip |= 4;
			}
			else if ( dist[1] > radius )
			{
				clip |= 8;
			}
			if (  dist[2] < -radius )
			{
				clip |= 16;
			}
			else if ( dist[2] > radius )
			{
				clip |= 32;
			}

			clipBits[i] = clip;
			clipall &= clip;
		}
		if ( clipall )
		{
			continue;	// this surface doesn't have any of this light
		}
		floatColor[0] = dl->color[0] * 255.0f;
		floatColor[1] = dl->color[1] * 255.0f;
		floatColor[2] = dl->color[2] * 255.0f;

		// build a list of triangles that need light
		numIndexes = 0;
		for ( i = 0 ; i < tess.numIndexes ; i += 3 )
		{
			int		a, b, c;

			a = tess.indexes[i];
			b = tess.indexes[i+1];
			c = tess.indexes[i+2];
			if ( clipBits[a] & clipBits[b] & clipBits[c] )
			{
				continue;	// not lighted
			}

			// copy the vertex positions
			VectorCopy(tess.xyz[a],posa);
			VectorCopy(tess.xyz[b],posb);
			VectorCopy(tess.xyz[c],posc);

			VectorSubtract( posa, posb,e1);
			VectorSubtract( posc, posb,e2);
			CrossProduct(e1,e2,normal);
// rjr - removed for hacking 			if ( (!r_dlightBacks->integer && DotProduct(normal,origin)-DotProduct(normal,posa) <= 0.0f) || // backface
			if ( DotProduct(normal,origin)-DotProduct(normal,posa) <= 0.0f || // backface
				DotProduct(normal,normal) < 1E-8f) // junk triangle
			{
				continue;
			}
			VectorNormalize(normal);
			fac=DotProduct(normal,origin)-DotProduct(normal,posa);
			if (fac >= radius)  // out of range
			{
				continue;
			}
			modulate = 1.0f-((fac*fac) / (radius*radius));
			fac = 0.5f/sqrtf(radius*radius - fac*fac);

			// save the verts
			VectorCopy(posa,vertCoordsArray[numIndexes]);
			VectorCopy(posb,vertCoordsArray[numIndexes+1]);
			VectorCopy(posc,vertCoordsArray[numIndexes+2]);

			// now we need e1 and e2 to be an orthonormal basis
			if (DotProduct(e1,e1) > DotProduct(e2,e2))
			{
				VectorNormalize(e1);
				CrossProduct(e1,normal,e2);
			}
			else
			{
				VectorNormalize(e2);
				CrossProduct(normal,e2,e1);
			}
			VectorScale(e1,fac,e1);
			VectorScale(e2,fac,e2);

			VectorSubtract( posa, origin,dist);
			texCoordsArray[numIndexes][0]=DotProduct(dist,e1)+0.5f;
			texCoordsArray[numIndexes][1]=DotProduct(dist,e2)+0.5f;

			VectorSubtract( posb, origin,dist);
			texCoordsArray[numIndexes+1][0]=DotProduct(dist,e1)+0.5f;
			texCoordsArray[numIndexes+1][1]=DotProduct(dist,e2)+0.5f;

			VectorSubtract( posc, origin,dist);
			texCoordsArray[numIndexes+2][0]=DotProduct(dist,e1)+0.5f;
			texCoordsArray[numIndexes+2][1]=DotProduct(dist,e2)+0.5f;

			if ((texCoordsArray[numIndexes][0] < 0.0f && texCoordsArray[numIndexes+1][0] < 0.0f && texCoordsArray[numIndexes+2][0] < 0.0f) ||
				(texCoordsArray[numIndexes][0] > 1.0f && texCoordsArray[numIndexes+1][0] > 1.0f && texCoordsArray[numIndexes+2][0] > 1.0f) ||
				(texCoordsArray[numIndexes][1] < 0.0f && texCoordsArray[numIndexes+1][1] < 0.0f && texCoordsArray[numIndexes+2][1] < 0.0f) ||
				(texCoordsArray[numIndexes][1] > 1.0f && texCoordsArray[numIndexes+1][1] > 1.0f && texCoordsArray[numIndexes+2][1] > 1.0f) )
			{
				continue; // didn't end up hitting this tri
			}
			/* old code, get from the svars = wrong
			oldTexCoordsArray[numIndexes][0]=tess.svars.texcoords[0][a][0];
			oldTexCoordsArray[numIndexes][1]=tess.svars.texcoords[0][a][1];
			oldTexCoordsArray[numIndexes+1][0]=tess.svars.texcoords[0][b][0];
			oldTexCoordsArray[numIndexes+1][1]=tess.svars.texcoords[0][b][1];
			oldTexCoordsArray[numIndexes+2][0]=tess.svars.texcoords[0][c][0];
			oldTexCoordsArray[numIndexes+2][1]=tess.svars.texcoords[0][c][1];
			*/
			oldTexCoordsArray[numIndexes][0]=tess.texCoords[a][0][0];
			oldTexCoordsArray[numIndexes][1]=tess.texCoords[a][0][1];
			oldTexCoordsArray[numIndexes+1][0]=tess.texCoords[b][0][0];
			oldTexCoordsArray[numIndexes+1][1]=tess.texCoords[b][0][1];
			oldTexCoordsArray[numIndexes+2][0]=tess.texCoords[c][0][0];
			oldTexCoordsArray[numIndexes+2][1]=tess.texCoords[c][0][1];

			colorTemp[0] = Q_ftol(floatColor[0] * modulate);
			colorTemp[1] = Q_ftol(floatColor[1] * modulate);
			colorTemp[2] = Q_ftol(floatColor[2] * modulate);
			colorTemp[3] = 255;

			byteAlias_t *ba = (byteAlias_t *)&colorTemp;
			colorArray[numIndexes + 0] = ba->ui;
			colorArray[numIndexes + 1] = ba->ui;
			colorArray[numIndexes + 2] = ba->ui;

			hitIndexes[numIndexes] = numIndexes;
			hitIndexes[numIndexes+1] = numIndexes+1;
			hitIndexes[numIndexes+2] = numIndexes+2;
			numIndexes += 3;

			if (numIndexes>=SHADER_MAX_VERTEXES-3)
			{
				break; // we are out of space, so we are done :)
			}
		}

		if ( !numIndexes ) {
			continue;
		}

		//don't have fog enabled when we redraw with alpha test, or it will double over
		//and screw the tri up -rww
		if (r_drawfog->value == 2 &&
			tr.world &&
			(tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs))
		{
			fogging = qglIsEnabled(GL_FOG);

			if (fogging)
			{
				qglDisable(GL_FOG);
			}
		}
		else
		{
			fogging = 0;
		}


		dStage = NULL;
		if (tess.shader && qglActiveTextureARB)
		{
			int i = 0;
			while (i < tess.shader->numUnfoggedPasses)
			{
				const int blendBits = (GLS_SRCBLEND_BITS+GLS_DSTBLEND_BITS);
				if (((tess.shader->stages[i].bundle[0].image && !tess.shader->stages[i].bundle[0].isLightmap && !tess.shader->stages[i].bundle[0].numTexMods && tess.shader->stages[i].bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[i].bundle[0].tcGen != TCGEN_FOG) ||
					 (tess.shader->stages[i].bundle[1].image && !tess.shader->stages[i].bundle[1].isLightmap && !tess.shader->stages[i].bundle[1].numTexMods && tess.shader->stages[i].bundle[1].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[i].bundle[1].tcGen != TCGEN_FOG)) &&
					(tess.shader->stages[i].stateBits & blendBits) == 0 )
				{ //only use non-lightmap opaque stages
                    dStage = &tess.shader->stages[i];
					break;
				}
				i++;
			}
		}
		if (!needResetVerts)
		{
			needResetVerts=1;
			if (qglUnlockArraysEXT)
			{
				qglUnlockArraysEXT();
				GLimp_LogComment( "glUnlockArraysEXT\n" );
			}
		}
		qglVertexPointer (3, GL_FLOAT, 16, vertCoordsArray);	// padded for SIMD

		if (dStage)
		{
			GL_SelectTexture( 0 );
			GL_State(0);
			qglTexCoordPointer( 2, GL_FLOAT, 0, oldTexCoordsArray[0] );
			if (dStage->bundle[0].image && !dStage->bundle[0].isLightmap && !dStage->bundle[0].numTexMods && dStage->bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && dStage->bundle[0].tcGen != TCGEN_FOG)
			{
				R_BindAnimatedImage( &dStage->bundle[0] );
			}
			else
			{
				R_BindAnimatedImage( &dStage->bundle[1] );
			}

			GL_SelectTexture( 1 );
			qglEnable( GL_TEXTURE_2D );
			qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
			qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );
			qglEnableClientState( GL_COLOR_ARRAY );
			qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );
			GL_Bind( tr.dlightImage );
			GL_TexEnv( GL_MODULATE );


			GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL);// | GLS_ATEST_GT_0);

			R_DrawElements( numIndexes, hitIndexes );

			qglDisable( GL_TEXTURE_2D );
			GL_SelectTexture(0);
		}
		else
		{
			qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
			qglTexCoordPointer( 2, GL_FLOAT, 0, texCoordsArray[0] );

			qglEnableClientState( GL_COLOR_ARRAY );
			qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray );

			GL_Bind( tr.dlightImage );
			// include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light
			// where they aren't rendered
			if ( dl->additive ) {
				GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
			}
			else {
				GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL );
			}

			R_DrawElements( numIndexes, hitIndexes );
		}

		if (fogging)
		{
			qglEnable(GL_FOG);
		}

		backEnd.pc.c_totalIndexes += numIndexes;
		backEnd.pc.c_dlightIndexes += numIndexes;
	}
	if (needResetVerts)
	{
		qglVertexPointer (3, GL_FLOAT, 16, tess.xyz);	// padded for SIMD
		if (qglLockArraysEXT)
		{
			qglLockArraysEXT(0, tess.numVertexes);
			GLimp_LogComment( "glLockArraysEXT\n" );
		}
	}
}
Exemple #19
0
/*
** R_DrawTriangleOutlines
*/
void R_DrawTriangleOutlines(msurface_t *surf) // jit/GuyP, redone
{
	int        i;
	glpoly_t *p;

	if (!gl_showtris->value)
        return;

    // Guy: *\/\/\/ gl_showtris fix begin \/\/\/*
    qgl.Disable(GL_DEPTH_TEST);
	qgl.Color4f(1.0f, 1.0f, 1.0f, 1.0f);

    if (!surf)    // Guy: Called from non-multitexture mode; need to loop through surfaces defined by non-mtex functions
    {
        int j;

        qgl.Disable(GL_TEXTURE_2D);
        
        for (i = 0; i < MAX_LIGHTMAPS; i++)
        {
            for (surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain)
            {
                for (p = surf->polys; p; p = p->chain)
                {
                    for (j = 2; j < p->numverts; j++)
                    {
                        qgl.Begin(GL_LINE_STRIP);
                            qgl.Vertex3fv(p->verts[0]);
                            qgl.Vertex3fv(p->verts[j - 1]);
                            qgl.Vertex3fv(p->verts[j]);
                            qgl.Vertex3fv(p->verts[0]);
                        qgl.End();
                    }
                }
            }
        }

        qgl.Enable(GL_TEXTURE_2D);
    }
    
    else    // Guy: Called from multitexture mode; surface to be rendered in wireframe already passed in
    {
        float    tex_state0,
                 tex_state1;

        GL_SelectTexture(QGL_TEXTURE0);
        qgl.GetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_state0);

        GL_SelectTexture(QGL_TEXTURE1);
        qgl.GetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_state1);

        GL_EnableMultitexture(false);
        qgl.Disable(GL_TEXTURE_2D);

        for (p = surf->polys; p; p = p->chain)
        {
            for (i = 2; i < p->numverts; i++)
            {
				//distcolor = p->verts[
				
                qgl.Begin(GL_LINE_STRIP);
                    //qgl.Color4f(1, 1, 1, 1);
					//qgl.Color4f(0,1,0,1);
                    qgl.Vertex3fv(p->verts[0]);
                    qgl.Vertex3fv(p->verts[i - 1]);
                    qgl.Vertex3fv(p->verts[i]);
                    qgl.Vertex3fv(p->verts[0]);
                qgl.End();
            }
        }

        qgl.Enable(GL_TEXTURE_2D);
        GL_EnableMultitexture(true);
        
		GL_SelectTexture(QGL_TEXTURE0);
		GL_TexEnv(tex_state0);

		GL_SelectTexture(QGL_TEXTURE1);
		GL_TexEnv(tex_state1);
	}

	qgl.Enable(GL_DEPTH_TEST);
	// Guy: */\/\/\ gl_showtris fix end /\/\/\*
}
Exemple #20
0
/*
=================
R_Bloom_GeneratexDiamonds
=================
*/
static void R_Bloom_GeneratexDiamonds( void )
{
	int i, j, k;
	float intensity, scale, *diamond;

	// set up sample size workspace
	qglScissor( 0, 0, sample_width, sample_height );
	qglViewport( 0, 0, sample_width, sample_height );
	qglMatrixMode( GL_PROJECTION );
	qglLoadIdentity();
	qglOrtho( 0, sample_width, sample_height, 0, -10, 100 );
	qglMatrixMode( GL_MODELVIEW );
	qglLoadIdentity();

	// copy small scene into r_bloomeffecttexture
	GL_Bind( 0, r_bloomeffecttexture );
	qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height );

	// start modifying the small scene corner
	qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );

	// darkening passes
	if( r_bloom_darken->integer )
	{
		GL_TexEnv( GL_MODULATE );
		GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO );

		for( i = 0; i < r_bloom_darken->integer; i++ )
			R_Bloom_SamplePass( 0, 0 );
		qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height );
	}

	// bluring passes
	GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR );

	if( r_bloom_diamond_size->integer > 7 || r_bloom_diamond_size->integer <= 3 )
	{
		if( r_bloom_diamond_size->integer != 8 )
			Cvar_ForceSet( "r_bloom_diamond_size", "8" );
	}
	else if( r_bloom_diamond_size->integer > 5 )
	{
		if( r_bloom_diamond_size->integer != 6 )
			Cvar_ForceSet( "r_bloom_diamond_size", "6" );
	}
	else if( r_bloom_diamond_size->integer > 3 )
	{
		if( r_bloom_diamond_size->integer != 4 )
			Cvar_ForceSet( "r_bloom_diamond_size", "4" );
	}

	switch( r_bloom_diamond_size->integer )
	{
	case 4:
		k = 2;
		diamond = &Diamond4x[0][0];
		scale = r_bloom_intensity->value * 0.8f;
		break;
	case 6:
		k = 3;
		diamond = &Diamond6x[0][0];
		scale = r_bloom_intensity->value * 0.5f;
		break;
	default:
//	case 8:
		k = 4;
		diamond = &Diamond8x[0][0];
		scale = r_bloom_intensity->value * 0.3f;
		break;
	}

	for( i = 0; i < r_bloom_diamond_size->integer; i++ )
	{
		for( j = 0; j < r_bloom_diamond_size->integer; j++, diamond++ )
		{
			intensity =  *diamond * scale;
			if( intensity < 0.01f )
				continue;

			qglColor4f( intensity, intensity, intensity, 1.0 );
			R_Bloom_SamplePass( i - k, j - k );
		}
	}

	qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height );

	// restore full screen workspace
	qglScissor( 0, 0, glState.width, glState.height );
	qglViewport( 0, 0, glState.width, glState.height );
	qglMatrixMode( GL_PROJECTION );
	qglLoadIdentity();
	qglOrtho( 0, glState.width, glState.height, 0, -10, 100 );
	qglMatrixMode( GL_MODELVIEW );
	qglLoadIdentity();
}
Exemple #21
0
/*
=================
R_DrawAliasModel
=================
*/
void R_DrawAliasModel (entity_t *e)
{
	maliasmodel_t	*paliashdr;
	vec3_t		bbox[8];
	qboolean	mirrormodel = false;
	int			i;

	// also skip this for viewermodels and cameramodels
	if ( !(e->flags & RF_WEAPONMODEL || e->flags & RF_VIEWERMODEL || e->renderfx & RF2_CAMERAMODEL) )
	{
		if (R_CullAliasModel(bbox, e))
			return;
	}

	// mirroring support
	if (e->flags & RF_WEAPONMODEL)
	{
		if (r_lefthand->value == 2)
			return;
		else if (r_lefthand->value == 1)
			mirrormodel = true;
	}
	else if (e->renderfx & RF2_CAMERAMODEL)
	{
		if (r_lefthand->value==1)
			mirrormodel = true;
	}
	else if (e->flags & RF_MIRRORMODEL)
		mirrormodel = true;
	// end mirroring support

	paliashdr = (maliasmodel_t *)currentmodel->extradata;

	R_SetShadeLight ();

	if (e->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
	{
		if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
			GL_DepthRange (gldepthmin, gldepthmin + 0.01*(gldepthmax-gldepthmin));
		else
			GL_DepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
	}

	// mirroring support
	if (mirrormodel)
		R_FlipModel(true);

	for (i=0; i < paliashdr->num_meshes; i++)
		c_alias_polys += paliashdr->meshes[i].num_tris;

	qglPushMatrix ();
	e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
	R_RotateForEntity (e, true);
	e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards

	GL_ShadeModel (GL_SMOOTH);

	GL_TexEnv(GL_MODULATE);

	if ( (e->frame >= paliashdr->num_frames) || (e->frame < 0) )
	{
		VID_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n", currentmodel->name, e->frame);
		e->frame = 0;
		e->oldframe = 0;
	}

	if ( (e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
	{
		VID_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
			currentmodel->name, e->oldframe);
		e->frame = 0;
		e->oldframe = 0;
	}

	if (!r_lerpmodels->value)
		e->backlerp = 0;

	R_DrawAliasFrameLerp (paliashdr, e);

	GL_TexEnv(GL_REPLACE);
	GL_ShadeModel (GL_FLAT);

	qglPopMatrix ();

	// mirroring support
	if (mirrormodel)
		R_FlipModel(false);

	// show model bounding box
	R_DrawAliasModelBBox (bbox, e);

	if (e->flags & RF_DEPTHHACK)
		GL_DepthRange (gldepthmin, gldepthmax);

	aliasShadowAlpha = R_CalcShadowAlpha(e);

	if (!(e->flags & (RF_WEAPONMODEL | RF_NOSHADOW))
		// no shadows from shells
		&& !( (e->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM)) && (e->flags & RF_TRANSLUCENT) )
		&& r_shadows->value >= 1 && aliasShadowAlpha >= DIV255)
	{
 		qglPushMatrix ();
		GL_DisableTexture(0);
		GL_Enable (GL_BLEND);

		if (r_shadows->value == 3) {
			e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
			R_RotateForEntity (e, true);
			e->angles[ROLL] = -e->angles[ROLL];		// roll is backwards
			R_DrawAliasVolumeShadow (paliashdr, bbox);
		}
		else {
			R_RotateForEntity (e, false);
			R_DrawAliasPlanarShadow (paliashdr);
		}

		GL_Disable (GL_BLEND);
		GL_EnableTexture(0);
		qglPopMatrix ();
	}
}