Cette page montre les valeurs d'un buffer WebGL.
Entrons dans le détail :
Le code javascript & WebGL suivant se termine par l'affichage d'un carré dans un buffer. Et non pas dans l'écran.
Le carré a une taille affichée de 3x3 pixels.
le voici :
Bon, en fait le but est de connaître toutes les valeurs d'un buffer. On va afficher ces valeurs dans une texture.
Voici le contenu de ce buffer :
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
//l'extension suivante permet
gl.getExtension("OES_texture_float");
canvas.style.imageRendering="pixelated";
canvas.style.backgroundColor="rgb(0,255,0)"
la taille du carré affiché sera de 3x3 pixels https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
let size = 3;
canvas.style.width = `${size}px`;
canvas.style.height = `${size}px`;
...Mais la taille en mémoire du carré sera plus grande si devicePixelRatio est supérieur à 1
let scale = window.devicePixelRatio;
canvas.width = Math.floor(size * scale) ;
canvas.height = Math.floor(size * scale) ;
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
let vs=`
attribute vec2 aPosition;
varying vec2 vPosition;
void main() {
gl_Position = vec4(
(aPosition.x + 0.5)/ ${canvas.width}.0 * 2.0 -1.0,
(aPosition.y + 0.5)/ ${canvas.height}.0 * 2.0 -1.0,
0,1);
gl_Position=vec4(aPosition,0,1);
vPosition = aPosition;
gl_PointSize = 1.0;
}`;
let fs=`
precision mediump float;
varying vec2 vPosition;
void main() {
gl_FragColor = vec4(1,vPosition.x,vPosition.y,1);
}`;
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader,vs);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader,fs);
gl.compileShader(fragmentShader);
const program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
let positionAttributeLocation = gl.getAttribLocation(program, "aPosition");
Le buffer contient les coordonnées de sommet.
let positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
/*
0 60 60 60
0 0 60 0
*/
let L=3;
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0, 0,
L, 0,
0, L,
0, L,
L, 0,
L, L,
]), gl.STATIC_DRAW);
/*
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1, -1,
1, -1,
-1, 1,
-1, 1,
1, -1,
1, 1,
]), gl.STATIC_DRAW);
*/
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.UNSIGNED_BYTE, false, 0, 0);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
gl.bindFramebuffer(gl.FRAMEBUFFER,null);
let textureEcran = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, textureEcran);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
canvas.width,
canvas.height,
0,
gl.RGBA,
gl.FLOAT,
null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
let fbEcran = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER,fbEcran);
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D,
textureEcran,
0
);
gl.bindFramebuffer(gl.FRAMEBUFFER,null);
gl.drawArrays(gl.TRIANGLES, 0, 6);
gl.bindFramebuffer(gl.FRAMEBUFFER,fbEcran);
gl.drawArrays(gl.TRIANGLES, 0, 6);
let pixels = new Float32Array(canvas.width*canvas.height*4);
gl.readPixels(0,0,canvas.width,canvas.height,gl.RGBA,gl.FLOAT,pixels);
var array = Array.from(pixels);
//affichage dans la div #ouput du buffer
let i=0;
for (let i=0; i<144;i=i+4) {
let rgba = array.slice(i,i+4);
let r = rgba[0].toPrecision(2);
let g = rgba[1].toPrecision(2);
let b = rgba[2].toPrecision(2);
let a = rgba[3].toPrecision(2);
// console.log(r+ " , " + g + " , "+ b + ", " + a);
let gr= document.getElementById("output").textContent ;
gr = gr + g + " "+ b + " ; ";
document.getElementById("output").textContent = gr;
}