WebGL 的 Sprite 动画是如何工作的? [英] How does Sprite Animation with WebGL work?

查看:32
本文介绍了WebGL 的 Sprite 动画是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然有很多关于如何渲染精灵的教程,我已经知道了,但我想知道如何以面向对象的方式为我的精灵设置动画.假设我有一个 Player-class

Although there are many tutorials about how to render sprites, which I already know, I was wondering about how I can animate my sprites in an object oriented way. Let's say I have a 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.:

So if player.jpg contains only ONE texture (like one character) i think it is very clear, that i use uv coordinates [0,0,1,0,1,1,0,1]. But lets say the player.jpg contains of 4 textures (character facing up, character to the left, character to the right and character facing down). What i did was dividing the uv coordinates in 4 uv coordinates (within a vertex shader) and depending on the frame f.e.:

if(currentFrame < 15)
    //use uv coord subdivision 1
if(currentFrame < 30)
    //use uv coord subdivision 2
to be continued.....

所以我的问题是:我是在顶点/片段着色器中细分 uv 坐标还是在 CPU 上计算它们?如果是这样,我将它们存储在 4 个不同的缓冲区中还是仅存储 1 个缓冲区?如果可能的话,你能提供一个代码示例吗?附加说明:我希望我所有的动画精灵都有 4 种运动状态,所以 f.e.整个图像为 64x64,包含 4 个 16x16 纹理.

So my question is: Do I subdivide the uv coords within the vertex/fragment shader or do I calculate them on the CPU? If so do I store them in 4 different buffers or only 1 buffer? And if possible can you provide a code example? Additional note: I want my ALL my animated sprites to have 4 states of movement, so f.e. the whole image is 64x64 and it contains 4 16x16 textures.

推荐答案

大概最常见的方式是使用带有单位四边形纹理坐标的单位四边形,并传入一个纹理矩阵乘以纹理坐标来选择部分你想要的纹理.

Probably the most common way is to use a unit quad with unit quad texture coordinates and pass in a texture matrix to multiply the texture coordinates to select the part of the texture you want.

 // vertex shader
 attribute vec2 texcoord;
 ...
 uniform mat4 texMatrix;
 ...
 varying vec2 v_texcoord;
 ...

 void main() {
    ...
    v_texcoord = (texMatrix * vec4(texcoord, 0, 1)).xy;
 }

请参阅此处了解数学

如果你不打算旋转,你可以通过传入一个 uv 偏移和 uv 比例来缩短它

If you don't plan on rotating you can shorten that by just passing in a uv offset and uv scale

 // vertex shader
 attribute vec2 texcoord;
 ...
 uniform vec2 uvOffset;
 uniform vec2 uvScale;
 ...
 varying vec2 v_texcoord;
 ...

 void main() {
    ...
    v_texcoord = texcoord * uvScale + uvOffset;
 }

如果给定纹理的所有精灵大小相同(假设所有精灵都是 40x20),那么您也可以通过传入单个精灵的大小或上下精灵的数量、大小来实现纹理和精灵编号,然后计算着色器中的 UV.

If all your sprites are the same size for a given texture (say all of them are 40x20) then you can also do it by just passing in the size of a single sprite or the number of sprites across and down, the size of the texture, and a sprite number then calculate the UVs in the shader.

您使用哪一种取决于您想要的灵活性以及您需要的速度.我几乎总是选择第一种方法,它是最灵活的.如果它对我的需求来说太慢了,那么我开始优化.

Which one you use depends on how flexible you want to be and how much speed you need. I almost always choose the first method is it's the most flexible. If it's too slow for my needs then I start optimizing.

这篇关于WebGL 的 Sprite 动画是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆