Click here to Skip to main content
15,890,741 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

this may be an unusual question, but I also think it's very interesting. I am working on a little graphics engine and already have a landscape object which more and more is not up to what we need anymore.

The current object generates the mesh from a height map and automatically assigns textures according to the height of each vertex. There are four textures for different heights and texture weights to blend them are calculated when the mesh is generated as well.

Now I want to change this a bit by assigning a texture to each vertex and calculating texture weights when two ajacent vertices have different textures. Also the number of textures is not limited to four anymore.

For this I would have to pass an array of textures to the effect. In HLSL there is a data type for arrays of textures, but the Effect.SetValue() method seems not to allow me to pass an array of textures as value.

Also, it's not quite clear how to access the texture array in the shader itself. My first idea was to use 3D texture coordinates (U, V and the index of the texture to be used)

Unfortunately I could not find any example code which deals with this, but I have seen it being done in some programs, the landscape objects for good old Morrowind for example.
Posted

Texture arrays are (unfortunately) not supported in DirectX 9 (and therefore XNA)
I have code that deals with several textures at once myself, what have you tried so far?
One way to do it, just have multiple "uniform extern texture" declarations and multiple samplers in the HLSL part, set them the usual way with SetValue, and of course you can't access them by index, you'd have to select them "manually".
The obvious downsides are that you can only have 16 (or some other fixed number, depending on the shader version) of them, and you need special code to access each of them.
Is it possible for you to "cheat" and put all textures together in a mega-texture? That way you could simply calculate an offset.
 
Share this answer
 
Comments
[no name] 19-Sep-10 10:14am    
Thanks for your reply. I should have thought of XNA limping behind DirectX a bit. I guess it's time for a new XBox, so that they can update XNA.

I have posted a reply for you, but as an answer, which may not have been too wise. It's a bit lengthy and I did not want to repost it. Please just take a look there.

But I agree, combining several textures into one looks like the way to go.
Thanks for your reply. I guess a picture says more than a thousand words, so I have uploaded one to this link:

http://yfrog.com/74shader1j[^]

And anotherone, to show a bit more of the animation. The burning building and the smoke don't look very good as the particle effects just had started.

http://img409.imageshack.us/f/shader2.jpg/[^]

Here can you see a test scene with some objects (they are the first I ever made with Blender and I'm not a great artist), some particle effexts after a building just got hit by some weapon and also the landscape object I want to replace.

Right now it's created from a height map, but I'm going to change that. In the future I want to have multiple landscape patches, organized in a Quadtree (landscapes are quite planar, so an Octree is probably not needed). This will help to render only the patches which are visible in the current frame. Also, more distant patches are going to be generated with a lower polygon count as a further optimization.

The landscape patch in the scene still is too large and has too many polygons. Up to now it uses four different textures. The blending weights are calculated by height, which you can see very clearly in the screenshot.

For the new landscape patches I will need to write some kind of editor which will allow me to set the heights (fitting to ajacent patches) and 'paint' the mesh with a selection of textures. Uniting the textures in one bitmap could also be done here.

Does it have a performance impact if I unite up to 16 1024 x 1024 textures in one 4096 x 4096 texture? Also, I know that texture widths and heights had to be powers of 2 on older GPUs. Newer ones don't have that restriction anymore, so it's a good question if that still is an issue or not.

2 x 2 textures would work, but a maximum of only four textures would still be a bit restrictive. 3 x 3 would be ok for most cases, but the width and height of the super texture would probably then have to be expanded to the next power of 2. 4 x 4 may be a better choice with even more textures and probably not much larger than the expanded 3 x 3 texture.

And last, I'm going to have to think about how many sets of texture coordinates and weights every vertex must have. The optimum would be 8, as every vertex has so many neighbors which all may have a different texture. I suspect such a shader will be a bit slow.
 
Share this answer
 
v2
Comments
[no name] 19-Sep-10 11:09am    
It has some performance impact, but (in my experience) less than using several samplers. I don't know how it compares to texture arrays, I've never tested them.
You could get away with 8192 x 8192 textures these days..
Also, if you arrange the sub-textures in a nice way you might be able to avoid having a ton of blend weights - I'm not exactly sure how much flexibility you want to have, but in my case a certain terrain could blend only with a limited number of other terrains, and not all of them.
[no name] 19-Sep-10 16:50pm    
The 4 x 4 approach for the merged texture will give me up to 16 separate textures to use on any single landscape patch. This should be quite sufficient.

For starters I will reduce the texture coordinates and weights to three per vertex. This way up to three textures can be blended between any three ajacent vertices. This should be sufficient and I'm rid of one blending stage and the rigid height-based mapping.
[no name] 19-Sep-10 18:22pm    
I have spent some hours tweaking the landscape object and measuring performance. Some results are as to be expected, but I also learned something very surprising.

Let's start with the surprise: I changed the multiplier in the calculation of the texture coordinates. This changes how often the texture is repeated over the length and width of the landscape patch. I expected no big impact as the textures are sampled by interpolation and was very wrong. If the texture is repeated very often the performance degrades to a slideshow and if it is stretched all across the mesh the framerate goes up very high.

Then I changed the resolution of the height map, first to 1/2 with and height and then to 1/4, resulting in 1/4 and 1/16 the number of vertices in the mesh respectively. To my surprise the appearance of the landscape did not degrade as much as I expected and the performance went up.

Unfortunately I also had to adjustthe multipliers in the texture coordinate calculation, reducing the performance again. In the end I I wound up just where I started. The number of vertices appears not to be as important as it used to be. If you reduce it, you will gain performance and then lose it to the shader when adjusting the texture coordinates.

Next I will try to find out what impact larger and smaller textures will have. And I guess there is a bit more to be learned about the performance of the texture samplers. In the end I hope to have some parameters to tweak as performance settings for stronger and weaker GPUs.
[no name] 19-Sep-10 20:01pm    
Nice, so it's all good now?
By the way, does the multiplier still have such a large performance impact when Anisotropic Filtering is enabled? (or was AF enabled already?)
[no name] 20-Sep-10 5:49am    
All is good? I guess this will never happen :) There is always something unclear or in need of optimization.

But thanks for your advice. When you are working all alone you sometimes will not see the forest because of all those trees anymore.

Anisotropic filtering was not on, but I expect it to have a noticable impact. How about going for anisotropic light (brilinear)? Anyway, landscapes hold some nasty pitfalls. The landscape as it is now kills performance much worse than all other objects combined.

By the way - how did you like my test scene? Please have mercy, I'm not really an artist :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900