Page 1 of 1

Feature Request: negative zoffset

Posted: Mon Nov 21, 2005 8:33 am
by jfarm
It would be handy if negative values were allowed for Zoffs (the z-buffer offset) so Zoffs could be used to help resolve zbuffer amibiguities, and perhaps other uses too. In my case, I have a plane in the distant background, with objects in front of it but close to it, and other objects closer still. The spread of objects makes the z-buffer have low resolution, causing objects close to the plane to intermittently disappear when round-off causes their z to coincide or fall behind the z of the plane. The spread of the objects precludes adjusting camera start and end clipping planes to improve z buffer resolution. Applying a +Zoffs to the objects in front of the plane will prevent them from disappearing behind it, but also causes bad interactions with the objects in front of *them*, i.e. they will pop in front of closer objects. I think if I could apply a negative Zoffset to the plane in the background, everything would work great.

The changes may be as simple as this:

uiDefButF(block, NUM, B_DIFF, "Zoffs:", 10,110,100,20, &(ma->zoffs), 0.0, 10.0, 100, 0, "Gives faces an artificial offset in the Z buffer for Ztransp option");
uiDefButF(block, NUM, B_DIFF, "Zoffs:", 10,110,100,20, &(ma->zoffs), -10.0, 10.0, 100, 0, "Gives faces an artificial offset in the Z buffer for Ztransp option");


#define EXPP_MAT_ZOFFS_MIN 0.0
#define EXPP_MAT_ZOFFS_MIN -10.0

I was hoping to try these changes today, but I ran out of time before I got all the pieces downloaded to allow a complete compile.

Posted: Thu Nov 24, 2005 12:40 pm
by joeri
More luck now?

Posted: Thu Dec 15, 2005 7:16 am
by jfarm
I finally had some time to try this, and yes, it works, sort of.
I made the first change I listed (to blender/source/blender/src/buttons_shading.c) to change the minimum from 0 to -10, allowing me to set a negative Zoffset. By applying the negative Zoffset to the ground plane, small objects on or near the plane were far less likely to intermittently disappear in various frames of an animation. But they still did disappear once in a while. Possibly allowing more negative offsets (-100?) would solve this. I might have a look at the z buffer code too, if I get some time--there are different ways the scan line conversion can be done that vary in how well they preserve floating point precision, and I'm curious now what is being done there.

However, there was a bad side effect that would prevent me from using negative zoffset. For Zoffset to be used, Ztransp must be activated. With Ztransp activated for the ground plane there appeared to be a narrow (<=1 pixel) faint halo around objects that were in front of the ground plane. This halo sort of shimmered in animation. At first I speculated it might be an aliasing artifact induced by the negative Zoffset, but it seemed to still be there even with Zoffs=0, and went away with Ztransp off. (I was using OSA 5). Unless my eyes were deceiving me, this points to a possible bug in the renderer. I know there is an issue with Ztransp and Mist (bug/todo 3433) but I think I see the halo with Ztransp on even if Mist is off. It still might be related to that though. I may try placing a black surface under the ground plane and see if that helps, or try tweaking the code to allow Zoffs to be used even if Ztransp is off.

But as usual, this turned into a far bigger project than I expected.

Posted: Thu Dec 15, 2005 5:20 pm
by joeri
I used to get rid of the halo effect by making all objects Ztransp forcing blender to render tra and not-tra objects in the same pass.

Posted: Thu Dec 15, 2005 10:26 pm
by theeth
joeri wrote:I used to get rid of the halo effect by making all objects Ztransp forcing blender to render tra and not-tra objects in the same pass.
Using the unified renderer fixes that too, except the UR has other problems now... :?


Posted: Sun Dec 18, 2005 10:59 pm
by joeri
theeth wrote:
joeri wrote:I used to get rid of the halo effect by making all objects Ztransp forcing blender to render tra and not-tra objects in the same pass.
Using the unified renderer fixes that too, except the UR has other problems now... :?

No should work, I forgot about the unified renderer. It should also fix the halos infront and behind transparent objects problem.

Posted: Wed Dec 28, 2005 7:15 pm
by jfarm
A couple updates:
(1)Using the unified renderer does indeed eliminate the halos around objects that have ztransp set, though of course it renders much slower.
(2)The code changes in my original post actually were not sufficient. It turns out that simply enabling ztransp for my ground plane, even with 0.0 zoffset, allowed other objects to be mostly visible "through" the ground plane when the zbuf put them "behind" it, thus reducing the blinking effect of objects intermittently disappearing behind the ground plane during an animation. (A black object becomes dark gray instead of disappearing entirely.) This made it look like the change was working. Two other changes were necessary to make the negative zoffset actually work:
(a) it appears that the abolute value needed to be removed from zbuf.c and vanillaRenderPipe.c for the line
Azvoordeel= (int) fabs(zval - fval );
I don't have the code change available (different computer), but I think I had to swap the subtract order as well, resulting in
Azvoordeel= (int) (fval - zval );
(b) because of the way my scene is scaled, I needed to allow much larger negative zoffsets than -10.

With these changes things worked better--black objects stayed black, but still disappeared a few times, though not as often.
I'll try to look at this again and report back.

Posted: Sat Jan 14, 2006 2:45 am
by jfarm
I ended up taking a different approach for this since what I was doing just wasn't working--I didn't want the "halos" caused by setting ztransp (needed to enable zoffset), and I didn't want the increased render time of the unified render (which would eliminate the halos). Also, ridiculously large zoffsets were going to be required.

So I did this instead: I allowed negative zoffsets to be entered in the GUI (via the change to buttons_shading.c described above). Then I changed zbuf.c such that if a zoffset of -10.0 is detected, the z-buffer value for the surface is set to a very large positive number, thus placing the surface "behind" everything else. This happens for non-transparent surfaces, so no halo is created since ztransp do not have to be set.

This worked great! By setting the zoffset of my ground plane to -10.0, it now stays behind everything else, and never eclipses objects near it. The objects don't flicker out of existence in animations. Looks wonderful, renders fast.

But the whole thing is an ugly hack, IMO, so I'm reluctant to pollute the code base with it. First, the user interface, by using a special value of zoffset of -10, is a cryptic, hidden, "mystery meat" user interface. Then, the code change in zbuf.c, while simple, is kind of ugly. It uses a new global, z_override (in a manner similar to the way Azvoordeel is used). It is used like this in zbufclip and zbufclip4 (a total of 8 places):
deler= f1[3];
vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
vez[2]= 0x7FFFFFFF *(f1[2]/deler);
if (z_override) vez[2] = FAR_Z; /* <- new line of code */

/* FAR_Z used for z buffer depth when z_override is set */
/* Value is less than max int because it must fit in a float */
#define FAR_Z (0x7FFFF000)

As far as the code goes, if ton (or somebody) is really going to rework the renderer, I would think they could find a much cleaner way of setting the z-depth than what I've done here.

And as far as the GUI goes, although simply allowing negative zoffset as I originally proposed may still be useful, it seems another idea might be useful as well, and that is a z-layer option, which is a generalization of what I did. A zlayer is an integer. A zlayer of zero has no effect on zbuffer depths. A zlayer of -1 would push the surface behind everything else by setting zbuffer values to 0x7FFFFFFF, a -2 would do the same except be in front of a -1, using 0x7FFFFFFE, etc. Likewise a +1 would place a surface in front of everything using 0x8000000 (?), etc. This is really intended for 2-D objects since the z depth for an object gets mapped to a single value. But it would be useful for pushing background surfaces behind everything, or ensuring something is always in front of everything else (like, say, a text item, parented to the camera, and scripted to update every frame to form an elapsed time indicator). I could have used both in my animation.

Edit: 2006.03.11 - reviewing what I wrote above, I find the layer ordering to be rather knuckleheaded--it is inside-out. It would of course make more sense to simply render the layers in numerical order, perhaps still with layer 0 being the default layer, -1 behind that, -2 behind both of those, etc., 1 in front, 2 in front of that, etc. (or reverse the order if you prefer larger numbers farther back, i.e. you interpret the layer number as a depth instead of a render order). End Edit

Any thoughts on this?
Or is this something that could be done with the Sequencer? (by rendering elements in separate passes then using the sequencer to combine them)

Posted: Sat Jan 14, 2006 10:40 am
by lightning
Ton is working on some of the render code is being worked on in the orange branch as we speak... one of the things he is hoping to implement is layer rendering (render one layer in front/behind another).

Posted: Sun Jan 15, 2006 1:39 pm
by joeri
Making sure that objects AWAYS stay in the backdrop is something easaly done in the sequence editor. That's how I used to put 3d text in front of everything. Frankly: I would not render that in one go, but render it in separate batches so I only need to rerender the text when I made a typo or for multi languages.

But,... for stuff that needs to be relative to another object, even when the camera starts rotating around those objects (don't know when) a cell layer system might be handy.
As I understand it; South Park was made in Maya, and a layer system as you discribed would be very handy to make sure things stay at 'right' depth.