简体   繁体   English

将纹理添加到由顶点构成的平面

[英]Adding texture to a plane made of vertices

I've created a plane at OpenGL with this code: 我使用以下代码在OpenGL上创建了一个平面:

glBegin(GL_TRIANGLE_STRIP);
glColor4f(0.8, 0.8, 0.5, 1.0);
glVertex3f(startlen, height, startwid);    
glVertex3f(startlen, height, startwid + width);
glVertex3f(startlen + length, height, startwid);
glVertex3f(startlen + length, height, startwid + width);
glEnd();

Now I want to apply a texture to this plane. 现在我想在这个平面上应用纹理。

I've read this tutorial here but I've stopped at the "Using the texture in OpenGL" part because I don't have the UV coordinates. 我在这里阅读了这个教程但我已经停止了“在OpenGL中使用纹理”部分,因为我没有UV坐标。

I know that we have to import the texture file, in my case a bitmap file. 我知道我们必须导入纹理文件,在我的例子中是一个位图文件。
The loader returns a Glint, which is the textureID, is that global? 加载器返回一个Glint,它是textureID,是全局的吗? In example, if I need to load that texture I simply need to call the bind texture function with the ID given? 在示例中,如果我需要加载该纹理,我只需要使用给定的ID调用绑定纹理函数?

Anyway, how can I apply the texture to the plane? 无论如何,我怎样才能将纹理应用到平面上?


EDIT #1: The texture at the example mosquito posted works now. 编辑#1:现在发布的示例蚊子的纹理有效。
What I found out was that I was loading the texture into the constructor of the class and I shouldn't because the object was public and it was constructed before OpenGL's initialization. 我发现的是我将纹理加载到类的构造函数中,我不应该因为该对象是公共的而且是在OpenGL初始化之前构造的。
So the texture now loads fine at the quad example :) 所以纹理现在加载四个例子:)

The problem now is that I've tried to use it at my plane and it looks distorted. 现在的问题是我试图在我的飞机上使用它,它看起来很扭曲。 The solution to this is probably enabling the texture to be loaded several times but keep it's original size (although I don't know how to do this) . 对此的解决方案可能是将纹理加载多次,但保持原始大小(虽然我不知道如何做到这一点)

Also, I've created another plane next to the current one with a cream colour but after the texturing it seems like this: 另外,我在当前的一个平面旁边创建了另一个带有奶油色的平面,但在纹理化之后它看起来像这样: 在此输入图像描述

So there are 2 problems now: 所以现在有两个问题:

  • texture must keep it's original resolution but displayed as many times as to cover the whole plane 纹理必须保持原始分辨率,但显示覆盖整个平面的次数
  • the plane next to it, has lost its colour (why did this happen? How to fix it? -- I might use a texture for this plane as well) 它旁边的飞机失去了它的颜色(为什么会发生这种情况?如何解决它? - 我也可以使用这个平面的纹理)

Edit #2: 编辑#2:

2nd problem has been fixed now, thanks to mosquito! 由于蚊子,第2个问题现在已经解决了! But the tiling still doesn't work. 但是平铺仍然不起作用。 This is how it looks now: 这就是它现在的样子: 在此输入图像描述

And this is the texture I've used: 这是我用过的纹理:
在此输入图像描述
Its dimensions are 256x256 (I've used an image editor to crop it) 它的尺寸是256x256(我用图像编辑器裁剪它)


Edit #3: 编辑#3:
These are the glTexCoord2f coordinates with their matching vertices (for the inner margin): 这些是glTexCoord2f坐标及其匹配顶点(对于内边距):

glTexCoord2f(0.0f, 0.0f);   glVertex3f(startlen, height, startwid);
glTexCoord2f(0.0f, 1.0f);   glVertex3f(startlen, height, startwid - width/2);
glTexCoord2f(1.0f, 0.0f);   glVertex3f(startlen + length, height, startwid);
glTexCoord2f(1.0f, 1.0f);   glVertex3f(startlen + length, height, startwid - width/2);

If you have loader which returns textureID then it probably already takes care of loading image data, setting properties and storing it as a real texture for further use. 如果你有一个返回textureID的加载器,它可能已经负责加载图像数据,设置属性并将其存储为真正的纹理以供进一步使用。 So I'll just move on to binding texture to your texturing target. 所以我将继续将纹理绑定到纹理目标。

If you have this id, you basically have to call glBindTexture() function before drawing your triangle strip: 如果你有这个id,你基本上必须在绘制三角形条之前调用glBindTexture()函数:

glBindTexture(GL_TEXTURE_2D, id); // where id is GLuint returned by your loader

now for each vertex you draw, you should also specify coordinates of texture for those vertices. 现在,对于您绘制的每个顶点,您还应该为这些顶点指定纹理坐标。 To do so, you use glTexCoord2f() function. 为此,您使用glTexCoord2f()函数。 For simple quad, it could look like this: 对于简单的四边形,它可能看起来像这样:

glBegin(GL_QUADS);
    // Bottom left
    glTexCoord2f(0.0f, 1.0f);                   
    glVertex2i(0.0f, 10.0f);

    // Top left
    glTexCoord2f(0.0f, 0.0f);
    glVertex2i(0.0f, 0.0f);

    // Top right
    glTexCoord2f(1.0f, 0.0f);
    glVertex2i(10.0f, 0.0f);

    // Bottom right
    glTexCoord2f(1.0f, 1.0f);
    glVertex2i(10.0f, 10.0f);
glEnd();

As you can see, each vertex has texture 'point' attached to it. 如您所见,每个顶点都附有纹理“点”。 It will tell OpenGL how to display your texture. 它会告诉OpenGL如何显示纹理。

Now it's up to you to choose how you want your texture to be distributed on a plane by specifying proper coordinates for vertices. 现在,您可以通过指定顶点的正确坐标来选择希望如何将纹理分布在平面上。

What you have to remember is that texture coordinates starts with 0.0 and ends with 1.0. 您必须记住的是纹理坐标以0.0开头并以1.0结尾。 Increasing this value to more than 1.0 will result in behaviour depending on settings for your texture (eg tiling). 将此值增加到大于1.0将导致行为取决于纹理的设置(例如平铺)。

In your tutorial, you have really nice picture presenting that texture coordinates are from 0.0 to 1.0 range and what texture coordinates are being set for specific vertices: 在你的教程中,你有非常好的图片呈现纹理坐标从0.0到1.0范围以及为特定顶点设置的纹理坐标:

在此输入图像描述

PS. PS。 In order to make textures being displayed, you have to enable this capability first by calling: 为了显示纹理,您必须首先通过调用以下方式启用此功能:

glEnable(GL_TEXTURE_2D);

You don't have to call it every time you draw object with texture. 每次用纹理绘制对象时都不必调用它。 It may be called just once before your drawing. 在绘图之前可能只调用一次。


EDIT 编辑

  1. According to your next problem: What you want is to achieve tiling effect, which can be easily done during creating a texture. 根据你的下一个问题:你想要的是实现平铺效果,这可以在创建纹理时轻松完成。 In your loader, after this line: 在您的装载机中,在此行之后:

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    you should set next texture parameters like this: 你应该设置下一个纹理参数,如下所示:

     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); 

    In this case GL_REPEAT is being used to repeat texture whenever it's coordinates are higher than 1.0. 在这种情况下, GL_REPEAT用于在坐标高于1.0时重复纹理。 For example if you specify texture coordinate to be 2.0 it is the same as you'd put 1.0, and so on. 例如,如果指定纹理坐标为2.0,则与放置1.0相同,依此类推。

  2. Your second problem exist because you have still your texture bound and you have texturing enabled (remember that you used glEnable(GL_TEXTURE_2D); ), so basically everything you draw now, will be covered with texture. 你的第二个问题是存在的,因为你仍然有你的纹理绑定并且你已经启用了纹理(请记住你使用了glEnable(GL_TEXTURE_2D); ),所以基本上你现在绘制的所有内容都会被纹理所覆盖。

    However if you want now to draw something without texturing it, you basically have to disable texturing before drawing your second plane and enable it again after drawing: 但是,如果你现在想要绘制一些没有纹理的东西,你基本上必须在绘制第二个平面之前禁用纹理,并在绘制之后再次启用它:

     glDisable(GL_TEXTURE_2D); // Draw your second plane here glEnable(GL_TEXTURE_2D); 

EDIT2 EDIT2

Well, I think you misunderstood me a bit. 好吧,我觉得你误解了我一点。 In this case tiling cannot work, because you specify texture coordinates to maximum of 1.0 which is the end of your texture. 在这种情况下,平铺无法工作,因为您指定纹理坐标最大为1.0,这是纹理的结束。 I have prepared an image that could show you what I mean: 我准备了一张图片,可以告诉你我的意思:

在此输入图像描述

In those pictures in the middle with red color I marked texture coordinates and with black - vertices coordinates. 在那些中间有红色的图片中,我标记了纹理坐标和黑色 - 顶点坐标。

So basically if you set your texture coordinates like you do it right now (max of 1.0), you make your texture stretched around your plane. 所以基本上如果你像现在这样设置你的纹理坐标(最大值为1.0),你可以让你的纹理在你的平面上伸展。 Now imagine that this plane is very large - it can cause nothing else but ugly stretch effect if texture is of low resolution. 现在想象一下这个平面非常大 - 如果纹理分辨率低,它只会造成丑陋的拉伸效果。

In order to achieve tiling effect, you have to set values higher than 1.0, like in my example - 2.0 causes texture to be repeated two times. 为了实现平铺效果,你必须设置高于1.0的值,就像在我的例子中 - 2.0导致纹理重复两次。

As there is no magic method to make your texture look 'nice' on your plane, you have to use some math to achieve it. 由于没有神奇的方法可以让你的纹理在飞机上看起来“漂亮”,你必须使用一些数学来实现它。 Now this I leave to you. 现在我留给你。

You will need to specify a uv coordinate for every vertex. 您需要为每个顶点指定一个uv坐标。 You do this with the function glTexCoord2f(); 你可以使用函数glTexCoord2f();
the function takes two arguments, the first is the u the other the v. Your drawing code would turn into this: 该函数有两个参数,第一个是你,另一个是v。你的绘图代码会变成这样:

glBegin(GL_TRIANGLE_STRIP);
glColor4f(0.8, 0.8, 0.5, 1.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(startlen, height, startwid);
glTexCoord2f(0.0f, 1.0f); glVertex3f(startlen, height, startwid + width);
glTexCoord2f(1.0f, 1.0f); glVertex3f(startlen + length, height, startwid);
glTexCoord2f(1.0f, 0.0f); glVertex3f(startlen + length, height, startwid + width);
glEnd();

You might to switch them around a bit, I don't know how you want to map your texture to it. 您可能会稍微切换它们,我不知道您想如何将纹理映射到它。 You can see u as an x on the texture where 0.0 = left and 1.0 = right, and you can see v as an y on the texture where 0.0 = top and 1.0 = bottom. 您可以在纹理上看到u为x,其中0.0 =左,1.0 =右,您可以在纹理上看到v为y,其中0.0 = top,1.0 = bottom。
Now, there are a few more things you need, first of all, texturing needs to be enabled: 现在,还有一些你需要的东西,首先,需要启用纹理:

glEnable(GL_TEXTURE_2D); //call this once, during initialization

The texture needs to be loaded, like you already said: 需要加载纹理,就像你已经说过的那样:

glGenTextures(1, &MyTexture);
glBindTexture(GL_TEXTURE_2D, MyTexture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //data is a gluByte array of your image data

And it has to be bound before drawing your quad: 在绘制四边形之前必须绑定它:

glBindTexture(GL_TEXTURE_2D, MyTexture);

I will let the actual loading of the texture up to you, as that would be a completely different question and to extensive to discuss here. 我会让纹理的实际加载到你这里,因为这将是一个完全不同的问题,并在此广泛讨论。

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

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