Texture Splatting

NOTICE: Enlightenment follows. If you or anyone looking over your shoulders prefers ignorance (aka "ignorance is bliss") then avert your eyes now. This is your only warning.



Good old Sun JavaDocs:


A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

Looks like I haven't run across "most implementations" so far, then… I have often solved performance issues in single- or multithreaded text processing intensive applications just by replacing StringBuilder- with StringBuffer usage.



EDIT: After a little bit of thinking, it occurs to the author that it might be not StringBuilder's fault, but something else in the conversion from implicit to explicit StringBuilder usage… and also, that he managed to hijack his own thread! Oh well…  :expressionless:

Thread hijacking is WRONG!  :stuck_out_tongue:

OK, webstart works now:

http://wwwhomes.uni-bielefeld.de/krabien/jmestuff/textureLayers/JMESplatting.jnlp

Test it :slight_smile:

Thats really nice Hevee

i would like to remove that simplewatershader class, since waterrenderpass can be configured to do exactly the same thing…anyone else using that old leftover class?

That worked a charm. Sweet feature.

as splatting can be easily done without shaders it would be nice with one of those too, anyone up to the task? :slight_smile:

I guess my code could be changed to a pure texture combine mode based solution, and originally I was tying to do just that - but being unable to find some in-depth documentation about how texture combine modes actually work, I got frustrated and went for the shader approach.

At some point I think I also got the impression that using texture combining would need 3 texture units per splat layer, whereas my current approach uses only 2 TUs per layer, and can probably be streamlined to use only 5 TUs for every 4 layers by packing the alpha maps into a single texture.

For me, the performance impact for having to resort to render passes for more than 2 splatting layers on top of the base texture on cards with 8 TUs outweighed the compatibility issues for cards that don't support shaders.

What about an abstraction that detects if shader support is there and uses it or fails over to the alternative without shaders?  Features like this I think would be nice in jME as we can hide more of the complexity of OpenGL and card-specifics and still have great features supported.

would be nice to have a cut off and not support older graphics cards IMHO - not sure when this could feasibly happen.



btw - how much is it for the cheapest graphic card to support shaders

well, since texturesplatting is very much doable on very sucky cards(on the old fixed function pipe) i think we should have a version that does it :slight_smile:

Well, there already is a fallback mechanism in my code, for whenever the card runs out of texture units. The tricky part is to make texture combine modes do what I want, and that's the part I gave up on during my last approach.

If anybody could give me some hints on how to properly do texture splatting without shaders, I'd be happy to take another go at that.

(MrCoder, you sound like you already have something in mind?)

what of BlackBluegL terrain shader, that (screenies) looks good real good I think someone else I forget who suggested that It might good to look at and come up one good solution based on all the the existing… I don't know but it just seems wasteful to have 2-3 seemingly good solutions to the same problem when they can be merged into one great solution…reminds me of the tons of jme model converters people was making all over the place.



my 2 cents 

Great demo hevee!



I would be VERY interested in using this code/idea in my project.  :wink:

@Liquidream (and everyboy else): Just use it, the code is free for all :slight_smile: All you need is the TextureSplattedNode class, and possibly TestTextureSplatting as some kind of tutorial on how to use it.

@mcbeth: BlackBluegL's approach to splatting is quite different from mine. He uses geometry information (height, and/or probably slope) to determine texture blending values, but my goal was to use image alpha maps. Also BlackBluegL's shader comes wit built in normal mapping, or so I think, while mine doesn't :wink: So I think there's not really much to combine here, but rather a good example of a situation where it makes sense to have different tools for different needs.

there are tons of ways of using the texture combinemode in the fixed function pipeline to achieve splatting offcourse. here's one way, just modding the good old TestBox class and using the few sucky textures that has alpha in the jmetest data folder :wink:

instead of passes you would offcourse create a node that just sets the states and draws the geometry several times…



public class TestBox extends SimplePassGame {

Thanks for the example, MrCoder - however, this is not quite what I was aiming for. Your code uses the Alpha Channel of the "splatmap" to determine splat texture alpha values, while I was aiming for a solution utilizing color channels - is that even possible using the fixed function pipeline? E.g. to use the red channel of the texture in TU1 instead of it's alpha channel?

no i don't think that's possible. but what you are aiming for is just an optimization.



i'm just saying that doing it this way is not as bad as people might think:

  1. it works on "all" computers
  2. it's easier to create standard alpha textures compared to packing in channels(and editors like freeworld exports to normal alphatextures etc)
  3. the speed increase of packing and combining through a shader was so small in the spirits demo we did that we just dropped it and used this way. might not be true for newer cards, but on the other hand they don't have much problem with pumping triangles anyway. so it's a balance between being pixel bound(due to heavy shader) or vertex bound(due to drawing the mesh several times)
  4. since you use the fixed function pipeline your splatted geometry can use the normal lighting system, whatever amount of basic multitexturing you wish and fog without having to change the shader for every setup. with a shader you would have to add lots of code for every light added etc etc…
MrCoder said:

3) the speed increase of packing and combining through a shader was so small in the spirits demo we did that we just dropped it and used this way. might not be true for newer cards, but on the other hand they don't have much problem with pumping triangles anyway. so it's a balance between being pixel bound(due to heavy shader) or vertex bound(due to drawing the mesh several times)

OK, so my implementation of the fallback solution is just bad; I kinda suspected that :D
I am using SharedNode to create layers in my fallback mechanism (which is used once all TUs on the card are used up, or a defined maximum has been used), I was under the impression that that should be enough to do what you suggest:
MrCoder said:
instead of passes you would offcourse create a node that just sets the states and draws the geometry several times...

With my approach, however, i get quite a bit of performance improvement from using shaders and many TUs instead of two TUs per layer and shared geometry.
Could it be possible that using many TUs reduces the number of gl state switches as well?
Anyway, the webstart demo has been updated, you can now specify a maximum number of texture units to use for splatting - setting it to 0 or 1 will enforce my fallback mechanism from start, so you can see for yourself how it compares to the TU-heavy approach.
Oh, and btw, thanks for all the input, it's appreciated! :)