/* ================== GL_DepthBounds ================== */ void GL_DepthBounds (float min, float max){ if (glState.depthBoundsMin == min && glState.depthBoundsMax == max) return; glState.depthBoundsMin = min; glState.depthBoundsMax = max; qglDepthBoundsEXT(min, max); }
/* ===================== RB_T_Shadow the shadow volumes face INSIDE ===================== */ static void RB_T_Shadow( const drawSurf_t *surf ) { const srfTriangles_t *tri; // set the light position if we are using a vertex program to project the rear surfaces if ( tr.backEndRendererHasVertexPrograms && r_useShadowVertexProgram.GetBool() && surf->space != backEnd.currentSpace ) { idVec4 localLight; R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.vLight->globalLightOrigin, localLight.ToVec3() ); localLight.w = 0.0f; qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, localLight.ToFloatPtr() ); } tri = surf->geo; if ( !tri->shadowCache ) { return; } qglVertexPointer( 4, GL_FLOAT, sizeof( shadowCache_t ), vertexCache.Position(tri->shadowCache) ); // we always draw the sil planes, but we may not need to draw the front or rear caps int numIndexes; bool external = false; if ( !r_useExternalShadows.GetInteger() ) { numIndexes = tri->numIndexes; } else if ( r_useExternalShadows.GetInteger() == 2 ) { // force to no caps for testing numIndexes = tri->numShadowIndexesNoCaps; } else if ( !(surf->dsFlags & DSF_VIEW_INSIDE_SHADOW) ) { // if we aren't inside the shadow projection, no caps are ever needed needed numIndexes = tri->numShadowIndexesNoCaps; external = true; } else if ( !backEnd.vLight->viewInsideLight && !(surf->geo->shadowCapPlaneBits & SHADOW_CAP_INFINITE) ) { // if we are inside the shadow projection, but outside the light, and drawing // a non-infinite shadow, we can skip some caps if ( backEnd.vLight->viewSeesShadowPlaneBits & surf->geo->shadowCapPlaneBits ) { // we can see through a rear cap, so we need to draw it, but we can skip the // caps on the actual surface numIndexes = tri->numShadowIndexesNoFrontCaps; } else { // we don't need to draw any caps numIndexes = tri->numShadowIndexesNoCaps; } external = true; } else { // must draw everything numIndexes = tri->numIndexes; } // set depth bounds if( glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool() ) { qglDepthBoundsEXT( surf->scissorRect.zmin, surf->scissorRect.zmax ); } // debug visualization if ( r_showShadows.GetInteger() ) { if ( r_showShadows.GetInteger() == 3 ) { if ( external ) { qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright ); } else { // these are the surfaces that require the reverse qglColor3f( 1/backEnd.overBright, 0.1/backEnd.overBright, 0.1/backEnd.overBright ); } } else { // draw different color for turboshadows if ( surf->geo->shadowCapPlaneBits & SHADOW_CAP_INFINITE ) { if ( numIndexes == tri->numIndexes ) { qglColor3f( 1/backEnd.overBright, 0.1/backEnd.overBright, 0.1/backEnd.overBright ); } else { qglColor3f( 1/backEnd.overBright, 0.4/backEnd.overBright, 0.1/backEnd.overBright ); } } else { if ( numIndexes == tri->numIndexes ) { qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright ); } else if ( numIndexes == tri->numShadowIndexesNoFrontCaps ) { qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.6/backEnd.overBright ); } else { qglColor3f( 0.6/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright ); } } } qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); qglDisable( GL_STENCIL_TEST ); GL_Cull( CT_TWO_SIDED ); RB_DrawShadowElementsWithCounters( tri, numIndexes ); GL_Cull( CT_FRONT_SIDED ); qglEnable( GL_STENCIL_TEST ); return; } // patent-free work around if ( !external ) { // "preload" the stencil buffer with the number of volumes // that get clipped by the near or far clip plane qglStencilOp( GL_KEEP, tr.stencilDecr, tr.stencilDecr ); GL_Cull( CT_FRONT_SIDED ); RB_DrawShadowElementsWithCounters( tri, numIndexes ); qglStencilOp( GL_KEEP, tr.stencilIncr, tr.stencilIncr ); GL_Cull( CT_BACK_SIDED ); RB_DrawShadowElementsWithCounters( tri, numIndexes ); } // traditional depth-pass stencil shadows qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilIncr ); GL_Cull( CT_FRONT_SIDED ); RB_DrawShadowElementsWithCounters( tri, numIndexes ); qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilDecr ); GL_Cull( CT_BACK_SIDED ); RB_DrawShadowElementsWithCounters( tri, numIndexes ); }
/* ================== GL_SetDefaultState ================== */ void GL_SetDefaultState (){ int i; QGL_LogPrintf("---------- GL_SetDefaultState ----------\n"); // Reset the state manager glState.projectionMatrixIdentity = true; glState.modelviewMatrixIdentity = true; for (i = 0; i < MAX_TEXTURE_UNITS; i++) glState.textureMatrixIdentity[i] = true; for (i = 0; i < MAX_TEXTURE_UNITS; i++) glState.texture[i] = NULL; glState.program = NULL; glState.indexBuffer = NULL; glState.vertexBuffer = NULL; glState.viewportX = 0; glState.viewportY = 0; glState.viewportWidth = glConfig.videoWidth; glState.viewportHeight = glConfig.videoHeight; glState.scissorX = 0; glState.scissorY = 0; glState.scissorWidth = glConfig.videoWidth; glState.scissorHeight = glConfig.videoHeight; glState.depthBoundsMin = 0.0f; glState.depthBoundsMax = 1.0f; glState.texUnit = 0; for (i = 0; i < MAX_TEXTURE_UNITS; i++){ glState.texTarget[i] = 0; glState.texEnv[i] = GL_MODULATE; glState.texGen[i][0] = GL_OBJECT_LINEAR; glState.texGen[i][1] = GL_OBJECT_LINEAR; glState.texGen[i][2] = GL_OBJECT_LINEAR; glState.texGen[i][3] = GL_OBJECT_LINEAR; } glState.cullFace = false; glState.polygonOffsetFill = false; glState.polygonOffsetLine = false; glState.blend = false; glState.alphaTest = false; glState.depthTest = false; glState.stencilTest = false; for (i = 0; i < MAX_TEXTURE_UNITS; i++){ glState.textureGen[i][0] = false; glState.textureGen[i][1] = false; glState.textureGen[i][2] = false; glState.textureGen[i][3] = false; } glState.cullMode = GL_FRONT; glState.polygonMode = GL_FILL; glState.polygonOffsetFactor = 0.0f; glState.polygonOffsetUnits = 0.0f; glState.blendSrc = GL_ONE; glState.blendDst = GL_ZERO; glState.blendMode = GL_FUNC_ADD; glState.alphaFunc = GL_GREATER; glState.alphaFuncRef = 0.0f; glState.depthFunc = GL_LEQUAL; glState.stencilFunc[0] = GL_ALWAYS; glState.stencilFunc[1] = GL_ALWAYS; glState.stencilFuncRef[0] = 0; glState.stencilFuncRef[1] = 0; glState.stencilFuncMask[0] = 255; glState.stencilFuncMask[1] = 255; glState.stencilOpFail[0] = GL_KEEP; glState.stencilOpFail[1] = GL_KEEP; glState.stencilOpZFail[0] = GL_KEEP; glState.stencilOpZFail[1] = GL_KEEP; glState.stencilOpZPass[0] = GL_KEEP; glState.stencilOpZPass[1] = GL_KEEP; glState.depthMin = 0.0f; glState.depthMax = 1.0f; glState.colorMask[0] = GL_TRUE; glState.colorMask[1] = GL_TRUE; glState.colorMask[2] = GL_TRUE; glState.colorMask[3] = GL_TRUE; glState.depthMask = GL_TRUE; glState.stencilMask[0] = 255; glState.stencilMask[1] = 255; // Set default state qglMatrixMode(GL_PROJECTION); qglLoadIdentity(); qglMatrixMode(GL_MODELVIEW); qglLoadIdentity(); for (i = MAX_TEXTURE_UNITS - 1; i >= 0; i--){ if (i >= glConfig.maxTextureImageUnits) continue; if (i >= glConfig.maxTextureUnits){ qglActiveTexture(GL_TEXTURE0 + i); qglBindTexture(GL_TEXTURE_2D, 0); qglBindTexture(GL_TEXTURE_3D, 0); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); qglBindTexture(GL_TEXTURE_2D_ARRAY, 0); continue; } qglActiveTexture(GL_TEXTURE0 + i); qglMatrixMode(GL_TEXTURE); qglLoadIdentity(); qglDisable(GL_TEXTURE_2D); qglDisable(GL_TEXTURE_3D); qglDisable(GL_TEXTURE_CUBE_MAP); qglDisable(GL_TEXTURE_2D_ARRAY); qglBindTexture(GL_TEXTURE_2D, 0); qglBindTexture(GL_TEXTURE_3D, 0); qglBindTexture(GL_TEXTURE_CUBE_MAP, 0); qglBindTexture(GL_TEXTURE_2D_ARRAY, 0); qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); qglDisable(GL_TEXTURE_GEN_S); qglDisable(GL_TEXTURE_GEN_T); qglDisable(GL_TEXTURE_GEN_R); qglDisable(GL_TEXTURE_GEN_Q); qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); qglTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); } qglDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); qglUseProgram(0); qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); qglBindBuffer(GL_ARRAY_BUFFER, 0); qglViewport(0, 0, glConfig.videoWidth, glConfig.videoHeight); qglEnable(GL_SCISSOR_TEST); qglScissor(0, 0, glConfig.videoWidth, glConfig.videoHeight); qglEnable(GL_DEPTH_BOUNDS_TEST_EXT); qglDepthBoundsEXT(0.0f, 1.0f); qglFrontFace(GL_CCW); qglShadeModel(GL_SMOOTH); qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL); qglDisable(GL_CULL_FACE); qglCullFace(GL_FRONT); qglDisable(GL_POLYGON_OFFSET_FILL); qglDisable(GL_POLYGON_OFFSET_LINE); qglPolygonOffset(0.0f, 0.0f); qglDisable(GL_BLEND); qglBlendFunc(GL_ONE, GL_ZERO); qglBlendEquation(GL_FUNC_ADD); qglDisable(GL_ALPHA_TEST); qglAlphaFunc(GL_GREATER, 0.0f); qglDisable(GL_DEPTH_TEST); qglDepthFunc(GL_LEQUAL); qglDisable(GL_STENCIL_TEST); qglStencilFunc(GL_ALWAYS, 128, 255); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglDepthRange(0.0f, 1.0f); qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); qglDepthMask(GL_TRUE); qglStencilMask(255); qglDisable(GL_DEPTH_CLAMP); qglDisable(GL_CLIP_PLANE0); if (glConfig.multiSamples > 1){ qglDisable(GL_MULTISAMPLE); qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); } qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglClearDepth(1.0f); qglClearStencil(128); qglEnableClientState(GL_VERTEX_ARRAY); qglDisableVertexAttribArray(GL_ATTRIB_NORMAL); qglDisableVertexAttribArray(GL_ATTRIB_TANGENT1); qglDisableVertexAttribArray(GL_ATTRIB_TANGENT2); qglDisableVertexAttribArray(GL_ATTRIB_TEXCOORD); qglDisableVertexAttribArray(GL_ATTRIB_COLOR); QGL_LogPrintf("--------------------\n"); }