Jump to content
  • Advertisement
Sign in to follow this  
mind in a box

How to texture this "monster"?

This topic is 3080 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My engine supports a terrain which can get generated out of voxels (Converted to polygons), so you can make nice caves and mountains as well as flat landscapes pretty easily. For texturing it, we use Triplanar texturing, so the thread title doesn't fit really. My main question is: How can I have different Layers of shader materials on it, like grass, mud and stone.

To make you familiar with that what I'm talking about, here is a picture from our ModDB profile (Pretty old version, the newer are smoothed [smile]):
Terrain
(http://www.moddb.com/engines/wtech/images/terrain)

The whole terrain is made out of chunks, which are little meshes. I divided it into them because then, the regeneration of the meshes is faster than parsing the whole Voxel-Volume, even at locations which are untouched.

That means, the whole terrain has a large Polygon/Drawcall count.


I've made some thoughts about this, and now I would like to know if there is a better approach, or if someone knows an optimization, or just feedback [smile].

All of my "Algorithms" start with having one Hi-Res voxel-volume for the geometry and for each layer one low-res volume, which look like the main volume, just in a lower resolution (Those volumes aren't very memory friendly)

While the main volume holds the values to smooth the terrain (I won't go further into that), all layer volumes can hold a alpha value for each voxel, in a range of 0..255.

Lets say we have 3 layers, a Grass, a Mud and a Stone layer.


Approach Nr. 1, Layer-Meshes:
Generate as many terrains as we have layers, here 3.
Now, for each vertex in the Layer-Mesh parse the Layer-Volume, find the nearest Voxel to it and assign an alpha value to it. Do this 3 times with 3 meshes and we have 3 meshes which have the alpha values of the layer.

Then render all 3 Layermeshes with different shaders, with the given alpha value, and blend them together.

This would do it, but results in a giant fillrate and draw call count.



Approach Nr. 2, Terrain-Shader:
As I can't use normal UV-Mapping for the textures, there are free places in the vertices. These are: UV (Two channels), Tangent (Three channels) and Binormal (Three channels).
Then, instead of making a mesh for each layer, the alpha value could go into them. This would give us up to 8 layers. Then render it with one shader and let it blend all layers together (. This would only require one render of the terrain, but one shader would have to do everything. And this could get pretty messy and slow. Also the artist who is working with my engine isn't a "shader warrior", and I don't want him to write such complex shaders.


Approach Nr. 3, Deferred Rendering:
Do it like in Nr.2 and put the alpha values into the vertices. Then, render the terrain once with a special shader which writes the Position and Normals (Needed for Triplanar texturing) to rendertargets. Since I have a deferred renderer for the lighting already set up I don't need to do this anymore and I can use this instead. So the Terrain-Shader only needs to write the alpha values to one or two R8G8B8A8 rendertargets, according to how many layers we have (Maximum of 8).
When we have that, render a fullscreen quad for each layer (With the right alpha value), which puts the texture and effects onto the terrain.
This would provide the possibility of using multiple shaders for the layers and I only need to render the terrain once. However, there is a second "Layer-Pass".


What would you advise to me? Or do you maybe have a completely different idea of how to do that? [wink]

[Edited by - mind in a box on July 12, 2010 3:38:02 PM]

Share this post


Link to post
Share on other sites
Advertisement
Go to the developer.nvidia.com site. I believe GPU gems 1 (or one of the others) had a procedural texturing terrain. I think they did various texture projections from top,side etc and did some algorithm after that.

Share this post


Link to post
Share on other sites
You mean that?
http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html
(1.5 Texturing and Shading)

Thats not the problem. NVidia used only different textures for the different sides. So, every polygon that would be on the "ground" has grass and every poly on the wall would be rock. But grass in a cave (Which has a ground, too)... No sand at all, just grass... That are not the layers I need.

[Edit]: Here, thats what I mean [smile]

Share this post


Link to post
Share on other sites
I've used something similar to your second idea where I stored the weights for each material in a texcoord. You can use up to 16 of these as float4 values I think so up to 64 layers if you need them. I had 5 different materials by using one float4 set of weights. Basically there was a base material and then 4 other materials given according to the weights. The base material was whatever was left over after the weights were added up. So I was sampling 5 diffuse textures, 5 normal textures and 5 specular textures and that wasn't actually that slow.

My current approach is slightly modified, I'm using a deferred renderer with a dynamic mesh based on a height map and then I just have a same sized blob map that I sample from for each vertex too with the weights. Your third idea has made me think about just passing the weights through to the deferred shader and letting the 5 different samplers happen there. It'd result in less texture sampling overall.

Share this post


Link to post
Share on other sites
The problem with Nr. 2 is that the whole terrain would have to run only one shader. I have to use Triplanar texturing, which results into 3 lookups per texture, so 9 lookups for 1 diffuse, 1 normal and 1 specular. Having 4 layers then, you are at 36 texture lookups (+ many many math calculations) even when you don't see anything of the layer. When using the deferred renderer one can set up scissoring rects over the terrain chunks. (Side note: In a chunked terrain you can have 4 layers per chunk, so others in other chunks) I really thought hard about this, and I came to the conclusion that my 3rd idea is maybe the best for me... I think I should go for it [smile]

Share this post


Link to post
Share on other sites
I think you're probably right in that extending your deferred shader to handle this, but as you've already broken the terrain into multiple draw calls, for each chunk you could calculate which layers are actually visible (have alpha>0) and encode the information into shader constants. Sort your draw calls by this same value and in the shader branch based on these constants to do the texturing. That way you wont waste cycles or lookups that are never needed.

Or if you never have more than 3 layers active just set the texture inputs to match the top three layers in that chunk. Your vertex stream would contain the top three blend weights, calculated when you generate the vertex data. They just need to match.

Share this post


Link to post
Share on other sites
The problem with rendering the terrain multiple times is the high drawcall count.

It has usually around 100 drawcalls yet, which makes my FPS go from 400 to 100. Still acceptable. But when it has around 500 draw calls, my FPS goes down to 50, without any drawn polygons, I wasn't culling out chunks without any polygons at the moment when I found that out.

And rendering everything in one shader is too messy for my artist (As I said above, somewhere in the text [smile]).

That's why I don't like the two techniques. But I think when I would use my engine alone, I would go for your idea. It is easier to implement! [wink]

Share this post


Link to post
Share on other sites
Fair enough but why does your artist need to know anything about the shader?

I don't know how the artist interface works but I guess all they need to do to texture the world is to specify the alpha of each of the 8 layers at each point in space. The code can process the raw data and pick the top 3 contributing materials and bake that information in.

Share this post


Link to post
Share on other sites
Yes, that would be enough if we only wanted to texture the terrain. But our game is a feature style Hack'n'slay with lots if effects, like from the music which is playing in the background. Also that makes it possible to put effects like parallax mapping or a Fresnel onto the terrain layer. Only a texture isn't enough for that reasons. Also, if you find a nice rock shader, made by someone, you can't simply set it as layer. You would have to edit the Terrain Shader.
If I would only need a texture + normal map, your's would be the way to go.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!