WebGL Shader

shdertoy上的动态黄昏图

看效果在这里插入图片描述

外加两张shader里用到的图片在这里插入图片描述
请添加图片描述

下面是shader代码,在webgl可以运行,在three也可以

<script id="vertexshader" type="x-shader/x-vertex">
    attribute vec3 A_position3;
    attribute vec2 A_uv;
    uniform mat4 mvp;

    varying vec2 out_uv;

    void main(void){

      gl_Position = mvp * vec4(A_position3,1.0);

      out_uv = A_uv;
    }
  </script>
  <script id="fragmentshader" type="x-shader/x-vertex">
    precision highp float;
    precision highp int;
    varying vec2 out_uv;
    uniform vec2 iResolution;
    uniform float iTime;
    uniform sampler2D iChannel0;
    uniform sampler2D iChannel1;

    const vec3 sunColor = vec3(1.5,.9,.7);
    const vec3 lightColor = vec3(1.,.8,.7);
    const vec3 darkColor = vec3(.2,.2,.3);
    const vec3 baseSkyColor = vec3(.6,.7,.8);
    const vec3 seaColor = vec3(.1,.3,.5);
    const vec3 seaLight = vec3(.1,.45,.55);
    const vec2 iMouse = vec2(60.0);
    //---------------------------------------

    vec3 gamma( vec3 col, float g){
        return pow(col,vec3(g));
    }
        
        
    // clouds layered noise
    float noiseLayer(vec2 uv){    
        float t = (iTime+iMouse.x)/5.;
        uv.y -= t/60.; // clouds pass by
        float e = 0.;
        for(float j=1.; j<9.; j++){
            // shift each layer in different directions
            float timeOffset = t*mod(j,2.989)*.02 - t*.015;
            e += 1.-texture2D(iChannel0, uv * (j*1.789) + j*159.45 + timeOffset).r / j ;
        }
        e /= 3.5;
        return e;
    }

    // waves layered noise
    float waterHeight(vec2 uv){
        float t = (iTime+iMouse.x);
        float e = 0.;
        for(float j=1.; j<6.; j++){
            // shift each layer in different directions
            float timeOffset = t*mod(j,.789)*.1 - t*.05;
            e += texture2D(iChannel1, uv * (j*1.789) + j*159.45 + timeOffset).r / j ;
        }
        e /= 6.;
        return e;
    }

    vec3 waterNormals(vec2 uv){
        uv.x *= .25;
        float eps = 0.008;    
        vec3 n=vec3( waterHeight(uv) - waterHeight(uv+vec2(eps,0.)),
                    1.,
                    waterHeight(uv) - waterHeight(uv+vec2(0.,eps)));
      return normalize(n);
    }	


    vec3 drawSky( vec2 uv, vec2 uvInit){ 
            
      float clouds = noiseLayer(uv);
        
        // clouds normals
        float eps = 0.1;
        vec3 n = vec3(	clouds - noiseLayer(uv+vec2(eps,0.)),
                    -.3,
                    clouds - noiseLayer(uv+vec2(0.,eps)));
        n = normalize(n);
        
        // fake lighting
        float l = dot(n, normalize(vec3(uv.x,-.2,uv.y+.5)));
        l = clamp(l,0.,1.);
        
        // clouds color	(color gradient from light)
        vec3 cloudColor = mix(baseSkyColor, darkColor, length(uvInit)*1.7);
        cloudColor = mix( cloudColor,sunColor, l );
        
        // sky color (color gradient on Y)
        vec3 skyColor = mix(lightColor , baseSkyColor, clamp(uvInit.y*2.,0.,1.) );
        skyColor = mix ( skyColor, darkColor, clamp(uvInit.y*3.-.8,0.,1.) );
        skyColor = mix ( skyColor, sunColor, clamp(-uvInit.y*10.+1.1,0.,1.) );
        
      // draw sun
        if(length(uvInit-vec2(0.,.04) )<.03){
          skyColor += vec3(2.,1.,.8);
        }
          
        // mix clouds and sky
        float cloudMix = clamp(0.,1.,clouds*4.-8.);
        vec3 color = mix( cloudColor, skyColor, clamp(cloudMix,0.,1.) );
        
        // draw islands on horizon
        uvInit.y = abs(uvInit.y);
        float islandHeight = texture2D(iChannel1, uvInit.xx/2.+.67).r/15. - uvInit.y + .978;
        islandHeight += texture2D(iChannel1, uvInit.xx*2.).r/60.;
        islandHeight = clamp(floor(islandHeight),0.,1.);    
        vec3 landColor = mix(baseSkyColor, darkColor, length(uvInit)*1.5);
        color = mix(color, landColor, islandHeight);

        return color;
    }
    void main(void){
      // center uv around horizon and manage ratio
      vec2 uvInit = out_uv;
      uvInit.x -= .5;
      uvInit.x *= iResolution.x/iResolution.y;	
      uvInit.y -= 0.35;
      
      // perspective deform 
      vec2 uv = uvInit;
      uv.y -=.01;
      uv.y = abs(uv.y);
      uv.y = log(uv.y)/2.;
      uv.x *= 1.-uv.y;
      uv *= .2;
      
      vec3 col = vec3(1.,1.,1.);
      
      // draw water
      if(uvInit.y < 0.){       
        
          vec3 n = waterNormals(uv);
          
          // draw reflection of sky into water
          vec3 waterReflections = drawSky(uv+n.xz, uvInit+n.xz);

          // mask for fore-ground green light effect in water
          float transparency = dot(n, vec3(0.,.2,1.5));        
          transparency -= length ( (uvInit - vec2(0.,-.35)) * vec2(.2,1.) );
          transparency = (transparency*12.+1.5);
          
          // add foreground water effect
          waterReflections = mix( waterReflections, seaColor, clamp(transparency,0.,1.) );
          waterReflections = mix( waterReflections, seaLight, max(0.,transparency-1.5) );

          col = waterReflections;
          
          // darken sea near horizon
          col = mix(col, col*vec3(.6,.8,1.), -uv.y);
          
          //sun specular
          col += max(0.,.02-abs(uv.x+n.x))* 8000. * vec3(1.,.7,.3) * -uv.y * max(0.,-n.z);
          
      }else{      
          
          // sky
          col = drawSky(uv, uvInit);
      }
      
      // sun flare & vignette
      col += vec3(1.,.8,.6) * (0.55-length(uvInit)) ;
      
      // "exposure" adjust
      col *= .75;
      col = gamma(col,1.3);
      gl_FragColor = vec4(col,1.0);

    }
  </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值