/* ================ RB_StageIteratorSky All of the visible sky triangles are in tess Other things could be stuck in here, like birds in the sky, etc ================ */ void RB_StageIteratorSky( void ) { if ( r_fastsky->integer ) { return; } // go through all the polygons and project them onto // the sky box to see which blocks on each side need // to be drawn RB_ClipSkyPolygons( &tess ); // r_showsky will let all the sky blocks be drawn in // front of everything to allow developers to see how // much sky is getting sucked in if ( r_showsky->integer ) { qglDepthRangef( 0.0, 0.0 ); } else { qglDepthRangef( 1.0, 1.0 ); } // draw the outer skybox if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { glColor4f( tr.identityLight, tr.identityLight, tr.identityLight, 1.0f ); qglPushMatrix (); GL_State( 0 ); qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); DrawSkyBox( tess.shader ); qglPopMatrix(); } // generate the vertexes for all the clouds, which will be drawn // by the generic shader routine R_BuildCloudData( &tess ); RB_StageIteratorGeneric(); // draw the inner skybox // back to normal depth range qglDepthRangef( 0.0, 1.0 ); // note that sky was drawn so we will draw a sun later backEnd.skyRenderedThisView = qtrue; }
/* ** RB_DrawSun */ void RB_DrawSun( void ) { float size; float dist; vec3_t origin, vec1, vec2; vec3_t temp; if ( !backEnd.skyRenderedThisView ) { return; } if ( !r_drawSun->integer ) { return; } qglLoadMatrixf( backEnd.viewParms.world.modelMatrix ); qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3) size = dist * 0.4; VectorScale( tr.sunDirection, dist, origin ); PerpendicularVector( vec1, tr.sunDirection ); CrossProduct( tr.sunDirection, vec1, vec2 ); VectorScale( vec1, size, vec1 ); VectorScale( vec2, size, vec2 ); // farthest depth range qglDepthRangef( 1.0, 1.0 ); // FIXME: use quad stamp RB_BeginSurface( tr.sunShader, tess.fogNum ); VectorCopy( origin, temp ); VectorSubtract( temp, vec1, temp ); VectorSubtract( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 0; tess.texCoords[tess.numVertexes][0][1] = 0; tess.vertexColors[tess.numVertexes][0] = 255; tess.vertexColors[tess.numVertexes][1] = 255; tess.vertexColors[tess.numVertexes][2] = 255; tess.numVertexes++; VectorCopy( origin, temp ); VectorAdd( temp, vec1, temp ); VectorSubtract( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 0; tess.texCoords[tess.numVertexes][0][1] = 1; tess.vertexColors[tess.numVertexes][0] = 255; tess.vertexColors[tess.numVertexes][1] = 255; tess.vertexColors[tess.numVertexes][2] = 255; tess.numVertexes++; VectorCopy( origin, temp ); VectorAdd( temp, vec1, temp ); VectorAdd( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 1; tess.texCoords[tess.numVertexes][0][1] = 1; tess.vertexColors[tess.numVertexes][0] = 255; tess.vertexColors[tess.numVertexes][1] = 255; tess.vertexColors[tess.numVertexes][2] = 255; tess.numVertexes++; VectorCopy( origin, temp ); VectorSubtract( temp, vec1, temp ); VectorAdd( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 1; tess.texCoords[tess.numVertexes][0][1] = 0; tess.vertexColors[tess.numVertexes][0] = 255; tess.vertexColors[tess.numVertexes][1] = 255; tess.vertexColors[tess.numVertexes][2] = 255; 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; RB_EndSurface(); // back to normal depth range qglDepthRangef( 0.0, 1.0 ); }
/* ================== RB_RenderDrawSurfList ================== */ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { shader_t *shader, *oldShader; int fogNum, oldFogNum; int entityNum, oldEntityNum; int dlighted, oldDlighted; qboolean depthRange, oldDepthRange, isCrosshair, wasCrosshair; int i; drawSurf_t *drawSurf; int oldSort; float originalTime; // save original time for entity shader offsets originalTime = backEnd.refdef.floatTime; // clear the z buffer, set the modelview, etc RB_BeginDrawingView (); // draw everything oldEntityNum = -1; backEnd.currentEntity = &tr.worldEntity; oldShader = NULL; oldFogNum = -1; oldDepthRange = qfalse; wasCrosshair = qfalse; oldDlighted = qfalse; oldSort = -1; depthRange = qfalse; 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 ); // // 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 || ( entityNum != oldEntityNum && !shader->entityMergable ) ) { if (oldShader != NULL) { RB_EndSurface(); } RB_BeginSurface( shader, fogNum ); oldShader = shader; oldFogNum = fogNum; oldDlighted = dlighted; } // // change the modelview matrix if needed // if ( entityNum != oldEntityNum ) { depthRange = isCrosshair = qfalse; 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 ); } 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 ); } qglLoadMatrixf( 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 qglMatrixMode(GL_PROJECTION); qglLoadMatrixf(backEnd.viewParms.projectionMatrix); qglMatrixMode(GL_MODELVIEW); } } else { viewParms_t temp = backEnd.viewParms; R_SetupProjection(&temp, r_znear->value, qfalse); qglMatrixMode(GL_PROJECTION); qglLoadMatrixf(temp.projectionMatrix); qglMatrixMode(GL_MODELVIEW); } } if(!oldDepthRange) #ifdef PANDORA qglDepthRangef (0, 0.3); #else qglDepthRange (0, 0.3); #endif } else { if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER) { qglMatrixMode(GL_PROJECTION); qglLoadMatrixf(backEnd.viewParms.projectionMatrix); qglMatrixMode(GL_MODELVIEW); } #ifdef PANDORA qglDepthRangef (0, 1); #else qglDepthRange (0, 1); #endif } 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(); } // go back to the world modelview matrix qglLoadMatrixf( backEnd.viewParms.world.modelMatrix ); if ( depthRange ) { #ifdef PANDORA qglDepthRangef (0, 1); #else qglDepthRange (0, 1); #endif } #if 0 RB_DrawSun(); #endif // darken down any stencil shadows RB_ShadowFinish(); // add light flares on lights that aren't obscured RB_RenderFlares(); }