简体   繁体   English

在LibGDX中实现梯形精灵

[英]Implementing trapezoidal sprites in LibGDX

I'm trying to create a procedural animation engine for a simple 2D game, that would let me create nice looking animations out of a small number of images (similar to this approach, but for 2D: http://www.gdcvault.com/play/1020583/Animation-Bootcamp-An-Indie-Approach ) 我正在尝试为一个简单的2D游戏创建程序动画引擎,这将使我能够从少量图像中创建外观精美的动画(类似于这种方法,但适用于2D: http//www.gdcvault.com / play / 1020583 / Animation-Bootcamp-An-Indie-Approach

At the moment I have keyframes which hold data for different animation objects, the keyframes are arrays of floats representing the following: 目前,我有一些关键帧保存着不同动画对象的数据,这些关键帧是表示以下内容的float数组:

translateX, translateY, scaleX, scaleY, rotation (degrees) translateX,translateY,scaleX,scaleY,旋转(度)

I'd like to add skewX, skewY, taperTop, and taperBottom to this list, but I'm having trouble properly rendering them. 我想将skewX,skewY,taperTop和taperBottom添加到此列表中,但是我无法正确渲染它们。

This was my attempt at implementing a taper to the top of the sprite to give it a trapezoid shape: 这是我尝试在精灵的顶部实现锥形以使其具有梯形形状的尝试:

float[] vert = sprite.getVertices();
vert[5] += 20; // top-left vertex x co-ordinate
vert[10] -= 20; // top-right vertex x co-ordinate

batch.draw(texture, vert, 0, vert.length);

Unfortunately this is producing some weird texture morphing. 不幸的是,这会产生一些奇怪的纹理变形。

I had a bit of a Google and a look around StackOverflow and found this, which appears to be the problem I'm having: 我对Google有点了解,然后环顾了StackOverflow,发现了这一点,这似乎是我遇到的问题:

http://www.xyzw.us/~cass/qcoord/ http://www.xyzw.us/~cass/qcoord/

However I don't understand the maths behind it (what are s, t, r and q?). 但是我不理解它背后的数学(s,t,r和q是什么?)。

Can someone explain it a bit simpler? 有人可以解释一下吗?

Basically, the less a quad resembles a rectangle, the worse the appearance due to the effect of linearly interpolating the texture coordinates across the shape. 基本上,四边形与矩形的相似程度越小,由于在形状上线性插入纹理坐标的效果,外观越差。 The two triangles that make up the quad are stretched to different sizes, so linear interpolation make the seam very noticeable. 组成四边形的两个三角形被拉伸为不同的大小,因此线性插值使接缝非常明显。

The texture coordinates of each vertex are linearly interpolated for each fragment that the fragment shader processes. 对于片段着色器处理的每个片段,线性插入每个顶点的纹理坐标。 Texture coordinates typically are stored with the size of the object already divided out, so the coordinates are in the range of 0-1, corresponding with the edges of the texture (and values outside this range are clamped or wrapped around). 通常将纹理坐标存储为已划分对象的大小,因此坐标在0-1的范围内,与纹理的边缘相对应(超出此范围的值将被夹紧或包裹)。 This is also typically how any 3D modeling program exports meshes. 通常,这也是任何3D建模程序如何导出网格的方式。

With a trapezoid, we can limit the distortion by pre-multiplying the texture coordinates by the width and then post-dividing the width out of the texture coordinates after linear interpolation. 对于梯形,我们可以通过将纹理坐标乘以宽度,然后在线性插值后将宽度从纹理坐标后除以来限制变形。 This is like curving the diagonal between the two triangles such that its slope is more horizontal at the corner that is on the wider side of the trapezoid. 这就像弯曲两个三角形之间的对角线,以使它的斜率在梯形更宽的边角处更加水平。 Here's an image that helps illustrate it. 这是一张有助于说明它的图像。

在此处输入图片说明

Texture coordinates are usually expressed as a 2D vector with components U and V, also known as S and T. But if you want to divide the size out of the components, you need one more component that you are going to divide by after interpolation, and this is called the Q component. 纹理坐标通常表示为具有分量U和V(也称为S和T)的2D向量。但是,如果您想将尺寸除以这些分量,则需要在插值后再分割一个分量,这就是所谓的Q分量。 (The P component would be used as the third position in the texture if you were looking up something in a 3D texture instead of a 2D texture). (如果您在3D纹理而不是2D纹理中查找某些内容,则P分量将用作纹理中的第三个位置)。

Now here comes the hard part... libgdx's SpriteBatch doesn't support the extra vertex attribute necessary for the Q component. 现在来了困难的部分... libgdx的SpriteBatch不支持Q组件所需的额外顶点属性。 So you can either clone SpriteBatch and carefully go through and modify it to have an extra component in the texCoord attribute, or you can try to re-purpose the existing color attribute, although it's stored as an unsigned byte. 因此,您可以克隆SpriteBatch并仔细进行修改,使其在texCoord属性中具有额外的组件,或者可以尝试重新利用现有的color属性,尽管它以无符号字节的形式存储。

Regardless, you will need pre-width-divided texture coordinates. 无论如何,您都需要预先按宽度划分的纹理坐标。 One way to simplify this is to, instead of using the actual size of the quad for the four vertices, get the ratio of the top and bottom widths of the trapezoid, so we can treat the top parts as width of 1 and therefore leave them alone. 一种简化此方法的方法是,不使用四边形的实际四边形大小,而是获取梯形的顶部和底部宽度的比率,因此我们可以将顶部的宽度视为1,因此将其保留单独。

float bottomWidth = taperBottom / taperTop;

Then you need to modify the TextureRegion's existing texture coordinates to pre-multiply them by the widths. 然后,您需要修改TextureRegion的现有纹理坐标,以将它们预先乘以宽度。 We can leave the vertices on the top side of the trapezoid alone because of the above simplification, but the U and V coordinates of the two narrow-side vertices need to be multiplied by bottomWidth . 由于上述简化,我们可以将梯形的顶点留在顶部,但是两个窄边顶点的U和V坐标需要乘以bottomWidth You would need to recalculate them and put them into your vertex array every time you change the TextureRegion or one of the taper values. 每次更改TextureRegion或其中一个锥度值时,都需要重新计算它们并将其放入顶点数组。

In the vertex shader, you would need to pass the extra Q component to the fragment shader. 在顶点着色器中,您需要将额外的Q分量传递给片段着色器。 In the fragment shader, we normally look up our texture color using the size-divided texture coordinates like this: 在片段着色器中,我们通常使用大小划分的纹理坐标来查找纹理颜色,如下所示:

vec4 textureColor = texture2D(u_texture, v_texCoords);

but in our case we still need to divide by that Q component: 但是在我们的情况下,我们仍然需要除以那个Q分量:

vec4 textureColor = texture2D(u_texture, v_texCoords.st / v_texCoords.q);

However, this causes a dependent texture read because we are modifying a vector before it is passed into the texture function. 但是,这会导致读取依赖的纹理,因为我们在将向量传递到纹理函数之前对其进行了修改。 GLSL provides a function that automatically does the above (and I assume does not cause a dependent texture read): GLSL提供了一个自动执行上述操作的功能(并且我认为不会导致依赖的纹理读取):

vec4 textureColor = texture2DProj(u_texture, v_texCoords); //first two components automatically divided by last component

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM