%PDF- %PDF-
Direktori : /var/www/html/shaban/laviva/wp-content/themes/levelup/assets/js/fx/ |
Current File : /var/www/html/shaban/laviva/wp-content/themes/levelup/assets/js/fx/glitch.js |
// A very lightweight layer on top of the WebGL API to make coding WebGL faster and much more fun. // // This isn't a 3D engine, but could be used as the foundation for one. /*! @copyright 2016 Justin Windle @license http://opensource.org/licenses/MIT @author Justin Windle <justin@soulwire.co.uk> @see https://github.com/soulwire/gl.js @see http://soulwire.co.uk */ var GL = (function() { 'use strict'; var GL = { // // Create // -------------------------------------------------- // // Creates a WebGL drawing context and augments it // to add the functionality of the __gl.js__ library // // Parameters: // - `canvas` _(optional)_ The canvas element to use // create: function( canvas ) { var gl; if ( !canvas ) canvas = document.createElement( 'canvas' ); if ( !( gl = ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ) ) throw 'Error creating WebGL context'; var shader, bindings = {}; return extend( gl, { bindings: bindings, // // Shader // -------------------------------------------------- // // Creates a shader object from a given type and source code // // Parameters: // - `source` Source string for the shader // - `type` The shader type (`VERTEX_SHADER` or `FRAGMENT_SHADER`) // shader: function( source, type ) { source = PRECISION + '\n' + source; gl.shaderSource( shader = gl.createShader( type ), source ); gl.compileShader( shader ); if ( !gl.getShaderParameter( shader, COMPILE_STATUS ) ) logShaderError( gl.getShaderInfoLog( shader ), source ); return shader; }, // // Program // -------------------------------------------------- // // Creates a shader program from _vertex_ and _fragment_ // shader source code // // Parameters: // - `vs` Source string for the vertex shader // - `fs` Source string for the fragment shader // program: function( vs, fs ) { var attribute, program, uniform, source, name, type, size, span, program = gl.createProgram(); program.state = {}; gl.attachShader( program, gl.shader( vs, VERTEX_SHADER ) ); gl.attachShader( program, gl.shader( fs, FRAGMENT_SHADER ) ); gl.linkProgram( program ); if ( !gl.getProgramParameter( program, LINK_STATUS ) ) throw gl.getProgramInfoLog( program ); /* Concatenates vertex and fragment shader source code and strips out comments, ready to be parsed for attributes and uniforms */ source = [ vs, fs ].join( '\n' ).replace( COMMENT, '' ); /* Parse attributes in the shader code, create `attribute` objects for each and store them in the program */ while ( attribute = ATTRIBUTE.exec( source ) ) { type = attribute[1]; name = attribute[2]; if ( !program[ name ] ) program[ name ] = gl.attribute( program, name, type ); } /* Parse uniforms in the shader code, create `uniform` objects for each and store them in the program */ while ( uniform = UNIFORM.exec( source ) ) { type = uniform[1]; name = uniform[2]; span = uniform[5]; if ( !program[ name ] ) program[ name ] = gl.uniform( program, name, type, span ); } /* Extends the core program functionalty */ return extend( program, { // ##### on // Tells WebGL to start using this program on: function() { if ( gl.usedProgram !== program ) gl.useProgram( gl.usedProgram = program ); }, // ##### draw // Draw a `mesh` object using this program // // Parameters // - `mesh` The `mesh` object to draw // - `mode` _(optional)_ The drawing mode to use (if not `mesh.mode`) // - `first` _(optional)_ The index to start drawing from // - `count` _(optional)_ How many items to draw draw: function( mesh, mode, first, count ) { program.on(); var key, val, obj, unit = 0; /* Attributes */ for ( key in obj = mesh.attributes ) if ( program[ key ] ) obj[ key ].on( program[ key ] ); /* Uniforms */ for ( key in obj = mesh.uniforms ) if ( program[ key ] ) program[ key ].set( obj[ key ] ); /* Textures */ for ( key in obj = mesh.textures ) if ( program[ key ] ) obj[ key ].on( unit ), program[ key ].set( unit++ ); /* Vertices */ for ( key in obj = mesh.vertices ) ( val = obj[ key ] ).on( program[ key ] ); /* Draw */ if ( mesh.indices ) { mesh.indices.on(); gl.drawElements( TRIANGLES, mesh.indices.length, UNSIGNED_SHORT, 0 ); } else { gl.drawArrays( mode || mesh.mode, first || 0, count || ( val.length / program[ key ].size ) ); } } }); }, // // Attribute // -------------------------------------------------- // // Creates an object that encapsulates a vertex shader // attribute and provides methods for using it // // Parameters: // - `program` The `program` object the attribute belongs to // - `name` The name of the attribute (usually prefixed with _a_) // - `type` The type of object used for this attribute (e.g. _vec3_) // attribute: function( program, name, type ) { var location = gl.getAttribLocation( program, name ); var dataType = getType( type ); var size = getSize( type ); var on = false; return { name: name, type: type, size: size, dataType: dataType, location: location, // ##### on // Enable the attribute and setup pointers on: function() { if ( !on ) gl.enableVertexAttribArray( location ); gl.vertexAttribPointer( location, size, dataType, false, 0, 0 ); on = true; }, // ##### off // Disable the attribute off: function() { gl.disableVertexAttribArray( location ); } }; }, // // Uniform // -------------------------------------------------- // // Creates an object that encapsulates a program // uniform and provides methods for using it // // Parameters: // - `program` The `program` object the uniform belongs to // - `name` The name of the uniform (usually prefixed with _u_) // - `type` The type of object used for this uniform (e.g. _vec3_) // - `span` _(optional)_ The length of this uniform if it's an array // uniform: function( program, name, type, span ) { var location = gl.getUniformLocation( program, name ); var setter = gl[ uniformMethod( type, span ) ]; var state = program.state; return { name: name, type: type, span: span || 1, location: location, setter: setter, // ##### get // Returns the current value of the uniform get: function() { return gl.getUniform( program, location ); }, // ##### set // Sets the current value of the uniform set: function( value ) { if ( state[ name ] !== value ) { program.on(); setter.apply( gl, [ location ].concat( state[ name ] = value ) ); } } }; }, // // Buffer // -------------------------------------------------- // // Creates a buffer object to use for attributes or indices // // Parameters: // - `type` The type of buffer (`ARRAY_BUFFER` or `ELEMENT_ARRAY_BUFFER`) // - `data` _(optional)_ The initial data to fill the buffer with // buffer: function( type, data ) { var ArrayType = type === ARRAY_BUFFER ? Float32Array : Uint16Array; var buffer = gl.createBuffer(); extend( buffer, { // ##### length // The current length of the buffer length: 0, // ##### on // Binds the buffer to the appropriate bind point and // enables the attribute for the buffer // // Parameters // - `attribute` The attribute that this buffer is for on: function( attribute ) { if ( bindings[ type ] !== buffer ) { gl.bindBuffer( type, bindings[ type ] = buffer ); if ( attribute ) attribute.on(); } }, // ##### fill // Fills the buffer with data // // Parameters // - `data` The data to fill the buffer with // - `usage` _(optional)_ How the buffer will be used (defaults to `STATIC_DRAW`) fill: function( data, usage ) { if ( toType( data ) == 'array' ) data = new ArrayType( data ); gl.bindBuffer( type, buffer ); gl.bufferData( type, data, usage || STATIC_DRAW ); buffer.length = data.length; }, // ##### push // Pushes data into the buffer at a given offset // // Parameters // - `data` The data to push into the buffer // - `offset` The point at which to start pushing in data push: function( data, offset ) { if ( isArray( data ) ) data = new ArrayType( data ); gl.bindBuffer( type, buffer ); gl.bufferSubData( type, offset, data ); } }); if ( data ) buffer.fill( data ); return buffer; }, // // VBO // -------------------------------------------------- // // Creates a vertex buffer for sending attributes to a vertex shader // (internally this calls `gl.buffer` with type `ARRAY_BUFFER`) // // Parameters: // - `data` _(optional)_ The initial data to fill the buffer with // vbo: function( data ) { return gl.buffer( ARRAY_BUFFER, data ); }, // // IBO // -------------------------------------------------- // // Creates a buffer for specifying vertex indices (internally // this calls `gl.buffer` with type `ELEMENT_ARRAY_BUFFER`) // // Parameters: // - `data` _(optional)_ The initial data to fill the buffer with // ibo: function( data ) { return gl.buffer( ELEMENT_ARRAY_BUFFER, data ); }, // // FBO // -------------------------------------------------- // // Creates a frame buffer object that can be used as an // alternative rendering target // // Parameters: // - `width` _(optional)_ The initial width of the frame buffer // - `height` _(optional)_ The initial height of the frame buffer // - `data` _(optional)_ The initial texture data // // TODO: // - Add support for `renderBuffers` // fbo: function( width, height, data, options ) { var fbo = gl.createFramebuffer(); var tex = gl.texture(); extend( fbo, { // ##### texture // The texture object that the frame buffer renders to texture: tex, // ##### set // Sets up the frame buffer with optional data and dimensions // // Parameters: // - `data` _(optional)_ Image data for the frame buffer // - `width` _(optional)_ The initial width of the frame buffer // - `height` _(optional)_ The initial height of the frame buffer set: function( data, width, height, options ) { fbo.on(); tex.set( data, fbo.width = width, fbo.height = height, options ); gl.framebufferTexture2D( FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, tex, 0 ); fbo.off(); }, // ##### on // Binds the frame buffer to use as an off screen rendering target on: function() { gl.bindFramebuffer( FRAMEBUFFER, fbo ); }, // ##### off // Unbinds the frame buffer, re-enabling the default render target off: function() { gl.bindFramebuffer( FRAMEBUFFER, null ); } }); fbo.set( data, width || 1, height || 1, options ); return fbo; }, // // Texture // -------------------------------------------------- // // Creates a texture object // // Parameters: // - `source` _(optional)_ The initial source data for the texture. // Possible values are: // - `string` (path to an image file) // - `ArrayBufferView` _(pixels)_ // - `ImageData` _(pixels)_ // - `HTMLImageElement` _(May throw DOMException)_ // - `HTMLCanvasElement` _(May throw DOMException)_ // - `HTMLVideoElement` _(May throw DOMException)_ // - `width` _(optional)_ Width of the texture, if not one of the above types // - `height` _(optional)_ Height of the texture, if not one of the above types // - `options` _(optional)_ Options to use during `setup` // // TODO: // - Auto convert arrays to typed // texture: function( source, width, height, options ) { var texture = gl.createTexture(); var content; var pot; if ( typeof width == 'object' ) options = width; extend( texture, { // ##### param // Sets a parameter for this texture (for example `TEXTURE_MIN_FILTER`) // // Parameters: // - `name` The name of the parameter to set (e.g. `TEXTURE_MIN_FILTER`) // - `value` The value for the parameter (e.g. `LINEAR`) param: function( name, value ) { gl.texParameteri( TEXTURE_2D, name, value ); }, // ##### setup // Sets up the texture by configuring several parameters and generates // mipmaps if appropriate // // Parameters: // - `options` _(optional)_ An object containing parameter names and their values // Possible keys are: // - `min` How to resample when shrinking // - `mag` How to resample when stretching // - `s` Whether to clamp or repeat on the _s_ (_x_) axis // - `t` Whether to clamp or repeat on the _t_ (_y_) axis setup: function( options ) { options = extend( options || {}, { min: LINEAR, mag: LINEAR, s: CLAMP_TO_EDGE, t: CLAMP_TO_EDGE }); texture.on(); texture.param( TEXTURE_MAG_FILTER, options.mag ); texture.param( TEXTURE_MIN_FILTER, options.min ); texture.param( TEXTURE_WRAP_S, options.s ); texture.param( TEXTURE_WRAP_T, options.t ); if ( options.mipmap ) gl.generateMipmap( TEXTURE_2D ); texture.off(); }, // ##### on // Binds the texture and if `unit` is specified, tells WebGL to // use this texture as the texture at the given unit, which will // correspond to a shader uniform // // Parameters: // - `unit` _(optional)_ The unit to activate this texture for on: function( unit ) { if ( exists( unit ) ) gl.activeTexture( TEXTURE0 + unit ); gl.bindTexture( TEXTURE_2D, texture ); }, // ##### off // Unbinds this texture off: function() { gl.bindTexture( TEXTURE_2D, null ); }, // ##### set // Populates this texture object with data of one of the supported // types (see the constructor's `source` parameter above) // // Parameters: // - `data` _(optional)_ The data to populate the texture with // - `width` _(optional)_ The width of the texture // - `height` _(optional)_ The height of the texture set: function( data, width, height, options ) { options = extend( options || {}, { mipmap: pot = width > 1 && height > 1 && isPowerOf2( width ) && isPowerOf2( height ), format: RGBA, min: pot ? LINEAR_MIPMAP_LINEAR : LINEAR, flip: true }); var path = typeof data === 'string'; if ( path || !data && !width && !height ) { texture.set( EMPTY_PIXEL, 1, 1 ); if ( path ) loadImage( data, texture.set ); return; } var type = /^float/i.test( toType( data ) ) ? FLOAT : UNSIGNED_BYTE; texture.on(); gl.pixelStorei( UNPACK_FLIP_Y_WEBGL, options.flip ); if ( width && height ) gl.texImage2D( TEXTURE_2D, 0, options.format, width, height, 0, options.format, type, data ); else gl.texImage2D( TEXTURE_2D, 0, options.format, options.format, UNSIGNED_BYTE, data ); if ( data !== content ) texture.setup( options ); content = data; texture.off(); } }); texture.set( source, width, height, options ); return texture; }, // // Size // -------------------------------------------------- // // Resizes the canvas and viewport // // Parameters: // - `width` The desired width // - `height` The desired height // size: function( width, height ) { gl.viewport( 0, 0, width, height ); gl.height = canvas.height = height; gl.width = canvas.width = width; }, // // Mesh // -------------------------------------------------- // // Creates a mesh object that encapsulates the properties // needed to render a mesh and can be given to a `program` // to draw // // Parameters: // - `options` The properties to initialise the mesh with // - `mode` The default drawing mode to use // - `attributes` Names attribute keys and buffer their values // - `uniforms` A hash of uniforms and their initial values // - `textures` Texture uniform keys and corresponding textures // - `textures` Texture uniform keys and corresponding textures // - `textures` Texture uniform keys and corresponding textures // // Example: // // var quad = gl.mesh({ // uniforms: { // uTime: 0 // }, // textures: { // uTexture: gl.texture( 'some-image.png' ) // }, // vertices: { // aPosition: gl.vbo([ -1, 1, 1, 1, -1, -1, 1, -1 ]) // }, // attributes: { // aTexCoord: gl.vbo([ 0, 1, 1, 1, 0, 0, 1, 0 ]) // }, // indices: gl.ibo([ 0, 1, 3, 3, 1, 2 ]) // }); // // program.draw( quad ); // mesh: function( options ) { var mesh = extend( options || {}, { mode: TRIANGLE_STRIP, attributes: {}, uniforms: {}, textures: {}, indices: null, vertices: { /* programAttributeName: VBO */ } }); return mesh; } }); } }; // // Internal // -------------------------------------------------- // // Constants and helper methods, not exposed via the API // var EMPTY_PIXEL = new Uint8Array([ 0, 0, 0, 0 ]); var PRECISION = '#ifdef GL_ES\nprecision mediump float;\n#endif'; var ATTRIBUTE = /attribute\s+(\w+)\s+([\w_-]+)/gi; var UNIFORM = /uniform\s+(\w+)\s+([\w_-]+)(\[(\s+)?([\w_-]+))?/gi; var COMMENT = /(\/\/.+|\/\*[^(\*\/)]+\*\/)/i; /* Enumeration */ var ELEMENT_ARRAY_BUFFER = 34963; var LINEAR_MIPMAP_LINEAR = 9987; var UNPACK_FLIP_Y_WEBGL = 37440; var TEXTURE_MAG_FILTER = 10240; var TEXTURE_MIN_FILTER = 10241; var COLOR_ATTACHMENT0 = 36064; var FRAGMENT_SHADER = 35632; var COMPILE_STATUS = 35713; var UNSIGNED_SHORT = 5123; var TEXTURE_WRAP_S = 10242; var TEXTURE_WRAP_T = 10243; var TRIANGLE_STRIP = 5; var CLAMP_TO_EDGE = 33071; var UNSIGNED_BYTE = 5121; var VERTEX_SHADER = 35633; var ARRAY_BUFFER = 34962; var FRAMEBUFFER = 36160; var STATIC_DRAW = 35044; var LINK_STATUS = 35714; var TEXTURE_2D = 3553; var TRIANGLES = 4; var TEXTURE0 = 33984; var NEAREST = 9728; var LINEAR = 9729; var FLOAT = 5126; var RGBA = 6408; var INT = 5124; /* Utils */ var define = Object.defineProperty; /* Merge properties of `source` into `target` */ function extend( target, source, overwrite ) { for ( var key in source ) if ( overwrite || ( !( key in target ) || !exists( target[ key ] ) ) ) target[ key ] = source[ key ]; return target; } /* Checks whether an object has been defined */ function exists( object ) { return object != null; } /* Checks whether a number is power of two */ function isPowerOf2( value ) { return ( value & ( value - 1 ) ) === 0; } /* Load an image from a given path and fire a callback when ready */ function loadImage( path, callback ) { var image = new Image(); image.onload = function() { callback( image ); }; image.src = path; } /* Returns the name of the uniform setter method for a uniform type, for example a type of `vec2` would yield `uniform2f` */ function uniformMethod( type, span ) { return 'uniform{m}{d}{t}{a}' .replace( '{m}', /mat/i.test( type ) ? 'Matrix' : '' ) .replace( '{d}', /\d$/.test( type ) ? type.match( /\d$/ )[0] : 1 ) .replace( '{t}', /^[bis]/i.test( type ) ? 'i' : 'f' ) .replace( '{a}', span > 0 ? 'v' : '' ); } /* Returns the size (number of dimensions) of an object type */ function getSize( type ) { return /\d/.test( type ) ? parseInt( type.match( /\d$/ )[0], 10 ) : 1; } /* Returns the WebGL datatype of an object type (e.g vec3 -> gl.FLOAT) */ function getType( type ) { return /^[bi]/i.test( type ) ? INT : FLOAT; } /* Returns a string representing the type of object provided @see http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ */ function toType( obj ) { return ({}).toString.call( obj ).match( /\s([a-zA-Z0-9]+)/ )[1].toLowerCase(); } /* Highlights GLSL code and the location of an error therein */ function logShaderError( error, source ) { var line = /\d+:(\d+)/g.exec( error ); if ( line ) { line = parseInt( line[1], 10 ) - 1; source = source.split( '\n' ); console.log( '%c' + source.splice( 0, line ).join( '\n' ) + '%c' + '\n' + source[ 0 ] + '\n' + '%c' + source.splice( 1 ).join( '\n' ), 'color: #ccc', 'color: red', 'color: #ccc' ); } throw error; } // ##### Finally, return the API return GL; })(); var Shaders = Shaders || {}; Shaders.Glitch = {}; Shaders.Glitch.VertexShader = [ 'attribute vec2 aPosition;', 'attribute vec2 aTexCoord;', 'varying vec2 vTexCoord;', 'void main() {', 'gl_Position = vec4( aPosition, 0, 1 );', 'vTexCoord = aTexCoord;', '}' ].join('\n'); Shaders.Glitch.FragmentShader = [ 'uniform sampler2D uTexture;', 'uniform sampler2D uOffsets;', 'varying vec2 vTexCoord;', 'uniform int uSkip;', 'uniform float uAmount;', 'uniform float uAngle;', 'uniform float uSeed;', 'uniform float uSeedX;', 'uniform float uSeedY;', 'uniform float uDistortionX;', 'uniform float uDistortionY;', 'uniform float uColS;', 'float rand(vec2 co){', 'return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);', '}', 'void main() {', 'vec4 texel = texture2D( uTexture, vTexCoord );', 'gl_FragColor = texel;', 'if (uSkip < 1) {', 'vec2 p = vTexCoord;', 'float xs = floor(gl_FragCoord.x / 0.5);', 'float ys = floor(gl_FragCoord.y / 0.5);', '//based on staffantans glitch shader for unity https://github.com/staffantan/unityglitch', 'vec4 normal = texture2D(uOffsets, p * uSeed * uSeed);', 'if (p.y < uDistortionX + uColS && p.y > uDistortionX - uColS * uSeed) {', 'if(uSeedX > 0.0){', 'p.y = 1.0 - (p.y + uDistortionY);', '}', 'else {', 'p.y = uDistortionY;', '}', '}', 'if (p.x < uDistortionY + uColS && p.x > uDistortionY - uColS * uSeed) {', 'if (uSeedY > 0.0){', 'p.x = uDistortionX;', '}', 'else {', 'p.x = 1. - (p.x + uDistortionX);', '}', '}', 'p.x += normal.x * uSeedX * (uSeed /5.0);', 'p.y += normal.y * uSeedY * (uSeed /5.0);', '//base from RGB shift shader', 'vec2 offset = uAmount * vec2( cos(uAngle), sin(uAngle) );', 'vec4 cr = texture2D(uTexture, p + offset);', 'vec4 cga = texture2D(uTexture, p);', 'vec4 cb = texture2D(uTexture, p - offset);', 'gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);', '}', 'else {', 'gl_FragColor = texture2D(uTexture, vTexCoord);', '}', '}', ].join('\n'); function GlitchFx() { this.domElement = document.createElement('div'); this.domElement.className = 'glitch'; this.bindMethods(); this.setupContext(); this.render(); this.enabled = true; this.glitchFrames = 0; this.glitching = false; // GlitchFx settings... // Chance of switching glitch effect on when off. this.onProbability = 0.005; // Chance of switching glitch effect off when on. this.offProbability = 0.2; // Minimum frames to glitch for. this.minGlitchedFrames = 5; // Maximum frames to glitch for. this.maxGlitchedFrames = 30; // Chance of updating distortion values. this.distortionProbability = 0.35; // Maximum seed value (signed, e.g. between -n and n) this.maxSeedValue = 0.2; // Maximum distortion. this.maxDistortion = 0.2; // Smoothing applied to random values of `uAmount` uniform. this.strengthDivisor = 60; } GlitchFx.prototype.enable = function() { this.enabled = true; } GlitchFx.prototype.disable = function() { if (this.enabled) { this.enabled = false; this.updateProgramUniforms(); this.program.draw(this.mesh); } } GlitchFx.prototype.bindMethods = function() { this.onImageLoaded = this.onImageLoaded.bind(this); this.resize = this.resize.bind(this); this.render = this.render.bind(this); } GlitchFx.prototype.setupContext = function() { try { // Attempt to create a GL context. this.canvas = document.createElement('canvas'); this.context = GL.create(this.canvas); this.domElement.appendChild(this.canvas); this.hasWebGL = true; } catch (error) { this.hasWebGL = false; } if (this.hasWebGL) { // We can't use background cover, so compute manually on resize. window.addEventListener('resize', this.resize, false); // If WebGL is supported, set up the context. this.enableWebGLExtensions(); this.program = this.context.program( Shaders.Glitch.VertexShader, Shaders.Glitch.FragmentShader ); this.texture = this.context.texture(); this.mesh = this.createQuadMesh(); this.setupProgramUniforms(); this.frame = 0; } } GlitchFx.prototype.createQuadMesh = function() { return this.context.mesh({ textures: { uTexture: this.texture, uOffsets: this.generateHeightMap(64) }, vertices: { aPosition: this.createScreenSpaceQuad() }, attributes: { aTexCoord: this.createUVCoordinates() } }); } GlitchFx.prototype.createScreenSpaceQuad = function() { return this.context.vbo([ -1, 1, 1, 1, -1, -1, 1, -1 ]) } GlitchFx.prototype.createUVCoordinates = function() { return this.context.vbo([ 0, 1, 1, 1, 0, 0, 1, 0 ]); } GlitchFx.prototype.enableWebGLExtensions = function() { this.context.getExtension('OES_texture_float'); this.context.getExtension('OES_half_float_linear'); this.context.getExtension('OES_float_linear'); } GlitchFx.prototype.setupProgramUniforms = function(arguments) { this.program.uSkip.set(1); this.program.uAmount.set(0.01); this.program.uAngle.set(0.01); this.program.uSeed.set(0.01); this.program.uSeedX.set(0.01); this.program.uSeedY.set(0.01); this.program.uDistortionX.set(0.1); this.program.uDistortionY.set(0.1); this.program.uColS.set(0.1); this.generateTrigger(); } GlitchFx.prototype.updateProgramUniforms = function() { if (!this.enabled) { this.glitching = false; this.program.uSkip.set(1); return; } if (this.glitching) { this.program.uSeed.set(Math.random()); this.program.uSkip.set(0); this.program.uAmount.set(Math.random() / this.strengthDivisor); this.program.uAngle.set(this.randomFloat(-Math.PI, Math.PI)); this.program.uSeedX.set(this.randomFloat(-this.maxSeedValue, this.maxSeedValue)); this.program.uSeedY.set(this.randomFloat(-this.maxSeedValue, this.maxSeedValue)); if (Math.random() < this.distortionProbability) { this.program.uDistortionX.set(this.randomFloat(0, this.maxDistortion)); this.program.uDistortionY.set(this.randomFloat(0, this.maxDistortion)); } if (this.glitchFrames > this.minGlitchedFrames) { if (this.glitchFrames > this.maxGlitchedFrames || Math.random() < this.offProbability) { this.program.uSkip.set(1); this.glitching = false; } } this.glitchFrames++; } else { this.glitching = Math.random() < this.onProbability; this.glitchFrames = 0; } this.frame++; } GlitchFx.prototype.generateHeightMap = function(size) { // Fill a Float buffer with 3 channels worth of data (RGB). var data = new Float32Array( size * size * 3 ); var length = size * size; for ( var value, index, i = 0; i < length; i++ ) { index = i * 3; value = Math.random(); data[ index ] = value; data[ index + 1 ] = value; data[ index + 2 ] = value; } return this.context.texture(data, size, size, { format: this.context.RGB, mipmap: false, min: this.context.NEAREST, mag: this.context.NEAREST, s: this.context.REPEAT, t: this.context.REPEAT }); } GlitchFx.prototype.generateTrigger = function() { this.randX = Math.floor(this.randomFloat(120, 240)); } GlitchFx.prototype.randomFloat = function(min, max) { if (typeof max == 'undefined') { max = min; min = 0; } return min + Math.random() * (max - min); } // TODO: This mimics contain and not cover. // TODO: Call during view project tween. GlitchFx.prototype.resize = function() { // var bounds = this.domElement.getBoundingClientRect(); var ratio1 = this.domElement.offsetWidth / this.domElement.offsetHeight; var ratio2 = this.image.width / this.image.height; var landscape = ratio1 < ratio2; // this.canvas.style.height = landscape ? '100%' : 'auto'; // this.canvas.style.width = landscape ? 'auto' : '100%'; } GlitchFx.prototype.render = function() { requestAnimationFrame(this.render); if (this.enabled) { this.updateProgramUniforms(); this.program.draw(this.mesh); } } GlitchFx.prototype.setImagePath = function(path, with_bg) { // Always set the background image as a fallback. if ( with_bg == undefined ) { with_bg = true; } if (with_bg) this.domElement.style.backgroundImage = 'url(' + path + ')'; if (this.hasWebGL) { this.image = new Image(); this.image.onload = this.onImageLoaded; this.image.src = path; } } GlitchFx.prototype.onImageLoaded = function() { this.context.size(this.image.width, this.image.height); this.texture.set(this.image); this.resize(); }