# Creating grass... transparent textures and texture position?

## Recommended Posts

Starshine_    122
Hi! I need help with one more thing... I'm supposed to create a simple grass using the method described here: http://http.developer.nvidia.com/GPUGems/gpugems_ch07.html I don't need to make it animated, though. I started with making one grass cell, but I have two problems with it... first, I'm not sure how to position the texture on each quad. Right now it seems that the texture is not only positioned differently on each quad, but also it's moving in strange ways, even though there are no animations connected with the grass cell... the only animations in the scene are a rotating cube next to it, and a moving light. Another problem is with the transparency. Right now my texture is a 200 x 100 PNG one with a green text on transparent background. (it's just temporary, not the final one for the grass ;) ) Here's what I do to make the texture appear on the grass cell: The grass cell object has a GLuint _grasstexture private field, which is set in the constructor... I'm calling the constructor with one of the parameters as bindTexture(QImage("/home/piotrek/qt/projekt/bin/meep.png")) and I assign it to the _grasstexture field. In the render() method of the grass object, I do this first: glBindTexture(GL_TEXTURE_2D, _grassTexture); and rendering one quad looks like this: glBegin(GL_QUADS); glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 0.0f); glEnd(); Here's the grass cell I get (well, it's not grass yet, but I want it to be grass eventually :D ) http://i11.photobucket.com/albums/a156/Miracle86/transptexture.png When I don't use a texture image, but simply set the quad color to semitransparent, it's working well. As you can see, the places which should be transparent are gray, and the texture is positioned in a really weird way... how can I fix it?

##### Share on other sites
Thaumaturge    3826
First of all, I don't see any setting of texture coordinates in your quad code. Much as with vertices and normals, this has an OpenGL call of its own: glTexCoord.

Secondly, are you sure that you have blending enabled?

##### Share on other sites
Starshine_    122
Hi Thaumaturge!

Thanks for the reply...yes, I have blending enabled... at least I think so. I have this in initializeGL():

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

and when I use a semitransparent RGBA color instead of texture, then it's working well.

As for texture coordinates, I tried using glTexCoord, but it didn't change anything. But I've just thought about something else... I have shadow mapping in that program, and shadow mapping uses GL_TEXTURE_2D. Since the texture on the "grass" is changing when the light is moving, then maybe the texture is somehow projected on the surface from the light in the same way as the shadow map is?

##### Share on other sites
MARS_999    1627
Ah do you have a 32bit texture with alpha channel used for alpha blending setup? Also unless you have a GL2.0 card 200x100 textures aren't going to work unless you called gluBuild2DMipmaps(). So resize to 256x128 and try again.

##### Share on other sites
Starshine_    122
Yes, it's a PNG file with a transparent background. The texture appears when I render it, except that it's gray where it should be transparent. My video card is GeForce 8400, so I think it supports OpenGL 2.0 :)

##### Share on other sites
Thaumaturge    3826
Quote:
 Originally posted by Starshine_Hi Thaumaturge!Thanks for the reply...

Hello, and my pleasure. ^_^

Quote:
 Originally posted by Starshine_yes, I have blending enabled... at least I think so. I have this in initializeGL():glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Good good - that looks as though it should be okay.

Quote:
 Originally posted by Starshine_As for texture coordinates, I tried using glTexCoord, but it didn't change anything.

Fair enough - although I do think that, unless they're set elsewhere (which I don't think should work with the immediate-mode calls that you seem to be using), you should be setting them within your quad generation code. I would recommend putting in texture coordinates and leaving them in while you look elsewhere; you can always remove experimentally them once you have the texturing working, I imagine.

Quote:
 Originally posted by Starshine_I have shadow mapping in that program, and shadow mapping uses GL_TEXTURE_2D. Since the texture on the "grass" is changing when the light is moving, then maybe the texture is somehow projected on the surface from the light in the same way as the shadow map is?

Hmm... This is plausible. Are you perhaps altering the texture matrix for your shadow mapping (as I would imagine that you are), and not re-loading the original matrix afterwards?

##### Share on other sites
Starshine_    122
Hi! The main problem I have with glTexCoord is that I'm not exactly sure how to use it, especially since it has only two parameters... when I think about positioning a texture on a 2D surface, I'm not really sure how it can be done without four parameters... the coordinates of the top-left point, and the bottom-right point, relative to the quad...

As for the texture, here's how it's done in my program... I did shadow mapping in exactly the same way as in this tutorial: http://www.paulsprojects.net/tutorials/smt/smt.html

The only differences are that I'm using QT which makes some things simpler, and I have my own scene that's different than the scene in the tutorial... so the GL_TEXTURE_2D is used for the shadow mapping in the whole program. Before rendering the third pass, there are a few glTexGeni functions called, which apparently define how the GL_TEXTURE_2D is projected on the objects in the scene... is there some way to make OpenGL kind of forget all that before rendering the grass cell, and then restore it? Or maybe it can be fixed in some different way?

##### Share on other sites
Thaumaturge    3826

You use glTexCoord in much the same way that you might use glVertex, to specify coordinates in a space, in this case the space of your texture (commonly a two dimensional space, of course), as opposed to the space of your model. While the vertex coordinates specify where the object's vertices are in world-space, the texture coordinates, as I recall, specify where it is in texture space.

So, for example, take the following quad in world-space:

 (-1, 1, 0)             (1, 1, 0)           o-----------o           |           |    y           |           |    |  z           |           |    | /           |           |    |/___ x           o-----------o (-1, -1, 0)             (1, -1, 0)

Similarly, take the following "image". Note that in an image, we also have coordinates in a space:
     (0, 0)             (1, 0)           o-----------o     ____ x           |    __     |    |           |   /  \    |    |           |  /____\   |    |           | /      \  |    y           o-----------o     (0, 1)             (1, 1)

Just as we tell OpenGL where the above quad was in world-space, we can tell OpenGL where it lies in the space of the image:

glBegin(GL_QUADS);glTexCoord2f(0.0, 0.0);glVertex3f(-1.0, 1.0, 0.0);glTexCoord2f(0.0, 1.0);glVertex3f(-1.0, -1.0, 0.0);glTexCoord2f(1.0, 1.0);glVertex3f(1.0, -1.0, 0.0);glTexCoord2f(1.0, 0.0);glVertex3f(1.0, 1.0, 0.0);glEnd();

Note that if you have a vertex that should lie somewhere within the image, then its coordinates would probably be appropriate values below one and above zero. For example, if we instead had two quads which, between the two, should be "covered" by a single texture, with the split occurring vertically in the middle of the image, then you might have something like this:

glBegin(GL_QUADS);//Quad 1glTexCoord2f(0.0, 0.0);glVertex3f(-1.0, 1.0, 0.0);glTexCoord2f(0.0, 1.0);glVertex3f(-1.0, -1.0, 0.0);glTexCoord2f(0.5, 1.0);glVertex3f(0.0, -1.0, 0.0);glTexCoord2f(0.5, 0.0);glVertex3f(0.0, 1.0, 0.0);//Quad 2glTexCoord2f(0.5, 0.0);glVertex3f(0.0, 1.0, 0.0);glTexCoord2f(0.5, 1.0);glVertex3f(0.0, -1.0, 0.0);glTexCoord2f(1.0, 1.0);glVertex3f(1.0, -1.0, 0.0);glTexCoord2f(1.0, 0.0);glVertex3f(1.0, 1.0, 0.0);glEnd();

The first quad should run from one side to the centre of the texture, and the second quad from the centre to the opposite side.

Note the pairing of glVertex and glTexCoord calls. If I recall correctly, the glTexCoord call applies to any vertices declared after it (presuming that another change doesn't supercede it, of course).

I think that I'm correct in my axes in the image example.

NB: If I recall correctly, you are not, technically, "applying the image to the object", as I'm pretty sure that I've heard it described. While one can think of it this way, especially for situations involving 2D textures, I believe that what is technically happening is that you are specifying where the vertices of the object lie in the texture's space.

I hope that I've explained all of that clearly - if not, please let me know, and I'll try to clarify what I mean, most probably with a proper (albeit simple) picture.

As to the shadow mapping tutorial that you linked to, I didn't see any alterations to the texture matrix offhand, but then I'm not familiar with the texture generation calls that they use; I imagine that they don't change the texture matrix, however.

That said, since they would seem to be generating texture coordinates, it could well be that this is carrying over to your quads. I notice that texture generation seems to be enabled there; I suspect that it might help to disable that once you're done with it.

[Edited by - Thaumaturge on May 14, 2008 10:22:10 AM]

##### Share on other sites
Starshine_    122
Thank you for the long explanation! It's working, and the texture is positioned correctly now :)

I still have a problem with transparency, though :( There's still gray in the place where the PNG with the image is transparent... here's a screenshot: http://i11.photobucket.com/albums/a156/Miracle86/notransparency.png

(the PNG with the texture is just a green MEEP on a transparent background, so everything except transparency is displayed correctly)

The only thing I need now to make my grass work is to find out how to do transparency... maybe I need to add the alpha channel to the texture separately somehow? But according to QT documentation, the bindTexture function uses the GL_RGBA format by default, which already includes the alpha channel...

edit: I did it! :D it's working... well, almost, but I'm happy with it. :) I had to disable GL_DEPTH_TEST before rendering the grass, and then enable it again. Now the transparency is working almost perfectly well. :) The transparent isn't perfectly transparent, but slightly white... but it's much better than what it was before. :) There's no shadow now, though.

edit2: without depth testing, the grass is visible even when it's behind other objects... :(

[Edited by - Starshine_ on May 14, 2008 12:44:28 PM]

##### Share on other sites
Thaumaturge    3826
It's my pleasure - I'm really glad to hear that you've advanced so far. ^_^

Quote:
 Originally posted by Starshine_edit2: without depth testing, the grass is visible even when it's behind other objects... :(

Indeed, I'm afraid that, for objects rendered with normal transparency (as opposed to, say, additive transparency), I'm pretty sure that sorting by depth is called for. You then draw from most distant to least distant to get what should be the correct result.

As to the slight whiteness, I would suggest checking in your image editor that those regions are entirely transparent, as opposed to being, say, 90% transparent. (Note: I don't recommend doing this by inspection; instead, I recommend examining the numerical representation of the colour in your editor (the means to this might vary by editor - I should be able to help you if you happen to use the GIMP).)

As to the lack of shadow, I imagine that shadow mapping is intended to be a two- (or more) pass system, meaning that you will probably be rendering your grass twice. I haven't programmed a shadow system of this sort myself that I recall, so I'm afraid that I don't know what the appropriate method of limiting the shadow to the non-transparent regions is; technically, it sounds as though you want some sort of multiplicative blending, but the stencil buffer might work.

 Finally, your results including grey fill previously prompt me to ask: when are you rendering your grass? It should be rendered after your fully-opaque geometry, I believe.

##### Share on other sites
Starshine_    122
I'll check it with Gimp :) but I'm not sure why there would be any whiteness, since I made that PNG in Gimp... I started with a totally transparent one and only added the text...

And yes, I'm rendering my grass after everything else in each of these 3 passes... the first pass renders the scene from the light's point of view and saves it to the GL_TEXTURE_2D, the second one renders a dark scene, and the third one renders the parts of the scene which aren't shadowed, so that they are brighter than the shadows... I think it's doing it by somehow projecting that texture saved after the first pass on the scene from the light's point of view. Maybe something's wrong when I also use GL_TEXTURE_2D for the grass texture and then don't change it back... I don't know how to do it, though...

##### Share on other sites
Tenac    124
Well, I use SDL to load my .png images and it works. Maybe add this if you haven't already?

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

and make sure you use GL_RGBA since there are 4 alpha channels.
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, image->width, image->height, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);

##### Share on other sites
artefon    122
this is also happening to me!

when i enable BLEND:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

the window gets black :(

this is my results:

Blitting using SDL:
http://img375.imageshack.us/img375/7909/sdlfw2.png

Using OpenGL:
http://img48.imageshack.us/img48/3606/opengltd4.png

##### Share on other sites
Thaumaturge    3826
Starshine_, I've taken a look at some of the description given in the tutorial that you linked to, and I think that I have a possible source of your grass not being shadowed.

According to the tutorial, part of the process is having OpenGL cull front faces, and record the depth results for the back faces. Since drawing the grass involves disabling depth testing, the depth of whatever was drawn behind the grass is used, leading to grass generally being lit. Similarly, when the depth of the point in question is tested to see whether it should be shadowed, it should produce the depth value for whatever was rendered behind the grass, which may well be unshadowed.

You might be able to get around this by rendering the grass into the stencil buffer, and then re-rendering with depth writing and testing on. There might also be a way to write to the depth buffer conditionally, having it write only when the alpha value is 1.0, although if there is, then I'm not sure of what that may be, offhand, I'm afraid. :/

However, I may well be wrong in some or all of this, and I'm not sure that my suggestion above is the best solution. I may well take another look once I've had some sleep, however. ^^;

artefon, may I please see your texture setup code for that texture map?

##### Share on other sites
Starshine_    122
Thanks for telling me! I'll try do it later. :) Right now the grass shadow isn't my main concern yet... and at the moment I'm not even going to touch stencil buffers unless they are absolutely necessary, because I have no idea what they are, and I need to have the grass (even if it's without shadow yet) finished for Monday. O_o

Right now my main problem is still correctly displaying grass, because two things aren't working yet when I disable depth testing and render things that are farther away first. When I put an unshadowed grass cell behind a shadowed object, then the grass cell is still visible, because the third pass renders unshadowed elements (such as the grass) without rendering shadowed ones, so that even if there's a shadowed object in front of the grass, it doesn't cover it. I've read somewhere that it's possible to combine the second and third passes of shadow mapping together, maybe that would help somehow? I have no idea how to do it, though... and I don't know if it's easy or hard. I'm still an OpenGL newbie...

Another problem is that I don't know how to save the current GL_TEXTURE_2D so that when I temporarily change it, for example when rendering grass, I can change it back after that. When I looked in OpenGL documentation, I discovered glGet functions... but doing this:

GLuint currentTexture;
glGetIntegerv(GL_TEXTURE_2D_BINDING, currentTexture);

gives me the error:
'GL_TEXTURE_2D_BINDING' was not declared in this scope

as if there was no such thing as GL_TEXTURE_2D_BINDING :(

edit: I changed GL_TEXTURE_2D_BINDING to simply GL_TEXTURE_2D and it's working correctly :) Which is really strange, because it's against official OpenGL documentation which I found here: http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/get.html

I still have the first problem, though :(

##### Share on other sites
Thaumaturge    3826
Hmm... According to this documentation page (from the documentation that I tend to use), it appears that you should be using GL_TEXTURE_BINDING_2D - note that "2D" comes after "BINDING" in this version. According to that same page, GL_TEXTURE_2D should return to you a boolean value, indicating whether 2D texture mapping is enabled or not. It occurs to me that if your texture binding happens to be 1, then using GL_TEXTURE_2D might appear to work, but for the wrong reason...

As to your visibility problem, surely you're writing to the depth buffer on your first, shadowed pass from the camera's perspective?

It occurs to me that surely you should be disabling depth masking (via glDepthMask(true/false)), rather than depth testing, for transparent objects? After all, semi-transparent objects should be tested against existing depth values (so that they're clipped properly), but not themselves write new depth values, so that transparent sections don't obscure objects behind them.

I'm sorry for not mentioning this earlier - I think that it did occur to me, but that I put it aside, perhaps because your code appeared to be working.

Perhaps, if you don't have depth masking disabled for the grass, try doing so. Presuming that depth masking is on otherwise (as I imagine that it is), you should have something roughly along these lines:
//In your rendering code//Perform everything intended to happen before grass is rendered//If depth testing is off, enable it here//Disable depth testing, so that the grass won't write to the depth bufferglDepthMask(false);//Render your grass, in order from furthest to nearest.//Re-enable depth testing, so that other things will perform depth writesglDepthMask(true);

If that doesn't work, then perhaps you should look into fitting a write into the depth buffer from the camera's perspective into your passes somewhere, preferably, I would think, as part of one of the existing passes (perhaps the "shadowed" pass).

As to combining the second and third passes, I don't know, I'm afraid. :/

Have you done any research on combining them, yet?

##### Share on other sites
Starshine_    122
Thank you, that worked... it's generally displaying correctly now :D so I don't need to combine the two passes, hopefully. :)

It's strange that OpenGL has two different documentations which say different things. The one I found was the first result in Google... but maybe it's old?

There's still that little problem with the grass not being totally transparent... it's a small problem, but here's a screenshot...maybe you'll have an idea about what's causing it. Here it is: http://i11.photobucket.com/albums/a156/Miracle86/weirdtransparency.png I checked that texture in GIMP, and it's supposed to be totally transparent everywhere except for the text...

I also have another question, kind of unrelated to the topic, but you know a lot about OpenGL so maybe you'll know how to help. :) What's the easiest way to render the shadow map (the first pass) to a framebuffer and then to the texture, so that it's not rendered on the screen? I've tried using QGLFramebufferObject, but it's giving me strange errors. So I can try to do it using normal OpenGL functions for framebuffers, without using QT ones... but, to be honest, I don't really know how...

##### Share on other sites
Thaumaturge    3826
I would guess that the documentation that you found is indeed old.

As to your problem, that does look odd - it's not what I had imagined, I don't believe. Does it change at all as the point of view changes? If you change the colour of the backdrop plane, or the clear colour, does the colour of those lines change? I find it interesting that it only seems to show up against the cube, despite the floor plane having different shades of grey, thanks to the shadow.

As to rendering to a frame buffer, I'm afraid that I don't think that I've done that before, myself. Some searching (primarily of this site) turned up this article and these two threads; I haven't read much of them myself, and the article is a few years old, but might provide some help. It may be that there is a more recent method for creating framebuffers, or a more recent structure for that. I'm sorry that I'm not of more help on this. :/

Anyway, I don't think that I know that much about OpenGL #^_^# - what I know comes from experience with and use of it, having encountered discussion of such things elsewhere (particularly on this forum, I believe) and - notably - having found some good places in which to look when I want more information. ;)

##### Share on other sites
Starshine_    122
I've tried doing some stuff and I found out three things... first, the color of the grass element around the word "MEEP" depends on the color which I set using glColor4f before rendering the grass quads. For example, when I set the color of the quads to green, here's what I got:

http://i11.photobucket.com/albums/a156/Miracle86/weirdtransparency2.png

as you can see, I also changed the color of the floor, but that doesn't affect the grass...

The second thing is that the color around MEEP only appears when it's rendered in front of shadowed areas... here's a screenshot which shows it better:

http://i11.photobucket.com/albums/a156/Miracle86/weirdtransparency3.png

The green thing doesn't show when it's rendered in front of unshadowed parts of the floor and an unshadowed face of the cube...

And the third thing I've noticed is that the intensity of the color around MEEP depends on the intensity of ambient light and shadowed light (the light used in the second pass which determines the light intensity of shadowed areas). With both the ambient light and shadowed light intensity set to zero, so that shadows are almost black, the color around MEEP is almost totally transparent. By the way, isn't it strange that with both ambient light set to zero and shadowed light set to zero, shadowed areas aren't totally black? Hmm... anyway, here's a screenshot :)

http://i11.photobucket.com/albums/a156/Miracle86/weirdtransparency4.png

And thanks for the link to the frambuffer tutorial, it seems that it's going to be really useful to me ^_^

##### Share on other sites
Thaumaturge    3826
Hmm... Well, from this I'm guessing that the erroneous sections are being drawn during the shadowed pass, with lit sections of geometry overdrawing them during the lit pass.

Since the erroneous results react to glColor and the current light source, and they can take a colour other than that of the floor plane, they would seem to be something drawn on the grass planes. This seems to me to suggest either an incorrect texture, or, given the sort of thing that you're doing, incorrect texture coordinates (or both, of course ;P).

So, are you drawing the grass at all during the shadowed stage? If so, are you sure that the grass texture is valid at that point, and that if it is, that it is the selected texture at that point, and that the texture coordinates are being properly set in that pass?

For that matter, if you comment out the entire lit pass (including any drawing of the grass in that stage), what do you get?

Quote:
 Originally posted by Starshine_And thanks for the link to the frambuffer tutorial, it seems that it's going to be really useful to me ^_^

I'm glad to hear it, and it's my pleasure. ^_^

##### Share on other sites
Starshine_    122
Yes, it seems that it's happening during the second pass, since when I comment out the second pass, it doesn't appear there anymore. But it's really strange, since for each of these passes the objects are rendered using my drawScene() method which always works in an identical way... so the grass texture is always rendered in an identical way too. Since the text in this textures is positioned perfectly, then it doesn't seem to be the source of the problem... for some reason the second pass creates that weird thing.

##### Share on other sites
Thaumaturge    3826
First of all, my apologies for the delay - I seem to recall that you have a deadline. ^^;

The second pass is the shadowed path, correct? I'm wondering whether the error appears over the full extent of the grass quad if the lit pass (which is pass three, based on the tutorial that you linked to, I think) is omitted.

Hmm... I'm not sure what the cause might be, but I wonder whether it's not related to the front-face culling used in the shadowed pass. It could also be related to the lit pass setting transparency as it goes...

Perhaps it would be better, for now, at least, to remove the grass rendering step from the shadowed pass, and only render the grass in the final lit pass?

If you have access within your program to information on whether a particular position is lit or unlit, you might be able to use that to create a rough shadowing effect on your grass.

##### Share on other sites
Starshine_    122
it's ok, I have so many problems that I won't be able to do everything perfectly for the deadline anyway... I hope the teacher understands that it's too difficult to do perfectly for someone who never did anything with OpenGL before. :)

As for the culling, it's disabled when rendering grass, because otherwise the grass doesn't render. And according to that page describing the method of making grass, culling should be disabled. :)

I removed rendering grass from the second pass, and it's okay now. The weird thing around grass doesn't appear anymore, and everything else looks just like it looked before. :) Of course there are no shadows on the grass, but that's probably because the shadow map isn't applied on the grass, because while rendering it GL_TEXTURE_2D is set to the grass texture instead of the shadow map. I was thinking about it and I couldn't find any way to get around that limitation...

By the way, do you know what buffer objects are? I'm supposed to learn about them too, and I haven't even started yet... o_O

##### Share on other sites
Thaumaturge    3826
I'm sorry to hear that you're behind, but glad to hear that you seem to have things more or less working.

If you have time, I think that I'd be interested to see a screenshot of the final results - why not post one here? ^_^

As to buffer objects, I'm not sure of what specific objects are intended; you already know about framebuffer objects, which might count, for example, but they may also mean vertex buffer objects (just search - you should find plenty of references, I imagine).

PS: By the way, we're not actually supposed to answer homework-related questions, at least not much beyond hints, I don't believe. :P

[Edited by - Thaumaturge on May 18, 2008 2:17:30 PM]

##### Share on other sites
Starshine_    122
I think it was supposed to be vertex buffer objects. :) I've read something about them, and then I've read something about lists, and from what I've seen, lists seemed to be better for my grass than vertex arrays, so I used a list in my program. :) Do you know if there would be some speed advantage if I used vertex arrays and glDrawElements instead of compiling a list in the constructor and then using glCallList to render grass elements?

As for my final result... well, I don't think it's final yet, but the grass is generally done for now.. it's far from perfect, and maybe I'll have to improve it, but here's a screenshot of what I got so far :) http://i11.photobucket.com/albums/a156/Miracle86/sortoffinal.png

As for homework related questions...well, some things are impossible to find out without asking on the forums, because documentation is often kind of hard to understand and contains no examples... ^_^ and I only ask about some specific things which I need to use for homework, I'm not asking anyone to write the whole homework for me :)