Beispiel #1
0
static void SetViewportAndScissor( void ) {
	GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );

	// set the window clipping
	qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, 
		backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
	qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, 
		backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight );
}
Beispiel #2
0
/*
================
RB_SetGL2D

================
*/
void	RB_SetGL2D (void) {
	mat4_t matrix;
	int width, height;

	if (backEnd.projection2D && backEnd.last2DFBO == glState.currentFBO)
		return;

	backEnd.projection2D = qtrue;
	backEnd.last2DFBO = glState.currentFBO;

	if (glState.currentFBO)
	{
		width = glState.currentFBO->width;
		height = glState.currentFBO->height;
	}
	else
	{
		width = glConfig.vidWidth;
		height = glConfig.vidHeight;
	}

	// set 2D virtual screen size
	qglViewport( 0, 0, width, height );
	qglScissor( 0, 0, width, height );

	Mat4Ortho(0, width, height, 0, 0, 1, matrix);
	GL_SetProjectionMatrix(matrix);
	Mat4Identity(matrix);
	GL_SetModelviewMatrix(matrix);

	GL_State( GLS_DEPTHTEST_DISABLE |
			  GLS_SRCBLEND_SRC_ALPHA |
			  GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );

	qglDisable( GL_CULL_FACE );
	qglDisable( GL_CLIP_PLANE0 );

	// set time for 2D shaders
	backEnd.refdef.time = ri.Milliseconds();
	backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;

	// reset color scaling
	backEnd.refdef.colorScale = 1.0f;
}
Beispiel #3
0
/*
==================
RB_RenderFlares

Because flares are simulating an occular effect, they should be drawn after
everything (all views) in the entire frame has been drawn.

Because of the way portals use the depth buffer to mark off areas, the
needed information would be lost after each view, so we are forced to draw
flares after each view.

The resulting artifact is that flares in mirrors or portals don't dim properly
when occluded by something in the main view, and portal flares that should
extend past the portal edge will be overwritten.
==================
*/
void RB_RenderFlares (void) {
	flare_t		*f;
	flare_t		**prev;
	qboolean	draw;
	mat4_t    oldmodelview, oldprojection, matrix;

	if ( !r_flares->integer ) {
		return;
	}

	if(r_flareCoeff->modified)
	{
		R_SetFlareCoeff();
		r_flareCoeff->modified = qfalse;
	}

	// Reset currentEntity to world so that any previously referenced entities
	// don't have influence on the rendering of these flares (i.e. RF_ renderer flags).
	backEnd.currentEntity = &tr.worldEntity;
	backEnd.or = backEnd.viewParms.world;

	// (SA) turned light flares back on.  must evaluate problem id had with this
	RB_AddDlightFlares();

	RB_AddCoronaFlares();

	// perform z buffer readback on each flare in this view
	draw = qfalse;
	prev = &r_activeFlares;
	while ( ( f = *prev ) != NULL ) {
		// throw out any flares that weren't added last frame
		if ( f->addedFrame < backEnd.viewParms.frameCount - 1 ) {
			*prev = f->next;
			f->next = r_inactiveFlares;
			r_inactiveFlares = f;
			continue;
		}

		// don't draw any here that aren't from this scene / portal
		f->drawIntensity = 0;
		if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
			&& f->inPortal == backEnd.viewParms.isPortal ) {
			RB_TestFlare( f );
			if ( f->drawIntensity ) {
				draw = qtrue;
			} else {
				// this flare has completely faded out, so remove it from the chain
				*prev = f->next;
				f->next = r_inactiveFlares;
				r_inactiveFlares = f;
				continue;
			}
		}

		prev = &f->next;
	}

	if ( !draw ) {
		return;		// none visible
	}

	if ( backEnd.viewParms.isPortal ) {
		qglDisable (GL_CLIP_PLANE0);
	}

	Mat4Copy(glState.projection, oldprojection);
	Mat4Copy(glState.modelview, oldmodelview);
	Mat4Identity(matrix);
	GL_SetModelviewMatrix(matrix);
	Mat4Ortho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth,
	               backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight,
	               -99999, 99999, matrix );
	GL_SetProjectionMatrix(matrix);

	for ( f = r_activeFlares ; f ; f = f->next ) {
		if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum
			&& f->inPortal == backEnd.viewParms.isPortal
			&& f->drawIntensity ) {
			RB_RenderFlare( f );
		}
	}

	GL_SetProjectionMatrix(oldprojection);
	GL_SetModelviewMatrix(oldmodelview);
}
Beispiel #4
0
/*
 * RB_RenderDrawSurfList
 */
void
RB_RenderDrawSurfList(drawSurf_t *drawSurfs, int numDrawSurfs)
{
	material_t	*shader, *oldShader;
	int		fogNum, oldFogNum;
	int		entityNum, oldEntityNum;
	int		dlighted, oldDlighted;
	int		pshadowed, oldPshadowed;
	qbool		depthRange, oldDepthRange, isCrosshair, wasCrosshair;
	int		i;
	drawSurf_t              *drawSurf;
	int		oldSort;
	float		originalTime;
	float		depth[2];
	FBO_t		* fbo	= NULL;
	qbool		inQuery = qfalse;

	/* save original time for entity shader offsets */
	originalTime = backEnd.refdef.floatTime;

	/* clear the z buffer, set the modelview, etc */
	RB_BeginDrawingView ();

	fbo = glState.currentFBO;

	/* draw everything */
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange	= qfalse;
	wasCrosshair	= qfalse;
	oldDlighted	= qfalse;
	oldPshadowed	= qfalse;
	oldSort = -1;
	depthRange = qfalse;
	depth[0] = 0.f;
	depth[1] = 1.f;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for(i = 0, drawSurf = drawSurfs; i < numDrawSurfs; i++, drawSurf++){
		if(drawSurf->sort == oldSort){
			/* fast path, same as previous sort */
			rb_surfaceTable[ *drawSurf->surface ](drawSurf->surface);
			continue;
		}
		oldSort = drawSurf->sort;
		R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed);

		/*
		 * change the tess parameters if needed
		 * a "entityMergable" shader is a shader that can have surfaces from seperate
		 * entities merged into a single batch, like smoke and blood puff sprites */
		if(shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed !=
		   oldPshadowed
		   || (entityNum != oldEntityNum && !shader->entityMergable)){
			if(oldShader != NULL){
				RB_EndSurface();
			}
			RB_BeginSurface(shader, fogNum);
			backEnd.pc.c_surfBatches++;
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
			oldPshadowed = pshadowed;
		}

		/*
		 * change the modelview matrix if needed
		 *  */
		if(entityNum != oldEntityNum){
			qbool sunflare = qfalse;
			depthRange = isCrosshair = qfalse;

#ifdef REACTION
			/* if we were rendering to a FBO and the previous entity was a sunflare
			 * and the current one isn't, switch back to the main fbo */
			if(oldEntityNum != -1 && fbo &&
			   RF_SUNFLARE == (backEnd.refdef.entities[oldEntityNum].e.renderfx & RF_SUNFLARE) &&
			   0 == (backEnd.refdef.entities[entityNum].e.renderfx & RF_SUNFLARE)){
				if(inQuery){
					inQuery = qfalse;
					qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
				}
				FBO_Bind(fbo);
				qglDepthRange(depth[0], depth[1]);
			}
#endif

			if(entityNum != ENTITYNUM_WORLD){
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
				/* we have to reset the shaderTime as well otherwise image animations start
				 * from the wrong frame */
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				/* set up the transformation matrix */
				R_RotateForEntity(backEnd.currentEntity, &backEnd.viewParms, &backEnd.or);

				/* set up the dynamic lighting if needed */
				if(backEnd.currentEntity->needDlights){
					R_TransformDlights(backEnd.refdef.num_dlights, backEnd.refdef.dlights,
						&backEnd.or);
				}

#ifdef REACTION
				/* if the current entity is a sunflare */
				if(backEnd.currentEntity->e.renderfx & RF_SUNFLARE){
					/* if we're rendering to a fbo */
					if(fbo){
						copyv3(backEnd.currentEntity->e.origin,
							backEnd.sunFlarePos);
						/* switch FBO */
						FBO_Bind(tr.godRaysFbo);

						qglClearColor(0.0f, 0.0f, 0.0f, 1.0f);
						qglClear(GL_COLOR_BUFFER_BIT);

						qglDepthRange(1.f, 1.f);
						if(glRefConfig.occlusionQuery && !inQuery &&
						   !backEnd.hasSunFlare){
							inQuery = qtrue;
							tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue;
							qglBeginQueryARB(
								GL_SAMPLES_PASSED_ARB,
								tr.sunFlareQuery[tr.sunFlareQueryIndex]);
						}
						/* backEnd.hasSunFlare = qtrue; */
						sunflare = qtrue;
					}else{
						depthRange = qtrue;
					}
				}
#endif

				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK){
					/* hack the depth range to prevent view model from poking into walls */
					depthRange = qtrue;

					if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
						isCrosshair = qtrue;
				}
			}else{
				backEnd.currentEntity = &tr.worldEntity;
				backEnd.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;
				/* we have to reset the shaderTime as well otherwise image animations on
				 * the world (like water) continue with the wrong frame */
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
				R_TransformDlights(backEnd.refdef.num_dlights, backEnd.refdef.dlights,
					&backEnd.or);
			}

			GL_SetModelviewMatrix(backEnd.or.modelMatrix);

			/*
			 * change depthrange. Also change projection matrix so first person weapon does not look like coming
			 * out of the screen.
			 *  */
			if(oldDepthRange != depthRange || wasCrosshair != isCrosshair){
				if(depthRange){
					if(backEnd.viewParms.stereoFrame != STEREO_CENTER){
						if(isCrosshair){
							if(oldDepthRange){
								/* was not a crosshair but now is, change back proj matrix */
								GL_SetProjectionMatrix(
									backEnd.viewParms.projectionMatrix);
							}
						}else{
							viewParms_t temp = backEnd.viewParms;

							R_SetupProjection(&temp, r_znear->value, 0, qfalse);

							GL_SetProjectionMatrix(temp.projectionMatrix);
						}
					}

#ifdef REACTION
					if(!oldDepthRange){
						depth[0] = 0;
						depth[1] = 0.3f;
						qglDepthRange (0, 0.3);
					}
#endif
				}else{
					if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER){
						GL_SetProjectionMatrix(backEnd.viewParms.projectionMatrix);
					}

					if(!sunflare)
						qglDepthRange (0, 1);
					depth[0] = 0;
					depth[1] = 1;
				}

				oldDepthRange	= depthRange;
				wasCrosshair	= isCrosshair;
			}

			oldEntityNum = entityNum;
		}

		/* add the triangles for this surface */
		rb_surfaceTable[ *drawSurf->surface ](drawSurf->surface);
	}

	backEnd.refdef.floatTime = originalTime;

	/* draw the contents of the last shader batch */
	if(oldShader != NULL){
		RB_EndSurface();
	}

	if(inQuery){
		inQuery = qfalse;
		qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
	}
	FBO_Bind(fbo);

	/* go back to the world modelview matrix */

	GL_SetModelviewMatrix(backEnd.viewParms.world.modelMatrix);
	/* if ( depthRange ) { */
	qglDepthRange (0, 1);
	/* } */

#if 0
	RB_DrawSun();
#endif
	/* darken down any stencil shadows */
	RB_ShadowFinish();

	/* add light flares on lights that aren't obscured */
	RB_RenderFlares();

	if(glRefConfig.framebufferObject)
		FBO_Bind(NULL);
}
Beispiel #5
0
/*
==================
RB_RenderDrawSurfList
==================
*/
void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
	shader_t		*shader, *oldShader;
	int				fogNum, oldFogNum;
	int				entityNum, oldEntityNum;
	int				dlighted, oldDlighted;
	int				pshadowed, oldPshadowed;
	int             cubemapIndex, oldCubemapIndex;
	qboolean		depthRange, oldDepthRange, isCrosshair, wasCrosshair;
	int				i;
	drawSurf_t		*drawSurf;
	int				oldSort;
	float			originalTime;
	FBO_t*			fbo = NULL;
	qboolean		inQuery = qfalse;

	float			depth[2];


	// save original time for entity shader offsets
	originalTime = backEnd.refdef.floatTime;

	fbo = glState.currentFBO;

	// draw everything
	oldEntityNum = -1;
	backEnd.currentEntity = &tr.worldEntity;
	oldShader = NULL;
	oldFogNum = -1;
	oldDepthRange = qfalse;
	wasCrosshair = qfalse;
	oldDlighted = qfalse;
	oldPshadowed = qfalse;
	oldCubemapIndex = -1;
	oldSort = -1;

	depth[0] = 0.f;
	depth[1] = 1.f;

	backEnd.pc.c_surfaces += numDrawSurfs;

	for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
		if ( drawSurf->sort == oldSort && drawSurf->cubemapIndex == oldCubemapIndex) {
			if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
				continue;

			// fast path, same as previous sort
			rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
			continue;
		}
		oldSort = drawSurf->sort;
		R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed );
		cubemapIndex = drawSurf->cubemapIndex;

		//
		// change the tess parameters if needed
		// a "entityMergable" shader is a shader that can have surfaces from seperate
		// entities merged into a single batch, like smoke and blood puff sprites
		if ( shader != NULL && ( shader != oldShader || fogNum != oldFogNum || dlighted != oldDlighted || pshadowed != oldPshadowed || cubemapIndex != oldCubemapIndex
			|| ( entityNum != oldEntityNum && !shader->entityMergable ) ) ) {
			if (oldShader != NULL) {
				RB_EndSurface();
			}
			RB_BeginSurface( shader, fogNum, cubemapIndex );
			backEnd.pc.c_surfBatches++;
			oldShader = shader;
			oldFogNum = fogNum;
			oldDlighted = dlighted;
			oldPshadowed = pshadowed;
			oldCubemapIndex = cubemapIndex;
		}

		if (backEnd.depthFill && shader && shader->sort != SS_OPAQUE)
			continue;

		//
		// change the modelview matrix if needed
		//
		if ( entityNum != oldEntityNum ) {
			qboolean sunflare = qfalse;
			depthRange = isCrosshair = qfalse;

			if ( entityNum != REFENTITYNUM_WORLD ) {
				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
				// we have to reset the shaderTime as well otherwise image animations start
				// from the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;

				// set up the transformation matrix
				R_RotateForEntity( backEnd.currentEntity, &backEnd.viewParms, &backEnd.or );

				// set up the dynamic lighting if needed
				if ( backEnd.currentEntity->needDlights ) {
					R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
				}

				if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK)
				{
					// hack the depth range to prevent view model from poking into walls
					depthRange = qtrue;
					
					if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR)
						isCrosshair = qtrue;
				}
			} else {
				backEnd.currentEntity = &tr.worldEntity;
				backEnd.refdef.floatTime = originalTime;
				backEnd.or = backEnd.viewParms.world;
				// we have to reset the shaderTime as well otherwise image animations on
				// the world (like water) continue with the wrong frame
				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
				R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or );
			}

			GL_SetModelviewMatrix( backEnd.or.modelMatrix );

			//
			// change depthrange. Also change projection matrix so first person weapon does not look like coming
			// out of the screen.
			//
			if (oldDepthRange != depthRange || wasCrosshair != isCrosshair)
			{
				if (depthRange)
				{
					if(backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						if(isCrosshair)
						{
							if(oldDepthRange)
							{
								// was not a crosshair but now is, change back proj matrix
								GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
							}
						}
						else
						{
							viewParms_t temp = backEnd.viewParms;

							R_SetupProjection(&temp, r_znear->value, 0, qfalse);

							GL_SetProjectionMatrix( temp.projectionMatrix );
						}
					}

 					if(!oldDepthRange)
					{
						depth[0] = 0;
						depth[1] = 0.3f;
 						qglDepthRange (depth[0], depth[1]);
	 				}
				}
				else
				{
					if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER)
					{
						GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix );
					}

					if (!sunflare)
						qglDepthRange (0, 1);

					depth[0] = 0;
					depth[1] = 1;
				}

				oldDepthRange = depthRange;
				wasCrosshair = isCrosshair;
			}

			oldEntityNum = entityNum;
		}

		// add the triangles for this surface
		rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
	}

	backEnd.refdef.floatTime = originalTime;

	// draw the contents of the last shader batch
	if (oldShader != NULL) {
		RB_EndSurface();
	}

	if (inQuery) {
		qglEndQueryARB(GL_SAMPLES_PASSED_ARB);
	}

	if (glRefConfig.framebufferObject)
		FBO_Bind(fbo);

	// go back to the world modelview matrix

	GL_SetModelviewMatrix( backEnd.viewParms.world.modelMatrix );

	qglDepthRange (0, 1);
}