Page 1 of 1

Titan's haze

Posted: 24.06.2005, 04:09
by Rassilon
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!

Posted: 24.06.2005, 10:14
by selden
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

Posted: 24.06.2005, 13:05
by ElChristou
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... :?)

Posted: 24.06.2005, 16:34
by Rassilon
It already is...POVRay was more than likely built using an OpenGL engine...

Posted: 24.06.2005, 20:36
by Harry
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

Posted: 24.06.2005, 21:48
by ElChristou
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...

Posted: 25.06.2005, 02:17
by Rassilon
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!

Posted: 25.06.2005, 03:19
by ElChristou
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...)