| 1 | #include <osgFX/SpecularHighlights> |
|---|
| 2 | #include <osgFX/Registry> |
|---|
| 3 | |
|---|
| 4 | #include <osg/TextureCubeMap> |
|---|
| 5 | #include <osg/TexGen> |
|---|
| 6 | #include <osg/TexEnv> |
|---|
| 7 | #include <osg/ColorMatrix> |
|---|
| 8 | |
|---|
| 9 | #include <osgUtil/HighlightMapGenerator> |
|---|
| 10 | |
|---|
| 11 | using namespace osgFX; |
|---|
| 12 | |
|---|
| 13 | namespace |
|---|
| 14 | { |
|---|
| 15 | |
|---|
| 16 | class AutoTextureMatrix: public osg::StateAttribute { |
|---|
| 17 | public: |
|---|
| 18 | AutoTextureMatrix() |
|---|
| 19 | : osg::StateAttribute(), |
|---|
| 20 | _lightnum(0), |
|---|
| 21 | _active(false) |
|---|
| 22 | { |
|---|
| 23 | } |
|---|
| 24 | |
|---|
| 25 | AutoTextureMatrix(const AutoTextureMatrix& copy, const osg::CopyOp& copyop) |
|---|
| 26 | : osg::StateAttribute(copy, copyop), |
|---|
| 27 | _lightnum(copy._lightnum), |
|---|
| 28 | _active(copy._active) |
|---|
| 29 | { |
|---|
| 30 | } |
|---|
| 31 | |
|---|
| 32 | AutoTextureMatrix(int lightnum, bool active = true) |
|---|
| 33 | : osg::StateAttribute(), |
|---|
| 34 | _lightnum(lightnum), |
|---|
| 35 | _active(active) |
|---|
| 36 | { |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | META_StateAttribute(osgFX, AutoTextureMatrix, osg::StateAttribute::TEXMAT); |
|---|
| 40 | |
|---|
| 41 | virtual bool isTextureAttribute() const { return true; } |
|---|
| 42 | |
|---|
| 43 | int compare(const osg::StateAttribute &sa) const |
|---|
| 44 | { |
|---|
| 45 | COMPARE_StateAttribute_Types(AutoTextureMatrix, sa); |
|---|
| 46 | if (_lightnum < rhs._lightnum) return -1; |
|---|
| 47 | if (_lightnum > rhs._lightnum) return 1; |
|---|
| 48 | return 0; |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | void apply(osg::State& state) const |
|---|
| 52 | { |
|---|
| 53 | #ifdef OSG_GL_MATRICES_AVAILABLE |
|---|
| 54 | |
|---|
| 55 | glMatrixMode(GL_TEXTURE); |
|---|
| 56 | |
|---|
| 57 | if (_active) { |
|---|
| 58 | osg::Matrix M = state.getInitialViewMatrix(); |
|---|
| 59 | M(3, 0) = 0; M(3, 1) = 0; M(3, 2) = 0; |
|---|
| 60 | M(3, 3) = 1; M(0, 3) = 0; M(1, 3) = 0; |
|---|
| 61 | M(2, 3) = 0; |
|---|
| 62 | |
|---|
| 63 | osg::Vec4 lightvec; |
|---|
| 64 | glGetLightfv(GL_LIGHT0+_lightnum, GL_POSITION, lightvec._v); |
|---|
| 65 | |
|---|
| 66 | osg::Vec3 eye_light_ref = osg::Vec3(0, 0, 1) * M; |
|---|
| 67 | |
|---|
| 68 | osg::Matrix LM = osg::Matrix::rotate( |
|---|
| 69 | osg::Vec3(lightvec.x(), lightvec.y(), lightvec.z()), |
|---|
| 70 | eye_light_ref); |
|---|
| 71 | |
|---|
| 72 | glLoadMatrix((LM * osg::Matrix::inverse(M)).ptr()); |
|---|
| 73 | |
|---|
| 74 | } else { |
|---|
| 75 | glLoadIdentity(); |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | glMatrixMode(GL_MODELVIEW); |
|---|
| 79 | #else |
|---|
| 80 | OSG_NOTICE<<"Warning: osgFX::SpecualHighlights unable to set texture matrix."<<std::endl; |
|---|
| 81 | #endif |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | private: |
|---|
| 85 | int _lightnum; |
|---|
| 86 | bool _active; |
|---|
| 87 | }; |
|---|
| 88 | |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | namespace |
|---|
| 92 | { |
|---|
| 93 | |
|---|
| 94 | Registry::Proxy proxy(new SpecularHighlights); |
|---|
| 95 | |
|---|
| 96 | class DefaultTechnique: public Technique { |
|---|
| 97 | public: |
|---|
| 98 | |
|---|
| 99 | DefaultTechnique(int lightnum, int unit, const osg::Vec4& color, float sexp) |
|---|
| 100 | : Technique(), |
|---|
| 101 | _lightnum(lightnum), |
|---|
| 102 | _unit(unit), |
|---|
| 103 | _color(color), |
|---|
| 104 | _sexp(sexp) |
|---|
| 105 | { |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | virtual void getRequiredExtensions(std::vector<std::string>& extensions) |
|---|
| 109 | { |
|---|
| 110 | extensions.push_back("GL_ARB_texture_env_add"); |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | bool validate(osg::State& state) const |
|---|
| 114 | { |
|---|
| 115 | if (!Technique::validate(state)) return false; |
|---|
| 116 | |
|---|
| 117 | osg::TextureCubeMap::Extensions *ext = |
|---|
| 118 | osg::TextureCubeMap::getExtensions(state.getContextID(), true); |
|---|
| 119 | if (ext) { |
|---|
| 120 | return ext->isCubeMapSupported(); |
|---|
| 121 | } |
|---|
| 122 | return false; |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | protected: |
|---|
| 126 | |
|---|
| 127 | void define_passes() |
|---|
| 128 | { |
|---|
| 129 | osg::ref_ptr<osg::StateSet> ss = new osg::StateSet; |
|---|
| 130 | |
|---|
| 131 | ss->setTextureAttributeAndModes(_unit, new AutoTextureMatrix(_lightnum), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); |
|---|
| 132 | |
|---|
| 133 | osg::ref_ptr<osgUtil::HighlightMapGenerator> hmg = new osgUtil::HighlightMapGenerator(osg::Vec3(0, 0, -1), _color, _sexp); |
|---|
| 134 | hmg->generateMap(false); |
|---|
| 135 | |
|---|
| 136 | osg::ref_ptr<osg::TextureCubeMap> texture = new osg::TextureCubeMap; |
|---|
| 137 | texture->setImage(osg::TextureCubeMap::POSITIVE_X, hmg->getImage(osg::TextureCubeMap::POSITIVE_X)); |
|---|
| 138 | texture->setImage(osg::TextureCubeMap::POSITIVE_Y, hmg->getImage(osg::TextureCubeMap::POSITIVE_Y)); |
|---|
| 139 | texture->setImage(osg::TextureCubeMap::POSITIVE_Z, hmg->getImage(osg::TextureCubeMap::POSITIVE_Z)); |
|---|
| 140 | texture->setImage(osg::TextureCubeMap::NEGATIVE_X, hmg->getImage(osg::TextureCubeMap::NEGATIVE_X)); |
|---|
| 141 | texture->setImage(osg::TextureCubeMap::NEGATIVE_Y, hmg->getImage(osg::TextureCubeMap::NEGATIVE_Y)); |
|---|
| 142 | texture->setImage(osg::TextureCubeMap::NEGATIVE_Z, hmg->getImage(osg::TextureCubeMap::NEGATIVE_Z)); |
|---|
| 143 | texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); |
|---|
| 144 | texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); |
|---|
| 145 | texture->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); |
|---|
| 146 | ss->setTextureAttributeAndModes(_unit, texture.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); |
|---|
| 147 | |
|---|
| 148 | osg::ref_ptr<osg::TexGen> texgen = new osg::TexGen; |
|---|
| 149 | texgen->setMode(osg::TexGen::REFLECTION_MAP); |
|---|
| 150 | ss->setTextureAttributeAndModes(_unit, texgen.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); |
|---|
| 151 | |
|---|
| 152 | osg::ref_ptr<osg::TexEnv> texenv = new osg::TexEnv; |
|---|
| 153 | texenv->setMode(osg::TexEnv::ADD); |
|---|
| 154 | ss->setTextureAttributeAndModes(_unit, texenv.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); |
|---|
| 155 | |
|---|
| 156 | addPass(ss.get()); |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | private: |
|---|
| 160 | int _lightnum; |
|---|
| 161 | int _unit; |
|---|
| 162 | osg::Vec4 _color; |
|---|
| 163 | float _sexp; |
|---|
| 164 | }; |
|---|
| 165 | |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | |
|---|
| 169 | SpecularHighlights::SpecularHighlights() |
|---|
| 170 | : Effect(), |
|---|
| 171 | _lightnum(0), |
|---|
| 172 | _unit(0), |
|---|
| 173 | _color(1, 1, 1, 1), |
|---|
| 174 | _sexp(16) |
|---|
| 175 | { |
|---|
| 176 | } |
|---|
| 177 | |
|---|
| 178 | SpecularHighlights::SpecularHighlights(const SpecularHighlights& copy, const osg::CopyOp& copyop) |
|---|
| 179 | : Effect(copy, copyop), |
|---|
| 180 | _lightnum(copy._lightnum), |
|---|
| 181 | _unit(copy._unit), |
|---|
| 182 | _color(copy._color), |
|---|
| 183 | _sexp(copy._sexp) |
|---|
| 184 | { |
|---|
| 185 | } |
|---|
| 186 | |
|---|
| 187 | bool SpecularHighlights::define_techniques() |
|---|
| 188 | { |
|---|
| 189 | addTechnique(new DefaultTechnique(_lightnum, _unit, _color, _sexp)); |
|---|
| 190 | return true; |
|---|
| 191 | } |
|---|