Ajout d'entités "glitch" a la scene
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
import { Glitcher } from "./lib/glitcher";
|
||||
|
||||
const UI_GLITCHER = new Glitcher(document.getElementById("ui-canvas"))
|
||||
const CANVAS = document.getElementById("ui-canvas")
|
||||
const UI_GLITCHER = new Glitcher(CANVAS)
|
||||
const FORM = document.getElementById("glitcher-form")
|
||||
|
||||
async function updateFromForm(){
|
||||
let data = new FormData(FORM)
|
||||
|
||||
let image = data.get("image")
|
||||
if(image){
|
||||
if(image.size > 0){
|
||||
await UI_GLITCHER.setImage(image)
|
||||
UI_GLITCHER.clearGlitch()
|
||||
} else {
|
||||
UI_GLITCHER.clearImage()
|
||||
}
|
||||
@@ -25,4 +27,60 @@ FORM.addEventListener("submit", e => {
|
||||
updateFromForm()
|
||||
})
|
||||
|
||||
CANVAS.addEventListener("pointerdown", e => {
|
||||
let pointerId = e.pointerId;
|
||||
|
||||
let lastX = undefined;
|
||||
let lastY = undefined;
|
||||
let lastCommit = null;
|
||||
|
||||
function applyGlitch(e){
|
||||
if(e.pointerId != pointerId){
|
||||
return
|
||||
}
|
||||
|
||||
let canvasRect = CANVAS.getBoundingClientRect()
|
||||
let x = e.clientX - canvasRect.left
|
||||
let y = e.clientY - canvasRect.top
|
||||
|
||||
let now = Date.now()
|
||||
|
||||
if(lastCommit === null || now - lastCommit > 100){
|
||||
let width = 20;
|
||||
if(e.pointerType == "touch"){
|
||||
width *= 2
|
||||
}
|
||||
|
||||
let deltaX = lastX !== undefined ? x - lastX : 0
|
||||
let deltaY = lastY !== undefined ? y - lastY : 0
|
||||
|
||||
width += Math.max(Math.abs(deltaX), Math.abs(deltaY))
|
||||
|
||||
//UI_GLITCHER.addGlitch(x + (Math.random() * width) - width/2, y + (Math.random() * width) - width/2, width)
|
||||
UI_GLITCHER.addGlitch(x, y, width)
|
||||
UI_GLITCHER.render()
|
||||
|
||||
lastCommit = now
|
||||
}
|
||||
|
||||
lastX = x
|
||||
lastY = y
|
||||
}
|
||||
|
||||
function endGlitch(e){
|
||||
if(e.pointerId != pointerId){
|
||||
return
|
||||
}
|
||||
|
||||
window.removeEventListener("pointermove", applyGlitch)
|
||||
window.removeEventListener("pointerup", endGlitch)
|
||||
}
|
||||
|
||||
window.addEventListener("pointerup", endGlitch)
|
||||
window.addEventListener("pointermove", applyGlitch)
|
||||
|
||||
applyGlitch(e)
|
||||
})
|
||||
|
||||
|
||||
updateFromForm()
|
||||
@@ -1,9 +1,9 @@
|
||||
attribute vec4 aVertexPosition;
|
||||
attribute vec2 aVertexPosition;
|
||||
attribute vec2 aTextureCoord;
|
||||
|
||||
varying highp vec2 vTextureCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = aVertexPosition;
|
||||
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
|
||||
vTextureCoord = aTextureCoord;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
void main() {
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
attribute vec4 aVertexPosition;
|
||||
|
||||
uniform vec2 uGlitchPosition;
|
||||
uniform float uGlitchWidth;
|
||||
uniform vec2 uImageRatio;
|
||||
|
||||
void main() {
|
||||
vec2 vertex = aVertexPosition.xy;
|
||||
|
||||
vertex *= uImageRatio;
|
||||
vertex *= 0.001;
|
||||
vertex *= uGlitchWidth;
|
||||
vertex += uGlitchPosition;
|
||||
|
||||
gl_Position = vec4(vertex, -1.0, 1.0);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import resizeToFit from 'intrinsic-scale';
|
||||
import resizeToFit from 'intrinsic-scale'
|
||||
|
||||
import baseVertSource from "./base.vert?raw"
|
||||
import baseFragSource from "./base.frag?raw"
|
||||
|
||||
import glitchVertSource from "./glitch.vert?raw"
|
||||
import glitchFragSource from "./glitch.frag?raw"
|
||||
|
||||
export class Glitcher {
|
||||
|
||||
/** @type {HTMLCanvasElement} */
|
||||
canvas
|
||||
|
||||
gliches = []
|
||||
|
||||
/**
|
||||
* @param {HTMLCanvasElement} canvas
|
||||
*/
|
||||
@@ -21,35 +27,7 @@ export class Glitcher {
|
||||
throw new Error("WebGL isn't supported")
|
||||
}
|
||||
|
||||
let baseVertShader = this.ctx.createShader(this.ctx.VERTEX_SHADER)
|
||||
this.ctx.shaderSource(baseVertShader, baseVertSource)
|
||||
this.ctx.compileShader(baseVertShader)
|
||||
|
||||
if (!this.ctx.getShaderParameter(baseVertShader, this.ctx.COMPILE_STATUS)) {
|
||||
throw new Error(`failed to compile base.vert: ${this.ctx.getShaderInfoLog(baseVertShader)}`)
|
||||
}
|
||||
|
||||
let baseFragShader = this.ctx.createShader(this.ctx.FRAGMENT_SHADER)
|
||||
this.ctx.shaderSource(baseFragShader, baseFragSource)
|
||||
this.ctx.compileShader(baseFragShader)
|
||||
|
||||
if (!this.ctx.getShaderParameter(baseFragShader, this.ctx.COMPILE_STATUS)) {
|
||||
throw new Error(`failed to compile base.frag: ${this.ctx.getShaderInfoLog(baseFragShader)}`)
|
||||
}
|
||||
|
||||
let baseShaderProgram = this.ctx.createProgram()
|
||||
this.ctx.attachShader(baseShaderProgram, baseVertShader)
|
||||
this.ctx.attachShader(baseShaderProgram, baseFragShader)
|
||||
this.ctx.linkProgram(baseShaderProgram)
|
||||
|
||||
if (!this.ctx.getProgramParameter(baseShaderProgram, this.ctx.LINK_STATUS)) {
|
||||
throw new Error(`failed to link base shaders: ${this.ctx.getProgramInfoLog(baseShaderProgram)}`)
|
||||
}
|
||||
|
||||
this.baseProgram = baseShaderProgram;
|
||||
this.aVertexPosition = this.ctx.getAttribLocation(baseShaderProgram, "aVertexPosition")
|
||||
this.aTextureCoord = this.ctx.getAttribLocation(baseShaderProgram, "aTextureCoord")
|
||||
this.uImageSampler = this.ctx.getUniformLocation(baseShaderProgram, "uImageSampler")
|
||||
let baseProgram = createProgram(this.ctx, baseVertSource, baseFragSource);
|
||||
|
||||
let panelPositionBuffer = this.ctx.createBuffer()
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, panelPositionBuffer)
|
||||
@@ -60,7 +38,6 @@ export class Glitcher {
|
||||
1.0, -1.0,
|
||||
]
|
||||
this.ctx.bufferData(this.ctx.ARRAY_BUFFER, new Float32Array(positions), this.ctx.STATIC_DRAW)
|
||||
this.panelPositionsBuffer = panelPositionBuffer
|
||||
|
||||
let panelUVBuffer = this.ctx.createBuffer()
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, panelUVBuffer)
|
||||
@@ -71,11 +48,41 @@ export class Glitcher {
|
||||
1.0, 1.0,
|
||||
]
|
||||
this.ctx.bufferData(this.ctx.ARRAY_BUFFER, new Float32Array(uv), this.ctx.STATIC_DRAW)
|
||||
this.panelUVBuffer = panelUVBuffer
|
||||
|
||||
let imageTexture = this.ctx.createTexture()
|
||||
this.imageTexture = imageTexture;
|
||||
|
||||
this.base = {
|
||||
program: baseProgram,
|
||||
aVertexPosition: this.ctx.getAttribLocation(baseProgram, "aVertexPosition"),
|
||||
aTextureCoord: this.ctx.getAttribLocation(baseProgram, "aTextureCoord"),
|
||||
uImageSampler: this.ctx.getUniformLocation(baseProgram, "uImageSampler"),
|
||||
imageTexture: imageTexture,
|
||||
panelUVBuffer: panelUVBuffer,
|
||||
panelPositionsBuffer: panelPositionBuffer
|
||||
}
|
||||
this.clearImage();
|
||||
|
||||
|
||||
let glitchPositionBuffer = this.ctx.createBuffer()
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, glitchPositionBuffer)
|
||||
const glitchPosition = [
|
||||
-1.0, 1.0,
|
||||
1.0, 1.0,
|
||||
-1.0, -1.0,
|
||||
1.0, -1.0,
|
||||
]
|
||||
this.ctx.bufferData(this.ctx.ARRAY_BUFFER, new Float32Array(glitchPosition), this.ctx.STATIC_DRAW)
|
||||
|
||||
let glitchProgram = createProgram(this.ctx, glitchVertSource, glitchFragSource)
|
||||
|
||||
this.glitch = {
|
||||
program: glitchProgram,
|
||||
aVertexPosition: this.ctx.getAttribLocation(glitchProgram, "aVertexPosition"),
|
||||
uGlitchPosition: this.ctx.getUniformLocation(glitchProgram, "uGlitchPosition"),
|
||||
uGlitchWidth: this.ctx.getUniformLocation(glitchProgram, "uGlitchWidth"),
|
||||
uImageRatio: this.ctx.getUniformLocation(glitchProgram, "uImageRatio"),
|
||||
glitchPositionBuffer: glitchPositionBuffer
|
||||
}
|
||||
}
|
||||
|
||||
clearImage(){
|
||||
@@ -92,6 +99,22 @@ export class Glitcher {
|
||||
)
|
||||
}
|
||||
|
||||
clearGlitch(){
|
||||
this.glitches = []
|
||||
}
|
||||
|
||||
addGlitch(x, y, width=1){
|
||||
let computedStyle = window.getComputedStyle(this.canvas)
|
||||
let clientWidth = parseFloat(computedStyle.width)
|
||||
let clientHeight = parseFloat(computedStyle.height)
|
||||
|
||||
this.glitches.push({
|
||||
x: ((x*2)/clientWidth)-1,
|
||||
y: (((y*2)/clientHeight)-1)*-1,
|
||||
width
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {File} imageFile
|
||||
*/
|
||||
@@ -132,7 +155,7 @@ export class Glitcher {
|
||||
this.currentImageFile = imageFile
|
||||
this.currentImage = image
|
||||
|
||||
this.ctx.bindTexture(this.ctx.TEXTURE_2D, this.imageTexture)
|
||||
this.ctx.bindTexture(this.ctx.TEXTURE_2D, this.base.imageTexture)
|
||||
this.ctx.texImage2D(
|
||||
this.ctx.TEXTURE_2D,
|
||||
0,
|
||||
@@ -184,38 +207,99 @@ export class Glitcher {
|
||||
|
||||
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT)
|
||||
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.panelPositionsBuffer)
|
||||
this.ctx.vertexAttribPointer(
|
||||
this.aVertexPosition,
|
||||
2, // N components per iteration
|
||||
this.ctx.FLOAT,
|
||||
false, //Normalize,
|
||||
0, // (stride) how many bytes to get from one set of values to the next
|
||||
0, // Start offset
|
||||
)
|
||||
this.ctx.enableVertexAttribArray(this.aVertexPosition)
|
||||
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.panelUVBuffer)
|
||||
this.ctx.vertexAttribPointer(
|
||||
this.aTextureCoord,
|
||||
2,
|
||||
this.ctx.FLOAT,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
this.ctx.enableVertexAttribArray(this.aTextureCoord)
|
||||
{ // Base rendering
|
||||
this.ctx.useProgram(this.base.program)
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.base.panelPositionsBuffer)
|
||||
this.ctx.vertexAttribPointer(
|
||||
this.base.aVertexPosition,
|
||||
2, // N components per iteration
|
||||
this.ctx.FLOAT,
|
||||
false, //Normalize,
|
||||
0, // (stride) how many bytes to get from one set of values to the next
|
||||
0, // Start offset
|
||||
)
|
||||
this.ctx.enableVertexAttribArray(this.base.aVertexPosition)
|
||||
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.base.panelUVBuffer)
|
||||
this.ctx.vertexAttribPointer(
|
||||
this.base.aTextureCoord,
|
||||
2,
|
||||
this.ctx.FLOAT,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
)
|
||||
this.ctx.enableVertexAttribArray(this.base.aTextureCoord)
|
||||
|
||||
this.ctx.activeTexture(this.ctx.TEXTURE0)
|
||||
this.ctx.bindTexture(this.ctx.TEXTURE_2D, this.imageTexture)
|
||||
this.ctx.uniform1i(this.uImageSampler, 0)
|
||||
this.ctx.activeTexture(this.ctx.TEXTURE0)
|
||||
this.ctx.bindTexture(this.ctx.TEXTURE_2D, this.base.imageTexture)
|
||||
|
||||
this.ctx.uniform1i(this.base.uImageSampler, 0)
|
||||
|
||||
this.ctx.drawArrays(
|
||||
this.ctx.TRIANGLE_STRIP,
|
||||
0, // Vertex offset
|
||||
4, // Total vertex
|
||||
);
|
||||
}
|
||||
|
||||
this.ctx.useProgram(this.baseProgram)
|
||||
|
||||
this.ctx.drawArrays(
|
||||
this.ctx.TRIANGLE_STRIP,
|
||||
0, // Vertex offset
|
||||
4, // Total vertex
|
||||
);
|
||||
{ // Glitch rendering
|
||||
this.ctx.useProgram(this.glitch.program)
|
||||
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.glitch.glitchPositionBuffer)
|
||||
this.ctx.vertexAttribPointer(
|
||||
this.glitch.glitchPositionBuffer,
|
||||
2, // N components per iteration
|
||||
this.ctx.FLOAT,
|
||||
false, //Normalize,
|
||||
0, // (stride) how many bytes to get from one set of values to the next
|
||||
0, // Start offset
|
||||
)
|
||||
|
||||
this.ctx.enableVertexAttribArray(this.glitch.aVertexPosition)
|
||||
if(this.canvas.width > this.canvas.height){
|
||||
this.ctx.uniform2f(this.glitch.uImageRatio, 1.0, this.canvas.width/this.canvas.height)
|
||||
} else {
|
||||
this.ctx.uniform2f(this.glitch.uImageRatio, this.canvas.height/this.canvas.width, 1.0)
|
||||
}
|
||||
|
||||
for(let glitch of this.glitches) {
|
||||
this.ctx.uniform2f(this.glitch.uGlitchPosition, glitch.x, glitch.y)
|
||||
this.ctx.uniform1f(this.glitch.uGlitchWidth, glitch.width)
|
||||
this.ctx.drawArrays(
|
||||
this.ctx.TRIANGLE_STRIP,
|
||||
0, // Vertex offset
|
||||
4, // Total vertex
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createProgram(gl, vertSource, fragSource){
|
||||
let vertShader = gl.createShader(gl.VERTEX_SHADER)
|
||||
gl.shaderSource(vertShader, vertSource)
|
||||
gl.compileShader(vertShader)
|
||||
|
||||
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) {
|
||||
throw new Error(`failed to compile vertex: ${gl.getShaderInfoLog(vertShader)}`)
|
||||
}
|
||||
|
||||
let fragShader = gl.createShader(gl.FRAGMENT_SHADER)
|
||||
gl.shaderSource(fragShader, fragSource)
|
||||
gl.compileShader(fragShader)
|
||||
|
||||
if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) {
|
||||
throw new Error(`failed to compile fragment: ${gl.getShaderInfoLog(fragShader)}`)
|
||||
}
|
||||
|
||||
let program = gl.createProgram()
|
||||
gl.attachShader(program, vertShader)
|
||||
gl.attachShader(program, fragShader)
|
||||
gl.linkProgram(program)
|
||||
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
throw new Error(`failed to link shader: ${gl.getProgramInfoLog(program)}`)
|
||||
}
|
||||
|
||||
return program
|
||||
}
|
||||
Reference in New Issue
Block a user