2012-04-18 6 views
16

Durante los últimos días, he intentado hacer funcionar las texturas Three.js. El problema que he tenido es que mi navegador estaba bloqueando las texturas de la carga, lo que se resolvió siguiendo las instrucciones here.¿Cómo puedo representar una "atmósfera" sobre una representación de la Tierra en Three.js?

De todos modos, estoy haciendo un juego de navegador espacial para una de mis clases que demuestra navegando nave espacial a través del espacio. Entonces, estoy renderizando un montón de planetas, siendo la Tierra uno de ellos. He incluido una imagen de mi representación de la Tierra a continuación. Se ve bien, pero lo que estoy tratando de hacer es hacer que parezca más realista agregando una 'atmósfera' alrededor del planeta.

He mirado alrededor, y he encontrado algunos realmente neat looking creations que tratan con resplandor, pero no creo que se apliquen a mi situación, desafortunadamente.

Y aquí está el código que añade la tierra a mi escena (que es una versión modificada del código que recibí de un tutorial Three.js):

function addEarth(x,y){ 

     var sphereMaterial = 
     new THREE.MeshLambertMaterial({ 
      //color: 0x0000ff, 
      map: earthTexture 
     }); 

     // set up the sphere vars 
     var radius = 75; 
     segments = 16; 
     rings = 16; 

     // create a new mesh with 
     // sphere geometry - we will cover 
     // the sphereMaterial next! 
     earth = new THREE.Mesh(

     new THREE.SphereGeometry(
     radius, 
     segments, 
     rings), 

     sphereMaterial); 

     earth.position.x = x; 
     earth.position.y = y; 

     // add the sphere to the scene 
     scene.add(earth); 
    } 

enter image description here

Respuesta

13

¿qué estás buscando ¿en tu atmósfera? Podría ser tan simple como representar otra esfera transparente ligeramente más grande en la parte superior de su globo terráqueo, o podría ser muy muy complejo, en realidad refractando la luz que entra en él. (Casi como la dispersión subsuperficial utilizada en la representación de la piel).

Nunca he probado un efecto así, pero algunos rápidos de Google muestran algunos resultados prometedores. Por ejemplo, creo que this effect se ve bastante bien, y el autor incluso lo siguió con un más detailed variant más adelante. Si está interesado en un desglose más técnico this technique detalla muchos de los antecedentes teóricos. Estoy seguro de que hay más, solo tienes que hurgar un poco. (¡A decir verdad, no sabía que este era un tema de renderizado tan popular!)

Si tiene problemas con algún aspecto de esas técnicas específicamente como se aplica a Three.js, ¡no dude en preguntar!

[ACTUALIZACIÓN]

Ah, lo siento. Sí, eso es mucho para lanzarte sin conocimiento previo del shader.

El código en el segundo enlace es en realidad un archivo DirectX FX, el código central es HLSL, por lo que no es algo que simplemente se conecta a WebGL pero los dos formatos de sombreador son lo suficientemente similares como para que no sea un problema traducir entre ellos. Si realmente conoces sombreadores, eso es. Yo recomendaría leer sobre cómo funcionan los sombreadores antes de intentar sumergirme en un efecto complicado como este.

Comenzaría con algo simple como this tutorial, que simplemente habla sobre cómo obtener un sombreador básico que se ejecuta con Three.js. Una vez que sepa cómo obtener un sombreador que trabaje con los tutoriales de Three.js y GLSL (como this one), le brindará información básica sobre cómo funciona un sombreador y qué puede hacer con él.

Sé que parece un montón de trabajo por adelantado, pero si quieres hacer efectos visuales avanzados en WebGL (y esto sin duda se ajusta a la factura de efectos avanzados) absolutamente debe comprender sombreadores!

Por otra parte, si está buscando una solución rápida, siempre hay esa opción de esfera transparente de la que estaba hablando.:)

+0

Wow, esos ejemplos son realmente impresionante! Sin embargo, debes saber que soy nuevo en esto. En el segundo enlace que publicó, parece que hay algún código de aspecto C. ¿Es así como usaría ese sombreador de atmósfera? ¿Es esto lo que llaman 'glsl'? ¿Cómo implemento esto en Three.js? Perdón por mi gran ignorancia sobre el tema. – Hassan

+0

Gracias por las actualizaciones rápidas. Creo que seguiré adelante y trataré de aprender sobre los sombreadores, ya que parecen importantes. Sin embargo, dado que tengo que demostrar esto en aproximadamente una semana, no creo que pueda aprenderlo todo en ese plazo. Pero lo intentaré, y luego, como dices, siempre puedo crear una esfera transparente. – Hassan

22

Bueno, una pregunta vieja y ya respondida pero quería agregar mi solución para la consideración de principiante. Tiene plaing a lo largo de la dispersión atmosférica y GLSL durante mucho tiempo y vienen a esta versión simplificada VEEERRRYYY (si la animación se detiene actualización de la página o ver la GIF en algo más decend):

[example[1]

  1. planeta es y elipsoide (centro x, y, z y radios rx, ry, rz)
  2. atmósfera también es ellipsod (el mismo pero más grande por la altura de la atmósfera)
  3. todo el renderizado se hace normalmente pero además de eso se agrega 1 pase para el planeta observador cercano
  4. que pasan es quad único que cubre toda la pantalla
  5. dentro fragmento que calcula la intersección de rayos pixel con estos 2 elipsoides
  6. tomar la parte visible (no detrás, no después de suelo)
  7. calcular la atmósfera en el interior longitud ray
  8. distorsionan color original como función de r, g, b params escalados por la longitud del rayo (algo así como la integración a lo largo de la ruta)
    • un cierto color se toma algunos dadas ...
    • afecta en gran medida del color por lo que su posible simular diferentes atmósferas por sólo unos pocos atributos
  9. que funcione bien dentro y fuera de la atmósfera (desde lejos)
  10. puede añadir estrellas cercanas como fuente de luz (yo uso máximo de 3 estrellas del sistema)

el resultado es impresionante ver imágenes a continuación:

enter image description here enter image description here enter image description here enter image description here enter image description here

Vertex:

/* SSH GLSL Atmospheric Ray light scattering ver 3.0 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_ONE,GL_ONE); 
    use with single quad covering whole screen 

    no Modelview/Projection/Texture matrixes used 

    gl_Normal is camera direction in ellipsoid space 
    gl_Vertex is pixel in ellipsoid space 
    gl_Color is pixel pos in screen space <-1,+1> 

    const int _lights=3; 
    uniform vec3 light_dir[_lights];  // direction to local star in ellipsoid space 
    uniform vec3 light_col[_lights];  // local star color * visual intensity 
    uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space 
    uniform vec4 B0;      // atmosphere scattering coefficient (affects color) (r,g,b,-) 

    [ToDo:] 
    add light map texture for light source instead of uniform star colide parameters 
    - all stars and distant planets as dots 
    - near planets ??? maybe too slow for reading pixels 
    aspect ratio correction 
*/ 

varying vec3 pixel_nor;  // camera direction in ellipsoid space 
varying vec4 pixel_pos;  // pixel in ellipsoid space 

void main(void) 
    { 
    pixel_nor=gl_Normal; 
    pixel_pos=gl_Vertex; 
    gl_Position=gl_Color; 
    } 

Fragmento:

varying vec3 pixel_nor;    // camera direction in ellipsoid space 
varying vec4 pixel_pos;    // pixel in ellipsoid space 

uniform vec3 planet_r;    // rx^-2,ry^-2,rz^-2 - surface 
uniform vec3 planet_R;    // Rx^-2,Ry^-2,Rz^-2 - atmosphere 
uniform float planet_h;    // atmoshere height [m] 
uniform float view_depth;   // max. optical path length [m] ... saturation 

// lights are only for local stars-atmosphere ray colision to set start color to star color 
const int _lights=3; 
uniform vec3 light_dir[_lights];  // direction to local star in ellipsoid space 
uniform vec3 light_col[_lights];  // local star color * visual intensity 
uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space 
uniform vec4 B0;      // atmosphere scattering coefficient (affects color) (r,g,b,-) 

// compute length of ray(p0,dp) to intersection with ellipsoid((0,0,0),r) -> view_depth_l0,1 
// where r.x is elipsoid rx^-2, r.y = ry^-2 and r.z=rz^-2 
float view_depth_l0=-1.0,view_depth_l1=-1.0; 
bool _view_depth(vec3 p0,vec3 dp,vec3 r) 
    { 
    float a,b,c,d,l0,l1; 
    view_depth_l0=-1.0; 
    view_depth_l1=-1.0; 
    a=(dp.x*dp.x*r.x) 
    +(dp.y*dp.y*r.y) 
    +(dp.z*dp.z*r.z); a*=2.0; 
    b=(p0.x*dp.x*r.x) 
    +(p0.y*dp.y*r.y) 
    +(p0.z*dp.z*r.z); b*=2.0; 
    c=(p0.x*p0.x*r.x) 
    +(p0.y*p0.y*r.y) 
    +(p0.z*p0.z*r.z)-1.0; 
    d=((b*b)-(2.0*a*c)); 
    if (d<0.0) return false; 
    d=sqrt(d); 
    l0=(-b+d)/a; 
    l1=(-b-d)/a; 
    if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; } 
    if (l0<0.0)   { a=l0; l0=l1; l1=a; } 
    if (l0<0.0) return false; 
    view_depth_l0=l0; 
    view_depth_l1=l1; 
    return true; 
    } 
// determine if ray (p0,dp) hits a sphere ((0,0,0),r) 
// where r is (sphere radius)^-2 
bool _star_colide(vec3 p0,vec3 dp,float r) 
    { 
    float a,b,c,d,l0,l1; 
    a=(dp.x*dp.x*r) 
    +(dp.y*dp.y*r) 
    +(dp.z*dp.z*r); a*=2.0; 
    b=(p0.x*dp.x*r) 
    +(p0.y*dp.y*r) 
    +(p0.z*dp.z*r); b*=2.0; 
    c=(p0.x*p0.x*r) 
    +(p0.y*p0.y*r) 
    +(p0.z*p0.z*r)-1.0; 
    d=((b*b)-(2.0*a*c)); 
    if (d<0.0) return false; 
    d=sqrt(d); 
    l0=(-b+d)/a; 
    l1=(-b-d)/a; 
    if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; } 
    if (l0<0.0)   { a=l0; l0=l1; l1=a; } 
    if (l0<0.0) return false; 
    return true; 
    } 

// compute atmosphere color between ellipsoids (planet_pos,planet_r) and (planet_pos,planet_R) for ray(pixel_pos,pixel_nor) 
vec3 atmosphere() 
    { 
    const int n=8; 
    const float _n=1.0/float(n); 
    int i; 
    bool b0,b1; 
    vec3 p0,p1,dp,p,c,b; 
    // c - color of pixel from start to end 

    float l0,l1,l2,h,dl; 
    c=vec3(0.0,0.0,0.0); 
    b0=_view_depth(pixel_pos.xyz,pixel_nor,planet_r); 
    if ((b0)&&(view_depth_l0>0.0)&&(view_depth_l1<0.0)) return c; 
    l0=view_depth_l0; 
    b1=_view_depth(pixel_pos.xyz,pixel_nor,planet_R); 
    l1=view_depth_l0; 
    l2=view_depth_l1; 

    dp=pixel_nor; 
    p0=pixel_pos.xyz; 

    if (!b0) 
     {          // outside surface 
     if (!b1) return c;      // completly outside planet 
     if (l2<=0.0)       // inside atmosphere to its boundary 
      { 
      l0=l1; 
      } 
     else{         // throu atmosphere from boundary to boundary 
      p0=p0+(l1*dp); 
      l0=l2-l1; 
      } 
     // if a light source is in visible path then start color is light source color 
     for (i=0;i<_lights;i++) 
     if (light_posr[i].a<=1.0) 
     if (_star_colide(p0-light_posr[i].xyz,dp,light_posr[i].a)) 
     c+=light_col[i]; 
     } 
    else{          // into surface 
     if (l0<l1) b1=false;     // atmosphere is behind surface 
     if (!b1)        // inside atmosphere to surface 
      { 
      l0=l0; 
      } 
     else{         // from atmosphere boundary to surface 
      p0=p0+(l1*dp); 
      l0=l0-l1; 
      } 
     } 
    dp*=l0; 
    p1=p0+dp; 
    dp*=_n; 
/* 
    p=normalize(p1); 
    h=0.0; l2=0.0; 
    for (i=0;i<_lights;i++) 
    if (light_posr[i].a<=1.0) 
     { 
     dl=dot(pixel_nor,light_dir[i]);   // cos(ang: light-eye) 
     if (dl<0.0) dl=0.0; 
     h+=dl; 
     dl=dot(p,light_dir[i]);     // normal shading 
     if (dl<0.0) dl=0.0; 
     l2+=dl; 
     } 
    if (h>1.0) h=1.0; 
    if (l2>1.0) l2=1.0; 
    h=0.5*(2.0+(h*h)); 
*/ 
    float qqq=dot(normalize(p1),light_dir[0]); 


    dl=l0*_n/view_depth; 
    for (p=p1,i=0;i<n;p-=dp,i++)    // p1->p0 path throu atmosphere from ground 
     { 
     _view_depth(p,normalize(p),planet_R); // view_depth_l0=depth above atmosphere top [m] 
     h=exp(view_depth_l0/planet_h)/2.78; 

     b=B0.rgb*h*dl; 
     c.r*=1.0-b.r; 
     c.g*=1.0-b.g; 
     c.b*=1.0-b.b; 
     c+=b*qqq; 
     } 
    if (c.r<0.0) c.r=0.0; 
    if (c.g<0.0) c.g=0.0; 
    if (c.b<0.0) c.b=0.0; 
    h=0.0; 
    if (h<c.r) h=c.r; 
    if (h<c.g) h=c.g; 
    if (h<c.b) h=c.b; 
    if (h>1.0) 
     { 
     h=1.0/h; 
     c.r*=h; 
     c.g*=h; 
     c.b*=h; 
     } 
    return c; 
    } 

void main(void) 
    { 
    gl_FragColor.rgb=atmosphere(); 
    } 

Lo sentimos, pero es una fuente muy viejo de mi ... debe, probablemente, se convirtieron al perfil núcleo

[ Editar 1] lo siento, olvide agregar mis constantes de dispersión de entrada para la atmósfera de la Tierra

double view_depth=1000000.0; // [m] ... longer path is saturated atmosphere color 
    double ha=40000.0;    // [m] ... usable atmosphere height (higher is too low pressure) 

// this is how B0 should be computed (for real atmospheric scattering with nested volume integration) 
// const float lambdar=650.0*0.000000001; // wavelengths for R,G,B rays 
// const float lambdag=525.0*0.000000001; 
// const float lambdab=450.0*0.000000001; 
// double r=1.0/(lambdar*lambdar*lambdar*lambdar); // B0 coefficients 
// double g=1.0/(lambdag*lambdag*lambdag*lambdag); 
// double b=1.0/(lambdab*lambdab*lambdab*lambdab); 

// and these are my empirical coefficients for earth like 
// blue atmosphere with my simplified integration style 
// images above are rendered with this: 
    float r=0.198141888310295; 
    float g=0.465578010163675; 
    float b=0.862540960504986; 
    float B0=2.50000E-25; 
    i=glGetUniformLocation(ShaderProgram,"planet_h"); glUniform1f(i,ha); 
    i=glGetUniformLocation(ShaderProgram,"view_depth"); glUniform1f(i,view_depth); 
    i=glGetUniformLocation(ShaderProgram,"B0");  glUniform4f(i,r,g,b,B0); 
// all other atributes are based on position and size of planet and are 
// pretty straightforward so here is just the earth size i use ... 
    double r_equator=6378141.2; // [m] 
    double r_poles=6356754.8; // [m] 

[Edit2] 09/03/2014 nuevo código fuente

que tenía algún tiempo recientemente para aplicar zoom a la mía motor y descubrió que el código fuente original no es muy preciso desde lejos y por encima de 0,002 UA. Sin Zoom, solo quedan unos pocos píxeles, por lo que no se ve nada, pero con el zoom todos cambian, así que intenté mejorar la precisión tanto como pude.

Después de algunos ajustes más logro que pueda utilizarse hasta 25,0 UA y con artefactos de interpolación de hasta 50,0 a 100,0 UA. Ese es el límite para HW actual porque no puedo pasar no flat fp64 a interpoladores de vértice a fragmento. Una manera de evitarlo podría ser mover la transformación del sistema de coordenadas a fragmento, pero aún no lo hemos probado. Aquí hay algunos cambios:

  • nueva fuente utiliza 64 bits flota
  • y añadir uniform int lights que es el recuento de las luces usadas
  • también algunos cambios en el significado B0 (que son constantes dependientes de la longitud de onda más larga que no, pero el color en vez) por lo que debe cambiar ligeramente el valor uniforme en el código de la CPU.
  • algunas mejoras de rendimiento se añadió

[vértice]

/* SSH GLSL Atmospheric Ray light scattering ver 3.1 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); 
    use with single quad covering whole screen 

    no Modelview/Projection/Texture matrixes used 

    gl_Normal is camera direction in ellipsoid space 
    gl_Vertex is pixel in ellipsoid space 
    gl_Color is pixel pos in screen space <-1,+1> 

    const int _lights=3; 
    uniform int lights;     // actual number of lights 
    uniform vec3 light_dir[_lights];  // direction to local star in ellipsoid space 
    uniform vec3 light_col[_lights];  // local star color * visual intensity 
    uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space 
    uniform vec4 B0;      // atmosphere scattering coefficient (affects color) (r,g,b,-) 

    [ToDo:] 
    add light map texture for light source instead of uniform star colide parameters 
    - all stars and distant planets as dots 
    - near planets ??? maybe too slow for reading pixels 
    aspect ratio correction 
*/ 

varying vec3 pixel_nor;  // camera direction in ellipsoid space 
varying vec4 pixel_pos;  // pixel in ellipsoid space 
varying vec4 pixel_scr;  // pixel in screen space <-1,+1> 

varying vec3 p_r;    // rx,ry,rz 
uniform vec3 planet_r;   // rx^-2,ry^-2,rz^-2 - surface 

void main(void) 
    { 
    p_r.x=1.0/sqrt(planet_r.x); 
    p_r.y=1.0/sqrt(planet_r.y); 
    p_r.z=1.0/sqrt(planet_r.z); 
    pixel_nor=gl_Normal; 
    pixel_pos=gl_Vertex; 
    pixel_scr=gl_Color; 
    gl_Position=gl_Color; 
    } 

[fragmento]

#extension GL_ARB_gpu_shader_fp64 : enable 
double abs(double x) { if (x<0.0) x=-x; return x; } 

varying vec3 pixel_nor;    // camera direction in ellipsoid space 
varying vec4 pixel_pos;    // pixel in ellipsoid space 
varying vec4 pixel_scr;    // pixel in screen space 
varying vec3 p_r;     // rx,ry,rz       

uniform vec3 planet_r;    // rx^-2,ry^-2,rz^-2 - surface 
uniform vec3 planet_R;    // Rx^-2,Ry^-2,Rz^-2 - atmosphere 
uniform float planet_h;    // atmoshere height [m] 
uniform float view_depth;   // max. optical path length [m] ... saturation 

// lights are only for local stars-atmosphere ray colision to set start color to star color 
const int _lights=3; 
uniform int lights;     // actual number of lights 
uniform vec3 light_dir[_lights];  // direction to local star in ellipsoid space 
uniform vec3 light_col[_lights];  // local star color * visual intensity 
uniform vec4 light_posr[_lights]; // local star position and radius^-2 in ellipsoid space 
uniform vec4 B0;      // atmosphere scattering color coefficients (r,g,b,ambient) 

// compute length of ray(p0,dp) to intersection with ellipsoid((0,0,0),r) -> view_depth_l0,1 
// where r.x is elipsoid rx^-2, r.y = ry^-2 and r.z=rz^-2 
const double view_depth_max=100000000.0; // > max view depth 
double view_depth_l0=-1.0, // view_depth_l0 first hit 
     view_depth_l1=-1.0; // view_depth_l1 second hit 
bool _view_depth_l0=false; 
bool _view_depth_l1=false; 
bool _view_depth(vec3 _p0,vec3 _dp,vec3 _r) 
    { 
    dvec3 p0,dp,r; 
    double a,b,c,d,l0,l1; 
    view_depth_l0=-1.0; _view_depth_l0=false; 
    view_depth_l1=-1.0; _view_depth_l1=false; 
    // conversion to double 
    p0=dvec3(_p0); 
    dp=dvec3(_dp); 
    r =dvec3(_r); 
    // quadratic equation a.l.l+b.l+c=0; l0,l1=?; 
    a=(dp.x*dp.x*r.x) 
    +(dp.y*dp.y*r.y) 
    +(dp.z*dp.z*r.z); 
    b=(p0.x*dp.x*r.x) 
    +(p0.y*dp.y*r.y) 
    +(p0.z*dp.z*r.z); b*=2.0; 
    c=(p0.x*p0.x*r.x) 
    +(p0.y*p0.y*r.y) 
    +(p0.z*p0.z*r.z)-1.0; 
    // discriminant d=sqrt(b.b-4.a.c) 
    d=((b*b)-(4.0*a*c)); 
    if (d<0.0) return false; 
    d=sqrt(d); 
    // standard solution l0,l1=(-b +/- d)/2.a 
    a*=2.0; 
    l0=(-b+d)/a; 
    l1=(-b-d)/a; 
    // alternative solution q=-0.5*(b+sign(b).d) l0=q/a; l1=c/q; (should be more accurate sometimes) 
// if (b<0.0) d=-d; d=-0.5*(b+d); 
// l0=d/a; 
// l1=c/d; 
    // sort l0,l1 asc 
    if ((l0<0.0)||((l1<l0)&&(l1>=0.0))) { a=l0; l0=l1; l1=a; } 
    // exit 
    if (l1>=0.0) { view_depth_l1=l1; _view_depth_l1=true; } 
    if (l0>=0.0) { view_depth_l0=l0; _view_depth_l0=true; return true; } 
    return false; 
    } 

// determine if ray (p0,dp) hits a sphere ((0,0,0),r) 
// where r is (sphere radius)^-2 
bool _star_colide(vec3 _p0,vec3 _dp,float _r) 
    { 
    dvec3 p0,dp,r; 
    double a,b,c,d,l0,l1; 
    // conversion to double 
    p0=dvec3(_p0); 
    dp=dvec3(_dp); 
    r =dvec3(_r); 
    // quadratic equation a.l.l+b.l+c=0; l0,l1=?; 
    a=(dp.x*dp.x*r) 
    +(dp.y*dp.y*r) 
    +(dp.z*dp.z*r); 
    b=(p0.x*dp.x*r) 
    +(p0.y*dp.y*r) 
    +(p0.z*dp.z*r); b*=2.0; 
    c=(p0.x*p0.x*r) 
    +(p0.y*p0.y*r) 
    +(p0.z*p0.z*r)-1.0; 
    // discriminant d=sqrt(b.b-4.a.c) 
    d=((b*b)-(4.0*a*c)); 
    if (d<0.0) return false; 
    d=sqrt(d); 
    // standard solution l0,l1=(-b +/- d)/2.a 
    a*=2.0; 
    l0=(-b+d)/a; 
    l1=(-b-d)/a; 
    // alternative solution q=-0.5*(b+sign(b).d) l0=q/a; l1=c/q; (should be more accurate sometimes) 
// if (b<0.0) d=-d; d=-0.5*(b+d); 
// l0=d/a; 
// l1=c/d; 
    // sort l0,l1 asc 
    if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; } 
    if (l0<0.0)   { a=l0; l0=l1; l1=a; } 
    if (l0<0.0) return false; 
    return true; 
    } 

// compute atmosphere color between ellipsoids (planet_pos,planet_r) and (planet_pos,planet_R) for ray(pixel_pos,pixel_nor) 
vec4 atmosphere() 
    { 
    const int n=8; 
    const float _n=1.0/float(n); 
    int i; 
    bool b0,b1; 
    vec3 p0,p1,dp,p,b; 
    vec4 c;  // c - color of pixel from start to end 

    float h,dl,ll; 
    double l0,l1,l2; 
    bool e0,e1,e2; 
    c=vec4(0.0,0.0,0.0,0.0); // a=0.0 full background color, a=1.0 no background color (ignore star) 
    b1=_view_depth(pixel_pos.xyz,pixel_nor,planet_R); 
    if (!b1) return c;       // completly outside atmosphere 
    e1=_view_depth_l0; l1=view_depth_l0;  // first atmosphere hit 
    e2=_view_depth_l1; l2=view_depth_l1;  // second atmosphere hit 
    b0=_view_depth(pixel_pos.xyz,pixel_nor,planet_r); 
    e0=_view_depth_l0; l0=view_depth_l0;  // first surface hit 
    if ((b0)&&(view_depth_l1<0.0)) return c; // under ground 
    // set l0 to view depth and p0 to start point 
    dp=pixel_nor; 
    p0=pixel_pos.xyz; 
    if (!b0)         // outside surface 
     { 
     if (!e2)        // inside atmosphere to its boundary 
      { 
      l0=l1; 
      } 
     else{         // throu atmosphere from boundary to boundary 
      p0=vec3(dvec3(p0)+(dvec3(dp)*l1)); 
      l0=l2-l1; 
      } 
     // if a light source is in visible path then start color is light source color 
     for (i=0;i<lights;i++) 
     if (_star_colide(p0.xyz-light_posr[i].xyz,dp.xyz,light_posr[i].a*0.75)) // 0.75 is enlargment to hide star texture corona 
      { 
      c.rgb+=light_col[i]; 
      c.a=1.0; // ignore already drawed local star color 
      } 
     } 
    else{          // into surface 
     if (l1<l0)        // from atmosphere boundary to surface 
      { 
      p0=vec3(dvec3(p0)+(dvec3(dp)*l1)); 
      l0=l0-l1; 
      } 
     else{         // inside atmosphere to surface 
      l0=l0; 
      } 
     } 
    // set p1 to end of view depth, dp to intergral step 
    p1=vec3(dvec3(p0)+(dvec3(dp)*l0)); dp=p1-p0; 
    dp*=_n; 

    dl=float(l0)*_n/view_depth; 
    ll=B0.a; for (i=0;i<lights;i++)    // compute normal shaded combined light sources into ll 
    ll+=dot(normalize(p1),light_dir[0]); 
    for (p=p1,i=0;i<n;p-=dp,i++)    // p1->p0 path throu atmosphere from ground 
     { 
//  _view_depth(p,normalize(p),planet_R); // too slow... view_depth_l0=depth above atmosphere top [m] 
//  h=exp(view_depth_l0/planet_h)/2.78; 

     b=normalize(p)*p_r;      // much much faster 
     h=length(p-b); 
     h=exp(h/planet_h)/2.78; 

     b=B0.rgb*h*dl; 
     c.r*=1.0-b.r; 
     c.g*=1.0-b.g; 
     c.b*=1.0-b.b; 
     c.rgb+=b*ll; 
     } 
    if (c.r<0.0) c.r=0.0; 
    if (c.g<0.0) c.g=0.0; 
    if (c.b<0.0) c.b=0.0; 
    h=0.0; 
    if (h<c.r) h=c.r; 
    if (h<c.g) h=c.g; 
    if (h<c.b) h=c.b; 
    if (h>1.0) 
     { 
     h=1.0/h; 
     c.r*=h; 
     c.g*=h; 
     c.b*=h; 
     } 
    return c; 
    } 

void main(void) 
    { 
    gl_FragColor.rgba=atmosphere(); 
    } 

[valores uniformes]

// Earth 
re=6378141.2   // equatoreal radius r.x,r.y 
rp=6356754.79506139 // polar radius r.z 
planet_h=60000  // atmosphere thickness R(r.x+planet_h,r.y+planet_h,r.z+planet_h) 
view_depth=250000 // max view distance before 100% scattering occur 
B0.r=0.1981   // 100% scattered atmosphere color 
B0.g=0.4656 
B0.b=0.8625 
B0.a=0.75   // overglow (sky is lighter before Sun actually rise) it is added to light dot product 

// Mars 
re=3397000 
rp=3374919.5 
ha=30000 
view_depth=300000 
B0.r=0.4314 
B0.g=0.3216 
B0.b=0.196 
B0.a=0.5 

para obtener más información (y más nuevo imágenes) Ver también relacionados:

+0

¿podría proporcionar un enlace a una demostración? – user2070775

+1

aquí está: http://ulozto.sk/xewsQkcE/atmosphericscattering-rar solo extraer ir a la carpeta bin leer el txt (funciones de teclas) y ejecutar el exe. tenga cuidado, simula la física real + sistema ctrl de la nave, así que configure la velocidad y espere hasta que la nave coincida ... y no se olvide de reducir la velocidad antes de entrar a la atmósfera para no sobrevolar rápidamente (no hay choques) o prueba de colisión ...) (la burbuja azul en el radar representa la distancia de parada si estás cerca de ella empieza a disminuir). El sol gira rápidamente alrededor de la Tierra para realizar pruebas diurnas/nocturnas, por lo que no necesitas volar o esperar ... – Spektre

+0

Por cierto, tuvimos la idea de mejorar esto recientemente (para ser mucho más realista) mediante un pequeño mapa de atmósfera esférica. lo que permitiría algunas cosas adicionales que necesito bud no tuvo tiempo para implementarlo y probarlo y no habrá al menos en un año :(tiene proyectos pagos demasiado complejos antes de vez en cuando ... – Spektre

Cuestiones relacionadas