Hadil66 / portfolio.V1

https://portfolio-v1-six-mauve.vercel.app
0 stars 0 forks source link

Ripple effect met WebGL #10

Closed Hadil66 closed 3 weeks ago

Hadil66 commented 3 weeks ago

Het eerste wat ik heb gedaan is KodeLife gedowndload en een tutorial gevolgd voor het maken van een shader. Ik kwam er later achter dat de tutorial verouderd was. Ik heb toen de oorspronkelijke code van KodeLife gebruikt. Ik heb de kleuren van de shaders aangepast naar de kleueren uit mijn kleurenpalette.

Image

      vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
        float dist = length(uv);

        vec3 color1 = vec3(0.663, 0.804, 0.369);  // (#A9CD5E)
        vec3 color2 = vec3(0.937, 0.427, 0.600);  // (#EF6D99)
        vec3 color3 = vec3(0.953, 0.863, 0.800);  // (#F3DCCC)

        vec3 dynamicColor = mix(color1, color2, abs(sin(time + dist * 7.0)));
        dynamicColor = mix(dynamicColor, color3, abs(cos(time + dist * 3.0)));

        gl_FragColor = vec4(dynamicColor, 1.0);

in sveltekit implementeren shader.svelte en shader.js

Ik probeerde een Library, glslCanvas, te gebruiken, maar kreeg een window not defined error

Daarom heb ik direct met WebGL gewerkt waardoor ik mijn code moest omzetten.

import { onMount } from 'svelte';

let canvas;
let gl;

vertexShader: berekent posities van de punten in de 3D-ruimte,

fragmentShader: bepaalt de kleur en andere eigenschappen van pixels.

const vertexShaderSource = `
    attribute vec4 a_position;
    void main() {
        gl_Position = a_position;
    }
`;

time zorgt voor animatie over tijd, en resolution zorgt ervoor dat de fragment shader zich kan aanpassen aan de schermgrootte.

const fragmentShaderSource = `
    precision mediump float;

    uniform float time;
    uniform vec2 resolution;

Door dist te berekenen (de afstand van het middelpunt), en sin en cos te gebruiken op basis van time, krijg je dynamische kleurveranderingen over tijd. De mix-functie zorgt voor een vloeiende overgang tussen drie kleuren

function createShader(type, source) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        return shader;
    } else {
        console.error('Shader failed to compile:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
    }
}

function createProgram(vertexShader, fragmentShader) {
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    return program;
}

De postitionBuffer is nodig om WebGL de coördinaten van de hoekpunten te geven en een rechthoek op het canvas te tekenen.

uniform is nodig om de shader de canvasgrootte te laten kennen, zodat effecten op schaal kunnen worden toegepast.

function initializeShader(canvasElement) {
    canvas = canvasElement;
    gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    if (!gl) {
        console.error('WebGL is not supported');
        return;
    }

    const vertexShader = createShader(gl.VERTEX_SHADER, vertexShaderSource);
    const fragmentShader = createShader(gl.FRAGMENT_SHADER, fragmentShaderSource);

    const program = createProgram(vertexShader, fragmentShader);
    gl.useProgram(program);

    const positionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    const positions = new Float32Array([
        -1, -1,
         1, -1,
        -1,  1,
        -1,  1,
         1, -1,
         1,  1,
    ]);
    gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);

    const positionLocation = gl.getAttribLocation(program, 'a_position');
    gl.enableVertexAttribArray(positionLocation);
    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

    const resolutionLocation = gl.getUniformLocation(program, 'resolution');
    gl.uniform2f(resolutionLocation, canvas.width, canvas.height);

    updateShaderTime();
}