// This could be two functions, but I want to keep the number of different API calls to a minimum void GLRB_SetPortalRendering( qboolean enabled, const float* flipMatrix, const float* plane ) { if ( enabled ) { double dplane[4] = { plane[0], plane[1], plane[2], plane[3] }; qglLoadMatrixf( flipMatrix ); qglClipPlane( GL_CLIP_PLANE0, dplane ); qglEnable( GL_CLIP_PLANE0 ); } else { qglDisable( GL_CLIP_PLANE0 ); } }
/* ================= RB_BeginDrawingView Any mirrored or portaled views have already been drawn, so prepare to actually render the visible surfaces for this view ================= */ void RB_BeginDrawingView (void) { int clearBits = 0; // sync with gl if needed if ( r_finish->integer == 1 && !glState.finishCalled ) { qglFinish (); glState.finishCalled = qtrue; } if ( r_finish->integer == 0 ) { glState.finishCalled = qtrue; } // we will need to change the projection matrix before drawing // 2D images again backEnd.projection2D = qfalse; // // set the modelview matrix for the viewer // SetViewportAndScissor(); // ensures that depth writes are enabled for the depth clear GL_State( GLS_DEFAULT ); // clear relevant buffers clearBits = GL_DEPTH_BUFFER_BIT; if ( r_measureOverdraw->integer || r_shadows->integer == 2 ) { clearBits |= GL_STENCIL_BUFFER_BIT; } if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) ) { clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used #ifdef _DEBUG qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky #else qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky #endif } qglClear( clearBits ); if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) ) { RB_Hyperspace(); return; } else { backEnd.isHyperspace = qfalse; } glState.faceCulling = -1; // force face culling to set next time // we will only draw a sun if there was sky rendered in this view backEnd.skyRenderedThisView = qfalse; // clip to the plane of the portal if ( backEnd.viewParms.isPortal ) { float plane[4]; double plane2[4]; plane[0] = backEnd.viewParms.portalPlane.normal[0]; plane[1] = backEnd.viewParms.portalPlane.normal[1]; plane[2] = backEnd.viewParms.portalPlane.normal[2]; plane[3] = backEnd.viewParms.portalPlane.dist; plane2[0] = DotProduct (backEnd.viewParms.or.axis[0], plane); plane2[1] = DotProduct (backEnd.viewParms.or.axis[1], plane); plane2[2] = DotProduct (backEnd.viewParms.or.axis[2], plane); plane2[3] = DotProduct (plane, backEnd.viewParms.or.origin) - plane[3]; qglLoadMatrixf( s_flipMatrix ); qglClipPlane (GL_CLIP_PLANE0, plane2); qglEnable (GL_CLIP_PLANE0); } else { qglDisable (GL_CLIP_PLANE0); } }
/* ================= RB_BeginDrawingView Any mirrored or portaled views have already been drawn, so prepare to actually render the visible surfaces for this view ================= */ void RB_BeginDrawingView( void ) { int clearBits = 0; // sync with gl if needed if ( r_finish->integer == 1 && !glState.finishCalled ) { qglFinish(); glState.finishCalled = qtrue; } if ( r_finish->integer == 0 ) { glState.finishCalled = qtrue; } // we will need to change the projection matrix before drawing // 2D images again backEnd.projection2D = qfalse; // // set the modelview matrix for the viewer // SetViewportAndScissor(); // ensures that depth writes are enabled for the depth clear GL_State( GLS_DEFAULT ); ////////// (SA) modified to ensure one glclear() per frame at most // clear relevant buffers clearBits = 0; if ( r_measureOverdraw->integer || r_shadows->integer == 2 ) { clearBits |= GL_STENCIL_BUFFER_BIT; } if ( r_uiFullScreen->integer ) { clearBits = GL_DEPTH_BUFFER_BIT; // (SA) always just clear depth for menus } else if ( skyboxportal ) { if ( backEnd.refdef.rdflags & RDF_SKYBOXPORTAL ) { // portal scene, clear whatever is necessary clearBits |= GL_DEPTH_BUFFER_BIT; if ( r_fastsky->integer || backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) { // fastsky: clear color // try clearing first with the portal sky fog color, then the world fog color, then finally a default clearBits |= GL_COLOR_BUFFER_BIT; if ( glfogsettings[FOG_PORTALVIEW].registered ) { qglClearColor( glfogsettings[FOG_PORTALVIEW].color[0], glfogsettings[FOG_PORTALVIEW].color[1], glfogsettings[FOG_PORTALVIEW].color[2], glfogsettings[FOG_PORTALVIEW].color[3] ); } else if ( glfogNum > FOG_NONE && glfogsettings[FOG_CURRENT].registered ) { qglClearColor( glfogsettings[FOG_CURRENT].color[0], glfogsettings[FOG_CURRENT].color[1], glfogsettings[FOG_CURRENT].color[2], glfogsettings[FOG_CURRENT].color[3] ); } else { // qglClearColor ( 1.0, 0.0, 0.0, 1.0 ); // red clear for testing portal sky clear qglClearColor( 0.5, 0.5, 0.5, 1.0 ); } } else { // rendered sky (either clear color or draw quake sky) if ( glfogsettings[FOG_PORTALVIEW].registered ) { qglClearColor( glfogsettings[FOG_PORTALVIEW].color[0], glfogsettings[FOG_PORTALVIEW].color[1], glfogsettings[FOG_PORTALVIEW].color[2], glfogsettings[FOG_PORTALVIEW].color[3] ); if ( glfogsettings[FOG_PORTALVIEW].clearscreen ) { // portal fog requests a screen clear (distance fog rather than quake sky) clearBits |= GL_COLOR_BUFFER_BIT; } } } } else { // world scene with portal sky, don't clear any buffers, just set the fog color if there is one clearBits |= GL_DEPTH_BUFFER_BIT; // this will go when I get the portal sky rendering way out in the zbuffer (or not writing to zbuffer at all) if ( glfogNum > FOG_NONE && glfogsettings[FOG_CURRENT].registered ) { if ( backEnd.refdef.rdflags & RDF_UNDERWATER ) { if ( glfogsettings[FOG_CURRENT].mode == GL_LINEAR ) { clearBits |= GL_COLOR_BUFFER_BIT; } } else if ( !( r_portalsky->integer ) ) { // portal skies have been manually turned off, clear bg color clearBits |= GL_COLOR_BUFFER_BIT; } qglClearColor( glfogsettings[FOG_CURRENT].color[0], glfogsettings[FOG_CURRENT].color[1], glfogsettings[FOG_CURRENT].color[2], glfogsettings[FOG_CURRENT].color[3] ); } } } else { // world scene with no portal sky clearBits |= GL_DEPTH_BUFFER_BIT; // NERVE - SMF - we don't want to clear the buffer when no world model is specified if ( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) { clearBits &= ~GL_COLOR_BUFFER_BIT; } // -NERVE - SMF // (SA) well, this is silly then else if ( r_fastsky->integer ) { // || backEnd.refdef.rdflags & RDF_NOWORLDMODEL clearBits |= GL_COLOR_BUFFER_BIT; if ( glfogsettings[FOG_CURRENT].registered ) { // try to clear fastsky with current fog color qglClearColor( glfogsettings[FOG_CURRENT].color[0], glfogsettings[FOG_CURRENT].color[1], glfogsettings[FOG_CURRENT].color[2], glfogsettings[FOG_CURRENT].color[3] ); } else { // qglClearColor ( 0.0, 0.0, 1.0, 1.0 ); // blue clear for testing world sky clear qglClearColor( 0.5, 0.5, 0.5, 1.0 ); } } else { // world scene, no portal sky, not fastsky, clear color if fog says to, otherwise, just set the clearcolor if ( glfogsettings[FOG_CURRENT].registered ) { // try to clear fastsky with current fog color qglClearColor( glfogsettings[FOG_CURRENT].color[0], glfogsettings[FOG_CURRENT].color[1], glfogsettings[FOG_CURRENT].color[2], glfogsettings[FOG_CURRENT].color[3] ); if ( glfogsettings[FOG_CURRENT].clearscreen ) { // world fog requests a screen clear (distance fog rather than quake sky) clearBits |= GL_COLOR_BUFFER_BIT; } } } } if ( clearBits ) { qglClear( clearBits ); } //----(SA) done if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) ) { RB_Hyperspace(); return; } else { backEnd.isHyperspace = qfalse; } glState.faceCulling = -1; // force face culling to set next time // we will only draw a sun if there was sky rendered in this view backEnd.skyRenderedThisView = qfalse; // clip to the plane of the portal if ( backEnd.viewParms.isPortal ) { float plane[4]; double plane2[4]; plane[0] = backEnd.viewParms.portalPlane.normal[0]; plane[1] = backEnd.viewParms.portalPlane.normal[1]; plane[2] = backEnd.viewParms.portalPlane.normal[2]; plane[3] = backEnd.viewParms.portalPlane.dist; plane2[0] = DotProduct( backEnd.viewParms.or.axis[0], plane ); plane2[1] = DotProduct( backEnd.viewParms.or.axis[1], plane ); plane2[2] = DotProduct( backEnd.viewParms.or.axis[2], plane ); plane2[3] = DotProduct( plane, backEnd.viewParms.or.origin ) - plane[3]; qglLoadMatrixf( s_flipMatrix ); qglClipPlane( GL_CLIP_PLANE0, plane2 ); qglEnable( GL_CLIP_PLANE0 ); } else { qglDisable( GL_CLIP_PLANE0 ); } }
/* ================= RB_BeginDrawingView Any mirrored or portaled views have already been drawn, so prepare to actually render the visible surfaces for this view ================= */ static void RB_BeginDrawingView (void) { int clearBits = GL_DEPTH_BUFFER_BIT; // sync with gl if needed if ( r_finish->integer == 1 && !glState.finishCalled ) { qglFinish (); glState.finishCalled = qtrue; } if ( r_finish->integer == 0 ) { glState.finishCalled = qtrue; } // we will need to change the projection matrix before drawing // 2D images again backEnd.projection2D = qfalse; // // set the modelview matrix for the viewer // SetViewportAndScissor(); // ensures that depth writes are enabled for the depth clear GL_State( GLS_DEFAULT ); // clear relevant buffers if ( r_measureOverdraw->integer || r_shadows->integer == 2 || tr_stencilled ) { clearBits |= GL_STENCIL_BUFFER_BIT; tr_stencilled = false; } if (skyboxportal) { if ( backEnd.refdef.rdflags & RDF_SKYBOXPORTAL ) { // portal scene, clear whatever is necessary if (r_fastsky->integer || (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) ) { // fastsky: clear color // try clearing first with the portal sky fog color, then the world fog color, then finally a default clearBits |= GL_COLOR_BUFFER_BIT; if (tr.world && tr.world->globalFog != -1) { const fog_t *fog = &tr.world->fogs[tr.world->globalFog]; qglClearColor(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], 1.0f ); } else { qglClearColor ( 0.3f, 0.3f, 0.3f, 1.0 ); } } } } else { if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) && !g_bRenderGlowingObjects ) { if (tr.world && tr.world->globalFog != -1) { const fog_t *fog = &tr.world->fogs[tr.world->globalFog]; qglClearColor(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], 1.0f ); } else { qglClearColor( 0.3f, 0.3f, 0.3f, 1 ); // FIXME: get color of sky } clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used } } if ( !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) && ( r_DynamicGlow->integer && !g_bRenderGlowingObjects ) ) { if (tr.world && tr.world->globalFog != -1) { //this is because of a bug in multiple scenes I think, it needs to clear for the second scene but it doesn't normally. const fog_t *fog = &tr.world->fogs[tr.world->globalFog]; qglClearColor(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], 1.0f ); clearBits |= GL_COLOR_BUFFER_BIT; } } // If this pass is to just render the glowing objects, don't clear the depth buffer since // we're sharing it with the main scene (since the main scene has already been rendered). -AReis if ( g_bRenderGlowingObjects ) { clearBits &= ~GL_DEPTH_BUFFER_BIT; } if (clearBits) { qglClear( clearBits ); } if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) ) { RB_Hyperspace(); return; } else { backEnd.isHyperspace = qfalse; } glState.faceCulling = -1; // force face culling to set next time // we will only draw a sun if there was sky rendered in this view backEnd.skyRenderedThisView = qfalse; // clip to the plane of the portal if ( backEnd.viewParms.isPortal ) { float plane[4]; double plane2[4]; plane[0] = backEnd.viewParms.portalPlane.normal[0]; plane[1] = backEnd.viewParms.portalPlane.normal[1]; plane[2] = backEnd.viewParms.portalPlane.normal[2]; plane[3] = backEnd.viewParms.portalPlane.dist; plane2[0] = DotProduct (backEnd.viewParms.ori.axis[0], plane); plane2[1] = DotProduct (backEnd.viewParms.ori.axis[1], plane); plane2[2] = DotProduct (backEnd.viewParms.ori.axis[2], plane); plane2[3] = DotProduct (plane, backEnd.viewParms.ori.origin) - plane[3]; qglLoadMatrixf( s_flipMatrix ); qglClipPlane (GL_CLIP_PLANE0, plane2); qglEnable (GL_CLIP_PLANE0); } else { qglDisable (GL_CLIP_PLANE0); } }
/* ================== GL_Setup3D TODO: time is messed up ================== */ void GL_Setup3D (int time){ double clipPlane[4]; QGL_LogPrintf("---------- RB_Setup3D ----------\n"); backEnd.projection2D = false; backEnd.time = time; backEnd.floatTime = MS2SEC(Sys_Milliseconds()); backEnd.viewport.x = backEnd.viewParms.viewport.x; backEnd.viewport.y = backEnd.viewParms.viewport.y; backEnd.viewport.width = backEnd.viewParms.viewport.width; backEnd.viewport.height = backEnd.viewParms.viewport.height; backEnd.scissor.x = backEnd.viewParms.scissor.x; backEnd.scissor.y = backEnd.viewParms.scissor.y; backEnd.scissor.width = backEnd.viewParms.scissor.width; backEnd.scissor.height = backEnd.viewParms.scissor.height; backEnd.coordScale[0] = 1.0f / backEnd.viewport.width; backEnd.coordScale[1] = 1.0f / backEnd.viewport.height; backEnd.coordBias[0] = -backEnd.viewport.x * backEnd.coordScale[0]; backEnd.coordBias[1] = -backEnd.viewport.y * backEnd.coordScale[1]; backEnd.depthFilling = false; backEnd.debugRendering = false; backEnd.currentColorCaptured = SORT_BAD; backEnd.currentDepthCaptured = false; // Set up the viewport GL_Viewport(backEnd.viewport); // Set up the scissor GL_Scissor(backEnd.viewport); // Set up the depth bounds if (glConfig.depthBoundsTestAvailable) GL_DepthBounds(0.0f, 1.0f); // Set the projection matrix GL_LoadMatrix(GL_PROJECTION, backEnd.viewParms.projectionMatrix); // Set the modelview matrix GL_LoadIdentity(GL_MODELVIEW); // Set the GL state GL_PolygonMode(GL_FILL); GL_Disable(GL_CULL_FACE); GL_Disable(GL_POLYGON_OFFSET_FILL); GL_Disable(GL_BLEND); GL_Disable(GL_ALPHA_TEST); GL_Disable(GL_DEPTH_TEST); GL_Disable(GL_STENCIL_TEST); GL_DepthRange(0.0f, 1.0f); GL_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); GL_DepthMask(GL_TRUE); GL_StencilMask(255); // Enable the clip plane if needed if (backEnd.viewParms.viewType != VIEW_MIRROR) qglDisable(GL_CLIP_PLANE0); else { clipPlane[0] = -DotProduct(backEnd.viewParms.axis[1], backEnd.viewParms.clipPlane.normal); clipPlane[1] = DotProduct(backEnd.viewParms.axis[2], backEnd.viewParms.clipPlane.normal); clipPlane[2] = -DotProduct(backEnd.viewParms.axis[0], backEnd.viewParms.clipPlane.normal); clipPlane[3] = DotProduct(backEnd.viewParms.origin, backEnd.viewParms.clipPlane.normal) - backEnd.viewParms.clipPlane.dist; qglEnable(GL_CLIP_PLANE0); qglClipPlane(GL_CLIP_PLANE0, clipPlane); } // Enable multisampling if available if (glConfig.multiSamples > 1) qglEnable(GL_MULTISAMPLE); // Clear the buffers qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglClearDepth(1.0f); qglClearStencil(0); if (backEnd.viewParms.primaryView) qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); else qglClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Check for errors if (!r_ignoreGLErrors->integerValue) GL_CheckForErrors(); QGL_LogPrintf("--------------------\n"); }