Mixing terrain-nodes impossible!

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Suliman

Mixing terrain-nodes impossible!

Post by Suliman »

Hi I asked this a long time ago but do it again now in a own thread. Plz answer if you know how to solve this...

Water:
I try to make a water-plane (as geomipmap or irrlicht waternode, i've tried both) but the edge between the terrain and the water is really ugly, even if the water is frozen/not animated. the water gets "cut-up" just when going under the terrain, like shards of it is seen. I have a pic of it but there is no way to upload here.

Here is a screenshot of the mix between waterplane and terrain. It looks really... well... ugly.

http://www.gamedev.se/projekt/screenshot.php?id=26



Another strange thing:
When loading a heightmap, it loads mirrored. One dimension (the former y and now z) works while the x-dim is backwards. How should I handle this?See below:

Bitmap:

1 2

3 4


Geomipmap drawn

2 1

4 3


dopyiii
Posts: 26
Joined: Wed Mar 23, 2005 7:48 pm

Post by dopyiii »

I've had the same problem with the terrain and water thing. Sorry I don't have any ideas to fix it, though. I've tried changing the scale, culling, different textures, etc. Nothing has worked for me yet.

I didn't try turning on bi/trilinear filtering. Does that help?

Okay, I guess I had ONE suggestion for you :wink:
Guest

Post by Guest »

Looks like a classic case of z-fighting.

The pixels (fragments) coming from the water are at virtually the same depth (measured from the viewer) and you don't get enough precision in the depth buffer.
It's worse because most video cards use a non-linear formula. There's more precision near the camera than there is far from the camera.

There are a couple of ways to solve it, but most of them are at a lower level (OpenGL or Direct3D).

The one thing I know you can do with Irrlicht is increase the camera's nearvalue, (or reduce the far value).

One more low-level method would be basically rendering your objects in "layers": render distant objects first with different near/farvalues, then reset the depth buffer and render the near objects. There's some extra setup needed (user clip planes) but the results are, apparently, good.

Another is to use w-buffering (although I don't know how you would calculate good w values) - which allows you to use a different distribution.
Operation Flashpoint can be switched to use w-buffering, and that solves precisely the same problem that you're having.

Yet another is using a depth bias for the water, to make it more likely to "win". Although it's quite possible that that just shifts the trouble further inland.
Guest

Post by Guest »

Allow me to correct myself.

It seems that the depth bias in OpenGL is not applied during rendering but only when reading and writing textures/pixels. I seem to remember reading somewhere that it was possible to use a bias when rendering.
However, it's more useful for decals anyway (roads rendered on top of terrain, for example). Those don't intersect but coincide.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

I've got to test out what I think the fix, but I think the problem is that the terrain node is rendered, mixed in with all other default scene nodes ( which the water scene node is also rendered as ). When I implemented the GeoMipMapSceneNode in my modified engine, I created a new E_SCENE_NODE_RENDER_PASS for the terrain, so the order would be -

Lights and Camera
SkyBox
Terrain
Solid
Shadow
Transparent

As a quick fix, you can change the line #222 in CTerrainSceneNode.cpp from

Code: Select all

SceneManager->registerNodeForRendering(this);
to

Code: Select all

SceneManager->registerNodeForRendering(this,ESNRP_SKY_BOX);
I believe the correct fix would be to add the terrain to render between the skybox and the solid objects, I guess, if it happens to render before the skybox, you could have the same Z issues between the skybox and the terrain. Make sure you add the sky before the terrain to make sure the sky is drawn before the terrain. Also, you could make sure the terrain node is the first node added to the scene and not change the code in the engine.

Hope it fixes the problem.

EDIT: Nope, didn't fix the problem, I'll keep looking into it.
Image
Guest

Post by Guest »

I don't think rendering the terrain in a separate pass can ever fix the issue:

Either you clear the depthbuffer, in which case the waterplane will always show completely.

Or you don't clear the depthbuffer, in which case you get z-fighting.

There are three "proper" ways to render deep scenes:
1. clip the waterplane so you don't get intersecting triangles. Any z-fighting will be limited to the waterline.
2. render in layers based on distance to viewer. The downside is that vertex shaders disable user clipping planes, so no hw accelerated skinning at a distance.
3. use a different depth-formula (w-buffering)

You could also try rendering the water in the same pass as the terrain, with a large nearvalue (maybe 10 or so). That way, z-fighting could be reduced for this sort of situation. Of course, that _is_ a very specific fix.

Useful link: http://www.sjbaker.org/steve/omniv/love ... uffer.html
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Re: Mixing terrain-nodes impossible!

Post by Midnight »

Suliman wrote:I have a pic of it but there is no way to upload here.
You mean like this?

Image
Suliman

Post by Suliman »

I dont use any skybox.

Is there no fairly easy way to put two nodes close without the flimmer effect? Two terrainNodes cannot do it either (that waterNode is nice-looking but cost enourmous CPU on even a small map).
William Finlayson
Posts: 61
Joined: Mon Oct 25, 2004 12:11 am

Post by William Finlayson »

I have seen this problem before and the fix was to simply use a 24/32 bit z-buffer rather than a 16 bit one. I don't know how you can force z-buffer size in Irrlicht, you may have to dive into the engine code and tweak it.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Thanks a ton William, that's the fix.

For DirectX8 and DirectX9, a 16 bit depth buffer is used, only if you pass true to the createDevice function to enable stencil buffers. If you do not enable stencil buffers, then a D3DFMT_D16 format buffer is used which gives you a 16 bit depth buffer only. Maybe there should be a change to createDevice, so you can specify the depth buffer bits without enabling stencil buffer. You could change

Code: Select all

if (!StencilBuffer)
		present.AutoDepthStencilFormat = D3DFMT_D16;
to

Code: Select all

if (!StencilBuffer)
		present.AutoDepthStencilFormat = D3DFMT_D24X8;
for 24 bit zbuffer or

Code: Select all

if (!StencilBuffer)
		present.AutoDepthStencilFormat = D3DFMT_D32;
for 32 bit zbuffer

to get the water and terrain scene nodes working well together at a distance, or you could just enable the stencil buffer.

I'll look into how to do this for OpenGL and submit a suggested change to be able to configure the depth buffer without having to enable the stencil buffer.

Here's a screenshot with the fix....

http://irrlicht.spintz.com/terrainandwaternode.bmp

The screenshot is with a 24 bit zbuffer, all my video card supports, but seems sufficient
Image
Suliman

Post by Suliman »

Great!

Ill try it first thing when I get home
Suliman

Post by Suliman »

If enambling stencil-buffer, the mix works in windowed mode but not in fullscreen.

The other thing, changing that code, I haven't tried that one, as I do not find that peice of code to be changed... Where is it?
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Yes, the fullscreen problem is the reason I changed the engine code, because in fullscreen, stencilbuffers do not work right. With the above changed code, if you enable fullscreen and disable stencil buffers, it looks great ( that screenshot I posted was in fullscreen mode ).

Anyways, that code is in the initDriver function in CVideoDirectX8.cpp and CVideoDirectX9.cpp. For OpenGL, in the initDriver function in CVideoOpenGL.cpp, in the definition of the PIXELFORMATDESCRIPTOR structure, change

Code: Select all

16,		// 16Bit Z-Buffer (Depth Buffer)
to

Code: Select all

24,		// 24Bit Z-Buffer (Depth Buffer)
The engine should allow you to specify the size of the depth buffer you want to use. I'll post some code on that later. And maybe look into why the problem still occurs with stencil buffers enabled in full-screen mode, I think some posts about full-screen and stencil buffers have been posted before.
Image
Post Reply