#Reverse engineering a shader from a site

5 messages · Page 1 of 1 (latest)

faint current
#
const fragmentShader = `
precision highp float;

uniform vec3 color1;
uniform vec3 color2;
uniform vec3 color3;
uniform vec3 color4;
uniform float colorSize;
uniform float colorSpacing;
uniform float colorRotation;
uniform float colorSpread;
uniform float displacement;
uniform float zoom;
uniform float spacing;
uniform float seed;
uniform vec2 viewportSize;
uniform vec2 colorOffset;
uniform vec2 transformPosition;
uniform float noiseSize;
uniform float noiseIntensity;
    
in vec2 vPosition;

vec3 gradientDerivativesNoise3DHash(vec3 p)
{
    //p = 50.0 * fract(p * 0.3183099 + vec2(0.71, 0.113));
    //return -1.0 + 2.0 * fract(p.x * p.y * (p.x + p.y));

    p = fract(p * vec3(.1031, .1030, .0973));
        p += dot(p, p.yxz + 33.33);
        return fract((p.xxy + p.yxx) * p.zyx);
}
#
// return value noise (in x) and its derivatives (in yzw)
vec4 gradientDerivativesNoise3D(in vec3 x)
{
    // grid
    vec3 p = floor(x);
    vec3 w = fract(x);

    #if 1
    // quintic interpolant
    vec3 u = w * w * w * (w * (w * 6.0 - 15.0) + 10.0);
    vec3 du = 30.0 * w * w * (w * (w - 2.0) + 1.0);
    #else
    // cubic interpolant
    vec3 u = w * w * (3.0 - 2.0 * w);
    vec3 du = 6.0 * w * (1.0 - w);
    #endif    

    // gradients
    vec3 ga = gradientDerivativesNoise3DHash(p + vec3(0.0, 0.0, 0.0));
    vec3 gb = gradientDerivativesNoise3DHash(p + vec3(1.0, 0.0, 0.0));
    vec3 gc = gradientDerivativesNoise3DHash(p + vec3(0.0, 1.0, 0.0));
    vec3 gd = gradientDerivativesNoise3DHash(p + vec3(1.0, 1.0, 0.0));
    vec3 ge = gradientDerivativesNoise3DHash(p + vec3(0.0, 0.0, 1.0));
    vec3 gf = gradientDerivativesNoise3DHash(p + vec3(1.0, 0.0, 1.0));
    vec3 gg = gradientDerivativesNoise3DHash(p + vec3(0.0, 1.0, 1.0));
    vec3 gh = gradientDerivativesNoise3DHash(p + vec3(1.0, 1.0, 1.0));

    // projections
    float va = dot(ga, w - vec3(0.0, 0.0, 0.0));
    float vb = dot(gb, w - vec3(1.0, 0.0, 0.0));
    float vc = dot(gc, w - vec3(0.0, 1.0, 0.0));
    float vd = dot(gd, w - vec3(1.0, 1.0, 0.0));
    float ve = dot(ge, w - vec3(0.0, 0.0, 1.0));
    float vf = dot(gf, w - vec3(1.0, 0.0, 1.0));
    float vg = dot(gg, w - vec3(0.0, 1.0, 1.0));
    float vh = dot(gh, w - vec3(1.0, 1.0, 1.0));
#
    // interpolations
    return vec4(va + u.x * (vb - va) + u.y * (vc - va) + u.z * (ve - va) + u.x * u.y * (va - vb - vc + vd) + u.y * u.z * (va - vc - ve + vg) + u.z * u.x * (va - vb - ve + vf) + (-va + vb + vc - vd + ve - vf - vg + vh) * u.x * u.y * u.z,    // value
                ga + u.x * (gb - ga) + u.y * (gc - ga) + u.z * (ge - ga) + u.x * u.y * (ga - gb - gc + gd) + u.y * u.z * (ga - gc - ge + gg) + u.z * u.x * (ga - gb - ge + gf) + (-ga + gb + gc - gd + ge - gf - gg + gh) * u.x * u.y * u.z +   // derivatives
                du * (vec3(vb, vc, ve) - va + u.yzx * vec3(va - vb - vc + vd, va - vc - ve + vg, va - vb - ve + vf) + u.zxy * vec3(va - vb - ve + vf, va - vb - vc + vd, va - vc - ve + vg) + u.yzx * u.zxy * (-va + vb + vc - vd + ve - vf - vg + vh)));
}

float hash(vec2 p) {
    p = 50.0 * fract(p * 0.3183099 + vec2(0.71, 0.113));
    return -1.0 + 2.0 * fract(p.x * p.y * (p.x + p.y));
}

float computeNoise(in vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);
    vec2 u = f * f * (3.0 - 2.0 * f);
    return mix(mix(hash(i + vec2(0.0, 0.0)),
                   hash(i + vec2(1.0, 0.0)), u.x),
               mix(hash(i + vec2(0.0, 1.0)),
                   hash(i + vec2(1.0, 1.0)), u.x), u.y);
}

vec2 rotate(vec2 v, float a) {
    float s = sin(a);
    float c = cos(a);
    mat2 m = mat2(c, -s, s, c);
    return m * v;
}
#
void main() {
    vec2 position = vPosition;
    position.x *= min(1.0, viewportSize.x / viewportSize.y);
    position.y *= min(1.0, viewportSize.y / viewportSize.x);
    position /= zoom;
    position += transformPosition;

    vec2 noiseLocalPosition = position * 0.5 + 0.5;
    vec3 displacementNoise = gradientDerivativesNoise3D(vec3(noiseLocalPosition, seed)).xyz;

    float noise = computeNoise(vPosition * viewportSize / noiseSize);

    position += displacementNoise.xz * displacement;

    vec2 offsetedPosition = position;
    offsetedPosition -= colorOffset;
    offsetedPosition = mod(offsetedPosition - spacing, vec2(spacing * 2.0)) - spacing;
    offsetedPosition = rotate(offsetedPosition, -colorRotation);
    offsetedPosition /= vec2(colorSize, colorSize);
    offsetedPosition *= vec2(1.0 / colorSpread, 1.0);

    vec3 color = vec3(0.0);
    color = mix(color1, color, smoothstep(0.0, 1.0, distance(offsetedPosition, vec2(0.0, colorSpacing * 1.5))));
    color = mix(color2, color, smoothstep(0.0, 1.0, distance(offsetedPosition, vec2(0.0, colorSpacing * 0.5))));
    color = mix(color3, color, smoothstep(0.0, 1.0, distance(offsetedPosition, vec2(0.0, -colorSpacing * 0.5))));
    color = mix(color4, color, smoothstep(0.0, 1.0, distance(offsetedPosition, vec2(0.0, -colorSpacing * 1.5))));
    
    color += noise * noiseIntensity;
    color = clamp(color, 0.0, 1.0);

    gl_FragColor = vec4(color, 1.0);
    //gl_FragColor = vec4(0.6, 0.5, 0.5, 1.0);
}

If I output the uncommented //gl_FragColor = vec4(0.6, 0.5, 0.5, 1.0) , it displays a flat colour just fine

#

The uniforms I'm using for the fragmentShader are as follows:

this.gradientEffect = {
    uniforms: {
        "color1": { value: new THREE.Vector3(0.604,0.302,0.2) },
        "color2": { value: new THREE.Vector3(0.996,0.663,0.) },
        "color3": { value: new THREE.Vector3(0.996,0.663,0.) },
        "color4": { value: new THREE.Vector3(0.608,0.788,0.608) },
        "colorSize": { value: 0.0 },
        "colorSpread": { value: 4.52},
        "colorSpacing": { value: 0.52 },
        "colorRotation": { value: -0.381592653589793 },
        "colorOffset": { value: new THREE.Vector2(-0.7741174697875977,-0.20644775390624992) },
        "displacement": { value: 0.1 },
        "seed": { value: -0.9 },
        "position": { value: new THREE.Vector2(-0.2816110610961914,-0.43914794921875) },
        "zoom": { value: 0.72 },
        "spacing": { value: 4.27 },
        "noiseIntensity": {value: .04 },
        "noiseSize": {value: .5 },
        "viewportSize": {value: new THREE.Vector2(window.innerWidth, window.innerHeight)},
        "transformPosition": {value: new THREE.Vector2(0.125, 0.059)}
    },
    vertexShader: vertexShader,
    fragmentShader: fragmentShader
}

Some of these values are retrieved from the site itself: https://monopo.london/ , I've just hardcoded them there, although I'm not sure what transformPosition does yet exactly
If you check the element inspector the values are shown there

We are a design-driven creative agency working across branding, digital design and communications. Based in London, born in Tokyo.