From 36d9ac42304f37f974fd642b771c4a08e896a0e6 Mon Sep 17 00:00:00 2001 From: EpicKiwi Date: Sun, 2 Aug 2026 15:12:30 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20la=20vid=C3=A9o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/cuteTexture.js | 78 ++++++++++++++++++++++++++++++++++++++-- status/index.fermé.html | 7 ++-- status/index.ouvert.html | 26 +++++++++----- 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/js/cuteTexture.js b/js/cuteTexture.js index ed08a51..85adc8e 100644 --- a/js/cuteTexture.js +++ b/js/cuteTexture.js @@ -73,10 +73,16 @@ const FRAGMENT_SHADER_UTILITIES = ` return vec3(HCV.x, S, L); } - highp vec3 hue_rotate(highp vec3 rgb_input, highp float amount) { - highp vec3 hsl = rgb_to_hsl(rgb_input); + highp vec4 hue_rotate(highp vec4 rgb_input, highp float amount) { + highp vec3 hsl = rgb_to_hsl(rgb_input.xyz); hsl.x = mod(hsl.x+amount,1.0); - return hsl_to_rgb(hsl); + return vec4(hsl_to_rgb(hsl), rgb_input.w); + } + + highp vec4 grayscale(highp vec4 rgb_input, highp float amount) { + highp vec3 hsl = rgb_to_hsl(rgb_input.xyz); + hsl.y = 1.0 - amount; + return vec4(hsl_to_rgb(hsl), rgb_input.w); } ` @@ -89,6 +95,10 @@ const DEFAULT_FRAGMENT_SHADER = ` uniform lowp vec2 uCanvasSize; // Number of seconds since canvas was initialized uniform lowp float uTime; + // Current frame of first video with [data-cute-texture-video] attribute + uniform sampler2D uVideo; + // Size (in pixels) of current video frame in uVideo + uniform lowp vec2 uVideoSize; // Coordinates of current pixel being computed from [0,0] (top left) to [1,1] (bottom right) varying highp vec2 vTextureCoord; @@ -195,6 +205,30 @@ function initMainShader(ctx, oldShader=null){ return null } + let videoElement, videoTexture = null; + if(ctx.getUniformLocation(shaderProgram, "uVideo") != null){ + videoElement = document.querySelector("video[data-cute-texture-video]") || document.querySelector("video"); + if(!videoElement){ + console.warn("Aucune vidéo avec l'attribut [data-cute-texture-video] n'a été trouvé sur la page"); + } else { + videoTexture = ctx.createTexture(); + ctx.bindTexture(ctx.TEXTURE_2D, videoTexture) + ctx.texImage2D( + ctx.TEXTURE_2D, + 0, + ctx.RGBA, + 1, 1, + 0, + ctx.RGBA, + ctx.UNSIGNED_BYTE, + new Uint8Array([0, 0, 0, 255]) + ) + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE); + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE); + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR); + } + } + if(oldShader){ ctx.deleteProgram(oldShader.program) ctx.deleteShader(oldShader.vertexShader) @@ -211,10 +245,14 @@ function initMainShader(ctx, oldShader=null){ vertexShader, fragmentShader, fragmentShaderElement: fragmentShaderCodeElement, + videoElement, + videoTexture, aVertexIndex: ctx.getAttribLocation(shaderProgram, "aVertexIndex"), uRandom: ctx.getUniformLocation(shaderProgram, "uRandom"), uCanvasSize: ctx.getUniformLocation(shaderProgram, "uCanvasSize"), uTime: ctx.getUniformLocation(shaderProgram, "uTime"), + uVideo: ctx.getUniformLocation(shaderProgram, "uVideo"), + uVideoSize: ctx.getUniformLocation(shaderProgram, "uVideoSize"), vertexIndexBuffer, } } @@ -269,6 +307,40 @@ function renderCuteTexture(target, mainShader, initTime){ (Date.now() - initTime)/1000 ) } + + if(mainShader.uVideo){ + ctx.activeTexture(ctx.TEXTURE0); + ctx.bindTexture(ctx.TEXTURE_2D, mainShader.videoTexture); + ctx.uniform1i( + mainShader.uVideo, + 0 + ) + } + + if(mainShader.uVideo && mainShader.videoElement && mainShader.videoTexture){ + ctx.activeTexture(ctx.TEXTURE0); + ctx.bindTexture(ctx.TEXTURE_2D, mainShader.videoTexture); + ctx.texImage2D( + ctx.TEXTURE_2D, + 0, + ctx.RGBA, + ctx.RGBA, + ctx.UNSIGNED_BYTE, + mainShader.videoElement, + ); + ctx.uniform1i( + mainShader.uVideo, + 0 + ) + } + + if(mainShader.uVideoSize && mainShader.videoElement) { + ctx.uniform2f( + mainShader.uVideoSize, + mainShader.videoElement.videoWidth, + mainShader.videoElement.videoHeight + ) + } ctx.drawArrays(ctx.TRIANGLE_STRIP, 0, 3); } \ No newline at end of file diff --git a/status/index.fermé.html b/status/index.fermé.html index 3c171e8..48eea8b 100644 --- a/status/index.fermé.html +++ b/status/index.fermé.html @@ -32,13 +32,14 @@ void main() { highp float lum = (noise1(uRandom.yz+coords) * 0.631372549); lowp float opacity = 0.5; - highp vec3 baseColor = vec3( + highp vec4 baseColor = vec4( 0.0, lum, - lum + lum, + 1.0 ); - highp vec3 rotatedColor = hue_rotate(baseColor, 13.12); + highp vec4 rotatedColor = hue_rotate(baseColor, 13.12); gl_FragColor = vec4( rotatedColor.x*opacity, diff --git a/status/index.ouvert.html b/status/index.ouvert.html index 5b6cfbc..4eb5b6e 100644 --- a/status/index.ouvert.html +++ b/status/index.ouvert.html @@ -11,6 +11,7 @@ Le LOL est Ouvert +
@@ -26,6 +27,8 @@ uniform highp vec4 uRandom; uniform highp vec2 uCanvasSize; // Number of seconds since canvas was initialized uniform lowp float uTime; +// Current frame of first video with [data-cute-texture-video] attribute +uniform sampler2D uVideo; // Coordinates of current pixel being computed from [0,0] (top left) to [1,1] (bottom right) varying highp vec2 vTextureCoord; @@ -35,20 +38,27 @@ void main() { highp float lum = abs(sin(coords.y-uTime)) + 0.631372549; lowp float opacity = 0.5; - highp vec3 baseColor = vec3( + gl_FragColor = vec4( 0.0, lum, - 0.0 + 0.0, + 1.0 ); - - highp vec3 rotatedColor = hue_rotate(baseColor, 13.12); + + gl_FragColor = hue_rotate(gl_FragColor, 13.12); gl_FragColor = vec4( - rotatedColor.x*opacity, - rotatedColor.y*opacity, - rotatedColor.z*opacity, - opacity + gl_FragColor.rgb * opacity, + 1.0 ); + + highp vec2 videoCoords = vTextureCoord.xy / 2.0 + vec2(0, 0.45); + highp vec4 videoPix = clamp(( grayscale(texture2D(uVideo, videoCoords), 1.0) * 2.0 ), vec4(0), vec4(1)); + videoPix *= 0.777; + + gl_FragColor = abs( videoPix - gl_FragColor ); + + gl_FragColor.a = 1.0; }