TextureUnitStates vs. Precompiled Texture

Hi
I want to put different textures on my terrain. Like grass, sand… There are two ways of doing this I think:

  1. Using TextureUnitStates and mapping (maybe also non-tileable) textures, which fade to their ends, randomly over the terrain. There, where sand is I use more the sand texture, where grass should be I use the grass texture.
    This would probably give a very nice look and there can be also slow fades between grass and sand. On the performance side I’m very sceptical, because it would probably use loads of TextureUnitStates, which probably take a lot of the rendering time. + I don’t really know how to do this distributing of the textures.

  2. Generating the texture fades before using the textures and saving the generated textures in one big texture file. For each quad in the terrain a texture-type (grass or sand) will be applied. Depending on the surrounding texture-types the texture (fade) will be set for the quad. I tried to implement this version, but I stepped over these problems:

  • the created file is (for a texture size of 256256) 2562562^9 (there are 9 surrounding texture-types, so 2^9 different textures) pixels big. If this data is saved in ints this will be 2^82^82^94 = 2^27 byte = 2^7 mb = 128 mb
  • because of this I always get OutOfMemoryError when trying to load it (I tried already with -mx500m). Are maybe all tyles saved again on the terrain squads? (I got 10 000 of those [10 0002^184 = approx. 2^33 = 8 gb])

Is ther maybe a third way or someway to imorove these approaches. Or is maybe no.1 not that bad as I think?

Arne

I think you should use multiple texture states since, if you don’t, you will always encounter texture and memory size problems.

There are quite a lot of resources on the net on the subject. Here are some references ;

In the Xith3D getting started guide ;
http://xith.org/tutes/GettingStarted/html/more_fun_with_textures.html#SECTION00073000000000000000

From GameDev ;
http://www.gamedev.net/reference/articles/article2238.asp

I don’t know how well these techniques can be integrated with the existing Terrain support in Xith3D since I never had to use it.

     Vincent

Thanks for the links! The second one helped a lot. I hope this ‘trick’ works.

Does anybody know how textures are handled inside xith/jogl - just interested, cause you have to know how something works to use it best :wink:

Arne

In Xith3D, textures are defined through the Appearance object which has a setTexture method for defining a single texture.

When you are using multiple texture, you use the setTextureUnitState method which lets you define multiple texture state, i.e. multiple texture.

The combine method is specified in the TextureAttributes object associated with the TextureUnitState object.

Internally, the rendering pipeline transforms texture in shader state which are then renderer by the JOGL or LWJGL renderer.

The renderer use the MultiTextureARB OpenGL extension to render texture (driver whithout this extension won’t work with Xith3D default renderers).

Note that for the moment, the implementation does not check for the availability of the required texture states. The ARB extension defines that a graphic card should at least offers 2 texture state ; it is safe to rely on that. Most graphic cards offer more than 2 texture state 4 or 8 are a minimum nowadays.

 Vincent

Thanks for the info

Hmm… for these Decal groups I need to have textures that are partly transparent, right? So how can I load the alpha channel, too? I always get black, where it should be transparent.

You have to use the appropriate texture loader function.

Here is an extract of a simple (but a bit slow) code that performs alpha texture loading correctly ;


        imageAppearance = new Appearance();
        Texture texture;
        BufferedImage dbi = TextureLoader.tf.getImageAlpha(imageFileName);
        if (dbi.getColorModel().hasAlpha()) {
                        texture = TextureLoader.tf.getMinMapAlphaTexture(imageFileName);
        } else {
                        texture = TextureLoader.tf.getMinMapTexture(imageFileName);
        }
        imageAppearance.setTexture(texture);
        TransparencyAttributes transAttr = new TransparencyAttributes(TransparencyAttributes.BLENDED, 0f, TransparencyAttributes.BLEND_SRC_ALPHA, TransparencyAttributes.BLEND_ONE_MINUS_SRC_ALPHA);
        imageAppearance.setTransparencyAttributes(transAttr);

Hi
I tried that and first of all it only seems to work with directly set Textures, not with TextureUnitStates. Second It does funny stuff, if it is applied on top of another Shape (like with Decalgroups). Here’s a screenschot:

http://www.wi-bw.tfh-wildau.de/~_amueller/screenshot.jpg

The underlying texture is only visible at totally transparent parts and it is totally ignored, where the transparent texture is not totally transparent.

This is strange, isn’t it? What can I do prevent this?

Arne

Because of the problems with TextureUnitStates i came back to thinking about precompiled textures.
I think the reason for all the required memory is the mipmap creation. The texture-file is only 112mb in bmp-format(pixel for pixel without compression; it’s only 4 mb when saved as jpg)

So I thought what about having a JPEGImage class that calculates the pixel value on the fly with a given resolution, so the whole data hasn’t to be stored. Or maybe it has a function that gets a part of the image in a given resolution, so mipmaps don’t have to be saved.

If these functions would go fast this would be a good memory saving, wouldn’t it?

Arne

Yout right, my previous post is for single texture only. It was mainly to show the way to detect & load the alpha channel with the provided TextreLoader class.

When using multi texturing, you have to set for each TextureUnitState the TextureAttributes.

It’s in the texture attributes that you define the blend / combine methods. Therefore, here is a quickly modified version of my previous code (not tested) ;


Texture texture1;
BufferedImage dbi1 = TextureLoader.tf.getImageAlpha(imageFileName1);
if (dbi1.getColorModel().hasAlpha()) {
    texture1 = TextureLoader.tf.getMinMapAlphaTexture(imageFileName1);
} else {
    texture1 = TextureLoader.tf.getMinMapTexture(imageFileName1);
}
TextureAttributes ta1 = new TextureAttributes();
TextureUnitState tus1 = new TextureUnitState();
tus1.setTexture(texture1);
tus1.setTextureAttributes(ta1);

Texture texture2;
BufferedImage dbi2 = TextureLoader.tf.getImageAlpha(imageFileName2);
if (dbi2.getColorModel().hasAlpha()) {
    texture2 = TextureLoader.tf.getMinMapAlphaTexture(imageFileName2);
} else {
    texture2 = TextureLoader.tf.getMinMapTexture(imageFileName2);
}
TextureAttributes ta2 = new TextureAttributes();
TextureUnitState tus2 = new TextureUnitState();
tus2.setTexture(texture2);
tus2.setTextureAttributes(ta2);

TransparencyAttributes transAttr = new TransparencyAttributes(TransparencyAttributes.BLENDED, 0f, TransparencyAttributes.BLEND_SRC_ALPHA, TransparencyAttributes.BLEND_ONE_MINUS_SRC_ALPHA);

groundAppearance = new Appearance();
groundAppearance.setTextureUnitState(0, tus1);
groundAppearance.setTextureUnitState(0, tus2);
groundAppearance.setTransparencyAttributes(transAttr);


You will have to tweak the TextureAttributes parameter to get the desired result. I suggest that you have a look to http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=22 to get a better understanding of OpenGL multitexture combine functions.

The solution of precalculating the texture is a bad one. Even if it’s only a 4meg in JPEG, it will be far more when decompressed in the wideo memory. The compressed format used by graphic hardware are not standard and they are not as efficient as JPeg compression. So, I think that you need to solve your multi texture combine problem to get a suitable solution.

Bye

  Vincent

the xith org tutorial referenced by niwak “more fun with textures” shows how to layer (decal) texutres on top of each other with alpha blencing of the texture layers

Ok I played a bit more with the TransparencyAttributes, but then I got the idea to move the underlying Shape a bit down, so the overlying transparent texture did show. This worked pretty well. Here’s a screenshot:

http://www.wi-bw.tfh-wildau.de/~_amueller/screenshot2.jpg

The only problem I have now is the shading, there should be shading, because I had some before and I haven’t changed anything at the material settings.

Arne

I have managed the shading now, too.

Thanks for your help :slight_smile:

the only thing that bugs me is some flickering, because the underlying texture is drawn above the other, I don’t know why this happens, so I’m not able to fix it- I guess it has something to do with jogl, cause the shapes are still close together (0,1 m or less, depending on the slope)

I don’t think that you will get a satisfying result with Decal group objet of Xith3D.

Decal object are meant to be a way to let you choose the order of rendering of scenegraph object. Therefore, you will always have the flickering (due to the lack of precision of your z-buffer) that you can see now.

Another problem in your case with Decal is that Decal render 2 times the geometry. If you use multi texture, you will render just once your geometry. Therefore, you will get better performance.

I think the solution to your problem lies in the TextureUnitStates capacilities.

       Vincent

I’m not using Decalgroups anymore, because that didn’t worked, I used Branchgroups instead and moved the underlying Shapes with Transformgroups down.
What do you mean with “multi Texture” ? TextureUnitStates? I tried to use more than two TextureUnitStates , but I got some Error there- I don’t know if this is because of my Graphics card or some Error in my code.

To improve my speed I have now created SplitShapes and I don’t show the Shapes, that are not able to be seen (e.g. because a opaque Shape is above it, or because it is fully transparent).

Arne

PS: How can I see how many TextureUnitStates my graphics card supports?