Не могу получить рабочий пример текстуры WebGL2 с использованием изображений

Я осмотрелся и не нашел простого примера, демонстрирующего 3D-текстуры с использованием нескольких изображений для сопоставления с любой геометрией.

Я нашел следующие примеры:

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

В первом примере я не могу заставить его работать, используя изображения в качестве источника данных. Во втором примере не используются 3D-текстуры.

Если есть какие-либо примеры отображения 3D-текстур, отображающих несколько изображений (например, JPG) на плоскости, это было бы очень полезно.


person Detuned    schedule 26.10.2018    source источник
comment
Вот пример, который загружает 6 изображений в массив 2-мерных текстур. TEXTURE_2D_ARRAY и TEXTURE_3D принимают одни и те же аргументы для заполнения своих данных. Вот пример, загружает холст в TEXTURE_2D_ARRAY. Это тот же код для изображения.   -  person gman    schedule 26.10.2018


Ответы (1)


Вот небольшой образец. Он использует dataURL для изображений, но они могут быть обычными изображениями так же легко, если все они имеют одинаковые размеры. Если они не того же размера, вам придется масштабировать их, чтобы они были либо офлайн, либо через холст, либо что-то в этом роде.

В противном случае образец не устанавливает никаких униформ, потому что значение униформ по умолчанию равно 0. Он просто рисует одну точку с использованием 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>

person gman    schedule 26.10.2018