2012-04-18 3 views
16

In den letzten paar Tagen habe ich versucht, Three.js Texturierung zur Arbeit zu bringen. Das Problem, das ich hatte, ist, dass mein Browser Texturen vom Laden blockierte, was durch Befolgen der Anweisungen here gelöst wurde.Wie kann ich eine 'Atmosphäre' über eine Darstellung der Erde in Three.js wiedergeben?

Wie auch immer, ich mache ein Space-Navigator-Spiel für eine meiner Klassen, die das Navigieren von Raumfahrzeugen durch den Weltraum demonstriert. Ich rendere also eine Menge Planeten, von denen die Erde eine davon ist. Ich habe unten ein Bild meiner Erdwiedergabe eingefügt. Es sieht okay aus, aber ich versuche es realistischer zu machen, indem ich eine "Atmosphäre" um den Planeten herum hinzufüge.

Ich habe mich umgesehen, und ich habe einige wirklich neat looking creations gefunden, die mit Glühen beschäftigen, aber ich denke nicht, dass sie auf meine Situation leider zutreffen.

Und hier ist der Code, der die Erde in meine Szene fügt hinzu (es ist eine modifizierte Version von Code, den ich von einem Three.js Tutorial bekam):

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

Antwort

13

Was genau suchen Sie In deiner Atmosphäre? Es könnte so einfach wie das Rendern einer anderen etwas größeren transparenten Kugel über der Spitze Ihres Globus sein, oder es könnte sehr komplex sein, tatsächlich brechendes Licht, das es betritt. (Fast wie Subsurface Streuung im Skin Rendering).

Ich habe noch nie einen solchen Effekt selbst probiert, aber ein paar schnelle Googles zeigen vielversprechende Ergebnisse. Zum Beispiel denke ich, this effect sieht ziemlich nett aus, und der Autor folgte sogar später mit einem mehr detailed variant. Wenn Sie an einer eher technischen Aufschlüsselung interessiert sind, gibt this technique einen großen Teil des theoretischen Hintergrunds an. Ich bin mir sicher, da ist noch mehr, du musst nur ein bisschen herumstochern. (Um ehrlich zu sein, wusste ich nicht, dass dies ein so populäres Rendering-Thema war!)

Wenn Sie Probleme mit einem bestimmten Aspekt dieser Techniken haben, wie es für Three.js gilt, zögern Sie nicht zu fragen!

[UPDATE]

Ah, sorry. Ja, das ist ein bisschen viel, in das man ohne vorheriges Shader-Wissen reinkommt. Der Code auf dem zweiten Link ist eigentlich eine DirectX-FX-Datei, der Hauptcode ist HLSL, also ist es nicht etwas, das einfach in WebGL einfügt, aber die beiden Shader-Formate sind ähnlich genug, dass es normalerweise kein Problem ist, es zu übersetzen Sie. Wenn du tatsächlich Shader kennst. Ich würde empfehlen, zu lesen, wie Shader funktionieren, bevor Sie versuchen, in einen komplizierten Effekt wie diesen einzutauchen.

Ich würde mit etwas einfach wie this tutorial beginnen, die einfach darüber spricht, wie man einen grundlegenden Shader mit Three.js läuft. Sobald Sie wissen, wie Sie einen Shader erhalten, der mit Three.js- und GLSL-Tutorials arbeitet (wie this one), erhalten Sie die Grundlagen, wie ein Shader funktioniert und was Sie damit machen können.

Ich weiß, dass wie viel Arbeit scheint vorne, aber wenn Sie erweiterte visuelle Effekte in WebGL machen wollen (und dies sicherlich passt die Rechnung von fortgeschrittenen Effekte) Sie absolut müssen verstehen Shadern!

Wenn Sie auf der Suche nach einer schnellen Lösung sind, gibt es immer wieder die transparente Sphäre, von der ich gesprochen habe.:)

+0

Wow, diese Beispiele sind wirklich beeindruckend: Bilder) siehe auch im Zusammenhang! Sie sollten jedoch wissen, dass ich wirklich neu in diesem Zeug bin. In dem zweiten Link, den Sie gepostet haben, scheint es einen C-Code zu geben. Würde ich diesen atmosphärischen Shader benutzen? Ist das, was sie "Glsl" nennen? Wie implementiere ich das in Three.js? Entschuldigung für meine schwere Ignoranz zu diesem Thema. – Hassan

+0

Danke für die schnellen Updates. Ich denke, ich werde weitermachen und versuchen, etwas über Shaders zu lernen, da sie wichtig erscheinen. Aber da ich dieses Ding in ungefähr einer Woche demonstrieren muss, glaube ich nicht, dass ich in der Lage sein werde, alles in diesem Zeitraum zu lernen. Aber ich werde es versuchen, und dann, wie du sagst, kann ich immer eine durchsichtige Sphäre machen. – Hassan

22

Nun eine alte und bereits beantwortete Frage, aber ich wollte meine Lösung für Anfänger Überlegungen da draußen hinzufügen. Haben entlang Atmosphärische Streuung und GLSL für eine lange Zeit plaing und kommen auf diese VEEERRRYYY Vereinfachte Version (wenn Animation refresh Seite stoppt oder verfolgen Sie die GIF in etwas mehr hilfstücke tüchtig):

[example[1]

  1. Planeten und Ellipsoid (Mitte x, y, z und Radien rx, ry, rz)
  2. Atmosphäre ist auch Ellipsod (die gleiche, aber größer durch die Höhe der Atmosphäre)
  3. alle Render erfolgt normal, aber darüber hinaus ist 1 Pass hinzugefügt für nahen Beobachterplaneten
  4. die vergehen ist Single Quad abdeckt gesamten Bildschirm
  5. innerhalb Fragments es den Schnittpunkt des Pixels ray mit diesen 2 Ellipsoide berechnet
  6. den sichtbaren Teil nehmen (nicht hinter, nicht nach Masse)
  7. die Innenatmosphäre Strahllänge berechnen,
  8. verzerren Originalfarbe als Funktion von r, g, b skalierten params durch Strahllänge (so etwas wie auf dem Weg der Integration)
    • etwas Farbe einige gegeben genommen wird ...
    • stark beeinflusst Farbe so seine möglichen unterschiedlichen Atmosphären durch nur wenige Attribute
  9. es innerhalb und auch außerhalb der Atmosphäre arbeiten gut zu simulieren (aus der Ferne)
  10. schließen Sterne als Lichtquelle hinzufügen kann (i verwenden max 3 Sterne System)

das Ergebnis ist atemberaubend siehe Bilder unten:

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; 
    } 

Fragment:

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(); 
    } 

Sorry, aber es ist eine wirklich alte Quelle meiner ... sollte wohl

zum Kernprofil umgewandelt werden [ Edit 1] Tut mir leid vergessen, meine Eingabe Streuung Konstanten für die Erdatmosphäre hinzuzufügen

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] 2014.03.09 neuer Quellcode

ich einige Zeit hatte vor kurzen Zoom Mine Motor zu implementieren und herausgefunden, dass Original-Quellcode von Abstand über 0.002 AU nicht sehr präzise ist. Ohne Zoom sind es nur ein paar Pixel, so dass nichts gesehen wird, aber mit dem Zoom alle Änderungen, so dass ich versuchte, die Genauigkeit so gut wie möglich zu verbessern.

Nach einigen zwickt ich es verwendbar bis zu 25,0 AU zu erhalten und mit Interpolationsartefakte bis zu 50,0 bis 100,0 AU. Das ist die Grenze für die aktuelle HW, weil ich nicht flat fp64 Interpolatoren von Ecke zu Fragment übergeben kann. Eine Möglichkeit wäre, die Transformation des Koordinatensystems in ein Fragment zu verschieben, aber noch nicht ausprobiert zu haben. Hier sind einige Änderungen:

  • neue Quelle verwendet 64 Bit schwimmt
  • und fügen uniform int lights, welche die Anzahl der verwendeten Leuchten ist
  • auch einige Änderungen in B0 Bedeutung (sie sind nicht mehr wellenlängenabhängig konstant, sondern Farbe statt) Sie müssen also den Wert für den einheitlichen Wert ändern, indem Sie den CPU-Code leicht eingeben.
  • einige Leistungsverbesserungen wurde

[Vertex]

/* 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; 
    } 

[Fragment] hinzugefügt

#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(); 
    } 

[einheitliche Werte]

// 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 

Für weitere Informationen (und neuer

+0

könnten Sie einen Link zu einer Demo bereitstellen? – user2070775

+1

hier sind Sie: http://ulozto.sk/xewsQkcE/atmospherecattering-rar nur extrahieren gehen Sie zum bin-Ordner Lesen Sie den TXT (Schlüsselfunktionen) und führen Sie die exe. Sei vorsichtig, es simuliert die reale Physik und das System des Schiffes, also setze die Geschwindigkeit und warte, bis das Schiff dazu passt ... und vergesse nicht, vor dem Betreten der Atmosphäre langsamer zu fahren, damit du nicht schnell überfliegt (es gibt keinen Absturz) oder Kollisionstest ...) (blaue Luftblase auf Radar stellt Halteabstand dar, wenn Sie nah an ihm sind, fangen an zu verlangsamen) Sonne dreht sich schnell um Erde für Tag/Nacht, die Sie nicht herumfliegen oder warten müssen ... – Spektre

+0

BTW hatte eine Idee, dies in letzter Zeit durch eine sphärische Atmosphärenkarte zu verbessern. das würde einige zusätzliche Sachen erlauben, die ich brauche, hatte keine Zeit, es zu implementieren und zu testen, und es wird in mindestens einem Jahr nicht geben :(haben zu komplexe bezahlte Projekte vorher und dann ... – Spektre

Verwandte Themen