简体   繁体   English

纹理映射 - 拉伸

[英]Texture mapping - Stretching

I am attempting to create a simple GUI in OpenGL. 我试图在OpenGL中创建一个简单的GUI。 I have created a picture so I can refer to it and make the explanation simpler: 我创建了一张图片,所以我可以参考它并使解释更简单:

纹理贴图

When I apply a texture of a button (32x32) onto a quad polygon with the size of 120x20 (ie not a rectangle as the texture), ML and MR get stretched into very thick lines and it makes the button look unsightly. 当我将按钮(32x32)的纹理应用到尺寸为120x20的四边形(即不是矩形作为纹理)时, MLMR会拉伸成非常粗的线条,这会使按钮看起来不美观。 I know that by creating a new quad polygon for each of the segments ( TL , TM , TR , etc.) and applying a part of the texture to each of them, I can avoid the distortion as shown in the picture: 我知道通过为每个段( TLTMTR等)创建一个新的四边形多边形并将纹理的一部分应用到每个段,我可以避免失真,如图所示:

扭曲的纹理

Question #1: Can I somehow apply parts of a source texture on exact position of a quad polygon? 问题1:我可以以某种方式将源纹理的一部分应用于四边形的精确位置吗? Could I take the TL/ML/BL part of the texture and apply it with vertical stretching on the left-most side of the quad polygon, then take TM/MM/BM and apply them with horizontal stretching right next to the previous part, etc.? 我可以采用纹理的TL / ML / BL部分并在四边形多边形的最左侧进行垂直拉伸,然后使用TM / MM / BM并将它们应用于前一部分旁边的水平拉伸,等等。? Is it even possible and would it be faster, since I'd only need 4 vertices? 它是否可能并且会更快,因为我只需要4个顶点?

  • To rephrase, could I stretch only parts of a texture? 换句话说,我可以只拉伸纹理的一部分吗? Stretch some parts vertically and some parts horizontally and then apply this multi-stretched texture to a polygon? 垂直拉伸某些零件,水平拉伸某些零件,然后将这个多拉伸纹理应用于多边形?

Question #2: If it's not possible, how would I go about reducing the number of vertices needed? 问题2:如果不可能,我将如何减少所需的顶点数量? Creating 9x4vert quads needs 36 vertices, but if I made them share all the vertices that can be shared, I could reduce this number to 16? 创建9x4vert四边形需要36个顶点,但是如果我让它们共享所有可以共享的顶点,我可以将这个数字减少到16个?

The answer: 答案:

I have been working very long, drawing all the indices and coordinates by hand and putting it together on paper, so I hope this will be useful to someone. 我一直工作很长时间,手工绘制所有索引和坐标并将它们放在纸上,所以我希望这对某人有用。 I hope it is correct, although it works fine for me. 我希望它是正确的,虽然它对我来说很好。 It is in C#, but translating it to C++ is trivial. 它在C#中,但将其转换为C ++是微不足道的。

Edit: I've been working on it a whole lot longer and this is the final vertex/index array for a 3x3 plane. 编辑:我已经做了很长时间了,这是3x3平面的最终顶点/索引数组。

    public Vector3[] VertexData = new[]
                                    {
                                        new Vector3(-1.0f, -1.0f, 0.0f),
                                        new Vector3(-0.33f, -1.0f, 0.0f),
                                        new Vector3(0.33f, -1.0f, 0.0f),
                                        new Vector3(1.0f, -1.0f, 0.0f),

                                        new Vector3(-1.0f, -0.33f, 0.0f),
                                        new Vector3(-0.33f, -0.33f, 0.0f),
                                        new Vector3(0.33f, -0.33f, 0.0f),
                                        new Vector3(1.0f, -0.33f, 0.0f),

                                        new Vector3(-1.0f, 0.33f, 0.0f),
                                        new Vector3(-0.33f, 0.33f, 0.0f),
                                        new Vector3(0.33f, 0.33f, 0.0f),
                                        new Vector3(1.0f, 0.33f, 0.0f),

                                        new Vector3(-1.0f, 1.0f, 0.0f),
                                        new Vector3(-0.33f, 1.0f, 0.0f),
                                        new Vector3(0.33f, 1.0f, 0.0f),
                                        new Vector3(1.0f, 1.0f, 0.0f)
                                    };

    public Vector3[] NormalData = new[]
                                   {
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),

                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),

                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),

                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f),
                                       new Vector3(0f, 0f, 1f)
                                   };

    public Vector2[] TextureData = new[]
                                   {
                                       new Vector2(0.0f, 1.0f),
                                       new Vector2(0.33f, 1.0f),
                                       new Vector2(0.66f, 1.0f), 
                                       new Vector2(1.0f, 1.0f), 

                                       new Vector2(0.0f, 0.66f),
                                       new Vector2(0.33f, 0.66f),
                                       new Vector2(0.66f, 0.66f), 
                                       new Vector2(1.0f, 0.66f), 

                                       new Vector2(0.0f, 0.33f), 
                                       new Vector2(0.33f, 0.33f), 
                                       new Vector2(0.66f, 0.33f), 
                                       new Vector2(1.0f, 0.33f), 

                                       new Vector2(0.0f, 0.0f), 
                                       new Vector2(0.33f, 0.0f), 
                                       new Vector2(0.66f, 0.0f), 
                                       new Vector2(1.0f, 0.0f) 
                                   };

    public UInt32[] IndicesData = new UInt32[54]
                                      {
                                          0, 1, 5,
                                          0, 4, 5,
                                          1, 2, 6,
                                          1, 5, 6,
                                          2, 3, 7,
                                          2, 6, 7,

                                          4, 5, 9,
                                          4, 8, 9,
                                          5, 6, 10,
                                          5, 9, 10,
                                          6, 7, 11,
                                          6, 10, 11,

                                          8, 9, 13,
                                          8, 12, 13,
                                          9, 10, 14,
                                          9, 13, 14,
                                          10, 11, 15,
                                          10, 14, 15
                                      };

I know that by creating a new quad polygon for each of the segments (TL, TM, TR, etc.) and applying a part of the texture to each of them, I can avoid the distortion as shown in the picture 我知道通过为每个段(TL,TM,TR等)创建一个新的四边形多边形并将纹理的一部分应用到每个段,我可以避免失真,如图所示

And that's exactly what you should to. 这正是你应该做的。

Question #2: If it's not possible, how would I go about reducing the number of vertices needed? 问题2:如果不可能,我将如何减少所需的顶点数量?

You can of course, and you should share the vertices where the edges meet, as your texture mapping is continous there and only the 1st derivative changes, which is completely in order. 当然,您可以共享边缘相交的顶点,因为纹理映射在那里是连续的,只有一阶导数发生变化,这完全是有序的。

I haven't heard anything about stretching parts of a texture. 我没有听说过任何关于拉伸纹理部分的信息。 In your case not only the ML and MR are being stretched, MM is stretched too. 在你的情况下,不仅MLMR被拉伸, MM也被拉伸。 It is just not that visible as MM is one colour. 它只是不可见,因为MM是一种颜色。

About your problem... can you partition the polygon of the button to 9 quads, like in the picture you posted? 关于你的问题...你可以将按钮的多边形划分为9个四边形,就像你发布的图片一样吗? Then you can slice the texture and apply the different parts of it on the different quads. 然后,您可以切片纹理并将其不同部分应用于不同的四边形。 That's all I can think of at the moment. 这就是我现在所能想到的。

About question #2 - you should look at vertex and index buffers, I believe. 关于问题#2 - 我相信你应该看看顶点和索引缓冲区。 Basically, the vertex buffer is a buffer of all the unique vertices, and the index buffer holds the indices of the vertices from the vertex buffer in the order, in which they appear when you assemble triangles from them. 基本上,顶点缓冲区是所有唯一顶点的缓冲区,索引缓冲区按顺序保存顶点缓冲区顶点的索引,当您从它们组装三角形时,它们会出现在顶点缓冲区中。 In the index buffer an index can appear more than once (that is the purpose of this buffer - so you don't have the same vertices more than once). 在索引缓冲区中,索引可以出现多次(这是此缓冲区的目的 - 因此您不会多次使用相同的顶点)。

Instead of drawing the OpenGL polygon with four points each with texture coordinates 而不是使用纹理坐标的四个点绘制OpenGL多边形

please try to make it with more points so you can control which part of the texture will be stretched. 请尝试使用更多的点,以便您可以控制纹理的哪个部分将被拉伸。 referring to your image you can make 9 rectangles in OpenGL to avoid the stretching of the margins. 参考你的图像,你可以在OpenGL中制作9个矩形,以避免边缘的拉伸。

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

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