具有多种纹理的 VBO
你能渲染一个由四边形组成的 VBO,每个四边形都具有不同的纹理吗?现在,我读到了有关按纹理或纹理图集排序的内容,但这仍然不能回答我的问题。我正在开发一款 2d 游戏。现在我的动画精灵将拥有其帧的纹理图集和法线贴图,并且所有这些都将共享相同的 VBO(如果可能)。所以每个精灵都会有一个图集(某些动画可能有很多帧和姿势,可能会填充 4096*4096 纹理)。那么有可能吗?是还是不是。如果不是,为每个精灵拥有一个带有其所有动画帧的所有纹理坐标的索引 VBO,并且每帧仅发送 4 个索引(对于单个动画帧)并更改每个 VBO 的纹理是否有效? 编辑:其中一些可能会移动(显然),有些可能不会。
经过一番思考,我意识到内存使用也是一个问题。这些纹理图集会占用大量内存。一个 4096*4096 RGBA 纹理需要 64 MB,这很大了(而且没有法线贴图,这会使使用量增加一倍)。而且我认为我无法将这么多动画塞进一个图集中。像《暗黑破坏神》这样的老游戏,或者那些使用 Infinity 引擎的游戏,只需要几兆 VRAM,而且看起来非常不错。
Can you render a VBO of quads each with a different texture?. Now, i read about sorting by texture or texture atlasses but that still doesn't answer my question. I'm working on a 2d game. Now my animated sprites are going to have a texture atlas for their frames and also a normal map, and all of them are going to share the same VBO (if possible). So each sprite is going to have an atlass (some animations could have lots of frames and poses that could maybe fill a 4096*4096 texture). So is it possible? Yes or no. If not is it efficient to have an indexed VBO for each sprite with all the texture coords for all its animation frames and to send only 4 indices each frame (for a single animation frame) and change the texture for each VBO?
EDIT: also some of them may be moving(obviously) and some may be not.
After thinking about it a bit i realised that memory usage is also a problem. Those texture atlasses are going to eat a lot of memory. A 4096*4096 RGBA texture takes 64 MB, wich is a lot (and that's without the normal map wich would double the usage). And i don't think i could cram so many animations into a single atlass. Older games like Diablo, or those on Infinity Engine required only a few megs of VRAM and they looked very good.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
澄清一下,VBO 可以包含纹理坐标,但不知道将应用哪些纹理。
让 VBO 独立于纹理,并根据动画/帧索引计算片段/像素着色器中的纹理坐标。假设您的 VBO 中有四边形,然后您设置纹理坐标,以便它们只映射整个纹理。然后在着色器中,您将缩放并平移纹理坐标以在纹理图集中映射单个帧。然后,您可以将动画索引、图集中的帧数等作为统一值提供给着色器。
编辑(进一步澄清):
四边形的纹理坐标
这对应于将整个纹理映射到该单个四边形。
假设您的纹理被方便地分割成 16x16“帧”,并在纹理图集中按行列顺序堆叠。因此,单帧的大小在 u 和 v 的纹理坐标中分别为 1/16。这是你的移动窗口。现在,在着色器中,您传递动画的“帧”编号,并且四边形中每个顶点的纹理坐标是按 16 缩放的纹理坐标,然后按帧进行平移(基于 0 的整数):
现在我这是我凭空写下来的,所以可能会有一些小错误。另外,此代码假设 texCoord 是四边形上片段的纹理坐标。请注意,计算 1/16 一次比重复除以 16(我可以添加每个像素)便宜得多。如果您还没有关注我,那么 float2(scale*frame%16,scale*(frame/16)) 行可能会令人困惑。一个更简单的情况:
Just to clarify, the VBO can contain texture coordinates but has no knowledge of which textures will be applied to it.
Leave the VBO independent of the textures and compute the texture coordinates in the fragment/pixel shader according to an animation/frame index. Assuming you have quads in your VBO, then you set the texture coordinates so they just map the entire texture. Then in your shader you will scale and translate the texture coordinates to map a single frame on the texture atlas. You can then give the animation index, numbers of frames in the atlas and so on as uniform values to the shader.
Edit (to further clarify):
Texture coordinates for a quad
This corresponds to mapping the entire texture to this single quad.
Let's say your texture is conveniently split into 16x16 "frames", stacked in a row-column order in your texture atlas. The size of a single frame is therefore 1/16 in texture coordinates in both u and v respectively. This is your moving window. Now in your shader, you pass on the "frame" number for your animation and the texture coordinate for each vertex in your quad is it's texture coordinate scaled by 16 and then translated by the frame (0-based integer):
Now I'm writing this off the top of my head here so there might be minor errors. also, this code assumes texCoord is the texture coordinate of the fragment on the quad. Note that computing 1/16 once is much cheaper than repeatedly dividing by 16, per pixel may I add. The line float2(scale*frame%16, scale*(frame/16)) can be confusing if you are not already following me. A simpler case:
当然,这是可能的(假设纹理坐标保持不变)。只需使用
glBindTexture()
附加要使用的纹理,并使用glActiveTexture()
选择要修改的纹理单元。显然,如果您仅使用一种纹理,则可以跳过
glActiveTexture()
。Sure, it's possible (assuming texture coordinates stay the same). Just use
glBindTexture()
to attach the texture to be used andglActiveTexture()
to select the texture unit to be modified.Obviously
glActiveTexture()
can be skipped if you're working with one texture only.