From dba02e35d45a3c11aa4478ef39f8e1008a02e0fc Mon Sep 17 00:00:00 2001 From: ehofman Date: Fri, 2 Apr 2004 14:40:54 +0000 Subject: [PATCH] Frederic Bouvier: FG_ENABLE_MULTIPASS_CLOUDS must be defined to enable the algorithm. I made this because the stencil buffer must be initialized at the beginning of the program and OpenGL can fallback to software rendering if it can't find a visual with stencil buffer. I didn't touch the configure script, so CXXFLAGS=-DFG_ENABLE_MULTIPASS_CLOUDS must be set before running ./configure. If FG_ENABLE_MULTIPASS_CLOUDS is defined, the main render loop begins by reading the /sim/rendering/multi-pass-clouds property. It is a boolean property so there are only two quality levels. false means no multi pass and no use of the stencil buffer, true means an additionnal pass for both upper and lower cloud layers. The algorithms are as follow : /sim/rendering/multi-pass-clouds=false 1. draw sky dome 2. draw terrain only 3. draw clouds above the viewer 4. draw models except the aircraft 5. draw clouds below the viewer 6. draw the aircraft. The cloud rendering doesn't update the depth buffer. This means that models overwrite clouds above the viewer. This is only noticeable for tall buildings and when flying very low. Also, drawing low clouds after models means that they are not blended with models' translucent surfaces. Large transparent area require alpha test enabled and AI aircraft canopy are making holes. The pilot's aircraft being rendered at the end, there is no problem with canopy or prop disc. /sim/rendering/multi-pass-clouds=true 1. draw the sky dome 2. draw the terrain only 3. draw all clouds 4. draw models except the aircraft 5. redraw the clouds where the models where drawn ( stencil test on ) 6. draw the aircraft The assumptions made by this algoritm are that the terrain is not transparent ( should be true in all cases and that there are no clouds between the aircraft and the viewer. Assuming these facts, there should be no blending bugs. The screenshot rendering is not updated yet. --- src/Main/fg_os.cxx | 3 +- src/Main/fg_os.hxx | 2 +- src/Main/main.cxx | 97 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 82 insertions(+), 20 deletions(-) diff --git a/src/Main/fg_os.cxx b/src/Main/fg_os.cxx index 4a1eb9c0f..81ddf0b55 100644 --- a/src/Main/fg_os.cxx +++ b/src/Main/fg_os.cxx @@ -177,10 +177,11 @@ void fgRequestRedraw() glutPostRedisplay(); } -void fgOSOpenWindow(int w, int h, int bpp, bool alpha) +void fgOSOpenWindow(int w, int h, int bpp, bool alpha, bool stencil) { int mode = GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE; if(alpha) mode |= GLUT_ALPHA; + if(stencil) mode |= GLUT_STENCIL; glutInitDisplayMode(mode); glutInitWindowSize(w, h); diff --git a/src/Main/fg_os.hxx b/src/Main/fg_os.hxx index ba36a0879..8d05d49cc 100644 --- a/src/Main/fg_os.hxx +++ b/src/Main/fg_os.hxx @@ -38,7 +38,7 @@ enum { KEYMOD_NONE = 0, // void fgOSInit(int* argc, char** argv); -void fgOSOpenWindow(int w, int h, int bpp, bool alpha); +void fgOSOpenWindow(int w, int h, int bpp, bool alpha, bool stencil); void fgOSFullScreen(); void fgOSMainLoop(); diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 2cbc13538..57f1713e5 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -299,7 +299,8 @@ void trRenderFrame( void ) { // we need a white diffuse light for the phase of the moon ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, white ); - thesky->preDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER, fog_exp2_density ); + thesky->preDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER ); + thesky->drawUpperClouds( fog_exp2_density ); // draw the ssg scene // return to the desired diffuse color @@ -317,7 +318,7 @@ void trRenderFrame( void ) { ssgCullAndDraw( globals->get_scenery()->get_gnd_lights_root() ); if (fgGetBool("/environment/clouds/status")) - thesky->postDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER ); + thesky->drawLowerClouds(); globals->get_model_mgr()->draw(); globals->get_aircraft_model()->draw(); @@ -330,6 +331,12 @@ void fgRenderFrame() { bool skyblend = fgGetBool("/sim/rendering/skyblend"); bool enhanced_lighting = fgGetBool("/sim/rendering/enhanced-lighting"); bool distance_attenuation = fgGetBool("/sim/rendering/distance-attenuation"); +#ifdef FG_ENABLE_MULTIPASS_CLOUDS + bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds"); +#else + bool multi_pass_clouds = false; +#endif + bool draw_clouds = fgGetBool("/environment/clouds/status"); GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 }; @@ -434,6 +441,10 @@ void fgRenderFrame() { l->sky_color()[2], l->sky_color()[3]); clear_mask |= GL_COLOR_BUFFER_BIT; } + if ( multi_pass_clouds && draw_clouds ) { + glClearStencil( 0 ); + clear_mask |= GL_STENCIL_BUFFER_BIT; + } glClear( clear_mask ); // Tell GL we are switching to model view parameters @@ -597,15 +608,12 @@ void fgRenderFrame() { globals->get_multiplayer_rx_mgr()->Update(); #endif - if ( draw_otw && skyblend ) - { + if ( draw_otw && skyblend ) { // draw the sky backdrop // we need a white diffuse light for the phase of the moon ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, white ); - - thesky->preDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER, fog_exp2_density ); - + thesky->preDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER ); // return to the desired diffuse color ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() ); } @@ -620,7 +628,62 @@ void fgRenderFrame() { glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); } if ( draw_otw ) { - ssgCullAndDraw( globals->get_scenery()->get_scene_graph() ); + if ( draw_clouds ) { + + // Draw the terrain + FGTileMgr::set_tile_filter( true ); + sgSetModelFilter( false ); + ssgCullAndDraw( globals->get_scenery()->get_scene_graph() ); + + // Disable depth buffer update, draw the clouds + glDepthMask( GL_FALSE ); + thesky->drawUpperClouds( fog_exp2_density ); + if ( multi_pass_clouds ) { + thesky->drawLowerClouds(); + } + glDepthMask( GL_TRUE ); + + if ( multi_pass_clouds ) { + // Draw the objects except the aircraft + // and update the stencil buffer with 1 + glEnable( GL_STENCIL_TEST ); + glStencilFunc( GL_ALWAYS, 1, 1 ); + glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE ); + } + FGTileMgr::set_tile_filter( false ); + sgSetModelFilter( true ); + globals->get_aircraft_model()->select( false ); + ssgCullAndDraw( globals->get_scenery()->get_scene_graph() ); + + if ( multi_pass_clouds ) { + // Disable depth buffer update, draw the clouds where the + // objects overwrite the already drawn clouds, by testing + // the stencil buffer against 1 + glDepthMask( GL_FALSE ); + glStencilFunc( GL_EQUAL, 1, 1 ); + glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); + thesky->drawUpperClouds( fog_exp2_density ); + thesky->drawLowerClouds(); + glDepthMask( GL_TRUE ); + glDisable( GL_STENCIL_TEST ); + } else { + glDepthMask( GL_FALSE ); + thesky->drawLowerClouds(); + glDepthMask( GL_TRUE ); + } + + // Draw the aircraft + sgSetModelFilter( false ); + globals->get_aircraft_model()->select( true ); + ssgCullAndDraw( globals->get_scenery()->get_scene_graph() ); + FGTileMgr::set_tile_filter( true ); + sgSetModelFilter( true ); + } else { + FGTileMgr::set_tile_filter( true ); + sgSetModelFilter( true ); + globals->get_aircraft_model()->select( true ); + ssgCullAndDraw( globals->get_scenery()->get_scene_graph() ); + } } // This is a bit kludgy. Every 200 frames, do an extra @@ -724,15 +787,6 @@ void fgRenderFrame() { ssgCullAndDraw( globals->get_scenery()->get_gnd_lights_root() ); } - if ( skyblend ) { - // draw the sky cloud layers - if ( draw_otw && fgGetBool("/environment/clouds/status") ) - { - thesky->postDraw( cur_fdm_state->get_Altitude() - * SG_FEET_TO_METER ); - } - } - if ( draw_otw && fgGetBool("/sim/rendering/clouds3d") ) { glDisable( GL_FOG ); @@ -1409,11 +1463,18 @@ bool fgMainInit( int argc, char **argv ) { fgRegisterIdleHandler( fgIdleFunction ); fgRegisterDrawHandler( fgRenderFrame ); +#ifdef FG_ENABLE_MULTIPASS_CLOUDS + bool get_stencil_buffer = true; +#else + bool get_stencil_buffer = false; +#endif + // Clouds3D requires an alpha channel fgOSOpenWindow( fgGetInt("/sim/startup/xsize"), fgGetInt("/sim/startup/ysize"), fgGetInt("/sim/rendering/bits-per-pixel"), - fgGetBool("/sim/rendering/clouds3d") ); + fgGetBool("/sim/rendering/clouds3d"), + get_stencil_buffer ); // This seems to be the absolute earliest in the init sequence // that these calls will return valid info. Too bad it's after -- 2.39.5