js实现canvas液态鼠标跟随动画效果代码
代码语言:html
所属分类:动画
代码描述:js实现canvas液态鼠标跟随动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<html> <head> <style> body { background: #555555; margin: 0; } canvas { position: fixed; } </style> </head> <body> <canvas id="webgl" width="574" height="611" style="width: 574px; height: 611px;"></canvas> <script id="vertexShader" type="x-shader/x-vertex"> attribute vec4 a_position; uniform mat4 u_modelViewMatrix; uniform mat4 u_projectionMatrix; void main() { gl_Position = a_position; } </script> <script id="fragmentShader" type="x-shader/x-fragment"> #extension GL_OES_standard_derivatives: enable precision highp float; uniform vec2 u_resolution; uniform vec2 u_mouse; uniform vec2 u_oldmouse; uniform float u_time; uniform sampler2D u_noise; uniform int u_frame; uniform sampler2D u_b_buffer; uniform bool u_buffer_pass; #define PI 3.141592653589793 vec2 getScreenSpace() { vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / min(u_resolution.y, u_resolution.x); return uv; } float sdSegment(in vec2 p, in vec2 a, in vec2 b) { vec2 pa = p-a, ba = b-a; float h = clamp(dot(pa, ba)/dot(ba, ba), 0.0, 1.0); return length(pa - ba*h); } vec4 render_effect() { vec2 uv = getScreenSpace(); vec2 oldmouse = u_oldmouse.xy; vec2 mouse = u_mouse.xy; return vec4(vec3(smoothstep(.02, .0, sdSegment(uv, oldmouse, mouse))), 1.); } vec4 blurBuffer(vec2 uv) { vec3 pixs = vec3(1./u_resolution.xy, 0.)*5.; vec4 sample = texture2D(u_b_buffer, uv + pixs.zy); sample += texture2D(u_b_buffer, uv - pixs.zy); sample += texture2D(u_b_buffer, uv + pixs.xz); sample += texture2D(u_b_buffer, uv - pixs.xz); sample *= .25; return sample; } void main() { vec4 tex = texture2D(u_b_buffer, gl_FragCoord.xy/u_resolution.xy); tex = blurBuffer(gl_FragCoord.xy/u_resolution.xy); if (u_buffer_pass) { gl_FragColor = (tex * .9995 + render_effect()); } else { float f = sin(min(10., tex.r)); f = smoothstep(0., 1., tex.r); float tex1 = texture2D(u_b_buffer, gl_FragCoord.xy/u_resolution.xy - 20./u_resolution.xy).r; float f1 = sin(min(10., tex1)); f1 = smoothstep(0., 1., tex1); float s = f; s = 1. - pow(s, .3); s = s*3.; float r = smoothstep(0.6, .8, f) - s; float g = smoothstep(0.5, .5+fwidth(f), f) - s; float b = smoothstep(0.1, .4, f1) - s; float sh = clamp(r-b, 0., 1.); // sh = smoothstep(0., .8, sh); gl_FragColor = vec4(vec3(r-sh*.5), 1.); } } </script> <script> function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; }return obj; } /** * A basic Web GL class. This provides a very basic setup for GLSL shader code. * Currently it doesn't support anything except for clip-space 3d, but this was * done so that we could start writing fragments right out of the gate. My * Intention is to update it with particle and polygonal 3d support later on. * * @class WTCGL * @author Liam Egan <liam@wethecollective.com> * @version 0.0.8 * @created Jan 16, 2019 */ class WTCGL { /** * The WTCGL Class constructor. If construction of the webGL context fails * for any reason this will return null. * * @TODO make the dimension properties properly optional * @TODO provide the ability to allow for programmable buffers * * @constructor * @param {HTMLElement} el The canvas element to use as the root * @param {string} vertexShaderSource The vertex shader source * @param {string} fragmentShaderSource The fragment shader source * @param {number} [width] The width of the webGL context. This will default to the canvas dimensions * @param {number} [height] The height of the webGL context. This will default to the canvas dimensions * @param {number} [pxratio=1] The pixel aspect ratio of the canvas * @param {boolean} [styleElement] A boolean indicating whether to apply a style property to the canvas (resizing the canvas by the inverse of the pixel ratio) * @param {boolean} [webgl2] A boolean indicating whether to try to create a webgl2 context instead of a regulart context */ constructor(el, vertexShaderSource, fragmentShaderSource, width, height, pxratio, styleElement, webgl2, params = {}) { this.run = this.run.bind(this); this._onRun = () => {}; // Destructure if an object is aprovided instead a series of parameters if (el instanceof Object && el.el) { ({ el, vertexShaderSource, fragmentShaderSource, width, height, pxratio, webgl2, styleElement } = el); } // If the HTML element isn't a canvas, return null if (!el instanceof HTMLElement || el.nodeName.toLowerCase() !== 'canvas') { console.log('Provided element should be a canvas element'); return null; } this._el = el; // The context should be either webgl2, webgl or experimental-webgl if (webgl2 === true) { this.isWebgl2 = true; this._ctx = this._el.getContext("webgl2", this.webgl_params) || this._el.getContext("webgl", this.webgl_params) || this._el.getContext("experimental-webgl", this.webgl_params); } else { this.isWebgl2 = false; this._ctx = this._el.getContext("webgl", Object.assign({}, this.webgl_params, params)) || this._el.getContext("experimental-webgl", Object.assign({}, this.webgl_params, params)); } // Set up the extensions this._ctx.getExtension('OES_standard_derivatives'); this._ctx.getExtension('EXT_shader_texture_lod'); this._ctx.getExtension('OES_texture_float'); this._ctx.getExtension('WEBGL_color_buffer_float'); this._ctx.getExtension('OES_texture_float_linear'); this._ctx.getExtension('EXT_color_buffer_float'); // We can't make the context so return an error if (!this._ctx) { console.log('Browser doesn\'t support WebGL '); return null; } // Create the shaders this._vertexShader = WTCGL.createShaderOfType(this._ctx, this._ctx.VERTEX_SHADER, vertexShaderSource); this._fragmentShader = WTCGL.createShaderOfType(this._ctx, this._ctx.FRAGMENT_SHADER, fragmentShaderSource); // Create the program and link the shaders this._program = this._ctx.createProgram(); this._ctx.attachShader(this._program, this._vertexShader); this._ctx.attachShader(this._program, this._fragmentShader); this._ctx.linkProgram(this._program); // If we can't set up the params, this means the shaders have failed for some reason if (!this._ctx.getProgramParameter(this._program, this._ctx.LINK_STATUS)) { console.log('Unable to initialize the shader program: ' + this._ctx.getProgramInfoLog(this._program)); return null; } // Initialise the vertex buffers this.initBuffers([ -1.0, 1.0, -1., 1.0, 1.0, -1., -1.0, -1.0, -1., 1.0, -1.0, -1.]); // Initialise the frame buffers this.frameBuffers = []; // The program information object. This is essentially a state machine for the webGL instance this._programInfo = { attribs: { vertexPosition: this._ctx.getAttribLocation(this._program, 'a_position') }, uniforms: { projectionMatrix: this._ctx.getUniformLocation(this._program, 'u_projectionMatrix'), modelViewMatrix: this._ctx.getUniformLocation(this._program, 'u_modelViewMatrix'), resolution: this._ctx.getUniformLocation(this._program, 'u_resolution'), time: this._ctx.getUniformLocation(this._program, 'u_time') } }; // Tell WebGL to use our program when drawing this._ctx.useProgram(this._program); this.pxratio = pxratio; this.styleElement = styleElement !== true; this.resize(width, height); } /** * Public methods */ addFrameBuffer(w, h, tiling = 0, buffertype = 0) { // create to render to const gl = this._ctx; const targetTextureWidth = w * this.pxratio; const targetTextureHeight = h * this.pxratio; const targetTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, targetTexture); { // define size and format of level 0 const level = 0; let internalFormat = gl.RGBA; const border = 0; let format = gl.RGBA; let t; if (buffertype & WTCGL.TEXTYPE_FLOAT) { const e = gl.getExtension('OES_texture_float'); window.extension = e; t = e.FLOAT; // internalFormat = gl.RGBA32F; } else if (buffertype & WTCGL.TEXTYPE_HALF_FLOAT_OES) { // t = gl.renderer.isWebgl2 ? e.HALF_FLOAT : e.HALF_FLOAT_OES; // gl.renderer.extensions['OES_texture_half_float'] ? gl.renderer.extensions['OES_texture_half_float'].HALF_FLOAT_OES : // gl.UNSIGNED_BYTE; const e = gl.getExtension('OES_texture_half_float'); t = this.isWebgl2 ? gl.HALF_FLOAT: e.HALF_FLOAT_OES; // format = gl.RGBA; if (this.isWebgl2) { internalFormat = gl.RGBA16F; } // internalFormat = gl.RGB32F; // format = gl.RGB32F; // window.gl = gl // t = e.HALF_FLOAT_OES; } else { t = gl.UNSIGNED_BYTE; } const type = t; const data = null; gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, targetTextureWidth, targetTextureHeight, border, format, type, data); // gl.generateMipmap(gl.TEXTURE_2D); // set the filtering so we don't need mips gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); // Set the parameters based on the passed type if (tiling === WTCGL.IMAGETYPE_TILE) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); } else if (tiling === WTCGL.IMAGETYPE_MIRROR) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); } else if (tiling === WTCGL.IMAGETYPE_REGULAR) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); } } // Create and bind the framebuffer const fb = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb); // attach the texture as the first color attachment const attachmentPoint = gl.COLOR_ATTACHMENT0; const level = .........完整代码请登录后点击上方下载按钮下载查看
网友评论0