Esempio n. 1
0
PDGL_API void pdglColor4f(float r, float g, float b, float a)
{
	if(pglColor4f)
		{ pglColor4f(r, g, b, a); return; }
	pglColor4f=pdglGetProcAddress("glColor4f");
	pglColor4f(r, g, b, a);
}
Esempio n. 2
0
/*
===============
R_Set2DMode
===============
*/
void R_Set2DMode( qboolean enable )
{
	if( enable )
	{
		if( glState.in2DMode )
			return;

		// set 2D virtual screen size
		pglScissor( 0, 0, glState.width, glState.height );
		pglViewport( 0, 0, glState.width, glState.height );
		pglMatrixMode( GL_PROJECTION );
		pglLoadIdentity();
		pglOrtho( 0, glState.width, glState.height, 0, -99999, 99999 );
		pglMatrixMode( GL_MODELVIEW );
		pglLoadIdentity();

		GL_Cull( 0 );

		pglDepthMask( GL_FALSE );
		pglDisable( GL_DEPTH_TEST );
		pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );

		glState.in2DMode = true;
		RI.currententity = NULL;
		RI.currentmodel = NULL;
	}
	else
	{
		pglDepthMask( GL_TRUE );
		pglEnable( GL_DEPTH_TEST );
		pglMatrixMode( GL_MODELVIEW );
		glState.in2DMode = false;
	}
}
Esempio n. 3
0
/*
=============
R_ShadowPassSetupGL
=============
*/
static void R_ShadowPassSetupGL( const plight_t *pl )
{
	// matrices already computed
	RI.worldviewMatrix = pl->modelviewMatrix;
	RI.projectionMatrix = pl->projectionMatrix;
	RI.worldviewProjectionMatrix = RI.projectionMatrix.Concat( RI.worldviewMatrix );

	GLfloat dest[16];

	// tell engine about worldviewprojection matrix so TriWorldToScreen and TriScreenToWorld
	// will be working properly
	RI.worldviewProjectionMatrix.CopyToArray( dest );
	SET_ENGINE_WORLDVIEW_MATRIX( dest );

	pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] );
	pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] );

	pglMatrixMode( GL_PROJECTION );
	GL_LoadMatrix( RI.projectionMatrix );

	pglMatrixMode( GL_MODELVIEW );
	GL_LoadMatrix( RI.worldviewMatrix );

	GL_Cull( GL_FRONT );

	pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
	pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
	pglEnable( GL_POLYGON_OFFSET_FILL );
	pglDisable( GL_TEXTURE_2D );
	pglDepthMask( GL_TRUE );
	pglPolygonOffset( 8, 30 );
	pglEnable( GL_DEPTH_TEST );
	pglDisable( GL_ALPHA_TEST );
	pglDisable( GL_BLEND );
}
Esempio n. 4
0
/*
=================
R_Bloom_DownsampleView
=================
*/
static void R_Bloom_DownsampleView( void )
{
    pglDisable( GL_BLEND );
    pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );

    if( r_screendownsamplingtexture_size )
    {
        // stepped downsample
        int midsample_width = ( r_screendownsamplingtexture_size * sampleText_tcw );
        int midsample_height = ( r_screendownsamplingtexture_size * sampleText_tch );

        // copy the screen and draw resized
        GL_Bind( GL_TEXTURE0, r_bloomscreentexture );
        pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height );
        R_Bloom_Quad( 0, glState.height - midsample_height, midsample_width, midsample_height, screenTex_tcw, screenTex_tch );

        // now copy into downsampling (mid-sized) texture
        GL_Bind( GL_TEXTURE0, r_bloomdownsamplingtexture );
        pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height );

        // now draw again in bloom size
        pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f );
        R_Bloom_Quad( 0, glState.height - sample_height, sample_width, sample_height, sampleText_tcw, sampleText_tch );

        // now blend the big screen texture into the bloom generation space (hoping it adds some blur)
        pglEnable( GL_BLEND );
        pglBlendFunc( GL_ONE, GL_ONE );
        pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f );
        GL_Bind( GL_TEXTURE0, r_bloomscreentexture );
        R_Bloom_Quad( 0, glState.height - sample_height, sample_width, sample_height, screenTex_tcw, screenTex_tch );
        pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
        pglDisable( GL_BLEND );
    }
    else
    {
        // downsample simple
        GL_Bind( GL_TEXTURE0, r_bloomscreentexture );
        pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height );
        R_Bloom_Quad( 0, glState.height - sample_height, sample_width, sample_height, screenTex_tcw, screenTex_tch );
    }
}
Esempio n. 5
0
/*
=============
R_SetupGL
=============
*/
static void R_SetupGL( void )
{
	if( RI.refdef.waterlevel >= 3 )
	{
		float	f;
		f = sin( cl.time * 0.4f * ( M_PI * 2.7f ));
		RI.refdef.fov_x += f;
		RI.refdef.fov_y -= f;
	}

	R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix );
	R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix );
//	if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0];

	Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix );

	pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] );
	pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] );

	pglMatrixMode( GL_PROJECTION );
	GL_LoadMatrix( RI.projectionMatrix );

	pglMatrixMode( GL_MODELVIEW );
	GL_LoadMatrix( RI.worldviewMatrix );

	if( RI.params & RP_CLIPPLANE )
	{
		GLdouble	clip[4];
		mplane_t	*p = &RI.clipPlane;

		clip[0] = p->normal[0];
		clip[1] = p->normal[1];
		clip[2] = p->normal[2];
		clip[3] = -p->dist;

		pglClipPlane( GL_CLIP_PLANE0, clip );
		pglEnable( GL_CLIP_PLANE0 );
	}

	if( RI.params & RP_FLIPFRONTFACE )
		GL_FrontFace( !glState.frontFace );

	GL_Cull( GL_FRONT );

	pglDisable( GL_BLEND );
	pglDisable( GL_ALPHA_TEST );
	pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
}
Esempio n. 6
0
/*
=================
R_Bloom_DrawEffect
=================
*/
static void R_Bloom_DrawEffect( void )
{
    GL_Bind( GL_TEXTURE0, r_bloomeffecttexture );
    pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
    pglColor4f( r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f );
    pglBlendFunc( GL_ONE, GL_ONE );
    pglEnable( GL_BLEND );

    pglBegin( GL_QUADS );
    pglTexCoord2f( 0, sampleText_tch );
    pglVertex2f( curView_x, curView_y );
    pglTexCoord2f( 0, 0 );
    pglVertex2f( curView_x, curView_y+curView_height );
    pglTexCoord2f( sampleText_tcw, 0 );
    pglVertex2f( curView_x+curView_width, curView_y+curView_height );
    pglTexCoord2f( sampleText_tcw, sampleText_tch );
    pglVertex2f( curView_x+curView_width, curView_y );
    pglEnd();

    pglDisable( GL_BLEND );
}
Esempio n. 7
0
/*
=============
Draw_TileClear

This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void R_DrawTileClear( int x, int y, int w, int h )
{
	float		tw, th;
	gltexture_t	*glt;

	GL_SetRenderMode( kRenderNormal );
	pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
	GL_Bind( GL_TEXTURE0, cls.tileImage );

	glt = R_GetTexture( cls.tileImage );
	tw = glt->srcWidth;
	th = glt->srcHeight;

	pglBegin( GL_QUADS );
		pglTexCoord2f( x / tw, y / th );
		pglVertex2f( x, y );
		pglTexCoord2f((x + w) / tw, y / th );
		pglVertex2f( x + w, y );
		pglTexCoord2f((x + w) / tw, (y + h) / th );
		pglVertex2f( x + w, y + h );
		pglTexCoord2f( x / tw, (y + h) / th );
		pglVertex2f( x, y + h );
	pglEnd ();
}
Esempio n. 8
0
/*
=============
R_SetupGL
=============
*/
static void R_SetupGL( void )
{
	if( r_underwater_distortion->value && RI.refdef.waterlevel >= 3 )
	{
		float	f;
		f = sin( cl.time * r_underwater_distortion->value * ( M_PI * 2.7f ));
		RI.refdef.fov_x += f;
		RI.refdef.fov_y -= f;
	}

	R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix );
	R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix );
//	if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0];

	Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix );

	if( RP_NORMALPASS( ))
	{
		int	x, x2, y, y2;

		// set up viewport (main, playersetup)
		x = floor( RI.viewport[0] * glState.width / glState.width );
		x2 = ceil(( RI.viewport[0] + RI.viewport[2] ) * glState.width / glState.width );
		y = floor( glState.height - RI.viewport[1] * glState.height / glState.height );
		y2 = ceil( glState.height - ( RI.viewport[1] + RI.viewport[3] ) * glState.height / glState.height );

		pglViewport( x, y2, x2 - x, y - y2 );
	}
	else
	{
		// envpass, mirrorpass
		pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] );
	}

	pglMatrixMode( GL_PROJECTION );
	GL_LoadMatrix( RI.projectionMatrix );

	pglMatrixMode( GL_MODELVIEW );
	GL_LoadMatrix( RI.worldviewMatrix );

	if( RI.params & RP_CLIPPLANE )
	{
		GLdouble	clip[4];
		mplane_t	*p = &RI.clipPlane;

		clip[0] = p->normal[0];
		clip[1] = p->normal[1];
		clip[2] = p->normal[2];
		clip[3] = -p->dist;

		pglClipPlane( GL_CLIP_PLANE0, clip );
		pglEnable( GL_CLIP_PLANE0 );
	}

	if( RI.params & RP_FLIPFRONTFACE )
		GL_FrontFace( !glState.frontFace );

	GL_Cull( GL_FRONT );

	pglDisable( GL_BLEND );
	pglDisable( GL_ALPHA_TEST );
	pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
}
Esempio n. 9
0
/*
===============
R_ShowTextures

Draw all the images to the screen, on top of whatever
was there.  This is used to test for texture thrashing.
===============
*/
void R_ShowTextures( void )
{
	gltexture_t	*image;
	float		x, y, w, h;
	int		i, j, k, base_w, base_h;
	int		total, start, end;
	rgba_t		color = { 192, 192, 192, 255 };
	int		charHeight, numTries = 0;
	static qboolean	showHelp = true;
	string		shortname;

	if( !gl_showtextures->integer )
		return;

	if( showHelp )
	{
		CL_CenterPrint( "use '<-' and '->' keys to view all the textures", 0.25f );
		showHelp = false;
	}

	pglClear( GL_COLOR_BUFFER_BIT );
	pglFinish();

	base_w = 8;
	base_h = 6;

rebuild_page:
	total = base_w * base_h;
	start = total * (gl_showtextures->integer - 1);
	end = total * gl_showtextures->integer;
	if( end > MAX_TEXTURES ) end = MAX_TEXTURES;

	w = glState.width / (float)base_w;
	h = glState.height / (float)base_h;

	Con_DrawStringLen( NULL, NULL, &charHeight );

	for( i = j = 0; i < MAX_TEXTURES; i++ )
	{
		image = R_GetTexture( i );
		if( j == start ) break; // found start
		if( pglIsTexture( image->texnum )) j++;
	}

	if( i == MAX_TEXTURES && gl_showtextures->integer != 1 )
	{
		// bad case, rewind to one and try again
		Cvar_SetFloat( "r_showtextures", max( 1, gl_showtextures->integer - 1 ));
		if( ++numTries < 2 ) goto rebuild_page;	// to prevent infinite loop
	}

	for( k = 0; i < MAX_TEXTURES; i++ )
	{
		if( j == end ) break; // page is full

		image = R_GetTexture( i );
		if( !pglIsTexture( image->texnum ))
			continue;

		x = k % base_w * w;
		y = k / base_w * h;

		pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
		GL_Bind( XASH_TEXTURE0, i ); // NOTE: don't use image->texnum here, because skybox has a 'wrong' indexes

		if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE ))
			pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );

		pglBegin( GL_QUADS );
		pglTexCoord2f( 0, 0 );
		pglVertex2f( x, y );
		if( image->flags & TF_TEXTURE_RECTANGLE )
			pglTexCoord2f( image->width, 0 );
		else pglTexCoord2f( 1, 0 );
		pglVertex2f( x + w, y );
		if( image->flags & TF_TEXTURE_RECTANGLE )
			pglTexCoord2f( image->width, image->height );
		else pglTexCoord2f( 1, 1 );
		pglVertex2f( x + w, y + h );
		if( image->flags & TF_TEXTURE_RECTANGLE )
			pglTexCoord2f( 0, image->height );
		else pglTexCoord2f( 0, 1 );
		pglVertex2f( x, y + h );
		pglEnd();

		if(( image->flags & TF_DEPTHMAP ) && !( image->flags & TF_NOCOMPARE ))
			pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB );

		FS_FileBase( image->name, shortname );
		if( Q_strlen( shortname ) > 18 )
		{
			// cutoff too long names, it looks ugly
			shortname[16] = '.';
			shortname[17] = '.';
			shortname[18] = '\0';
		}
		Con_DrawString( x + 1, y + h - charHeight, shortname, color );
		j++, k++;
	}

	CL_DrawCenterPrint ();
	pglFinish();
}
Esempio n. 10
0
/*
=================
R_BloomBlend
=================
*/
void R_BloomBlend( const ref_params_t *fd )
{
    if( !r_bloom->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
    pglScissor( 0, 0, glState.width, glState.height );
    pglViewport( 0, 0, glState.width, glState.height );
    pglMatrixMode( GL_PROJECTION );
    pglLoadIdentity();

    pglOrtho( 0, glState.width, glState.height, 0, -10, 100 );

    pglMatrixMode( GL_MODELVIEW );
    pglLoadIdentity();

    pglDisable( GL_DEPTH_TEST );
    pglDisable( GL_ALPHA_TEST );
    pglDepthMask( GL_FALSE );
    pglDisable( GL_BLEND );

    GL_Cull( 0 );
    pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
    pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

    // set up current sizes
    curView_x = fd->viewport[0];
    curView_y = fd->viewport[1];
    curView_width = fd->viewport[2];
    curView_height = fd->viewport[3];

    screenTex_tcw = ( (float)curView_width / (float)screen_texture_width );
    screenTex_tch = ( (float)curView_height / (float)screen_texture_height );
    if( curView_height > curView_width )
    {
        sampleText_tcw = ( (float)curView_width / (float)curView_height );
        sampleText_tch = 1.0f;
    }
    else
    {
        sampleText_tcw = 1.0f;
        sampleText_tch = ( (float)curView_height / (float)curView_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( GL_TEXTURE0, r_bloombackuptexture );
    pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_width * sampleText_tcw, r_screenbackuptexture_height * sampleText_tch );

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

    pglDisable( GL_BLEND );
    // restore the screen-backup to the screen
    GL_Bind( GL_TEXTURE0, r_bloombackuptexture );

    pglColor4f( 1, 1, 1, 1 );

    R_Bloom_Quad( 0,
                  glState.height - (r_screenbackuptexture_height * sampleText_tch),
                  r_screenbackuptexture_width * sampleText_tcw,
                  r_screenbackuptexture_height * sampleText_tch,
                  sampleText_tcw, sampleText_tch );

    pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] );

    R_Bloom_DrawEffect();

    pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] );

    pglMatrixMode( GL_PROJECTION );
    GL_LoadMatrix( RI.projectionMatrix );

    pglMatrixMode( GL_MODELVIEW );
    GL_LoadMatrix( RI.worldviewMatrix );

    pglEnable( GL_DEPTH_TEST );
    pglDepthMask( GL_TRUE );
    pglDisable( GL_BLEND );
    GL_Cull( GL_FRONT );
}
Esempio n. 11
0
/*
=================
R_Bloom_GeneratexDiamonds
=================
*/
static void R_Bloom_GeneratexDiamonds( void )
{
    int i, j;
    float intensity;

    // set up sample size workspace
    pglScissor( 0, 0, sample_width, sample_height );
    pglViewport( 0, 0, sample_width, sample_height );
    pglMatrixMode( GL_PROJECTION );
    pglLoadIdentity();
    pglOrtho( 0, sample_width, sample_height, 0, -10, 100 );
    pglMatrixMode( GL_MODELVIEW );
    pglLoadIdentity();

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

    // start modifying the small scene corner
    pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
    pglEnable( GL_BLEND );

    // darkening passes
    if( r_bloom_darken->value )
    {
        pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
        pglBlendFunc( GL_DST_COLOR, GL_ZERO );

        for( i = 0; i < (int)r_bloom_darken->value; i++ )
            R_Bloom_SamplePass( 0, 0 );

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

    // bluring passes
    pglBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR );

    if( r_bloom_diamond_size->value > 7.0f || r_bloom_diamond_size->value <= 3.0f )
    {
        if( r_bloom_diamond_size->value != 8.0f )
            CVAR_SET_FLOAT( "r_bloom_diamond_size", 8.0f );

        for( i = 0; i < r_bloom_diamond_size->value; i++ )
        {
            for( j = 0; j < r_bloom_diamond_size->value; j++ )
            {
                intensity = r_bloom_intensity->value * 0.3f * Diamond8x[i][j];
                if( intensity < 0.01f ) continue;
                pglColor4f( intensity, intensity, intensity, 1.0f );
                R_Bloom_SamplePass( i-4, j-4 );
            }
        }
    }
    else if( r_bloom_diamond_size->value > 5.0f )
    {
        if( r_bloom_diamond_size->value != 6.0f )
            CVAR_SET_FLOAT( "r_bloom_diamond_size", 6.0f );

        for( i = 0; i < r_bloom_diamond_size->value; i++ )
        {
            for( j = 0; j < r_bloom_diamond_size->value; j++ )
            {
                intensity = r_bloom_intensity->value * 0.5f * Diamond6x[i][j];
                if( intensity < 0.01f ) continue;
                pglColor4f( intensity, intensity, intensity, 1.0f );
                R_Bloom_SamplePass( i-3, j-3 );
            }
        }
    }
    else if( r_bloom_diamond_size->value > 3.0f )
    {
        if( r_bloom_diamond_size->value != 4.0f )
            CVAR_SET_FLOAT( "r_bloom_diamond_size", 4.0f );

        for( i = 0; i < r_bloom_diamond_size->value; i++ )
        {
            for( j = 0; j < r_bloom_diamond_size->value; j++ )
            {
                intensity = r_bloom_intensity->value * 0.8f * Diamond4x[i][j];
                if( intensity < 0.01f ) continue;
                pglColor4f( intensity, intensity, intensity, 1.0f );
                R_Bloom_SamplePass( i-2, j-2 );
            }
        }
    }

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

    // restore full screen workspace
    pglScissor( 0, 0, glState.width, glState.height );
    pglViewport( 0, 0, glState.width, glState.height );
    pglMatrixMode( GL_PROJECTION );
    pglLoadIdentity();
    pglOrtho( 0, glState.width, glState.height, 0, -10, 100 );
    pglMatrixMode( GL_MODELVIEW );
    pglLoadIdentity();
}
Esempio n. 12
0
void CParticleSystem :: DrawParticle( CParticle *part, Vector &right, Vector &up )
{
	float fSize = part->m_fSize;

	// nothing to draw?
	if( fSize <= 0 ) return;

	// frustrum visible check
	if( !ParticleIsVisible( part ))
		return;

	Vector point1, point2, point3, point4;
	Vector origin = part->origin;

	float fCosSize = CosLookup( part->m_fAngle ) * fSize;
	float fSinSize = SinLookup( part->m_fAngle ) * fSize;

	// calculate the four corners of the sprite
	point1 = origin + up * fSinSize + right * -fCosSize;
	point2 = origin + up * fCosSize + right * fSinSize;
	point3 = origin + up * -fSinSize + right * fCosSize;	
	point4 = origin + up * -fCosSize + right * -fSinSize;

	int iContents = CONTENTS_NONE;
	model_t *pModel;

	for( CParticle *pDraw = part; pDraw; pDraw = pDraw->m_pOverlay )
	{
		if( !pDraw->pType->m_hSprite )
			continue;

		if( pDraw->pType->m_iDrawCond )
		{
			if( pDraw->pType->m_iDrawCond == CONTENT_SPOTLIGHT )
			{
				if( !R_CountPlights( ))
					continue;	// fast reject

				for( int i = 0; i < MAX_PLIGHTS; i++ )
				{
					plight_t *pl = &cl_plights[i];

					if( pl->die < GET_CLIENT_TIME() || !pl->radius )
						continue;

					if( !R_CullSphereExt( pl->frustum, part->origin, part->m_fSize + 1, pl->clipflags ))
						break; // cone intersected with particle

				}

				if( i == MAX_PLIGHTS )
					continue;	// no intersection
			}
			else
			{
				if( iContents == CONTENTS_NONE )
					iContents = POINT_CONTENTS( origin );

				if( iContents != pDraw->pType->m_iDrawCond )
					continue;
			}
		}

		pModel = (model_t *)gEngfuncs.GetSpritePointer( pDraw->pType->m_hSprite );

		// if we've reached the end of the sprite's frames, loop back
		while (pDraw->frame > pModel->numframes)
			pDraw->frame -= pModel->numframes;

		while (pDraw->frame < 0)
			pDraw->frame += pModel->numframes;

		if( !TriSpriteTexture( pModel, (int)pDraw->frame ))
			continue;

		gEngfuncs.pTriAPI->RenderMode( pDraw->pType->m_iRenderMode );

		if( m_iLightingModel >= 1 )
		{
			color24 lightColor;
			Vector lightingColor;

			if( m_iLightingModel == 1 )
				R_LightForPoint( part->origin, &lightColor, false, true, fSize + 1 );
			else R_LightForPoint( part->origin, &lightColor, false, true, 0.0f );
			
			// FIXME: this code is totally wrong.
			// We need a fake lightmap here like in sprite implementation
			lightingColor.x = pDraw->m_fRed * lightColor.r * (1.0f / 255.0f);
			lightingColor.y = pDraw->m_fGreen * lightColor.g * (1.0f / 255.0f);
			lightingColor.z = pDraw->m_fBlue * lightColor.b * (1.0f / 255.0f);
			pglColor4f( lightingColor.x, lightingColor.y, lightingColor.z, pDraw->m_fAlpha );
		}
		else pglColor4f( pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue, pDraw->m_fAlpha );

		pglBegin( GL_QUADS );
			pglTexCoord2f( 0.0f, 0.0f );
			pglVertex3fv( point1 );

			pglTexCoord2f( 1.0f, 0.0f );
			pglVertex3fv( point2 );

			pglTexCoord2f( 1.0f, 1.0f );
			pglVertex3fv( point3 );

			pglTexCoord2f( 0.0f, 1.0f );
			pglVertex3fv( point4 );
		pglEnd();

		if( m_iLightingModel >=2 && R_CountPlights( ))
		{
			for( int i = 0; i < MAX_PLIGHTS; i++ )
			{
				plight_t *pl = &cl_plights[i];

				if( pl->die < GET_CLIENT_TIME() || !pl->radius )
					continue;

				if( R_CullSphereExt( pl->frustum, part->origin, part->m_fSize + 1, pl->clipflags ))
					continue;

				R_BeginDrawProjection( pl );

				pglBegin( GL_QUADS );
					pglVertex3fv( point1 );
					pglVertex3fv( point2 );
					pglVertex3fv( point3 );
					pglVertex3fv( point4 );
				pglEnd();

				R_EndDrawProjection();
			}
		}
	}
}