diff --git a/src/osgEarthDrivers/bumpmap/BumpMap.frag.progressive.glsl b/src/osgEarthDrivers/bumpmap/BumpMap.frag.progressive.glsl index ed24b731b7..f17a5af301 100644 --- a/src/osgEarthDrivers/bumpmap/BumpMap.frag.progressive.glsl +++ b/src/osgEarthDrivers/bumpmap/BumpMap.frag.progressive.glsl @@ -34,37 +34,40 @@ in float oe_bumpmap_range; // Entry point for progressive blended bump maps void oe_bumpmap_fragment(inout vec4 color) { - // sample the bump map - const float amplitudeDecay = 1.0; // no decay. - float maxLOD = float(oe_bumpmap_octaves)+1.0; - - // starter vector: - vec3 bump = vec3(0.0); - float scale = 1.0; - float amplitude = 1.0; - float limit = oe_bumpmap_range; - float range = oe_bumpmap_maxRange; - float lastRange = oe_bumpmap_maxRange; - for(float lod = 1.0; lod < maxLOD; lod += 1.0, scale *= 2.0, amplitude *= amplitudeDecay) + if (oe_bumpmap_octaves > 0) { - float fadeIn = 1.0; - if ( range <= limit && limit < oe_bumpmap_maxRange ) - fadeIn = clamp((lastRange-limit)/(lastRange-range), 0.0, 1.0); - bump += (texture(oe_bumpmap_tex, oe_bumpmap_coords*scale).xyz*2.0-1.0)*amplitude*fadeIn; - if ( range <= limit ) - break; - lastRange = range; - range = oe_bumpmap_maxRange/exp(lod); - } + // sample the bump map + const float amplitudeDecay = 1.0; // no decay. + float maxLOD = float(oe_bumpmap_octaves) + 1.0; + + // starter vector: + vec3 bump = vec3(0.0); + float scale = 1.0; + float amplitude = 1.0; + float limit = oe_bumpmap_range; + float range = oe_bumpmap_maxRange; + float lastRange = oe_bumpmap_maxRange; + for (float lod = 1.0; lod < maxLOD; lod += 1.0, scale *= 2.0, amplitude *= amplitudeDecay) + { + float fadeIn = 1.0; + if (range <= limit && limit < oe_bumpmap_maxRange) + fadeIn = clamp((lastRange - limit) / (lastRange - range), 0.0, 1.0); + bump += (texture(oe_bumpmap_tex, oe_bumpmap_coords * scale).xyz * 2.0 - 1.0) * amplitude * fadeIn; + if (range <= limit) + break; + lastRange = range; + range = oe_bumpmap_maxRange / exp(lod); + } - // finally, transform into view space and normalize the vector. - bump = normalize(oe_bumpmap_normalMatrix*bump); - - // calculate slope from normal: - float slope = mix(1.0, 1.0 - dot(oe_UpVectorView, vp_Normal), oe_bumpmap_slopeFactor); + // finally, transform into view space and normalize the vector. + bump = normalize(oe_bumpmap_normalMatrix * bump); - // permute the normal with the bump. - vp_Normal = normalize(vp_Normal + bump*oe_bumpmap_intensity*slope); + // calculate slope from normal: + float slope = mix(1.0, 1.0 - dot(oe_UpVectorView, vp_Normal), oe_bumpmap_slopeFactor); + + // permute the normal with the bump. + vp_Normal = normalize(vp_Normal + bump * oe_bumpmap_intensity * slope); + } } #endif \ No newline at end of file diff --git a/src/osgEarthDrivers/bumpmap/BumpMap.frag.simple.glsl b/src/osgEarthDrivers/bumpmap/BumpMap.frag.simple.glsl index 07fd3b4e6f..e410710069 100644 --- a/src/osgEarthDrivers/bumpmap/BumpMap.frag.simple.glsl +++ b/src/osgEarthDrivers/bumpmap/BumpMap.frag.simple.glsl @@ -20,20 +20,24 @@ flat in mat3 oe_bumpmap_normalMatrix; in vec3 oe_UpVectorView; uniform sampler2D oe_bumpmap_tex; -uniform float oe_bumpmap_intensity; -uniform float oe_bumpmap_slopeFactor; +uniform float oe_bumpmap_intensity; +uniform float oe_bumpmap_slopeFactor; +uniform int oe_bumpmap_octaves; void oe_bumpmap_fragment(inout vec4 color) { - // sample the bump map - vec3 bump = oe_bumpmap_normalMatrix * normalize(texture(oe_bumpmap_tex, oe_bumpmap_coords).xyz*2.0-1.0); - - // calculate slope from normal: - float slope = clamp( (1.0-dot(oe_UpVectorView, vp_Normal))*oe_bumpmap_slopeFactor, 0.0, 1.0); - - // permute the normal with the bump. - vp_Normal = normalize(vp_Normal + bump*oe_bumpmap_intensity*slope); + if (oe_bumpmap_octaves > 0) + { + // sample the bump map + vec3 bump = oe_bumpmap_normalMatrix * normalize(texture(oe_bumpmap_tex, oe_bumpmap_coords).xyz * 2.0 - 1.0); + + // calculate slope from normal: + float slope = clamp((1.0 - dot(oe_UpVectorView, vp_Normal)) * oe_bumpmap_slopeFactor, 0.0, 1.0); + + // permute the normal with the bump. + vp_Normal = normalize(vp_Normal + bump * oe_bumpmap_intensity * slope); + } } #endif \ No newline at end of file diff --git a/src/osgEarthDrivers/bumpmap/BumpMapExtension b/src/osgEarthDrivers/bumpmap/BumpMapExtension deleted file mode 100644 index 3a8b423427..0000000000 --- a/src/osgEarthDrivers/bumpmap/BumpMapExtension +++ /dev/null @@ -1,70 +0,0 @@ -/* -*-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 - */ -#ifndef OSGEARTH_BUMPMAP_EXTENSION -#define OSGEARTH_BUMPMAP_EXTENSION 1 - -#include "BumpMapOptions" -#include "BumpMapTerrainEffect" -#include -#include - -namespace osgEarth { namespace BumpMap -{ - using namespace osgEarth; - - /** - * Extension for loading the normal mapping effect on demand. - */ - class BumpMapExtension : - public Extension, - public BumpMapOptions, - public ExtensionInterface - { - public: - META_OE_Extension(osgEarth, BumpMapExtension, bumpmap); - - // CTORs - BumpMapExtension(); - BumpMapExtension(const BumpMapOptions& options); - - // DTOR - virtual ~BumpMapExtension(); - - - public: // Extension - - void setDBOptions(const osgDB::Options* dbOptions) override; - - const ConfigOptions& getConfigOptions() const override { return *this; } - - - public: // ExtensionInterface - - bool connect(MapNode* mapNode) override; - - bool disconnect(MapNode* mapNode) override; - - private: - osg::ref_ptr _dbOptions; - osg::ref_ptr _effect; - }; - -} } // namespace osgEarth::BumpMap - -#endif // OSGEARTH_BUMPMAP_EXTENSION diff --git a/src/osgEarthDrivers/bumpmap/BumpMapExtension.cpp b/src/osgEarthDrivers/bumpmap/BumpMapExtension.cpp deleted file mode 100644 index 8830899986..0000000000 --- a/src/osgEarthDrivers/bumpmap/BumpMapExtension.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* -*-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 - */ -#include "BumpMapExtension" -#include "BumpMapTerrainEffect" - -#include -#include - -using namespace osgEarth; -using namespace osgEarth::BumpMap; - -#define LC "[BumpMapExtension] " - - -REGISTER_OSGEARTH_EXTENSION(osgearth_bumpmap, BumpMapExtension); -REGISTER_OSGEARTH_EXTENSION(osgearth_bump_map, BumpMapExtension); - - -BumpMapExtension::BumpMapExtension() -{ - //nop -} - -BumpMapExtension::BumpMapExtension(const BumpMapOptions& options) : -BumpMapOptions( options ) -{ - //nop -} - -BumpMapExtension::~BumpMapExtension() -{ - //nop -} - -void -BumpMapExtension::setDBOptions(const osgDB::Options* dbOptions) -{ - _dbOptions = dbOptions; -} - -bool -BumpMapExtension::connect(MapNode* mapNode) -{ - if ( !mapNode ) - { - OE_WARN << LC << "Illegal: MapNode cannot be null." << std::endl; - return false; - } - - osg::ref_ptr image = imageURI()->getImage( _dbOptions.get() ); - if ( !image.valid() ) - { - OE_WARN << LC << "Failed; unable to load normal map image from " - << imageURI()->full() << "\n"; - return false; - } - - _effect = new BumpMapTerrainEffect( _dbOptions.get() ); - _effect->setBumpMapImage( image.get() ); - - if (intensity().isSet()) - _effect->getIntensityUniform()->set( intensity().get() ); - - if (scale().isSet()) - _effect->getScaleUniform()->set( scale().get() ); - - if ( octaves().isSet() ) - _effect->setOctaves( octaves().get() ); - - if ( baseLOD().isSet() ) - _effect->setBaseLOD( baseLOD().get() ); - - mapNode->getTerrainEngine()->addEffect( _effect.get() ); - - OE_INFO << LC << "Installed.\n"; - - return true; -} - -bool -BumpMapExtension::disconnect(MapNode* mapNode) -{ - if ( mapNode ) - { - mapNode->getTerrainEngine()->removeEffect( _effect.get() ); - } - _effect = 0L; - return true; -} - diff --git a/src/osgEarthDrivers/bumpmap/BumpMapLayer b/src/osgEarthDrivers/bumpmap/BumpMapLayer new file mode 100644 index 0000000000..220346d93d --- /dev/null +++ b/src/osgEarthDrivers/bumpmap/BumpMapLayer @@ -0,0 +1,41 @@ +/* -*-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 + */ +#pragma once + +#include "BumpMapOptions" +#include "BumpMapTerrainEffect" +#include + +namespace osgEarth +{ + class TerrainEngine; + + /** + * Layer that installs a bumpmapping terrain effect. + */ + class BumpMapLayer : public VisibleLayer + { + public: + META_Layer(osgEarth, BumpMapLayer, BumpMapOptions, VisibleLayer, bumpmap); + + void prepareForRendering(TerrainEngine* engine) override; + + osg::ref_ptr _effect; + }; +} diff --git a/src/osgEarthDrivers/bumpmap/BumpMapLayer.cpp b/src/osgEarthDrivers/bumpmap/BumpMapLayer.cpp new file mode 100644 index 0000000000..d2be9ab052 --- /dev/null +++ b/src/osgEarthDrivers/bumpmap/BumpMapLayer.cpp @@ -0,0 +1,69 @@ +/* -*-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 + */ +#include "BumpMapLayer" +#include "BumpMapTerrainEffect" + +#include + +using namespace osgEarth; + +#define LC "[BumpMapLayer] " + +REGISTER_OSGEARTH_LAYER(bumpmap, BumpMapLayer); + + +void +BumpMapLayer::prepareForRendering(TerrainEngine* engine) +{ + if ( !engine ) + return; + + osg::ref_ptr image = options().imageURI()->getImage(getReadOptions()); + if ( !image.valid() ) + { + OE_WARN << LC << "Failed; unable to load normal map image from " + << options().imageURI()->full() << "\n"; + return; + } + + _effect = new BumpMapTerrainEffect(); + + _effect->setBumpMapImage(image.get()); + + if (options().intensity().isSet()) + _effect->getIntensityUniform()->set(options().intensity().get()); + + if (options().scale().isSet()) + _effect->getScaleUniform()->set(options().scale().get()); + + if (options().octaves().isSet()) + _effect->setOctaves(options().octaves().get()); + + if (options().baseLOD().isSet()) + _effect->setBaseLOD(options().baseLOD().get()); + + engine->addEffect(_effect); + + OE_DEBUG << LC << "Installed.\n"; + + onVisibleChanged([&](auto* layer) + { + _effect->setActive(layer->getVisible()); + }); +} diff --git a/src/osgEarthDrivers/bumpmap/BumpMapOptions b/src/osgEarthDrivers/bumpmap/BumpMapOptions index 315202661f..d3db65a62e 100644 --- a/src/osgEarthDrivers/bumpmap/BumpMapOptions +++ b/src/osgEarthDrivers/bumpmap/BumpMapOptions @@ -16,13 +16,13 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ -#ifndef OSGEARTH_DRIVER_BUMPMAP_OPTIONS -#define OSGEARTH_DRIVER_BUMPMAP_OPTIONS 1 +#pragma once #include #include +#include -namespace osgEarth { namespace BumpMap +namespace osgEarth { using namespace osgEarth; @@ -31,50 +31,24 @@ namespace osgEarth { namespace BumpMap * A Bump Map is a repeating normal texture that modifies the * existing normal vector per fragment. */ - class BumpMapOptions : public ConfigOptions // NO EXPORT; header only + class BumpMapOptions : public VisibleLayer::Options { - public: - // bump map texture to load. - optional& imageURI() { return _imageURI; } - const optional& imageURI() const { return _imageURI; } - - // Intensity of normal map effect. - optional& intensity() { return _intensity; } - const optional& intensity() const { return _intensity; } - - // Scale factor for the normal map texture. - optional& scale() { return _scale; } - const optional& scale() const { return _scale; } - - /** Number of times to proressively scale and multisample the bump map - based on camera range. Default is 1. */ - optional& octaves() { return _octaves; } - const optional& octaves() const { return _octaves; } - - /** Camera range at which to render one octave (outer range). */ - optional& maxRange() { return _maxRange; } - const optional& maxRange() const { return _maxRange; } - - /** LOD at which the bumpmap renders at a scale of 1.0. */ - optional& baseLOD() { return _baseLOD; } - const optional& baseLOD() const { return _baseLOD; } + META_LayerOptions(osgEarth, BumpMapOptions, VisibleLayer::Options); public: - BumpMapOptions( const ConfigOptions& opt =ConfigOptions() ) : ConfigOptions( opt ) - { - // Defaults. - _intensity.init( 1.0f ); - _scale.init ( 1.0f ); - _octaves.init ( 1 ); - _maxRange.init (25000.0f); - _baseLOD.init ( 13u ); - - fromConfig( _conf ); - } + //! bump map texture to load. + OE_OPTION(URI, imageURI); + //! Intensity of normal map effect. + OE_OPTION(float, intensity, 1.0f); + //! Scale factor for the normal map texture. + OE_OPTION(float, scale, 1.0f); + //! Number of times to proressively scale and multisample the bump map based on camera range. Default is 1. + OE_OPTION(int, octaves, 1); + //! Camera range at which to render one octave (outer range). + OE_OPTION(float, maxRange, 25000.0f); + //! LOD at which the bumpmap renders at a scale of 1.0. + OE_OPTION(unsigned, baseLOD, 13u); - virtual ~BumpMapOptions() { } - - public: Config getConfig() const { Config conf = ConfigOptions::getConfig(); conf.set("image", _imageURI); @@ -86,13 +60,6 @@ namespace osgEarth { namespace BumpMap return conf; } - protected: - void mergeConfig( const Config& conf ) { - ConfigOptions::mergeConfig( conf ); - fromConfig( conf ); - } - - private: void fromConfig( const Config& conf ) { conf.get("image", _imageURI); conf.get("intensity", _intensity); @@ -101,16 +68,5 @@ namespace osgEarth { namespace BumpMap conf.get("max_range", _maxRange); conf.get("base_lod", _baseLOD); } - - optional _imageURI; - optional _intensity; - optional _scale; - optional _octaves; - optional _maxRange; - optional _baseLOD; }; - -} } // namespace osgEarth::BumpMap - -#endif // OSGEARTH_DRIVER_BUMPMAP_OPTIONS - +} // namespace osgEarth diff --git a/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect index 12940781db..8e2b3a0d77 100644 --- a/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect +++ b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect @@ -19,8 +19,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see */ -#ifndef OSGEARTH_BumpMap_TERRAIN_EFFECT_H -#define OSGEARTH_BumpMap_TERRAIN_EFFECT_H +#pragma once #include #include @@ -30,7 +29,7 @@ using namespace osgEarth; -namespace osgEarth { namespace BumpMap +namespace osgEarth { /** * Effect that applies bump mapping to the terrain. @@ -39,7 +38,9 @@ namespace osgEarth { namespace BumpMap { public: /** construct a new terrain effect. */ - BumpMapTerrainEffect(const osgDB::Options* dbOptions); + BumpMapTerrainEffect(); + + void setActive(bool); /** Sets the image containing the normal offsets. */ void setBumpMapImage(osg::Image* image); @@ -62,25 +63,23 @@ namespace osgEarth { namespace BumpMap public: // TerrainEffect interface - void onInstall(TerrainEngineNode* engine); + void onInstall(TerrainEngineNode* engine) override; - void onUninstall(TerrainEngineNode* engine); + void onUninstall(TerrainEngineNode* engine) override; protected: virtual ~BumpMapTerrainEffect(); - bool _ok; - int _bumpMapUnit; - int _octaves; - float _maxRange; - unsigned _baseLOD; + bool _ok = true; + int _bumpMapUnit = -1; + int _octaves = 1; + float _maxRange = 25000.0f; + unsigned _baseLOD = 13u; osg::ref_ptr _bumpMapTex; - osg::ref_ptr _bumpMapTexUniform; - osg::ref_ptr _scaleUniform; - osg::ref_ptr _intensityUniform; + osg::ref_ptr _bumpMapTexUniform; + osg::ref_ptr _scaleUniform; + osg::ref_ptr _intensityUniform; + osg::ref_ptr _octavesUniform; }; - -} } // namespace osgEarth::BumpMap - -#endif // OSGEARTH_BumpMap_TERRAIN_EFFECT_H +} \ No newline at end of file diff --git a/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect.cpp b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect.cpp index a91071983a..43361efa7e 100644 --- a/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect.cpp +++ b/src/osgEarthDrivers/bumpmap/BumpMapTerrainEffect.cpp @@ -37,17 +37,16 @@ using namespace osgEarth; using namespace osgEarth::BumpMap; -BumpMapTerrainEffect::BumpMapTerrainEffect(const osgDB::Options* dbOptions) : -_ok(true), -_bumpMapUnit(-1) +BumpMapTerrainEffect::BumpMapTerrainEffect() { BumpMapOptions defaults; _octaves = defaults.octaves().get(); _maxRange = defaults.maxRange().get(); _baseLOD = defaults.baseLOD().get(); - _scaleUniform = new osg::Uniform("oe_bumpmap_scale", defaults.scale().get()); + _scaleUniform = new osg::Uniform("oe_bumpmap_scale", defaults.scale().get()); _intensityUniform = new osg::Uniform("oe_bumpmap_intensity", defaults.intensity().get()); + _octavesUniform = new osg::Uniform("oe_bumpmap_octaves", defaults.octaves().get()); } BumpMapTerrainEffect::~BumpMapTerrainEffect() @@ -104,8 +103,8 @@ BumpMapTerrainEffect::onInstall(TerrainEngineNode* engine) package.load( vp, package.VertexView ); package.load( vp, _octaves <= 1? package.FragmentSimple : package.FragmentProgressive ); - if ( _octaves > 1 ) - stateset->addUniform(new osg::Uniform("oe_bumpmap_octaves", _octaves)); + stateset->addUniform(_octavesUniform); + _octavesUniform->set(_octaves); stateset->addUniform(new osg::Uniform("oe_bumpmap_maxRange", _maxRange)); stateset->addUniform(new osg::Uniform("oe_bumpmap_slopeFactor", 1.0f)); @@ -131,11 +130,11 @@ BumpMapTerrainEffect::onUninstall(TerrainEngineNode* engine) if ( _bumpMapTex.valid() ) { stateset->removeUniform("oe_bumpmap_maxRange"); - stateset->removeUniform("oe_bumpmap_octaves"); - stateset->removeUniform( _scaleUniform.get() ); - stateset->removeUniform( _intensityUniform.get() ); - stateset->removeUniform( _bumpMapTexUniform.get() ); - stateset->removeTextureAttribute( _bumpMapUnit, osg::StateAttribute::TEXTURE ); + stateset->removeUniform(_octavesUniform.get()); + stateset->removeUniform(_scaleUniform.get()); + stateset->removeUniform(_intensityUniform.get()); + stateset->removeUniform(_bumpMapTexUniform.get()); + stateset->removeTextureAttribute(_bumpMapUnit, osg::StateAttribute::TEXTURE); _bumpMapTex->releaseGLObjects(nullptr); } @@ -154,3 +153,12 @@ BumpMapTerrainEffect::onUninstall(TerrainEngineNode* engine) _bumpMapUnit = -1; } } + +void +BumpMapTerrainEffect::setActive(bool value) +{ + if (value) + _octavesUniform->set(_octaves); + else + _octavesUniform->set(0); +} diff --git a/src/osgEarthDrivers/bumpmap/CMakeLists.txt b/src/osgEarthDrivers/bumpmap/CMakeLists.txt index b9338daae7..9d778104be 100644 --- a/src/osgEarthDrivers/bumpmap/CMakeLists.txt +++ b/src/osgEarthDrivers/bumpmap/CMakeLists.txt @@ -15,15 +15,16 @@ configure_shaders( ${SHADERS_CPP} ${TARGET_GLSL} ) -add_osgearth_plugin(TARGET osgdb_osgearth_bumpmap +add_osgearth_plugin( + TARGET osgdb_osgearth_bumpmap PUBLIC_HEADERS - BumpMapExtension BumpMapOptions - BumpMapTerrainEffect HEADERS + BumpMapLayer BumpMapShaders + BumpMapTerrainEffect SOURCES - BumpMapExtension.cpp + BumpMapLayer.cpp BumpMapTerrainEffect.cpp ${SHADERS_CPP} TEMPLATES