webgl实现草原上的七星瓢虫三维爬行效果代码

代码语言:html

所属分类:三维

代码描述:webgl实现草原上的七星瓢虫三维爬行效果代码

代码标签: webgl 草原 瓢虫 三维

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开


<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">
 
  
  
  
<style>
html {
  height: 100%;
}
body {
  background: #286870;
  background: -moz-linear-gradient(180deg, #286870 0%, #0b232b 62%, #588849 100%);
  background: -webkit-linear-gradient(180deg, #286870 0%, #0b232b 62%, #588849 100%);
  background: linear-gradient(180deg, #286870 0%, #0b232b 62%, #588849 100%);
  overflow: hidden;
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  position: relative;
}
canvas {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  outline: none;
  box-shadow: 2px 20px 13px rgba(0, 0, 0, 0.75);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 800px;
  height: 450px;
  z-index: 0;
}
</style>



</head>

<body >
  <!-- VertexShader code here -->
<script id="vertexShader" type="x-shader/x-vertex">#version 300 es
precision highp float;
in vec4 vPosition;
void main() {
	gl_Position = vPosition;
}
</script>
<!-- FragmentShader code here -->
<script id="fragmentShader" type="x-shader/x-fragment">#version 300 es
precision highp float;
out vec4 fragColor;
  
uniform vec4 mouse;
uniform vec2 resolution;
uniform float time;

#define R           resolution
#define T           time
#define M           mouse

#define PI  3.14159265359
#define PI2 6.28318530718

#define MAX_DIST    120.
#define MIN_DIST    .0005

float hash21(vec2 p) { return fract(sin(dot(p,vec2(23.86,48.32)))*4374.432); }
vec2  hash2( vec2 p) { return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453); }
vec3  hash3( vec2 p) {
    vec3 q = vec3( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)), dot(p,vec2(419.2,371.9)) );
	return fract(sin(q)*43758.5453);
}

mat2 rot(float a) { return mat2(cos(a),sin(a),-sin(a),cos(a)); }
vec3 noised( in vec2 x ){
    vec2 f = fract(x);
    vec2 u = f*f*(3.0-2.0*f);
    vec2 p = vec2(floor(x));
    float a = hash21( p+vec2(0,0) );
	float b = hash21( p+vec2(1,0) );
	float c = hash21( p+vec2(0,1) );
	float d = hash21( p+vec2(1,1) );
	return vec3(a+(b-a)*u.x+(c-a)*u.y+(a-b-c+d)*u.x*u.y,
		   6.0*f*(1.0-f)*(vec2(b-a,c-a)+(a-b-c+d)*u.yx));
}

float fbm( vec2 p, float freq ) {	
	float h = -1.,w = 2.6,m = .35;
	for (float i = 0.; i < freq; i++) {
		h += w * noised((p * m)).x;
		w *= .5;
		m *= 2.;
	}
	return h;
}

vec2 truchet(vec2 uv, float scale) {
    uv *= scale;   
    vec2 grid = fract(uv)-.5;
    vec2 id = floor(uv);
    float hs = hash21(id);
    if(hs>.5) grid.x*=-1.;
    vec2 d2 = vec2(length(grid-.5), length(grid+.5));
    vec2 gx = d2.x<d2.y? vec2(grid-.5) : vec2(grid+.5);
    float circle = length(gx)-.5;
    circle=abs(circle)-.095;
    return vec2(clamp(circle,0.,1.),hs);
}

//@iq Voronoi Distances
//https://www.shadertoy.com/view/ldl3W8
vec4 voronoi( in vec2 x){
    vec2 n = floor(x);
    vec2 f = fract(x);
    float ox = 0.;
	float wave = 323.23123;
	vec2 mg, mr;

    float md = 8.;
    for( float j=-1.; j<=1.; j++ )
    for( float i=-1.; i<=1.; i++ )
    {
        vec2 g = vec2(i,j);
		vec2 o = hash2( n + g );

		o = .35 + .35 *sin(o * wave + PI2);
        vec2 r = g + o - f;
        float d = dot(r,r);
        if( d<md ){
            md = d;
            mr = r;
            mg = g;
        }
    }

    md = 8.;
    for( float j=-2.; j<=2.; j++ )
    for( float i=-2.; i<=2.; i++ )
    {
        vec2 g = mg + vec2(i,j);
		vec2 o = hash2( n + g );
        ox = o.x;
		o = .35 + .35 *sin(o * wave + PI2);
        vec2 r = g + o - f;
        if( dot(mr-r,mr-r)>.00001 )
        md = min( md, dot( .5*(mr+r), normalize(r-mr) ) );
    }
    return vec4( md, mr, ox );
}

//globals
vec3 hitPoint,hit;
mat2 rotA,rotB,rotC;

float box(vec3 p,vec3 s) {
    p=abs(p)-s; return max(p.x,max(p.y,p.z));
}

float box(vec2 p, vec2 b) {
    vec2 d = abs(p)-b; return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
}

// Field created watching @nusans shader livestream
// with some improvisations on some things

float blade(vec3 p, float sc) {
    p/=sc; p.y-=1.5;
    p.zx+= abs(p.xz)*.1;
    float wd = sin((p.y+1.5)*1.5)*.1;
    float d = box(p,vec3(wd,1.5,wd));
    return d*sc*.8;
}

vec2 field(vec3 p, float rp) {
    vec2 res=vec2(1e5,0);
    vec2 id=floor(p.xz/rp-.5);
    float hs = hash21(id);
    p.xz=(fract(p.xz/rp-.5)-.5)*rp;

    p.xz*=rot(hs*PI2);
    float fs = hash21(id+3.4);
    float sc = .5+hs*.8;
    float b = blade(p,sc);
    if(b<res.x) res =vec2(b,1.);
    
    if(fs>.9) {
        float fb=length(p-vec3(0,sc*2.,0))-(sc*.075);
        if(fb<res.x) res =vec2(fb,6.);
    }
    return res;
}

vec2 grass(vec3 p) {
    vec2 res = vec2(1e5,0),d;
    
    p.xz +=sin(p.zx*.15+p.y*.1+T*3.)*.3*max(0.,p.y)*.5;
    d = field(p,1.75);
    if(d.x<res.x) res = d;
    
    p.xz*=rotA;
    p.x+=45.35;
    d = field(p,1.15);
    if(d.x<res.x) res = d;
  
    p.xz*=rotB;
    p.x+=141.5;
    d = field(p,.75);
    if(d.x<res.x) res = d;
 
    return res;
}

float specks(vec3 p,float rp) {
    p.z+=T*5.+abs(sin(T*.5-p.z*.01))*10.;
    p.xyz+=sin(p.zxy*vec3(.02,0,.07)+vec3(.1,.07,.05)*T)*5.5;
    p = (fract(p/rp-.5)-.5)*rp;   
    return length(p)-.05;
}

float mst=0.;
float mist(vec3 p) {  
    vec3 q = p;
    float d = specks(p,11.);
    p.xz*=rotC;
    p.yz*=rotB;
    d = min(specks(p,7.),d);
    
    d += max(.0,-(6.-q.y)*.025);
    return d; 
}

// The truchet path is something I made up, however I haven't
// found a good way of implimenting yet - tried some other 
// multi-tap systems so prevent the cutoff but not smart enough
// mathwise to know what I'm trying to do.
// well its not perfect but looks ok if you squint.

float gid,sid;
vec2 map(vec3 p, float sd) {
	  vec2 res = vec2(1e5,0.);
    p.x+=T;
    vec3 pbk = p;
    float gnd = fbm(p.xz*.15,.1)*1.95;
    p.y+=gnd;
    
    vec2 uv = p.xz*.05;
    float py = p.y+.5;
    vec2 tc = truchet(p.xz,.05);
    float cc = tc.x;
    vec2 dx = grass(p);
    if(dx.x<res.x) {
        if(cc<.03){
           dx.x += max(.1,.15-cc*.25);
        }
       res = vec2(dx.x,dx.y);
       hit=p;
    }
   
    float mt3 = mist(p);

    if(mt3<res.x && sd>0.) {
       res = vec2(mt3,3.);
       mst +=clamp(.0025/(.00025+mt3*mt3) ,.0, max(.0, (gnd)*.015) );
       //mst += .0025/(.00025+mt3*mt3);
    }
    
    vec2 id = floor(p.xz*.05);
    vec2 guv= fract(p.xz*.05)-.5;
    
    float hs = hash21(id);
    if(hs>.5) guv.x*=-1.;
    
    float dir = mod(id.x+id.y,2.)<.5? -1. : 1.;
    
    vec2 x2 = vec2(length(guv-.5), length(guv+.5)); 
    vec2 pp = x2.x<x2.y? vec2(guv-.5) : vec2(guv+.5);
    
    pp *= rot(T*.125*dir);
    
    float amt = 3.,dbl = 6.;
    
    float a = atan(pp.y, pp.x);
    float ai = floor(dir*a-.5/PI*dbl);
    a = (floor(a/PI2*dbl) + .5)/dbl;
    float ws = mod(ai,3.);
    gid=ws;
    vec2 qr = rot(-a*PI2)*pp; 
    qr.x -= .5;
    vec3 np = vec3(qr.x/.05, py, qr.y/.05);
    
    //ladybugs
    float d6=box(np,vec3(2.5,.6,2.5));
    float d5=length(np-vec3(0,.5,0))-.75;
    d5=max(d5,-d6);
    if(d5<res.x) {
       res = vec2(d5,5.);
       hit=vec3(np.x,np.y,dir*np.z);
    }
    float d7=length(np-vec3(0,.75,dir*.6))-.35;
    d7=max(d7,-d6);
    if(d7<res.x) {
       res = vec2(d7,4.);
       hit=vec3(np.x,np.y,np.z-(dir*.6));
    }

    float d2=p.y;
    if(d2<res.x) {
       res = vec2(d2,2.);
       hit=pbk;
    }

    return res;
}

// Normal
vec3 normal(vec3 p, float t) {
    float e = MIN_DIST*t;
    vec2 h = vec2(1.0,-1.0)*0.5773;
    return normalize( 
        h.xyy*map( p + h.xyy*e,0. ).x + 
        h.yyx*map( p + h.yyx*e,0. ).x + 
        h.yxy*map( p + h.yxy*e,0. ).x + 
        h.xxx*map( p + h.xxx*e,0. ).x );
}

vec3 render(vec3 ro, vec3 rd, vec2 uv) {

    vec3 C = vec3(0);
    vec3 p = ro;
    
    // Sky
    vec3 sky = mix(
    max(vec3(.03),vec3(0.5,0.6,1.)-rd.y*2.),
    vec3(0.9,0.7,0.5)*10.,
    pow(max(.03, dot(rd,normalize(vec3(4.,15,4.)) )),10.));
    vec2 vuv = (rd.xz/(rd.y+.075))-vec2(0,T*.75)*.75;
    sky = mix(sky,vec3(.9), .25+.25*smoothstep(.01,.75,fbm(vuv,2.)) );

    // Marcher
    float d =0.,m = 0.;
    for (int i = 0; i<192;i++) {
     	p = ro + rd * d;
        vec2 ray = map(p,1.);
        if(abs(ray.x)<d*MIN_DIST || d>MAX_DIST)break;
        d += i<32? ray.x*.25 : ray.x*.85;  
        m = ray.y;
    }
    
    hitPoint=hit;
    sid=gid;
    float alpha = 0.;
    
    if(d<MAX_DIST){
      	vec3 n = normal(p, d);
        vec3 lpos = vec3(15.,35,10.);
        vec3 l = normalize(lpos-p); 

        // Diffused and Shadow
        float diff = clamp(dot(n,l),0.,1.);

        float shdw = 1., t = .01;
        for(int i=0; i<25; i++){
            float h = map(p + l*t,0.).x;
            if( h<MIN_DIST ) {shdw = 0.; break;}
            shdw = min(shdw, 25.*h/t);
            t += h;
            if( shdw<MIN_DIST || t>32. ) break;
        }
        diff = mix(diff,diff*shdw,.35);

        // Materials
        vec3 h = vec3(.0);
        if(m==1.) h = vec3(0.192,0.490,0.07);
        if(m==2.) {
            
            vec2 uv = hitPoint.xz;
            float px = fwidth(uv.x);
            float circle = truchet(uv, .05).x;
            circle=smoothstep(px,-px,circle);
            
            float dmp = hash21(floor(uv*25.))*.175;
            h = vec3(0.059,0.196+dmp,0.004);
            h = mix(h, h*vec3(0.020,0.055,0.004),circle);
            
            uv*=.05;
            
            vec2 guv = fract(uv)-.5;
            vec2 id = floor(uv);

            float hs = hash21(id);
            if(hs>.5) guv.x*=-1.;
            float dir = mod(id.y + id.x,2.) * 2. - 1.;

            vec2 d2 = vec2(length(guv-.5), length(guv+.5));
      .........完整代码请登录后点击上方下载按钮下载查看

网友评论0