commit 7731836f6a3127253e7129ae55a68652232f4579 Author: stitchy Date: Tue Dec 17 07:20:25 2024 +0000 initial commit Currently has a working website with half of two images displayed. Please find your own images diff --git a/frag.shader b/frag.shader new file mode 100644 index 0000000..ffa7b1e --- /dev/null +++ b/frag.shader @@ -0,0 +1,25 @@ +#version 300 es +precision highp float; + +// Inputs +in vec2 texture_coordinates; +uniform float time; +uniform sampler2D uSampler1; +uniform sampler2D uSampler2; + +// Output +out vec4 color; + +const float PI = 3.1415; + +void main() { + + if ((texture_coordinates.x + texture_coordinates.y) > 1.) { + color = texture(uSampler1, texture_coordinates); + } + else { + color = texture(uSampler2, texture_coordinates); + } + + // color = vec4( texture_coordinates, (sin( time * PI) + 1.)/2. , 1.); +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..290c63e --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + Shaders are Fun + + + + + + + diff --git a/shader.mjs b/shader.mjs new file mode 100644 index 0000000..8e7d09a --- /dev/null +++ b/shader.mjs @@ -0,0 +1,140 @@ +const CANVAS_WIDTH = 300; +const CANVAS_HEIGHT = 300; +let TIME = 0; + +// ** Initialization stuffs ** // + +async function initShader() { + // Get GL contexts and stuffs + const canvas = document.getElementById("shader"); + const gl = canvas.getContext("webgl2"); + + canvas.width = CANVAS_WIDTH; + canvas.height = CANVAS_HEIGHT; + + gl.viewport(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); + + // Create Vertex Array + const vao = gl.createVertexArray(); + gl.bindVertexArray(vao); + + // manipulating bitfield for canvas + gl.clearColor(1, 1, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + + // Array of verticies for gpu to render + const verticies = new Float32Array([ + -1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, + ]); + + // Managing the pixel buffer + const buf = gl.createBuffer(); + + gl.bindBuffer(gl.ARRAY_BUFFER, buf); + gl.bufferData(gl.ARRAY_BUFFER, verticies, gl.STATIC_DRAW); + + // fetch shaders + const vert_shader = await fetch_local("./vert.shader"); + const frag_shader = await fetch_local("./frag.shader"); + + // Compile Shaders + const vert = compileShader(vert_shader, gl.VERTEX_SHADER, gl); + const frag = compileShader(frag_shader, gl.FRAGMENT_SHADER, gl); + + // Link shaders into program + const program = gl.createProgram(); + + gl.attachShader(program, vert); + gl.attachShader(program, frag); + + gl.linkProgram(program); + + // Check errors + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + const info = gl.getProgramInfoLog(program); + throw `bitch you messed up\n\n${info}`; + } + + // Set this as the program that is used to render + gl.useProgram(program); + + // assign shader variables + const vert_pos_loc = gl.getAttribLocation(program, "vertex_position"); + gl.enableVertexAttribArray(vert_pos_loc); + + gl.vertexAttribPointer(vert_pos_loc, 2, gl.FLOAT, true, 0, 0); + + // Load Textures + loadTexture(gl, "./favicon.ico", gl.TEXTURE0); + const tex1_attr = gl.getUniformLocation(program, "uSampler1"); + gl.uniform1i(tex1_attr, 0); + loadTexture(gl, "./brain.webp", gl.TEXTURE1); + const tex2_attr = gl.getUniformLocation(program, "uSampler2"); + gl.uniform1i(tex2_attr, 1); + + return [gl, program]; +} + +// Compile Shader Function +function compileShader(source, type, gl) { + // Set up shader + const shader = gl.createShader(type); + gl.shaderSource(shader, source); + + // compile the shaders + gl.compileShader(shader); + + return shader; +} + +// fetch local source as a text string +async function fetch_local(src) { + const res = await fetch(src); + return await res.text(); +} + +// update the canvas +function draw(gl, program) { + // Create uniform + const loc = gl.getUniformLocation(program, "time"); + TIME += 1 / 60; + gl.uniform1f(loc, TIME); + + // Draw the frame recursively on next frame + gl.drawArrays(gl.TRIANGLES, 0, 6); + requestAnimationFrame(() => draw(gl, program)); +} + +// Initialize the shader +const [gl, program] = await initShader(); + +function loadTexture(gl, url, gl_tex) { + // Create texture + const texture = gl.createTexture(); + gl.activeTexture(gl_tex); + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Create the javascript image + const image = new Image(); + image.onload = () => { + // Create GL Texture Buffer + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + }; + + image.src = url; + + // gl.NEAREST is also allowed, instead of gl.LINEAR, as neither mipmap. + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + // Prevents s-coordinate wrapping (repeating). + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + // Prevents t-coordinate wrapping (repeating). + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + + return texture; +} + +// Update loop +draw(gl, program); diff --git a/vert.shader b/vert.shader new file mode 100644 index 0000000..80f0411 --- /dev/null +++ b/vert.shader @@ -0,0 +1,13 @@ +#version 300 es +precision highp float; + +in vec2 vertex_position; +out vec2 texture_coordinates; + + + +void main() { + + gl_Position = vec4( vertex_position, 0.5, 1.0 ); + texture_coordinates = vec2( (vertex_position + vec2(1.0) ) / 2.0 ); +}