/* ============= R_SetupGL ============= */ static void R_SetupGL( void ) { if( RI.refdef.waterlevel >= 3 ) { float f; f = sin( cl.time * 0.4f * ( M_PI * 2.7f )); RI.refdef.fov_x += f; RI.refdef.fov_y -= f; } R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix ); R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix ); // if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0]; Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] ); pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); if( RI.params & RP_CLIPPLANE ) { GLdouble clip[4]; mplane_t *p = &RI.clipPlane; clip[0] = p->normal[0]; clip[1] = p->normal[1]; clip[2] = p->normal[2]; clip[3] = -p->dist; pglClipPlane( GL_CLIP_PLANE0, clip ); pglEnable( GL_CLIP_PLANE0 ); } if( RI.params & RP_FLIPFRONTFACE ) GL_FrontFace( !glState.frontFace ); GL_Cull( GL_FRONT ); pglDisable( GL_BLEND ); pglDisable( GL_ALPHA_TEST ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); }
/* ================ R_RenderView A view may be either the actual camera view, a mirror / remote location, or a 3D view on a gui surface. Parms will typically be allocated with R_FrameAlloc ================ */ void R_RenderView( viewDef_t *parms ) { // save view in case we are a subview viewDef_t * oldView = tr.viewDef; tr.viewDef = parms; // setup the matrix for world space to eye space R_SetupViewMatrix( tr.viewDef ); // we need to set the projection matrix before doing // portal-to-screen scissor calculations R_SetupProjectionMatrix( tr.viewDef ); // setup render matrices for faster culling idRenderMatrix::Transpose( *(idRenderMatrix *)tr.viewDef->projectionMatrix, tr.viewDef->projectionRenderMatrix ); idRenderMatrix viewRenderMatrix; idRenderMatrix::Transpose( *(idRenderMatrix *)tr.viewDef->worldSpace.modelViewMatrix, viewRenderMatrix ); idRenderMatrix::Multiply( tr.viewDef->projectionRenderMatrix, viewRenderMatrix, tr.viewDef->worldSpace.mvp ); // the planes of the view frustum are needed for portal visibility culling idRenderMatrix::GetFrustumPlanes( tr.viewDef->frustum, tr.viewDef->worldSpace.mvp, false, true ); // the DOOM 3 frustum planes point outside the frustum for ( int i = 0; i < 6; i++ ) { tr.viewDef->frustum[i] = - tr.viewDef->frustum[i]; } // remove the Z-near to avoid portals from being near clipped tr.viewDef->frustum[4][3] -= r_znear.GetFloat(); // identify all the visible portal areas, and create view lights and view entities // for all the the entityDefs and lightDefs that are in the visible portal areas static_cast<idRenderWorldLocal *>(parms->renderWorld)->FindViewLightsAndEntities(); // wait for any shadow volume jobs from the previous frame to finish tr.frontEndJobList->Wait(); // make sure that interactions exist for all light / entity combinations that are visible // add any pre-generated light shadows, and calculate the light shader values R_AddLights(); // adds ambient surfaces and create any necessary interaction surfaces to add to the light lists R_AddModels(); // build up the GUIs on world surfaces R_AddInGameGuis( tr.viewDef->drawSurfs, tr.viewDef->numDrawSurfs ); // any viewLight that didn't have visible surfaces can have it's shadows removed R_OptimizeViewLightsList(); // sort all the ambient surfaces for translucency ordering R_SortDrawSurfs( tr.viewDef->drawSurfs, tr.viewDef->numDrawSurfs ); // generate any subviews (mirrors, cameras, etc) before adding this view if ( R_GenerateSubViews( tr.viewDef->drawSurfs, tr.viewDef->numDrawSurfs ) ) { // if we are debugging subviews, allow the skipping of the main view draw if ( r_subviewOnly.GetBool() ) { return; } } // write everything needed to the demo file if ( common->WriteDemo() ) { static_cast<idRenderWorldLocal *>(parms->renderWorld)->WriteVisibleDefs( tr.viewDef ); } // add the rendering commands for this viewDef R_AddDrawViewCmd( parms, false ); // restore view in case we are a subview tr.viewDef = oldView; }
/* ============= R_SetupGL ============= */ static void R_SetupGL( void ) { if( r_underwater_distortion->value && RI.refdef.waterlevel >= 3 ) { float f; f = sin( cl.time * r_underwater_distortion->value * ( M_PI * 2.7f )); RI.refdef.fov_x += f; RI.refdef.fov_y -= f; } R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix ); R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix ); // if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0]; Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); if( RP_NORMALPASS( )) { int x, x2, y, y2; // set up viewport (main, playersetup) x = floor( RI.viewport[0] * glState.width / glState.width ); x2 = ceil(( RI.viewport[0] + RI.viewport[2] ) * glState.width / glState.width ); y = floor( glState.height - RI.viewport[1] * glState.height / glState.height ); y2 = ceil( glState.height - ( RI.viewport[1] + RI.viewport[3] ) * glState.height / glState.height ); pglViewport( x, y2, x2 - x, y - y2 ); } else { // envpass, mirrorpass pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); } pglMatrixMode( GL_PROJECTION ); GL_LoadMatrix( RI.projectionMatrix ); pglMatrixMode( GL_MODELVIEW ); GL_LoadMatrix( RI.worldviewMatrix ); if( RI.params & RP_CLIPPLANE ) { GLdouble clip[4]; mplane_t *p = &RI.clipPlane; clip[0] = p->normal[0]; clip[1] = p->normal[1]; clip[2] = p->normal[2]; clip[3] = -p->dist; pglClipPlane( GL_CLIP_PLANE0, clip ); pglEnable( GL_CLIP_PLANE0 ); } if( RI.params & RP_FLIPFRONTFACE ) GL_FrontFace( !glState.frontFace ); GL_Cull( GL_FRONT ); pglDisable( GL_BLEND ); pglDisable( GL_ALPHA_TEST ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); }
/* ======================== R_MirrorViewBySurface ======================== */ static viewDef_t* R_MirrorViewBySurface( const drawSurf_t* drawSurf ) { // copy the viewport size from the original viewDef_t* parms = ( viewDef_t* )R_FrameAlloc( sizeof( *parms ) ); *parms = *tr.viewDef; parms->renderView.viewID = 0; // clear to allow player bodies to show up, and suppress view weapons parms->isSubview = true; parms->isMirror = true; parms->isObliqueProjection = false; // create plane axis for the portal we are seeing idPlane originalPlane, plane; R_PlaneForSurface( drawSurf->frontEndGeo, originalPlane ); R_LocalPlaneToGlobal( drawSurf->space->modelMatrix, originalPlane, plane ); orientation_t surface; surface.origin = plane.Normal() * -plane[3]; surface.axis[0] = plane.Normal(); surface.axis[0].NormalVectors( surface.axis[1], surface.axis[2] ); surface.axis[2] = -surface.axis[2]; orientation_t camera; camera.origin = surface.origin; camera.axis[0] = -surface.axis[0]; camera.axis[1] = surface.axis[1]; camera.axis[2] = surface.axis[2]; // set the mirrored origin and axis R_MirrorPoint( tr.viewDef->renderView.vieworg, &surface, &camera, parms->renderView.vieworg ); R_MirrorVector( tr.viewDef->renderView.viewaxis[0], &surface, &camera, parms->renderView.viewaxis[0] ); R_MirrorVector( tr.viewDef->renderView.viewaxis[1], &surface, &camera, parms->renderView.viewaxis[1] ); R_MirrorVector( tr.viewDef->renderView.viewaxis[2], &surface, &camera, parms->renderView.viewaxis[2] ); // make the view origin 16 units away from the center of the surface const idVec3 center = (drawSurf->frontEndGeo->bounds[0] + drawSurf->frontEndGeo->bounds[1]) * 0.5f; const idVec3 viewOrigin = center + (originalPlane.Normal() * 16.0f); R_LocalPointToGlobal(drawSurf->space->modelMatrix, viewOrigin, parms->initialViewAreaOrigin); // set the mirror clip plane parms->numClipPlanes = 1; parms->clipPlanes[0] = -camera.axis[0]; parms->clipPlanes[0][3] = -( camera.origin * parms->clipPlanes[0].Normal() ); if (r_waterReflectFix.GetBool() && !parms->is2Dgui && drawSurf->material->GetSurfaceType() == SURFTYPE_MIRROR) { parms->isObliqueProjection = true; float dist = parms->clipPlanes[0].Dist(); float viewdist = parms->renderView.vieworg * parms->clipPlanes[0].Normal(); float fDist = -dist + viewdist; static const float fudge = 2.f; //fudge avoids depth precision artifacts when performing oblique projection if (fDist > fudge || fDist < -fudge) { if (fDist < 0.f) fDist += fudge; else fDist -= fudge; } parms->clipPlanes[0][3] = fDist; R_SetupViewMatrix(parms); R_SetupProjectionMatrix(parms); R_ObliqueProjection(parms); } return parms; }