如何使用 texSubImage2D 在 webgl 中显示精灵?

发布于 2024-10-22 02:26:00 字数 492 浏览 2 评论 0原文

我可以通过调用 gl.texImage2D 成功显示整个精灵 (32x512):

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

正如我预期的那样,它被水平挤压,但至少在屏幕上呈现。我试图仅显示工作表中的第一个 32x32 精灵,并且我假设我可以简单地使用 gl.texSubImage2D 来实现此效果。我尝试用 texSubImage2D (修改参数)简单替换 texImage2D,但屏幕上只是出现一个黑框。这是我正在使用的代码:

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

我是否遗漏了一些关于texSubImage2D 的实现?我还需要执行其他步骤吗?或者 texSubImage2D 不是制作精灵表的正确方法?

I can display my entire sprite (32x512) successfully with this call to gl.texImage2D:

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

It's squished horizontally, like I expected, but it renders on the screen at least. I'm trying to only display the first 32x32 sprite in the sheet and I assumed that I could simply use gl.texSubImage2D to achieve this effect. I tried a simple replacement of texImage2D with texSubImage2D (with modified parameters) but I just get a black box on the screen. Here's the code I'm using:

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

Am I missing something about the implementation of texSubImage2D? Is there some other step I have to do? Or is texSubImage2D not the right way to do sprite sheets?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故事灯 2024-10-29 02:26:00

texSubImage2D 不是您想要的功能。您遇到了三个问题:

  1. texSubImage2D 不会将 image 的子集复制到 GL 纹理中。它将整个image复制到GL纹理顶部给定的偏移处。
  2. texSubImage2D 只能修改现有的纹理数据,并且除非先为 GL 纹理调用 texImage2D ,否则会造成混乱。
  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);

texSubImage2D is not the function you want. You're running into three problems:

  1. texSubImage2D does not copy a subset of image into the GL texture. It copies the entirety of image on top of the GL texture at a given offset.
  2. texSubImage2D can only modify existing texture data, and will mess up unless texImage2D has been called first for the GL texture.
  3. The calling style you're using for texSubImage2D expects a pixel array instead of an HTMLImageElement.

There are four possible signatures for these methods:

// 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);

To create a texture using the first 32x32 pixels of your image, do something like this instead:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文