mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
display: Support specifying depth range on DisplayRegion
See https://discourse.panda3d.org/t/depthoffsetattrib-z-range-composition-order/27943/4
This commit is contained in:
parent
3d4dd50358
commit
280175f267
@ -156,6 +156,28 @@ set_dimensions(const LVecBase4 &dimensions) {
|
|||||||
set_dimensions(0, dimensions);
|
set_dimensions(0, dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the range of the depth buffer this DisplayRegion writes to.
|
||||||
|
* The parameters range from 0 to 1. It is legal for the near value to be
|
||||||
|
* larger than the far value.
|
||||||
|
*/
|
||||||
|
INLINE void DisplayRegion::
|
||||||
|
set_depth_range(PN_stdfloat near, PN_stdfloat far) {
|
||||||
|
CDWriter cdata(_cycler, true);
|
||||||
|
cdata->_depth_range.set(near, far);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE void DisplayRegion::
|
||||||
|
get_depth_range(PN_stdfloat &near, PN_stdfloat &far) const {
|
||||||
|
CDReader cdata(_cycler);
|
||||||
|
const LVecBase2 &range = cdata->_depth_range;
|
||||||
|
near = range[0];
|
||||||
|
far = range[1];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the GraphicsOutput that this DisplayRegion is ultimately associated
|
* Returns the GraphicsOutput that this DisplayRegion is ultimately associated
|
||||||
* with, or NULL if no window is associated.
|
* with, or NULL if no window is associated.
|
||||||
@ -693,6 +715,16 @@ get_top(int i) const {
|
|||||||
return _cdata->_regions[i]._dimensions[3];
|
return _cdata->_regions[i]._dimensions[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
INLINE void DisplayRegionPipelineReader::
|
||||||
|
get_depth_range(PN_stdfloat &near, PN_stdfloat &far) const {
|
||||||
|
const LVecBase2 &range = _cdata->_depth_range;
|
||||||
|
near = range[0];
|
||||||
|
far = range[1];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the GraphicsOutput that this DisplayRegion is ultimately associated
|
* Returns the GraphicsOutput that this DisplayRegion is ultimately associated
|
||||||
* with, or NULL if no window is associated.
|
* with, or NULL if no window is associated.
|
||||||
|
@ -738,7 +738,8 @@ CData() :
|
|||||||
_stereo_channel(Lens::SC_mono),
|
_stereo_channel(Lens::SC_mono),
|
||||||
_tex_view_offset(0),
|
_tex_view_offset(0),
|
||||||
_target_tex_page(-1),
|
_target_tex_page(-1),
|
||||||
_scissor_enabled(true)
|
_scissor_enabled(true),
|
||||||
|
_depth_range(0, 1)
|
||||||
{
|
{
|
||||||
_regions.push_back(Region());
|
_regions.push_back(Region());
|
||||||
}
|
}
|
||||||
@ -757,7 +758,8 @@ CData(const DisplayRegion::CData ©) :
|
|||||||
_stereo_channel(copy._stereo_channel),
|
_stereo_channel(copy._stereo_channel),
|
||||||
_tex_view_offset(copy._tex_view_offset),
|
_tex_view_offset(copy._tex_view_offset),
|
||||||
_target_tex_page(copy._target_tex_page),
|
_target_tex_page(copy._target_tex_page),
|
||||||
_scissor_enabled(copy._scissor_enabled)
|
_scissor_enabled(copy._scissor_enabled),
|
||||||
|
_depth_range(copy._depth_range)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,9 @@ PUBLISHED:
|
|||||||
virtual void set_dimensions(int i, const LVecBase4 &dimensions);
|
virtual void set_dimensions(int i, const LVecBase4 &dimensions);
|
||||||
MAKE_PROPERTY(dimensions, get_dimensions, set_dimensions);
|
MAKE_PROPERTY(dimensions, get_dimensions, set_dimensions);
|
||||||
|
|
||||||
|
INLINE void set_depth_range(PN_stdfloat near, PN_stdfloat far);
|
||||||
|
INLINE void get_depth_range(PN_stdfloat &near, PN_stdfloat &far) const;
|
||||||
|
|
||||||
INLINE GraphicsOutput *get_window() const;
|
INLINE GraphicsOutput *get_window() const;
|
||||||
GraphicsPipe *get_pipe() const;
|
GraphicsPipe *get_pipe() const;
|
||||||
virtual bool is_stereo() const;
|
virtual bool is_stereo() const;
|
||||||
@ -233,6 +236,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Regions _regions;
|
Regions _regions;
|
||||||
|
LVecBase2 _depth_range; // near, far
|
||||||
|
|
||||||
int _lens_index; // index into which lens of a camera is associated with this display region. 0 is default
|
int _lens_index; // index into which lens of a camera is associated with this display region. 0 is default
|
||||||
|
|
||||||
@ -333,6 +337,8 @@ public:
|
|||||||
INLINE PN_stdfloat get_bottom(int i = 0) const;
|
INLINE PN_stdfloat get_bottom(int i = 0) const;
|
||||||
INLINE PN_stdfloat get_top(int i = 0) const;
|
INLINE PN_stdfloat get_top(int i = 0) const;
|
||||||
|
|
||||||
|
INLINE void get_depth_range(PN_stdfloat &near, PN_stdfloat &far) const;
|
||||||
|
|
||||||
INLINE GraphicsOutput *get_window() const;
|
INLINE GraphicsOutput *get_window() const;
|
||||||
GraphicsPipe *get_pipe() const;
|
GraphicsPipe *get_pipe() const;
|
||||||
|
|
||||||
|
@ -528,6 +528,7 @@ CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) :
|
|||||||
|
|
||||||
_scissor_enabled = false;
|
_scissor_enabled = false;
|
||||||
_scissor_attrib_active = false;
|
_scissor_attrib_active = false;
|
||||||
|
_has_attrib_depth_range = false;
|
||||||
|
|
||||||
_white_texture = 0;
|
_white_texture = 0;
|
||||||
|
|
||||||
@ -3337,6 +3338,7 @@ reset() {
|
|||||||
_glDepthRangedNV(-1.0, 1.0);
|
_glDepthRangedNV(-1.0, 1.0);
|
||||||
_use_depth_zero_to_one = true;
|
_use_depth_zero_to_one = true;
|
||||||
_use_remapped_depth_range = true;
|
_use_remapped_depth_range = true;
|
||||||
|
_has_attrib_depth_range = false;
|
||||||
|
|
||||||
if (GLCAT.is_debug()) {
|
if (GLCAT.is_debug()) {
|
||||||
GLCAT.debug()
|
GLCAT.debug()
|
||||||
@ -3352,6 +3354,17 @@ reset() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (_has_attrib_depth_range) {
|
||||||
|
#ifdef OPENGLES
|
||||||
|
glDepthRangef(0.0f, 1.0f);
|
||||||
|
#else
|
||||||
|
glDepthRange(0.0, 1.0);
|
||||||
|
#endif
|
||||||
|
_depth_range_near = 0;
|
||||||
|
_depth_range_far = 1;
|
||||||
|
_has_attrib_depth_range = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up all the enableddisabled flags to GL's known initial values:
|
// Set up all the enableddisabled flags to GL's known initial values:
|
||||||
// everything off.
|
// everything off.
|
||||||
_multisample_mode = 0;
|
_multisample_mode = 0;
|
||||||
@ -3926,6 +3939,33 @@ prepare_display_region(DisplayRegionPipelineReader *dr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PN_stdfloat near;
|
||||||
|
PN_stdfloat far;
|
||||||
|
dr->get_depth_range(near, far);
|
||||||
|
#ifdef GSG_VERBOSE
|
||||||
|
if (GLCAT.is_spam()) {
|
||||||
|
GLCAT.spam()
|
||||||
|
<< "glDepthRange(" << near << ", " << far << ")" << endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPENGLES
|
||||||
|
// OpenGL ES uses a single-precision call.
|
||||||
|
glDepthRangef((GLclampf)near, (GLclampf)far);
|
||||||
|
#else
|
||||||
|
// Mainline OpenGL uses a double-precision call.
|
||||||
|
if (!_use_remapped_depth_range) {
|
||||||
|
glDepthRange((GLclampd)near, (GLclampd)far);
|
||||||
|
} else {
|
||||||
|
// If we have a remapped depth range, we should adjust the values to range
|
||||||
|
// from -1 to 1. We need to use an NV extension to pass unclamped values.
|
||||||
|
_glDepthRangedNV(near * 2.0 - 1.0, far * 2.0 - 1.0);
|
||||||
|
}
|
||||||
|
#endif // OPENGLES
|
||||||
|
_has_attrib_depth_range = false;
|
||||||
|
_depth_range_near = near;
|
||||||
|
_depth_range_far = far;
|
||||||
|
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8151,24 +8191,35 @@ do_issue_depth_offset() {
|
|||||||
|
|
||||||
PN_stdfloat min_value = target_depth_offset->get_min_value();
|
PN_stdfloat min_value = target_depth_offset->get_min_value();
|
||||||
PN_stdfloat max_value = target_depth_offset->get_max_value();
|
PN_stdfloat max_value = target_depth_offset->get_max_value();
|
||||||
|
if (min_value != (PN_stdfloat)0.0 ||
|
||||||
|
max_value != (PN_stdfloat)1.0 ||
|
||||||
|
_has_attrib_depth_range) {
|
||||||
|
min_value = _depth_range_far * min_value + _depth_range_near * (1 - min_value);
|
||||||
|
max_value = _depth_range_far * max_value + _depth_range_near * (1 - max_value);
|
||||||
|
|
||||||
#ifdef GSG_VERBOSE
|
#ifdef GSG_VERBOSE
|
||||||
GLCAT.spam()
|
if (GLCAT.is_spam()) {
|
||||||
<< "glDepthRange(" << min_value << ", " << max_value << ")" << endl;
|
GLCAT.spam()
|
||||||
|
<< "glDepthRange(" << min_value << ", " << max_value << ")" << endl;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef OPENGLES
|
#ifdef OPENGLES
|
||||||
// OpenGL ES uses a single-precision call.
|
// OpenGL ES uses a single-precision call.
|
||||||
glDepthRangef((GLclampf)min_value, (GLclampf)max_value);
|
glDepthRangef((GLclampf)min_value, (GLclampf)max_value);
|
||||||
#else
|
#else
|
||||||
// Mainline OpenGL uses a double-precision call.
|
// Mainline OpenGL uses a double-precision call.
|
||||||
if (!_use_remapped_depth_range) {
|
if (!_use_remapped_depth_range) {
|
||||||
glDepthRange((GLclampd)min_value, (GLclampd)max_value);
|
glDepthRange((GLclampd)min_value, (GLclampd)max_value);
|
||||||
} else {
|
} else {
|
||||||
// If we have a remapped depth range, we should adjust the values to range
|
// If we have a remapped depth range, we should adjust the values to range
|
||||||
// from -1 to 1. We need to use an NV extension to pass unclamped values.
|
// from -1 to 1. We need to use an NV extension to pass unclamped values.
|
||||||
_glDepthRangedNV(min_value * 2.0 - 1.0, max_value * 2.0 - 1.0);
|
_glDepthRangedNV(min_value * 2.0 - 1.0, max_value * 2.0 - 1.0);
|
||||||
}
|
}
|
||||||
#endif // OPENGLES
|
#endif // OPENGLES
|
||||||
|
|
||||||
|
_has_attrib_depth_range = true;
|
||||||
|
}
|
||||||
|
|
||||||
report_my_gl_errors();
|
report_my_gl_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,6 +675,9 @@ protected:
|
|||||||
bool _scissor_enabled;
|
bool _scissor_enabled;
|
||||||
bool _scissor_attrib_active;
|
bool _scissor_attrib_active;
|
||||||
epvector<LVecBase4i> _scissor_array;
|
epvector<LVecBase4i> _scissor_array;
|
||||||
|
PN_stdfloat _depth_range_near;
|
||||||
|
PN_stdfloat _depth_range_far;
|
||||||
|
bool _has_attrib_depth_range;
|
||||||
|
|
||||||
#ifndef OPENGLES_1
|
#ifndef OPENGLES_1
|
||||||
BitMask32 _enabled_vertex_attrib_arrays;
|
BitMask32 _enabled_vertex_attrib_arrays;
|
||||||
|
@ -56,7 +56,7 @@ def depth_region(request, graphics_pipe):
|
|||||||
engine.remove_window(buffer)
|
engine.remove_window(buffer)
|
||||||
|
|
||||||
|
|
||||||
def render_depth_pixel(region, distance, near, far, clear=None, write=True):
|
def render_depth_pixel(region, distance, near, far, clear=None, write=True, state=None):
|
||||||
"""Renders a fragment at the specified distance using the specified render
|
"""Renders a fragment at the specified distance using the specified render
|
||||||
settings, and returns the resulting depth value."""
|
settings, and returns the resulting depth value."""
|
||||||
|
|
||||||
@ -65,6 +65,9 @@ def render_depth_pixel(region, distance, near, far, clear=None, write=True):
|
|||||||
scene.set_attrib(core.DepthTestAttrib.make(core.RenderAttrib.M_always))
|
scene.set_attrib(core.DepthTestAttrib.make(core.RenderAttrib.M_always))
|
||||||
scene.set_depth_write(write)
|
scene.set_depth_write(write)
|
||||||
|
|
||||||
|
if state:
|
||||||
|
scene.set_state(scene.get_state().compose(state))
|
||||||
|
|
||||||
camera = scene.attach_new_node(core.Camera("camera"))
|
camera = scene.attach_new_node(core.Camera("camera"))
|
||||||
camera.node().get_lens(0).set_near_far(near, far)
|
camera.node().get_lens(0).set_near_far(near, far)
|
||||||
camera.node().set_cull_bounds(core.OmniBoundingVolume())
|
camera.node().set_cull_bounds(core.OmniBoundingVolume())
|
||||||
@ -151,3 +154,28 @@ def test_inverted_depth_clipping(depth_region):
|
|||||||
|
|
||||||
# Just far enough; read a value close to 0.0.
|
# Just far enough; read a value close to 0.0.
|
||||||
assert 0.01 > render_depth_pixel(depth_region, 9.999, near=10, far=1, clear=0.5)
|
assert 0.01 > render_depth_pixel(depth_region, 9.999, near=10, far=1, clear=0.5)
|
||||||
|
|
||||||
|
|
||||||
|
def test_depth_range(depth_region):
|
||||||
|
try:
|
||||||
|
depth_region.set_depth_range(0.25, 0.75)
|
||||||
|
z = render_depth_pixel(depth_region, 1.00001, near=1, far=10)
|
||||||
|
assert z == pytest.approx(0.25, rel=0.01)
|
||||||
|
|
||||||
|
z = render_depth_pixel(depth_region, 10, near=1, far=10)
|
||||||
|
assert z == pytest.approx(0.75, rel=0.01)
|
||||||
|
|
||||||
|
# Combines with DepthOffsetAttrib range.
|
||||||
|
state = core.RenderState.make(core.DepthOffsetAttrib.make(0, 0.25, 0.75))
|
||||||
|
z = render_depth_pixel(depth_region, 1.00001, near=1, far=10, state=state)
|
||||||
|
assert z == pytest.approx(0.375, rel=0.01)
|
||||||
|
|
||||||
|
# Reverse the depth range.
|
||||||
|
depth_region.set_depth_range(0.75, 0.25)
|
||||||
|
z = render_depth_pixel(depth_region, 1.00001, near=1, far=10)
|
||||||
|
assert z == pytest.approx(0.75, rel=0.01)
|
||||||
|
|
||||||
|
z = render_depth_pixel(depth_region, 10, near=1, far=10)
|
||||||
|
assert z == pytest.approx(0.25, rel=0.01)
|
||||||
|
finally:
|
||||||
|
depth_region.set_depth_range(0, 1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user