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