Как мне использовать texSubImage2D, чтобы показать спрайты в webgl? - PullRequest
7 голосов
/ 15 марта 2011

Я могу успешно отобразить весь свой спрайт (32x512) с помощью этого вызова gl.texImage2D:

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

Это сжато по горизонтали, как я и ожидал, но, по крайней мере, отображается на экране. Я пытаюсь отобразить только первый спрайт 32x32 на листе, и я предположил, что могу просто использовать gl.texSubImage2D для достижения этого эффекта. Я попробовал простую замену texImage2D на texSubImage2D (с измененными параметрами), но я просто получил черный ящик на экране. Вот код, который я использую:

gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 32, 32, gl.RGBA, gl.UNSIGNED_BYTE, image);

Я что-то упускаю из-за реализации texSubImage2D? Есть ли какой-то другой шаг, который я должен сделать? Или texSubImage2D не правильный способ сделать спрайт листы?

1 Ответ

11 голосов
/ 16 марта 2011

texSubImage2D не та функция, которую вы хотите. Вы столкнулись с тремя проблемами:

  1. texSubImage2D не копирует подмножество image в текстуру GL. Он копирует всю image поверх текстуры GL с заданным смещением.
  2. texSubImage2D может только изменять существующие данные текстуры и будет портиться, если только texImage2D не был вызван первым для текстуры GL.
  3. Стиль вызова, который вы используете для texSubImage2D, ожидает массив пикселей вместо HTMLImageElement.

Существует четыре возможных подписи для этих методов:

// These two accept the normal HTMLImageElement, etc. for the last param.

texImage2D(enum target, int level,  enum internalformat, enum format,
  enum type, Object object);
texSubImage2D(enum target, int level, int xoffset, int yoffset,
  enum format, enum type, Object object);

// These two accept a Uint8Array[] of pixels as the last parameter, despite
// being documented as wanting an ImageData object. The only reason these
// have a width/height param is *because* they take a pixel array, and GL
// doesn't know how large the image is.

texImage2D(enum target, int level, enum internalformat, long width,
  long height, int border, enum format, enum type, Object pixels);
texSubImage2D(enum target, int level, int xoffset, int yoffset,
  long width, long height, enum format, enum type, Object pixels);

Чтобы создать текстуру с использованием первых 32x32 пикселей изображения, сделайте что-то вроде этого:

var spriteCanvas = document.createElement('canvas');
spriteCanvas.width = 32;
spriteCanvas.height = 32;

var spriteContext = spriteCanvas.getContext('2d');
spriteContext.drawImage(image, 0, 0);

gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, spriteCanvas);
...