From 0c39caa622d64852723ae1173bb4bb1b007715a4 Mon Sep 17 00:00:00 2001 From: ehofman Date: Sun, 16 Aug 2009 08:42:23 +0000 Subject: [PATCH] Differentiate between sun color (based in visibility) and scene color (based on humidity) --- simgear/scene/sky/oursun.cxx | 250 +++++++++++++++++------------------ simgear/scene/sky/oursun.hxx | 1 + 2 files changed, 126 insertions(+), 125 deletions(-) diff --git a/simgear/scene/sky/oursun.cxx b/simgear/scene/sky/oursun.cxx index 67bbc723..cb1c5f66 100644 --- a/simgear/scene/sky/oursun.cxx +++ b/simgear/scene/sky/oursun.cxx @@ -81,10 +81,8 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) osg::Material* material = new osg::Material; material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); - material->setEmission(osg::Material::FRONT_AND_BACK, - osg::Vec4(0, 0, 0, 1)); - material->setSpecular(osg::Material::FRONT_AND_BACK, - osg::Vec4(0, 0, 0, 1)); + material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1)); + material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1)); stateSet->setAttribute(material); osg::ShadeModel* shadeModel = new osg::ShadeModel; @@ -118,6 +116,9 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) sun_cl = new osg::Vec4Array; sun_cl->push_back(osg::Vec4(1, 1, 1, 1)); + scene_cl = new osg::Vec4Array; + scene_cl->push_back(osg::Vec4(1, 1, 1, 1)); + osg::Vec3Array* sun_vl = new osg::Vec3Array; sun_vl->push_back(osg::Vec3(-sun_size, 0, -sun_size)); sun_vl->push_back(osg::Vec3(sun_size, 0, -sun_size)); @@ -217,7 +218,6 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) sun_transform->addChild( geode ); - // force a repaint of the sun colors with arbitrary defaults repaint( 0.0, 1.0 ); @@ -232,126 +232,126 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node ) // 180 degrees = darkest midnight bool SGSun::repaint( double sun_angle, double new_visibility ) { - if ( visibility != new_visibility ) { - visibility = new_visibility; - - static const double sqrt_m_log01 = sqrt( -log( 0.01 ) ); - sun_exp2_punch_through = sqrt_m_log01 / ( visibility * 15 ); - } - - if ( prev_sun_angle != sun_angle ) { - prev_sun_angle = sun_angle; - - // determine how much aerosols are in the air (rough guess) - double aerosol_factor; - if ( visibility < 100 ){ - aerosol_factor = 8000; - } - else { - aerosol_factor = 80.5 / log( visibility / 100 ); - } - - // get environmental data from property tree or use defaults - double rel_humidity, density_avg; - - if ( !env_node ) - { - rel_humidity = 0.5; - density_avg = 0.7; - } - else - { - rel_humidity = env_node->getFloatValue( "relative-humidity" ); - density_avg = env_node->getFloatValue( "atmosphere/density-tropo-avg" ); - } - - // ok, now let's go and generate the sun color - osg::Vec4 i_halo_color, o_halo_color, sun_color; - - // Some comments: - // When the sunangle changes, light has to travel a longer distance through the atmosphere. - // So it's scattered more due to raleigh scattering, which affects blue more than green light. - // Red is almost not scattered and effectively only get's touched when the sun is near the horizon. - // Visability also affects suncolor inasmuch as more particles are in the air that cause more scattering. - // We base our calculation on the halo's color, which is most scattered. - - // Red - is almost not scattered - // Lambda is 700 nm - - double red_scat_f = ( aerosol_factor * path_distance * density_avg ) / 5E+07; - sun_color[0] = 1 - red_scat_f; - i_halo_color[0] = 1 - ( 1.1 * red_scat_f ); - o_halo_color[0] = 1 - ( 1.4 * red_scat_f ); - - // Green - 546.1 nm - double green_scat_f = ( aerosol_factor * path_distance * density_avg ) / 8.8938E+06; - sun_color[1] = 1 - green_scat_f; - i_halo_color[1] = 1 - ( 1.1 * green_scat_f ); - o_halo_color[1] = 1 - ( 1.4 * green_scat_f ); - - // Blue - 435.8 nm - double blue_scat_f = ( aerosol_factor * path_distance * density_avg ) / 3.607E+06; - sun_color[2] = 1 - blue_scat_f; - i_halo_color[2] = 1 - ( 1.1 * blue_scat_f ); - o_halo_color[2] = 1 - ( 1.4 * blue_scat_f ); - - // Alpha - sun_color[3] = 1; - i_halo_color[3] = 1; - - o_halo_color[3] = blue_scat_f; - if ( ( new_visibility < 10000 ) && ( blue_scat_f > 1 )){ - o_halo_color[3] = 2 - blue_scat_f; - } - - - // Now that we have the color calculated - // let's consider the saturation which is produced by mie scattering - double saturation = 1 - ( rel_humidity / 200 ); - sun_color[1] += (( 1 - saturation ) * ( 1 - sun_color[1] )); - sun_color[2] += (( 1 - saturation ) * ( 1 - sun_color[2] )); - - i_halo_color[1] += (( 1 - saturation ) * ( 1 - i_halo_color[1] )); - i_halo_color[2] += (( 1 - saturation ) * ( 1 - i_halo_color[2] )); - - o_halo_color[1] += (( 1 - saturation ) * ( 1 - o_halo_color[1] )); - o_halo_color[2] += (( 1 - saturation ) * ( 1 - o_halo_color[2] )); - - // just to make sure we're in the limits - if ( sun_color[0] < 0 ) sun_color[0] = 0; - else if ( sun_color[0] > 1) sun_color[0] = 1; - if ( i_halo_color[0] < 0 ) i_halo_color[0] = 0; - else if ( i_halo_color[0] > 1) i_halo_color[0] = 1; - if ( o_halo_color[0] < 0 ) o_halo_color[0] = 0; - else if ( o_halo_color[0] > 1) o_halo_color[0] = 1; - - if ( sun_color[1] < 0 ) sun_color[1] = 0; - else if ( sun_color[1] > 1) sun_color[1] = 1; - if ( i_halo_color[1] < 0 ) i_halo_color[1] = 0; - else if ( i_halo_color[1] > 1) i_halo_color[1] = 1; - if ( o_halo_color[1] < 0 ) o_halo_color[1] = 0; - else if ( o_halo_color[1] > 1) o_halo_color[1] = 1; - - if ( sun_color[2] < 0 ) sun_color[2] = 0; - else if ( sun_color[2] > 1) sun_color[2] = 1; - if ( i_halo_color[2] < 0 ) i_halo_color[2] = 0; - else if ( i_halo_color[2] > 1) i_halo_color[2] = 1; - if ( o_halo_color[2] < 0 ) o_halo_color[2] = 0; - else if ( o_halo_color[2] > 1) o_halo_color[2] = 1; - if ( o_halo_color[3] < 0 ) o_halo_color[3] = 0; - else if ( o_halo_color[3] > 1) o_halo_color[3] = 1; + if ( visibility != new_visibility ) { + visibility = new_visibility; + if (new_visibility < 100.0) new_visibility = 100.0; + else if (new_visibility > 45000.0) new_visibility = 45000.0; + sun_exp2_punch_through = 2.0/log(visibility); + } + + if ( prev_sun_angle != sun_angle ) { + prev_sun_angle = sun_angle; + + // determine how much aerosols are in the air (rough guess) + double aerosol_factor; + if ( visibility < 100 ) { + aerosol_factor = 8000; + } + else { + aerosol_factor = 80.5 / log( visibility / 100 ); + } + + // get environmental data from property tree or use defaults + double rel_humidity, density_avg; + + if ( !env_node ) { + rel_humidity = 0.5; + density_avg = 0.7; + } + else { + rel_humidity = env_node->getFloatValue( "relative-humidity" ); + density_avg = env_node->getFloatValue( "atmosphere/density-tropo-avg" ); + } + + // ok, now let's go and generate the sun and scene color + osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color; + + // Some comments: + // * When the sunangle changes, light has to travel a longer + // distance through the atmosphere. So it's scattered more due + // to raleigh scattering, which affects blue more than green + // light. + // * Red is almost not scattered and effectively only get's + // touched when the sun is near the horizon. + // * Visability also affects suncolor inasmuch as more particles + // are in the air that cause more scattering. + // * We base our calculation on the halo's color, which is most + // scattered. + double red_scat_f, red_scat_corr_f, green_scat_f, blue_scat_f; + + // Red - is almost not scattered + // Lambda is 700 nm - gamma_correct_rgb( i_halo_color._v ); - gamma_correct_rgb( o_halo_color._v ); - gamma_correct_rgb( sun_color._v ); - - (*sun_cl)[0] = sun_color; - sun_cl->dirty(); - (*ihalo_cl)[0] = i_halo_color; - ihalo_cl->dirty(); - (*ohalo_cl)[0] = o_halo_color; - ohalo_cl->dirty(); + red_scat_f = (aerosol_factor * path_distance * density_avg)/5E+07; + red_scat_corr_f = sun_exp2_punch_through / (1 - red_scat_f); + sun_color[0] = 1; + scene_color[0] = 1 - red_scat_f; + + // Green - 546.1 nm + green_scat_f = (aerosol_factor * path_distance * density_avg)/8.8938E+06; + sun_color[1] = 1 - green_scat_f * red_scat_corr_f; + scene_color[1] = 1 - green_scat_f; + + // Blue - 435.8 nm + blue_scat_f = (aerosol_factor * path_distance * density_avg)/3.607E+06; + sun_color[2] = 1 - blue_scat_f * red_scat_corr_f; + scene_color[2] = 1 - blue_scat_f; + + // Alpha + sun_color[3] = 1; + scene_color[3] = 1; + + // Now that we have the color calculated + // let's consider the saturation which is produced by mie scattering + double saturation = 1 - ( rel_humidity / 200 ); + scene_color[1] += (( 1 - saturation ) * ( 1 - scene_color[1] )); + scene_color[2] += (( 1 - saturation ) * ( 1 - scene_color[2] )); + + if (sun_color[0] > 1.0) sun_color[0] = 1.0; + if (sun_color[0] < 0.0) sun_color[0] = 0.0; + if (sun_color[1] > 1.0) sun_color[1] = 1.0; + if (sun_color[1] < 0.0) sun_color[1] = 0.0; + if (sun_color[2] > 1.0) sun_color[2] = 1.0; + if (sun_color[2] < 0.0) sun_color[2] = 0.0; + + if (scene_color[0] > 1.0) scene_color[0] = 1.0; + if (scene_color[0] < 0.0) scene_color[0] = 0.0; + if (scene_color[1] > 1.0) scene_color[1] = 1.0; + if (scene_color[1] < 0.0) scene_color[1] = 0.0; + if (scene_color[2] > 1.0) scene_color[2] = 1.0; + if (scene_color[2] < 0.0) scene_color[2] = 0.0; + + double scene_f = 0.5 * (1 / (1 - red_scat_f)); + double sun_f = 1.0 - scene_f; + i_halo_color[0] = sun_f * sun_color[0] + scene_f * scene_color[0]; + i_halo_color[1] = sun_f * sun_color[1] + scene_f * scene_color[1]; + i_halo_color[2] = sun_f * sun_color[2] + scene_f * scene_color[2]; + i_halo_color[3] = 1; + + o_halo_color[0] = 0.2 * sun_color[0] + 0.8 * scene_color[0]; + o_halo_color[1] = 0.2 * sun_color[1] + 0.8 * scene_color[1]; + o_halo_color[2] = 0.2 * sun_color[2] + 0.8 * scene_color[2]; + o_halo_color[3] = blue_scat_f; + if ((new_visibility < 10000) && (blue_scat_f > 1)) { + o_halo_color[3] = 2 - blue_scat_f; + } + if (o_halo_color[3] > 1) o_halo_color[3] = 1; + if (o_halo_color[3] < 0) o_halo_color[3] = 0; + + gamma_correct_rgb( i_halo_color._v ); + gamma_correct_rgb( o_halo_color._v ); + gamma_correct_rgb( scene_color._v ); + gamma_correct_rgb( sun_color._v ); + + (*sun_cl)[0] = sun_color; + sun_cl->dirty(); + (*scene_cl)[0] = scene_color; + scene_cl->dirty(); + (*ihalo_cl)[0] = i_halo_color; + ihalo_cl->dirty(); + (*ohalo_cl)[0] = o_halo_color; + ohalo_cl->dirty(); } return true; @@ -364,7 +364,7 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) { // rotation (i.e. for the current time of day.) // Then calculate stuff needed for the sun-coloring bool SGSun::reposition( double rightAscension, double declination, - double sun_dist, double lat, double alt_asl, double sun_angle) + double sun_dist, double lat, double alt_asl, double sun_angle) { // GST - GMT sidereal time osg::Matrix T2, RA, DEC; @@ -420,5 +420,5 @@ bool SGSun::reposition( double rightAscension, double declination, SGVec4f SGSun::get_color() { - return SGVec4f((*sun_cl)[0][0], (*sun_cl)[0][1], (*sun_cl)[0][2], (*sun_cl)[0][3]); + return SGVec4f((*scene_cl)[0][0], (*scene_cl)[0][1], (*scene_cl)[0][2], (*scene_cl)[0][3]); } diff --git a/simgear/scene/sky/oursun.hxx b/simgear/scene/sky/oursun.hxx index 5abbfa01..4410847d 100644 --- a/simgear/scene/sky/oursun.hxx +++ b/simgear/scene/sky/oursun.hxx @@ -42,6 +42,7 @@ class SGSun : public SGReferenced { osg::ref_ptr sun_transform; osg::ref_ptr sun_cl; + osg::ref_ptr scene_cl; osg::ref_ptr ihalo_cl; osg::ref_ptr ohalo_cl; -- 2.39.5