微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 OpenGL 中计算立方体上的 UV 映射纹理图集

如何解决在 OpenGL 中计算立方体上的 UV 映射纹理图集

我一直在用 C 对 mineCraft 应用程序进行逆向工程,使用 OpenGL 构建。如果您不知道,游戏涉及立方体的生成、立方体的 UV 贴图纹理,然后将它们放置在您(通常)添加到的世界中,并移除以构建和销毁(以及更多)。

游戏功能齐全。有用。一切呈现。所有功能都没问题。但是我遇到了很多麻烦(几天),从纹理图集中重建立方体上的 UV 映射。具体问题是我不明白这个系统是如何使用 UV 映射将纹理映射到立方体上的。我对这篇文章中提到的函数进行了逆向工程、重建和手动计算,但从我阅读的所有资源来看,我没有达到。如果有人愿意帮助我了解我的理解有误,和/或这个函数是如何做的,我会欣喜若狂。这是最后一部分,我从里到外都理解了应用程序的其余部分。现在就是这样。

一个函数被用来创建顶点缓冲区数据、法线数据和纹理数据,以便在构建立方体之后向下推 GL 管道。

我正在逆向工程的函数中的顶点数据是不言自明的,因为它只是使用笛卡尔坐标系。正常的数据,也简单。但是紫外线数据,我已经为此纠结了三天。我被卡住的一个原因是所有 UV 贴图教程要么涉及在正方形的所有 6 个边上使用的单个正方形纹理,要么是解开的立方体纹理。本 minecraft 不使用其中任何一个。它使用 3x1 矩形地图。底部,中间,顶部。中间用作所有侧面(左、右、前、后),顶部和底部是独立的。

一个原因是当我做完数学运算(并且我一遍又一遍地检查我的计算)时,我无法想出与程序相同的答案。程序运行良好,可以正常工作。所以我知道我错过了一些东西。

我已经在白板上绘制了 UV 坐标,研究/阅读了许多来源的 UV 映射(我将在下面引用),但我无法弄清楚这个公式是如何工作的。主要原因是不存在的文档和人们用来创建这些函数的相对模糊的命名约定。但无论如何,我离完成一切都很近了。这是我需要理解的最后一部分,以便整个拼图卡到位。

根据我对其工作原理的理解,使用 UV 纹理贴图时,UV 或 ST 坐标映射与笛卡尔坐标相同,只是它们来自 [0..1]。但从我所看到的这个应用程序中的算法(有效)来看,我一定遗漏了一些东西。

我看待它的方式,或者至少我在多个地方读到的,是不管你的顶点在哪里,你想渲染它们的地方,你想要纹理左下角的地方,您将其放置在您认为左下角顶点所在的位置。纹理的右上角,右上角的顶点。等等。当我对其中的一些进行数学运算时,当我用正确的 [0..1] 坐标代替 向量时,有 4 / 6 个方程得到了解决

仅供参考,纹理图集从左到右有 16 个“行”或纹理。但每个立方体由 3 个纹理方块组成。没有“左”、“右”或“后”之分,因为“前”纹理用于每一面。意思是,左 = 前 = 后 = 左......最终,顶部,中间 x 4,底部。每个纹理块都是 0.0625 宽,0.0625 高。总共 16 个。

This is the actual texture atlas used. 16 textures,and in the 0..1 normalized coordinates,they are each 0.0625 coordinates each.

  • float *vector一个浮点数组,将用作着色器的顶点。
  • float *normal 是用于着色器的法线数据数组。
  • float *texture 是 UV 数据,同样稍后添加到着色器中。
  • int left,int right,int top,int bottom,int front,int back 都是布尔值。它们指定要渲染的面。如果全部为 1,则将呈现该立方体的所有顶点数据。如果所有这些都是 0,则不会呈现任何内容
  • float x,float y,float z 是要渲染的块的坐标。
  • int n 是下一个提供的坐标的偏移量,用于构建立方体(宽度和高度)
  • int w 是要使用的纹理。 (来自1 - 16

函数开始时,它从 1 中减去 w 以从 0 开始纹理坐标,而不是 1。然后它运行,为每个点设置坐标,转到下一个内存空间并为其分配以下坐标。对于指向 *vector_data*vector 和指向 *normal_data*normal,它一遍又一遍地这样做。这一切都很直观。

但是来到指向“*texture”的*texture_data,这对我来说就是地狱和手提篮。

我使用值 (0,0) 作为初始 (x,y,z)w = 1n = 0.5 和所有面 int left,int back = 1,1,1 来尝试剖析它,如在我下面引用的资源中找不到明确的信息,至少可以帮助我解决这个问题,我可以理解。

只是为了让您知道我已经尽我所能,我还会向您提供我通过此应用程序运行的数据,这些数据与我的方程式不匹配。

有问题的功能

make_cube(float *vector,float *normal,float *texture,int left,int back,float x,float z,float n,int w) {
    float *vector_data = vector;
    float *normal_data = normal;
    float *texture_data = texture;
    float s = 1.0f / 16; // 0.0625f
    float a = 0;
    float b = 1.0f / 16; // 0.0625
//    float b = s; // 0.0625
    float du,dv;
    float ou,ov;
    w--;
    ou = (w % 16) * s; // w % 16 * 0.0625 width offset... the position of the texture times the width percentage of textures texture_pos * (1 / 16)
    ov = (w / 16 * 3) * s; // height offset

    // 108 data points,or 36 (3D) vector_data for the cube
    // 108 data points,or 36 (3D) normal_data for the cube
    // 72 data points,or  36 (2D) texture_data for the cube
    if (left) {
        du = ou; dv = ov + s;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(normal_data++) = -1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = -1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = -1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = -1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = -1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = -1; *(normal_data++) = 0; *(normal_data++) = 0;

        // hint: z appears to be interchanged with y in pattern
        //   and x's pattern doesn't matter.
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
    }
    if (right) {
        du = ou; dv = ov + s;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(normal_data++) = 1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = 1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = 1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = 1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = 1; *(normal_data++) = 0; *(normal_data++) = 0;
        *(normal_data++) = 1; *(normal_data++) = 0; *(normal_data++) = 0;

        // hint: z appears to be interchanged with y in pattern
        //   and x's pattern doesn't matter.
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
    }
    if (top) {
        du = ou; dv = ov + s + s;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(normal_data++) = 0; *(normal_data++) = 1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = 1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = 1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = 1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = 1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = 1; *(normal_data++) = 0;

        // hint: the pattern seems to be with x and z,(not y) because it remains the same
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
    }
    if (bottom) {
        du = ou; dv = ov + 0;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(normal_data++) = 0; *(normal_data++) = -1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = -1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = -1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = -1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = -1; *(normal_data++) = 0;
        *(normal_data++) = 0; *(normal_data++) = -1; *(normal_data++) = 0;

        // hint: the pattern seems to fit with x,z and negate y
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
    }
    if (front) {
        du = ou; dv = ov + s;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z + n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z + n;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = -1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = -1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = -1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = -1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = -1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = -1;

        // hint: u seems to link with x,and v with y (but the opposite)
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
    }
    if (back) {
        du = ou; dv = ov + s;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x - n; *(vector_data++) = y - n; *(vector_data++) = z - n;
        *(vector_data++) = x - n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(vector_data++) = x + n; *(vector_data++) = y + n; *(vector_data++) = z - n;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = 1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = 1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = 1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = 1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = 1;
        *(normal_data++) = 0; *(normal_data++) = 0; *(normal_data++) = 1;

        // hint: the texture u seems to link with x,and v with y
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;


        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = b + du; *(texture_data++) = a + dv;
        *(texture_data++) = a + du; *(texture_data++) = b + dv;
        *(texture_data++) = b + du; *(texture_data++) = b + dv;
    }
}

当我从程序本身得到 left 的结果时,这就是我得到的顶点结果:

x = 0.500000,y = 0.500000,z = 0.500000
x = 0.500000,y = 1.500000,z = 1.500000
x = 0.500000,z = 1.500000

还有纹理数据...(记住,因为 left 立方体,是第二个(v = 0.0625)并且 x 起始位置是 u = 0),所以原点在 UV 中是 0,0.0625

x = 0.000000,y = 0.062500
x = 0.062500,y = 0.125000
x = 0.000000,y = 0.125000

但是我手工计算,当我将坐标应用到 UV 贴图定位时,我实际上得到了......我这样做的方式是每次我得到一个

x = 0.000000,y = 0.125000
x = 0.062500,y = 0.062500
x = 0.000000,y = 0.125000

我认为我获得了几乎正确的值并非偶然。立方体也没有完全相同的渲染纹理。它们中的一些被颠倒,使纹理看起来有机地相互连接。以下是立方体逆时针旋转时的 4 个边的一些屏幕截图。

Front

正面

Left

剩下

Back

后退

Right

有人知道这是如何工作的吗?有人可以指出我的方向吗?我觉得我已经看着这个很久了,我无法透过树木看到森林。我需要了解这些 UV 坐标是如何映射到这个立方体的这些特定侧面的。

如果其他人感兴趣,这里是顶点和纹理数据的其余输出(分别在同一代码块中)。

对了

x = 1.500000,z = 0.500000
x = 1.500000,z = 1.500000
x = 1.500000,z = 1.500000

x = 0.062500,y = 0.125000

顶部

x = 0.500000,z = 0.500000


x = 0.000000,y = 0.187500
x = 0.000000,y = 0.187500
x = 0.062500,y = 0.187500

底部

x = 0.500000,z = 1.500000


x = 0.000000,y = 0.000000
x = 0.062500,y = 0.062500

正面

x = 0.500000,z = 1.500000


x = 0.062500,y = 0.125000

返回

x = 0.500000,y = 0.125000

如果有人能解决这个问题,我将不胜感激。只是为了让我的心平静下来。我被称为 Jack-Rustle Terrier -- 无法放手。

我很想看到我遗漏的简单东西!如果你已经走了这么远,谢谢!

以下是我用来尝试解决此问题的一些参考资料。

http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/ https://gamedev.stackexchange.com/questions/152991/how-can-i-calculate-normals-using-a-vertex-and-index-buffer https://gamedev.stackexchange.com/questions/172352/finding-texture-coordinates-for-plane https://gamedev.net/forums/topic/626790-uv-mapping-where-do-the-u-v-coordinates-correspond-to-on-a-square-texture/4951976/ https://github.com/Hopson97/MineCraft-One-Week-Challenge/blob/master/Source/Texture/TextureAtlas.cpp https://en.wikipedia.org/wiki/UV_mapping https://gamedev.stackexchange.com/questions/25057/help-a-2d-image-onto-a-3d-cube OpenGL 4 - UV Coordinates for Triangle Strip Cube https://conceptartempire.com/uv-mapping-unwrapping/ Dave Astle 的《开始 OpenGL 游戏编程》第 151 - 158 页(纹理映射)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。