Correct z-ordering of tris near others ?

Blitz3D Forums/Blitz3D Beginners Area/Correct z-ordering of tris near others ?

RemiD(Posted 2012) [#1]
Hello, :)

I am trying to add a glow effect to some parts of the meshes, for example some windows of a building, or some parts of a lamp.

My method for now is to use 2 separate meshes : 1 mesh for the material parts, 1 mesh for the glowing parts.
This way, each frame i can color the material parts in black (with EntityColor), render the scene, and apply a blur routine to this image in order to have the glowing effect.

However it seems it produces a problem of z-ordering :


As you can see, some windows are drawn behind the walls, it is strange because there is an offset of 0.01 between the wall and each window.
Also i don't use the alpha flag or the mask flag, all the windows are meshes colored with vertex colors.

Do you think it will be possible to avoid this z-ordering problem if i use one mesh with 2 surfaces instead of 2 separate meshes ? (1 surface for the walls, 1 surface for the windows)

Else, do you have any idea about what to do to avoid this ?

I want to be able to change the color of each window when i want, i don't know if using a texture is a better way ? What do you think ?

Also please note that it is just a test, i want to add more details to each building and window.

Thanks for your suggestions,

Last edited 2012


Yasha(Posted 2012) [#2]
One thing I've found is that if you manually place vertices using VertexCoords, as long as you put one polygon exactly on top of another, you can force the drawing order: the most-recently-placed one will be drawn first without Z-fighting. They have to be dead-on-top for this though... I assume it disables sorting somehow. This only works if they're within the same mesh.

The other thing is that it depends on your camera range. Depending on how far away those building are, it may not have enough precision left for 0.01 to be a meaningful distance. There's a nice little Z-calculator here: http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html

...that shows that with Blitz3D's default camera range settings (1:1000), 0.01 is too small to represent in the Z-buffer at distances of greater than around 400 units.

You could either 1) dynamically increase the offset with distance from the camera, as the camera moves (which may cause some problems of its own); or 2) have a separate render for distant objects like the buildings, with a more appropriate camera range (since most Z-values are clustered nearer to the camera, this mainly means extending the minimum range to be as close to the target as possible so that the most precision is brought to bear on what you want); or 3) use a full-on skybox and have the buildings actually be very small.


RemiD(Posted 2012) [#3]

1) dynamically increase the offset with distance from the camera, as the camera moves


Good idea. But i don't think it will be appropriate when i will add more details to the walls and the windows.


2) have a separate render for distant objects like the buildings, with a more appropriate camera range


Ok and maybe i can use a quad with a texture for the far away buildings, i have thought about that.


3) use a full-on skybox and have the buildings actually be very small.


What do you mean ? To reduce the size of the buildings and the size of the world ?
How can this affect the z-ordering problem ?


About the skybox, if i want to have a skybox of 2048 * 2048 * 2048 units, then how am i suppose to render it, if i set the max CameraRange at less than 2048 ?
With EntityOrder() ?
With 2 Renderworld() ?

Thanks,

Last edited 2012


Yasha(Posted 2012) [#4]
What do you mean ? To reduce the size of the buildings and the size of the world ?
How can this affect the z-ordering problem ?


About the skybox, if i want to have a skybox of 2048 * 2048 * 2048 units, then how am i suppose to render it, if i set the max CameraRange at less than 2048 ?


If you have two cameras, in two scenes, each hidden when the other is rendered:

-- buildings and background can be made into a single scene with an appropriate scale/camera range combination. The camera's movement is scaled to match the player camera's movement in the main scene

-- the background camera renders first

-- either 1) render it directly, then disable the clearing of the colour buffer for the scene camera (in which case the background will just be "there"), or 2) render three views that match the player's orientation to a cubemap, and paste this cubemap onto a literal box around the player camera (option 2 is more demanding on resources, but option 1 may not work well with all rendering setups)

So the answer to your skybox question is: you don't. The skybox image isn't static, and the whole point is that it doesn't have to be 2048 units away (assuming it even has to exist): the image cubemapped onto it gives the illusion of much greater depth. The skybox only has to be just big enough to fit around every visible part of the main scene.


RemiD(Posted 2012) [#5]

The other thing is that it depends on your camera range. Depending on how far away those building are, it may not have enough precision left for 0.01 to be a meaningful distance. There's a nice little Z-calculator here


I have tried to set the CameraRange to 1,1000 and it seems to be rendered correctly. The render is also correct with 0.5,512
So it think that i will follow your suggestion to do several renders with different CameraRange

Maybe something like this :
1)Hide all components of the 3D scene
2)Show the skybox
3)Set the CameraRange to 100,2049
4)Render the scene and i keep this image in memory
5)Show all components of the 3d scene
6)Hide the skybox
7)Set the CameraRange to 1,1000 with a CameraClsColor of 000,000,000
8)Render the scene and i keep this image in memory
9)Set the CameraRange to 0.1,100 with a CameraClsColor of 000,000,000
10)Render the scene and i keep this image in memory
11)Draw the image of the skybox
12)Draw the image of the components of the 3d scene 1,1000
13)Draw the image of the components of the 3d scene 0.1,100

Because the pixels with a rgb or 000,000,000 are considered invisible by the function DrawImage(), this should work.
But i have to code a routine so that i only render the 3D components of the scene once.

Ok thank you for this suggestion, i will try.

Last edited 2012


Kryzon(Posted 2012) [#6]
Why don't you do a multipass render? this is something Ross C. used to suggest:

[bbcode]
;Multi-pass, Z-fighting free render method:

Const RANGE_INCREMENT# = 250 ;A smaller value will make it even more precise.

;[...]

;When rendering the camera:
CameraCLSMode camera,False,False ;Keep color and depth information for all passes, so they composite.

For i = 1 to 4
CameraRange(camera, (1+RANGE_INCREMENT*(i-1)), (1+RANGE_INCREMENT*i))
RenderWorld()
Next
[/bbcode]

What you're doing is this:

So you keep a precise Z-buffer for every 'shot' of the scene.

Last edited 2012


RemiD(Posted 2012) [#7]
Kryzon>>Interesting technique, thanks.

But i am wondering if it will calculate the render for some meshes twice...

I guess i have to try