regl+gl-matrix实现三维立方体镜面文字动画代码
代码语言:html
所属分类:三维
代码描述:regl+gl-matrix实现三维立方体镜面文字动画代码
代码标签: regl gl-matrix 三维 立方体 镜面 文字 动画 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> html, body { background-color: #000; min-height: 100%; } canvas { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .dribbble { position: fixed; display: block; right: 20px; bottom: 20px; } .dribbble img { display: block; height: 28px; } .twitter { position: fixed; display: block; right: 64px; bottom: 14px; } .twitter svg { width: 32px; height: 32px; fill: #1da1f2; } </style> </head> <body> <canvas class="canvas" width="500" height="500"></canvas> <!-- dribbble - twitter --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/regl.min.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/gl-matrix-min.js"></script> <script > const cubeCanvas = document.querySelector(".canvas"); const regl = createREGL({ canvas: cubeCanvas, attributes: { antialias: true, alpha: false, }, }); let tick; const play = (action) => { if (!tick) { tick = regl.frame(action); } }; const stop = () => { if (tick) { tick.cancel(); tick = null; } }; const Texture = (regl, src) => { const texture = regl.texture(); const image = new Image(); image.src = src; image.onload = function () { texture({ data: image, flipY: true, min: "mipmap", }); }; return texture; }; const emptyTexture = regl.texture(); const CONTENT_CONFIG = { translateX: 0, translateY: 0, translateZ: 0, rotation: 0, rotateX: 1, rotateY: 1, rotateZ: 1, scale: 1, }; const contentDraw = regl({ frag: ` precision mediump float; #define GLSLIFY 1 uniform vec2 u_resolution; uniform sampler2D u_texture; uniform int u_maskId; uniform int u_typeId; uniform sampler2D u_displacement; uniform sampler2D u_mask; uniform float u_tick; varying vec2 v_uv; const float PI2 = 6.283185307179586; const float PI = 3.141592653589793; const float PI2_0 = 6.28318530718; mat2 scale(vec2 value) { return mat2(value.x, 0.0, 0.0, value.y); } mat2 rotate2d(float value){ return mat2(cos(value), -sin(value), sin(value), cos(value)); } vec3 gradient1(vec2 st, float tick) { vec3 c1 = vec3(253.0/255.0, 142.0/255.0, 98.0/255.0); vec3 c2 = vec3(251.0/255.0, 83.0/255.0, 184.0/255.0); vec3 c3 = c2; vec3 c4 = vec3( 57.0/255.0, 15.0/255.0, 248.0/255.0); st.y = 1.0 - st.y; vec2 toCenter = vec2(0.55, 0.58) - st; float angle = atan(toCenter.y, toCenter.x) / PI; vec3 colorA = mix(c1, c2, smoothstep(0.0, 0.5, angle)); st -= vec2(0.5); st *= scale(vec2(1.4)); st *= rotate2d(-1.44); st += vec2(0.5); vec3 colorB = mix(c2, c3, smoothstep(0.3, 0.8, st.x)); colorB = mix(colorB, c4, smoothstep(0.55, 1.0, st.x)); return mix(colorA, colorB, smoothstep(0.28, 0.65, st.x)); } vec3 gradient2(vec2 st, float tick) { vec3 c1 = vec3(1.0, 0.8, 0.2); vec3 c2 = vec3(0.92, 0.20, 0.14); st -= vec2(0.5); st *= scale(vec2(3.8)); st *= rotate2d(tick * PI); st += vec2(0.5); return mix(c1, c2, st.x); } vec3 gradient3(vec2 st, float tick) { vec3 c1 = vec3(229.0/255.0, 255.0/255.0, 196.0/255.0); vec3 c2 = vec3(200.0/255.0, 255.0/255.0, 224.0/255.0); vec3 c3 = vec3(180.0/255.0, 255.0/255.0, 245.0/255.0); vec3 c4 = vec3(203.0/255.0, 223.0/255.0, 255.0/255.0); vec3 c5 = vec3(233.0/255.0, 201.0/255.0, 255.0/255.0); st -= vec2(0.5); st *= scale(vec2(1.2)); st *= rotate2d(tick * (PI / 2.5)); st += vec2(0.5); vec3 colorB = mix(c1, c2, smoothstep(0.0, 0.25, st.x)); colorB = mix(colorB, c3, smoothstep(0.25, 0.5, st.x)); colorB = mix(colorB, c4, smoothstep(0.5, 0.75, st.x)); colorB = mix(colorB, c5, smoothstep(0.75, 1.0, st.x)); return colorB; } vec3 gradients(int type, vec2 st, float tick) { if (type == 1) { return gradient1(st, tick); } else if (type == 2) { return gradient2(st, tick); } else if (type == 3) { return gradient3(st, tick); } } void main() { vec2 st = gl_FragCoord.xy / u_resolution; vec4 displacement = texture2D(u_displacement, st); vec2 direction = vec2(cos(displacement.r * PI2), sin(displacement.r * PI2)); float length = displacement.g; vec2 newUv = v_uv; newUv.x += (length * 0.07) * direction.x; newUv.y += (length * 0.07) * direction.y; vec4 texture = texture2D(u_texture, newUv); float tick = u_tick * 0.009; vec3 color = gradients(u_typeId, v_uv, tick); texture.rgb = color + (texture.rgb * color); vec4 mask = texture2D(u_mask, st); int maskId = int(mask.r * 4.0 + mask.g * 2.0 + mask.b * 1.0); if (maskId == u_maskId) { gl_FragColor = vec4(texture.rgb, texture.a * mask.a); } else { discard; } } `, vert: ` precision mediump float; #define GLSLIFY 1 attribute vec3 a_position; attribute vec2 a_uv; uniform mat4 u_projection; uniform mat4 u_view; uniform mat4 u_world; varying vec2 v_uv; void main() { v_uv = a_uv; gl_Position = u_projection * u_view * u_world * vec4(a_position, 1); } `, attributes: { a_position: [ [-1, -1, 0], [1, -1, 0], [1, 1, 0], [-1, 1, 0], ], a_uv: [ [0, 0], [1, 0], [1, 1], [0, 1], ], }, uniforms: { u_texture: regl.prop("texture"), u_typeId: regl.prop("typeId"), u_maskId: regl.prop("maskId"), }, depth: { enable: true, mask: false, func: "less", }, blend: { enable: true, func: { srcRGB: "src alpha", srcAlpha: 1, dstRGB: "one minus src alpha", dstAlpha: 1, }, equation: { rgb: "add", alpha: "add", }, color: [0, 0, 0, 0], }, elements: [0, 1, 2, 0, 2, 3], count: 6, }); const contentSetup = regl({ context: { world: () => { const { translateX, translateY, translateZ, rotation, rotateX, rotateY, rotateZ, scale, } = CONTENT_CONFIG; const world = mat4.create(); mat4.translate(world, world, [translateX, translateY, translateZ]); mat4.rotate(world, world, rotation, [rotateX, rotateY, rotateZ]); mat4.scale(world, world, [scale, scale, scale]); return world; }, mask: (context, { mask }) => { return mask || emptyTexture; }, displacement: (context, { displacement }) => { return displacement || emptyTexture; }, }, uniforms: { u_world: regl.context("world"), u_mask: regl.context("mask"), u_displacement: regl.context("displacement"), u_tick: regl.context("tick"), }, }); const content = (props) => { contentSetup(props, (context, { textures }) => { regl.clear({ color: [0, 0, 0, 0], depth: 1, }); contentDraw(textures); }); }; const ContentTypes = { GRADIENT: 1, RED: 2, BLUE: 3, }; const emptyCube = regl.cube(); const CUBE_CONFIG = { translateX: 0, translateY: 0, translateZ: 0, rotation: 0, rotateX: 1, rotateY: 1, rotateZ: 1, scale: 1, borderWidth: 0.008, displacementLength: 0.028, reflectionOpacity: 0.3, scene: 3, }; const cube = regl({ frag: ` precision mediump float; #define GLSLIFY 1 uniform vec2 u_resolution; uniform int u_face; uniform int u_typeId; uniform sampler2D u_texture; uniform samplerCube u_reflection; uniform float u_tick; uniform float u_borderWidth; uniform float u_displacementLength; uniform float u_reflectionOpacity; uniform int u_scene; varying vec3 v_normal; varying vec3 v_center; varying vec3 v_point; varying vec2 v_uv; varying vec3 v_color; varying float v_depth; const float PI2 = 6.283185307179586; float borders(vec2 uv, float strokeWidth) { vec2 borderBottomLeft = smoothstep(vec2(0.0), vec2(strokeWidth), uv); vec2 borderTopRight = smoothstep(vec2(0.0), vec2(strokeWidth), 1.0 - uv); return 1.0 - borderBottomLeft.x * borderBottomLeft.y * borderTopRight.x * borderTopRight.y; } const float PI2_0 = 6.28318530718; vec4 radialRainbow(vec2 st, float tick) { vec2 toCenter = vec2(0.5) - st; float angle = mod((atan(toCenter.y, toCenter.x) / PI2_0) + 0.5 + sin(tick * 0.002), 1.0); // colors vec4 c1 = vec4(229.0/255.0, 255.0/255.0, 196.0/255.0, 1.0); vec4 c2 = vec4(200.0/255.0, 255.0/255.0, 224.0/255.0, 1.0); vec4 c3 = vec4(180.0/255.0, 255.0/255.0, 245.0/255.0, 1.0); vec4 c4 = vec4(203.0/255.0, 223.0/255.0, 255.0/255.0, 1.0); vec4 c5 = vec4(233.0/255.0, 201.0/255.0, 255.0/255.0, 1.0); // vec4 a = vec4(0.43, 0.48, 0.95, 1.0); // vec4 b = vec4(0.94, 0.79, 0.41, 1.0); // // vec4 b = vec4(0.49, 0.88, 1.00, 1.0); // vec4 c = vec4(0.68, 0.29, 0.68, 1.0); // vec4 d = vec4(0.94, 0.79, 0.41, 1.0); // vec4 e = vec4(0.43, 0.48, 0.95, 1.0); float step = 1.0 / 10.0; vec4 color = c1; color = mix(color, c2, smoothstep(step * 1.0, step * 2.0, angle)); color = mix(color, c1, smoothstep(step * 2.0, step * 3.0, angle)); color = mix(color, c2, smoothstep(step * 3.0, step * 4.0, angle)); color = mix(color, c3, smoothstep(step * 4.0, step * 5.0, angle)); color = mix(color, c4, smoothstep(step * 5.0, step * 6.0, angle)); color = mix(color, c3, smoothstep(step * 6.0, step * 7.0, angle)); color = mix(color, c4, smoothstep(step * 7.0, step * 8.0, angle)); color = mix(color, c5, smoothstep(step * 8.0, step * 9.0, angle)); color = mix(color, c1, smoothstep(step * 9.0, step * 10.0, angle)); return color; } mat2 scale(vec2 value){ return mat2(value.x, 0.0, 0.0, value.y); } mat2 rotate2d(float value){ return mat2(cos(value), -sin(value), sin(value), cos(value)); } vec2 rotateUV(vec2 uv, float rotation) { float mid = 0.5; return vec2( cos(rotation) * (uv.x - mid) + sin(rotation) * (uv.y - mid) + mid, cos(rotation) * (uv.y - mid) - sin(rotation) * (uv.x - mid) + mid ); } vec4 type1() { vec2 toCenter = v_center.xy - v_point.xy; float angle = (atan(toCenter.y, toCenter.x) / PI2) + 0.5; float displacement = borders(v_uv, u_displacementLength) + borders(v_uv, u_displacementLength * 2.143) * 0.3; return vec4(angle, displacement, 0.0, 1.0); } vec4 type2() { return vec4(v_color, 1.0); } vec4 type3() { vec2 st = gl_FragCoord.xy / u_resolution; vec4 strokeColor = radialRainbow(st, u_tick); float depth = clamp(smoothstep(-1.0, 1.0, v_depth), 0.6, 0.9); vec4 stroke = strokeColor * vec4(borders(v_uv, u_borderWidth)) * depth; vec4 texture; if (u_face == -1) { vec3 normal = normalize(v_normal); texture = textureCube(u_reflection, normalize(v_normal)); texture.a *= u_reflectionOpacity * depth; } else { texture = texture2D(u_texture, st); } if (stroke.a > 0.0) { return stroke - texture.a; } else { return texture; } } vec4 switchScene(int id) { if (id == 1) { return type1(); } else if (id == 2) { return type2(); } else if (id == 3) { return type3(); } } void main() { if (u_scene == 3) { gl_FragColor = switchScene(u_typeId); } else { gl_FragColor = switchScene(u_scene); } } `, vert: ` precision mediump float; #define GLSLIFY 1 attribute vec3 a_position; attribute vec3 a_center; attribute vec2 a_uv; attribute vec3 a_color; uniform mat4 u_projection; uniform mat4 u_view; uniform mat4 u_world; varying vec3 v_normal; varying vec3 v_center; varying vec3 v_point; varying vec2 v_uv; varying vec3 v_color; varying float v_depth; void main() { vec4 center = u_projection * u_view * u_world * vec4(a_center, 1.0); vec4 position = u_projection * u_view * u_world * vec4(a_position, 1.0); v_normal = normalize(a_position); v_center = center.xyz; v_point = position.xyz; v_uv = a_uv; v_color = a_color; v_depth = (mat3(u_view) * mat3(u_world) * a_position).z; gl_Position = position; } `, context: { world: (context, { matrix }) => { const { translateX, translateY, translateZ, rotation, rotateX, rotateY, rotateZ, scale, } = CUBE_CONFIG; const world = mat4.create(); mat4.translate(world, world, [translateX, translateY, translateZ]); mat4.rotate(world, world, rotation, [rotateX, rotateY, rotateZ]); mat4.scale(world, world, [scale, scale, scale]); if (matrix) { mat4.multiply(world, world, matrix); } return world; }, face: (context, { cullFace }) => { return cullFace === CubeFaces.FRONT ? -1 : 1; }, texture: (context, { texture }) => { return texture || emptyTexture; }, reflection: (context, { reflection }) => { return reflection || emptyCube; }, textureMatrix: (context, { textureMatrix }) => { return textureMatrix; }, borderWidth: () => { const { borderWidth } = CUBE_CONFIG; return borderWidth; }, displacementLength: () => { const { displacementLength } = CUBE_CONFIG; return displacementLength; }, reflectionOpacity: () => { const { reflectionOpacity } = CUBE_CONFIG; return reflectionOpacity; }, scene: () => { const { scene } = CUBE_CONFIG; return parseFloat(scene); }, }, attributes: { a_position: [ [-1, +1, +1], [+1, +1, +1], [+1, -1, +1], [-1, -1, +1], // front face [+1, +1, +1], [+1, +1, -1], [+1, -1, -1], [+1, -1, +1], // right face [+1, +1, -1], [-1, +1, -1], [-1, -1, -1], [+1, -1, -1], // back face [-1, +1, -1], [-1, +1, +1], [-1, -1, +1], [-1, -1, -1], // left face [-1, +1, -1], [+1, +1, -1], [+1, +1, +1], [-1, +1, +1], // top face [-1, -1, -1], [+1, -1, -1], [+1, -1, +1], [-1, -1, +1], // bottom face ], a_center: [ [0, 0, 1], // front face [1, 0, 0], // right face [0, 0, -1], // back face [-1, 0, 0], // left face [0, 1, 0], // top face [0, -1, 0], // bottom face ].map((c) => { return [c, c, c, c]; }), a_uv: [ [0, 0], [1, 0], [1, 1], [0, 1], // front face [0, 0], [1, 0], [1, 1], [0, 1], // right face [0, 0], [1, 0], [1, 1], [0, 1], // back face [0, 0], [1, 0], [1, 1], [0, 1], // left face [0, 0], [1, 0], [1, 1], [0, 1], // top face [0, 0], [1, 0], [1, 1], [0, 1], // bottom face ], a_color: [ [0, 1, 0], // front face => mask 2 [0, 0, 1], // right face => mask 1 [1, 0, 0], // back face => mask 4 [1, 1, 0], // left face => mask 6 [1, 0, 1], // top face => mask 5 [0, 1, 1], // bottom face => mask 3 ].map((c) => { return [c, c, c, c]; }), }, uniforms: { u_world: regl.context("world"), u_face: regl.context("face"), u_typeId: regl.prop("typeId"), u_texture: regl.context("texture"), u_reflection: regl.context("reflection"), u_tick: regl.context("tick"), u_borderWidth: regl.context("borderWidth"), u_displacementLength: regl.context("displacementLength"), u_reflectionOpacity: regl.context("reflectionOpacity"), u_scene: regl.context("scene"), }, cull: { enable: true, face: regl.prop("cullFace"), }, depth: { enable: true, mask: false, func: "less", }, blend: { enable: true, func: { srcRGB: "src alpha", srcAlpha: 1, dstRGB: "one minus src alpha", dstAlpha: 1, }, equation: { rgb: "add", alpha: "add", }, color: [0, 0, 0, 0], }, elements: [ [2, 1, 0], [2, 0, 3], // front face [6, 5, 4], [6, 4, 7], // right face [10, 9, 8], [10, 8, 11], // back face [14, 13, 12], [14, 12, 15], // left face [18, 17, 16], [18, 16, 19], // top face [20, 21, 22], [23, 20, 22], // bottom face ], count: 36, framebuffer: regl.prop("fbo"), }); const CubeTypes = { DISPLACEMENT: 1, MASK: 2, FINAL: 3, }; const CubeFaces = { BACK: "back", FRONT: "front", }; const CubeMasks = { M1: 1, M2: 2, M3: 3, M4: 4, M5: 5, M6: 6, }; const CAMERA_CONFIG = { fov: 35, near: 0.01, far: 1000, }; const cameraConfig = { eye: [0, 0, 6], target: [0, 0, 0], up: [0, 1, 0], }; const camera = regl({ context: { projection: ({ viewportWidth, viewportHeight }) => { const { fov, near, far } = CAMERA_CONFIG; const fovy = (fov * Math.PI) / 180; const aspect = viewportWidth / viewportHeight; return mat4.perspective([], fovy, aspect, near, far); }, view: (context, props) => { const config = Object.assign({}, cameraConfig, props); const { eye, target, up } = config; return mat4.lookAt([], eye, target, up); }, fov: () => { const { fov } = CAMERA_CONFIG; return fov; }, }, uniforms: { u_projection: regl.context("projection"), u_view: regl.context("view"), u_cameraPosition: regl.context("eye"), u_resolution: ({ viewportWidth, viewportHeight }) => { return [viewportWidth, viewportHeight]; }, }, }); const plane = regl({ vert: ` precision mediump float; #define GLSLIFY 1 uniform sampler2D u_texture; varying vec4 vUv; void main() { gl_FragColor = texture2DProj(u_texture, vUv); } `, frag: ` precision mediump float; #define GLSLIFY 1 attribute vec3 a_position; uniform mat4 u_textureMatrix; uniform mat4 u_world; varying vec4 vUv; void main() { vUv = u_textureMatrix * vec4(a_position, 1.0); gl_Position = u_world * vec4(a_position, 1.0); } `, attributes: { a_position: [ [-1, 1, 0], [1, -1, 0], [-1, -1, 0], [-1, 1, 0], [1, 1, 0], [1, -1, 0], ], }, context: { world: (context, { uvRotation }) => { const world = mat4.create(); mat4.rotate(world, world, uvRotation, [0, 0, 1]); return world; }, }, uniforms: { u_world: regl.context("world"), u_texture: regl.prop("texture"), u_textureMatrix: regl.prop("textureMatrix"), }, count: 6, }); const reflector = regl({ frag: ` precision mediump float; #define GLSLIFY 1 uniform vec2 u_resolution; uniform sampler2D u_texture; uniform float u_depthOpacity; varying vec2 v_uv; varying float v_z; mat2 scale(vec2 scale){ return mat2(scale.x, 0.0, 0.0, scale.y); } void main() { vec2 st = gl_FragCoord.xy / u_resolution; vec4 texture = texture2D(u_texture, v_uv); texture.a -= u_depthOpacity * v_z; gl_FragColor = texture; } `, vert: ` precision mediump float; #define GLSLIFY 1 attribute vec3 a_position; attribute vec2 a_uv; uniform mat4 u_projection; uniform mat4 u_view; uniform mat4 u_world; uniform vec2 u_viewport; varying vec2 v_uv; varying float v_z; void main() { v_uv = a_uv; v_z = 1.0 - (mat3(u_view) * mat3(u_world) * a_position).z; gl_Position = u_projection * u_view * u_world * vec4(a_position, 1); } `, context: { world: ( { viewportWidth, viewportHeight }, { cameraConfig: mainCameraConfig, fov } ) => { const fovy = (fov * Math.PI) / 180; const aspect = viewportWidth / viewportHeight; const cameraHeight = Math.tan(fovy / 2) * mainCameraConfig.eye[2]; const cameraWidth = cameraHeight * aspect; const world = mat4.create(); mat4.scale(world, world, [cameraWidth, cameraHeight, 1.0]); return world; }, depthOpacity: () => { const depthOpacity = 0.75; return depthOpacity; }, }, attributes: { a_position: [ [-1, -1, 0], [1, -1, 0], [1, 1, 0], [-1, 1, 0], ], a_uv: [ [0, 0], [1, 0], [1, 1], [0, 1], ], }, uniforms: { u_world: regl.context("world"), u_texture: regl.prop("texture"), u_depthOpacity: regl.context("depthOpacity"), }, depth: { enable: true, mask: false, func: "less", }, blend: { enable: true, func: { srcRGB: "src alpha", srcAlpha: 1, dstRGB: "one minus src alpha", dstAlpha: 1, }, equation: { rgb: "add", alpha: "add", }, color: [0, 0, 0, 0], }, elements: [0, 1, 2, 0, 2, 3], count: 6, }); const planes = [ { position: [1, 0, 0], normal: [1, 0, 0], rotation: -Math.PI * 0.5, axis: [0, 1, 0], uvRotation: Math.PI, }, { position: [-1, 0, 0], normal: [-1, 0, 0], rotation: Math.PI * 0.5, axis: [0, 1, 0], uvRotation: Math.PI, }, { position: [0, 1, 0], normal: [0, 1, 0], rotation: Math.PI * 0.5, axis: [1, 0, 0], uvRotation: 0, }, { position: [0, -1, 0], normal: [0, -1, 0], rotation: -Math.PI * 0.5, axis: [1, 0, 0], uvRotation: 0, }, { position: [0, 0, 1], normal: [0, 0, 1], rotation: Math.PI, axis: [0, 1, 0], uvRotation: Math.PI, }, { position: [0, 0, -1], normal: [0, 0, -1], rotation: 0, axis: [0, 1, 0], uvRotation: Math.PI, }, ]; const renderTarget = regl.framebuffer(); const reflect = (a, b) => { const dot2 = new A.........完整代码请登录后点击上方下载按钮下载查看
网友评论0