From f7d7a746f3269aa398cef938c39085766c463ca5 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 26 Aug 2003 22:09:15 +0000 Subject: [PATCH] Added missing osgFX files. --- include/osgFX/AnisotropicLighting | 122 +++++++++ include/osgFX/Cartoon | 121 +++++++++ include/osgFX/Effect | 246 ++++++++++++++++++ include/osgFX/Export | 28 ++ include/osgFX/Registry | 80 ++++++ include/osgFX/Scribe | 101 +++++++ include/osgFX/SpecularHighlights | 138 ++++++++++ include/osgFX/Technique | 188 +++++++++++++ include/osgFX/Validator | 73 ++++++ src/osgPlugins/osgFX/GNUmakefile | 18 ++ .../osgFX/IO_AnisotropicLighting.cpp | 59 +++++ src/osgPlugins/osgFX/IO_Cartoon.cpp | 64 +++++ src/osgPlugins/osgFX/IO_Effect.cpp | 71 +++++ src/osgPlugins/osgFX/IO_Scribe.cpp | 54 ++++ .../osgFX/IO_SpecularHighlights.cpp | 75 ++++++ 15 files changed, 1438 insertions(+) create mode 100644 include/osgFX/AnisotropicLighting create mode 100644 include/osgFX/Cartoon create mode 100644 include/osgFX/Effect create mode 100644 include/osgFX/Export create mode 100644 include/osgFX/Registry create mode 100644 include/osgFX/Scribe create mode 100644 include/osgFX/SpecularHighlights create mode 100644 include/osgFX/Technique create mode 100644 include/osgFX/Validator create mode 100644 src/osgPlugins/osgFX/GNUmakefile create mode 100644 src/osgPlugins/osgFX/IO_AnisotropicLighting.cpp create mode 100644 src/osgPlugins/osgFX/IO_Cartoon.cpp create mode 100644 src/osgPlugins/osgFX/IO_Effect.cpp create mode 100644 src/osgPlugins/osgFX/IO_Scribe.cpp create mode 100644 src/osgPlugins/osgFX/IO_SpecularHighlights.cpp diff --git a/include/osgFX/AnisotropicLighting b/include/osgFX/AnisotropicLighting new file mode 100644 index 000000000..fabc3072a --- /dev/null +++ b/include/osgFX/AnisotropicLighting @@ -0,0 +1,122 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_ANISOTROPICLIGHTING_ +#define OSGFX_ANISOTROPICLIGHTING_ + +#include +#include + +#include +#include + +namespace osgFX +{ + + /** + This single-pass effect implements a sort of anisotropic + lighting that replaces the standard OpenGL lighting model. + The final color of vertices is not computed directly, it is + the result of a texture lookup on a user-supplied lighting + image map. A vertex program is used to compute the s and t + texture coordinates as follows: s = (N dot H) ; t = (N dot L) + where N is the vertex normal, L is the light-to-vertex vector, + H is the half-way vector. This is a good example of how you + can use the State::getInitialViewMatrix() method to retrieve + the view matrix and perform view-dependant effects without + fakes of any kind. + This effect requires the ARB_vertex_program extension. + */ + class OSGFX_EXPORT AnisotropicLighting: public Effect { + public: + AnisotropicLighting(); + AnisotropicLighting(const AnisotropicLighting ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + META_Effect(osgFX, AnisotropicLighting, + + "Anisotropic Lighting", + + "This single-pass effect implements a sort of anisotropic " + "lighting that replaces the standard OpenGL lighting model.\n" + "The final color of vertices is not computed directly, it is " + "the result of a texture lookup on a user-supplied lighting " + "image map. A vertex program is used to compute the s and t " + "texture coordinates as follows: s = (N dot H) ; t = (N dot L) " + "where N is the vertex normal, L is the light-to-vertex vector, " + "H is the half-way vector. This is a good example of how you " + "can use the State::getInitialViewMatrix() method to retrieve " + "the view matrix and perform view-dependant effects without " + "fakes of any kind.\n" + "This effect requires the ARB_vertex_program extension.", + + "Marco Jez"); + + + /** get the lighting map */ + inline osg::Image *getLightingMap(); + + /** get the const lighting map */ + inline const osg::Image *getLightingMap() const; + + /** set the lighting map */ + inline void setLightingMap(osg::Image *image); + + /** get the OpenGL light number */ + inline int getLightNumber() const; + + /** set the OpenGL light number that will be used in lighting computations */ + inline void setLightNumber(int n); + + protected: + virtual ~AnisotropicLighting() {} + AnisotropicLighting &operator=(const AnisotropicLighting &) { return *this; } + + bool define_techniques(); + + private: + int lightnum_; + osg::ref_ptr texture_; + }; + + // INLINE METHODS + + inline osg::Image *AnisotropicLighting::getLightingMap() + { + return texture_->getImage(); + } + + inline const osg::Image *AnisotropicLighting::getLightingMap() const + { + return texture_->getImage(); + } + + inline void AnisotropicLighting::setLightingMap(osg::Image *image) + { + texture_->setImage(image); + } + + inline int AnisotropicLighting::getLightNumber() const + { + return lightnum_; + } + + inline void AnisotropicLighting::setLightNumber(int n) + { + lightnum_ = n; + dirtyTechniques(); + } + +} + +#endif diff --git a/include/osgFX/Cartoon b/include/osgFX/Cartoon new file mode 100644 index 000000000..bdbb174f3 --- /dev/null +++ b/include/osgFX/Cartoon @@ -0,0 +1,121 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_CARTOON_ +#define OSGFX_CARTOON_ + +#include +#include + +#include +#include + +namespace osgFX +{ + + /** + This effect implements a technique called 'Cel-Shading' to produce a + cartoon-style (non photorealistic) rendering. Two passes are required: + the first one draws solid surfaces, the second one draws the outlines. + A vertex program is used to setup texture coordinates for a sharp lighting + texture on unit 0 which is generated on-the-fly. + This effect requires the ARB_vertex_program extension. + */ + class OSGFX_EXPORT Cartoon: public Effect { + public: + Cartoon(); + Cartoon(const Cartoon ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + // effect class informations + META_Effect( + osgFX, + Cartoon, + + "Cartoon", + + "This effect implements a technique called 'Cel-Shading' to produce a " + "cartoon-style (non photorealistic) rendering. Two passes are required: " + "the first one draws solid surfaces, the second one draws the outlines. " + "A vertex program is used to setup texture coordinates for a sharp lighting " + "texture on unit 0 which is generated on-the-fly.\n" + "This effect requires the ARB_vertex_program extension.", + + "Marco Jez"); + + /** get the outline color */ + inline const osg::Vec4 &getOutlineColor() const; + + /** set the outline color */ + inline void setOutlineColor(const osg::Vec4 &color); + + /** get the outline line width */ + inline float getOutlineLineWidth() const; + + /** set the outline line width */ + inline void setOutlineLineWidth(float w); + + /** get the OpenGL light number */ + inline int getLightNumber() const; + + /** set the OpenGL light number that will be used in lighting computations */ + inline void setLightNumber(int n); + + protected: + virtual ~Cartoon() {} + Cartoon &operator=(const Cartoon &) { return *this; } + + bool define_techniques(); + + private: + osg::ref_ptr wf_mat_; + osg::ref_ptr wf_lw_; + int lightnum_; + }; + + // INLINE METHODS + + inline const osg::Vec4 &Cartoon::getOutlineColor() const + { + return wf_mat_->getEmission(osg::Material::FRONT_AND_BACK); + } + + inline void Cartoon::setOutlineColor(const osg::Vec4 &color) + { + wf_mat_->setEmission(osg::Material::FRONT_AND_BACK, color); + } + + inline float Cartoon::getOutlineLineWidth() const + { + return wf_lw_->getWidth(); + } + + inline void Cartoon::setOutlineLineWidth(float w) + { + wf_lw_->setWidth(w); + } + + inline int Cartoon::getLightNumber() const + { + return lightnum_; + } + + inline void Cartoon::setLightNumber(int n) + { + lightnum_ = n; + dirtyTechniques(); + } + +} + +#endif diff --git a/include/osgFX/Effect b/include/osgFX/Effect new file mode 100644 index 000000000..5a93f5c65 --- /dev/null +++ b/include/osgFX/Effect @@ -0,0 +1,246 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_EFFECT_ +#define OSGFX_EFFECT_ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/** + An helper macro that defines the methods like effectName() and effectDescription() + making them return the strings passed as parameters, after the usual library name + and class name. + */ +#define META_Effect(library, classname, effectname, effectdescription, effectauthor) \ + META_Node(library, classname) \ + virtual const char *effectName() const { return effectname; } \ + virtual const char *effectDescription() const { return effectdescription; } \ + virtual const char *effectAuthor() const { return effectauthor; } + + +namespace osgFX +{ + + /** + The base class for special effects. An effect is basically a collection of + state attributes and an interface for configuring them in a predefined + fashion. The Effect class does more however, as it handles multipass + rendering transparently and it allows more than one "technique" to be + defined. Each technique tries to implement the effect in a different way, + often using different OpenGL extensions. The active technique can be + selected either manually, with selectTechnique(), or automatically, in which + case the first technique that is supported by all active rendering contexts + is chosen. + If you are an Effect user, then simply use it as a single-child group. + Create an instance of your desired effect, add it to your scene graph (it + is a Node) and call its setChild() method to set its child node as you + would do with a Group. + If you are an Effect developer, you will have to implement the method + define_techniques() to define the different techniques that can be used + for obtaining the desired effect. In define_techniques() you will usually + create one or more instances of custom classes derived from Technique and + you will add them to the effect with addTechnique(). The order is important: + techniques added first will have higher priority and will be used first as + soon as all rendering contexts support it. + */ + class OSGFX_EXPORT Effect: public osg::Node { + public: + Effect(); + Effect(const Effect ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + virtual inline bool isSameKindAs(const osg::Object *obj) const { return dynamic_cast(obj) != NULL; } + virtual inline const char *libraryName() const { return "osgFX"; } + virtual inline const char *className() const { return "Effect"; } + + /** get the name of this effect */ + virtual const char *effectName() const = 0; + + /** get a brief description of this effect */ + virtual const char *effectDescription() const = 0; + + /** get the effect author's name */ + virtual const char *effectAuthor() const = 0; + + /** get whether the effect is enabled or not */ + inline bool getEnabled() const; + + /** set whether the effect is enabled or not */ + inline void setEnabled(bool v); + + /** + optional: set effect parameters to produce a visually significant + result to be used in demo applications like osgfxbrowser. Default + is to do nothing. + */ + inline virtual void setUpDemo() {} + + /** get the const child node */ + inline const osg::Node *getChild() const; + + /** get the child node */ + inline osg::Node *getChild(); + + /** set the child node */ + inline void setChild(osg::Node *child); + + /** get the number of techniques defined for this effect */ + inline int getNumTechniques() const; + + /** get the i-th technique */ + inline Technique *getTechnique(int i); + + /** get the i-th const technique */ + inline const Technique *getTechnique(int i) const; + + /** get the index of the currently selected technique */ + inline int getSelectedTechnique() const; + + enum TechniqueSelection { + AUTO_DETECT = -1 + }; + + /** select a technique or enable automatic detection */ + inline void selectTechnique(int i = AUTO_DETECT); + + virtual void traverse(osg::NodeVisitor &nv); + + protected: + virtual ~Effect() {} + Effect &operator=(const Effect &) { return *this; } + + virtual bool computeBound() const; + + /** force rebuilding of techniques on next traversal */ + inline void dirtyTechniques(); + + /** add a technique to the effect */ + inline void addTechnique(Technique *tech); + + /** + abstract method to be implemented in derived classes; its purpose + if to create the techniques that can be used for obtaining the + desired effect. You will usually call addTechnique() inside + this method. + */ + virtual bool define_techniques() = 0; + + private: + friend class Validator; + + bool enabled_; + + typedef std::vector > Technique_list; + Technique_list techs_; + + mutable osg::buffered_value sel_tech_; + + // use int instead of bool to avoid errors + mutable osg::buffered_value tech_selected_; + int global_sel_tech_; + + bool techs_defined_; + + osg::ref_ptr child_; + osg::ref_ptr dummy_for_validation_; + + void build_dummy_node(); + }; + + // INLINE METHODS + + inline bool Effect::getEnabled() const + { + return enabled_; + } + + inline void Effect::setEnabled(bool v) + { + enabled_ = v; + } + + inline const osg::Node *Effect::getChild() const + { + return child_.get(); + } + + inline osg::Node *Effect::getChild() + { + return child_.get(); + } + + inline void Effect::setChild(osg::Node *child) + { + child_ = child; + setNumChildrenRequiringUpdateTraversal(0); + setNumChildrenWithCullingDisabled(0); + setNumChildrenWithOccluderNodes(0); + if (child) { + if (child->getNumChildrenRequiringUpdateTraversal() > 0 || child->getUpdateCallback()) + setNumChildrenRequiringUpdateTraversal(1); + if (child->getNumChildrenWithCullingDisabled() > 0 || !child->getCullingActive()) + setNumChildrenWithCullingDisabled(1); + if (child->getNumChildrenWithOccluderNodes() > 0 || dynamic_cast(child)) + setNumChildrenWithOccluderNodes(1); + } + dirtyBound(); + } + + inline int Effect::getNumTechniques() const + { + return static_cast(techs_.size()); + } + + inline Technique *Effect::getTechnique(int i) + { + return techs_[i].get(); + } + + inline const Technique *Effect::getTechnique(int i) const + { + return techs_[i].get(); + } + + inline int Effect::getSelectedTechnique() const + { + return global_sel_tech_; + } + + inline void Effect::selectTechnique(int i) + { + global_sel_tech_ = i; + } + + inline void Effect::addTechnique(Technique *tech) + { + techs_.push_back(tech); + } + + inline void Effect::dirtyTechniques() + { + techs_defined_ = false; + } + +} + +#endif diff --git a/include/osgFX/Export b/include/osgFX/Export new file mode 100644 index 000000000..f75dba97a --- /dev/null +++ b/include/osgFX/Export @@ -0,0 +1,28 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_EXPORT_ +#define OSGFX_EXPORT_ + +#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__) + # ifdef OSGFX_LIBRARY + # define OSGFX_EXPORT __declspec(dllexport) + # else + # define OSGFX_EXPORT __declspec(dllimport) + # endif /* OSGFX_LIBRARY */ +#else + # define OSGFX_EXPORT +#endif + +#endif diff --git a/include/osgFX/Registry b/include/osgFX/Registry new file mode 100644 index 000000000..8b9844184 --- /dev/null +++ b/include/osgFX/Registry @@ -0,0 +1,80 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_REGISTRY_ +#define OSGFX_REGISTRY_ + +#include +#include + +#include + +#include +#include + +namespace osgFX +{ + + class OSGFX_EXPORT Registry { + public: + + struct Proxy { + Proxy(const Effect *effect) + { + Registry::instance()->registerEffect(effect); + } + }; + + typedef std::map > Effect_map; + + inline static Registry *instance(); + + inline void registerEffect(const Effect *effect); + + inline const Effect_map &getEffectMap() const; + + protected: + + // Registry is a singleton; constructor and destructor must be protected + Registry(); + ~Registry() {} + + private: + static Registry *instance_; + Effect_map effects_; + }; + + // INLINE METHODS + + inline Registry *Registry::instance() + { + if (!instance_) { + instance_ = new Registry; + } + return instance_; + } + + inline const Registry::Effect_map &Registry::getEffectMap() const + { + return effects_; + } + + inline void Registry::registerEffect(const Effect *effect) + { + effects_[effect->effectName()] = effect; + } + +} + +#endif diff --git a/include/osgFX/Scribe b/include/osgFX/Scribe new file mode 100644 index 000000000..27b80b811 --- /dev/null +++ b/include/osgFX/Scribe @@ -0,0 +1,101 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_SCRIBE_ +#define OSGFX_SCRIBE_ + +#include +#include + +#include +#include + +namespace osgFX +{ + + /** + This is a two-passes effect; the first pass renders the subgraph as usual + while the second pass switches to wireframe mode, sets up lighting and + material to obtain a fixed (user-defined) color and then renders the subgraph. + This effect uses the PolygonOffset attribute to avoid Z-fighting, so it + requires at least OpenGL version 1.1. + */ + class OSGFX_EXPORT Scribe: public Effect { + public: + Scribe(); + Scribe(const Scribe ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + // effect class informations + META_Effect( + osgFX, + Scribe, + + "Scribe", + + "This is a two-passes effect; the first pass renders the subgraph as usual " + "while the second pass switches to wireframe mode, sets up lighting and " + "material to obtain a fixed (user-defined) color and then renders the subgraph.\n" + "This effect uses the PolygonOffset attribute to avoid Z-fighting, so it " + "requires at least OpenGL version 1.1.", + + "Marco Jez"); + + /** get the wireframe color */ + inline const osg::Vec4 &getWireframeColor() const; + + /** set the wireframe color */ + inline void setWireframeColor(const osg::Vec4 &color); + + /** get the wireframe line width */ + inline float getWireframeLineWidth() const; + + /** set the wireframe line width */ + inline void setWireframeLineWidth(float w); + + protected: + virtual ~Scribe() {} + Scribe &operator=(const Scribe &) { return *this; } + + bool define_techniques(); + + private: + osg::ref_ptr wf_mat_; + osg::ref_ptr wf_lw_; + }; + + // INLINE METHODS + + inline const osg::Vec4 &Scribe::getWireframeColor() const + { + return wf_mat_->getEmission(osg::Material::FRONT_AND_BACK); + } + + inline void Scribe::setWireframeColor(const osg::Vec4 &color) + { + wf_mat_->setEmission(osg::Material::FRONT_AND_BACK, color); + } + + inline float Scribe::getWireframeLineWidth() const + { + return wf_lw_->getWidth(); + } + + inline void Scribe::setWireframeLineWidth(float w) + { + wf_lw_->setWidth(w); + } + +} + +#endif diff --git a/include/osgFX/SpecularHighlights b/include/osgFX/SpecularHighlights new file mode 100644 index 000000000..3d6e4618b --- /dev/null +++ b/include/osgFX/SpecularHighlights @@ -0,0 +1,138 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_SPECULARHIGHLIGHTS_ +#define OSGFX_SPECULARHIGHLIGHTS_ + +#include +#include + +namespace osgFX +{ + + /** + This effect applies additive specular highlights at fragment level (instead + of OpenGL's vertex-level lighting) by using a cube map and reflective texgen. + A texture matrix is computed to rotate the cube map automatically; this makes + the specular effect consistent with respect to view direction and light position. + The user can choose which light should be used to compute the texture matrix. + This effect requires the GL_ARB_texture_env_add extension and one of the cube map + extensions (GL_EXT_texture_cube_map, GL_ARB_texture_cube_map or OpenGL v1.3). + */ + class OSGFX_EXPORT SpecularHighlights: public Effect { + public: + SpecularHighlights(); + SpecularHighlights(const SpecularHighlights ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + META_Effect(osgFX, SpecularHighlights, + + "Specular Highlights", + + "This effect applies additive specular highlights at fragment level (instead " + "of OpenGL's vertex-level lighting) by using a cube map and reflective texgen. " + "A texture matrix is computed to rotate the cube map automatically; this makes " + "the specular effect consistent with respect to view direction and light position. " + "The user can choose which light should be used to compute the texture matrix.\n" + "This effect requires the GL_ARB_texture_env_add extension and one of the cube map " + "extensions (GL_EXT_texture_cube_map, GL_ARB_texture_cube_map or OpenGL v1.3).", + + "Marco Jez"); + + + /** get the OpenGL light number */ + inline int getLightNumber() const; + + /** set the OpenGL light number that will be used in lighting computations */ + inline void setLightNumber(int n); + + /** get the texture unit number */ + inline int getTextureUnit() const; + + /** set the texture unit that will be used to apply the cube map */ + inline void setTextureUnit(int n); + + /** get the specular color */ + inline const osg::Vec4 &getSpecularColor() const; + + /** set the specular color */ + inline void setSpecularColor(const osg::Vec4 &color); + + /** get the specular exponent */ + inline float getSpecularExponent() const; + + /** set the specular exponent */ + inline void setSpecularExponent(float e); + + protected: + virtual ~SpecularHighlights() {} + SpecularHighlights &operator=(const SpecularHighlights &) { return *this; } + + bool define_techniques(); + + private: + int lightnum_; + int unit_; + osg::Vec4 color_; + float sexp_; + }; + + // INLINE METHODS + + inline int SpecularHighlights::getLightNumber() const + { + return lightnum_; + } + + inline void SpecularHighlights::setLightNumber(int n) + { + lightnum_ = n; + dirtyTechniques(); + } + + inline int SpecularHighlights::getTextureUnit() const + { + return unit_; + } + + inline void SpecularHighlights::setTextureUnit(int n) + { + unit_ = n; + dirtyTechniques(); + } + + inline const osg::Vec4 &SpecularHighlights::getSpecularColor() const + { + return color_; + } + + inline void SpecularHighlights::setSpecularColor(const osg::Vec4 &color) + { + color_ = color; + dirtyTechniques(); + } + + inline float SpecularHighlights::getSpecularExponent() const + { + return sexp_; + } + + inline void SpecularHighlights::setSpecularExponent(float e) + { + sexp_ = e; + dirtyTechniques(); + } + +} + +#endif diff --git a/include/osgFX/Technique b/include/osgFX/Technique new file mode 100644 index 000000000..f0f1b38cf --- /dev/null +++ b/include/osgFX/Technique @@ -0,0 +1,188 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_TECHNIQUE_ +#define OSGFX_TECHNIQUE_ + +#include + +#include +#include +#include +#include + +#include +#include + +/** + An helper macro that defines the methods techniqueName() and + techniqueDescription() making them return the strings passed as parameters. + */ +#define META_Technique(name, description) \ + inline virtual const char *techniqueName() { return name; } \ + inline virtual const char *techniqueDescription() { return description; } + + +namespace osgFX +{ + + /** + This is the base class for effect techniques. A technique represents one + of the possible ways to implement a special effect. This base class is + abstract, you will have to subclass your own techniques for your custom + effects. + Derived classes will have to implement the define_passes() method to + configure the rendering pass(es) that make up the technique. Usually + you will create one StateSet object for each rendering pass and then + you'll call addPass(stateset). + The validate() method should return true if the technique is valid within + the current rendering context, false otherwise. The default implementation + of validate() calls getRequiredExtensions() and tests whether all required + extensions are supported or not, returning false if at least one extension + is not supported. + */ + class OSGFX_EXPORT Technique: public osg::Referenced { + public: + Technique(); + + /** get the name of this technique */ + virtual const char *techniqueName() { return "Default"; } + + /** get a brief description of this technique */ + virtual const char *techniqueDescription() { return "This is the default technique"; } + + /** + collect the GL extension strings which are required for this technique + to work properly. This method is called from the default implementation + of validate(). + */ + virtual void getRequiredExtensions(std::vector & /*extensions*/) const {}; + + /** + tests whether this technique is valid for the current rendering context. + The default behavior is to call getRequiredExtensions() and check for + extension availability. + */ + virtual bool validate(osg::State &) const; + + /** get the number of rendering passes defined in this technique */ + inline int getNumPasses() const; + + /** get the Group object associated to the i-th pass */ + inline osg::Group *getPassGroup(int i); + + /** get the const Group object associated to the i-th pass */ + inline const osg::Group *getPassGroup(int i) const; + + /** get the StateSet object associated to the i-th pass */ + inline osg::StateSet *getPassStateSet(int i); + + /** get the const StateSet object associated to the i-th pass */ + inline const osg::StateSet *getPassStateSet(int i) const; + + /** + traverses the child nodes with multipass if necessary. + Don't call this method directly as it is called by osgFX::Effect + */ + virtual void accept(osg::NodeVisitor &nv, osg::Node *child); + + protected: + Technique(const Technique &): osg::Referenced() {} // copying is nonsense ;) + virtual ~Technique() {} + Technique &operator=(const Technique &) { return *this; } + + /** force rebuilding of pass nodes on next traversal */ + inline void dirtyPasses(); + + /** optional: return a node that overrides the child node on a specified pass */ + inline virtual osg::Node *getOverrideChild(int) { return 0; } + + /** create a new pass node, add it to the technique and associate a StateSet */ + void addPass(osg::StateSet *ss = 0); + + /** + add a new pass to the technique specifying an user-defined pass node. + You should call this version of addPass() only when you need to gain direct + control over the pass node (i.e. for setting up a cull callback); otherwise + please use addPass(StateSet*) and let the class create the pass node for you. + */ + void addPass(osg::Group *pass); + + /** + get the control node which holds the user's subgraph. + You may want to do something on it like applying a cull callback. + */ + inline osg::Group *getControlNode(); + + /** get the const control node which holds the user's subgraph */ + inline const osg::Group *getControlNode() const; + + /** + define the rendering passes that make up this technique. You must + implement this method in derived classes to add the required passes. + */ + virtual void define_passes() = 0; + + private: + bool passes_defined_; + + osg::ref_ptr control_node_; + osg::ref_ptr prev_child_; + }; + + // INLINE METHODS + + inline int Technique::getNumPasses() const + { + return static_cast(control_node_->getNumChildren()); + } + + inline osg::Group *Technique::getPassGroup(int i) + { + return static_cast(control_node_->getChild(i)); + } + + inline const osg::Group *Technique::getPassGroup(int i) const + { + return static_cast(control_node_->getChild(i)); + } + + inline osg::StateSet *Technique::getPassStateSet(int i) + { + return control_node_->getChild(i)->getStateSet(); + } + + inline const osg::StateSet *Technique::getPassStateSet(int i) const + { + return control_node_->getChild(i)->getStateSet(); + } + + inline osg::Group *Technique::getControlNode() + { + return control_node_.get(); + } + + inline const osg::Group *Technique::getControlNode() const + { + return control_node_.get(); + } + + inline void Technique::dirtyPasses() + { + passes_defined_ = false; + } + +} + +#endif diff --git a/include/osgFX/Validator b/include/osgFX/Validator new file mode 100644 index 000000000..ca1d4519b --- /dev/null +++ b/include/osgFX/Validator @@ -0,0 +1,73 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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 + * OpenSceneGraph Public License for more details. +*/ +//osgFX - Copyright (C) 2003 Marco Jez + +#ifndef OSGFX_VALIDATOR_ +#define OSGFX_VALIDATOR_ + +#include + +#include +#include + +#include + +namespace osgFX +{ + + // forward declaration + class Effect; + + /** + This class is used internally by osgFX::Effect to choose between different + techniques dynamically. The apply() method will call each technique's + validate() method and store the results in a buffered array. The Effect + class will then choose the first technique that could be validated in all + active rendering contexts. + */ + class OSGFX_EXPORT Validator: public osg::StateAttribute { + public: + Validator(); + Validator(Effect *effect); + Validator(const Validator ©, const osg::CopyOp ©op = osg::CopyOp::SHALLOW_COPY); + + META_StateAttribute(osgFX, Validator, 0x56616C69); + + void apply(osg::State &state) const; + + inline int compare(const osg::StateAttribute &sa) const; + + protected: + virtual ~Validator() {} + Validator &operator=(const Validator &) { return *this; } + + private: + mutable osg::ref_ptr effect_; + }; + + // INLINE METHODS + + inline int Validator::compare(const osg::StateAttribute &sa) const + { + const Validator *v = dynamic_cast(&sa); + if (!v) return -1; + + if (effect_.get() < v->effect_.get()) return -1; + if (effect_.get() > v->effect_.get()) return 1; + + return 0; + } + +} + +#endif diff --git a/src/osgPlugins/osgFX/GNUmakefile b/src/osgPlugins/osgFX/GNUmakefile new file mode 100644 index 000000000..a56a7306c --- /dev/null +++ b/src/osgPlugins/osgFX/GNUmakefile @@ -0,0 +1,18 @@ +TOPDIR = ../../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + IO_AnisotropicLighting.cpp\ + IO_Cartoon.cpp\ + IO_Scribe.cpp\ + IO_SpecularHighlights.cpp\ + IO_Effect.cpp\ + + +LIBS += -losgFX $(OSG_LIBS) $(OTHER_LIBS) + +TARGET_BASENAME = osgFX +include $(TOPDIR)/Make/cygwin_plugin_def +PLUGIN = $(PLUGIN_PREFIX)$(TARGET_BASENAME).$(PLUGIN_EXT) + +include $(TOPDIR)/Make/makerules diff --git a/src/osgPlugins/osgFX/IO_AnisotropicLighting.cpp b/src/osgPlugins/osgFX/IO_AnisotropicLighting.cpp new file mode 100644 index 000000000..8a50b2b3a --- /dev/null +++ b/src/osgPlugins/osgFX/IO_AnisotropicLighting.cpp @@ -0,0 +1,59 @@ +#include + +#include +#include +#include + +bool AnisotropicLighting_readLocalData(osg::Object &obj, osgDB::Input &fr); +bool AnisotropicLighting_writeLocalData(const osg::Object &obj, osgDB::Output &fw); + +osgDB::RegisterDotOsgWrapperProxy AnisotropicLighting_Proxy +( + new osgFX::AnisotropicLighting, + "osgFX::AnisotropicLighting", + "Object Node osgFX::Effect osgFX::AnisotropicLighting", + AnisotropicLighting_readLocalData, + AnisotropicLighting_writeLocalData +); + +bool AnisotropicLighting_readLocalData(osg::Object &obj, osgDB::Input &fr) +{ + osgFX::AnisotropicLighting &myobj = static_cast(obj); + bool itAdvanced = false; + + if (fr[0].matchWord("lightNumber")) { + int n; + if (fr[1].getInt(n)) { + myobj.setLightNumber(n); + fr += 2; + itAdvanced = true; + } + } + + if (fr[0].matchWord("lightingMapFileName") && fr[1].isString()) { + osg::Image *lmap = fr.readImage(fr[1].getStr()); + if (lmap) { + myobj.setLightingMap(lmap); + } + fr += 2; + itAdvanced = true; + } + + return itAdvanced; +} + +bool AnisotropicLighting_writeLocalData(const osg::Object &obj, osgDB::Output &fw) +{ + const osgFX::AnisotropicLighting &myobj = static_cast(obj); + + fw.indent() << "lightNumber " << myobj.getLightNumber() << "\n"; + + const osg::Image *lmap = myobj.getLightingMap(); + if (lmap) { + if (!lmap->getFileName().empty()) { + fw.indent() << "lightingMapFileName \"" << lmap->getFileName() << "\"\n"; + } + } + + return true; +} diff --git a/src/osgPlugins/osgFX/IO_Cartoon.cpp b/src/osgPlugins/osgFX/IO_Cartoon.cpp new file mode 100644 index 000000000..76eb8448d --- /dev/null +++ b/src/osgPlugins/osgFX/IO_Cartoon.cpp @@ -0,0 +1,64 @@ +#include + +#include +#include +#include + +bool Cartoon_readLocalData(osg::Object &obj, osgDB::Input &fr); +bool Cartoon_writeLocalData(const osg::Object &obj, osgDB::Output &fw); + +osgDB::RegisterDotOsgWrapperProxy Cartoon_Proxy +( + new osgFX::Cartoon, + "osgFX::Cartoon", + "Object Node osgFX::Effect osgFX::Cartoon", + Cartoon_readLocalData, + Cartoon_writeLocalData +); + +bool Cartoon_readLocalData(osg::Object &obj, osgDB::Input &fr) +{ + osgFX::Cartoon &myobj = static_cast(obj); + bool itAdvanced = false; + + if (fr[0].matchWord("lightNumber")) { + int n; + if (fr[1].getInt(n)) { + myobj.setLightNumber(n); + fr += 2; + itAdvanced = true; + } + } + + if (fr[0].matchWord("outlineColor")) { + osg::Vec4 w; + if (fr[1].getFloat(w.x()) && fr[2].getFloat(w.y()) && + fr[3].getFloat(w.z()) && fr[4].getFloat(w.w())) { + myobj.setOutlineColor(w); + fr += 5; + itAdvanced = true; + } + } + + if (fr[0].matchWord("outlineLineWidth")) { + float f; + if (fr[1].getFloat(f)) { + myobj.setOutlineLineWidth(f); + fr += 2; + itAdvanced = true; + } + } + + return itAdvanced; +} + +bool Cartoon_writeLocalData(const osg::Object &obj, osgDB::Output &fw) +{ + const osgFX::Cartoon &myobj = static_cast(obj); + + fw.indent() << "lightNumber " << myobj.getLightNumber() << "\n"; + fw.indent() << "outlineColor " << myobj.getOutlineColor() << "\n"; + fw.indent() << "outlineLineWidth " << myobj.getOutlineLineWidth() << "\n"; + + return true; +} diff --git a/src/osgPlugins/osgFX/IO_Effect.cpp b/src/osgPlugins/osgFX/IO_Effect.cpp new file mode 100644 index 000000000..82503c2df --- /dev/null +++ b/src/osgPlugins/osgFX/IO_Effect.cpp @@ -0,0 +1,71 @@ +#include + +#include +#include +#include + +bool Effect_readLocalData(osg::Object &obj, osgDB::Input &fr); +bool Effect_writeLocalData(const osg::Object &obj, osgDB::Output &fw); + +osgDB::RegisterDotOsgWrapperProxy Effect_Proxy +( + 0, + "osgFX::Effect", + "Object Node osgFX::Effect", + Effect_readLocalData, + Effect_writeLocalData +); + +bool Effect_readLocalData(osg::Object &obj, osgDB::Input &fr) +{ + osgFX::Effect &myobj = static_cast(obj); + bool itAdvanced = false; + + if (fr[0].matchWord("enabled")) { + if (fr[1].matchWord("FALSE")) { + myobj.setEnabled(false); + } else { + myobj.setEnabled(true); + } + fr += 2; + itAdvanced = true; + } + + if (fr[0].matchWord("selectedTechnique")) { + if (fr[1].matchWord("AUTO_DETECT")) { + myobj.selectTechnique(osgFX::Effect::AUTO_DETECT); + fr += 2; + itAdvanced = true; + } else { + int i; + if (fr[1].getInt(i)) { + myobj.selectTechnique(i); + fr += 2; + itAdvanced = true; + } + } + } + + osg::ref_ptr node = static_cast(fr.readObjectOfType(osgDB::type_wrapper())); + if (node.valid()) { + myobj.setChild(node.get()); + } + + return itAdvanced; +} + +bool Effect_writeLocalData(const osg::Object &obj, osgDB::Output &fw) +{ + const osgFX::Effect &myobj = static_cast(obj); + + fw.indent() << "enabled " << (myobj.getEnabled() ? "TRUE" : "FALSE") << "\n"; + fw.indent() << "selectedTechnique "; + if (myobj.getSelectedTechnique() == osgFX::Effect::AUTO_DETECT) { + fw << "AUTO_DETECT\n"; + } else { + fw << myobj.getSelectedTechnique() << "\n"; + } + fw.writeObject(*myobj.getChild()); + + return true; +} diff --git a/src/osgPlugins/osgFX/IO_Scribe.cpp b/src/osgPlugins/osgFX/IO_Scribe.cpp new file mode 100644 index 000000000..d17541d0f --- /dev/null +++ b/src/osgPlugins/osgFX/IO_Scribe.cpp @@ -0,0 +1,54 @@ +#include + +#include +#include +#include + +bool Scribe_readLocalData(osg::Object &obj, osgDB::Input &fr); +bool Scribe_writeLocalData(const osg::Object &obj, osgDB::Output &fw); + +osgDB::RegisterDotOsgWrapperProxy Scribe_Proxy +( + new osgFX::Scribe, + "osgFX::Scribe", + "Object Node osgFX::Effect osgFX::Scribe", + Scribe_readLocalData, + Scribe_writeLocalData +); + +bool Scribe_readLocalData(osg::Object &obj, osgDB::Input &fr) +{ + osgFX::Scribe &myobj = static_cast(obj); + bool itAdvanced = false; + + if (fr[0].matchWord("wireframeColor")) { + osg::Vec4 w; + if (fr[1].getFloat(w.x()) && fr[2].getFloat(w.y()) && + fr[3].getFloat(w.z()) && fr[4].getFloat(w.w())) { + myobj.setWireframeColor(w); + fr += 5; + itAdvanced = true; + } + } + + if (fr[0].matchWord("wireframeLineWidth")) { + float f; + if (fr[1].getFloat(f)) { + myobj.setWireframeLineWidth(f); + fr += 2; + itAdvanced = true; + } + } + + return itAdvanced; +} + +bool Scribe_writeLocalData(const osg::Object &obj, osgDB::Output &fw) +{ + const osgFX::Scribe &myobj = static_cast(obj); + + fw.indent() << "wireframeColor " << myobj.getWireframeColor() << "\n"; + fw.indent() << "wireframeLineWidth " << myobj.getWireframeLineWidth() << "\n"; + + return true; +} diff --git a/src/osgPlugins/osgFX/IO_SpecularHighlights.cpp b/src/osgPlugins/osgFX/IO_SpecularHighlights.cpp new file mode 100644 index 000000000..d51b4b1f5 --- /dev/null +++ b/src/osgPlugins/osgFX/IO_SpecularHighlights.cpp @@ -0,0 +1,75 @@ +#include + +#include +#include +#include + +bool SpecularHighlights_readLocalData(osg::Object &obj, osgDB::Input &fr); +bool SpecularHighlights_writeLocalData(const osg::Object &obj, osgDB::Output &fw); + +osgDB::RegisterDotOsgWrapperProxy SpecularHighlights_Proxy +( + new osgFX::SpecularHighlights, + "osgFX::SpecularHighlights", + "Object Node osgFX::Effect osgFX::SpecularHighlights", + SpecularHighlights_readLocalData, + SpecularHighlights_writeLocalData +); + +bool SpecularHighlights_readLocalData(osg::Object &obj, osgDB::Input &fr) +{ + osgFX::SpecularHighlights &myobj = static_cast(obj); + bool itAdvanced = false; + + if (fr[0].matchWord("lightNumber")) { + int n; + if (fr[1].getInt(n)) { + myobj.setLightNumber(n); + fr += 2; + itAdvanced = true; + } + } + + if (fr[0].matchWord("textureUnit")) { + int n; + if (fr[1].getInt(n)) { + myobj.setTextureUnit(n); + fr += 2; + itAdvanced = true; + } + } + + if (fr[0].matchWord("specularColor")) { + osg::Vec4 w; + if (fr[1].getFloat(w.x()) && fr[2].getFloat(w.y()) && + fr[3].getFloat(w.z()) && fr[4].getFloat(w.w())) { + myobj.setSpecularColor(w); + fr += 5; + itAdvanced = true; + } + } + + if (fr[0].matchWord("specularExponent")) { + float f; + if (fr[1].getFloat(f)) { + myobj.setSpecularExponent(f); + fr += 2; + itAdvanced = true; + } + } + + + return itAdvanced; +} + +bool SpecularHighlights_writeLocalData(const osg::Object &obj, osgDB::Output &fw) +{ + const osgFX::SpecularHighlights &myobj = static_cast(obj); + + fw.indent() << "lightNumber " << myobj.getLightNumber() << "\n"; + fw.indent() << "textureUnit " << myobj.getTextureUnit() << "\n"; + fw.indent() << "specularColor " << myobj.getSpecularColor() << "\n"; + fw.indent() << "specularExponent " << myobj.getSpecularExponent() << "\n"; + + return true; +}