虽然有许多关于如何渲染精灵的教程,我已经知道了,但我想知道如何以面向对象的方式为我的精灵制作动画。我们说我有一个玩家 - class
class Player{
constructor(){
this.textureAtlasPath = 'textures/player.jpg'
this.uvCoords = [0,0,1,0,1,1,0,1]
}
}
因此,如果player.jpg
仅包含一个纹理(如一个字符),我认为非常清楚,我使用uv坐标[0,0,1,0,1,1,0,1]
。但是让我们说player.jpg
包含4个纹理(字符朝上,字符在左边,字符在右边,字符朝下)。我所做的是将uv坐标划分为4 uv坐标(在顶点着色器中)并取决于帧f.e。:
if(currentFrame < 15)
//use uv coord subdivision 1
if(currentFrame < 30)
//use uv coord subdivision 2
to be continued.....
所以我的问题是: 我是否在顶点/片段着色器中细分uv coords还是在CPU上计算它们?如果是这样,我将它们存储在4个不同的缓冲区或只有1个缓冲区?如果可能,您能提供代码示例吗? 附加说明:我希望我的所有动画精灵都有4种运动状态,所以f.e.整个图像是64x64,它包含4个16x16纹理。
答案 0 :(得分:1)
最常见的方法可能是使用具有单位四维纹理坐标的单位四元组,并传入纹理矩阵以将纹理坐标相乘以选择所需纹理的一部分。
// vertex shader
attribute vec2 texcoord;
...
uniform mat4 texMatrix;
...
varying vec2 v_texcoord;
...
void main() {
...
v_texcoord = (texMatrix * vec4(texcoord, 0, 1)).xy;
}
如果您不打算旋转,可以通过传递紫外偏移和紫外线缩放来缩短它
// vertex shader
attribute vec2 texcoord;
...
uniform vec2 uvOffset;
uniform vec2 uvScale;
...
varying vec2 v_texcoord;
...
void main() {
...
v_texcoord = texcoord * uvScale + uvOffset;
}
如果所有的精灵对于给定的纹理都是相同的大小(比如它们都是40x20)那么你也可以通过传递一个精灵的大小或者精灵的数量和大小来实现它。纹理和精灵数字然后计算着色器中的UV。
您使用哪一个取决于您想要的灵活性以及您需要多快的速度。我几乎总是选择第一种方法,它是最灵活的。如果它对我的需求太慢,那么我就开始优化了。