2012-04-18 207 views
16

在過去的幾天裏,我一直在試圖讓Three.js紋理工作。我遇到的問題是我的瀏覽器阻止加載紋理,這是通過按照指令here解決的。無論如何,我正在爲我的一個課程製作太空導航遊戲,演示如何通過太空導航航天器。所以,我渲染了一堆行星,地球就是其中之一。我在下面添加了一張我的地球圖片。它看起來沒問題,但我想要做的是通過在地球周圍增加一種「氣氛」讓它看起來更加真實。如何渲染Three.js中的地球渲染的「氛圍」?

我環顧四周,發現了一些處理髮光的真正neat looking creations,但不幸的是,我認爲它們不適用於我的情況。

而這裏的,增加了地球到我的場景中的代碼(這是代碼的修改版本,我從一個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

回答

13

到底在尋找什麼在你的氛圍中?它可以像在地球上方渲染另一個稍大的透明球體那樣簡單,或者它可能非常複雜,實際上折射入射它的光線。 (幾乎類似於皮膚渲染中使用的子表面散射)。

我從來沒有嘗試過這樣的效果,但一些快速的谷歌搜索顯示出一些有希望的結果。例如,我認爲this effect看起來相當不錯,作者以後甚至會跟進更多的detailed variant。如果你對更多的技術細節感興趣,可以詳細瞭解大量的理論背景。我相信還有更多的東西,你只需要捅一下。如果您在使用的具體方法適用於three.js所不要猶豫,問這些技術的一些方面的麻煩(說實話我不知道這是這樣一個熱門話題渲染!)

[更新]

對不起。是的,如果沒有以前的着色器知識,這會讓你陷入一種困境。

第二個鏈接上的代碼實際上是一個DirectX FX文件,核心代碼是HLSL,所以它不是簡單地插入WebGL的東西,但兩種着色器格式足夠相似,以至於通常不需要轉換他們。如果你真的瞭解着色器,那就是。我會建議閱讀着色器的工作方式,然後再試圖深入探究這種複雜的效果。

我會先從一些簡單的像this tutorial,它只是關於如何獲得與three.js所運行的基本着色會談。一旦你知道如何讓着色器與Three.js和GLSL教程(如this one)一起工作,它將爲您提供着色器如何工作以及如何使用它的基礎知識。

我知道,看起來好像有很多工作要做,但如果你想在WebGL中做高級視覺效果(這當然符合高級效果的話),你絕對需要瞭解着色器!

話又說回來,如果你正在尋找一個快速解決總是有我在談論的是透明球體選項。:)

+0

哇,這些例子都讓人印象深刻!但是,你應該知道我對這些東西真的很陌生。在你發佈的第二個鏈接中,似乎有一些C代碼。這是我如何使用這個氛圍着色器?這就是他們所說的'glsl'嗎?我如何在Three.js中實現這個?對不起,我對這個問題非常無知。 – Hassan 2012-04-18 16:59:34

+0

感謝您的快速更新。我想我會繼續努力學習着色器,因爲它們看起來很重要。但是,由於我必須在一週內展示這件事,所以我認爲在那段時間內我無法全部瞭解。但我會嘗試,然後按照你的說法,我總是可以做出透明的球體。 – Hassan 2012-04-18 17:28:05

22

那麼一個老的和已經回答的問題,但我想增加我的解決方案,爲開始考慮那裏。沿着大氣散射和GLSL普蘭很長一段時間來這VEEERRRYYY簡化版本(如果動畫停止刷新頁面或查看GIF在更多的東西decend):

[example[1]

  1. 行星和橢球體(中心x,y,z和半徑rx,ry,rz)
  2. 大氣也是橢圓形的(相同但是大氣的高度相同)
  3. 所有的渲染都是正常完成的,但是最後增加了1遍爲近觀察星球
  4. 即通過是單個四覆蓋整個屏幕
  5. 內部片段它計算像素光線的交叉點與這些2個橢圓
  6. 採取的可見部分(未後面,接地後不)
  7. 計算射線長度內的氣氛
  8. 歪曲原來的顏色爲r的函數,G,b經縮放PARAMS由射線長度(類似於沿路徑積分)
    • 一些顏色被採取了一些給定...
    • 極大地影響了顏色,所以它可以通過只是幾個屬性來模擬不同的氣氛
  9. 這裏面也大氣層外(從遠處)
  10. 可以添加收星作爲光源(我用的最多3星運行良好

    enter image description here enter image description here enter image description here :下面系統)

結果是驚人的看到的圖像 enter image description here

頂點:

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

片段:

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

很抱歉,但我...應該可能轉化爲核心配置文件

[它是一個很老的源編輯1]抱歉忘記添加我的地球大氣輸入散射常數

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年3月9日新的源代碼

我有一段時間,最近以實現變焦礦發動機和想通了,原來的源代碼是不是從上述0.002 AU距離非常精確。沒有縮放它只是幾個像素,所以沒有看到任何東西,但縮放的所有變化,所以我儘可能提高準確性。

一些調整,我得到它是使用,最高25.0 AU和與插值文物達50.0-100.0 AU後的相關問題。這對於當前的硬件是有限的,因爲我無法將非flat fp64傳遞給從頂點到片段的內插器。一種方法可能是將座標系轉換爲片段,但還沒有嘗試過。這裏有一些改變:

  • 新源使用64位漂浮
  • 並添加uniform int lights這是應用於燈
  • 也有些變化,B0意義的計數(它們不再依賴於波長的恆定但顏色代替),所以你需要改變統一的值稍微填寫CPU代碼。
  • 一些性能改進的溶液中加入

[頂點]

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

[片段]

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

[均勻值]

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

有關詳細信息(和新圖像)也見相關:

+0

你能否提供一個演示鏈接? – user2070775 2014-04-20 23:45:41

+1

在這裏:http://ulozto.sk/xewsQkcE/atmosphericscattering-rar只是解壓縮到bin文件夾讀取txt(鍵功能)並運行exe。要小心它模擬船的真實物理+ ctrl系統,所以設置速度,並等待,直到船匹配它......並且不要忘記在進入大氣層之前放慢速度,這樣你就不會快速飛過(沒有碰撞或碰撞測試...)(雷達上的藍色氣泡代表停止距離,如果你靠近它開始減速)太陽在地球周圍快速旋轉以進行日/夜測試,因此您不需要四處飛行或等待... – Spektre 2014-04-21 07:32:38

+0

順便說一句,有一個想法,最近通過小球形大氣地圖來改進這個(更加現實)。這將允許一些額外的東西,我需要芽沒有時間來實施和測試它,至少有一年將沒有:(有太複雜的支付項目之前,現在然後... – Spektre 2014-04-21 07:39:13