使用 WebGL 的 Sprite Animation 如何工作?
How does Sprite Animation with WebGL work?
虽然有很多关于如何渲染精灵的教程,我已经知道了,但我想知道如何以面向对象的方式为我的精灵制作动画。假设我有一个 Player-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.....
所以我的问题是:
我是在 vertex/fragment 着色器内细分 uv 坐标还是在 CPU 上计算它们?如果是这样,我是将它们存储在 4 个不同的缓冲区中还是仅存储在 1 个缓冲区中?如果可能的话,你能提供一个代码示例吗?
附加说明:我希望我所有的动画精灵都有 4 种运动状态,所以 f.e。整个图像是 64x64,它包含 4 个 16x16 纹理。
可能最常见的方法是使用具有单位四边形纹理坐标的单位四边形并传入纹理矩阵以将纹理坐标乘以select您想要的纹理部分。
// vertex shader
attribute vec2 texcoord;
...
uniform mat4 texMatrix;
...
varying vec2 v_texcoord;
...
void main() {
...
v_texcoord = (texMatrix * vec4(texcoord, 0, 1)).xy;
}
如果您不打算旋转,您可以通过传入 uv 偏移量和 uv 比例来缩短它
// vertex shader
attribute vec2 texcoord;
...
uniform vec2 uvOffset;
uniform vec2 uvScale;
...
varying vec2 v_texcoord;
...
void main() {
...
v_texcoord = texcoord * uvScale + uvOffset;
}
如果给定纹理的所有精灵都具有相同的大小(假设所有精灵都是 40x20),那么您也可以通过传入单个精灵的大小或横向和向下的精灵数量来实现,纹理的大小和精灵编号然后计算着色器中的 UV。
您使用哪一个取决于您想要多灵活以及您需要多快的速度。我几乎总是选择第一种方法,因为它最灵活。如果它对我的需求来说太慢,那么我会开始优化。
虽然有很多关于如何渲染精灵的教程,我已经知道了,但我想知道如何以面向对象的方式为我的精灵制作动画。假设我有一个 Player-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.....
所以我的问题是: 我是在 vertex/fragment 着色器内细分 uv 坐标还是在 CPU 上计算它们?如果是这样,我是将它们存储在 4 个不同的缓冲区中还是仅存储在 1 个缓冲区中?如果可能的话,你能提供一个代码示例吗? 附加说明:我希望我所有的动画精灵都有 4 种运动状态,所以 f.e。整个图像是 64x64,它包含 4 个 16x16 纹理。
可能最常见的方法是使用具有单位四边形纹理坐标的单位四边形并传入纹理矩阵以将纹理坐标乘以select您想要的纹理部分。
// vertex shader
attribute vec2 texcoord;
...
uniform mat4 texMatrix;
...
varying vec2 v_texcoord;
...
void main() {
...
v_texcoord = (texMatrix * vec4(texcoord, 0, 1)).xy;
}
如果您不打算旋转,您可以通过传入 uv 偏移量和 uv 比例来缩短它
// vertex shader
attribute vec2 texcoord;
...
uniform vec2 uvOffset;
uniform vec2 uvScale;
...
varying vec2 v_texcoord;
...
void main() {
...
v_texcoord = texcoord * uvScale + uvOffset;
}
如果给定纹理的所有精灵都具有相同的大小(假设所有精灵都是 40x20),那么您也可以通过传入单个精灵的大小或横向和向下的精灵数量来实现,纹理的大小和精灵编号然后计算着色器中的 UV。
您使用哪一个取决于您想要多灵活以及您需要多快的速度。我几乎总是选择第一种方法,因为它最灵活。如果它对我的需求来说太慢,那么我会开始优化。