2012-02-05 15 views
7

Tôi nhận ra đây là câu hỏi tập trung vào toán học nhưng ... nếu bạn nhìn vào trang web này (và có cạc đồ họa tốt) http://mrdoob.github.com/three.js/examples/webgl_shader.htmlBất cứ ai có thể giải thích trình đổ bóng đoạn GLSL này đang làm gì không?

Nếu bạn nhìn vào nguồn, bạn sẽ thấy một bộ đổ bóng tìm kiếm đáng sợ .

Tôi không tìm kiếm giải thích chi tiết, nhưng ý tưởng về loại điều đang diễn ra hoặc nguồn thông tin về những gì chính xác đang diễn ra ở đây .. Tôi không theo hướng dẫn về GLSL, nhưng thông tin về toán học. Tôi nhận thấy điều này có thể phù hợp hơn với trang web Math StackExchange nhưng tôi nghĩ rằng tôi sẽ thử ở đây trước tiên ...

<script id="fragmentShader" type="x-shader/x-fragment"> 

      uniform vec2 resolution; 
      uniform float time; 

      void main() { 

       vec2 p = -1.0 + 2.0 * gl_FragCoord.xy/resolution.xy; 
       float a = time*40.0; 
       float d,e,f,g=1.0/40.0,h,i,r,q; 
       e=400.0*(p.x*0.5+0.5); 
       f=400.0*(p.y*0.5+0.5); 
       i=200.0+sin(e*g+a/150.0)*20.0; 
       d=200.0+cos(f*g/2.0)*18.0+cos(e*g)*7.0; 
       r=sqrt(pow(i-e,2.0)+pow(d-f,2.0)); 
       q=f/r; 
       e=(r*cos(q))-a/2.0;f=(r*sin(q))-a/2.0; 
       d=sin(e*g)*176.0+sin(e*g)*164.0+r; 
       h=((f+d)+a/2.0)*g; 
       i=cos(h+r*p.x/1.3)*(e+e+a)+cos(q*g*6.0)*(r+h/3.0); 
       h=sin(f*g)*144.0-sin(e*g)*212.0*p.x; 
       h=(h+(f-e)*q+sin(r-(a+h)/7.0)*10.0+i/4.0)*g; 
       i+=cos(h*2.3*sin(a/350.0-q))*184.0*sin(q-(r*4.3+a/12.0)*g)+tan(r*g+h)*184.0*cos(r*g+h); 
       i=mod(i/5.6,256.0)/64.0; 
       if(i<0.0) i+=4.0; 
       if(i>=2.0) i=4.0-i; 
       d=r/350.0; 
       d+=sin(d*d*8.0)*0.52; 
       f=(sin(a*g)+1.0)/2.0; 
       gl_FragColor=vec4(vec3(f*i/1.6,i/2.0+d/13.0,i)*d*p.x+vec3(i/1.3+d/8.0,i/2.0+d/18.0,i)*d*(1.0-p.x),1.0); 

      } 

     </script> 
+1

Có http://glsl.heroku.com/e được viết bởi mr.doob. Đây là mã ở trên được dán trong http://glsl.heroku.com/e#1579.0 – gman

Trả lời

20

Monjori là từ cảnh giới thiệu.

Câu trả lời đơn giản là sử dụng công thức để tạo mẫu. WebGL sẽ gọi hàm này một lần cho mỗi pixel trên màn hình. Những điều duy nhất sẽ thay đổi là thời gian và gl_FragCoord là vị trí của pixel được vẽ.

Hãy phá vỡ nó xuống một chút

// this is the resolution of the window 
    uniform vec2 resolution; 

    // this is a count in seconds. 
    uniform float time; 

    void main() { 
     // gl_FragCoord is the position of the pixel being drawn 
     // so this code makes p a value that goes from -1 to +1 
     // x and y 
     vec2 p = -1.0 + 2.0 * gl_FragCoord.xy/resolution.xy; 

     // a = the time speed up by 40 
     float a = time*40.0; 

     // declare a bunch of variables. 
     float d,e,f,g=1.0/40.0,h,i,r,q; 

     // e goes from 0 to 400 across the screen 
     e=400.0*(p.x*0.5+0.5); 

     // f goes from 0 to 400 down the screen 
     f=400.0*(p.y*0.5+0.5); 

     // i goes from 200 + or - 20 based 
     // on the sin of e * 1/40th + the slowed down time/150 
     // or in other words slow down even more. 
     // e * 1/40 means e goes from 0 to 1 
     i=200.0+sin(e*g+a/150.0)*20.0; 

     // d is 200 + or - 18.0 + or - 7 
     // the first +/- is cos of 0.0 to 0.5 down the screen 
     // the second +/i is cos of 0.0 to 1.0 across the screen 
     d=200.0+cos(f*g/2.0)*18.0+cos(e*g)*7.0; 

     // I'm stopping here. You can probably figure out the rest 
     // see answer 
     r=sqrt(pow(i-e,2.0)+pow(d-f,2.0)); 
     q=f/r; 
     e=(r*cos(q))-a/2.0;f=(r*sin(q))-a/2.0; 
     d=sin(e*g)*176.0+sin(e*g)*164.0+r; 
     h=((f+d)+a/2.0)*g; 
     i=cos(h+r*p.x/1.3)*(e+e+a)+cos(q*g*6.0)*(r+h/3.0); 
     h=sin(f*g)*144.0-sin(e*g)*212.0*p.x; 
     h=(h+(f-e)*q+sin(r-(a+h)/7.0)*10.0+i/4.0)*g; 
     i+=cos(h*2.3*sin(a/350.0-q))*184.0*sin(q-(r*4.3+a/12.0)*g)+tan(r*g+h)*184.0*cos(r*g+h); 
     i=mod(i/5.6,256.0)/64.0; 
     if(i<0.0) i+=4.0; 
     if(i>=2.0) i=4.0-i; 
     d=r/350.0; 
     d+=sin(d*d*8.0)*0.52; 
     f=(sin(a*g)+1.0)/2.0; 
     gl_FragColor=vec4(vec3(f*i/1.6,i/2.0+d/13.0,i)*d*p.x+vec3(i/1.3+d/8.0,i/2.0+d/18.0,i)*d*(1.0-p.x),1.0); 
} 

Một trong những điều đó là tốt để thử để xem những gì đang xảy ra là để chèn thoát sớm trong shader. Trước hết bạn sẽ nhìn thấy shader đây

http://glsl.heroku.com/e#1579.0

hoặc

https://www.shadertoy.com/view/lsfyRS

Nếu chúng tôi đi đến dòng 11

 e=400.0*(p.x*0.5+0.5); 

và chèn ngay sau đó một cái gì đó giống như

này
 e=400.0*(p.x*0.5+0.5); 
     gl_FragColor = vec4(e/400.0, 0, 0, 1); 
     return; 

Chừng nào chúng ta chuyển đổi các giá trị cho một cái gì đó 0-1 chúng ta có thể xem kết quả

ví dụ đi xuống đến dòng 14

d=200.0+cos(f*g/2.0)*18.0+cos(e*g)*7.0; 

Vì chúng ta biết nó đi từ 200 +/- 18 +/- 7 đó là 175 + 225 để chuyển đổi thành 0 thành 1 với

sẽ cho bạn biết ý tưởng của nó.

Tôi chắc chắn bạn có thể giải quyết phần còn lại.

+2

wow điều này thật tuyệt vời ... cảm ơn câu trả lời này !! Tôi đang điều chỉnh shader này bằng cách sử dụng các vars thời gian và p.x hoặc p.y để điều khiển hình dạng và màu sắc. Sẽ cho mười +1 nếu tôi có thể – Alex