/* * R_DrawPortals */ void R_DrawPortals( void ) { unsigned int i; if( rn.renderFlags & RF_SKYSHADOWVIEW ) { // render depth mask for skylights // TODO: rewrite this! float depthmin, depthmax; RB_GetDepthRange( &depthmin, &depthmax ); RB_ClearDepth( depthmin ); RB_Clear( GL_DEPTH_BUFFER_BIT, 0, 0, 0, 0 ); if( rn.portalmasklist && rn.portalmasklist->numDrawSurfs ) { RB_SetShaderStateMask( ~0, GLSTATE_DEPTHWRITE | GLSTATE_NO_COLORWRITE | GLSTATE_OFFSET_FILL | GLSTATE_DEPTHFUNC_GT ); RB_FlipFrontFace(); RB_DepthRange( depthmax, depthmax ); R_DrawPortalSurfaces( rn.portalmasklist ); RB_SetShaderStateMask( ~0, GLSTATE_DEPTHWRITE | GLSTATE_NO_COLORWRITE | GLSTATE_OFFSET_FILL ); RB_FlipFrontFace(); RB_DepthRange( depthmin, depthmax ); } RB_ClearDepth( depthmax ); return; } if( rn.renderFlags & ( RF_MIRRORVIEW | RF_LIGHTVIEW | RF_PORTALVIEW ) ) { return; } if( rn.viewcluster == -1 ) { return; } R_DrawPortalsDepthMask(); if( rn.skyportalSurface ) { // render skyportal portalSurface_t *ps = rn.skyportalSurface; R_DrawSkyportal( ps->entity, ps->skyPortal ); } else { // FIXME: move this? // render sky dome that writes to depth R_DrawDepthSkySurf(); } // render regular portals for( i = 0; i < rn.numPortalSurfaces; i++ ) { portalSurface_t ps = rn.portalSurfaces[i]; if( !ps.skyPortal ) { R_DrawPortalSurface( &ps ); rn.portalSurfaces[i] = ps; } } }
/* * R_RenderDebugBounds */ static void R_RenderDebugBounds( void ) { unsigned i, j; const vec_t *mins, *maxs; const uint8_t *color; mesh_t mesh; vec4_t verts[8]; byte_vec4_t colors[8]; elem_t elems[24] = { 0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 7, 7, 6, 6, 4 }; if( !r_num_debug_bounds ) return; memset( &mesh, 0, sizeof( mesh ) ); mesh.numVerts = 8; mesh.xyzArray = verts; mesh.numElems = 24; mesh.elems = elems; mesh.colorsArray[0] = colors; RB_SetShaderStateMask( ~0, GLSTATE_NO_DEPTH_TEST ); for( i = 0; i < r_num_debug_bounds; i++ ) { mins = r_debug_bounds[i].mins; maxs = r_debug_bounds[i].maxs; color = r_debug_bounds[i].color; for( j = 0; j < 8; j++ ) { verts[j][0] = ( ( j & 1 ) ? mins[0] : maxs[0] ); verts[j][1] = ( ( j & 2 ) ? mins[1] : maxs[1] ); verts[j][2] = ( ( j & 4 ) ? mins[2] : maxs[2] ); verts[j][3] = 1.0f; Vector4Copy( color, colors[j] ); } RB_AddDynamicMesh( rsc.worldent, rsh.whiteShader, NULL, NULL, 0, &mesh, GL_LINES, 0.0f, 0.0f ); } RB_FlushDynamicMeshes(); RB_SetShaderStateMask( ~0, 0 ); }
/* * R_DrawPortalsDepthMask * * Renders portal or sky surfaces from the BSP tree to depth buffer. Each rendered pixel * receives the depth value of 1.0, everything else is cleared to 0.0. * * The depth buffer is then preserved for portal render stage to minimize overdraw. */ static void R_DrawPortalsDepthMask( void ) { float depthmin, depthmax; if( !rn.portalmasklist || !rn.portalmasklist->numDrawSurfs ) { return; } RB_GetDepthRange( &depthmin, &depthmax ); RB_ClearDepth( depthmin ); RB_Clear( GL_DEPTH_BUFFER_BIT, 0, 0, 0, 0 ); RB_SetShaderStateMask( ~0, GLSTATE_DEPTHWRITE|GLSTATE_DEPTHFUNC_GT|GLSTATE_NO_COLORWRITE ); RB_DepthRange( depthmax, depthmax ); R_DrawSurfaces( rn.portalmasklist ); RB_DepthRange( depthmin, depthmax ); RB_ClearDepth( depthmax ); RB_SetShaderStateMask( ~0, 0 ); }
/* * RB_EnableTriangleOutlines * * Returns triangle outlines state before the call */ bool RB_EnableTriangleOutlines( bool enable ) { bool oldVal = rb.triangleOutlines; if( rb.triangleOutlines != enable ) { rb.triangleOutlines = enable; // OpenGL ES systems don't support glPolygonMode #ifndef GL_ES_VERSION_2_0 if( enable ) { RB_SetShaderStateMask( 0, GLSTATE_NO_DEPTH_TEST ); qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); } else { RB_SetShaderStateMask( ~0, 0 ); qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); } #endif } return oldVal; }
/* * RB_BeginFrame */ void RB_BeginFrame( void ) { Vector4Set( rb.nullEnt.shaderRGBA, 1, 1, 1, 1 ); rb.nullEnt.scale = 1; VectorClear( rb.nullEnt.origin ); Matrix3_Identity( rb.nullEnt.axis ); memset( &rb.stats, 0, sizeof( rb.stats ) ); // start fresh each frame RB_SetShaderStateMask( ~0, 0 ); RB_BindVBO( 0, 0 ); }
/* * RB_EnableTriangleOutlines * * Returns triangle outlines state before the call */ qboolean RB_EnableTriangleOutlines( qboolean enable ) { qboolean oldVal = rb.triangleOutlines; if( rb.triangleOutlines != enable ) { rb.triangleOutlines = enable; // OpenGL ES systems don't support glPolygonMode // so check whether the function is actually present if( qglPolygonMode ) { if( enable ) { RB_SetShaderStateMask( 0, GLSTATE_NO_DEPTH_TEST ); qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); } else { RB_SetShaderStateMask( ~0, 0 ); qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); } } } return oldVal; }