/* ** GLimp_BeginFrame */ void GLimp_BeginFrame( float camera_separation ) { if ( gl_bitdepth->modified ) { if ( gl_bitdepth->value != 0 && !glw_state.allowdisplaydepthchange ) { ri.Cvar_SetValue( "gl_bitdepth", 0 ); ri.Con_Printf( PRINT_ALL, "gl_bitdepth requires Win95 OSR2.x or WinNT 4.x\n" ); } gl_bitdepth->modified = false; } if ( camera_separation < 0 && gl_state.stereo_enabled ) { qglDrawBuffer( GL_BACK_LEFT ); } else if ( camera_separation > 0 && gl_state.stereo_enabled ) { qglDrawBuffer( GL_BACK_RIGHT ); } else { qglDrawBuffer( GL_BACK ); } }
/* ** GLimp_BeginFrame */ void GLimp_BeginFrame( void ) { if( r_colorbits->modified ) { if( r_colorbits->integer != 0 && !glw_state.allowdisplaydepthchange ) { Cvar_SetValue( "r_colorbits", 0 ); Com_Printf( "r_colorbits requires Win95 OSR2.x or WinNT 4.x\n" ); } r_colorbits->modified = qfalse; } if( glState.cameraSeparation < 0 && glState.stereoEnabled ) { qglDrawBuffer( GL_BACK_LEFT ); } else if( glState.cameraSeparation > 0 && glState.stereoEnabled ) { qglDrawBuffer( GL_BACK_RIGHT ); } else { qglDrawBuffer( GL_BACK ); } }
void CCamWnd::BenchMark() { PAINTSTRUCT ps; CRect rct; GetWindowRect(rct); long lStyle = ::GetWindowLong(GetSafeHwnd(), GWL_STYLE); ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, QE3_CHILDSTYLE); CWnd* pParent = GetParent(); SetParent(g_pParentWnd); MoveWindow(CRect(30, 30, 400, 400), TRUE); BeginPaint(&ps); if (!qwglMakeCurrent(ps.hdc, g_qeglobals.d_hglrcBase)) Error ("wglMakeCurrent failed in Benchmark"); qglDrawBuffer (GL_FRONT); double dStart = Sys_DoubleTime (); for (int i=0 ; i < 100 ; i++) { m_Camera.angles[YAW] = i*4; Cam_Draw(); } qwglSwapBuffers(ps.hdc); qglDrawBuffer (GL_BACK); double dEnd = Sys_DoubleTime (); EndPaint(&ps); Sys_Printf ("%5.2f seconds\n", dEnd - dStart); ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, lStyle); SetParent(pParent); MoveWindow(rct, TRUE); }
/* ** GL_SetDefaultState */ void GL_SetDefaultState( void ) { qglClearDepth( 1.0f ); qglCullFace(GL_FRONT); qglColor4f (1,1,1,1); // initialize downstream texture unit if we're running // in a multitexture environment if ( qglActiveTextureARB ) { GL_SelectTexture( 1 ); GL_TextureMode( r_textureMode->string ); GL_TexEnv( GL_MODULATE ); qglDisable( GL_TEXTURE_2D ); GL_SelectTexture( 0 ); } qglEnable(GL_TEXTURE_2D); GL_TextureMode( r_textureMode->string ); GL_TexEnv( GL_MODULATE ); qglShadeModel( GL_SMOOTH ); qglDepthFunc( GL_LEQUAL ); // the vertex array is always enabled, but the color and texture // arrays are enabled and disabled around the compiled vertex array call qglEnableClientState (GL_VERTEX_ARRAY); // // make sure our GL state vector is set correctly // glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); qglDepthMask( GL_TRUE ); qglDisable( GL_DEPTH_TEST ); qglEnable( GL_SCISSOR_TEST ); qglDisable( GL_CULL_FACE ); qglDisable( GL_BLEND ); qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); qglClearDepth( 1.0 ); qglDrawBuffer( GL_FRONT ); #ifdef IOS qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); #else qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); #endif qglDrawBuffer( GL_BACK ); #ifdef IOS qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); #else qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); #endif }
/* ** GL_SetDefaultState */ void GL_SetDefaultState( void ) { qglClearDepth( 1.0f ); qglCullFace(GL_FRONT); qglColor4f (1,1,1,1); // initialize downstream texture unit if we're running // in a multitexture environment if ( qglActiveTextureARB ) { GL_SelectTexture( 1 ); GL_TextureMode( r_textureMode->string ); GL_TexEnv( GL_MODULATE ); qglDisable( GL_TEXTURE_2D ); GL_SelectTexture( 0 ); } qglEnable(GL_TEXTURE_2D); GL_TextureMode( r_textureMode->string ); GL_TexEnv( GL_MODULATE ); //qglShadeModel( GL_SMOOTH ); qglDepthFunc( GL_LEQUAL ); // // make sure our GL state vector is set correctly // glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; glState.vertexAttribsState = 0; glState.vertexAttribPointersSet = 0; glState.currentProgram = 0; qglUseProgramObjectARB(0); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glState.currentVBO = NULL; glState.currentIBO = NULL; qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); qglDepthMask( GL_TRUE ); qglDisable( GL_DEPTH_TEST ); qglEnable( GL_SCISSOR_TEST ); qglDisable( GL_CULL_FACE ); qglDisable( GL_BLEND ); qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); qglClearDepth( 1.0 ); qglDrawBuffer( GL_FRONT ); qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); qglDrawBuffer( GL_BACK ); qglClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT ); }
/* ** GLimp_BeginFrame */ void GLimp_BeginFrame( float camera_separation ) { if (gl_state.stereo_enabled && camera_separation < 0) qglDrawBuffer( GL_BACK_LEFT ); else if (gl_state.stereo_enabled && camera_separation > 0) qglDrawBuffer( GL_BACK_RIGHT ); else qglDrawBuffer( GL_BACK ); }
/* ** GLimp_BeginFrame */ void GLimp_BeginFrame( void ) { if( glState.cameraSeparation < 0 && glState.stereoEnabled ) { qglDrawBuffer( GL_BACK_LEFT ); } else if( glState.cameraSeparation > 0 && glState.stereoEnabled ) { qglDrawBuffer( GL_BACK_RIGHT ); } else { qglDrawBuffer( GL_BACK ); } }
/* ============= RB_SetBuffer ============= */ static void RB_SetBuffer( const void *data ) { const setBufferCommand_t *cmd; // see which draw buffer we want to render the frame to cmd = (const setBufferCommand_t *)data; backEnd.frameCount = cmd->frameCount; qglDrawBuffer( cmd->buffer ); // clear screen for debugging // automatically enable this with several other debug tools // that might leave unrendered portions of the screen if ( r_clear.GetFloat() || idStr::Length( r_clear.GetString() ) != 1 || r_lockSurfaces.GetBool() || r_singleArea.GetBool() || r_showOverDraw.GetBool() ) { float c[3]; if ( sscanf( r_clear.GetString(), "%f %f %f", &c[0], &c[1], &c[2] ) == 3 ) { qglClearColor( c[0], c[1], c[2], 1 ); } else if ( r_clear.GetInteger() == 2 ) { qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); } else if ( r_showOverDraw.GetBool() ) { qglClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); } else { qglClearColor( 0.4f, 0.0f, 0.25f, 1.0f ); } qglClear( GL_COLOR_BUFFER_BIT ); } }
void GLRB_SetDrawBuffer( int buffer ) { switch (buffer) { case DRAW_BUFFER_BACK: qglDrawBuffer( GL_BACK ); break; case DRAW_BUFFER_FRONT: qglDrawBuffer( GL_FRONT ); break; case DRAW_BUFFER_BACK_LEFT: qglDrawBuffer( GL_BACK_LEFT ); break; case DRAW_BUFFER_BACK_RIGHT: qglDrawBuffer( GL_BACK_RIGHT ); break; } }
/* ============= RB_DrawBuffer ============= */ static void RB_DrawBuffer( const void *data ) { const drawBufferCommand_t *cmd; cmd = (const drawBufferCommand_t *)data; qglDrawBuffer( cmd->buffer ); R_FrameBuffer_StartFrame(); // clear screen for debugging if ( r_clear->integer ) { qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } }
/* ============= RB_DrawBuffer ============= */ const void *RB_DrawBuffer( const void *data ) { const drawBufferCommand_t *cmd; cmd = (const drawBufferCommand_t *)data; qglDrawBuffer( cmd->buffer ); // clear screen for debugging if ( r_clear->integer ) { qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } return (const void *)(cmd + 1); }
/* * RFB_AttachTextureToObject */ void RFB_AttachTextureToObject( int object, image_t *texture ) { r_fbo_t *fbo; int attachment; assert( object > 0 && object <= r_num_framebuffer_objects ); if( object <= 0 || object > r_num_framebuffer_objects ) { return; } assert( texture != NULL ); if( !texture ) { return; } fbo = r_framebuffer_objects + object - 1; qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID ); if( texture->flags & IT_DEPTH ) { attachment = GL_DEPTH_ATTACHMENT_EXT; fbo->depthTexture = texture; } else { attachment = GL_COLOR_ATTACHMENT0_EXT; fbo->colorTexture = texture; #ifndef GL_ES_VERSION_2_0 qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT ); qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT ); #endif } texture->fbo = object; // attach texture qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, texture->texnum, 0 ); if( ( texture->flags & ( IT_DEPTH|IT_STENCIL ) ) == ( IT_DEPTH|IT_STENCIL ) ) { qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texture->texnum, 0 ); } qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_objectID ? r_bound_framebuffer_object->objectID : 0 ); }
/* ============= RB_DrawBuffer ============= */ const void *RB_DrawBuffer( const void *data ) { const drawBufferCommand_t *cmd; cmd = (const drawBufferCommand_t *)data; qglDrawBuffer( cmd->buffer ); // clear screen for debugging if (tr.world && tr.world->globalFog != -1) { unsigned i = tr.world->fogs[tr.world->globalFog].colorInt; qglClearColor( ( (byte *)&i )[0] / 255.0, ( (byte *)&i )[1] / 255.0, ( (byte *)&i )[2] / 255.0, 1.0 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } else if ( r_clear->integer ) { qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } return (const void *)(cmd + 1); }
/* ============= RB_DrawBuffer ============= */ const void *RB_DrawBuffer( const void *data ) { const drawBufferCommand_t *cmd; cmd = (const drawBufferCommand_t *)data; // finish any 2D drawing if needed if(tess.numIndexes) RB_EndSurface(); if (glRefConfig.framebufferObject) FBO_Bind(NULL); qglDrawBuffer( cmd->buffer ); // clear screen for debugging if ( r_clear->integer ) { qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } return (const void *)(cmd + 1); }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd = NULL; colorMaskCommand_t *colcmd = NULL; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_IssuePendingRenderCommands(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_IssuePendingRenderCommands(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_IssuePendingRenderCommands(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // NVidia stuff // #ifndef VCMODS_OPENGLES // fog control if ( glConfig.NVFogAvailable && r_nv_fogdist_mode->modified ) { r_nv_fogdist_mode->modified = qfalse; if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE_ABSOLUTE_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE_ABSOLUTE_NV; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_RADIAL_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; } else { // in case this was really 'else', store a valid value for next time glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; ri.Cvar_Set( "r_nv_fogdist_mode", "GL_EYE_RADIAL_NV" ); } } #endif // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_IssuePendingRenderCommands(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_IssuePendingRenderCommands(); if ( ( err = qglGetError() ) != GL_NO_ERROR ) { ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err ); } } if (glConfig.stereoEnabled) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; cmd->commandId = RC_DRAW_BUFFER; if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if(r_anaglyphMode->integer) { if(r_anaglyphMode->modified) { // clear both, front and backbuffer. qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglDrawBuffer(GL_FRONT); qglClear(GL_COLOR_BUFFER_BIT); qglDrawBuffer(GL_BACK); qglClear(GL_COLOR_BUFFER_BIT); r_anaglyphMode->modified = qfalse; } if(stereoFrame == STEREO_LEFT) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else if(stereoFrame == STEREO_RIGHT) { clearDepthCommand_t *cldcmd; if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) return; cldcmd->commandId = RC_CLEARDEPTH; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); colcmd->commandId = RC_COLORMASK; } else { if(stereoFrame != STEREO_CENTER) ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; } if(cmd) { cmd->commandId = RC_DRAW_BUFFER; if(r_anaglyphMode->modified) { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); r_anaglyphMode->modified = qfalse; } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) cmd->buffer = (int)GL_FRONT; else cmd->buffer = (int)GL_BACK; } } tr.refdef.stereoFrame = stereoFrame; }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd = NULL; colorMaskCommand_t *colcmd = NULL; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_IssuePendingRenderCommands(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_IssuePendingRenderCommands(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_IssuePendingRenderCommands(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_IssuePendingRenderCommands(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_IssuePendingRenderCommands(); if ((err = qglGetError()) != GL_NO_ERROR) ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err); } if (glConfig.stereoEnabled) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; cmd->commandId = RC_DRAW_BUFFER; if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if(r_anaglyphMode->integer) { if(r_anaglyphMode->modified) { // clear both, front and backbuffer. qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = GL_FALSE; backEnd.colorMask[1] = GL_FALSE; backEnd.colorMask[2] = GL_FALSE; backEnd.colorMask[3] = GL_FALSE; qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); if (glRefConfig.framebufferObject) { // clear all framebuffers if (tr.msaaResolveFbo) { FBO_Bind(tr.msaaResolveFbo); qglClear(GL_COLOR_BUFFER_BIT); } if (tr.renderFbo) { FBO_Bind(tr.renderFbo); qglClear(GL_COLOR_BUFFER_BIT); } FBO_Bind(NULL); } qglDrawBuffer(GL_FRONT); qglClear(GL_COLOR_BUFFER_BIT); qglDrawBuffer(GL_BACK); qglClear(GL_COLOR_BUFFER_BIT); r_anaglyphMode->modified = qfalse; } if(stereoFrame == STEREO_LEFT) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else if(stereoFrame == STEREO_RIGHT) { clearDepthCommand_t *cldcmd; if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) return; cldcmd->commandId = RC_CLEARDEPTH; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); colcmd->commandId = RC_COLORMASK; } else { if(stereoFrame != STEREO_CENTER) ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; } if(cmd) { cmd->commandId = RC_DRAW_BUFFER; if(r_anaglyphMode->modified) { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = 0; backEnd.colorMask[1] = 0; backEnd.colorMask[2] = 0; backEnd.colorMask[3] = 0; r_anaglyphMode->modified = qfalse; } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) cmd->buffer = (int)GL_FRONT; else cmd->buffer = (int)GL_BACK; } } tr.refdef.stereoFrame = stereoFrame; }
/* * RFB_RegisterObject */ int RFB_RegisterObject( int width, int height, bool builtin, bool depthRB, bool stencilRB ) { int i; GLuint fbID; GLuint rbID; r_fbo_t *fbo; if( !r_frambuffer_objects_initialized ) return 0; for( i = 0, fbo = r_framebuffer_objects; i < r_num_framebuffer_objects; i++, fbo++ ) { if( !fbo->objectID ) { // free slot goto found; } } if( i == MAX_FRAMEBUFFER_OBJECTS ) { Com_Printf( S_COLOR_YELLOW "RFB_RegisterObject: framebuffer objects limit exceeded\n" ); return 0; } i = r_num_framebuffer_objects++; fbo = r_framebuffer_objects + i; found: qglGenFramebuffersEXT( 1, &fbID ); memset( fbo, 0, sizeof( *fbo ) ); fbo->objectID = fbID; if( builtin ) fbo->registrationSequence = -1; else fbo->registrationSequence = rsh.registrationSequence; fbo->width = width; fbo->height = height; qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID ); #ifndef GL_ES_VERSION_2_0 // until a color texture is attached, don't enable drawing to the buffer qglDrawBuffer( GL_NONE ); qglReadBuffer( GL_NONE ); #endif if( depthRB ) { int format; qglGenRenderbuffersEXT( 1, &rbID ); fbo->depthRenderBuffer = rbID; qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID ); if( stencilRB ) format = GL_DEPTH24_STENCIL8_EXT; else if( glConfig.ext.depth24 ) format = GL_DEPTH_COMPONENT24; else if( glConfig.ext.depth_nonlinear ) format = GL_DEPTH_COMPONENT16_NONLINEAR_NV; else format = GL_DEPTH_COMPONENT16; qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height ); qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbID ); if( stencilRB ) qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbID ); qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 ); } if( r_bound_framebuffer_objectID ) qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_object->objectID ); else qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); return i+1; }
/* ============= RB_DrawBuffer ============= */ const void *RB_DrawBuffer( const void *data ) { const drawBufferCommand_t *cmd; cmd = (const drawBufferCommand_t *)data; qglDrawBuffer( cmd->buffer ); // clear screen for debugging if (tr.world && tr.refdef.doLAGoggles) { fog_t *fog = &tr.world->fogs[tr.world->numfogs]; qglClearColor(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], 1.0f ); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else if (tr.world && tr.world->globalFog != -1) { const unsigned int i = tr.world->fogs[tr.world->globalFog].colorInt; qglClearColor( ( (byte *)&i )[0] / 255.0, ( (byte *)&i )[1] / 255.0, ( (byte *)&i )[2] / 255.0, 1.0 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } else if ( r_clear->integer ) { // clear screen for debugging int i = r_clear->integer; if (i == 42) { i = Q_irand(0,8); } switch (i) { default: qglClearColor( 1, 0, 0.5, 1 ); break; case 1: qglClearColor( 1.0, 0.0, 0.0, 1.0); //red break; case 2: qglClearColor( 0.0, 1.0, 0.0, 1.0); //green break; case 3: qglClearColor( 1.0, 1.0, 0.0, 1.0); //yellow break; case 4: qglClearColor( 0.0, 0.0, 1.0, 1.0); //blue break; case 5: qglClearColor( 0.0, 1.0, 1.0, 1.0); //cyan break; case 6: qglClearColor( 1.0, 0.0, 1.0, 1.0); //magenta break; case 7: qglClearColor( 1.0, 1.0, 1.0, 1.0); //white break; case 8: qglClearColor( 0.0, 0.0, 0.0, 1.0); //black break; } qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } return (const void *)(cmd + 1); }
/* * RFB_AttachTextureToObject */ bool RFB_AttachTextureToObject( int object, bool depth, int target, image_t *texture ) { r_fbo_t *fbo; int attachment; GLuint texnum = 0; assert( object > 0 && object <= r_num_framebuffer_objects ); if( object <= 0 || object > r_num_framebuffer_objects ) { return false; } if( target < 0 || target >= MAX_FRAMEBUFFER_COLOR_ATTACHMENTS ) { return false; } if( target > 0 && !glConfig.ext.draw_buffers ) { return false; } fbo = r_framebuffer_objects + object - 1; qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID ); bind: if( depth ) { attachment = GL_DEPTH_ATTACHMENT_EXT; if( texture ) { assert( texture->flags & IT_DEPTH ); texnum = texture->texnum; texture->fbo = object; } } else { #ifndef GL_ES_VERSION_2_0 const GLenum fboBuffers[8] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_COLOR_ATTACHMENT4_EXT, GL_COLOR_ATTACHMENT5_EXT, GL_COLOR_ATTACHMENT6_EXT, GL_COLOR_ATTACHMENT7_EXT, }; #endif attachment = GL_COLOR_ATTACHMENT0_EXT + target; #ifndef GL_ES_VERSION_2_0 if( target > 0 && texture ) { qglDrawBuffersARB( target + 1, fboBuffers ); } else { if( glConfig.ext.draw_buffers ) { qglDrawBuffersARB( 0, fboBuffers ); } qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT ); qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT ); } #endif if( texture ) { assert( !( texture->flags & IT_DEPTH ) ); texnum = texture->texnum; texture->fbo = object; } } // attach texture qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment, GL_TEXTURE_2D, texnum, 0 ); if( texture ) { if( ( texture->flags & ( IT_DEPTH | IT_STENCIL ) ) == ( IT_DEPTH | IT_STENCIL ) ) { qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texnum, 0 ); } } else { if( depth ) { qglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texnum, 0 ); } } qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_objectID ? r_bound_framebuffer_object->objectID : 0 ); // check framebuffer status and unbind if failed if( !RFB_CheckObjectStatus() ) { if( texture ) { texture = NULL; goto bind; } return false; } if( depth ) { fbo->depthTexture = texture; } else { fbo->colorTexture[target] = texture; } return true; }
/* * RFB_BlitObject * * The target FBO must be equal or greater in both dimentions than * the currently bound FBO! */ void RFB_BlitObject( int src, int dest, int bitMask, int mode, int filter, int readAtt, int drawAtt ) { int bits; int destObj; int dx, dy, dw, dh; r_fbo_t scrfbo; r_fbo_t *fbo; r_fbo_t *destfbo; if( !glConfig.ext.framebuffer_blit ) { return; } assert( src >= 0 && src <= r_num_framebuffer_objects ); if( src < 0 || src > r_num_framebuffer_objects ) { return; } if( src == 0 ) { fbo = &scrfbo; } else { fbo = r_framebuffer_objects + src - 1; } assert( dest >= 0 && dest <= r_num_framebuffer_objects ); if( dest < 0 || dest > r_num_framebuffer_objects ) { return; } if( dest ) { destfbo = r_framebuffer_objects + dest - 1; } else { destfbo = NULL; } bits = bitMask; if( !bits ) { return; } RB_ApplyScissor(); if( src == 0 ) { memset( fbo, 0, sizeof( *fbo ) ); fbo->width = glConfig.width; fbo->height = glConfig.height; } if( destfbo ) { dw = destfbo->width; dh = destfbo->height; destObj = destfbo->objectID; } else { dw = glConfig.width; dh = glConfig.height; destObj = 0; } switch( mode ) { case FBO_COPY_CENTREPOS: dx = ( dw - fbo->width ) / 2; dy = ( dh - fbo->height ) / 2; dw = fbo->width; dh = fbo->height; break; case FBO_COPY_INVERT_Y: dx = 0; dy = dh - fbo->height; dw = fbo->width; dh = fbo->height; break; case FBO_COPY_NORMAL_DST_SIZE: dx = 0; dy = 0; //dw = dw; //dh = dh; break; default: dx = 0; dy = 0; dw = fbo->width; dh = fbo->height; break; } qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); qglBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, fbo->objectID ); qglBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, destObj ); #ifndef GL_ES_VERSION_2_0 if( src == 0 ) { qglReadBuffer( GL_BACK ); qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT + drawAtt ); } else { qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT + readAtt ); qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT + drawAtt ); } #endif qglBlitFramebufferEXT( 0, 0, fbo->width, fbo->height, dx, dy, dx + dw, dy + dh, bits, filter ); qglBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, 0 ); qglBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, 0 ); qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID ); #ifndef GL_ES_VERSION_2_0 if( src == 0 ) { qglReadBuffer( GL_BACK ); qglDrawBuffer( GL_BACK ); } else { qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT ); qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT ); } #endif assert( qglGetError() == GL_NO_ERROR ); }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd = NULL; colorMaskCommand_t *colcmd = NULL; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_IssuePendingRenderCommands(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_IssuePendingRenderCommands(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_IssuePendingRenderCommands(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // ATI stuff // // TRUFORM if ( qglPNTrianglesiATI ) { // tess if ( r_ati_truform_tess->modified ) { r_ati_truform_tess->modified = qfalse; // cap if necessary if ( r_ati_truform_tess->value > glConfig.ATIMaxTruformTess ) { ri.Cvar_Set( "r_ati_truform_tess", va( "%d",glConfig.ATIMaxTruformTess ) ); } qglPNTrianglesiATI( GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, r_ati_truform_tess->value ); } // point mode if ( r_ati_truform_pointmode->modified ) { r_ati_truform_pointmode->modified = qfalse; // GR - shorten the mode name if ( !Q_stricmp( r_ati_truform_pointmode->string, "LINEAR" ) ) { glConfig.ATIPointMode = (int)GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI; // GR - fix point mode change } else if ( !Q_stricmp( r_ati_truform_pointmode->string, "CUBIC" ) ) { glConfig.ATIPointMode = (int)GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI; } else { // bogus value, set to valid glConfig.ATIPointMode = (int)GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI; ri.Cvar_Set( "r_ati_truform_pointmode", "LINEAR" ); } qglPNTrianglesiATI( GL_PN_TRIANGLES_POINT_MODE_ATI, glConfig.ATIPointMode ); } // normal mode if ( r_ati_truform_normalmode->modified ) { r_ati_truform_normalmode->modified = qfalse; // GR - shorten the mode name if ( !Q_stricmp( r_ati_truform_normalmode->string, "LINEAR" ) ) { glConfig.ATINormalMode = (int)GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI; // GR - fix normal mode change } else if ( !Q_stricmp( r_ati_truform_normalmode->string, "QUADRATIC" ) ) { glConfig.ATINormalMode = (int)GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI; } else { // bogus value, set to valid glConfig.ATINormalMode = (int)GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI; ri.Cvar_Set( "r_ati_truform_normalmode", "LINEAR" ); } qglPNTrianglesiATI( GL_PN_TRIANGLES_NORMAL_MODE_ATI, glConfig.ATINormalMode ); } } // // NVidia stuff // // fog control if ( glConfig.NVFogAvailable && r_nv_fogdist_mode->modified ) { r_nv_fogdist_mode->modified = qfalse; if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE_ABSOLUTE_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE_ABSOLUTE_NV; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_RADIAL_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; } else { // in case this was really 'else', store a valid value for next time glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; ri.Cvar_Set( "r_nv_fogdist_mode", "GL_EYE_RADIAL_NV" ); } } // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_IssuePendingRenderCommands(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_IssuePendingRenderCommands(); if ( ( err = qglGetError() ) != GL_NO_ERROR ) { ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err ); } } if (glConfig.stereoEnabled) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; cmd->commandId = RC_DRAW_BUFFER; if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if(r_anaglyphMode->integer) { if(r_anaglyphMode->modified) { // clear both, front and backbuffer. qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = GL_FALSE; backEnd.colorMask[1] = GL_FALSE; backEnd.colorMask[2] = GL_FALSE; backEnd.colorMask[3] = GL_FALSE; if (glRefConfig.framebufferObject) { // clear all framebuffers if (tr.msaaResolveFbo) { FBO_Bind(tr.msaaResolveFbo); qglClear(GL_COLOR_BUFFER_BIT); } if (tr.renderFbo) { FBO_Bind(tr.renderFbo); qglClear(GL_COLOR_BUFFER_BIT); } FBO_Bind(NULL); } qglDrawBuffer(GL_FRONT); qglClear(GL_COLOR_BUFFER_BIT); qglDrawBuffer(GL_BACK); qglClear(GL_COLOR_BUFFER_BIT); r_anaglyphMode->modified = qfalse; } if(stereoFrame == STEREO_LEFT) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else if(stereoFrame == STEREO_RIGHT) { clearDepthCommand_t *cldcmd; if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) return; cldcmd->commandId = RC_CLEARDEPTH; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); colcmd->commandId = RC_COLORMASK; } else { if(stereoFrame != STEREO_CENTER) ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; } if(cmd) { cmd->commandId = RC_DRAW_BUFFER; if(r_anaglyphMode->modified) { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = 0; backEnd.colorMask[1] = 0; backEnd.colorMask[2] = 0; backEnd.colorMask[3] = 0; r_anaglyphMode->modified = qfalse; } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) cmd->buffer = (int)GL_FRONT; else cmd->buffer = (int)GL_BACK; } } tr.refdef.stereoFrame = stereoFrame; }
/* ============ FBO_Init ============ */ void FBO_Init(void) { int i; // int width, height, hdrFormat, multisample; int hdrFormat, multisample; ri.Printf(PRINT_ALL, "------- FBO_Init -------\n"); if(!glRefConfig.framebufferObject) return; tr.numFBOs = 0; GL_CheckErrors(); R_IssuePendingRenderCommands(); /* if(glRefConfig.textureNonPowerOfTwo) { width = glConfig.vidWidth; height = glConfig.vidHeight; } else { width = NextPowerOfTwo(glConfig.vidWidth); height = NextPowerOfTwo(glConfig.vidHeight); } */ hdrFormat = GL_RGBA8; if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat) { hdrFormat = GL_RGBA16F_ARB; } qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample); if (r_ext_framebuffer_multisample->integer < multisample) { multisample = r_ext_framebuffer_multisample->integer; } if (multisample < 2 || !glRefConfig.framebufferBlit) multisample = 0; if (multisample != r_ext_framebuffer_multisample->integer) { ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample); } // only create a render FBO if we need to resolve MSAA or do HDR // otherwise just render straight to the screen (tr.renderFbo = NULL) if (multisample && glRefConfig.framebufferMultisample) { tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); FBO_Bind(tr.renderFbo); FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample); FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample); R_CheckFBO(tr.renderFbo); tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height); FBO_Bind(tr.msaaResolveFbo); //FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0); FBO_AttachTextureImage(tr.renderImage, 0); //FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); R_CheckFBO(tr.msaaResolveFbo); } else if (r_hdr->integer) { tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); FBO_Bind(tr.renderFbo); //FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0); FBO_AttachTextureImage(tr.renderImage, 0); //FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); R_CheckFBO(tr.renderFbo); } // clear render buffer // this fixes the corrupt screen bug with r_hdr 1 on older hardware if (tr.renderFbo) { FBO_Bind(tr.renderFbo); qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); FBO_Bind(NULL); } if (r_drawSunRays->integer) { tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height); FBO_Bind(tr.sunRaysFbo); FBO_AttachTextureImage(tr.sunRaysImage, 0); R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); R_CheckFBO(tr.sunRaysFbo); } // FIXME: Don't use separate color/depth buffers for a shadow buffer if (MAX_DRAWN_PSHADOWS && tr.pshadowMaps[0]) { for( i = 0; i < MAX_DRAWN_PSHADOWS; i++) { tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height); FBO_Bind(tr.pshadowFbos[i]); //FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0); FBO_AttachTextureImage(tr.pshadowMaps[i], 0); FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0); //R_AttachFBOTextureDepth(tr.textureDepthImage->texnum); R_CheckFBO(tr.pshadowFbos[i]); } } if (tr.sunShadowDepthImage[0]) { for ( i = 0; i < 4; i++) { tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height); FBO_Bind(tr.sunShadowFbo[i]); //FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0); //FBO_AttachTextureImage(tr.sunShadowImage, 0); qglDrawBuffer(GL_NONE); qglReadBuffer(GL_NONE); //FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum); R_CheckFBO(tr.sunShadowFbo[i]); } tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height); FBO_Bind(tr.screenShadowFbo); FBO_AttachTextureImage(tr.screenShadowImage, 0); R_CheckFBO(tr.screenShadowFbo); } for (i = 0; i < 2; i++) { tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height); FBO_Bind(tr.textureScratchFbo[i]); //FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0); FBO_AttachTextureImage(tr.textureScratchImage[i], 0); R_CheckFBO(tr.textureScratchFbo[i]); } { tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height); FBO_Bind(tr.calcLevelsFbo); //FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0); FBO_AttachTextureImage(tr.calcLevelsImage, 0); R_CheckFBO(tr.calcLevelsFbo); } { tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height); FBO_Bind(tr.targetLevelsFbo); //FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0); FBO_AttachTextureImage(tr.targetLevelsImage, 0); R_CheckFBO(tr.targetLevelsFbo); } for (i = 0; i < 2; i++) { tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height); FBO_Bind(tr.quarterFbo[i]); //FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0); FBO_AttachTextureImage(tr.quarterImage[i], 0); R_CheckFBO(tr.quarterFbo[i]); } if (r_ssao->integer) { tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height); FBO_Bind(tr.hdrDepthFbo); FBO_AttachTextureImage(tr.hdrDepthImage, 0); R_CheckFBO(tr.hdrDepthFbo); tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height); FBO_Bind(tr.screenSsaoFbo); FBO_AttachTextureImage(tr.screenSsaoImage, 0); R_CheckFBO(tr.screenSsaoFbo); } if (tr.renderCubeImage) { tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height); FBO_Bind(tr.renderCubeFbo); //FBO_AttachTextureImage(tr.renderCubeImage, 0); R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, tr.renderCubeImage->texnum, 0); glState.currentFBO->colorImage[0] = tr.renderCubeImage; FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); R_CheckFBO(tr.renderCubeFbo); } GL_CheckErrors(); FBO_Bind(NULL); }
/* * RFB_RegisterObject */ int RFB_RegisterObject( int width, int height, bool builtin, bool depthRB, bool stencilRB, bool colorRB, int samples, bool useFloat, bool sRGB ) { int i; int format; GLuint fbID; GLuint rbID = 0; r_fbo_t *fbo = NULL; if( !r_frambuffer_objects_initialized ) { return 0; } #ifdef GL_ES_VERSION_2_0 if( samples ) { return 0; } #else if( samples && !glConfig.ext.framebuffer_multisample ) { return 0; } #endif for( i = 0, fbo = r_framebuffer_objects; i < r_num_framebuffer_objects; i++, fbo++ ) { if( !fbo->objectID ) { // free slot goto found; } } if( i == MAX_FRAMEBUFFER_OBJECTS ) { Com_Printf( S_COLOR_YELLOW "RFB_RegisterObject: framebuffer objects limit exceeded\n" ); return 0; } clamp_high( samples, glConfig.maxFramebufferSamples ); i = r_num_framebuffer_objects++; fbo = r_framebuffer_objects + i; found: qglGenFramebuffersEXT( 1, &fbID ); memset( fbo, 0, sizeof( *fbo ) ); fbo->objectID = fbID; if( builtin ) { fbo->registrationSequence = -1; } else { fbo->registrationSequence = rsh.registrationSequence; } fbo->width = width; fbo->height = height; fbo->samples = samples; fbo->sRGB = sRGB; qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID ); if( colorRB ) { format = glConfig.forceRGBAFramebuffers ? GL_RGBA : GL_RGB; if( useFloat ) { format = glConfig.forceRGBAFramebuffers ? GL_RGBA16F_ARB : GL_RGB16F_ARB; } qglGenRenderbuffersEXT( 1, &rbID ); fbo->colorRenderBuffer = rbID; qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID ); #ifndef GL_ES_VERSION_2_0 if( samples ) { qglRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, samples, format, width, height ); } else #endif qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height ); } #ifndef GL_ES_VERSION_2_0 else { // until a color texture is attached, don't enable drawing to the buffer qglDrawBuffer( GL_NONE ); qglReadBuffer( GL_NONE ); } #endif if( depthRB ) { qglGenRenderbuffersEXT( 1, &rbID ); fbo->depthRenderBuffer = rbID; qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rbID ); if( stencilRB ) { format = GL_DEPTH24_STENCIL8_EXT; } else if( glConfig.ext.depth24 ) { format = GL_DEPTH_COMPONENT24; } else if( glConfig.ext.depth_nonlinear ) { format = GL_DEPTH_COMPONENT16_NONLINEAR_NV; } else { format = GL_DEPTH_COMPONENT16; } #ifndef GL_ES_VERSION_2_0 if( samples ) { qglRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, samples, format, width, height ); } else #endif qglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, format, width, height ); if( stencilRB ) { fbo->stencilRenderBuffer = rbID; } } if( rbID ) { qglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 ); } if( fbo->colorRenderBuffer ) { qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fbo->colorRenderBuffer ); } if( fbo->depthRenderBuffer ) { qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthRenderBuffer ); } if( fbo->stencilRenderBuffer ) { qglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->stencilRenderBuffer ); } if( colorRB && depthRB ) { if( !RFB_CheckObjectStatus() ) { goto fail; } } if( r_bound_framebuffer_objectID ) { qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, r_bound_framebuffer_object->objectID ); } else { qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); } return i + 1; fail: RFB_DeleteObject( fbo ); qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); return 0; }
/* ============= RB_DrawBuffer ============= */ const void *RB_DrawBuffer( const void *data ) { const drawBufferCommand_t *cmd; cmd = (const drawBufferCommand_t *)data; qglDrawBuffer( cmd->buffer ); // clear screen for debugging if (!( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) && tr.world && tr.refdef.rdflags & RDF_doLAGoggles) { const fog_t *fog = &tr.world->fogs[tr.world->numfogs]; qglClearColor(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], 1.0f ); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else if (!( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) && tr.world && tr.world->globalFog != -1 && tr.sceneCount)//don't clear during menus, wait for real scene { 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 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } else if ( r_clear->integer ) { // clear screen for debugging int i = r_clear->integer; if (i == 42) { i = Q_irand(0,8); } switch (i) { default: qglClearColor( 1, 0, 0.5, 1 ); break; case 1: qglClearColor( 1.0, 0.0, 0.0, 1.0); //red break; case 2: qglClearColor( 0.0, 1.0, 0.0, 1.0); //green break; case 3: qglClearColor( 1.0, 1.0, 0.0, 1.0); //yellow break; case 4: qglClearColor( 0.0, 0.0, 1.0, 1.0); //blue break; case 5: qglClearColor( 0.0, 1.0, 1.0, 1.0); //cyan break; case 6: qglClearColor( 1.0, 0.0, 1.0, 1.0); //magenta break; case 7: qglClearColor( 1.0, 1.0, 1.0, 1.0); //white break; case 8: qglClearColor( 0.0, 0.0, 0.0, 1.0); //black break; } qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } return (const void *)(cmd + 1); }