Fog and multipass rendering

Ok, the thing is, I’m currently using two redering passes to draw my terrain, one pass for each tiled texture (along with a greyscale map for blending textures together). When initializing OpenGL, I set fog color to light blue, and this works, I’ve tried. But when I enable foggin with my two passed, the fog color goes white.

Fogging works with one pass, but as I said, goes berserk with two passes. Is this a known issue, or can it be my not_so_proper setup that somehow adds the fog values from the previous pass (maybe it’s not white, but two light blue fogs added together)? Never have any problems with fog besides in my two passes.

Currently I’m using NVidias drivers 5.2.2 for my TNT, if that is the problem.

Have you tried turning on the fog just for the second pass? That might work as fog is posttexture. Of course that bites as then you are forced to constantly turn fog on and off. But I don’t see any other way myself other than doing your own fog calculations

Can you describe what you are doing in a bit more detail? What are the two passes? How do you set them up and draw them? How do you blend them?

Fog is after texturing and color sum. Doing fog when you are doing multipass tends to get a bit strange, because you only want to fog the final color, and you only want to fog it once.

For example, if you were rendering base texture plus detail texture in multipass with additive blending, to get proper results, you’d have to set the fog color to black in the second pass to make sure that (1) the fog causes the detail texture to fade out and (2) the fog doesn’t get added twice.

  • Matt

Oh well, will try to give some more details. Not at home now, so can’t try these new methods, but I will get back with results later.

What I’m doing, is that I build a terrain mesh. It’s strored in a vertex array, and I redraw the whole terrain mesh in the two passes, using different textures for each pass. First pass is basically a texture multiplicated with a greyscale mask. Second pass is something similar to (1-G)*T, where G is the mask and T is the texture. The greyscale mask is same in both passes.
What I can’t understand is that in the second pass, where the mask is completely black, should completely replace the current pixelvalue in the framebuffer, and therefore also the fog, and only one fog value whould be applied. So this makes me think that the problem can be with the multitexturing, and not multiple passes. I know I said it works with one pass, but maybe I lied, maybe it was with one pass AND second texture unit disabled, I realised that this can be the case .

DFrey: Fog only in second pass. Noted, this is one thing I will try. And, what do you mean by calculating my own fog? Passing my own fog coordinates with the fog_coord extension? Won’t this have the same effect because it’s still fog but with other coordinates? And I can’t set polygon color, because this is pretexture, and also because colors are ignored, this only screws up my miltitexturing, as it is now at least.

Anyways, will try these new things out and get back later.

And, what do you mean by calculating my own fog?

I mean actually calculating the fog color at each vertex and blending a smooth shaded polygon over the terrain polygons as a third pass. In other words, you do the fog, rather than have OpenGL do the fog. Something I’d really only consider doing for volumetric fog myself. For what you want I think just effectively drawing the fog during the second pass will be good enough.

[This message has been edited by DFrey (edited 10-14-2000).]

Ok, got some more details now.

This is the code I use to setup the first pass.

glBlendFunc(GL_ONE,GL_ZERO);

glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, hmask);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, tex1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_ONE_MINUS_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);

glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_BYTE, vertList);

And second pass is the following.

glBlendFunc(GL_ONE,GL_ONE);

glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, hmask);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, tex2);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);

glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_BYTE, vertList);

Sidenote: depthfunctions and other semirelevant stuff is also changed, but not shown here.

As you can see in the second pass, I use an additive blending function, which is the source of my problem. I didn’t noticed it until DFrey said I should enable fog in the second pass only. This idea wasn’t successfull, but thanks anyways, becasue you made me find the problem

I tried to change the color of the fog, and it was as I thought. The fog is added in the two passes. Now, I came up with another idea. If everything except the color of the fog look OK, then maybe I can do something about it. Since the fog is added in the two passes, why not set fog color to half of what it should be, and therefore added together to the real fog color. And… IT WORKED!

It’s not a nice solution codewise, but rather a “clever trick” i suppose. If I want three passes, I just divide the actual fog color by three instead.

The mesh which is generated is not the whole terrain, but rather smaller patches of the terrain. So I’m going to implement a routine to check what textures is involved, and only draw these passes, to prevend unnecessary rendering. However, this will ruin the whole trick with the fog, because some patches, the ones only draw once, will only get half the fog. So if anyone got some idea/trick to solve this fog problem, I would really appreciate if you shared your knowledge.

I’m not planning to give it up just because I know how to handle the problem. The problem is still there.

Bot so far, loads of thanks to both of ye.

And yeah, to you DFreay. Drawing the fog in a last pass is indeed a solution, I know what you mean now. But, the performance hit for each additional pass is noticable on my card, a TNT as I said above. Have not yet tried it on faster cards to see if it’s a a fillrate issue. If so, it probably will run faster on newer cards. I have at least tried to lower the resolution, and there was an increase in the framerate, so I believe its related to fillrates. So if I can’t some up with any solution at all that fits my needs, this might be THE solution.

You could always use the real fog color on the first pass and then set it to black for all subsequent passes.

  • Matt

If you used fog during the first pass only, that would seem to me to potentially introduce problems with later blended passes in general (not any particular case). It just seems to me, that since fog was designed to be posttexture, that you would continue to want it to be posttexture even in a multipass scenario. Sort of ‘post-multipass’ fog is what I’m thinking.

[This message has been edited by DFrey (edited 10-15-2000).]

Doh, why didn’t I think of that one. Black fog in all subsequent passes Yeah, the idea is the same, but I toss all the fog in the first pass instead of splitting it over all passes. So I guess this will work with a given fog color and a given number of passes, just what I wanted.

And I rather not do the extra pass only to get fog, when I can get it automatically in the passes in NEED to draw, but as I said, will keep it in mind if problem arises.

You guys’ solution of fogging during only one pass or using black the second pass works fine if the second blend function is GL_ONE, GL_ONE, or some other additive blend. But what if you have a multiplicative blend like this:

glBlendFunc(GL_ZERO, GL_SRC_COLOR); ?

If you are using the multitexture extension, you can do this combination and get fog to work “right”. If you are doing multi-pass rendering, you can’t (or at least it is very difficult).

What you want is for the final color to be fog(C1 * C2) but what you get is either fog(C1) * C2, C1 * fog(C2), or fog(C1) * fog(C2), none of which are the same.

My question is this: Supposing the above blending, how can you make fog look the same in two pass rendering as in a one pass multitexture rendering?

– Zeno

You do a third pass, for fog… It’s not a good situation no matter what.

To make things worse, you really want to put the fog factor in your pixel’s alpha so you can blend using the fog factor. There is only one way I know to do this, and that would be to use register combiners (put the fog alpha in G on the final combiner).

The alternative is to use textured fog in the fog pass, but this requires a fog texture and makes the fog pass more expensive; with register combiners, it can at least be an untextured pass, which is a little cheaper. You also can’t use radial fog for textured fog.

  • Matt