Expert help needed!

I am trying to solve this little puzzle with JOGL:

I have two textures. One is a mask, and the other is a normal flat texture. They are to be combined.

The mask is grayscale. A white pixel means the flat texture should be all visible at that pixel, black means leave the background as it is (transparent). Anything in-between should be semi-transparent.

It would normally make sense to use one texture with an alpha channel, but in this case it is not possible as the flat texture is to be tiled, while the mask is to cover the entire surface. (I need lower resolution for the mask than for the texture)

I know I need to use multitexturing somehow, but I have not figured it out. ???

Please help if you can…

I think this should work:

Pass 1: Darken the framebuffer where the image should be rendered

enable blending
blendFunc(ZERO, ONE_MINUS_SRC_COLOR)
render the mask

Pass 2: Darken the image where it should be transparent, and add to the framebuffer

enable blending
blendFunc(ONE, ONE)
set texture unit 1 to the texture
set texture unit 2 to the mask, mode MODULATE
render the mask+texture

If you keep the mask as an RGBA image instead with the alpha data in the A channel, you can do it in just one pass:

enable blending
blendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
set texture unit 1 to the texture
set texture unit 2 to the mask, mode MODULATE
render the mask+texture

Thanks for your reply.

I already tried the one pass approach you suggested here, and instead of getting transparency I get the color of the normal flat texture…?

Let me explain what I am actually trying to do:

I am rendering a landscape, and across it I am stretching a texture. However, the landscape is far to big to use only one texture. We are talking about several kilometers in all directions, and close up details like grass and water is important.

The solution is to use tiled textures for water, grass, roads etc. It will give the desired amount of detail, without spending more texture memory than I have.

So, my solution is to render this using several passes, with each pass rendering a new layer of he landscape texture.

So, for example:

First the road mask is combined with the tiled roadtexture. Then the grass mask is combined with the tiled grass texture etc. In the end, all the layers combine all the various types of ground in the landscape. There are a lot of layers like these.

All the masks are non-overlapping, and in pretty low resolution. And the idea is to render them during multiple passes. Real time rendering is not cruicial, however speed is an issue.

I have managed to solve this with the exception of the transparency issue. I am getting black where I want to leave the previous layer unhampered on the screen during each new pass…

Either you need to encode the transparancy data in the alpha channel of the mask, or you can use the two-pass method I suggested.

Hm, after experimenting, it seems like the alpha channel is being ignored?

In my test I am simply rendering one single textured surface, with

gl.glEnable( GL.GL_BLEND );
gl.glBlendFunc( GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA );

The alpha channel of the texture is filled with changing values, gradually from 0 to 255. The texture renders like normal, and alpha is ignored?

Maybe it is not properly implemented for JOGL?

Sounds very much like you’re doing texture splatting?

Blending should work fine in Jogl, but theres a few things that could trip you up.

  • Check you’ve got the correct zbuffer settings. You’ll probably want LEQUAL so layers overlap properly
  • Check your alpha texture really is an RGBA texture and the alpha isn’t getting discarded.
  • Since you’re combining the two with multi-texturing, check your texture coords for both units.

You might want to try drawing each layer individually to check that they’re as you expect. Duplicating your alpha channel into the RGB (as greyscale) might also show if you’ve got problems with the mask texture.

Yes, I think the term is texture splatting… :slight_smile:

Maybe the texture is not properly in RGBA form, but it should be. I am using a texture loader found on NeHe’s page.

Does anyone have a texture reader that will positively work with transparent PNGs?

You can solve this in a single pass using the ARB lerp combine mode COMBINE_INTERPOLATE, it interpolates between input units 0 and 1 based on the value provided by input unit 2. I have successfully used this technique to do masked environmental mapping, blending between a texture and an environmental map based on a mask or constant color, works fine. This article http://www.delphi3d.net/articles/viewarticle.php?article=terraintex.htm should help a lot.

Cheers

Wolfgang

Will it work with more layers than you have texture units? In my case the number of layers to be mixed can be anything from 6 to 20…

An

int a[]=new int [1];
gl.glGetIntegerv(GL.GL_MAX_TEXTURE_UNITS,a);

shows I have only four texture units available :frowning:

This means I cannot use this approach, I will need to do this in multiple passes. But, how?

Of course, for that many levels you will have to employ multiple passes, but you still can use the interpolate combine mode in each of that passes. Just use interpolate to combine your textures with their respective masks, and then combine the passes using one of the standard blend modes. This article http://www.cs.auckland.ac.nz/~jvan006/multitex/multitex.html shows how to combine up to four textures into two units, I think you could adapt that technique to your work.

Cheers

Wolfgang

Thank you! I am getting very close to a solution now I think.

I only have one problem left, how to combine new passes with what is already in the framebuffer?

Say I render out grass and water in one pass. It is now on screen, and what is not grass or water is all black. This works perfectly now.

Then I want to render out roads and rocks in the next pass.

How can I combine it so the black parts of the next pass is not overwriting what was drawn in the first pass?

I tried blending, using:

    gl.glEnable(GL.GL_BLEND);
    gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE);

It works when the scenery is viewed from above, but when viewed from the side I get transparent overlapping polygons that blends together.

Sorry for asking such newbie questions, but I just started with OpenGL a few days ago… :slight_smile:

I figured it out, thanks for all your help! :slight_smile:

The problem was caused by a buggy textureloader. It was not written by me, so it took some time to notice…

I still don’t know how to do it? I am an opengl beginner,would you please give me some code on this problem?

I am also very interested in some code or some more info on the topic of texture splatting if someone has it.

Thanks //
Gregof

I’ve recently been trying some texture splatting on a terrain generator i’ve been working on.
Much the same as Sinsro, i’m trying to use, at any given time, up to 5 different textures as well as a shadowmap.
The tutorial given sadly only deals effectively with the final blending of a lightmap with the mixture of detail textures with what seems to be a single texture.
I was wondering if anyone has yet come up with a way to combine multiple textures and allot the produced texture to another texture unit
thereby allowing more complex combinations i.e.
TU0 = TU1 + TU2

i am not very in the know about how the pipeline works and if there is no way to perform TU arithmetic then that’s fair enough. Just waiting for someone more knowledgeable to clear this up for me! :slight_smile: