Titan's haze

General discussion about Celestia that doesn't fit into other forums.
Topic author
Rassilon
Posts: 1887
Joined: 29.01.2002
With us: 22 years 9 months
Location: Altair

Titan's haze

Post #1by Rassilon » 24.06.2005, 04:09

In an attempt to port Chris's atmosphere code to my project I was thinking of ways to produce wierd and alien atmospheres....Titans latest photos show just that....

http://astrogeology.usgs.gov/HotTopics/ ... n_haze.jpg

I remember Fridger had origonally posted a thread about this some time back wondering if Celestia could be made to render atmospheres as so....I think this answeres that very question since I am using Chris's code....What I want to do eventually is slim it down into one pass....Right now my hacked version requires 4 passes including haze....

http://celestialvisions.net/gallery/dwu25.jpg

This is the code I use...I think most of it is self explanitory for those who know whats going on...

Code: Select all

void solarObj::renderAtmosphere(float fade, bool lit)
{
    if (planetInfo.hasSky == false)
        return;
   float botColor[4], topColor[4], hColor[4], sColor[4];
   int i,j;

    glDepthMask(GL_FALSE);
   gl_EnableColorMaterial();
   glDisable(GL_LIGHTING);
   glDisable(GL_TEXTURE_2D);
   glDisable(GL_ALPHA_TEST);
   glEnable(GL_BLEND);                     // Enable Blending
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   
   Point3f center = Point3f(float(planet_pos[planetInfo.planetNum][0]), float(planet_pos[planetInfo.planetNum][1]), float(planet_pos[planetInfo.planetNum][2]));
   Vec3f sunDirection[16];
   for(i = 0;i<number_lights;i++)   
      sunDirection[i] = Vec3f(float(planet_pos[planet_star[i]][0]), float(planet_pos[planet_star[i]][1]), float(planet_pos[planet_star[i]][2]));

    Vec3f eyeVec = center - Point3f(float(eyeX), float(eyeY), float(eyeZ));
    float centerDist = float(eyeVec.length());
    // double surfaceDist = (double) centerDist - (double) radius;

    Vec3f normal = eyeVec;
    normal = normal / float(centerDist);
   float radius = planetInfo.planetRadius;
    float tangentLength = float(sqrt(float(SQUARE(centerDist)) - float(SQUARE(radius))));
    float atmRadius = tangentLength * radius / float(centerDist);
    float atmOffsetFromCenter = float(SQUARE(radius)) / float(centerDist);
   float cosSunAngle, brightness, t, sunset, haze;
    Point3f atmCenter = center - atmOffsetFromCenter * normal;

    Vec3f uAxis, vAxis;
    if (FABS(normal.x) < FABS(normal.y) && FABS(normal.x) < FABS(normal.z))
    {
        uAxis = Vec3f(1, 0, 0) ^ normal;
        uAxis.normalize();
    }
    else if (FABS(eyeVec.y) < FABS(normal.z))
    {
        uAxis = Vec3f(0, 1, 0) ^ normal;
        uAxis.normalize();
    }
    else
    {
        uAxis = Vec3f(0, 0, 1) ^ normal;
        uAxis.normalize();
    }
    vAxis = uAxis ^ normal;

    float height = (planetInfo.skyHeight * 0.02f) / radius;

   int divisions = CLAMP(180 * (radius / distanceToPlanet[planetInfo.planetNum] * 2),90,180);
   float offset = 0.00237f * float(divisions / 180.0f);

   if(planetInfo.doubleAtmosphere) {
      height *= 0.5f;

      glBegin(GL_QUAD_STRIP);   
      for (i = 0; i <= divisions; i++)
      {
         float theta = float(i) / float(divisions + offset) * 2.0f * float(PI);
         Vec3f v = float(COS(theta)) * uAxis + float(SIN(theta)) * vAxis;
         Point3f base = atmCenter + v * atmRadius;
         Vec3f toCenter = base - center;
         cosSunAngle = -1e9;
         float getAngle = 0;
         for(j=0;j<number_lights;j++) {
            getAngle = (toCenter * sunDirection[j]) / radius / distanceToPlanet[planet_star[j]];
            if(getAngle > cosSunAngle) cosSunAngle = getAngle;
         }

         brightness = 1.0f;

         if (lit)
         {
            if (cosSunAngle < -0.2f)
            {
               brightness = 0;
               sunset = 0;
            }
            else
            {
               t = (0.2f + cosSunAngle) * 2.5f;
               brightness = CLAMP(t,0.0f,1.0f);
               sunset = CLAMP(t - 0.25f,0.0f,1.0f);
            }
            topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
            topColor[0] = (topColor[0] * brightness) + (sceneAmbient[0] * (1.0 - brightness));
            topColor[1] = (topColor[1] * brightness) + (sceneAmbient[1] * (1.0 - brightness));
            topColor[2] = (topColor[2] * brightness) + (sceneAmbient[2] * (1.0 - brightness));

         }
         else {
            topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
         }

         glColor4f(topColor[0], topColor[1], topColor[2], 0.35f);
         glVertex(base + toCenter * (height * 1.5f));
         glColor4f(topColor[0], topColor[1], topColor[2], 0.0f);
         glVertex(base + toCenter * (height * 2.0f));
      }
      glEnd();

      glBegin(GL_QUAD_STRIP);   
      for (i = 0; i <= divisions; i++)
      {
         float theta = float(i) / float(divisions + offset) * 2.0f * float(PI);
         Vec3f v = float(COS(theta)) * uAxis + float(SIN(theta)) * vAxis;
         Point3f base = atmCenter + v * atmRadius;
         Vec3f toCenter = base - center;
         cosSunAngle = -1e9;
         float getAngle = 0;
         for(j=0;j<number_lights;j++) {
            getAngle = (toCenter * sunDirection[j]) / radius / distanceToPlanet[planet_star[j]];
            if(getAngle > cosSunAngle) cosSunAngle = getAngle;
         }

         brightness = 1.0f;

         if (lit)
         {
            if (cosSunAngle < -0.2f)
            {
               brightness = 0;
               sunset = 0;
            }
            else
            {
               t = (0.2f + cosSunAngle) * 2.5f;
               brightness = CLAMP(t,0.0f,1.0f);
               sunset = CLAMP(t - 0.25f,0.0f,1.0f);
            }
            topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
            topColor[0] = (topColor[0] * brightness) + (sceneAmbient[0] * (1.0 - brightness));
            topColor[1] = (topColor[1] * brightness) + (sceneAmbient[1] * (1.0 - brightness));
            topColor[2] = (topColor[2] * brightness) + (sceneAmbient[2] * (1.0 - brightness));

         }
         else {
            topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
         }

         glColor4f(topColor[0], topColor[1], topColor[2], 0.0f);
         glVertex(base + toCenter * (height * 1.25f));
         glColor4f(topColor[0], topColor[1], topColor[2], 0.35f);
         glVertex(base + toCenter * (height * 1.5f));
      }
      glEnd();
   }

   glBegin(GL_QUAD_STRIP);   
    for (i = 0; i <= divisions; i++)
    {
        float theta = float(i) / float(divisions + offset) * 2.0f * float(PI);
        Vec3f v = float(COS(theta)) * uAxis + float(SIN(theta)) * vAxis;
        Point3f base = atmCenter + v * atmRadius;
        Vec3f toCenter = base - center;
      cosSunAngle = -1e9;
      float getAngle = 0;
      for(j=0;j<number_lights;j++) {
         getAngle = (toCenter * sunDirection[j]) / radius / distanceToPlanet[planet_star[j]];
         if(getAngle > cosSunAngle) cosSunAngle = getAngle;
      }

        brightness = 1.0f;

        if (lit)
        {
            if (cosSunAngle < -0.2f)
            {
                brightness = 0;
            sunset = 0;
            }
            else
            {
                t = (0.2f + cosSunAngle) * 2.5f;
                brightness = CLAMP(t,0.0f,1.0f);
            sunset = CLAMP(t - 0.25f,0.0f,1.0f);
            }
         sColor[0] = 1.0f - skyColor[0] * combined_light[0];
         sColor[1] = 1.0f - skyColor[1] * combined_light[1];
         sColor[2] = 1.0f - skyColor[2] * combined_light[2];
         returnHighestColor(sColor);
         sColor[0] *= planetInfo.brightness;
         sColor[1] *= planetInfo.brightness;
         sColor[2] *= planetInfo.brightness;
           botColor[0] = (skyColor2[0] * sunset) + (sColor[0] * (1.0 - sunset));
            botColor[1] = (skyColor2[1] * sunset) + (sColor[1] * (1.0 - sunset));
            botColor[2] = (skyColor2[2] * sunset) + (sColor[2] * (1.0 - sunset));
           topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
           botColor[0] = (botColor[0] * brightness) + (sceneAmbient[0] * (1.0 - brightness));
            botColor[1] = (botColor[1] * brightness) + (sceneAmbient[1] * (1.0 - brightness));
            botColor[2] = (botColor[2] * brightness) + (sceneAmbient[2] * (1.0 - brightness));
           topColor[0] = (topColor[0] * brightness) + (sceneAmbient[0] * (1.0 - brightness));
            topColor[1] = (topColor[1] * brightness) + (sceneAmbient[1] * (1.0 - brightness));
            topColor[2] = (topColor[2] * brightness) + (sceneAmbient[2] * (1.0 - brightness));

      }
      else {
           botColor[0] = skyColor2[0];
            botColor[1] = skyColor2[1];
            botColor[2] = skyColor2[2];
           topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
      }

        glColor4f(botColor[0], botColor[1], botColor[2], 1.0f);
        glVertex(center + toCenter * 0.999f);
        glColor4f(topColor[0], topColor[1], topColor[2], 0.0f);
        glVertex(base + toCenter * height);
    }
   glEnd();

   glBegin(GL_QUAD_STRIP);   
    for (i = 0; i <= divisions; i++)
    {
        float theta = float(i) / float(divisions + offset) * 2.0f * float(PI);
        Vec3f v = float(COS(theta)) * uAxis + float(SIN(theta)) * vAxis;
        Point3f base = atmCenter + v * atmRadius;
        Vec3f toCenter = base - center;
      cosSunAngle = -1e9;
      float getAngle = 0;
      for(j=0;j<number_lights;j++) {
         getAngle = (toCenter * sunDirection[j]) / radius / distanceToPlanet[planet_star[j]];
         if(getAngle > cosSunAngle) cosSunAngle = getAngle;
      }

        brightness = 1.0f;

        if (lit)
        {
            if (cosSunAngle < -0.2f)
            {
                brightness = 0;
            sunset = 0;
            }
            else
            {
                t = (0.2f + cosSunAngle) * 2.5f;
                brightness = CLAMP(t,0.0f,1.0f);
            sunset = CLAMP(t - 0.25f,0.0f,1.0f);
            }
         sColor[0] = 1.0f - skyColor[0] * combined_light[0];
         sColor[1] = 1.0f - skyColor[1] * combined_light[1];
         sColor[2] = 1.0f - skyColor[2] * combined_light[2];
         returnHighestColor(sColor);
         sColor[0] *= planetInfo.brightness;
         sColor[1] *= planetInfo.brightness;
         sColor[2] *= planetInfo.brightness;
           botColor[0] = (skyColor2[0] * sunset) + (sColor[0] * (1.0 - sunset));
            botColor[1] = (skyColor2[1] * sunset) + (sColor[1] * (1.0 - sunset));
            botColor[2] = (skyColor2[2] * sunset) + (sColor[2] * (1.0 - sunset));
           topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
           botColor[0] = (botColor[0] * brightness) + (sceneAmbient[0] * (1.0 - brightness));
            botColor[1] = (botColor[1] * brightness) + (sceneAmbient[1] * (1.0 - brightness));
            botColor[2] = (botColor[2] * brightness) + (sceneAmbient[2] * (1.0 - brightness));
           topColor[0] = (topColor[0] * brightness) + (sceneAmbient[0] * (1.0 - brightness));
            topColor[1] = (topColor[1] * brightness) + (sceneAmbient[1] * (1.0 - brightness));
            topColor[2] = (topColor[2] * brightness) + (sceneAmbient[2] * (1.0 - brightness));

      }
      else {
           botColor[0] = skyColor2[0];
            botColor[1] = skyColor2[1];
            botColor[2] = skyColor2[2];
           topColor[0] = skyColor[0];
            topColor[1] = skyColor[1];
            topColor[2] = skyColor[2];
      }

        glColor4f(botColor[0], botColor[1], botColor[2], 0.0f);
        glVertex(center + toCenter * 0.994f);
        glColor4f(botColor[0], botColor[1], botColor[2], 1.0f);
        glVertex(center + toCenter * 0.999f);

    }
   glEnd();

   glBegin(GL_QUAD_STRIP);   

    for (i = 0; i <= divisions; i++)
    {
        float theta = float(i) / float(divisions + 0.00237f) * 2.0f * float(PI);
        Vec3f v = float(COS(theta)) * uAxis + float(SIN(theta)) * vAxis;
        Point3f base = atmCenter + v * atmRadius;
        Vec3f toCenter = base - center;
      cosSunAngle = -1e9;
      float getAngle = -1e9;
      for(j=0;j<number_lights;j++) {
         getAngle = (toCenter * sunDirection[j]) / radius / distanceToPlanet[planet_star[j]];
         if(getAngle > cosSunAngle) cosSunAngle = getAngle;
      }

        brightness = 1.0f;

        if (lit)
        {
            if (cosSunAngle < -0.2f)
            {
            haze = 0;
            }
            else
            {
                t = (0.2f + cosSunAngle) * 2.5f;
            haze = CLAMP(t * 0.5f,0,1);
            }

           hColor[0] = (fogColor[0] * haze) + (sceneAmbient[0] * (1.0 - haze));
            hColor[1] = (fogColor[1] * haze) + (sceneAmbient[1] * (1.0 - haze));
            hColor[2] = (fogColor[2] * haze) + (sceneAmbient[2] * (1.0 - haze));

      }
      else {
           hColor[0] = fogColor[0];
            hColor[1] = fogColor[1];
            hColor[2] = fogColor[2];
      }
        glColor4f(hColor[0], hColor[1], hColor[2], 0.0f);
        glVertex(center + toCenter * 0.75f);
        glColor4f(hColor[0], hColor[1], hColor[2], 0.5f * planetInfo.hazeDensity);
        glVertex(center + toCenter * 0.999f);

    }
   glEnd();

   glDisable(GL_COLOR_MATERIAL);
   glEnable(GL_LIGHTING);
   glEnable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
}


I didnt do anything that spectacular...I could probably speed things up a bit using vertex arrays....but its not slowing down my FPS that bad...


For those interested in this update to DWU...I will have it up sometime soon...

Maybe this will be seen very soon in Celestia!
I'm trying to teach the cavemen how to play scrabble, its uphill work. The only word they know is Uhh and they dont know how to spell it!

Avatar
selden
Developer
Posts: 10192
Joined: 04.09.2002
With us: 22 years 2 months
Location: NY, USA

Post #2by selden » 24.06.2005, 10:14

I was just forwarded a link to a site that shows Titan's haze being rendered with POVRay. Of course, it uses quite different rendering techniques, but gives an idea of what can be accomplished.

http://www.beugungsbild.de/huygens/povr ... dered.html
Selden

ElChristou
Developer
Posts: 3776
Joined: 04.02.2005
With us: 19 years 9 months

Post #3by ElChristou » 24.06.2005, 13:05

Rassilon,

Nice, Tx for the work... Question: is this condition in the haze is permanent or only visible in special opportunity? (first time I saw it)

The link from Selden is really impressive... The day OpenGL will be as powerfull as a raytrace or a radiosity will be a wonderfull day (perhaps in 50 years... :?)
Image

Topic author
Rassilon
Posts: 1887
Joined: 29.01.2002
With us: 22 years 9 months
Location: Altair

Post #4by Rassilon » 24.06.2005, 16:34

It already is...POVRay was more than likely built using an OpenGL engine...
I'm trying to teach the cavemen how to play scrabble, its uphill work. The only word they know is Uhh and they dont know how to spell it!

Harry
Posts: 559
Joined: 05.09.2003
With us: 21 years 2 months
Location: Germany

Post #5by Harry » 24.06.2005, 20:36

Rassilon wrote:POVRay was more than likely built using an OpenGL engine...

No, it is using good old ray-tracing, which doesn't have much to do with OpenGL. Povray is very old - it started around 1989, long before 3D graphic cards became available for PCs (1996?).

Have a look at the images in:
ftp://ftp.povray.org/pub/povray/Hall-Of-Fame/
Note the modification time of the files...

More links:
http://en.wikipedia.org/wiki/POV-Ray
http://en.wikipedia.org/wiki/Raytracing


Harald

ElChristou
Developer
Posts: 3776
Joined: 04.02.2005
With us: 19 years 9 months

Post #6by ElChristou » 24.06.2005, 21:48

Harry wrote:...No, it is using good old ray-tracing, which doesn't have much to do with OpenGL...


Right, raytrace/radiosity are quite different fron OpenGL renderer... the "touch" of the images of the Selden's link is quite caracteristic...
Image

Topic author
Rassilon
Posts: 1887
Joined: 29.01.2002
With us: 22 years 9 months
Location: Altair

Post #7by Rassilon » 25.06.2005, 02:17

Ive seen some OpenGL projects almost as impressive....I suppose with todays cards those images could be rendered....but I dont think something like that could have in the 80's except on a mainframe....Maybe on an amiga but they still were very slow machines....

And Im willing to bet most of those raycasting programs couldnt be used for full blown animation except on a beefed up pentium...I cannot begin to imagine how many trillions of triangles are in this image....

ftp://ftp.povray.org/pub/povray/Hall-Of ... tplant.jpg

And I dont think 50 years does graphics justice....Just look how far we have come since 1980...The Atari 2600 days!
I'm trying to teach the cavemen how to play scrabble, its uphill work. The only word they know is Uhh and they dont know how to spell it!

ElChristou
Developer
Posts: 3776
Joined: 04.02.2005
With us: 19 years 9 months

Post #8by ElChristou » 25.06.2005, 03:19

Rassilon wrote:...And I dont think 50 years does graphics justice....


well, I can say that in 10 years, I have upgraded my rendering from raytrace to radiosity...
10 years ago, 5-15 hours of rendering were necessary to do a good raytrace scene (3k pix) on a "normal" config... Now I do the same in radiosity... at the time, radiosity was really too heavy...
To see such rendering in real time is quite inimaginable for now... and for a long time I'm afraid... (think in 60fps on a 1024 in radiosity...)
Image


Return to “Celestia Users”