canvas+webgl实现万圣节三维可拖动旋转南瓜头笑脸灯笼效果代码
代码语言:html
所属分类:三维
代码描述:canvas+webgl实现万圣节三维可拖动旋转南瓜头笑脸灯笼效果代码
代码标签: canvas webgl 万圣节 三维 拖动 旋转 南瓜头 笑脸 灯笼
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> </head> <body > <script> const canvas = document.createElement("canvas"); const gl = canvas.getContext("webgl2"); document.title = "🤖"; document.body.innerHTML = ""; document.body.appendChild(canvas); document.body.style = "margin:0;touch-action:none;overflow:hidden"; canvas.style.width = "100%"; canvas.style.height = "auto"; canvas.style.userSelect = "none"; const dpr = window.devicePixelRatio; function resize() { const { innerWidth: width, innerHeight: height } = window; canvas.width = width * dpr; canvas.height = height * dpr; gl.viewport(0, 0, width * dpr, height * dpr); } window.onresize = resize; const vertexSource = `#version 300 es #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif in vec4 position; void main(void) { gl_Position = position; } `; const fragmentSource = `#version 300 es /********* * made by Matthias Hurrle (@atzedent) */ #ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif // this particular pixel's color out vec4 fragColor; uniform vec2 resolution; uniform vec2 touch; uniform int pointerCount; uniform float time; #define P pointerCount #define mouse (touch/resolution) #define T time #define S smoothstep mat2 rot(float a) { float s=sin(a), c=cos(a); // 2D rotation matrix return mat2(c,-s,s,c); } float pumpkin(vec3 p) { // a squished sphere with fancy ripples const float r = 1.; // radius of the sphere float a = sin(10.*atan(p.x,p.z)); // ripples a = 1.-sqrt(abs(a)); // flat out surface of ripples and sharpen ridges p *= 1.+a*vec3(.05,.025,.05); // apply ripples p.y *= 1.+.5*(r-length(p.xz))/r; //squish sphere return length(p)-r; // sdf of a sphere with radius r } float mouth(vec3 p) { // no mouth at the back if (p.z > .0) return 5e5; // cylinders float a = length(p.xy+vec2(0,-.15))-.5; // upper lip float b = length(p.xy+vec2(0,-.55))-.7; // lower return max(a, -b); // carve out lower lip } float nose(vec3 p) { // no nose at the back if (p.z > .0) return 5e5; // equilateral triangle vec2 q = p.xy+vec2(0,-.15); // position q.x = abs(q.x); // mirror along y-axis float d = dot(q, normalize(vec2(1,.5))); // aspect ratio d = max(d, -(q.y+.15)); // size return d; } float eyes(vec3 p) { // no eyes at the back if (p.z > .0) return 5e5; vec2 q = p.xy; q.x = abs(q.x); //mirror q -= vec2(.4,.4); // position (doubles the eye, too) // sides of a scalene right triangle float d = dot(q, normalize(vec2(-.4, .95))); // ratio d = max(d, dot(q, normalize(vec2(.95, .4)))); // // ratio d = max(d, -.125+dot(q, normalize(vec2(0, -1)))); // size return d; } float stalk(vec3 p) { vec3 q = p; q.x += -(q.y-.5)*.1; // inclination // cylinder, capped by two planes float d = length(q.xz)-.07; // thickness d = max(d, p.y-.95 + p.x*.25); // angle cut on top d = max(d, -(p.y-.4)); return d; } vec2 map(vec3 p) { float bdy = pumpkin(p), mth = mouth(p), nse = nose(p), eys = eyes(p), slk = stalk(p); float d = max(pumpkin(p),-(length(p)-.65)); // carve out inner hollow d = max(d, -mth); // carve mouth d = max(d, -nse); // carve nose d = max(d, -eys); // carve eyes vec2 a = vec2(d*.5, 1); // define head (scale sdf down by a half for higher precision ray marching) a = a.x < slk ? a : vec2(slk, 2); // whats the nearest sdf, head or stalk? return a; } vec3 norm(vec3 p) { float h=1e-3; vec2 k=vec2(-1,1); // sample four points of the surface where the ray hit, to calculate the normal return normalize( k.xyy*map(p+k.xyy*h).x+ k.yxy*map(p+k.yxy*h).x+ k.yyx*map(p+k.yyx*h).x+ k.xxx*map(p+k.xxx*h).x ); } float getshadow(vec3 p, vec3 rd) { const float steps = 10., k = 128.; float shade = 1.; for (float i=1e-3; i<steps;) { // march the shadows float d = map(p + rd * i).x; if (d < 1e-3) { shade = 5e-3; break; } shade = min(shade, k * d / i); i += d; } return shade; } float getocc(vec3 p, vec3 rd) { float sca = 2., occ = .0; for(float i=.0; i<5.; i++) { // march ambient occlusion float d = 1e-2 + i*.125, dd = map(p + rd * d).x; occ += (d-dd) * sca; sca *= .7; } return clamp(1.-occ, .0, 1.); } vec3 shade(vec3 p, vec3 rd, float id) { // define color (night) and get the normal of the surface at point p vec3 col=vec3(0), n=norm(p), // place an outside light source lp=vec3(0,1,-3); float albedo=.2, // calculate the light from a bulb in front and above the origin diff=clamp(dot(n, normalize(lp)),.0,1.), // calculate fresnel fres=1.+clamp(dot(-rd,n),.0,1.), // distance from light source with a minimum to a.........完整代码请登录后点击上方下载按钮下载查看
网友评论0