diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 9dc68a7d9b..a818e24bc4 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -2422,20 +2422,24 @@ void GLGraphicsStateGuardian::apply_material(const Material *material) { //////////////////////////////////////////////////////////////////// void GLGraphicsStateGuardian:: apply_fog(Fog *fog) { - Fog::Mode fmode=fog->get_mode(); + Fog::Mode fmode = fog->get_mode(); call_glFogMode(get_fog_mode_type(fmode)); - switch(fmode) { - case Fog::M_linear: - float fog_start,fog_end; - fog->get_range(fog_start,fog_end); - call_glFogStart(fog_start); - call_glFogEnd(fog_end); - break; - case Fog::M_exponential: - case Fog::M_exponential_squared: - call_glFogDensity(fog->get_density()); - break; + + if (fmode == Fog::M_linear) { + // Linear fog may be world-relative or camera-relative. The fog + // object knows how to decode its parameters into camera-relative + // properties. + float onset, opaque; + fog->compute_linear_range(onset, opaque, _current_projection_node, + _coordinate_system); + call_glFogStart(onset); + call_glFogEnd(opaque); + + } else { + // Exponential fog is always camera-relative. + call_glFogDensity(fog->get_exp_density()); } + call_glFogColor(fog->get_color()); report_errors(); } diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 066705b3c8..7e4f408e37 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -9,7 +9,7 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define SOURCES \ - LOD.I LOD.h config_gobj.h drawable.h fog.I fog.h geom.I geom.N \ + LOD.I LOD.h config_gobj.h drawable.h geom.I geom.N \ geom.h geomLine.h geomLinestrip.h geomPoint.h geomPolygon.h \ geomQuad.h geomSphere.h geomSprite.I geomSprite.h geomTri.h \ geomTrifan.h geomTristrip.h imageBuffer.I imageBuffer.h \ @@ -20,7 +20,7 @@ texturePool.I texturePool.h #define INCLUDED_SOURCES \ - LOD.cxx config_gobj.cxx drawable.cxx fog.cxx geom.cxx \ + LOD.cxx config_gobj.cxx drawable.cxx geom.cxx \ geomLine.cxx geomLinestrip.cxx geomPoint.cxx geomPolygon.cxx \ geomQuad.cxx geomSphere.cxx geomSprite.cxx geomTri.cxx \ geomTrifan.cxx geomTristrip.cxx imageBuffer.cxx material.cxx \ @@ -30,7 +30,7 @@ #define INSTALL_HEADERS \ LOD.I LOD.h config_gobj.h \ - drawable.h fog.I fog.h geom.I geom.h geomLine.h \ + drawable.h geom.I geom.h geomLine.h \ geomLinestrip.h geomPoint.h geomPolygon.h geomQuad.h geomSphere.h \ geomSprite.I geomSprite.h geomTri.h geomTrifan.h geomTristrip.h \ geomprimitives.h imageBuffer.I imageBuffer.h material.I material.h \ diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index b0147d4bd7..c605c403c0 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -20,7 +20,6 @@ #include "config_gobj.h" #include "LOD.h" #include "drawable.h" -#include "fog.h" #include "geom.h" #include "geomprimitives.h" #include "imageBuffer.h" @@ -163,7 +162,6 @@ ConfigureFn(config_gobj) { textures_down_square = config_gobj.GetBool("textures-square", false); } - Fog::init_type(); Geom::init_type(); GeomLine::init_type(); GeomLinestrip::init_type(); diff --git a/panda/src/gobj/fog.I b/panda/src/gobj/fog.I deleted file mode 100644 index 4058928eac..0000000000 --- a/panda/src/gobj/fog.I +++ /dev/null @@ -1,101 +0,0 @@ -// Filename: fog.I -// Created by: krisg (05Feb01) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: Fog::get_mode -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE Fog::Mode Fog::get_mode(void) const { - return _mode; -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::set_mode -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void Fog::set_mode(Mode mode) { - _mode = mode; -// compute_density(); -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::get_color -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE Colorf Fog::get_color(void) const { - return _color; -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::set_color -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void Fog::set_color(const Colorf &color) { - _color = color; -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::get_range -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void Fog::get_range(float &onset, float &opaque) const { - onset = _onset_distance; - opaque = _opaque_distance; -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::set_range -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void Fog::set_range(float onset, float opaque) { - _onset_distance = onset; - _opaque_distance = opaque; -// compute_density(); -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::get_density -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE float Fog::get_density(void) const { - return _density; -} - -INLINE void Fog::set_density(float fDensity) { - assert((fDensity >= 0.0) && (fDensity <= 1.0)); - _density = fDensity; -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::apply -// Access: Public -// Description: Called during rendering to enable fogging with the -// GSG. -//////////////////////////////////////////////////////////////////// -INLINE void Fog:: -apply(GraphicsStateGuardianBase *gsg) { - gsg->apply_fog(this); -} diff --git a/panda/src/gobj/fog.cxx b/panda/src/gobj/fog.cxx deleted file mode 100644 index 846de68f72..0000000000 --- a/panda/src/gobj/fog.cxx +++ /dev/null @@ -1,113 +0,0 @@ -// Filename: fog.cxx -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// -#include - -#include "fog.h" - -#include -#include - -//////////////////////////////////////////////////////////////////// -// Static variables -//////////////////////////////////////////////////////////////////// -TypeHandle Fog::_type_handle; - -ostream & -operator << (ostream &out, Fog::Mode mode) { - switch (mode) { - case Fog::M_linear: - return out << "linear"; - - case Fog::M_exponential: - return out << "exponential"; - - case Fog::M_exponential_squared: - return out << "exponential-squared"; - } - - return out << "**invalid**(" << (int)mode << ")"; -} - -//////////////////////////////////////////////////////////////////// -// Function: Fog::Constructor -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -Fog::Fog(Mode mode, int bits_per_color_channel) { - _bits_per_color_channel = bits_per_color_channel; - set_mode(mode); - set_color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); - set_range(0.0f, 100.0f); - - _density = 0.5f; -// compute_density(); -} - -#if 0 -// this fn tries to 'match' exponential to linear fog by computing a exponential density -// factor such that exponential fog matches linear fog at the linear fog's 'fog-end' distance. -// usefulness of this is debatable since the exponential fog that matches will be very very -// close to observer, and it's harder to guess a good end fog distance than it is to manipulate -// the [0.0,1.0] density range directly, so taking this out - -//////////////////////////////////////////////////////////////////// -// Function: Fog::compute_density -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -void Fog::compute_density(void) { - _density = 1.0f; - float opaque_multiplier; - switch (_mode) { - case M_linear: - break; - case M_exponential: - // Multiplier = ln(2^bits) - // attempt to compute density based on full - opaque_multiplier = MathNumbers::ln2 * _bits_per_color_channel; - _density = opaque_multiplier / _opaque_distance; - break; - case M_exponential_squared: - // Multiplier = ln(sqrt(2^bits)) - opaque_multiplier = 0.5f * MathNumbers::ln2 * _bits_per_color_channel; - opaque_multiplier *= opaque_multiplier; - _density = opaque_multiplier / _opaque_distance; - break; - } -} - -#endif - -//////////////////////////////////////////////////////////////////// -// Function: Fog::output -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void Fog:: -output(ostream &out) const { - out << "fog:" << _mode; - switch (_mode) { - case M_linear: - break; - case M_exponential: - case M_exponential_squared: - out << "(" << _bits_per_color_channel << "," << _density - << "," << _opaque_distance << ")"; - break; - }; -} diff --git a/panda/src/gobj/fog.h b/panda/src/gobj/fog.h deleted file mode 100644 index 363f9a38a3..0000000000 --- a/panda/src/gobj/fog.h +++ /dev/null @@ -1,108 +0,0 @@ -// Filename: fog.h -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://www.panda3d.org/license.txt . -// -// To contact the maintainers of this program write to -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// -#ifndef FOG_H -#define FOG_H -// -//////////////////////////////////////////////////////////////////// -// Includes -//////////////////////////////////////////////////////////////////// -#include - -#include -#include -#include -#include - -//////////////////////////////////////////////////////////////////// -// Defines -//////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// -// Class : Fog -// Description : Specifies atmospheric fog parameters -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA Fog : public TypedReferenceCount { -PUBLISHED: - enum Mode { - M_linear, // f = (end - z) / (end - start) - M_exponential, // f = e^(-density * z) - M_exponential_squared // f = e^((-density * z)^2) - }; - - Fog(Mode mode = M_linear, int bits_per_color_channel = 8); - - INLINE ~Fog(void) {}; - - INLINE Mode get_mode(void) const; - INLINE void set_mode(Mode mode); - - INLINE Colorf get_color(void) const; - INLINE void set_color(const Colorf &color); - - INLINE void get_range(float &onset, float &opaque) const; - INLINE void set_range(float onset, float opaque); - - INLINE float get_density(void) const; - INLINE void set_density(float fDensity); - - void output(ostream &out) const; - -public: - INLINE void apply(GraphicsStateGuardianBase *gsg); - -protected: - void compute_density(void); - -protected: - Mode _mode; - int _bits_per_color_channel; - Colorf _color; - float _onset_distance; - float _opaque_distance; - float _density; - -public: - - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedReferenceCount::init_type(); - register_type(_type_handle, "Fog", - TypedReferenceCount::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - - static TypeHandle _type_handle; -}; - -ostream &operator << (ostream &out, Fog::Mode mode); - -INLINE ostream &operator << (ostream &out, const Fog &fog) { - fog.output(out); - return out; -} - -#include "fog.I" - -#endif diff --git a/panda/src/gobj/gobj_composite1.cxx b/panda/src/gobj/gobj_composite1.cxx index d93ef6cd00..5818a592fb 100644 --- a/panda/src/gobj/gobj_composite1.cxx +++ b/panda/src/gobj/gobj_composite1.cxx @@ -10,5 +10,4 @@ #include "geomTri.cxx" #include "geomTrifan.cxx" #include "geomTristrip.cxx" -#include "fog.cxx" diff --git a/panda/src/sgattrib/Sources.pp b/panda/src/sgattrib/Sources.pp index 5c92103f47..40343e5849 100644 --- a/panda/src/sgattrib/Sources.pp +++ b/panda/src/sgattrib/Sources.pp @@ -28,7 +28,7 @@ depthTestTransition.I depthTestTransition.h \ depthWriteTransition.I depthWriteTransition.h \ drawBoundsTransition.I drawBoundsTransition.h \ - fogTransition.I fogTransition.h \ + fog.I fog.h fogTransition.I fogTransition.h \ linesmoothTransition.I linesmoothTransition.h \ materialTransition.I \ materialTransition.h pointShapeProperty.I \ @@ -61,7 +61,7 @@ cullFaceProperty.cxx cullFaceTransition.cxx \ decalTransition.cxx depthTestProperty.cxx \ depthTestTransition.cxx depthWriteTransition.cxx \ - drawBoundsTransition.cxx fogTransition.cxx \ + drawBoundsTransition.cxx fog.cxx fogTransition.cxx \ linesmoothTransition.cxx \ materialTransition.cxx pointShapeProperty.cxx \ pointShapeTransition.cxx \ @@ -96,7 +96,7 @@ depthTestTransition.I depthTestTransition.h \ depthWriteTransition.I depthWriteTransition.h \ drawBoundsTransition.I drawBoundsTransition.h \ - fogTransition.I fogTransition.h \ + fog.I fog.h fogTransition.I fogTransition.h \ linesmoothTransition.I \ linesmoothTransition.h \ materialTransition.I materialTransition.h \ diff --git a/panda/src/sgattrib/config_sgattrib.cxx b/panda/src/sgattrib/config_sgattrib.cxx index 4620492ad4..e552bced15 100644 --- a/panda/src/sgattrib/config_sgattrib.cxx +++ b/panda/src/sgattrib/config_sgattrib.cxx @@ -33,6 +33,7 @@ #include "textureApplyTransition.h" #include "clipPlaneTransition.h" #include "transparencyTransition.h" +#include "fog.h" #include "fogTransition.h" #include "linesmoothTransition.h" #include "transformTransition.h" @@ -132,6 +133,7 @@ ConfigureFn(config_sgattrib) { TextureApplyTransition::init_type(); ClipPlaneTransition::init_type(); TransparencyTransition::init_type(); + Fog::init_type(); FogTransition::init_type(); LinesmoothTransition::init_type(); PruneTransition::init_type(); diff --git a/panda/src/sgattrib/fog.I b/panda/src/sgattrib/fog.I new file mode 100644 index 0000000000..b842c56c8c --- /dev/null +++ b/panda/src/sgattrib/fog.I @@ -0,0 +1,283 @@ +// Filename: fog.I +// Created by: krisg (05Feb01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: Fog::get_mode +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE Fog::Mode Fog:: +get_mode() const { + return _mode; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_mode +// Access: Published +// Description: Specifies the computation that is used to determine +// the fog effect. If this is M_linear, then the fog +// will range from linearly from the onset point to the +// opaque point (or for the distances specified in +// set_linear_range), and the fog object should be +// parented into the scene graph, or to the camera. +// +// If this is anything else, the onset point and opaque +// point are not used, and the fog effect is based on +// the value specified to set_exp_density(), and it +// doesn't matter to which node the fog object is +// parented, or if it is parented anywhere at all. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_mode(Mode mode) { + _mode = mode; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::get_bits_per_color_channel +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE int Fog:: +get_bits_per_color_channel() const { + return _bits_per_color_channel; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_bits_per_color_channel +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_bits_per_color_channel(int bits_per_color_channel) { + _bits_per_color_channel = bits_per_color_channel; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::get_color +// Access: Published +// Description: Returns the color of the fog. +//////////////////////////////////////////////////////////////////// +INLINE const Colorf &Fog:: +get_color() const { + return _color; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_color +// Access: Published +// Description: Sets the color of the fog. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_color(float r, float g, float b) { + _color[0] = r; + _color[1] = g; + _color[2] = b; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_color +// Access: Published +// Description: Sets the color of the fog. The alpha component is +// not used. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_color(const Colorf &color) { + _color = color; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_linear_range +// Access: Published +// Description: Specifies the effects of the fog in linear distance +// units. This is only used if the mode is M_linear. +// +// This specifies a fog that begins at distance onset +// units from the origin, and becomes totally opaque at +// distance opaque units from the origin, along the +// forward axis (usually Y). +// +// This function also implicitly sets the mode the +// M_linear, if it is not already set. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_linear_range(float onset, float opaque, CoordinateSystem cs) { + LVector3f forward = LVector3f::forward(cs); + _linear_onset_point = onset * forward; + _linear_opaque_point = opaque * forward; + _mode = M_linear; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::get_linear_onset_point +// Access: Published +// Description: Returns the point in space at which the fog begins. +// This is only used if the mode is M_linear. +//////////////////////////////////////////////////////////////////// +INLINE const LPoint3f &Fog:: +get_linear_onset_point() const { + return _linear_onset_point; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_linear_onset_point +// Access: Published +// Description: Specifies the point in space at which the fog begins. +// This is only used if the mode is M_linear. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_linear_onset_point(float x, float y, float z) { + _linear_onset_point.set(x, y, z); +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_linear_onset_point +// Access: Published +// Description: Specifies the point in space at which the fog begins. +// This is only used if the mode is M_linear. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_linear_onset_point(const LPoint3f &linear_onset_point) { + _linear_onset_point = linear_onset_point; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::get_linear_opaque_point +// Access: Published +// Description: Returns the point in space at which the fog +// completely obscures geometry. This is only used if +// the mode is M_linear. +//////////////////////////////////////////////////////////////////// +INLINE const LPoint3f &Fog:: +get_linear_opaque_point() const { + return _linear_opaque_point; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_linear_opaque_point +// Access: Published +// Description: Specifies the point in space at which the fog +// completely obscures geometry. This is only used if +// the mode is M_linear. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_linear_opaque_point(float x, float y, float z) { + _linear_opaque_point.set(x, y, z); +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_linear_opaque_point +// Access: Published +// Description: Specifies the point in space at which the fog +// completely obscures geometry. This is only used if +// the mode is M_linear. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_linear_opaque_point(const LPoint3f &linear_opaque_point) { + _linear_opaque_point = linear_opaque_point; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_linear_fallback +// Access: Published +// Description: Fog effects are traditionally defined in +// camera-relative space, but the Panda Fog node has a +// special mode in which it can define a linear fog +// effect in an arbitrary coordinate space. +// +// This is done by specifying 3-d onset and opaque +// points, and parenting the Fog object somewhere within +// the scene graph. In this mode, the fog will be +// rendered as if it extended along the vector from the +// onset point to the opaque point, in 3-d space. +// +// However, the underlying fog effect supported by +// hardware is generally only one-dimensional, and must +// be rendered based on linear distance from the camera +// plane. Thus, this in-the-world effect is most +// effective when the fog vector from onset point to +// opaque point is most nearly parallel to the camera's +// eye vector. +// +// As the angle between the fog vector and the eye +// vector increases, the accuracy of the effect +// diminishes, up to a complete breakdown of the effect +// at a 90 degree angle. +// +// This function exists to define the workaround to this +// problem. The linear fallback parameters given here +// specify how the fog should be rendered when the +// parameters are exceeded in this way. +// +// The angle parameter is the minimum angle, in degrees, +// of the fog vector to the eye vector, at which the +// fallback effect should be employed. The onset and +// opaque parameters specify the camera-relative onset +// and opaque distances to pass to the rendering +// hardware when employing the fallback effect. This +// supercedes the 3-d onset point and opaque points. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_linear_fallback(float angle, float onset, float opaque) { + _linear_fallback_cosa = ccos(deg_2_rad(angle)); + _linear_fallback_onset = onset; + _linear_fallback_opaque = opaque; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::get_exp_density +// Access: Published +// Description: Returns the density of the fog for exponential +// calculations. This is only used if the mode is not +// M_linear. +//////////////////////////////////////////////////////////////////// +INLINE float Fog:: +get_exp_density() const { + return _exp_density; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::set_exp_density +// Access: Published +// Description: Sets the density of the fog for exponential +// calculations. This is only used if the mode is not +// M_linear. +// +// If the mode is currently set to M_linear, this +// function implicitly sets it to M_exponential. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +set_exp_density(float exp_density) { + nassertv((exp_density >= 0.0) && (exp_density <= 1.0)); + _exp_density = exp_density; + + if (_mode == M_linear) { + _mode = M_exponential; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::apply +// Access: Public +// Description: Called during rendering to enable fogging with the +// GSG. +//////////////////////////////////////////////////////////////////// +INLINE void Fog:: +apply(GraphicsStateGuardianBase *gsg) { + gsg->apply_fog(this); +} diff --git a/panda/src/sgattrib/fog.cxx b/panda/src/sgattrib/fog.cxx new file mode 100644 index 0000000000..0742873bfe --- /dev/null +++ b/panda/src/sgattrib/fog.cxx @@ -0,0 +1,258 @@ +// Filename: fog.cxx +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// +#include "pandabase.h" + +#include "fog.h" + +#include "mathNumbers.h" +#include "renderRelation.h" +#include "transformTransition.h" +#include "wrt.h" + +#include + +//////////////////////////////////////////////////////////////////// +// Static variables +//////////////////////////////////////////////////////////////////// +TypeHandle Fog::_type_handle; + +ostream & +operator << (ostream &out, Fog::Mode mode) { + switch (mode) { + case Fog::M_linear: + return out << "linear"; + + case Fog::M_exponential: + return out << "exponential"; + + case Fog::M_exponential_squared: + return out << "exponential-squared"; + } + + return out << "**invalid**(" << (int)mode << ")"; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +Fog:: +Fog(const string &name) : NamedNode(name) { + _mode = M_linear; + _bits_per_color_channel = 8; + _color.set(1.0f, 1.0f, 1.0f, 1.0f); + _linear_onset_point.set(0.0f, 0.0f, 0.0f); + _linear_opaque_point.set(0.0, 100.0f, 0.0f); + _exp_density = 0.5f; + _linear_fallback_cosa = -1.0f; + _linear_fallback_onset = 0.0f; + _linear_fallback_opaque = 0.0f; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +Fog:: +Fog(const Fog ©) : + NamedNode(copy) +{ + _mode = copy._mode; + _bits_per_color_channel = copy._bits_per_color_channel; + _color = copy._color; + _linear_onset_point = copy._linear_onset_point; + _linear_opaque_point = copy._linear_opaque_point; + _exp_density = copy._exp_density; + _linear_fallback_cosa = copy._linear_fallback_cosa; + _linear_fallback_onset = copy._linear_fallback_onset; + _linear_fallback_opaque = copy._linear_fallback_opaque; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void Fog:: +operator = (const Fog ©) { + NamedNode::operator = (copy); + _mode = copy._mode; + _bits_per_color_channel = copy._bits_per_color_channel; + _color = copy._color; + _linear_onset_point = copy._linear_onset_point; + _linear_opaque_point = copy._linear_opaque_point; + _exp_density = copy._exp_density; + _linear_fallback_cosa = copy._linear_fallback_cosa; + _linear_fallback_onset = copy._linear_fallback_onset; + _linear_fallback_opaque = copy._linear_fallback_opaque; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +Fog:: +~Fog() { +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::make_copy +// Access: Public, Virtual +// Description: Returns a newly-allocated Node that is a shallow copy +// of this one. It will be a different Node pointer, +// but its internal data may or may not be shared with +// that of the original Node. +//////////////////////////////////////////////////////////////////// +Node *Fog:: +make_copy() const { + return new Fog(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::xform +// Access: Public, Virtual +// Description: Transforms the contents of this node by the indicated +// matrix, if it means anything to do so. For most +// kinds of nodes, this does nothing. +//////////////////////////////////////////////////////////////////// +void Fog:: +xform(const LMatrix4f &mat) { + _linear_onset_point = _linear_onset_point * mat; + _linear_opaque_point = _linear_opaque_point * mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::output +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void Fog:: +output(ostream &out) const { + out << "fog: " << _mode; + switch (_mode) { + case M_linear: + out << "(" << _linear_onset_point << ") -> (" + << _linear_opaque_point << ")"; + break; + + case M_exponential: + case M_exponential_squared: + out << "(" << _bits_per_color_channel << ", " << _exp_density + << ")"; + break; + }; +} + +//////////////////////////////////////////////////////////////////// +// Function: Fog::compute_linear_range +// Access: Public +// Description: This function is intended to be called by GSG's to +// compute the appropriate camera-relative onset and +// opaque distances, based on the fog node's position +// within the scene graph (if linear fog is in effect). +//////////////////////////////////////////////////////////////////// +void Fog:: +compute_linear_range(float &onset, float &opaque, + Node *camera_node, CoordinateSystem cs) { + LVector3f forward = LVector3f::forward(cs); + + LPoint3f onset_point, opaque_point; + if (get_num_parents(RenderRelation::get_class_type()) != 0) { + // Linear fog is relative to the fog's net transform in the scene + // graph. + LMatrix4f mat; + + NodeTransitionWrapper ntw(TransformTransition::get_class_type()); + wrt(this, camera_node, ntw, RenderRelation::get_class_type()); + const TransformTransition *tt; + if (!get_transition_into(tt, ntw)) { + // No relative transform. + mat = LMatrix4f::ident_mat(); + } else { + mat = tt->get_matrix(); + } + + // How far out of whack are we? + LVector3f fog_vector = (_linear_opaque_point - _linear_onset_point) * mat; + fog_vector.normalize(); + float cosa = fog_vector.dot(forward); + if (cabs(cosa) < _linear_fallback_cosa) { + // The fog vector is too far from the eye vector; use the + // fallback mode. + onset = _linear_fallback_onset; + opaque = _linear_fallback_opaque; + //cerr << "fallback! " << cosa << " vs. " << _linear_fallback_cosa << "\n"; + return; + } + + onset_point = _linear_onset_point * mat; + opaque_point = _linear_opaque_point * mat; + + } else { + // If the fog object has no parents, we assume the user meant + // camera-relative fog. + onset_point = _linear_onset_point; + opaque_point = _linear_opaque_point; + } + + onset = onset_point.dot(forward); + opaque = opaque_point.dot(forward); +} + +#if 0 +// this fn tries to 'match' exponential to linear fog by computing an +// exponential density factor such that exponential fog matches linear +// fog at the linear fog's 'fog-end' distance. usefulness of this is +// debatable since the exponential fog that matches will be very very +// close to observer, and it's harder to guess a good end fog distance +// than it is to manipulate the [0.0,1.0] density range directly, so +// taking this out + +//////////////////////////////////////////////////////////////////// +// Function: Fog::compute_density +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +void Fog::compute_density(void) { + _density = 1.0f; + float opaque_multiplier; + switch (_mode) { + + case M_linear: + break; + + case M_exponential: + // Multiplier = ln(2^bits) + // attempt to compute density based on full + opaque_multiplier = MathNumbers::ln2 * _bits_per_color_channel; + _density = opaque_multiplier / _opaque_distance; + break; + + case M_exponential_squared: + // Multiplier = ln(sqrt(2^bits)) + opaque_multiplier = 0.5f * MathNumbers::ln2 * _bits_per_color_channel; + opaque_multiplier *= opaque_multiplier; + _density = opaque_multiplier / _opaque_distance; + break; + } +} + +#endif diff --git a/panda/src/sgattrib/fog.h b/panda/src/sgattrib/fog.h new file mode 100644 index 0000000000..32afb4f65f --- /dev/null +++ b/panda/src/sgattrib/fog.h @@ -0,0 +1,144 @@ +// Filename: fog.h +// Created by: mike (09Jan97) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// +#ifndef FOG_H +#define FOG_H + +#include "pandabase.h" + +#include "graphicsStateGuardianBase.h" +#include "luse.h" +#include "pointerToArray.h" +#include "namedNode.h" +#include "cmath.h" +#include "deg_2_rad.h" + +class ArcChain; + +//////////////////////////////////////////////////////////////////// +// Class : Fog +// Description : Specifies how atmospheric fog effects are applied to +// geometry. The Fog object is now a Node, which means +// it can be used similar to a Light to define effects +// relative to a particular coordinate system within the +// scene graph. +// +// In exponential mode, the fog effects are always +// camera-relative, and it does not matter where the Fog +// node is parented. However, in linear mode, the onset +// and opaque distances are defined as offsets along the +// local forward axis (e.g. the Y axis). This allows +// the fog effect to be localized to a particular region +// in space, rather than always camera-relative. If the +// fog object is not parented to any node, it is treated +// as if it were parented to the camera. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA Fog : public NamedNode { +PUBLISHED: + Fog(const string &name = ""); + +public: + Fog(const Fog ©); + void operator = (const Fog ©); + virtual ~Fog(); + + virtual Node *make_copy() const; + virtual void xform(const LMatrix4f &mat); + +PUBLISHED: + enum Mode { + M_linear, // f = (end - z) / (end - start) + M_exponential, // f = e^(-density * z) + M_exponential_squared // f = e^((-density * z)^2) + }; + + INLINE Mode get_mode() const; + INLINE void set_mode(Mode mode); + + INLINE int get_bits_per_color_channel() const; + INLINE void set_bits_per_color_channel(int bits_per_color_channel); + + INLINE const Colorf &get_color() const; + INLINE void set_color(float r, float g, float b); + INLINE void set_color(const Colorf &color); + + INLINE void set_linear_range(float onset, float opaque, + CoordinateSystem cs = CS_default); + + INLINE const LPoint3f &get_linear_onset_point() const; + INLINE void set_linear_onset_point(float x, float y, float z); + INLINE void set_linear_onset_point(const LPoint3f &linear_onset_point); + + INLINE const LPoint3f &get_linear_opaque_point() const; + INLINE void set_linear_opaque_point(const LPoint3f &linear_opaque_point); + INLINE void set_linear_opaque_point(float x, float y, float z); + + INLINE void set_linear_fallback(float angle, float onset, float opaque); + + INLINE float get_exp_density() const; + INLINE void set_exp_density(float exp_density); + + void output(ostream &out) const; + +public: + INLINE void apply(GraphicsStateGuardianBase *gsg); + + void compute_linear_range(float &onset, float &opaque, + Node *camera_node, CoordinateSystem cs); + +protected: + void compute_density(); + +protected: + Mode _mode; + int _bits_per_color_channel; + Colorf _color; + LPoint3f _linear_onset_point; + LPoint3f _linear_opaque_point; + float _exp_density; + + float _linear_fallback_cosa; + float _linear_fallback_onset, _linear_fallback_opaque; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "Fog", + TypedReferenceCount::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +ostream &operator << (ostream &out, Fog::Mode mode); + +INLINE ostream &operator << (ostream &out, const Fog &fog) { + fog.output(out); + return out; +} + +#include "fog.I" + +#endif diff --git a/panda/src/sgattrib/fogTransition.h b/panda/src/sgattrib/fogTransition.h index bcdd0922f9..6019408710 100644 --- a/panda/src/sgattrib/fogTransition.h +++ b/panda/src/sgattrib/fogTransition.h @@ -19,10 +19,10 @@ #ifndef FOGTRANSITION_H #define FOGTRANSITION_H -#include +#include "pandabase.h" -#include -#include +#include "onOffTransition.h" +#include "fog.h" //////////////////////////////////////////////////////////////////// // Class : FogTransition diff --git a/panda/src/sgattrib/sgattrib_composite1.cxx b/panda/src/sgattrib/sgattrib_composite1.cxx index a2340523cf..659afd3ab6 100644 --- a/panda/src/sgattrib/sgattrib_composite1.cxx +++ b/panda/src/sgattrib/sgattrib_composite1.cxx @@ -11,3 +11,4 @@ #include "depthTestTransition.cxx" #include "depthWriteTransition.cxx" #include "drawBoundsTransition.cxx" +#include "fog.cxx"