2012-04-18 22 views
16

Trong vài ngày qua, tôi đã cố gắng để có được kết cấu Three.js hoạt động. Vấn đề tôi gặp phải là trình duyệt của tôi đang chặn kết cấu tải, được giải quyết bằng cách thực hiện theo các hướng dẫn here.Tôi làm cách nào để hiển thị 'bầu không khí' trên kết xuất Earth trong Three.js?

Dù sao, tôi đang thực hiện trò chơi điều hướng không gian cho một trong các lớp học của tôi thể hiện tàu vũ trụ điều hướng trong không gian. Vì vậy, tôi đang vẽ một loạt các hành tinh, trái đất là một trong số chúng. Tôi đã bao gồm một hình ảnh về dựng hình Trái đất của tôi bên dưới. Nó có vẻ ổn, nhưng những gì tôi đang cố gắng làm là làm cho nó trông thực tế hơn bằng cách thêm một 'bầu không khí' trên khắp hành tinh.

Tôi đã xem xét xung quanh, và tôi đã tìm thấy một số thực sự neat looking creations đối phó với ánh sáng, nhưng tôi không nghĩ rằng chúng áp dụng cho tình hình của tôi, thật không may.

Và đây là đoạn code mà thêm đất để cảnh của tôi (đó là một phiên bản sửa đổi của mã tôi nhận được từ một hướng dẫn 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

Trả lời

13

gì chính xác Bạn đang tìm kiếm Trong bầu không khí của bạn? Nó có thể đơn giản như vẽ một quả cầu trong suốt lớn hơn một chút trên đỉnh địa cầu của bạn, hoặc nó có thể rất rất phức tạp, thực sự khúc xạ ánh sáng đi vào nó. (Gần giống như tán xạ dưới bề mặt được sử dụng trong hiển thị trên da).

Tôi chưa bao giờ thử một hiệu ứng như vậy, nhưng một số Googling nhanh chóng hiển thị một số kết quả đầy hứa hẹn. Ví dụ, tôi nghĩ rằng this effect trông khá đẹp, và tác giả thậm chí còn theo dõi nó với hơn detailed variant sau này. Nếu bạn quan tâm đến một sự cố kỹ thuật hơn, chi tiết this technique sẽ chi tiết rất nhiều nền tảng lý thuyết. Tôi chắc chắn có nhiều hơn, bạn chỉ cần có để poke xung quanh một chút. (Sự thật là tôi không biết đây là một chủ đề dựng hình phổ biến!)

Nếu bạn gặp khó khăn với một số khía cạnh của những kỹ thuật đó đặc biệt áp dụng cho Three.js, đừng ngần ngại hỏi!

[UPDATE]

Ah, xin lỗi. Vâng, đó là một chút nhiều để ném bạn vào mà không có kiến ​​thức shader trước.

Mã trên liên kết thứ hai thực sự là tệp DirectX FX, mã lõi là HLSL, vì vậy nó không phải là thứ đơn giản chỉ cần cắm vào WebGL, nhưng hai định dạng đổ bóng tương tự nhau đến mức thường không phải là vấn đề cần dịch chúng. Nếu bạn thực sự biết shaders, đó là. Tôi sẽ khuyên bạn nên đọc về cách shaders làm việc trước khi cố gắng đi sâu vào một hiệu ứng phức tạp như thế này.

Tôi bắt đầu với một cái gì đó đơn giản như this tutorial, mà chỉ đơn giản là nói về cách để có được một trình đổ bóng cơ bản chạy với Three.js. Một khi bạn biết cách để có được một shader làm việc với các hướng dẫn Three.js và GLSL (như this one) sẽ cung cấp cho bạn những kiến ​​thức cơ bản về cách một công cụ đổ bóng hoạt động và những gì bạn có thể làm với nó.

Tôi biết rằng có vẻ như rất nhiều công việc ở phía trước, nhưng nếu bạn muốn thực hiện các hiệu ứng hình ảnh tiên tiến trong WebGL (và điều này chắc chắn phù hợp với các hiệu ứng nâng cao), bạn hoàn toàn phải hiểu shader!

Sau đó, một lần nữa, nếu bạn đang tìm kiếm bản sửa lỗi nhanh, luôn có tùy chọn hình cầu trong suốt mà tôi đang nói đến.:)

+0

Wow, những ví dụ là thực sự ấn tượng! Tuy nhiên, bạn nên biết rằng tôi thực sự mới với công cụ này. Trong liên kết thứ hai bạn đăng, có vẻ như có một số mã C-looking. Đây có phải là cách tôi sử dụng bóng đổ không khí đó không? Đây có phải là những gì họ gọi là 'glsl'? Làm thế nào để thực hiện điều này trong Three.js? Xin lỗi vì sự thiếu hiểu biết nghiêm trọng của tôi về chủ đề này. – Hassan

+0

Cảm ơn bạn đã cập nhật nhanh. Tôi nghĩ rằng tôi sẽ tiếp tục và cố gắng tìm hiểu về shaders, vì chúng có vẻ quan trọng. Tuy nhiên, kể từ khi tôi phải chứng minh điều này trong khoảng một tuần, tôi không nghĩ rằng tôi sẽ có thể tìm hiểu tất cả trong khung thời gian đó. Nhưng tôi sẽ cố gắng, và như bạn nói, tôi luôn có thể tạo ra một quả cầu trong suốt. – Hassan

22

Cũng là một câu hỏi cũ và đã được trả lời nhưng tôi muốn thêm giải pháp của tôi để bắt đầu xem xét trên mạng. Có plaing cùng tán xạ khí quyển và GLSL trong một thời gian dài và đến phiên bản Giản VEEERRRYYY này (nếu hoạt hình dừng trang làm mới hoặc xem GIF trong một cái gì đó hơn decend):

[example[1]

  1. hành tinh là và ellipsoid (trung tâm x, y, z và bán kính rx, ry, rz)
  2. bầu không khí cũng là elip (giống nhau nhưng lớn hơn bởi chiều cao không khí)
  3. tất cả kết xuất được thực hiện bình thường nhưng trên đầu trang được thêm 1 lần cho hành tinh quan sát gần
  4. mà vượt qua là quad đơn bao trùm toàn bộ màn hình
  5. bên trong đoạn nó tính toán giao điểm của tia pixel với những 2 ellipsoids
  6. mất phần nhìn thấy được (không phải phía sau, không phải sau khi mặt đất)
  7. tính toán chiều dài ray bầu không khí bên trong
  8. bóp méo màu gốc như chức năng của r, g, b params nhân theo tỷ lệ chiều dài ray (cái gì đó như tích hợp dọc theo đường dẫn)
    • một số màu sắc được thực hiện một số trao ...
    • rất ảnh hưởng đến màu sắc để có thể của nó để mô phỏng bầu khí quyển khác nhau bằng cách chỉ vài thuộc tính
  9. nó hoạt động tốt bên trong và cũng bên ngoài bầu khí quyển (từ khoảng cách)
  10. có thể thêm sao gần như là nguồn ánh sáng (tôi sử dụng tối đa 3 sao hệ thống)

kết quả là nhìn thấy hình ảnh tuyệt đẹp dưới đây:

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

Xin lỗi nhưng một nguồn thực sự cũ của tôi ... có lẽ nên được chuyển đổi vào hồ sơ của lõi

[ Chỉnh sửa 1] xin lỗi quên thêm các hằng số phân tán đầu vào của tôi cho bầu khí quyển Trái đất

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/09/03 mã nguồn mới

tôi đã có một số thời gian gần đây để thực hiện zoom vào công cụ mỏ và đã tìm ra rằng mã nguồn gốc không phải là rất chính xác từ khoảng cách trên 0,002 AU. Nếu không có Zoom nó chỉ là một vài điểm ảnh để không có gì được nhìn thấy, nhưng với zoom tất cả các thay đổi vì vậy tôi đã cố gắng để cải thiện độ chính xác nhiều nhất có thể.

Sau một vài tinh chỉnh tôi càng làm cho nó được sử dụng lên đến 25,0 AU và với các đồ tạo tác nội suy lên đến 50,0-100,0 AU. Đó là giới hạn cho HW hiện tại vì tôi không thể vượt qua phi flat fp64 để nội suy từ đỉnh đến đoạn. Một cách có thể là di chuyển hệ tọa độ biến đổi thành mảnh nhưng chưa thử nó. Dưới đây là một số thay đổi:

  • nguồn mới sử dụng 64 bit nổi
  • và thêm uniform int lights đó là đếm đèn đã qua sử dụng
  • cũng có một số thay đổi trong ý nghĩa B0 (họ bước sóng không còn thường xuyên phụ thuộc nhưng màu sắc thay vì) vì vậy bạn cần phải thay đổi giá trị thống nhất điền vào mã CPU một chút.
  • một số cải tiến hiệu suất đã được bổ sung

[đỉnh]

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

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

[giá trị thống nhất]

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

Để biết thêm thông (và mới hơn hình ảnh) cũng thấy liên quan:

+0

bạn có thể cung cấp liên kết đến bản trình diễn không? – user2070775

+1

ở đây bạn là: http://ulozto.sk/xewsQkcE/atmosphericscattering-rar chỉ cần giải nén vào thư mục bin đọc txt (các phím chức năng) và chạy exe. hãy cẩn thận nó mô phỏng hệ thống vật lý + ctrl thực của tàu để đặt tốc độ và đợi cho đến khi con tàu khớp với nó ... và đừng quên giảm tốc độ trước khi bước vào bầu khí quyển để bạn không bay qua nhanh (không có tai nạn hoặc va chạm thử nghiệm ...) (bong bóng màu xanh trên radar đại diện cho khoảng cách dừng nếu bạn gần với nó bắt đầu chậm lại) Sun đang quay vòng nhanh chóng quanh Trái Đất để kiểm tra Ngày/Đêm, do đó bạn không cần phải bay vòng hoặc chờ ... – Spektre

+0

btw đã có một ý tưởng để cải thiện điều này gần đây (thực tế hơn) bằng bản đồ bầu không khí hình cầu nhỏ. mà sẽ cho phép một số công cụ bổ sung tôi cần nụ không có thời gian để thực hiện và kiểm tra nó và sẽ không có trong ít nhất một năm: (có quá phức tạp trả dự án trước và sau đó ... – Spektre

Các vấn đề liên quan