Continued work to clean up the hires screen shot code and move it back towards
a working state. I still see an anomoly when taking a screen shot from inside a 3d cockpit, but external (chase/tower) views seem to work well. I also added a property to control how many screen-res tiles are generated in the output. Theoretically, you can now generate unlimited resolution screen shots, or limited only by your disk space and patience. Today I successfully generated a 20*1024 x 20*768 (20480x15360) resolution screen shot. If you rendered that at 100 dpi it would cover a poster of about 17 feet by 12.8 feet. Good luck trying to display something that big or convert it to anything useful on a typical PC. :-)
This commit is contained in:
parent
600384d5c7
commit
41e217fb9a
4 changed files with 57 additions and 175 deletions
|
@ -57,9 +57,9 @@ extern int gui_menu_on;
|
|||
extern void saveFlight(puObject *);
|
||||
extern void loadFlight(puObject *);
|
||||
extern void reInit(puObject *);
|
||||
extern void dumpSnapShot(puObject *);
|
||||
extern void fgDumpSnapShotWrapper(puObject *);
|
||||
#ifdef TR_HIRES_SNAP
|
||||
extern void dumpHiResSnapShot(puObject *);
|
||||
extern void fgHiResDumpWrapper(puObject *);
|
||||
extern void fgHiResDump();
|
||||
#endif
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__)
|
||||
|
|
|
@ -138,9 +138,9 @@ const __fg_gui_fn_t __fg_gui_fn[] = {
|
|||
{"loadFlight", loadFlight},
|
||||
{"reInit", reInit},
|
||||
#ifdef TR_HIRES_SNAP
|
||||
{"dumpHiResSnapShot", dumpHiResSnapShot},
|
||||
{"dumpHiResSnapShot", fgHiResDumpWrapper},
|
||||
#endif
|
||||
{"dumpSnapShot", dumpSnapShot},
|
||||
{"dumpSnapShot", fgDumpSnapShotWrapper},
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__)
|
||||
{"printScreen", printScreen},
|
||||
#endif
|
||||
|
@ -528,6 +528,7 @@ void fgHiResDump()
|
|||
fgSetBool("/sim/freeze/master", true);
|
||||
}
|
||||
|
||||
TurnCursorOff();
|
||||
if ( !puCursorIsHidden() ) {
|
||||
show_pu_cursor = true;
|
||||
puHideCursor();
|
||||
|
@ -541,21 +542,8 @@ void fgHiResDump()
|
|||
// we need two render frames here to clear the menu and cursor
|
||||
// ... not sure why but doing an extra fgRenderFrame() shouldn't
|
||||
// hurt anything
|
||||
renderer->update();
|
||||
renderer->update();
|
||||
|
||||
// Make sure we have SSG projection primed for current view
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
ssgSetCamera( (sgVec4 *)globals->get_current_view()->get_VIEW() );
|
||||
ssgSetFOV( globals->get_current_view()->get_h_fov(),
|
||||
globals->get_current_view()->get_v_fov() );
|
||||
cout << "FOV = " << globals->get_current_view()->get_h_fov()
|
||||
<< ", " << globals->get_current_view()->get_v_fov() << endl;
|
||||
|
||||
// ssgSetNearFar( 10.0f, 120000.0f );
|
||||
ssgSetNearFar( 0.5f, 1200000.0f );
|
||||
|
||||
renderer->update( true );
|
||||
renderer->update( true );
|
||||
|
||||
// This ImageSize stuff is a temporary hack
|
||||
// should probably use 128x128 tile size and
|
||||
|
@ -636,7 +624,7 @@ void fgHiResDump()
|
|||
trBeginTile(tr);
|
||||
int curColumn = trGet(tr, TR_CURRENT_COLUMN);
|
||||
int curRow = trGet(tr, TR_CURRENT_ROW);
|
||||
renderer->screendump();
|
||||
renderer->update( false );
|
||||
if ( do_hud )
|
||||
fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step,
|
||||
(curColumn+1)*hud_col_step, (curRow+1)*hud_row_step );
|
||||
|
@ -696,6 +684,8 @@ void fgHiResDump()
|
|||
puShowCursor();
|
||||
}
|
||||
|
||||
TurnCursorOn();
|
||||
|
||||
if ( !freeze ) {
|
||||
fgSetBool("/sim/freeze/master", false);
|
||||
}
|
||||
|
@ -729,7 +719,7 @@ GLubyte *hiResScreenCapture( int multiplier )
|
|||
globals->get_renderer()->resize( cur_width, cur_height );
|
||||
// pan to tile
|
||||
rotateView( 0, (y*fov)-((multiplier-1)*fov/2), (x*fov)-((multiplier-1)*fov/2) );
|
||||
globals->get_renderer()->update();
|
||||
globals->get_renderer()->update( false );
|
||||
// restore view
|
||||
GlBitmap b2;
|
||||
b1->copyBitmap( &b2, cur_width*x, cur_height*y );
|
||||
|
@ -766,12 +756,12 @@ void printScreen ( puObject *obj ) {
|
|||
#endif // #ifdef WIN32
|
||||
|
||||
|
||||
void dumpSnapShot ( puObject *obj ) {
|
||||
void fgDumpSnapShotWrapper ( puObject *obj ) {
|
||||
fgDumpSnapShot();
|
||||
}
|
||||
|
||||
|
||||
void dumpHiResSnapShot ( puObject *obj ) {
|
||||
void fgHiResDumpWrapper ( puObject *obj ) {
|
||||
fgHiResDump();
|
||||
}
|
||||
|
||||
|
@ -805,8 +795,8 @@ void fgDumpSnapShot () {
|
|||
// we need two render frames here to clear the menu and cursor
|
||||
// ... not sure why but doing an extra fgRenderFrame() shouldn't
|
||||
// hurt anything
|
||||
renderer->update();
|
||||
renderer->update();
|
||||
renderer->update( true );
|
||||
renderer->update( true );
|
||||
|
||||
while (count < 1000) {
|
||||
FILE *fp;
|
||||
|
|
|
@ -212,132 +212,9 @@ FGRenderer::init( void ) {
|
|||
}
|
||||
|
||||
|
||||
// For HiRes screen Dumps using Brian Pauls TR Library
|
||||
void
|
||||
FGRenderer::screendump( void ) {
|
||||
#ifdef FG_ENABLE_MULTIPASS_CLOUDS
|
||||
bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds") &&
|
||||
!SGCloudLayer::enable_bump_mapping; // ugly artefact now
|
||||
#else
|
||||
bool multi_pass_clouds = false;
|
||||
#endif
|
||||
bool draw_clouds = fgGetBool("/environment/clouds/status");
|
||||
|
||||
if ( fgPanelVisible() ) {
|
||||
GLfloat height = fgGetInt("/sim/startup/ysize");
|
||||
GLfloat view_h =
|
||||
(globals->get_current_panel()->getViewHeight() - globals->get_current_panel()->getYOffset())
|
||||
* (height / 768.0) + 1;
|
||||
glTranslatef( 0.0, view_h, 0.0 );
|
||||
}
|
||||
|
||||
static GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 };
|
||||
static GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
|
||||
|
||||
FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
|
||||
|
||||
glClearColor(l->adj_fog_color()[0], l->adj_fog_color()[1],
|
||||
l->adj_fog_color()[2], l->adj_fog_color()[3]);
|
||||
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// set the opengl state to known default values
|
||||
default_state->force();
|
||||
|
||||
glEnable( GL_FOG );
|
||||
glFogf ( GL_FOG_DENSITY, fog_exp2_density);
|
||||
glFogi ( GL_FOG_MODE, GL_EXP2 );
|
||||
glFogfv ( GL_FOG_COLOR, l->adj_fog_color() );
|
||||
|
||||
// GL_LIGHT_MODEL_AMBIENT has a default non-zero value so if
|
||||
// we only update GL_AMBIENT for our lights we will never get
|
||||
// a completely dark scene. So, we set GL_LIGHT_MODEL_AMBIENT
|
||||
// explicitely to black.
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, black );
|
||||
glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE );
|
||||
|
||||
ssgGetLight( 0 ) -> setColour( GL_AMBIENT, l->scene_ambient() );
|
||||
|
||||
// texture parameters
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ) ;
|
||||
|
||||
// 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 );
|
||||
|
||||
// draw the ssg scene
|
||||
// return to the desired diffuse color
|
||||
ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
ssgSetNearFar( scene_nearplane, scene_farplane );
|
||||
if ( draw_clouds ) {
|
||||
// Draw the terrain
|
||||
FGTileMgr::set_tile_filter( true );
|
||||
sgSetModelFilter( false );
|
||||
globals->get_aircraft_model()->select( false );
|
||||
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
|
||||
// Disable depth buffer update, draw the clouds
|
||||
glDepthMask( GL_FALSE );
|
||||
thesky->drawUpperClouds();
|
||||
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_KEEP, GL_KEEP, GL_REPLACE );
|
||||
}
|
||||
FGTileMgr::set_tile_filter( false );
|
||||
sgSetModelFilter( true );
|
||||
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
|
||||
} else {
|
||||
FGTileMgr::set_tile_filter( true );
|
||||
sgSetModelFilter( true );
|
||||
globals->get_aircraft_model()->select( false );
|
||||
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
|
||||
}
|
||||
|
||||
// draw the lights
|
||||
glFogf (GL_FOG_DENSITY, rwy_exp2_punch_through);
|
||||
ssgSetNearFar( scene_nearplane, scene_farplane );
|
||||
ssgCullAndDraw( globals->get_scenery()->get_vasi_lights_root() );
|
||||
ssgCullAndDraw( globals->get_scenery()->get_rwy_lights_root() );
|
||||
|
||||
ssgCullAndDraw( globals->get_scenery()->get_gnd_lights_root() );
|
||||
|
||||
if ( draw_clouds ) {
|
||||
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();
|
||||
thesky->drawLowerClouds();
|
||||
glDepthMask( GL_TRUE );
|
||||
glDisable( GL_STENCIL_TEST );
|
||||
} else {
|
||||
glDepthMask( GL_FALSE );
|
||||
thesky->drawLowerClouds();
|
||||
glDepthMask( GL_TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
globals->get_aircraft_model()->select( true );
|
||||
globals->get_model_mgr()->draw();
|
||||
globals->get_aircraft_model()->draw();
|
||||
}
|
||||
|
||||
|
||||
// Update all Visuals (redraws anything graphics related)
|
||||
void
|
||||
FGRenderer::update() {
|
||||
FGRenderer::update( bool refresh_camera_settings ) {
|
||||
bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override");
|
||||
bool draw_otw = fgGetBool("/sim/rendering/draw-otw");
|
||||
bool skyblend = fgGetBool("/sim/rendering/skyblend");
|
||||
|
@ -368,10 +245,12 @@ FGRenderer::update() {
|
|||
|
||||
// update fog params
|
||||
double actual_visibility;
|
||||
if (fgGetBool("/environment/clouds/status"))
|
||||
if (fgGetBool("/environment/clouds/status")) {
|
||||
actual_visibility = thesky->get_visibility();
|
||||
else
|
||||
} else {
|
||||
actual_visibility = fgGetDouble("/environment/visibility-m");
|
||||
}
|
||||
|
||||
if ( actual_visibility != last_visibility ) {
|
||||
last_visibility = actual_visibility;
|
||||
|
||||
|
@ -412,10 +291,17 @@ FGRenderer::update() {
|
|||
// calculate our current position in cartesian space
|
||||
globals->get_scenery()->set_center( globals->get_scenery()->get_next_center() );
|
||||
|
||||
if ( refresh_camera_settings ) {
|
||||
// update view port
|
||||
resize( fgGetInt("/sim/startup/xsize"),
|
||||
fgGetInt("/sim/startup/ysize") );
|
||||
|
||||
// Tell GL we are switching to model view parameters
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
ssgSetCamera( (sgVec4 *)current__view->get_VIEW() );
|
||||
}
|
||||
|
||||
if ( fgGetBool("/sim/rendering/clouds3d") ) {
|
||||
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
|
||||
cloud3d_imposter_state->force();
|
||||
|
@ -460,16 +346,6 @@ FGRenderer::update() {
|
|||
}
|
||||
glClear( clear_mask );
|
||||
|
||||
// Tell GL we are switching to model view parameters
|
||||
|
||||
// I really should create a derived ssg node or use a call
|
||||
// back or something so that I can draw the sky within the
|
||||
// ssgCullAndDraw() function, but for now I just mimic what
|
||||
// ssg does to set up the model view matrix
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
ssgSetCamera( (sgVec4 *)current__view->get_VIEW() );
|
||||
|
||||
// set the opengl state to known default values
|
||||
default_state->force();
|
||||
|
||||
|
@ -597,11 +473,6 @@ FGRenderer::update() {
|
|||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ) ;
|
||||
|
||||
// glMatrixMode( GL_PROJECTION );
|
||||
// glLoadIdentity();
|
||||
ssgSetFOV( current__view->get_h_fov(),
|
||||
current__view->get_v_fov() );
|
||||
|
||||
double agl =
|
||||
current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER
|
||||
- globals->get_scenery()->get_cur_elev();
|
||||
|
@ -920,7 +791,23 @@ FGRenderer::resize( int width, int height ) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
// For HiRes screen Dumps using Brian Pauls TR Library
|
||||
//
|
||||
// Curt writes: Unfortunately, if the jpeg image server code is
|
||||
// compiled into simgear and flightgear, this function get's called
|
||||
// from simgear which is not the direction we want our dependencies to
|
||||
// go, but it's the way things are right now.
|
||||
//
|
||||
// If I had to guess, I would speculate that this code probably
|
||||
// doesn't work, at least not 100% correctly, but I don't have time
|
||||
// right now to sort this one out. Also the jpeg server was very
|
||||
// experimental and was extremely limited in the resolution images it
|
||||
// could serve out for some never debugged reason. It's a novel
|
||||
// feature, but I wouldn't be entirely opposed to seeing it go away
|
||||
// unless someone wants to fix it so it works right and robustly and
|
||||
// can serve full resolution images without crashing ourselves.
|
||||
|
||||
void trRenderFrame( void ) {
|
||||
#ifdef FG_ENABLE_MULTIPASS_CLOUDS
|
||||
bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds") &&
|
||||
|
@ -1041,4 +928,5 @@ void trRenderFrame( void ) {
|
|||
globals->get_aircraft_model()->draw();
|
||||
}
|
||||
|
||||
|
||||
// end of renderer.cxx
|
||||
|
|
|
@ -22,11 +22,15 @@ public:
|
|||
~FGRenderer() {}
|
||||
|
||||
void init();
|
||||
static void update();
|
||||
|
||||
void build_states();
|
||||
static void resize(int width, int height );
|
||||
|
||||
void screendump();
|
||||
void build_states();
|
||||
// calling update( refresh_camera_settings = false ) will not
|
||||
// touch window or camera settings. This is useful for the tiled
|
||||
// renderer which needs to set the view frustum itself.
|
||||
static void update( bool refresh_camera_settings );
|
||||
inline static void update() { update( true ); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue