/* * * Copyright (C) 2004, 2005, 2006 Mekensleep * * Mekensleep * 24 rue vieille du temple * 75004 Paris * licensing@mekensleep.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Authors: * Igor Kravtchenko * Loic Dachary * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef USE_NPROFILE #include #else // USE_NPROFILE #define NPROFILE_SAMPLE(a) #endif // USE_NPROFILE #ifdef WIN32 #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #define SET_VIEWPORT_FROM_TEXTURE_SIZE(a) vp_w = (a)->getTextureWidth(); vp_h = (a)->getTextureHeight(); \ if (!vp_w) { vp_w = (a)->getImage()->s(); vp_h = (a)->getImage()->t(); } #define START_INDEX_RBIN -500000 #define RENDERBIN_NAME "RenderBin" namespace osgCal { static bool g_bInit = false; static osg::ref_ptr g_tmpTexture[3]; static int g_iRBin = START_INDEX_RBIN; static int g_alphapreca[256]; static std::vector< osg::ref_ptr > g_filterTexture; TextureLayersFlatten::TextureLayersFlatten() { if (!g_bInit) { g_bInit = true; for (int i = 0; i < 3; i++) { osg::Texture2D *tex = new osg::Texture2D(); g_tmpTexture[i] = tex; tex->setInternalFormat(GL_RGB); tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); tex->setTextureSize(512, 512); } } for (int i = 0; i < 256; i++) g_alphapreca[i] = int((255.0f / i) * 255.0f); // g_state = new osg::State(); } void TextureLayersFlatten::destroy() { if (g_bInit) { for (int i = 0; i < 3; i++) g_tmpTexture[i] = NULL; g_filterTexture.clear(); g_bInit = false; } } TextureLayersFlatten::~TextureLayersFlatten() { int nbTechnics = technics_.size(); for (int i = 0; i < nbTechnics; i++) { BaseRenderTechnic *technic = technics_[i]; delete technic; } /* int nbFilterTextures = g_filterTexture.size(); for (int i = 0; i < nbFilterTextures; i++) { osg::Texture2D *tex = g_filterTexture[i].get(); if (tex == maskOn_.get() || tex == outputTexture_.get() ) { g_filterTexture.erase( g_filterTexture.begin() + i); break; } } */ if (modelview_abs_.valid() && modelview_abs_->getNumParents() > 0) modelview_abs_->getParent(0)->removeChild(modelview_abs_.get()); if (projection_.valid() && projection_->getNumParents() > 0) projection_->getParent(0)->removeChild(projection_.get()); modelview_abs_ = NULL; projection_ = NULL; outputTexture_ = NULL; colorMask_ = NULL; maskOn_ = NULL; } void TextureLayersFlatten::resetBinCounter() { g_iRBin = START_INDEX_RBIN; } //static int iii = 0; void TextureLayersFlatten::init(int _width, int _height, std::vector &_layers, osg::Group *_on, osg::Texture2D *_myOutputTexture, osg::Texture2D *_colorMask, osg::Texture2D *_maskOn, osg::Texture2D *_alphaPart, bool _bUseOldLayersParams) { int i; _on->setCullingActive(false); if (_layers.size() == 0) return; if (!_myOutputTexture) { outputTexture_ = new osg::Texture2D(); outputTexture_->setInternalFormat(GL_RGB); outputTexture_->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); outputTexture_->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); } else { outputTexture_ = _myOutputTexture; } std::map tex2Opacity; std::map tex2Color; int nbOldTechnics = technics_.size(); for (i = 0; i < nbOldTechnics; i++) { BaseRenderTechnic *technic = technics_[i]; osg::Texture2D *tex; if (i == 0) tex = technic->textureA_.get(); else tex = technic->textureB_.get(); if (_bUseOldLayersParams) { float oldOpa = technic->getOpacity(); tex2Opacity[tex] = oldOpa; osg::Vec3f oldColorFactor = technic->getColorFactor(); tex2Color[tex] = oldColorFactor; } delete technic; } technics_.clear(); if (modelview_abs_.valid()) { modelview_abs_->removeChild(projection_.get()); modelview_abs_->getParent(0)->removeChild(modelview_abs_.get()); } modelview_abs_ = NULL; projection_ = NULL; colorMask_ = _colorMask; maskOn_ = _maskOn; alphaPart_ = _alphaPart; modelview_abs_ = new osg::MatrixTransform; modelview_abs_->setReferenceFrame(osg::Transform::ABSOLUTE_RF); modelview_abs_->setMatrix(osg::Matrix::identity()); projection_ = new osg::Projection; modelview_abs_->addChild(projection_.get()); _on->addChild(modelview_abs_.get()); int nbLayers = _layers.size(); orgLayers_.clear(); for (i = 0; i < nbLayers; i++) { orgLayers_.push_back( _layers[i] ); } Layer &layer = orgLayers_[0]; osg::Texture2D *textureA = layer.texture_.get(); if (!textureA) osg::notify(osg::FATAL) << "TextureLayersFlatten: texture for layer 0 is NULL" << std::endl; textureA->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); textureA->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); BaseRenderTechnic *technic = NULL; technic = new DecalRenderTechnic( this, textureA, outputTexture_.get() ); technic->setup(projection_.get()); if (_bUseOldLayersParams && nbOldTechnics > 1) { if (tex2Color.find(textureA) != tex2Color.end()) technic->setColorFactor( tex2Color[textureA] ); if (tex2Opacity.find(textureA) != tex2Opacity.end()) technic->setOpacity( tex2Opacity[textureA] ); } technics_.push_back(technic); technic->createdFromlayer_ = &layer; for (i = 1; i < nbLayers; i++) { Layer &layer = orgLayers_[i]; osg::Texture2D *textureA; osg::Texture2D *textureB; textureA = outputTexture_.get(); textureB = layer.texture_.get(); if (!textureB) osg::notify(osg::FATAL) << "TextureLayersFlatten: one texture layer is NULL" << std::endl; textureA->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); textureA->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); textureB->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); textureB->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); BaseRenderTechnic *technic = NULL; int pixop = layer.pixelOp_; switch(pixop) { case PIXELOP_NORMAL: technic = new NormalRenderTechnic( this, textureA, textureB, outputTexture_.get() ); break; case PIXELOP_OVERLAY: technic = new OverlayRenderTechnic(this, textureA, textureB, outputTexture_.get() ); break; case PIXELOP_LINEARDODGE: technic = new LinearDodgeRenderTechnic( this, textureA, textureB, outputTexture_.get() ); break; case PIXELOP_MULTIPLY: technic = new MultiplyRenderTechnic( this, textureA, textureB, outputTexture_.get() ); break; default: break; } technic->createdFromlayer_ = &layer; technic->setup(projection_.get()); if (_bUseOldLayersParams) { // && i < nbOldTechnics) { if (tex2Color.find(textureB) != tex2Color.end()) { osg::Vec3f &colorFactor = tex2Color[textureB]; technic->setColorFactor( colorFactor ); } if (tex2Opacity.find(textureB) != tex2Opacity.end()) { float opa = tex2Opacity[textureB]; technic->setOpacity( opa ); } } technics_.push_back(technic); } if (colorMask_.valid()) { colorMask_->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); colorMask_->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); g_filterTexture.push_back( colorMask_.get() ); } // g_filterTexture.push_back( outputTexture_.get() ); //g_filterTexture.push_back( maskOn_.get() ); setupLastColorMaskPass(projection_.get()); if (_alphaPart) { g_filterTexture.push_back( alphaPart_.get() ); setupAlphaPartPass(projection_.get(), maskOn_.get() ); } } void TextureLayersFlatten::setupLastColorMaskPass(osg::Group *_on) { osg::TexEnvCombine *combiner; osg::BlendFunc *bf; osg::StateSet *ss; MyGeometry *geom; QuadParams quadParam; int vp_w, vp_h; quadParam.minPt = osg::Vec2f(-1, -1); quadParam.maxPt = osg::Vec2f(1, 1); quadParam.bInvertUV = false; osg::Group *grp = new osg::Group(); grp->setName("TextureLayersFlatten_ColorMask"); _on->addChild(grp); if (colorMask_.valid()) { // PASS1, OUTPUT TEXTURE * COLOR MASK geom = new MyGeometry(NULL, false); quadParam.geomToUse = geom; quads_[0] = new Quad(quadParam); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quads_[0]->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( maskOn_.get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, outputTexture_.get() ); ss->setTextureAttributeAndModes(1, colorMask_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quads_[0]->getGeode()); // PASS2, IN ADDITIVE MODE: MASKON * (1 - COLORMASK) geom = new MyGeometry( maskOn_.get(), true); quadParam.geomToUse = geom; quads_[1] = new Quad(quadParam); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quads_[1]->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ONE); ss->setAttributeAndModes(bf); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, colorMask_.get() ); ss->setTextureAttributeAndModes(1, maskOn_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_ONE_MINUS_SRC_COLOR); combiner->setOperand0_Alpha(GL_ONE_MINUS_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quads_[1]->getGeode()); } else { geom = new MyGeometry( maskOn_.get(), true); quadParam.geomToUse = geom; quads_[0] = new Quad(quadParam); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quads_[0]->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( maskOn_.get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, outputTexture_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); geom->setNodeToMask(grp); grp->addChild(quads_[0]->getGeode()); } } void TextureLayersFlatten::setupAlphaPartPass(osg::Group *_on, osg::Texture2D *_textureToPutAlphaOn) { if (!alphaPart_.get()) return; osg::TexEnvCombine *combiner; osg::BlendFunc *bf; osg::StateSet *ss; MyGeometry *geom; QuadParams quadParam; int vp_w, vp_h; quadParam.minPt = osg::Vec2f(-1, -1); quadParam.maxPt = osg::Vec2f(1, 1); quadParam.bInvertUV = false; osg::Group *grp = new osg::Group(); grp->setName("TextureLayersFlatten_AlphaPartPass"); _on->addChild(grp); // PASS1 geom = new MyGeometry(NULL, false); quadParam.geomToUse = geom; quads_[2] = new Quad(quadParam); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quads_[2]->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( _textureToPutAlphaOn ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, _textureToPutAlphaOn ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); geom->setNodeToMask(grp); grp->addChild(quads_[2]->getGeode()); // PASS2 geom = new MyGeometry(_textureToPutAlphaOn, true); quadParam.geomToUse = geom; quads_[3] = new Quad(quadParam); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( _textureToPutAlphaOn ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); combiner = new osg::TexEnvCombine(); ss->setTextureAttributeAndModes(0, alphaPart_.get() ); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); //combiner->setConstantColor( osg::Vec4f(1.0f, 1.0f, 1.0f, 0.5f) ); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); // combiner->setSource0_RGB(GL_CONSTANT_ARB); //combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); osg::ColorMask *cmask = new osg::ColorMask(false, false, false, true); ss->setAttributeAndModes(cmask); geom->setNodeToMask(grp); grp->addChild(quads_[3]->getGeode()); } void TextureLayersFlatten::flushTextureCacheForAllBRT() { int size = technics_.size(); for (int i = 0; i < size; i++) { BaseRenderTechnic *technic = technics_[i]; technic->flushTextureCache(); } if (quads_[0].valid()) ((MyGeometry*)quads_[0]->getGeometry())->nodeToMask_->setNodeMask(0xFFFFFFFF); if (quads_[1].valid()) ((MyGeometry*)quads_[1]->getGeometry())->nodeToMask_->setNodeMask(0xFFFFFFFF); if (quads_[2].valid()) ((MyGeometry*)quads_[2]->getGeometry())->nodeToMask_->setNodeMask(0xFFFFFFFF); if (quads_[3].valid()) ((MyGeometry*)quads_[3]->getGeometry())->nodeToMask_->setNodeMask(0xFFFFFFFF); } // BASE RENDER TECHNIC TextureLayersFlatten::BaseRenderTechnic::~BaseRenderTechnic() { if (parentGroup_.valid()) parentGroup_->removeChild(0, 1); } void TextureLayersFlatten::BaseRenderTechnic::setOpacity(float _opacity) { opacity_ = _opacity; updateCombiners(); } void TextureLayersFlatten::BaseRenderTechnic::setColorFactor(const osg::Vec3f &_colorFactor) { colorFactor_ = _colorFactor; updateCombiners(); } void TextureLayersFlatten::BaseRenderTechnic::updateCombiners() { } void TextureLayersFlatten::BaseRenderTechnic::flushTextureCache() { int nbQuads = quads_.size(); for (int i = 0; i < nbQuads; i++) { if (quads_[i].valid()) ((MyGeometry*)quads_[i]->getGeometry())->nodeToMask_->setNodeMask(0xFFFFFFFF); } } // DECAL RENDER TECHNIC void TextureLayersFlatten::DecalRenderTechnic::updateCombiners() { Parent::updateCombiners(); combiner_->setConstantColor(osg::Vec4f(colorFactor_._v[0], colorFactor_._v[1], colorFactor_._v[2], 1)); } void TextureLayersFlatten::DecalRenderTechnic::flushTextureCache() { Parent::flushTextureCache(); } void TextureLayersFlatten::DecalRenderTechnic::setup(osg::Group *_on) { osg::TexEnvCombine *combiner; osg::BlendFunc *bf; osg::StateSet *ss; MyGeometry *geom; QuadParams quadParam; Quad *quad; int vp_w; int vp_h; quadParam.minPt = osg::Vec2f(-1, -1); quadParam.maxPt = osg::Vec2f(1, 1); quadParam.bInvertUV = false; osg::Group *grp = new osg::Group(); grp->setName("TextureLayersFlatten_DecalGroup"); _on->addChild(grp); parentGroup_ = grp; // PASS1, COPY TEXTURE A geom = new MyGeometry( textureOutput_.get(), true); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( textureOutput_.get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureA_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_CONSTANT_ARB); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setConstantColor(osg::Vec4f(1, 1, 1, 1) ); combiner_ = combiner; ss->setTextureAttributeAndModes(0, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); } // NORMAL RENDER TECHNIC - 1 PASS // Description: The background is completely covered by the blend layer, so you should have some transparency if you use this mode. // col = B void TextureLayersFlatten::NormalRenderTechnic::updateCombiners() { Parent::updateCombiners(); combiners_[0]->setConstantColor(osg::Vec4f(colorFactor_._v[0]*opacity_, colorFactor_._v[1]*opacity_, colorFactor_._v[2]*opacity_, opacity_)); combiners_[1]->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, opacity_)); } void TextureLayersFlatten::NormalRenderTechnic::flushTextureCache() { Parent::flushTextureCache(); } void TextureLayersFlatten::NormalRenderTechnic::setup(osg::Group *_on) { osg::TexEnvCombine *combiner; osg::BlendFunc *bf; osg::StateSet *ss; MyGeometry *geom; QuadParams quadParam; Quad *quad; int vp_w, vp_h; quadParam.minPt = osg::Vec2f(-1, -1); quadParam.maxPt = osg::Vec2f(1, 1); quadParam.bInvertUV = false; osg::Group *grp = new osg::Group(); grp->setName("TextureLayersFlatten_NormalGroup"); _on->addChild(grp); parentGroup_ = grp; // PASS1, BLEND B geom = new MyGeometry( NULL, false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( textureOutput_.get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, textureB_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_ALPHA); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[0] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS2, BLEND A geom = new MyGeometry( textureOutput_.get(), true); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ONE); ss->setAttributeAndModes(bf); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, textureA_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[1] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_ONE_MINUS_SRC_ALPHA); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); } // OVERLAY RENDER TECHNIC - 10 PASS :( // Description: A combination of screen and multiply mode, depending on the base color. // if (A < 0.5) col = 2 * A * B // else col = 1 - 2 * (1 - A) * (1 - B) void TextureLayersFlatten::OverlayRenderTechnic::updateCombiners() { Parent::updateCombiners(); combiners_[0]->setConstantColor(osg::Vec4f(opacity_, opacity_, opacity_, opacity_)); combiners_[1]->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, opacity_)); } void TextureLayersFlatten::OverlayRenderTechnic::flushTextureCache() { Parent::flushTextureCache(); } void TextureLayersFlatten::OverlayRenderTechnic::setup(osg::Group *_on) { osg::TexEnvCombine *combiner; osg::BlendFunc *bf; osg::StateSet *ss; MyGeometry *geom; QuadParams quadParam; Quad *quad; int vp_w; int vp_h; quadParam.minPt = osg::Vec2f(-1, -1); quadParam.maxPt = osg::Vec2f(1, 1); quadParam.bInvertUV = false; osg::Group *grp = new osg::Group(); grp->setName("TextureLayersFlatten_OverlayGroup"); _on->addChild(grp); parentGroup_ = grp; // PASS1 : 2 * A * B geom = new MyGeometry( g_tmpTexture[0].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray()); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE(g_tmpTexture[0].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureA_.get() ); ss->setTextureAttributeAndModes(1, textureB_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setScale_RGB(2.0f); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS2 : 1 - 2 * (1 - A) * (1 - B) geom = new MyGeometry( g_tmpTexture[1].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray()); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE(g_tmpTexture[1].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureA_.get() ); ss->setTextureAttributeAndModes(1, textureB_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_ONE_MINUS_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_ONE_MINUS_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setScale_RGB(2.0f); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS 3,4,5,6 : IF (A < 0.5) A = 0 ELSE A = 1 for (int i = 2; i < 6; i++) { geom = new MyGeometry( g_tmpTexture[2].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE(g_tmpTexture[2].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); if (i == 2) ss->setTextureAttributeAndModes(0, textureA_.get() ); else ss->setTextureAttributeAndModes(0, g_tmpTexture[2].get() ); combiner = new osg::TexEnvCombine(); if (i == 2) { combiner->setCombine_RGB(GL_SUBTRACT_ARB); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_CONSTANT_ARB); combiner->setSource1_Alpha(GL_CONSTANT_ARB); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor( osg::Vec4f(0.5f, 0.5f, 0.5f, 0) ); } else { combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); } combiner->setScale_RGB(4.0f); ss->setTextureAttributeAndModes(0, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); } // PASS7, LOW PART for A < 0.5 geom = new MyGeometry( g_tmpTexture[0].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray()); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE(g_tmpTexture[0].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, g_tmpTexture[0].get() ); ss->setTextureAttributeAndModes(1, g_tmpTexture[2].get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_ONE_MINUS_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS8, HIGH PART for A > 0.5 geom = new MyGeometry( g_tmpTexture[1].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray()); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE(g_tmpTexture[1].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, g_tmpTexture[1].get() ); ss->setTextureAttributeAndModes(1, g_tmpTexture[2].get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_ONE_MINUS_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS9, LOW PART + HIGH PART geom = new MyGeometry( g_tmpTexture[2].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray()); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE(g_tmpTexture[2].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, g_tmpTexture[0].get() ); ss->setTextureAttributeAndModes(1, g_tmpTexture[1].get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_ADD); combiner->setCombine_Alpha(GL_ADD); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS10, BLEND B geom = new MyGeometry( NULL, false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( textureOutput_.get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, g_tmpTexture[2].get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_ALPHA); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[0] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS11, BLEND A geom = new MyGeometry( textureOutput_.get(), true); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ONE); ss->setAttributeAndModes(bf); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, textureA_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[1] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_ONE_MINUS_SRC_ALPHA); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); } // LINEAR DODGE RENDER TECHNIC - 2 PASS // Description: A very basic blend mode. // A + B void TextureLayersFlatten::LinearDodgeRenderTechnic::updateCombiners() { Parent::updateCombiners(); combiners_[0]->setConstantColor(osg::Vec4f(colorFactor_._v[0]*opacity_, colorFactor_._v[1]*opacity_, colorFactor_._v[2]*opacity_, opacity_)); combiners_[1]->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, opacity_)); } void TextureLayersFlatten::LinearDodgeRenderTechnic::flushTextureCache() { Parent::flushTextureCache(); } void TextureLayersFlatten::LinearDodgeRenderTechnic::setup(osg::Group *_on) { osg::TexEnvCombine *combiner; osg::BlendFunc *bf; osg::StateSet *ss; MyGeometry *geom; QuadParams quadParam; Quad *quad; int vp_w, vp_h; quadParam.minPt = osg::Vec2f(-1, -1); quadParam.maxPt = osg::Vec2f(1, 1); quadParam.bInvertUV = false; osg::Group *grp = new osg::Group(); grp->setName("TextureLayersFlatten_LinearDodgeGroup"); _on->addChild(grp); parentGroup_ = grp; // PASS1, A + B geom = new MyGeometry( g_tmpTexture[0].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray()); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( g_tmpTexture[0].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureA_.get() ); ss->setTextureAttributeAndModes(1, textureB_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_ADD); combiner->setCombine_Alpha(GL_ADD); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS2, BLEND B geom = new MyGeometry( NULL, false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( textureOutput_.get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, g_tmpTexture[0].get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_ALPHA); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[0] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quads_[1]->getGeode()); // PASS3, BLEND A geom = new MyGeometry( textureOutput_.get(), true); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ONE); ss->setAttributeAndModes(bf); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, textureA_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[1] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_ONE_MINUS_SRC_ALPHA); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); } // MULTIPLY RENDER TECHNIC - 2 PASS // Description: Both parameters are simply multiplied by each other. // This returns a darker result than both input parameters in most cases (except one of them equals 1). // Completely white layers do not change the background at all (and vice versa) - completely black layers give a black result. // A * B void TextureLayersFlatten::MultiplyRenderTechnic::updateCombiners() { Parent::updateCombiners(); combiners_[0]->setConstantColor(osg::Vec4f(colorFactor_._v[0]*opacity_, colorFactor_._v[1]*opacity_, colorFactor_._v[2]*opacity_, opacity_)); combiners_[1]->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, opacity_)); } void TextureLayersFlatten::MultiplyRenderTechnic::flushTextureCache() { Parent::flushTextureCache(); } void TextureLayersFlatten::MultiplyRenderTechnic::setup(osg::Group *_on) { osg::TexEnvCombine *combiner; osg::BlendFunc *bf; osg::StateSet *ss; MyGeometry *geom; QuadParams quadParam; Quad *quad; int vp_w, vp_h; quadParam.minPt = osg::Vec2f(-1, -1); quadParam.maxPt = osg::Vec2f(1, 1); quadParam.bInvertUV = false; osg::Group *grp = new osg::Group(); grp->setName("TextureLayersFlatten_MultiplyGroup"); _on->addChild(grp); parentGroup_ = grp; // PASS1, A * B geom = new MyGeometry( g_tmpTexture[0].get(), false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray()); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( g_tmpTexture[0].get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureA_.get() ); ss->setTextureAttributeAndModes(1, textureB_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_REPLACE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_TEXTURE); combiner->setSource0_Alpha(GL_TEXTURE); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS2, BLEND B geom = new MyGeometry( NULL, false); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ZERO); ss->setAttributeAndModes(bf); SET_VIEWPORT_FROM_TEXTURE_SIZE( textureOutput_.get() ); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, g_tmpTexture[0].get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_ALPHA); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[0] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); // PASS3, BLEND A geom = new MyGeometry( textureOutput_.get(), true); quadParam.geomToUse = geom; quad = new Quad(quadParam); quads_.push_back(quad); ss = geom->getOrCreateStateSet(); ss->setRenderBinDetails(g_iRBin++, RENDERBIN_NAME); geom->setTexCoordArray(1, quad->getUVArray() ); bf = new osg::BlendFunc(); bf->setFunction(GL_ONE, GL_ONE); ss->setAttributeAndModes(bf); ss->setAttributeAndModes(new osg::Viewport(0, 0, vp_w, vp_h)); ss->setTextureAttributeAndModes(0, textureB_.get() ); ss->setTextureAttributeAndModes(1, textureA_.get() ); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_MODULATE); combiner->setSource0_RGB(GL_CONSTANT_ARB); combiner->setSource0_Alpha(GL_CONSTANT_ARB); combiner->setOperand0_RGB(GL_SRC_COLOR); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); combiner->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); combiners_[1] = combiner; ss->setTextureAttributeAndModes(0, combiner); combiner = new osg::TexEnvCombine(); combiner->setCombine_RGB(GL_MODULATE); combiner->setCombine_Alpha(GL_REPLACE); combiner->setSource0_RGB(GL_PREVIOUS_ARB); combiner->setSource0_Alpha(GL_PREVIOUS_ARB); combiner->setOperand0_RGB(GL_ONE_MINUS_SRC_ALPHA); combiner->setOperand0_Alpha(GL_SRC_ALPHA); combiner->setSource1_RGB(GL_TEXTURE); combiner->setSource1_Alpha(GL_TEXTURE); combiner->setOperand1_RGB(GL_SRC_COLOR); combiner->setOperand1_Alpha(GL_SRC_ALPHA); ss->setTextureAttributeAndModes(1, combiner); geom->setNodeToMask(grp); grp->addChild(quad->getGeode()); } // TextureLayersFlatten::MyGeometry void TextureLayersFlatten::MyGeometry::drawImplementation(osg::State &_state) const { int i; #ifdef USE_NPROFILE double t1 = nprf::GetRealTime(); #endif osg::notify(osg::INFO) << "TextureLayersFlatten: calculate layered texture" << std::endl; std::map< osg::Texture2D*, osg::Texture2D::FilterMode > tex2MinFilter; std::map< osg::Texture2D*, osg::Texture2D::FilterMode > tex2MagFilter; int nbTexs = g_filterTexture.size(); for (i = 0; i < nbTexs; i++) { osg::Texture2D *tex = g_filterTexture[i].get(); if (!tex) continue; osg::Texture2D::FilterMode oldMinFilter = tex->getFilter(osg::Texture::MIN_FILTER); osg::Texture2D::FilterMode oldMagFilter = tex->getFilter(osg::Texture::MAG_FILTER); tex2MinFilter[tex] = oldMinFilter; tex2MagFilter[tex] = oldMagFilter; tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST); } Geometry::drawImplementation( _state ); if (target_.valid()) { osg::Texture2D *tgt = (osg::Texture2D*) target_.get(); // _state.setActiveTextureUnit(0); // _state.haveAppliedTextureAttribute(0, tgt); int w = tgt->getTextureWidth(); int h = tgt->getTextureHeight(); if (!w) { w = tgt->getImage()->s(); h = tgt->getImage()->t(); } tgt->copyTexImage2D(_state, 0, 0, w, h); // int t = _state.getActiveTextureUnit(); // _state.haveAppliedTextureAttribute(t, target_.get() ); } for (i = 0; i < nbTexs; i++) { osg::Texture2D *tex = g_filterTexture[i].get(); if (!tex) continue; //osg::Texture2D::FilterMode oldMinFilter = tex2MinFilter[tex]; // osg::Texture2D::FilterMode oldMagFilter = tex2MagFilter[tex]; // tex->setFilter(osg::Texture::MIN_FILTER, oldMinFilter ); // tex->setFilter(osg::Texture::MAG_FILTER, oldMagFilter); tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR ); tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR ); } if (bClearFrameBufferAfterRecopy_) { glColorMask(true, true, true, true); glClear(GL_COLOR_BUFFER_BIT); } if (nodeToMask_) nodeToMask_->setNodeMask(0); #ifdef USE_NPROFILE double t2 = nprf::GetRealTime(); static double cumul = 0; cumul += t2 - t1; osg::notify(osg::INFO) << "OSGCAL: Render to Screen for Texture Layers Flatten took: " << (t2-t1)*1000 << "ms, cumul is: " << cumul << "s" << std::endl; #endif } // TextureLayersFlatten::Quad::Quad(QuadParams &_params) { geode_ = new osg::Geode(); if (!_params.geomToUse) geom_ = new osg::Geometry(); else geom_ = _params.geomToUse; geode_->addDrawable(geom_.get()); geode_->setCullingActive(false); vertices_ = new osg::Vec3Array(); osg::Vec3Array *vert = vertices_.get(); vert->resize(4); geom_->setVertexArray(vert); vert[0][0] = osg::Vec3f(_params.minPt._v[0], _params.minPt._v[1], 0.1f); vert[0][1] = osg::Vec3f(_params.maxPt._v[0], _params.minPt._v[1], 0.1f); vert[0][2] = osg::Vec3f(_params.maxPt._v[0], _params.maxPt._v[1], 0.1f); vert[0][3] = osg::Vec3f(_params.minPt._v[0], _params.maxPt._v[1], 0.1f); uv_ = new osg::Vec2Array(); if (!_params.bInvertUV) { uv_->push_back( osg::Vec2f(_params.minUV._v[0], _params.minUV._v[1]) ); uv_->push_back( osg::Vec2f(_params.maxUV._v[0], _params.minUV._v[1]) ); uv_->push_back( osg::Vec2f(_params.maxUV._v[0], _params.maxUV._v[1]) ); uv_->push_back( osg::Vec2f(_params.minUV._v[0], _params.maxUV._v[1]) ); } else { uv_->push_back( osg::Vec2f(_params.minUV._v[0], _params.maxUV._v[1]) ); uv_->push_back( osg::Vec2f(_params.maxUV._v[0], _params.maxUV._v[1]) ); uv_->push_back( osg::Vec2f(_params.maxUV._v[0], _params.minUV._v[1]) ); uv_->push_back( osg::Vec2f(_params.minUV._v[0], _params.minUV._v[1]) ); } geom_->setTexCoordArray(0, uv_.get()); GLushort index[6]; index[0] = 0; index[1] = 1; index[2] = 2; index[3] = 0; index[4] = 2; index[5] = 3; geom_->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, 6, index)); geom_->setUseDisplayList(false); geom_->setUseVertexBufferObjects(false); osg::StateSet *state = geom_->getOrCreateStateSet(); material_ = new osg::Material; state->setAttributeAndModes(material_.get(), osg::StateAttribute::ON); state->setMode(GL_LIGHTING, osg::StateAttribute::OFF); state->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); material_->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 1, 1) ); texture_ = NULL; osg::BlendFunc *bf = new osg::BlendFunc; bf->setFunction(_params.srcBlendFactor, _params.dstBlendFactor); state->setAttributeAndModes(bf, osg::StateAttribute::ON); if (_params.bDisableWriteMask) { state->setMode(GL_DEPTH_TEST, false); } } TextureLayersFlatten::Quad::~Quad() { } void InvertPremultipliedAlpha(osg::Image &_img) { if (_img.getPixelFormat() != GL_RGBA) return; int w = _img.s(); int h = _img.t(); int size = w * h; // int t1 = timeGetTime(); unsigned char *pixs = _img.data(); /* for (int i = 0; i < size; i++, pixs += 4) { int a = pixs[3]; if (!a) continue; float fa = 255.0f / a; pixs[0] = int(pixs[0] * fa); pixs[1] = int(pixs[1] * fa); pixs[2] = int(pixs[2] * fa); } */ for (int i = 0; i < size; i++, pixs += 4) { int a = pixs[3]; if (!a) continue; int fa = g_alphapreca[a]; pixs[0] = (pixs[0] * fa) >> 8; pixs[1] = (pixs[1] * fa) >> 8; pixs[2] = (pixs[2] * fa) >> 8; } /* int t2 = timeGetTime() - t1; char str[200]; static int cumul = 0; cumul += t2; sprintf(str, "%ld\n", cumul); OutputDebugString(str); */ } }