Skip to content

Instantly share code, notes, and snippets.

@jesperlandberg
Created July 23, 2020 19:58
Show Gist options
  • Select an option

  • Save jesperlandberg/680ee1b5846e764cce500d351b619cfc to your computer and use it in GitHub Desktop.

Select an option

Save jesperlandberg/680ee1b5846e764cce500d351b619cfc to your computer and use it in GitHub Desktop.
precision highp float;
precision highp int;
uniform sampler2D uTexture;
uniform float uAlpha;
uniform float uProgress;
uniform float uScale;
uniform vec2 uRes;
uniform vec2 uSize;
varying vec2 vUv;
varying vec2 vScale;
varying float vRipple;
vec2 backgroundCoverUv( vec2 screenSize, vec2 imageSize, vec2 uv ) {
float screenRatio = screenSize.x / screenSize.y;
float imageRatio = imageSize.x / imageSize.y;
vec2 newSize = screenRatio < imageRatio
? vec2(imageSize.x * (screenSize.y / imageSize.y), screenSize.y)
: vec2(screenSize.x, imageSize.y * (screenSize.x / imageSize.x));
vec2 newOffset = (screenRatio < imageRatio
? vec2((newSize.x - screenSize.x) / 2.0, 0.0)
: vec2(0.0, (newSize.y - screenSize.y) / 2.0)) / newSize;
return uv * screenSize / newSize + newOffset;
}
vec2 scale(vec2 uv, float p, float a) {
return uv * (a + (p * a)) + ((a * .5) * (1. - p));
}
float shadow(float p, float a) {
return (a + (p * a)) + ((a * .5) * (1. - p));
}
vec4 transparent = vec4(1., 1., 1., 0);
void main() {
vec2 uv = vUv;
vec2 uvS = vUv;
vec2 scaledPlane = uRes * vScale;
uv = scale(uv, uScale, 0.5);
uv = backgroundCoverUv(scaledPlane, uSize, uv);
vec4 texture = texture2D(uTexture, uv);
float t = step(uvS.y, uScale);
vec4 color = mix(transparent, texture, t);
if (vRipple > 0.) {
gl_FragColor = color * shadow(1. + (vRipple * 0.25), 0.5);
} else {
gl_FragColor = color;
}
}
import {
Mesh,
Plane,
Program,
Texture,
Vec2
} from '@/lib/ogl'
import gsap from 'gsap'
import Core from '../Core'
import Elem from '../Elem'
import Pool from '../Pool'
import vertex from '@/gl/shaders/video/vert.vert'
import fragment from '@/gl/shaders/video/frag.frag'
import { evt, store } from '@/app/index'
const { bounds, dom } = store
export default class extends Elem {
init(args) {
const { gl } = Core
super.init(args)
this.geometry = new Plane(gl, {widthSegments: 15, heightSegments: 15})
this.texture = new Texture(gl, {
generateMipmaps: false,
minFilter: gl.LINEAR,
})
const img = new Image()
img.crossOrigin = '*'
img.src = this.el.dataset.src
img.decode().then(() => {
this.texture.image = img
this.program.uniforms.uSize.value.x = img.naturalWidth
this.program.uniforms.uSize.value.y = img.naturalHeight
})
this.program = new Program(gl, {
vertex,
fragment,
uniforms: {
uTexture: { value: this.texture },
uViewSize: { value: new Vec2(bounds.ww, bounds.wh) },
uRes: { value: new Vec2(this.bounds.width, this.bounds.height) },
uPos: { value: new Vec2(this.position.x, this.position.y) },
uSize: { value: new Vec2(1, 1) },
uScaleProgress: { value: 0 },
uScale: { value: 1 },
uStrength: { value: 0 },
uAlpha: { value: 1 },
},
cullFace: null,
depthTest: false
})
this.mesh = new Mesh(gl, {
geometry: this.geometry,
program: this.program,
})
this.addChild(this.mesh)
Pool.group.addChild(this)
Pool.planes[this.name] = this
this.tl = gsap.timeline({
paused: true
})
this.onAdd()
}
onAdd() {
gsap.timeline({
scrollTrigger: {
trigger: this.el,
once: true
}
})
.fromTo(this.program.uniforms.uScale, {
value: 0
}, {
value: 1,
duration: 2,
ease: 'expo'
})
}
resize() {
super.resize()
const { uRes, uPos, uViewSize } = this.program.uniforms
const { width, height } = this.bounds
const { x, y } = this.position
uRes.value.x = width
uRes.value.y = height
uPos.value.x = x
uPos.value.y = y
uViewSize.value.x = bounds.ww
uViewSize.value.y = bounds.wh
}
toFS(from, done) {
const { uPos, uScaleProgress, uStrength }
= this.program.uniforms
this.tl.clear()
.set(uPos.value, {
x: this.position.x,
y: this.position.y
})
.to(uScaleProgress, {
value: 1,
duration: 2,
ease: 'power3.inOut'
}, 0)
.to(uStrength, {
value: 1,
duration: 2,
ease: 'power1.inOut'
}, 0)
.add(() => {
evt.emit('transition:title-in')
}, 1)
.add(() => {
from.remove()
dom.scroll.scrollTop = 0
evt.emit('raf:reset')
Pool.removePlanes(from.dataset.id)
this.horizontal = false
this.update()
this.static = false
this.keep = false
done()
})
.play()
}
destroy() {
super.destroy()
const { uScaleProgress, uStrength }
= this.program.uniforms
uScaleProgress.value = 0
uStrength.value = 0
this.mesh.renderOrder = 1
this.out = true
this.animated = false
this.single = false
this.horizontal = false
}
}
precision highp float;
precision highp int;
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform float uScaleProgress;
uniform float uStrength;
uniform vec2 uRes;
uniform vec2 uViewSize;
uniform vec2 uPos;
varying vec2 vUv;
varying vec2 vScale;
varying float vRipple;
void main(){
vec3 pos = position;
float phase = (1.0 - dot(pos.xyz, pos.xyz)) * 20.;
float ripple = (cos(phase * (uStrength * .5)) * 0.5 + 0.5) * 15.;
ripple = ripple * (1.0 - abs(uStrength * 2.0 - 1.0));
pos.z += ripple;
vec4 mPos = modelViewMatrix * vec4(pos, 1.);
float vProgress = smoothstep(0., 1., uScaleProgress);
vec2 scaleUnit = uViewSize / uRes - 1.;
vec2 scale = vec2(1. + scaleUnit * vProgress);
mPos.y += -uPos.y * vProgress;
mPos.x += -uPos.x * vProgress;
mPos.xy *= scale;
vUv = uv;
vScale = scale;
vRipple = ripple;
gl_Position = projectionMatrix * mPos;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment