Esempio n. 1
0
/*
================
RB_DrawElementsWithCounters
================
*/
void RB_DrawElementsWithCounters( const srfTriangles_t *tri ) {

	backEnd.pc.c_drawElements++;
	backEnd.pc.c_drawIndexes += tri->numIndexes;
	backEnd.pc.c_drawVertexes += tri->numVerts;

	if ( tri->ambientSurface != NULL  ) {
		if ( tri->indexes == tri->ambientSurface->indexes ) {
			backEnd.pc.c_drawRefIndexes += tri->numIndexes;
		}
		if ( tri->verts == tri->ambientSurface->verts ) {
			backEnd.pc.c_drawRefVertexes += tri->numVerts;
		}
	}

	if ( tri->indexCache && r_useIndexBuffers.GetBool() ) {
		qglDrawElements( GL_TRIANGLES, 
						r_singleTriangle.GetBool() ? 3 : tri->numIndexes,
						GL_INDEX_TYPE,
						(int *)vertexCache.Position( tri->indexCache ) );
		backEnd.pc.c_vboIndexes += tri->numIndexes;
	} else {
		if ( r_useIndexBuffers.GetBool() ) {
			vertexCache.UnbindIndex();
		}
		qglDrawElements( GL_TRIANGLES, 
						r_singleTriangle.GetBool() ? 3 : tri->numIndexes,
						GL_INDEX_TYPE,
						tri->indexes );
	}
}
Esempio n. 2
0
/*
==================
R_DrawElements

Optionally performs our own glDrawElements that looks for strip conditions
instead of using the single glDrawElements call that may be inefficient
without compiled vertex arrays.
==================
*/
static void R_DrawElements(int numIndexes, const glIndex_t *indexes)
{
	switch (r_primitives->integer)
	{
	case 0:
		// default is to use triangles if compiled vertex arrays are present
		if (qglLockArraysEXT)
		{
			qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, indexes);
		}
		else
		{
			R_DrawStripElements(numIndexes, indexes, R_ArrayElement);
		}
		return;
	case 1:
		R_DrawStripElements(numIndexes, indexes, R_ArrayElement);
		return;
	case 2:
		qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, indexes);
		return;
	case 3:
		R_DrawStripElements(numIndexes, indexes, R_ArrayElementDiscrete);
		return;
	default: // anything else will cause no drawing
		return;
	}
}
Esempio n. 3
0
static void DrawSkySide( struct image_s *image, const int mins[2], const int maxs[2] )
{
	int s, t, i = 0;
	int size;
	glIndex_t *indicies;

	size = (maxs[1] - mins[1]) * (maxs[0] - mins[0] + 1);
	indicies = ri.Hunk_AllocateTempMemory(sizeof(glIndex_t) * size);

	GL_Bind( image );

	for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ )
	{
		for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ )
		{
			indicies[i++] = t * (SKY_SUBDIVISIONS + 1) + s;
			indicies[i++] = (t + 1) * (SKY_SUBDIVISIONS + 1) + s;
		}
	}

	qglDisableClientState(GL_COLOR_ARRAY);
	qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	qglTexCoordPointer(2, GL_FLOAT, 0, s_skyTexCoords);
	qglVertexPointer(3, GL_FLOAT, 0, s_skyPoints);
	qglDrawElements(GL_TRIANGLE_STRIP, i, GL_INDEX_TYPE, indicies);
	Hunk_FreeTempMemory(indicies);
}
Esempio n. 4
0
static void R_DrawMultiElementsVBO( int multiDrawPrimitives, glIndex_t *multiDrawMinIndex, glIndex_t *multiDrawMaxIndex, 
	GLsizei *multiDrawNumIndexes, glIndex_t **multiDrawFirstIndex)
{
	if (glRefConfig.multiDrawArrays)
	{
		qglMultiDrawElementsEXT(GL_TRIANGLES, multiDrawNumIndexes, GL_INDEX_TYPE, (const GLvoid **)multiDrawFirstIndex, multiDrawPrimitives);
	}
	else
	{
		int i;

		if (glRefConfig.drawRangeElements)
		{
			for (i = 0; i < multiDrawPrimitives; i++)
			{
				qglDrawRangeElementsEXT(GL_TRIANGLES, multiDrawMinIndex[i], multiDrawMaxIndex[i], multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]);
			}
		}
		else
		{
			for (i = 0; i < multiDrawPrimitives; i++)
			{
				qglDrawElements(GL_TRIANGLES, multiDrawNumIndexes[i], GL_INDEX_TYPE, multiDrawFirstIndex[i]);
			}
		}
	}
}
Esempio n. 5
0
/*
==================
R_DrawElements

Optionally performs our own glDrawElements that looks for strip conditions
instead of using the single glDrawElements call that may be inefficient
without compiled vertex arrays.
==================
*/
static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
	int primitives;

	primitives = r_primitives->integer;

	// default is to use triangles if compiled vertex arrays are present
	if ( primitives == 0 ) {
		if ( qglLockArraysEXT ) {
			primitives = 2;
		} else {
			primitives = 1;
		}
	}


	if ( primitives == 2 ) {
		qglDrawElements( GL_TRIANGLES,
						 numIndexes,
						 GL_INDEX_TYPE,
						 indexes );
		return;
	}

	if ( primitives == 1 ) {
		R_DrawStripElements( numIndexes,  indexes, qglArrayElement );
		return;
	}

	if ( primitives == 3 ) {
		R_DrawStripElements( numIndexes,  indexes, R_ArrayElementDiscrete );
		return;
	}

	// anything else will cause no drawing
}
Esempio n. 6
0
/*
=============
R_DrawShadowVolume 
=============
*/
void R_DrawShadowVolume (void)
{
	if (gl_config.drawRangeElements)
		qglDrawRangeElementsEXT(GL_TRIANGLES, 0, shadow_va, shadow_index, GL_UNSIGNED_INT, indexArray);
	else
		qglDrawElements(GL_TRIANGLES, shadow_index, GL_UNSIGNED_INT, indexArray);
}
Esempio n. 7
0
/*
================
DrawTris

Draws triangle outlines for debugging
================
*/
static void DrawTris (shaderCommands_t *input) {
	GL_Bind( tr.whiteImage );
	qglColor3f (1,1,1);

	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE );
	qglDepthRange( 0, 0 );

	qglDisableClientState (GL_COLOR_ARRAY);
	qglDisableClientState (GL_TEXTURE_COORD_ARRAY);

	qglVertexPointer (3, GL_FLOAT, 16, input->xyz);	// padded for SIMD

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

	#ifdef HAVE_GLES
	qglDrawElements( GL_LINE_STRIP, 
					input->numIndexes,
					GL_INDEX_TYPE,
					input->indexes );
	#else
	R_DrawElements( input->numIndexes, input->indexes );
	#endif

	if (qglUnlockArraysEXT) {
		qglUnlockArraysEXT();
		GLimp_LogComment( "glUnlockArraysEXT\n" );
	}
	qglDepthRange( 0, 1 );
}
Esempio n. 8
0
static void R_DrawElements( int numIndexes, const glIndex_t *indexes ) {
#ifdef GL_VERSION_ES_CM_1_0
	int i;
	//Com_Printf("R_DrawElements(): r_primitives %d numIndexes %d\n", r_primitives->integer, numIndexes);
	if ( r_primitives->integer != 2 && r_primitives->integer != 0 ) {
		Com_Printf("Error: R_DrawElements() not implemented on GLES for r_primitives != 2 (r_primitives %d)\n", r_primitives->integer);
		return;
	}
	
	// GLES does not support GL_UNSIGNED_INT for glDrawElements, so we'll convert values on the fly - this is SLOW, as you may imagine.
	for (i = 0; i < numIndexes; i++)
		indexes_short[i] = indexes[i];
	qglDrawElements(GL_TRIANGLES, numIndexes, GL_UNSIGNED_SHORT, indexes_short);
#else
	int		primitives;
	primitives = r_primitives->integer;

	// default is to use triangles if compiled vertex arrays are present
	if ( primitives == 0 ) {
		if ( qglLockArraysEXT ) {
			primitives = 2;
		} else {
			primitives = 1;
		}
	}


	if ( primitives == 2 ) {
		qglDrawElements( GL_TRIANGLES, 
						numIndexes,
						GL_INDEX_TYPE,
						indexes );
		return;
	}

	if ( primitives == 1 ) {
		R_DrawStripElements( numIndexes,  indexes, qglArrayElement );
		return;
	}
	
	if ( primitives == 3 ) {
		R_DrawStripElements( numIndexes,  indexes, R_ArrayElementDiscrete );
		return;
	}
#endif
	// anything else will cause no drawing
}
Esempio n. 9
0
void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex )
{
	if (glRefConfig.drawRangeElements)
		qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE)));
	else
		qglDrawElements(GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(GL_INDEX_TYPE)));
	
}
Esempio n. 10
0
/*
================
RB_DrawShadowElementsWithCounters

May not use all the indexes in the surface if caps are skipped
================
*/
void RB_DrawShadowElementsWithCounters( const srfTriangles_t *tri, int numIndexes ) {
	backEnd.pc.c_shadowElements++;
	backEnd.pc.c_shadowIndexes += numIndexes;
	backEnd.pc.c_shadowVertexes += tri->numVerts;

	if ( tri->indexCache && r_useIndexBuffers.GetBool() ) {
		qglDrawElements( GL_TRIANGLES, 
						r_singleTriangle.GetBool() ? 3 : numIndexes,
						GL_INDEX_TYPE,
						(int *)vertexCache.Position( tri->indexCache ) );
		backEnd.pc.c_vboIndexes += numIndexes;
	} else {
		if ( r_useIndexBuffers.GetBool() ) {
			vertexCache.UnbindIndex();
		}
		qglDrawElements( GL_TRIANGLES, 
						r_singleTriangle.GetBool() ? 3 : numIndexes,
						GL_INDEX_TYPE,
						tri->indexes );
	}
}
Esempio n. 11
0
/*
=================
RB_DrawArrays
=================
*/
void RB_DrawArrays (void)
{
	if (rb_vertex == 0 || rb_index == 0) // nothing to render
		return;

	GL_LockArrays (rb_vertex);
	if (glConfig.drawRangeElements)
		qglDrawRangeElementsEXT(GL_TRIANGLES, 0, rb_vertex, rb_index, GL_UNSIGNED_INT, indexArray);
	else
		qglDrawElements(GL_TRIANGLES, rb_index, GL_UNSIGNED_INT, indexArray);
	GL_UnlockArrays ();
}
Esempio n. 12
0
/*
=================
RB_DrawArrays
=================
*/
void RB_DrawArrays (GLenum polyMode)
{
	if (rb_vertex == 0 || rb_index == 0) // nothing to render
		return;

	GL_LockArrays (rb_vertex);
	if (gl_config.drawRangeElements)
		qglDrawRangeElementsEXT(polyMode, 0, rb_vertex, rb_index, GL_UNSIGNED_INT, indexArray);
	else
		qglDrawElements(polyMode, rb_index, GL_UNSIGNED_INT, indexArray);
	GL_UnlockArrays ();
}
void CMistyFog2::Render(CWorldEffectsSystem *system)
{
	if (mFadeAlpha <= 0.0)
	{
		return;
	}

	qglMatrixMode(GL_PROJECTION);
	qglPushMatrix();
    qglLoadIdentity ();
	MYgluPerspective (80.0,  1.0,  4,  2048.0);

	qglMatrixMode(GL_MODELVIEW);
	qglPushMatrix();
    qglLoadIdentity ();
    qglRotatef (-90,  1, 0, 0);	    // put Z going up
    qglRotatef (90,  0, 0, 1);	    // put Z going up
    qglRotatef (0,  1, 0, 0);
    qglRotatef (-90,  0, 1, 0);
    qglRotatef (-90,  0, 0, 1);

	qglDisable(GL_TEXTURE_2D);
	GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_ONE);
	qglShadeModel (GL_SMOOTH);

	qglColorPointer(4, GL_FLOAT, 0, mColors);
	qglEnableClientState(GL_COLOR_ARRAY);

	qglVertexPointer( 3, GL_FLOAT, 0, mVerts );
	qglEnableClientState(GL_VERTEX_ARRAY);

	if (qglLockArraysEXT) 
	{
		qglLockArraysEXT(0, MISTYFOG_HEIGHT*MISTYFOG_WIDTH);
	}
	qglDrawElements(GL_QUADS, (MISTYFOG_HEIGHT-1)*(MISTYFOG_WIDTH-1)*4, GL_UNSIGNED_INT, mIndexes);
	if ( qglUnlockArraysEXT ) 
	{
		qglUnlockArraysEXT();
	}

	qglDisableClientState(GL_COLOR_ARRAY);
//	qglDisableClientState(GL_VERTEX_ARRAY);	 backend doesn't ever re=enable this properly

	qglPopMatrix();
	qglMatrixMode(GL_PROJECTION);
	qglPopMatrix();
	qglMatrixMode(GL_MODELVIEW);	// bug somewhere in the backend which requires this
}
Esempio n. 14
0
/*
=================
RB_ShadowFinish

Darken everything that is is a shadow volume.
We have to delay this until everything has been shadowed,
because otherwise shadows from different body parts would
overlap and double darken.
=================
*/
void RB_ShadowFinish( void ) {
	vec3_t quad[4] = {
		{-100.0f,  100.0f, -10.0f},
		{ 100.0f,  100.0f, -10.0f},
		{ 100.0f, -100.0f, -10.0f},
		{-100.0f, -100.0f, -10.0f}
	};
	glIndex_t indicies[6] = { 0, 1, 2, 0, 3, 2 };

	if ( r_shadows->integer != 2 ) {
		return;
	}
	if ( glConfig.stencilBits < 4 ) {
		return;
	}
	qglEnable( GL_STENCIL_TEST );
	qglStencilFunc( GL_NOTEQUAL, 0, 255 );

	qglDisable (GL_CLIP_PLANE0);
	qglDisable (GL_CULL_FACE);

	GL_Bind( tr.whiteImage );

    qglLoadIdentity ();

	glColor4f( 0.6f, 0.6f, 0.6f, 1.0f );
	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO );

//	glColor4f( 1, 0, 0, 1 );
//	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );

	qglVertexPointer(3, GL_FLOAT, 0, quad);
	qglDrawElements(GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies);

	glColor4f(1,1,1,1);
	qglDisable( GL_STENCIL_TEST );
}
Esempio n. 15
0
/*
===============
RB_ShowImages

Draw all the images to the screen, on top of whatever
was there.  This is used to test for texture thrashing.

Also called by RE_EndRegistration
===============
*/
void RB_ShowImages( void ) {
	int		i;
	image_t	*image;
	float	x, y, w, h;
	int		start, end;
#ifdef VCMODS_OPENGLES
	vec2_t  texcoords[4] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} };
	vec2_t  verts[4];
	glIndex_t indicies[6] = { 0, 1, 2, 0, 3, 2};
#endif

	if ( !backEnd.projection2D ) {
		RB_SetGL2D();
	}

	qglClear( GL_COLOR_BUFFER_BIT );

	qglFinish();

	start = ri.Milliseconds();
#ifdef VCMODS_OPENGLES
	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
#endif

	for ( i=0 ; i<tr.numImages ; i++ ) {
		image = tr.images[i];

		w = glConfig.vidWidth / 20;
		h = glConfig.vidHeight / 15;
		x = i % 20 * w;
		y = i / 20 * h;

		// show in proportional size in mode 2
		if ( r_showImages->integer == 2 ) {
			w *= image->uploadWidth / 512.0f;
			h *= image->uploadHeight / 512.0f;
		}

#ifdef VCMODS_OPENGLES
		verts[0][0] = x;  verts[0][1] = y;
		verts[1][0] = x+w;  verts[1][1] = y;
		verts[2][0] = x+w;  verts[2][1] = y+h;
		verts[3][0] = x;  verts[3][1] = y+h;

		qglTexCoordPointer( 2, GL_FLOAT, 0, texcoords );
		qglVertexPointer  ( 2, GL_FLOAT, 0, verts );
		qglDrawElements( GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies );
#else
		GL_Bind( image );
		qglBegin (GL_QUADS);
		qglTexCoord2f( 0, 0 );
		qglVertex2f( x, y );
		qglTexCoord2f( 1, 0 );
		qglVertex2f( x + w, y );
		qglTexCoord2f( 1, 1 );
		qglVertex2f( x + w, y + h );
		qglTexCoord2f( 0, 1 );
		qglVertex2f( x, y + h );
		qglEnd();
#endif
	}

#ifdef VCMODS_OPENGLES
	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif
	qglFinish();

	end = ri.Milliseconds();
	ri.Printf( PRINT_ALL, "%i msec to draw all images\n", end - start );

}
Esempio n. 16
0
void R_RenderShadowEdges( void ) {
	int		i;
	int		c;
	int		j;
	int		i2;
#if 0
	int		c_edges, c_rejected;
	int		c2, k;
	int		hit[2];
#endif
#ifdef _STENCIL_REVERSE
	int		numTris;
	int		o1, o2, o3;
#endif

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
#if 0
	c_edges = 0;
	c_rejected = 0;
#endif

#ifdef HAVE_GLES
	idx = 0;
#endif

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			//with this system we can still get edges shared by more than 2 tris which
			//produces artifacts including seeing the shadow through walls. So for now
			//we are going to render all edges even though it is a tiny bit slower. -rww
#if 1
			i2 = edgeDefs[ i ][ j ].i2;
			#ifdef HAVE_GLES
			// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRIANGLE_STRIP call
			// even if it seems less efficiant, it's faster on the PANDORA
			indexes[idx++] = i;
			indexes[idx++] = i + tess.numVertexes;
			indexes[idx++] = i2;
			indexes[idx++] = i2;
			indexes[idx++] = i + tess.numVertexes;
			indexes[idx++] = i2 + tess.numVertexes;
			#else
			qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
			qglEnd();
			#endif
#else
			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if (hit[1] != 1)
			{
				qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
				qglEnd();
				c_edges++;
			} else {
				c_rejected++;
			}
#endif
		}
	}

#ifdef _STENCIL_REVERSE
	//Carmack Reverse<tm> method requires that volumes
	//be capped properly -rww
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ )
	{
		if ( !facing[i] )
		{
			continue;
		}

		o1 = tess.indexes[ i*3 + 0 ];
		o2 = tess.indexes[ i*3 + 1 ];
		o3 = tess.indexes[ i*3 + 2 ];

		#ifdef HAVE_GLES
		indexes[idx++]=o1;
		indexes[idx++]=o2;
		indexes[idx++]=o3;
		indexes[idx++]=o3 + tess.numVertexes;
		indexes[idx++]=o2 + tess.numVertexes;
		indexes[idx++]=o1 + tess.numVertexes;
		#else
		qglBegin(GL_TRIANGLES);
			qglVertex3fv(tess.xyz[o1]);
			qglVertex3fv(tess.xyz[o2]);
			qglVertex3fv(tess.xyz[o3]);
		qglEnd();
		qglBegin(GL_TRIANGLES);
			qglVertex3fv(tess.xyz[o3 + tess.numVertexes]);
			qglVertex3fv(tess.xyz[o2 + tess.numVertexes]);
			qglVertex3fv(tess.xyz[o1 + tess.numVertexes]);
		qglEnd();
		#endif
	}
	#ifdef HAVE_GLES
	qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
	#endif

#endif
}
void R_RenderShadowEdges( void ) {
	int		i;

#if 0
	int		numTris;

	// dumb way -- render every triangle's edges
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ ) {
		int		i1, i2, i3;

		if ( !facing[i] ) {
			continue;
		}

		i1 = tess.indexes[ i*3 + 0 ];
		i2 = tess.indexes[ i*3 + 1 ];
		i3 = tess.indexes[ i*3 + 2 ];

		qglBegin( GL_TRIANGLE_STRIP );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i2 ] );
		qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i3 ] );
		qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglEnd();
	}
#else
	int		c, c2;
	int		j, k;
	int		i2;
	int		c_edges, c_rejected;
	int		hit[2];

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
	c_edges = 0;
	c_rejected = 0;

	unsigned short indicies[4];

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if ( hit[ 1 ] == 0 ) {
				indicies[0] = i;
				indicies[1] = i + tess.numVertexes;
				indicies[2] = i2;
				indicies[3] = i2 + tess.numVertexes;

				qglVertexPointer(3, GL_FLOAT, 16, tess.xyz);
				qglDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indicies);
				c_edges++;
			} else {
				c_rejected++;
			}
		}
	}
#endif
}
Esempio n. 18
0
/*
* RB_DrawElementsReal
*/
void RB_DrawElementsReal( rbDrawElements_t *de )
{
    int firstVert, numVerts, firstElem, numElems;
    int numInstances;

    if( ! ( r_drawelements->integer || rb.currentEntity == &rb.nullEnt ) || !de )
        return;

    RB_ApplyScissor();

    numVerts = de->numVerts;
    numElems = de->numElems;
    firstVert = de->firstVert;
    firstElem = de->firstElem;
    numInstances = de->numInstances;

    if( numInstances ) {
        if( glConfig.ext.instanced_arrays ) {
            // the instance data is contained in vertex attributes
            qglDrawElementsInstancedARB( rb.primitive, numElems, GL_UNSIGNED_SHORT,
                                         (GLvoid *)(firstElem * sizeof( elem_t )), numInstances );

            rb.stats.c_totalDraws++;
        } else if( glConfig.ext.draw_instanced ) {
            int i, numUInstances = 0;

            // manually update uniform values for instances for currently bound program,
            // respecting the MAX_GLSL_UNIFORM_INSTANCES limit
            for( i = 0; i < numInstances; i += numUInstances ) {
                numUInstances = min( numInstances - i, MAX_GLSL_UNIFORM_INSTANCES );

                RB_SetInstanceData( numUInstances, rb.drawInstances + i );

                qglDrawElementsInstancedARB( rb.primitive, numElems, GL_UNSIGNED_SHORT,
                                             (GLvoid *)(firstElem * sizeof( elem_t )), numUInstances );

                rb.stats.c_totalDraws++;
            }
        } else {
            int i;

            // manually update uniform values for instances for currently bound program,
            // one by one
            for( i = 0; i < numInstances; i++ ) {
                RB_SetInstanceData( 1, rb.drawInstances + i );

                if( glConfig.ext.draw_range_elements ) {
                    qglDrawRangeElementsEXT( rb.primitive,
                                             firstVert, firstVert + numVerts - 1, numElems,
                                             GL_UNSIGNED_SHORT, (GLvoid *)(firstElem * sizeof( elem_t )) );
                } else {
                    qglDrawElements( rb.primitive, numElems, GL_UNSIGNED_SHORT,
                                     (GLvoid *)(firstElem * sizeof( elem_t )) );
                }

                rb.stats.c_totalDraws++;
            }
        }
    }
    else {
        numInstances = 1;

        if( glConfig.ext.draw_range_elements ) {
            qglDrawRangeElementsEXT( rb.primitive,
                                     firstVert, firstVert + numVerts - 1, numElems,
                                     GL_UNSIGNED_SHORT, (GLvoid *)(firstElem * sizeof( elem_t )) );
        } else {
            qglDrawElements( rb.primitive, numElems, GL_UNSIGNED_SHORT,
                             (GLvoid *)(firstElem * sizeof( elem_t )) );
        }

        rb.stats.c_totalDraws++;
    }

    rb.stats.c_totalVerts += numVerts * numInstances;
    if( rb.primitive == GL_TRIANGLES ) {
        rb.stats.c_totalTris += numElems * numInstances / 3;
    }
}
Esempio n. 19
0
void RB_DoShadowTessEnd( vec3_t lightPos )
{
	int		i;
	int		numTris;
	vec3_t	lightDir;

	// we can only do this if we have enough space in the vertex buffers
	if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) {
		return;
	}

	if ( glConfig.stencilBits < 4 ) {
		return;
	}

#if 1 //controlled method - try to keep shadows in range so they don't show through so much -rww
	vec3_t	worldxyz;
	vec3_t	entLight;
	float	groundDist;

	VectorCopy( backEnd.currentEntity->lightDir, entLight );
	entLight[2] = 0.0f;
	VectorNormalize(entLight);

	//Oh well, just cast them straight down no matter what onto the ground plane.
	//This presets no chance of screwups and still looks better than a stupid
	//shader blob.
	VectorSet(lightDir, entLight[0]*0.3f, entLight[1]*0.3f, 1.0f);
	// project vertexes away from light direction
	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		//add or.origin to vert xyz to end up with world oriented coord, then figure
		//out the ground pos for the vert to project the shadow volume to
		VectorAdd(tess.xyz[i], backEnd.ori.origin, worldxyz);
		groundDist = worldxyz[2] - backEnd.currentEntity->e.shadowPlane;
		groundDist += 16.0f; //fudge factor
		VectorMA( tess.xyz[i], -groundDist, lightDir, tess.xyz[i+tess.numVertexes] );
	}
#else
	if (lightPos)
	{
		for ( i = 0 ; i < tess.numVertexes ; i++ )
		{
			tess.xyz[i+tess.numVertexes][0] = tess.xyz[i][0]+(( tess.xyz[i][0]-lightPos[0] )*128.0f);
			tess.xyz[i+tess.numVertexes][1] = tess.xyz[i][1]+(( tess.xyz[i][1]-lightPos[1] )*128.0f);
			tess.xyz[i+tess.numVertexes][2] = tess.xyz[i][2]+(( tess.xyz[i][2]-lightPos[2] )*128.0f);
		}
	}
	else
	{
		VectorCopy( backEnd.currentEntity->lightDir, lightDir );

		// project vertexes away from light direction
		for ( i = 0 ; i < tess.numVertexes ; i++ ) {
			VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] );
		}
	}
#endif
	// decide which triangles face the light
	memset( numEdgeDefs, 0, 4 * tess.numVertexes );

	numTris = tess.numIndexes / 3;
	for ( i = 0 ; i < numTris ; i++ ) {
		int		i1, i2, i3;
		vec3_t	d1, d2, normal;
		float	*v1, *v2, *v3;
		float	d;

		i1 = tess.indexes[ i*3 + 0 ];
		i2 = tess.indexes[ i*3 + 1 ];
		i3 = tess.indexes[ i*3 + 2 ];

		v1 = tess.xyz[ i1 ];
		v2 = tess.xyz[ i2 ];
		v3 = tess.xyz[ i3 ];

		if (!lightPos)
		{
			VectorSubtract( v2, v1, d1 );
			VectorSubtract( v3, v1, d2 );
			CrossProduct( d1, d2, normal );

			d = DotProduct( normal, lightDir );
		}
		else
		{
			float planeEq[4];
			planeEq[0] = v1[1]*(v2[2]-v3[2]) + v2[1]*(v3[2]-v1[2]) + v3[1]*(v1[2]-v2[2]);
			planeEq[1] = v1[2]*(v2[0]-v3[0]) + v2[2]*(v3[0]-v1[0]) + v3[2]*(v1[0]-v2[0]);
			planeEq[2] = v1[0]*(v2[1]-v3[1]) + v2[0]*(v3[1]-v1[1]) + v3[0]*(v1[1]-v2[1]);
			planeEq[3] = -( v1[0]*( v2[1]*v3[2] - v3[1]*v2[2] ) +
						v2[0]*(v3[1]*v1[2] - v1[1]*v3[2]) +
						v3[0]*(v1[1]*v2[2] - v2[1]*v1[2]) );

			d = planeEq[0]*lightPos[0]+
				planeEq[1]*lightPos[1]+
				planeEq[2]*lightPos[2]+
				planeEq[3];
		}

		if ( d > 0 ) {
			facing[ i ] = 1;
		} else {
			facing[ i ] = 0;
		}

		// create the edges
		R_AddEdgeDef( i1, i2, facing[ i ] );
		R_AddEdgeDef( i2, i3, facing[ i ] );
		R_AddEdgeDef( i3, i1, facing[ i ] );
	}

	GL_Bind( tr.whiteImage );
	//qglEnable( GL_CULL_FACE );
	GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );

#ifndef _DEBUG_STENCIL_SHADOWS
	qglColor3f( 0.2f, 0.2f, 0.2f );

	// don't write to the color buffer
	qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );

	qglEnable( GL_STENCIL_TEST );
	qglStencilFunc( GL_ALWAYS, 1, 255 );
#else
	qglColor3f( 1.0f, 0.0f, 0.0f );
	qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	//qglDisable(GL_DEPTH_TEST);
#endif

	#ifdef HAVE_GLES
	GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
	if (text)
		qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
	if (glcol)
		qglDisableClientState( GL_COLOR_ARRAY );
	qglVertexPointer (3, GL_FLOAT, 16, tess.xyz);
	#endif

#ifdef _STENCIL_REVERSE
	qglDepthFunc(GL_LESS);

	//now using the Carmack Reverse<tm> -rww
	if ( backEnd.viewParms.isMirror ) {
		//qglCullFace( GL_BACK );
		GL_Cull(CT_BACK_SIDED);
		qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );

		R_RenderShadowEdges();

		//qglCullFace( GL_FRONT );
		GL_Cull(CT_FRONT_SIDED);
		qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );

		#ifdef HAVE_GLES
		qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
		#else
		R_RenderShadowEdges();
		#endif
	} else {
		//qglCullFace( GL_FRONT );
		GL_Cull(CT_FRONT_SIDED);
		qglStencilOp( GL_KEEP, GL_INCR, GL_KEEP );

		R_RenderShadowEdges();

		//qglCullFace( GL_BACK );
		GL_Cull(CT_BACK_SIDED);
		qglStencilOp( GL_KEEP, GL_DECR, GL_KEEP );

		#ifdef HAVE_GLES
		qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
		#else
		R_RenderShadowEdges();
		#endif
	}

	qglDepthFunc(GL_LEQUAL);
#else
	// mirrors have the culling order reversed
	if ( backEnd.viewParms.isMirror ) {
		qglCullFace( GL_FRONT );
		qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );

		R_RenderShadowEdges();

		qglCullFace( GL_BACK );
		qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );

		#ifdef HAVE_GLES
		qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
		#else
		R_RenderShadowEdges();
		#endif
	} else {
		qglCullFace( GL_BACK );
		qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );

		R_RenderShadowEdges();

		qglCullFace( GL_FRONT );
		qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR );

		#ifdef HAVE_GLES
		qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
		#else
		R_RenderShadowEdges();
		#endif
	}
#endif

	// reenable writing to the color buffer
	qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );

	#ifdef HAVE_GLES
	if (text)
		qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
	if (glcol)
		qglEnableClientState( GL_COLOR_ARRAY );
	#endif

#ifdef _DEBUG_STENCIL_SHADOWS
	qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
}
Esempio n. 20
0
void R_RenderShadowEdges( void ) {
	int		i;

#if 0
	int		numTris;

	// dumb way -- render every triangle's edges
	numTris = tess.numIndexes / 3;

	for ( i = 0 ; i < numTris ; i++ ) {
		int		i1, i2, i3;

		if ( !facing[i] ) {
			continue;
		}

		i1 = tess.indexes[ i*3 + 0 ];
		i2 = tess.indexes[ i*3 + 1 ];
		i3 = tess.indexes[ i*3 + 2 ];

		qglBegin( GL_TRIANGLE_STRIP );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i2 ] );
		qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i3 ] );
		qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] );
		qglVertex3fv( tess.xyz[ i1 ] );
		qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] );
		qglEnd();
	}
#else
	int		c, c2;
	int		j, k;
	int		i2;
	int		c_edges, c_rejected;
	int		hit[2];
	#ifdef HAVE_GLES
	idx = 0;
	#endif

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
	c_edges = 0;
	c_rejected = 0;

	for ( i = 0 ; i < tess.numVertexes ; i++ ) {
		c = numEdgeDefs[ i ];
		for ( j = 0 ; j < c ; j++ ) {
			if ( !edgeDefs[ i ][ j ].facing ) {
				continue;
			}

			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[ i ][ j ].i2;
			c2 = numEdgeDefs[ i2 ];
			for ( k = 0 ; k < c2 ; k++ ) {
				if ( edgeDefs[ i2 ][ k ].i2 == i ) {
					hit[ edgeDefs[ i2 ][ k ].facing ]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if ( hit[ 1 ] == 0 ) {
				#ifdef HAVE_GLES
				// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRAINGLE_STRIP call
				// even if it seems less efficiant, it's faster on the PANDORA
				indexes[idx++] = i;
				indexes[idx++] = i + tess.numVertexes;
				indexes[idx++] = i2;
				indexes[idx++] = i2;
				indexes[idx++] = i + tess.numVertexes;
				indexes[idx++] = i2 + tess.numVertexes;
				#else
				qglBegin( GL_TRIANGLE_STRIP );
				qglVertex3fv( tess.xyz[ i ] );
				qglVertex3fv( tess.xyz[ i + tess.numVertexes ] );
				qglVertex3fv( tess.xyz[ i2 ] );
				qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] );
				qglEnd();
				#endif
				c_edges++;
			} else {
				c_rejected++;
			}
		}
	}
	#ifdef HAVE_GLES
	qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
	#endif

#endif
}
Esempio n. 21
0
/*
 * RE_StretchRaw
 *
 * FIXME: not exactly backend
 * Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
 * Used for cinematics.
 */
void
RE_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qbool dirty)
{
	int i, j;
	int start, end;
	shaderProgram_t *sp = &tr.textureColorShader;
	Vec4 color;

	if(!tr.registered){
		return;
	}
	R_SyncRenderThread();

	/* we definately want to sync every frame for the cinematics */
	qglFinish();

	start = 0;
	if(r_speeds->integer){
		start = ri.Milliseconds();
	}

	/* make sure rows and cols are powers of 2 */
	for(i = 0; (1 << i) < cols; i++){
	}
	for(j = 0; (1 << j) < rows; j++){
	}
	if((1 << i) != cols || (1 << j) != rows){
		ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
	}

	GL_Bind(tr.scratchImage[client]);

	/* if the scratchImage isn't in the format we want, specify it as a new texture */
	if(cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height){
		tr.scratchImage[client]->width	= tr.scratchImage[client]->uploadWidth = cols;
		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
		qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}else{
		if(dirty){
			/* otherwise, just subimage upload it so that drivers can tell we are going to be changing
			 * it and don't try and do a texture compression */
			qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data);
		}
	}

	if(r_speeds->integer){
		end = ri.Milliseconds();
		ri.Printf(PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start);
	}

	/* FIXME: HUGE hack */
	if(glRefConfig.framebufferObject && !glState.currentFBO){
		if(backEnd.framePostProcessed){
			FBO_Bind(tr.screenScratchFbo);
		}else{
			FBO_Bind(tr.renderFbo);
		}
	}

	RB_SetGL2D();

	tess.numIndexes = 0;
	tess.numVertexes = 0;
	tess.firstIndex = 0;

	tess.xyz[tess.numVertexes][0]	= x;
	tess.xyz[tess.numVertexes][1]	= y;
	tess.xyz[tess.numVertexes][2]	= 0;
	tess.xyz[tess.numVertexes][3]	= 1;
	tess.texCoords[tess.numVertexes][0][0]	= 0.5f / cols;
	tess.texCoords[tess.numVertexes][0][1]	= 0.5f / rows;
	tess.texCoords[tess.numVertexes][0][2]	= 0;
	tess.texCoords[tess.numVertexes][0][3]	= 1;
	tess.numVertexes++;

	tess.xyz[tess.numVertexes][0]	= x + w;
	tess.xyz[tess.numVertexes][1]	= y;
	tess.xyz[tess.numVertexes][2]	= 0;
	tess.xyz[tess.numVertexes][3]	= 1;
	tess.texCoords[tess.numVertexes][0][0]	= (cols - 0.5f) / cols;
	tess.texCoords[tess.numVertexes][0][1]	= 0.5f / rows;
	tess.texCoords[tess.numVertexes][0][2]	= 0;
	tess.texCoords[tess.numVertexes][0][3]	= 1;
	tess.numVertexes++;

	tess.xyz[tess.numVertexes][0]	= x + w;
	tess.xyz[tess.numVertexes][1]	= y + h;
	tess.xyz[tess.numVertexes][2]	= 0;
	tess.xyz[tess.numVertexes][3]	= 1;
	tess.texCoords[tess.numVertexes][0][0]	= (cols - 0.5f) / cols;
	tess.texCoords[tess.numVertexes][0][1]	= (rows - 0.5f) / rows;
	tess.texCoords[tess.numVertexes][0][2]	= 0;
	tess.texCoords[tess.numVertexes][0][3]	= 1;
	tess.numVertexes++;

	tess.xyz[tess.numVertexes][0]	= x;
	tess.xyz[tess.numVertexes][1]	= y + h;
	tess.xyz[tess.numVertexes][2]	= 0;
	tess.xyz[tess.numVertexes][3]	= 1;
	tess.texCoords[tess.numVertexes][0][0]	= 0.5f / cols;
	tess.texCoords[tess.numVertexes][0][1]	= (rows - 0.5f) / rows;
	tess.texCoords[tess.numVertexes][0][2]	= 0;
	tess.texCoords[tess.numVertexes][0][3]	= 1;
	tess.numVertexes++;

	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 1;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 0;
	tess.indexes[tess.numIndexes++] = 2;
	tess.indexes[tess.numIndexes++] = 3;

	/* FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function */
	RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD);

	sp = &tr.textureColorShader;

	GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD);

	GLSL_BindProgram(sp);

	GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX,
		glState.modelviewProjection);
	setv34(color, 1, 1, 1, 1);
	GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color);

	qglDrawElements(GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(0));

	/* R_BindNullVBO();
	 * R_BindNullIBO(); */

	tess.numIndexes = 0;
	tess.numVertexes = 0;
	tess.firstIndex = 0;
}
Esempio n. 22
0
//R_DRAWCEL
static void R_DrawCel( int numIndexes, const glIndex_t *indexes ) {
	int		primitives;
	
	if(
		//. ignore the 2d projection. do i smell the HUD?
		(backEnd.projection2D == qtrue) ||
		//. ignore general entitites that are sprites. SEE NOTE #3.
		(backEnd.currentEntity->e.reType == RT_SPRITE) ||
		//. ignore these liquids. why? ever see liquid with tris on the surface? exactly. SEE NOTE #4.
		(tess.shader->contentFlags & (CONTENTS_WATER | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_FOG)) ||
		//. ignore things that are two sided, meaning mostly things that have transparency. SEE NOTE #1.		
		(tess.shader->cullType == CT_TWO_SIDED)
		
		) {
		return;
	}

	primitives = r_primitives->integer;

	// default is to use triangles if compiled vertex arrays are present
	if ( primitives == 0 ) {
		if ( qglLockArraysEXT ) {
			primitives = 2;
		} else {
			primitives = 1;
		}
	}

	//. correction for mirrors. SEE NOTE #2.
	if(backEnd.viewParms.isMirror == qtrue) { qglCullFace (GL_FRONT); }
	else { qglCullFace (GL_BACK); }	

	qglEnable (GL_BLEND);
	qglBlendFunc (GL_SRC_ALPHA ,GL_ONE_MINUS_SRC_ALPHA);
	qglColor3f (0.0f,0.0f,0.0f);
	qglLineWidth( (float) r_celoutline->integer );	

	if(primitives == 2) {
		qglDrawElements( GL_TRIANGLES, numIndexes, GL_INDEX_TYPE, indexes );
	} else if(primitives == 1) {
		R_DrawStripElements( numIndexes,  indexes, qglArrayElement );
	} else if(primitives == 3) {
		R_DrawStripElements( numIndexes,  indexes, R_ArrayElementDiscrete );
	}

	//. correction for mirrors. SEE NOTE #2.
	if(backEnd.viewParms.isMirror == qtrue) { qglCullFace (GL_BACK); }
	else { qglCullFace (GL_FRONT); }
	
	qglDisable (GL_BLEND);
	
	return;

/* Notes

1. this is going to be a pain in the arse. it fixes things like light `beams` from being cel'd but it
also will ignore any other shader set with no culling. this usually is everything that is translucent.
but this is a good hack to clean up the screen untill something more selective comes along. or who knows
group desision might actually be that this is liked. if so i take back calling it a `hack`, lol.
	= bob.

2. mirrors display correctly because the normals of the displayed are inverted of normal space. so to
continue to have them display correctly, we must invert them inversely from a normal inversion.
	= bob.
	
3. this turns off a lot of space hogging sprite cel outlines. picture if you will five people in a small
room all shooting rockets. each smoke puff gets a big black square around it, each explosion gets a big
black square around it, and now nobody can see eachother because everyones screen is solid black.
	= bob.

4. ignoring liquids means you will not get black tris lines all over the top of your liquid. i put this in
after seeing the lava on q3dm7 and water on q3ctf2 that had black lines all over the top, making the
liquids look solid instead of... liquid.
	= bob.

*/
}
Esempio n. 23
0
void R_RenderShadowEdges(void)
{
	int i;
	int c, c2;
	int j, k;
	int i2;
	int c_edges, c_rejected;
	int hit[2];

	// an edge is NOT a silhouette edge if its face doesn't face the light,
	// or if it has a reverse paired edge that also faces the light.
	// A well behaved polyhedron would have exactly two faces for each edge,
	// but lots of models have dangling edges or overfanned edges
	c_edges    = 0;
	c_rejected = 0;
	idx        = 0;

	for (i = 0 ; i < tess.numVertexes ; i++)
	{
		c = numEdgeDefs[i];
		for (j = 0 ; j < c ; j++)
		{
			if (!edgeDefs[i][j].facing)
			{
				continue;
			}

			hit[0] = 0;
			hit[1] = 0;

			i2 = edgeDefs[i][j].i2;
			c2 = numEdgeDefs[i2];
			for (k = 0 ; k < c2 ; k++)
			{
				if (edgeDefs[i2][k].i2 == i)
				{
					hit[edgeDefs[i2][k].facing]++;
				}
			}

			// if it doesn't share the edge with another front facing
			// triangle, it is a sil edge
			if (hit[1] == 0)
			{
				// A single drawing call is better than many. So I prefer a singe TRIANGLES call than many TRAINGLE_STRIP call
				// even if it seems less efficiant, it's faster on the PANDORA
				indexes[idx++] = i;
				indexes[idx++] = i + tess.numVertexes;
				indexes[idx++] = i2;
				indexes[idx++] = i2;
				indexes[idx++] = i + tess.numVertexes;
				indexes[idx++] = i2 + tess.numVertexes;
				c_edges++;
			}
			else
			{
				c_rejected++;
			}
		}
	}
	qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
}
Esempio n. 24
0
/*
=================
RB_ShadowTessEnd

triangleFromEdge[ v1 ][ v2 ]

  set triangle from edge( v1, v2, tri )
  if ( facing[ triangleFromEdge[ v1 ][ v2 ] ] && !facing[ triangleFromEdge[ v2 ][ v1 ] ) {
  }
=================
*/
void RB_ShadowTessEnd(void)
{
	int    i;
	int    numTris;
	vec3_t lightDir;

	// we can only do this if we have enough space in the vertex buffers
	if (tess.numVertexes >= tess.maxShaderVerts / 2)
	{
		return;
	}

	if (glConfig.stencilBits < 4)
	{
		return;
	}

	VectorCopy(backEnd.currentEntity->lightDir, lightDir);

	// project vertexes away from light direction
	for (i = 0 ; i < tess.numVertexes ; i++)
	{
		VectorMA(tess.xyz[i].v, -512, lightDir, tess.xyz[i + tess.numVertexes].v);
	}

	// decide which triangles face the light
	memset(numEdgeDefs, 0, 4 * tess.numVertexes);

	numTris = tess.numIndexes / 3;

	{
		int    i1, i2, i3;
		vec3_t d1, d2, normal;
		float  *v1, *v2, *v3;
		float  d;

		for (i = 0 ; i < numTris ; i++)
		{
			i1 = tess.indexes[i * 3 + 0];
			i2 = tess.indexes[i * 3 + 1];
			i3 = tess.indexes[i * 3 + 2];

			v1 = tess.xyz[i1].v;
			v2 = tess.xyz[i2].v;
			v3 = tess.xyz[i3].v;

			VectorSubtract(v2, v1, d1);
			VectorSubtract(v3, v1, d2);
			CrossProduct(d1, d2, normal);

			d = DotProduct(normal, lightDir);
			if (d > 0)
			{
				facing[i] = 1;
			}
			else
			{
				facing[i] = 0;
			}

			// create the edges
			R_AddEdgeDef(i1, i2, facing[i]);
			R_AddEdgeDef(i2, i3, facing[i]);
			R_AddEdgeDef(i3, i1, facing[i]);
		}
	}


	// draw the silhouette edges

	GL_Bind(tr.whiteImage);
	qglEnable(GL_CULL_FACE);
	GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO);
	qglColor3f(0.2f, 0.2f, 0.2f);

	// don't write to the color buffer
	qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

	qglEnable(GL_STENCIL_TEST);
	qglStencilFunc(GL_ALWAYS, 1, 255);

	qglVertexPointer(3, GL_FLOAT, 16, tess.xyz);
	GLboolean text  = qglIsEnabled(GL_TEXTURE_COORD_ARRAY);
	GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY);
	if (text)
	{
		qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
	}
	if (glcol)
	{
		qglDisableClientState(GL_COLOR_ARRAY);
	}
	// mirrors have the culling order reversed
	if (backEnd.viewParms.isMirror)
	{
		qglCullFace(GL_FRONT);
		qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);

		R_RenderShadowEdges();

		qglCullFace(GL_BACK);
		qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);

		qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
	}
	else
	{
		qglCullFace(GL_BACK);
		qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);

		R_RenderShadowEdges();

		qglCullFace(GL_FRONT);
		qglStencilOp(GL_KEEP, GL_KEEP, GL_DECR);

		qglDrawElements(GL_TRIANGLES, idx, GL_UNSIGNED_SHORT, indexes);
	}

	if (text)
	{
		qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
	}
	if (glcol)
	{
		qglEnableClientState(GL_COLOR_ARRAY);
	}
	// reenable writing to the color buffer
	qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
Esempio n. 25
0
void R_DrawSkyBox (void)
{
	int		i;
	float skyM[16];
	vec_t	*v, *st;

	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

		R_RotateMatrix(skyM, r_WorldViewMatrix, r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);
	} else {
		skyM[0]  = r_WorldViewMatrix[0];
		skyM[1]  = r_WorldViewMatrix[1];
		skyM[2]  = r_WorldViewMatrix[2];
		skyM[4]  = r_WorldViewMatrix[4];
		skyM[5]  = r_WorldViewMatrix[5];
		skyM[6]  = r_WorldViewMatrix[6];
		skyM[8]  = r_WorldViewMatrix[8];
		skyM[9]  = r_WorldViewMatrix[9];
		skyM[10] = r_WorldViewMatrix[10];
		skyM[3] = skyM[7] = skyM[11] = skyM[12] = skyM[13] = skyM[14] = 0.0f;
		skyM[15] = 1.0f;
	}

	qglLoadMatrixf( skyM );

	qglTexCoordPointer( 2, GL_FLOAT, 0, r_arrays.tcoords );
	for (i = 0; i < 6; i++)
	{
		if (skyrotate)
		{	// hack, forces full sky to draw when rotating
			skymins[0][i] =	skymins[1][i] = -1;
			skymaxs[0][i] =	skymaxs[1][i] = 1;
		}
		else if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i])
			continue;

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

		st = r_arrays.tcoords[0];
		v = r_arrays.vertices;
		MakeSkyVec (skymins[0][i], skymins[1][i], i, v, st);
		MakeSkyVec (skymins[0][i], skymaxs[1][i], i, v+=3, st+=2);
		MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i, v+=3, st+=2);
		MakeSkyVec (skymaxs[0][i], skymins[1][i], i, v+=3, st+=2);
		if(gl_state.compiledVertexArray) {
			qglLockArraysEXT( 0, 4 );
			qglDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, r_arrays.indices );
			qglUnlockArraysEXT ();
		} else {
			qglDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, r_arrays.indices );
		}
	}

	qglLoadMatrixf(r_WorldViewMatrix);
}
Esempio n. 26
0
/*
=============
RE_StretchRaw

FIXME: not exactly backend
Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle.
Used for cinematics.
=============
*/
void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
	int			i, j;
	int			start, end;
#ifdef VCMODS_OPENGLES
	vec2_t		texcoords[4];
	vec2_t		verts[4];
	glIndex_t	indicies[6] = {0, 1, 2, 0, 3, 2};
#endif

	if ( !tr.registered ) {
		return;
	}
	R_SyncRenderThread();

	// we definately want to sync every frame for the cinematics
	qglFinish();

	start = end = 0;
	if ( r_speeds->integer ) {
		start = ri.Milliseconds();
	}

	// make sure rows and cols are powers of 2
	for ( i = 0 ; ( 1 << i ) < cols ; i++ ) {
	}
	for ( j = 0 ; ( 1 << j ) < rows ; j++ ) {
	}
	if ( ( 1 << i ) != cols || ( 1 << j ) != rows) {
		ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
	}

	GL_Bind( tr.scratchImage[client] );

	// if the scratchImage isn't in the format we want, specify it as a new texture
	if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
		tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
		tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
#ifdef VCMODS_OPENGLES
      //don't do qglTexImage2D as this may end up doing a compressed image
      //on which we are not allowed to do further sub images
		glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#else
		qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
#endif
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
		qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
	} else {
		if (dirty) {
			// otherwise, just subimage upload it so that drivers can tell we are going to be changing
			// it and don't try and do a texture compression
			qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
		}
	}

	if ( r_speeds->integer ) {
		end = ri.Milliseconds();
		ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start );
	}

	RB_SetGL2D();

#ifdef VCMODS_OPENGLES
	qglColor4f( tr.identityLight, tr.identityLight, tr.identityLight, 1.0f );

	verts[0][0] = x;  verts[0][1] = y;
	verts[1][0] = x+w;  verts[1][1] = y;
	verts[2][0] = x+w;  verts[2][1] = y+h;
	verts[3][0] = x;  verts[3][1] = y+h;

	texcoords[0][0] = 0.5f/cols;      texcoords[0][1] = 0.5f/rows;
	texcoords[1][0] = (cols-0.5f)/cols;   texcoords[1][1] = 0.5f/rows;
	texcoords[2][0] = (cols-0.5f)/cols;   texcoords[2][1] = (rows-0.5f)/rows;
	texcoords[3][0] = 0.5f/cols;      texcoords[3][1] = (rows-0.5f)/rows;

	qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
	qglTexCoordPointer( 2, GL_FLOAT, 0, texcoords );
	qglVertexPointer  ( 2, GL_FLOAT, 0, verts );
	qglDrawElements( GL_TRIANGLE_STRIP, 6, GL_INDEX_TYPE, indicies );
	qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
#else
	qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight );

	qglBegin (GL_QUADS);
	qglTexCoord2f ( 0.5f / cols,  0.5f / rows );
	qglVertex2f (x, y);
	qglTexCoord2f ( ( cols - 0.5f ) / cols ,  0.5f / rows );
	qglVertex2f (x+w, y);
	qglTexCoord2f ( ( cols - 0.5f ) / cols, ( rows - 0.5f ) / rows );
	qglVertex2f (x+w, y+h);
	qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
	qglVertex2f (x, y+h);
	qglEnd ();
#endif
}