From d37992aaf9c21ebed166e093fb6d339dd6784316 Mon Sep 17 00:00:00 2001 From: ehofman Date: Tue, 26 Apr 2005 08:30:38 +0000 Subject: [PATCH] Harald Johnson: Changes ======= - corrected some strange behavior when playing with the render dialog options - the density slider is now working : if you are fps limited and still want to see clouds in the distance you should play with that - added the choice for texture resolution, its more comprehensible now (before it was wrongly allways choosing 64x64 textures) - changed the initial texture size : you now have 64 texture of 64x64, this uses 1Mo of texture memory (before it was 20 texture of 256x256, that took more memory and there was not enought impostors) - sun vector is now right so the lighting is a bit better - removed useless sort and light computations for impostors, this should save a lot of cpu - blending of distant cloud is more accurate now - clouds are now positioned correctly, they don't try to escape you anymore - no more red/white boxes around cloud - textures are now filtered (no more big pixels) known bugs ========== - distant objects are seen in front of clouds --- simgear/environment/visual_enviro.cxx | 38 +++++- simgear/environment/visual_enviro.hxx | 17 ++- simgear/scene/sky/bbcache.cxx | 20 ++-- simgear/scene/sky/cloudfield.cxx | 163 ++++++++++++++++++++------ simgear/scene/sky/cloudfield.hxx | 10 +- simgear/scene/sky/newcloud.cxx | 72 +++--------- 6 files changed, 210 insertions(+), 110 deletions(-) diff --git a/simgear/environment/visual_enviro.cxx b/simgear/environment/visual_enviro.cxx index 0fdeae26..ebe8f855 100644 --- a/simgear/environment/visual_enviro.cxx +++ b/simgear/environment/visual_enviro.cxx @@ -26,12 +26,38 @@ SGEnviro sgEnviro; -SGEnviro::SGEnviro(void) { +SGEnviro::SGEnviro(void) : + view_in_cloud(false), + precipitation_enable_state(false), + precipitation_density(100.0) + +{ } SGEnviro::~SGEnviro(void) { } +void SGEnviro::startOfFrame(void) { + view_in_cloud = false; + if(SGNewCloud::cldCache) + SGNewCloud::cldCache->startNewFrame(); +} + +void SGEnviro::endOfFrame(void) { +} + +// this can be queried to add some turbulence for example +bool SGEnviro::is_view_in_cloud(void) const { + return view_in_cloud; +} +void SGEnviro::set_view_in_cloud(bool incloud) { + view_in_cloud = incloud; +} + +int SGEnviro::get_CacheResolution(void) const { + return SGCloudField::get_CacheResolution(); +} + int SGEnviro::get_clouds_CacheSize(void) const { return SGCloudField::get_CacheSize(); } @@ -45,6 +71,10 @@ bool SGEnviro::get_clouds_enable_state(void) const { return SGCloudField::get_enable3dClouds(); } +void SGEnviro::set_CacheResolution(int resolutionPixels) { + SGCloudField::set_CacheResolution(resolutionPixels); +} + void SGEnviro::set_clouds_CacheSize(int sizeKb) { SGCloudField::set_CacheSize(sizeKb); } @@ -60,15 +90,17 @@ void SGEnviro::set_clouds_enable_state(bool enable) { // rain/snow float SGEnviro::get_precipitation_density(void) const { - return 0.0; + return precipitation_density; } bool SGEnviro::get_precipitation_enable_state(void) const { - return false; + return precipitation_enable_state; } void SGEnviro::set_precipitation_density(float density) { + precipitation_density = density; } void SGEnviro::set_precipitation_enable_state(bool enable) { + precipitation_enable_state = enable; } // others diff --git a/simgear/environment/visual_enviro.hxx b/simgear/environment/visual_enviro.hxx index cc2a65d5..f8a7e6c0 100644 --- a/simgear/environment/visual_enviro.hxx +++ b/simgear/environment/visual_enviro.hxx @@ -24,18 +24,32 @@ class SGEnviro { +private: + bool view_in_cloud; + bool precipitation_enable_state; + float precipitation_density; + public: SGEnviro(); ~SGEnviro(); + void startOfFrame(void); + void endOfFrame(void); + + // this can be queried to add some turbulence for example + bool is_view_in_cloud(void) const; + void set_view_in_cloud(bool incloud); + // Clouds // return the size of the memory pool used by texture impostors int get_clouds_CacheSize(void) const; + int get_CacheResolution(void) const; float get_clouds_visibility(void) const; float get_clouds_density(void) const; bool get_clouds_enable_state(void) const; void set_clouds_CacheSize(int sizeKb); + void set_CacheResolution(int resolutionPixels); void set_clouds_visibility(float distance); void set_clouds_density(float density); void set_clouds_enable_state(bool enable); @@ -54,5 +68,4 @@ public: extern SGEnviro sgEnviro; -#endif // _VISUAL_ENVIRO_HXX - +#endif // _VISUAL_ENVIRO_HXX \ No newline at end of file diff --git a/simgear/scene/sky/bbcache.cxx b/simgear/scene/sky/bbcache.cxx index a05ce7c8..64bb7c63 100644 --- a/simgear/scene/sky/bbcache.cxx +++ b/simgear/scene/sky/bbcache.cxx @@ -71,8 +71,8 @@ bool SGBbCache::allocTextureMemory(int cacheCount, int textureDimension) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } glBindTexture(GL_TEXTURE_2D, 0); cacheSizeKb = (textureDimension * textureDimension * 4); @@ -94,7 +94,7 @@ SGBbCache::SGBbCache(void) : rt(0), rtAvailable(false), frameNumber(0), - maxImpostorRegenFrame(10) + maxImpostorRegenFrame(20) { } @@ -139,11 +139,11 @@ void SGBbCache::init(int cacheCount) { } } if( cacheCount ) - allocTextureMemory( cacheCount, 256 ); + allocTextureMemory( cacheCount, 64 ); } -// TODO:not callable atm, texture size not handled correctly + bool SGBbCache::setCacheSize(int count, int textureDimension) { if( count < 0 || count > 500) return false; @@ -172,7 +172,7 @@ bool SGBbCache::setCacheSize(int count, int textureDimension) { return allocTextureMemory( count, textureDimension); } -// TODO:not callable atm, texture size not handled correctly + bool SGBbCache::setCacheSize(int sizeKb) { if( sizeKb < 0 || sizeKb > 256*1024) return false; @@ -181,10 +181,10 @@ bool SGBbCache::setCacheSize(int sizeKb) { return true; int count = 1; int textureDimension = 256; - if( cacheSizeKb >= 8*1024 ) { + if( sizeKb >= 8*1024 ) { // more than 32 256x256 textures textureDimension = 256; - } else if( cacheSizeKb >= 2*1024 ) { + } else if( sizeKb >= 2*1024 ) { // more than 32 128x128 textures textureDimension = 128; } else { @@ -305,10 +305,10 @@ bool SGBbCache::isBbValid( int cldId, int bbId, float angleY, float angleX) { if( builtBBframe >= maxImpostorRegenFrame ) return true; - if( fabs(angleY - bbList[bbId].angleY) >= 5.0 ) + if( fabs(angleY - bbList[bbId].angleY) >= 4.0 ) return false; - if( fabs(angleX - bbList[bbId].angleX) >= 5.0 ) + if( fabs(angleX - bbList[bbId].angleX) >= 4.0 ) return false; bbList[bbId].frameUsed = frameNumber; diff --git a/simgear/scene/sky/cloudfield.cxx b/simgear/scene/sky/cloudfield.cxx index 83f941d6..8555af20 100644 --- a/simgear/scene/sky/cloudfield.cxx +++ b/simgear/scene/sky/cloudfield.cxx @@ -29,12 +29,14 @@ #include #include #include +#include #include STL_ALGORITHM #include SG_USING_STD(vector); +#include #include "newcloud.hxx" #include "cloudfield.hxx" @@ -45,9 +47,26 @@ float SGCloudField::CloudVis = 25000.0f; bool SGCloudField::enable3D = true; // fieldSize must be > CloudVis or we can destroy the impostor cache // a cloud must only be seen once or the impostor will be generated for each of his positions -double SGCloudField::fieldSize = 30000.0; +double SGCloudField::fieldSize = 27000.0; float SGCloudField::density = 100.0; -static int last_cache_size = 4*1024; +static int last_cache_size = 1*1024; +static int cacheResolution = 64; + +int SGCloudField::get_CacheResolution(void) { + return cacheResolution; +} + +void SGCloudField::set_CacheResolution(int resolutionPixels) { + if(cacheResolution == resolutionPixels) + return; + cacheResolution = resolutionPixels; + if(enable3D) { + int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4); + if(count == 0) + count = 1; + SGNewCloud::cldCache->setCacheSize(count, cacheResolution); + } +} int SGCloudField::get_CacheSize(void) { return SGNewCloud::cldCache->queryCacheSize(); @@ -61,10 +80,17 @@ void SGCloudField::set_CacheSize(int sizeKb) { return; if(sizeKb) last_cache_size = sizeKb; - SGNewCloud::cldCache->setCacheSize(sizeKb); + if(enable3D) { + int count = last_cache_size * 1024 / (cacheResolution * cacheResolution * 4); + if(count == 0) + count = 1; +// SGNewCloud::cldCache->setCacheSize(sizeKb); + SGNewCloud::cldCache->setCacheSize(count, cacheResolution); + } } void SGCloudField::set_CloudVis(float distance) { - SGCloudField::CloudVis = distance; + if( distance <= fieldSize ) + SGCloudField::CloudVis = distance; } void SGCloudField::set_density(float density) { SGCloudField::density = density; @@ -104,15 +130,7 @@ void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, doub sgMakeCoordMat4( transform, &layerpos ); - // TODO:use a simple sphere earth - double az1, az2, s; - geo_inverse_wgs_84( 0.0, 0.0, 0.0, lat*SG_RADIANS_TO_DEGREES , lon*SG_RADIANS_TO_DEGREES, &az1, &az2, &s); - az1 = az1 * SG_DEGREES_TO_RADIANS; - // compute the view position on a 'flat' earth - deltay = -cos(SG_PI/2+az1) * s; - deltax = -sin(SG_PI/2+az1) * s; -// deltax = cos(0.0) * s; -// deltay = sin(0.0) * s; + this->alt = alt; // simulate clouds movement from wind @@ -126,13 +144,51 @@ void SGCloudField::reposition( sgVec3 p, sgVec3 up, double lon, double lat, doub relative_position[SG_Y] += by; } + if ( lon != last_lon || lat != last_lat || sp_dist != 0 ) { + Point3D start( last_lon, last_lat, 0.0 ); + Point3D dest( lon, lat, 0.0 ); + double course = 0.0, dist = 0.0; + + calc_gc_course_dist( dest, start, &course, &dist ); + // if start and dest are too close together, + // calc_gc_course_dist() can return a course of "nan". If + // this happens, lets just use the last known good course. + // This is a hack, and it would probably be better to make + // calc_gc_course_dist() more robust. + if ( isnan(course) ) { + course = last_course; + } else { + last_course = course; + } + + // calculate cloud movement due to external forces + double ax = 0.0, ay = 0.0; + + if (dist > 0.0) { + ax = cos(course) * dist; + ay = sin(course) * dist; + } + + deltax += ax; + deltay += ay; + + last_lon = lon; + last_lat = lat; + } + + // correct the frustum with the right far plane ssgContext *context = ssgGetCurrentContext(); frustum = *context->getFrustum(); frustum.setNearFar(1.0, CloudVis); } -SGCloudField::SGCloudField() { +SGCloudField::SGCloudField() : + last_density(0.0), + deltax(0.0), + deltay(0.0), + last_course(0.0) +{ sgSetVec3( relative_position, 0,0,0); theField.reserve(200); inViewClouds.reserve(200); @@ -147,11 +203,43 @@ SGCloudField::~SGCloudField() { } +// use a table or else we see poping when moving the slider... +static int densTable[][10] = { + {0,0,0,0,0,0,0,0,0,0}, + {1,0,0,0,0,0,0,0,0,0}, + {1,0,0,0,1,0,0,0,0,0}, + {1,0,0,0,1,0,0,1,0,0}, // 30% + {1,0,1,0,1,0,0,1,0,0}, + {1,0,1,0,1,0,1,1,0,0}, // 50% + {1,0,1,0,1,0,1,1,0,1}, + {1,0,1,1,1,0,1,1,0,1}, // 70% + {1,1,1,1,1,0,1,1,0,1}, + {1,1,1,1,1,0,1,1,1,1}, // 90% + {1,1,1,1,1,1,1,1,1,1} +}; + +// set the visible flag depending on density +void SGCloudField::applyDensity(void) { + int row = (int) (density / 10.0); + int col = 0; + list_of_Cloud::iterator iCloud; + for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) { + if(++col > 9) + col = 0; + if( densTable[row][col] ) { + iCloud->visible = true; + } else + iCloud->visible = false; + } + last_density = density; +} + // add one cloud, data is not copied, ownership given void SGCloudField::addCloud( sgVec3 pos, SGNewCloud *cloud) { Cloud cl; sgCopyVec3( cl.pos, pos ); cl.aCloud = cloud; + cl.visible = true; cloud->SetPos( pos ); theField.push_back( cl ); } @@ -165,7 +253,7 @@ static float Rnd(float n) { // build a field of cloud of size 25x25 km, its a grid of 11x11 clouds void SGCloudField::buildTestLayer(void) { - const float s = 2200.0f; + const float s = 2250.0f; for( int z = -5 ; z <= 5 ; z++) { for( int x = -5 ; x <= 5 ; x++ ) { @@ -175,21 +263,23 @@ void SGCloudField::buildTestLayer(void) { addCloud(pos, cloud); } } - + applyDensity(); } // cull all clouds of a tiled field void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) { list_of_Cloud::iterator iCloud; -// const float distVisCompare = CloudVis * CloudVis; // TODO:cull the field before culling the clouds in the field (should eliminate 3 fields) for( iCloud = theField.begin() ; iCloud != theField.end() ; iCloud++ ) { sgVec3 dist; sgSphere sphere; + if( ! iCloud->visible ) + continue; sgSubVec3( dist, iCloud->pos, eyePos ); sphere.setCenter(dist[0], dist[2], dist[1]); - sphere.setRadius(iCloud->aCloud->getRadius()); + float radius = iCloud->aCloud->getRadius(); + sphere.setRadius(radius); sphere.orthoXform(mat); if( frustum.contains( & sphere ) != SG_OUTSIDE ) { float squareDist = dist[0]*dist[0] + dist[1]*dist[1] + dist[2]*dist[2]; @@ -199,16 +289,13 @@ void SGCloudField::cullClouds(sgVec3 eyePos, sgMat4 mat) { // save distance for later sort, opposite distance because we want back to front tmp.dist = - squareDist; inViewClouds.push_back(tmp); + if( squareDist - radius*radius < 100*100 ) + sgEnviro.set_view_in_cloud(true); } } } -static inline void myswap(float &a, float &b) { - float tmp = a; - a = b; - b = tmp; -} // Render a cloud field // because no field can have an infinite size (and we don't want to reach his border) @@ -221,30 +308,29 @@ void SGCloudField::Render(void) { if( ! enable3D ) return; + if( last_density != density ) { + last_density = density; + applyDensity(); + } + // ask the impostor cache to do some cleanup // TODO:don't do that for every field SGNewCloud::cldCache->startNewFrame(); inViewClouds.clear(); - // cloud fields are tiled on the flat earth - // compute the position in the tile - relx = -fmod( deltax + relative_position[SG_X], fieldSize ); - rely = -fmod( deltay + relative_position[SG_Y], fieldSize ); glPushMatrix(); sgMat4 modelview, tmp, invtrans; - // try to find the sun position (buggy) + // try to find the sun position sgTransposeNegateMat4( invtrans, transform ); sgVec3 lightVec; ssgGetLight( 0 )->getPosition( lightVec ); - sgNegateVec3( lightVec ); sgXformVec3( lightVec, invtrans ); - sgNormaliseVec3( lightVec ); sgCopyVec3( SGNewCloud::modelSunDir, lightVec ); - + sgSetVec3( SGNewCloud::modelSunDir, lightVec[0], lightVec[2], lightVec[1]); // try to find the lighting data (buggy) sgVec4 diffuse, ambient; ssgGetLight( 0 )->getColour( GL_DIFFUSE, diffuse ); @@ -257,11 +343,12 @@ void SGCloudField::Render(void) { sgCopyMat4( tmp, transform ); sgPostMultMat4( tmp, modelview ); - sgSetVec3( eyePos, -relx, -tmp[3][2], -rely); - sgSetVec3( eyePos, -relx, 0, -rely); + // cloud fields are tiled on the flat earth + // compute the position in the tile + relx = -fmod( deltax + relative_position[SG_X] + tmp[3][0], fieldSize ); + rely = -fmod( deltay + relative_position[SG_Y] + tmp[3][1], fieldSize ); + sgSetVec3( eyePos, -relx, alt, -rely); -// sgSetVec3( eyePos, 0, - tmp[3][2], 0); -// sgSetVec3( eyePos, 20000, - tmp[3][2], 20000); tmp[3][2] = 0; tmp[3][0] = 0; @@ -296,12 +383,10 @@ void SGCloudField::Render(void) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); glDisable(GL_CULL_FACE); -// glDisable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST); glEnable(GL_SMOOTH); glEnable(GL_BLEND); glBlendFunc( GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); -// glEnable( GL_COLOR_MATERIAL ); glEnable( GL_TEXTURE_2D ); glDisable( GL_FOG ); glDisable(GL_LIGHTING); @@ -316,11 +401,13 @@ void SGCloudField::Render(void) { glBindTexture(GL_TEXTURE_2D, 0); glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + glEnable( GL_FOG ); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); ssgLoadModelviewMatrix( modelview ); glPopMatrix(); -// glEnable(GL_DEPTH_TEST); } diff --git a/simgear/scene/sky/cloudfield.hxx b/simgear/scene/sky/cloudfield.hxx index 39b0e001..2a547eb6 100644 --- a/simgear/scene/sky/cloudfield.hxx +++ b/simgear/scene/sky/cloudfield.hxx @@ -38,7 +38,7 @@ public: sgVec3 eyePos; float dist; bool operator<(const culledCloud &b) const { - return (this->dist < b.dist); + return this->dist < b.dist; } }; typedef vector list_of_culledCloud; @@ -50,6 +50,7 @@ private: public: SGNewCloud *aCloud; sgVec3 pos; + bool visible; // float dist; // bool culled; @@ -64,6 +65,8 @@ private: // cull all clouds of a tiled field void cullClouds(sgVec3 eyePos, sgMat4 mat); + void applyDensity(void); + list_of_Cloud theField; // this is a relative position only, with that we can move all clouds at once sgVec3 relative_position; @@ -73,6 +76,9 @@ private: sgMat4 transform; double deltax, deltay, alt; + double last_lon, last_lat, last_course; + + float last_density; public: @@ -101,11 +107,13 @@ public: // return the size of the memory pool used by texture impostors static int get_CacheSize(void); + static int get_CacheResolution(void); static float get_CloudVis(void) { return CloudVis; } static float get_density(void) { return density; } static bool get_enable3dClouds(void) { return enable3D; } static void set_CacheSize(int sizeKb); + static void set_CacheResolution(int resolutionPixels); static void set_CloudVis(float distance); static void set_density(float density); static void set_enable3dClouds(bool enable); diff --git a/simgear/scene/sky/newcloud.cxx b/simgear/scene/sky/newcloud.cxx index e0bcfce7..6ceb9dbb 100644 --- a/simgear/scene/sky/newcloud.cxx +++ b/simgear/scene/sky/newcloud.cxx @@ -33,6 +33,7 @@ #include STL_ALGORITHM #include SG_GLU_H +#include "cloudfield.hxx" #include "newcloud.hxx" @@ -45,7 +46,7 @@ static ssgTexture *cloudTextures[SGNewCloud::CLTexture_max]; bool SGNewCloud::useAnisotropic = true; SGBbCache *SGNewCloud::cldCache = 0; static bool texturesLoaded = false; -float SGNewCloud::nearRadius = 2500.0f; +float SGNewCloud::nearRadius = 3500.0f; bool SGNewCloud::lowQuality = false; sgVec3 SGNewCloud::sunlight = {0.5f, 0.5f, 0.5f}; sgVec3 SGNewCloud::ambLight = {0.5f, 0.5f, 0.5f}; @@ -67,7 +68,7 @@ SGNewCloud::SGNewCloud() : // if( ! texturesLoaded ) {} if( cldCache == 0 ) { cldCache = new SGBbCache; - cldCache->init( 20 ); + cldCache->init( 64 ); } } @@ -309,7 +310,7 @@ void SGNewCloud::genSprites( void ) { // definition of a cu cloud, only for testing void SGNewCloud::new_cu(void) { - float s = 150.0f; + float s = 250.0f; float r = Rnd(1.0) + 0.5; if( r < 0.5f ) { addContainer(0.0f, 0.0f, 0.0f, s, CLbox_cumulus); @@ -332,7 +333,7 @@ void SGNewCloud::new_cu(void) { } else { // cb - s = 475.0f; + s = 675.0f; addContainer(0, 0, 0, s, CLbox_cumulus); addContainer(0, 0, s, s, CLbox_cumulus); addContainer(s, 0, s, s, CLbox_cumulus); @@ -368,43 +369,12 @@ void SGNewCloud::SetPos(sgVec3 newPos) { -/* -Public Sub drawContainers() - Dim N As Integer, i As Integer - N = UBound(tbSpriteCont()) - - Call glPolygonMode(faceFrontAndBack, pgmLine) - - Call glColor3f(0.9, 0.9, 0.9) - - For i = 0 To N - 1 - With tbSpriteCont(i) - Call glPushMatrix - Call glTranslatef(.x * c_scale + cloudpos(0), .y * c_scale + cloudpos(1), .z * c_scale + cloudpos(2)) - Call gCtl.Shapes.box(.r * c_scale, .r * c_scale, .r * c_scale) - Call glPopMatrix - End With - Next i -If 0 Then - Call glPushMatrix - Call glTranslatef(ccenter(0), ccenter(1), ccenter(2)) - Call gCtl.Shapes.Sphere(cradius, 8, 8) - Call glPopMatrix -End If -End Sub -*/ void SGNewCloud::drawContainers() { } -/* -*/ - -//bool SGNewCloud::compareSpriteFunction(const spriteDef &a, const spriteDef &b) { -// return (a.dist > b.dist); -//} // sort on distance to eye because of transparency void SGNewCloud::sortSprite( sgVec3 eye ) { @@ -424,7 +394,12 @@ void SGNewCloud::Render3Dcloud( bool drawBB, sgVec3 FakeEyePos, sgVec3 deltaPos, /* int clrank = fadingrank / 10; int clfadeinrank = fadingrank - clrank * 10;*/ + float CloudVisFade = 1.0 / (1.5 * SGCloudField::get_CloudVis()); + computeSimpleLight( FakeEyePos ); + + // view point sort, we sort because of transparency + sortSprite( FakeEyePos ); GLint previousTexture = -1, thisTexture; list_of_spriteDef::iterator iSprite; @@ -491,8 +466,7 @@ void SGNewCloud::Render3Dcloud( bool drawBB, sgVec3 FakeEyePos, sgVec3 deltaPos, sgCopyVec4 ( l3, iSprite->l3 ); if( ! drawBB ) { // blend clouds with sky based on distance to limit the contrast of distant cloud - // TODO:use cloudfield vis, not hardcoded value - float t = 1.0f - dist_center / (15000.0f * 2.0 ); + float t = 1.0f - dist_center * CloudVisFade; if ( t < 0.0f ) t = 0.0f; // no, it should have been culled // now clouds at the far plane are half blended @@ -591,8 +565,9 @@ void SGNewCloud::RenderBB(sgVec3 deltaPos, float angleY, float angleX, float dis glRotatef(angleX, 1.0f, 0.0f, 0.0f); // blend clouds with sky based on distance to limit the contrast of distant cloud - // TODO:use cloudfield vis, not hardcoded value - float t = 1.0f - dist_center / (15000.0f * 2.0 ); + float CloudVisFade = (1.5 * SGCloudField::get_CloudVis()); + + float t = 1.0f - dist_center / CloudVisFade; // err the alpha value is not good for impostor, debug that t *= 1.65; if ( t < 0.0f ) @@ -611,7 +586,7 @@ void SGNewCloud::RenderBB(sgVec3 deltaPos, float angleY, float angleX, float dis glVertex2f(-r, -r); glEnd(); -#if 1 // debug only +#if 0 // debug only int age = cldCache->queryImpostorAge(bbId); // draw a red border for the newly generated BBs else draw a white border if( age < 200 ) @@ -646,36 +621,21 @@ bool SGNewCloud::isBillboardable(float dist) { // near clouds we don't want to use BB return false; } -// return false; return true; } // render the cloud, fakepos is a relative position inside the cloud field -void SGNewCloud::Render(sgVec3 fakepos) { - sgVec3 eyePos, FakeEyePos; +void SGNewCloud::Render(sgVec3 FakeEyePos) { sgVec3 dist; - glColor3f(1.0f, 1.0f, 1.0f); - - // obsolete code - sgCopyVec3( eyePos, fakepos ); - - sgCopyVec3( FakeEyePos, fakepos); sgVec3 deltaPos; -// sgSubVec3( deltaPos, eyePos, FakeEyePos); sgCopyVec3( deltaPos, FakeEyePos); sgSubVec3( dist, center, FakeEyePos); float dist_center = sgLengthVec3(dist); - // eeeek don't do that so early, perhaps we will use an impostor - computeSimpleLight( FakeEyePos ); - - // view point sort, we sort because of transparency - // eeeek don't do that so early, perhaps we will use an impostor - sortSprite( FakeEyePos ); if( !isBillboardable(dist_center) ) {