/* -*-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. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ #ifndef OSGEARTH_LIGHTING_H #define OSGEARTH_LIGHTING_H 1 #include #include #include #include #include #include #include #include // Use this with StateSet::setDefine to toggle lighting in osgEarth lighting shaders. #define OE_LIGHTING_DEFINE "OE_LIGHTING" namespace osgEarth { struct OSGEARTH_EXPORT Lighting { //! Sets the lighting mode on a stateset static void set(osg::StateSet* stateSet, osg::StateAttribute::OverrideValue value); //! Removed the lighting mode from a stateset static void remove(osg::StateSet* stateSet); //! Installs a default material on a stateset static void installDefaultMaterial(osg::StateSet* stateSet); }; /** * Traverses a graph, looking for Lights and Materials, and generates either static * uniforms or dynamic cull callbacks for them so they will work with core profile * shaders. (This is necessary for GL3+ core, OSX, Mesa etc. that don't support * compatibility mode.) */ class OSGEARTH_EXPORT GenerateGL3LightingUniforms : public osg::NodeVisitor { public: GenerateGL3LightingUniforms(); public: // osg::NodeVisitor virtual void apply(osg::Node& node); virtual void apply(osg::LightSource& node); protected: std::set _statesets; template bool alreadyInstalled(osg::Callback* cb) const { return !cb ? false : dynamic_cast(cb)!=0L ? true : alreadyInstalled(cb->getNestedCallback()); } }; /** * Material that will work in both FFP and non-FFP mode, by using the uniform * osg_FrontMaterial in place of gl_FrontMaterial. */ class OSGEARTH_EXPORT MaterialGL3 : public osg::Material { public: MaterialGL3() : osg::Material() { } MaterialGL3(const MaterialGL3& mat, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) : osg::Material(mat, copyop) {} MaterialGL3(const osg::Material& mat) : osg::Material(mat) { } META_StateAttribute(osgEarth, MaterialGL3, MATERIAL); void apply(osg::State&) const override; }; /** * StateAttributeCallback that will update osg::Material properties as Uniforms */ class OSGEARTH_EXPORT MaterialCallback : public osg::StateAttributeCallback { public: virtual void operator() (osg::StateAttribute* attr, osg::NodeVisitor* nv); }; /** * Light that will work in both FFP and non-FFP mode. * To use this, find a LightSource and replace the Light with a LightGL3. * Then install the LightSourceGL3UniformGenerator cull callback on the LightSource. */ class OSGEARTH_EXPORT LightGL3 : public osg::Light { public: LightGL3() : osg::Light(), _enabled(true) { } LightGL3(int lightnum) : osg::Light(lightnum), _enabled(true) { } LightGL3(const LightGL3& light, const osg::CopyOp& copyop =osg::CopyOp::SHALLOW_COPY) : osg::Light(light, copyop), _enabled(light._enabled) {} LightGL3(const osg::Light& light) : osg::Light(light), _enabled(true) { } void setEnabled(bool value) { _enabled = value; } bool getEnabled() const { return _enabled; } virtual osg::Object* cloneType() const { return new LightGL3(_lightnum); } virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new LightGL3(*this,copyop); } virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osgEarth"; } virtual const char* className() const { return "LightGL3"; } virtual Type getType() const { return LIGHT; } virtual void apply(osg::State&) const; protected: bool _enabled; }; /** * Cull callback that will install Light uniforms based on the Light in a LightSource. * Install this directly on the LightSource node. */ class OSGEARTH_EXPORT LightSourceGL3UniformGenerator : public osg::NodeCallback { public: LightSourceGL3UniformGenerator(); /** * Creates and installs Uniforms on the stateset for the Light components * of the Light that are non-positional (everything but the position and direction) */ void generateNonPositionalData(osg::StateSet* ss, osg::Light* light); public: // osg::NodeCallback bool run(osg::Object* obj, osg::Object* data); public: // osg::Object void resizeGLBufferObjects(unsigned maxSize); void releaseGLObjects(osg::State* state) const; mutable std::vector > _statesets; mutable std::mutex _statesetsMutex; }; } #endif // OSGEARTH_LIGHTING_H