DepthOffsetAttrib Z range composition order

I’m having issues when in my graph where a root node has a DepthOffsetAttrib to limit the Z output range and a child node has a DepthOffsetAttrib with a depth offset:

if I set on the root node DepthOffsetAttrib.make(0, 0.5, 1) and on the child node DepthOffsetAttrib.make(1), the net depth offset seems to be indeed 1, but the Z output range has been reset to [0, 1]. (According to the code in depthOffsetAttrib.cxx, the offset is accumulated, the Z output range is from the “closest” attrib)

If I set the priority of the DepthOffsetAttrib on the root node to 1, the child node does seem to have the correct Z output range [0.5, 1] but it’s own offset is ignored as it is part of an attrib with a lower priority.

If I’m not wrong, the problem is that two separate concepts share the same attrib object and so conflict ? If is that so, is there a workaround to use ?

Sample code to play with :

from panda3d.core import CardMaker, DepthOffsetAttrib
from direct.showbase.ShowBase import ShowBase


base = ShowBase()
root = base.render.attach_new_node('root')
root.set_attrib(DepthOffsetAttrib.make(0, 0.5, 1), 1)

cm = CardMaker('card')
card1 = root.attach_new_node(cm.generate())
card1.set_pos(-0.5, 3, -0.5)
card2= root.attach_new_node(cm.generate())
card2.set_pos(-0.5, 3, -0.5)

tex1 = loader.load_texture('maps/smiley.rgb')
card1.set_texture(tex1)

tex2 = loader.load_texture('maps/noise.rgb')
card2.set_texture(tex2)
card2.set_attrib(DepthOffsetAttrib.make(1))

base.run()

Yes, it is awkward that the min/max is specified in the DepthOffsetAttrib, maybe it would be better to have this in a separate DepthRangeAttrib.

Failing that, it would be better if the DepthOffsetAttrib composition did something like a max() on the min values and a min() on the max values.

For the record, filled wireframe does not work on nodes with non default depth range as the wireframe overlay uses a depth offset in order to be rendered in from of the object.

Creating a new attrib DepthRangeAttrib would be much cleaner indeed, but I wonder how to manage the backward compatibility with code that would still use DepthOffsetAttrib with a depth range ?

Compositing the range would be a good short term workaround, but this could also break backward compatibility with existing code, unless it is only activated with a config variable ?

I think one way to deal with the compatibility would be to split DepthOffsetAttrib into a new DepthBiasAttrib and DepthRangeAttrib, simultaneously addressing the fact that the current DepthOffsetAttrib parameterisation is too limited, see #1157. Then we can either deprecate DepthOffsetAttrib, or make it automatically translate to the appropriate Depth{Bias/Range}Attrib settings.

1 Like

In your use case, would it be OK if the depth range were applied DisplayRegion-wide or do you need it to be on specific nodes? I ask because it appears to be part of the viewport state, so part of me feels like it belongs on DisplayRegion.

Indeed, for my use case the depth range is set per DisplayRegion, all the nodes linked with a given region will have the same depth range (currently I’m applying the range on the root node of the Region). So indeed it would be more logical to apply the range on the DR. (I’m actually segmenting the scene into regions to not waste the depth buffer)

This should solve your problem:

It adds a set_depth_range(near, far) to DisplayRegion. It works cumulatively with DepthOffsetAttrib, ie. a DisplayRegion range of 0.25…0.75 and a DepthOffsetAttrib range of 0.25…0.75 will result in a net range of 0.375…0.625. This means that if you set it on the DisplayRegion, you should no longer see individual nodes override this setting.

In other news, DepthOffsetAttrib is deprecated, and DepthBiasAttrib supersedes it. It has more parameters to control the depth bias but does not include a depth range setting.

1 Like