Skip to content

Instantly share code, notes, and snippets.

@johndigital
Created October 3, 2019 15:55
Show Gist options
  • Save johndigital/026f333d4ae6bdd6f7081275c3c84eed to your computer and use it in GitHub Desktop.
Save johndigital/026f333d4ae6bdd6f7081275c3c84eed to your computer and use it in GitHub Desktop.
<template>
<div class="shared-gradient-playground">
<fragment-shader :uniforms="uniforms" :timescale="60">
<script type="shader/fragment">
precision highp float;
uniform vec2 uResolution;
uniform float uTime;
uniform vec3 color1;
uniform vec3 color2;
uniform vec3 color3;
uniform float seed;
uniform float rotation;
#include <snoise>
#include <rotate2d>
void main() {
vec2 uv = gl_FragCoord.xy / uResolution.xy;
// uv.x *= uResolution.x / uResolution.y;
// rotate UV
// see https://thebookofshaders.com/08/
uv -= vec2(0.5);
uv *= rotate2d(rotation);
uv += vec2(0.5);
// add 1 to uTime to ensure we're never at 0
float t = seed + (uTime + 10.) * 0.002;
// zoom in a bit - make the blobs larger
uv *= 0.4;
vec4 final = vec4(1.);
float lowBound = 0.5;
float highBound = 1.;
float noise1 = smoothstep(lowBound, highBound, (snoise((uv + vec2(-0.5, 0.) + t)) + 1.) / 2.);
final = mix(final, vec4(color1, 1.), noise1);
float noise2 = smoothstep(lowBound, highBound, (snoise((uv - t * 0.2)) + 1.) / 2.);
final = mix(final, vec4(color2, 1.), noise2);
float noise3 = smoothstep(lowBound, highBound, (snoise(uv + t + vec2(-0.3, 0.)) + 1.) / 2.);
final = mix(final, vec4(color3, 1.), noise3);
gl_FragColor = final;
}
</script>
</fragment-shader>
</div>
</template>
<script>
import { lerp } from '~/libs/utilities'
import { transform, tween } from 'popmotion'
const { wrap, interpolate } = transform
import Vue from 'vue'
let inProgress
export default {
data() {
return {
// key-value object consisting of route name
// and array of 0-1 colors for background colors
colors: {
index: [
[0.639, 0.996, 0.862],
[0.961, 0.933, 0.353],
[0.968, 0.89, 0.773]
],
'how-suki-works': [
[1, 0.949, 0.169],
[0.972, 0.78, 0.569],
[0.902, 0.965, 0.925]
],
slug: [
[0.059, 0.726, 0.804],
[1, 0.655, 0.525],
[1, 0.655, 0.145]
],
'for-surgeons': [
[0.902, 0.953, 0.894],
[0.965, 0.941, 0.329],
[0.989, 0.741, 0.38]
],
pricing: [
[1, 0.624, 0.067],
[0.984, 0.827, 0.769],
[0.729, 0.98, 0.914]
]
},
displayColors: [],
rotation: 0,
seed: Math.random() * 100 - 50
}
},
mounted() {
this.displayColors = [...this.cmpColors]
},
computed: {
uniforms() {
return {
color1: this.color1,
color2: this.color2,
color3: this.color3,
seed: { type: 'float', value: this.seed },
rotation: { type: 'float', value: this.rotation }
}
},
color1() {
return {
type: 'vec3',
value: _get(this, 'displayColors[0]', [1, 1, 1])
}
},
color2() {
return {
type: 'vec3',
value: _get(this, 'displayColors[1]', [1, 1, 1])
}
},
color3() {
return {
type: 'vec3',
value: _get(this, 'displayColors[2]', [1, 1, 1])
}
},
cmpColors() {
return this.colors[this.$route.name]
? this.colors[this.$route.name]
: this.colors.index
}
},
watch: {
'$route.name'(newVal) {
if (inProgress && inProgress.length) {
inProgress.map(ip => ip.stop())
}
inProgress = this.displayColors.map((v, i) => {
return tween({
from: v,
to: this.cmpColors[i],
duration: 2000
}).start(v => {
Vue.set(this.displayColors, i, v)
})
})
inProgress.push(
tween({
from: this.rotation,
to: (Math.random() * 2 - 1) * Math.PI,
duration: 2000
}).start(v => (this.rotation = v))
)
}
}
}
</script>
<style lang="scss">
.shared-gradient-playground {
@include fill(fixed);
width: 100%;
height: 100%;
z-index: -1;
--border-color: white;
.canvas {
@include fill(fixed);
width: 100%;
height: 100%;
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment