DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/DepthOffset

197 lines
6.3 KiB
Plaintext
Raw Normal View History

2024-12-24 23:49:36 +00:00
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_DEPTH_ADJUSTMENT_H
#define OSGEARTH_DEPTH_ADJUSTMENT_H 1
#include <osgEarth/Common>
#include <osgEarth/Config>
#include <osgEarth/Units>
#include <osg/Group>
#include <osg/Program>
#include <osg/Uniform>
#include <osg/observer_ptr>
/**
* Depth Offsetting.
*
* Geometry that coincides with the terrain can result in z-fighting artifacts.
* Depth offsetting mitigates this by biasing the depth value of the geometry.
* The idea is similar to polygon offsetting, but is dynamic and applies to all
* geometry (not just polygons).
*
* Depth offsetting works by pretending the vertex is closer to the camera
* than it actually is, and writing a depth value based on that simulated
* location. The distance we shift the vertex towards the camera is the "bias".
*
* The "range" is the distance from camera to vertex at which a given
* bias is applied. The minimum bias is applied to geometry at or below the
* minimum range; the maximum bias is applied to geometry at or above the
* maximum range; and the bias is interpolated for ranges in between.
*
* The tessellation granularity of the geometry affects how well depth offsetting
* works at a given camera distance. As a rule of thumb, the closer the camera is
* to the geometry, the more it needs to be tessellated in order for depth
* offsetting to work properly.
*/
namespace osgEarth
{
/**
* Depth Offsetting options.
*/
class OSGEARTH_EXPORT DepthOffsetOptions
{
public:
DepthOffsetOptions(const Config& conf =Config());
public:
/** whether to enable depth offsetting (when applicable) */
optional<bool>& enabled() { return _enabled; }
const optional<bool>& enabled() const { return _enabled; }
/** depth bias (in meters) applied at the minimum camera range. */
optional<Distance>& minBias() { return _minBias; }
const optional<Distance>& minBias() const { return _minBias; }
/** depth bias (in meters) applied at the maximum camera range. */
optional<Distance>& maxBias() { return _maxBias; }
const optional<Distance>& maxBias() const { return _maxBias; }
/** camera range (in meters) at which to apply the minimum depth bias. */
optional<Distance>& minRange() { return _minRange; }
const optional<Distance>& minRange() const { return _minRange; }
/** camera range (in meters) at which to apply the maximum depth bias. */
optional<Distance>& maxRange() { return _maxRange; }
const optional<Distance>& maxRange() const { return _maxRange; }
/** automatic calculation of the minRange based on geometry analysis */
optional<bool>& automatic() { return _auto; }
const optional<bool>& automatic() const { return _auto; }
public:
Config getConfig() const;
private:
optional<bool> _enabled;
optional<Distance> _minBias;
optional<Distance> _maxBias;
optional<Distance> _minRange;
optional<Distance> _maxRange;
optional<bool> _auto;
};
}
OSGEARTH_SPECIALIZE_CONFIG(osgEarth::DepthOffsetOptions);
namespace osgEarth
{
/**
* Interface for adding depth offset methods to anothe class without
* disturbing the class hierarchy. Use this in conjuction with the
* Adapter.
*/
class DepthOffsetInterface
{
public:
virtual void setDepthOffsetOptions( const DepthOffsetOptions& options ) =0;
virtual const DepthOffsetOptions& getDepthOffsetOptions() const =0;
virtual ~DepthOffsetInterface() { }
};
namespace Util
{
/**
* Adapter that affects depth offset functionality on a graph.
*/
class OSGEARTH_EXPORT DepthOffsetAdapter : public DepthOffsetInterface
{
public:
DepthOffsetAdapter();
DepthOffsetAdapter(osg::Node* graph);
virtual ~DepthOffsetAdapter() { }
void setGraph(osg::Node* graph );
void recalculate();
bool isDirty() const { return _dirty; }
/** whether depth offsetting is supported. */
bool supported() const { return _supported; }
public: // DepthOffsetInterface
void setDepthOffsetOptions( const DepthOffsetOptions& options );
const DepthOffsetOptions& getDepthOffsetOptions() const { return _options; }
private:
void init();
void updateUniforms();
bool _supported;
bool _dirty;
osg::observer_ptr<osg::Node> _graph;
osg::ref_ptr<osg::Uniform> _paramsUniform;
DepthOffsetOptions _options;
};
}
/**
* Group that applies the depth offset technique to its children.
*/
class OSGEARTH_EXPORT DepthOffsetGroup : public osg::Group, public DepthOffsetInterface
{
public:
/**
* Constructs a new depth offset group
*/
DepthOffsetGroup();
public: // DepthOffsetInterface
void setDepthOffsetOptions( const DepthOffsetOptions& options );
const DepthOffsetOptions& getDepthOffsetOptions() const;
public: // osg::Node
virtual osg::BoundingSphere computeBound() const;
virtual void traverse(osg::NodeVisitor& );
protected:
void setUniforms();
void dirty();
void scheduleUpdate();
Util::DepthOffsetAdapter _adapter;
bool _updatePending;
virtual ~DepthOffsetGroup() { }
};
} // namespace osgEarth
#endif // OSGEARTH_DEPTH_ADJUSTMENT_H