代码之家  ›  专栏  ›  技术社区  ›  Detuned

无法使用图像获取WebGL2纹理的工作示例

  •  0
  • Detuned  · 技术社区  · 6 年前

    我发现了以下例子:

    1) http://webglsamples.org/WebGL2Samples/#texture_3d https://webgl2fundamentals.org/webgl/lessons/webgl-data-textures.html

    在第一个示例中,我无法使用图像作为数据源。在第二个示例中,它不使用3D纹理。

    1 回复  |  直到 6 年前
        1
  •  1
  •   gman    6 年前

    这是一个小样本。它对图像使用dataurl,但只要它们的维度相同,它们就可以很容易地成为普通图像。如果它们不是相同的尺寸,你就必须缩放它们,这样它们要么离线,要么通过画布什么的。

    gl.POINTS , gl_PointSize gl_PointCoord 对于坐标,因此不需要缓冲区或属性

    const imageURLs = [
      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAUVBMVEX/BgD/////9vb/6ur/29v/fnz/a2n/VlP/Qz7/MSr/HxL/y8r/urn/kpH/p6YAWFkAbG0ARUUANDQA29wAy8wAursAp6gAk5QAgIEAJCQAFRVoLfwBAAAAW0lEQVQY04XGRw6FMBTF0Pt7oQXSs/+FEp5nTDiSJet2ovuJHmitMXqi1spoMFvHaTysh9Fo7hYzG02dc5PrGb1QSmH0Rs6Z0QcpJUZfxBgZ/RBCYPSH957RpR17cQhbwmkrjgAAAABJRU5ErkJggg==",
      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAUVBMVEWH/wD////7//bT/6PK/42//3e2/2Ks/0mi/y/1/+nu/9rl/8nd/7dqAN9jAM6a/wiR/wAhAEYZADURACUKABVZAL1QAKpHAJY9AII0AG4qAFrKpkVwAAAAXElEQVQY04XGNwKAMBADQZFzsMHx/w/lgmlomEJaVB+oPzCJm2hhZpeQxEKstToEKzHG6BA0r5wzH9pXSokPXRFjlEevQggaGIT3flAYmXNuLHCQveDGSbaCG78ep3wInxKnersAAAAASUVORK5CYII=",
      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAS1BMVEUA/v/7//+k//9k/v/p//+P//95/v+4///a///J//9N/v80/v8Y/v/NAAC8AACpAAA1AAAlAABGAADeAACCAABtAAAVAACVAABZAABgJ6tzAAAAW0lEQVQY043IRw7AIAxE0UnvQEiB+580Y1tskk2exPgLVC/fj1bdZIVR7EoTE4UQbAiDiJGPQ6iLnLMcdOYiDfTmJA00RUpJDmby3tsQFnLO2RBWsSlNmIPw0wP2LQdICCV9sQAAAABJRU5ErkJggg==",
      "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAUVBMVEWDAP/////69v/06v+fOf+XIf+OAP/s2v/kyv/Spf/IkP/cuP+9e/9TqQBJlAC0Zv+pUP9AgQAjRgA2bQArWQAaNQASJABt3QBlzQBdvAALFQBmRdTVAAAAYklEQVQY04XGWRaFIAwD0LzBGQUUZdj/Qi2x/vjjPW0SfB7wfcBPlVLY6C6H4EBPe8WFqVqJE0MVglzgxCi2TV6igjHGe68hYK1dblbAOTffnMBf5ZzZaFRKiY1WxRjZeHUCx08IxkTd/o4AAAAASUVORK5CYII=",
    ];
    
    const vs = `#version 300 es
    void main() {
      gl_Position = vec4(0, 0, 0, 1);
      gl_PointSize = 150.0;
    }
    `
    
    const fs = `#version 300 es
    precision mediump float;
    uniform mediump sampler3D tex;
    out vec4 outColor;
    void main() {
      vec3 uvw = vec3(gl_PointCoord.xy, gl_PointCoord.x * gl_PointCoord.y);
      outColor = texture(tex, uvw);
    }
    `;
    
    function main() {
      const gl = document.querySelector('canvas').getContext("webgl2");
      if (!gl) { return console.log; ("need webgl2"); }
      
      const program = twgl.createProgram(gl, [vs, fs]);
      
      const tex = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_3D, tex);
      gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      // we either need to preallocate the space OR we need to wait for 
      // one texture to download to find out the size. All the sizes have
      // to be the same as all slices are required to have the same dimensions
      
      // I happen to know all the images are 16x16 so
      const levels = 1;
      const internalFormat = gl.RGBA8;
      const width = 16;
      const height = 16;
      const depth = imageURLs.length;
      gl.texStorage3D(gl.TEXTURE_3D, levels, internalFormat, width, height, depth);
      
      // load the images
      imageURLs.forEach((url, ndx) => {
        const img = new Image();
        document.body.appendChild(img);  // so we can see the images;
        img.onload = () => {
          gl.bindTexture(gl.TEXTURE_3D, tex);
          
          const level = 0;
          const x = 0;
          const y = 0;
          const z = ndx;
          const depth = 1
          gl.texSubImage3D(
               gl.TEXTURE_3D, level, 
               x, y, z, width, height, depth, 
               gl.RGBA, gl.UNSIGNED_BYTE, img);
    
          // render each time an image comes in. This means
          // the first render will be missing 3 layers or rather
          // the'll be blank (0,0,0,0). We could wait for all images
          // to load instead.
          render();
        };
        img.src = url;
      });
    
      function render() {
        gl.useProgram(program);
        gl.drawArrays(gl.POINTS, 0, 1);  // 1 point
      }
    }
    main();
    canvas {
      margin: .25em;
      border: 1px solid black;
    }
    img {
      margin: .25em;
      border: 1px solid black;
      width: 64px;
      height: 64px;
      image-rendering: pixelated;
    }
    <canvas></canvas>
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>