Les Buffers et WebGL

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 :

    explication du code javascript donnant ce résultat

          
            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;
    
          }