简体   繁体   中英

Adding texture to a plane made of vertices

I've created a plane at OpenGL with this code:

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.

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? In example, if I need to load that texture I simply need to call the bind texture function with the ID given?

Anyway, how can I apply the texture to the plane?


EDIT #1: The texture at the example mosquito posted works now.
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.
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:

2nd problem has been fixed now, thanks to mosquito! 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)


Edit #3:
These are the glTexCoord2f coordinates with their matching vertices (for the inner margin):

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. 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:

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. 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.

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. Increasing this value to more than 1.0 will result in behaviour depending on settings for your texture (eg tiling).

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:

在此输入图像描述

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. 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. 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.

    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

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. 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. 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.

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. You do this with the function glTexCoord2f();
the function takes two arguments, the first is the u the other the v. Your drawing code would turn into this:

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.
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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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