/* -*- c++ -*- * * Copyright (C) 2004, 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 * */ #ifndef __OSGCAL__TEXLAYERS_FLATTEN_H__ #define __OSGCAL__TEXLAYERS_FLATTEN_H__ #include #include #include #include #include #include #include #include #include #include #include namespace osgCal { OSGCAL_EXPORT void InvertPremultipliedAlpha(osg::Image &_img); class TextureLayersFlatten : public osg::Referenced { public: enum PIXELOP { // terminology are taken from Photoshop PIXELOP_DECAL, // for single layer PIXELOP_NORMAL, PIXELOP_OVERLAY, PIXELOP_LINEARDODGE, PIXELOP_MULTIPLY, }; class Layer { public: Layer() { }; osg::ref_ptr texture_; PIXELOP pixelOp_; }; class MyGeometry : public osg::Geometry { public: MyGeometry(osg::Texture2D *_target, bool _bClearFrameBufferAfterRecopy) { target_ = _target; bClearFrameBufferAfterRecopy_ = _bClearFrameBufferAfterRecopy; nodeToMask_ = NULL; } void setNodeToMask(osg::Node *_nodeToMask) { nodeToMask_ = _nodeToMask; } osg::ref_ptr target_; osg::Geode *geode_; bool bClearFrameBufferAfterRecopy_; osg::Node *nodeToMask_; virtual void drawImplementation(osg::State &) const; }; class QuadParams { public: QuadParams() { geomToUse = NULL; minPt = osg::Vec2f(0, 0); maxPt = osg::Vec2f(1, 1); minUV = osg::Vec2f(0, 0); maxUV = osg::Vec2f(1, 1); srcBlendFactor = GL_SRC_ALPHA; dstBlendFactor = GL_ONE_MINUS_SRC_ALPHA; bInvertUV = true; bDisableWriteMask = true; } osg::Geometry *geomToUse; osg::Vec2f minPt; osg::Vec2f maxPt; osg::Vec2f minUV; osg::Vec2f maxUV; GLenum srcBlendFactor; GLenum dstBlendFactor; bool bInvertUV; bool bDisableWriteMask; }; class Quad : public osg::Referenced { Quad() { }; public: explicit Quad( QuadParams &); virtual ~Quad(); inline osg::Geode* getGeode() const { return (osg::Geode*) geode_.get(); } inline osg::Geometry* getGeometry() const { return (osg::Geometry*) geom_.get(); } inline osg::Vec3Array* getVerticesArray() const { return (osg::Vec3Array*) vertices_.get(); } inline osg::Vec2Array* getUVArray() const { return (osg::Vec2Array*) uv_.get(); } inline osg::Material* getMaterial() const { return (osg::Material*) material_.get(); } inline osg::Texture2D* getTexture() const { return (osg::Texture2D*) texture_.get(); } inline void setTexture(osg::Texture2D *_tex) { texture_ = _tex; } protected: osg::ref_ptr geode_; osg::ref_ptr geom_; osg::ref_ptr vertices_; osg::ref_ptr uv_; osg::ref_ptr material_; osg::ref_ptr texture_; }; class BaseRenderTechnic { public: BaseRenderTechnic(TextureLayersFlatten *_parent, osg::Texture2D *_textureA, osg::Texture2D *_textureB, osg::Texture2D *_textureOutput) : parent_(_parent), createdFromlayer_(NULL), textureA_(_textureA), textureB_(_textureB), textureOutput_(_textureOutput), opacity_(1), colorFactor_(1, 1, 1) { }; virtual ~BaseRenderTechnic(); OSGCAL_EXPORT inline int getTechnicID() const { return technicID_; } OSGCAL_EXPORT inline float getOpacity() const { return opacity_; } OSGCAL_EXPORT void setOpacity(float); OSGCAL_EXPORT inline const osg::Vec3f& getColorFactor() const { return colorFactor_; } OSGCAL_EXPORT void setColorFactor(const osg::Vec3f &_col); virtual void flushTextureCache(); protected: virtual void setup(osg::Group *on) { }; virtual void updateCombiners(); int technicID_; TextureLayersFlatten *parent_; Layer *createdFromlayer_; osg::ref_ptr textureA_; osg::ref_ptr textureB_; osg::ref_ptr textureOutput_; osg::ref_ptr parentGroup_; float opacity_; osg::Vec3f colorFactor_; std::vector< osg::ref_ptr > quads_; friend class TextureLayersFlatten; }; class DecalRenderTechnic : public BaseRenderTechnic { public: typedef BaseRenderTechnic Parent; DecalRenderTechnic(TextureLayersFlatten *_parent, osg::Texture2D *_textureA, osg::Texture2D *_textureOutput) : BaseRenderTechnic(_parent, _textureA, NULL, _textureOutput) { technicID_ = PIXELOP_DECAL; } virtual ~DecalRenderTechnic() { } virtual void flushTextureCache(); protected: virtual void setup(osg::Group *parent); virtual void updateCombiners(); osg::ref_ptr combiner_; friend class TextureLayersFlatten; }; class NormalRenderTechnic : public BaseRenderTechnic { public: typedef BaseRenderTechnic Parent; NormalRenderTechnic(TextureLayersFlatten *_parent, osg::Texture2D *_textureA, osg::Texture2D *_textureB, osg::Texture2D *_textureOutput) : BaseRenderTechnic(_parent, _textureA, _textureB, _textureOutput) { technicID_ = PIXELOP_NORMAL; } virtual ~NormalRenderTechnic() { } virtual void flushTextureCache(); protected: virtual void setup(osg::Group *parent); virtual void updateCombiners(); osg::ref_ptr combiners_[2]; friend class TextureLayersFlatten; }; class OverlayRenderTechnic : public BaseRenderTechnic { public: typedef BaseRenderTechnic Parent; OverlayRenderTechnic(TextureLayersFlatten *_parent, osg::Texture2D *_textureA, osg::Texture2D *_textureB, osg::Texture2D *_textureOutput) : BaseRenderTechnic(_parent, _textureA, _textureB, _textureOutput) { technicID_ = PIXELOP_OVERLAY; } virtual ~OverlayRenderTechnic() { } void flushTextureCache(); protected: virtual void setup(osg::Group *on); virtual void updateCombiners(); osg::ref_ptr combiners_[2]; friend class TextureLayersFlatten; }; class LinearDodgeRenderTechnic : public BaseRenderTechnic { public: typedef BaseRenderTechnic Parent; LinearDodgeRenderTechnic(TextureLayersFlatten *_parent, osg::Texture2D *_textureA, osg::Texture2D *_textureB, osg::Texture2D *_textureOutput) : BaseRenderTechnic(_parent, _textureA, _textureB, _textureOutput) { technicID_ = PIXELOP_LINEARDODGE; } virtual ~LinearDodgeRenderTechnic() { } virtual void flushTextureCache(); protected: virtual void setup(osg::Group *on); virtual void updateCombiners(); osg::ref_ptr combiners_[2]; friend class TextureLayersFlatten; }; class MultiplyRenderTechnic : public BaseRenderTechnic { public: typedef BaseRenderTechnic Parent; MultiplyRenderTechnic(TextureLayersFlatten *_parent, osg::Texture2D *_textureA, osg::Texture2D *_textureB, osg::Texture2D *_textureOutput) : BaseRenderTechnic(_parent, _textureA, _textureB, _textureOutput) { technicID_ = PIXELOP_MULTIPLY; } virtual ~MultiplyRenderTechnic() { } void flushTextureCache(); protected: virtual void setup(osg::Group *on); virtual void updateCombiners(); osg::ref_ptr combiners_[2]; friend class TextureLayersFlatten; }; TextureLayersFlatten(); virtual ~TextureLayersFlatten(); static void resetBinCounter(); static void destroy(); void init( int width, int height, std::vector &layers, osg::Group *on, osg::Texture2D *myOutputTexture, osg::Texture2D *colorMask, osg::Texture2D *maskOn, osg::Texture2D *alphaPart = NULL, bool bUseOldLayersParams = true); inline const std::vector& getOrgLayer() const { return orgLayers_; } inline BaseRenderTechnic* getBaseRenderTechnic(unsigned int _index) { return _index < technics_.size() ? technics_[_index] : NULL; } inline int getNbBaseRenderTechnics() const { return technics_.size(); } inline osg::Texture2D* getOutputTexture() { return outputTexture_.get(); } inline void setOutputTexture(osg::Texture2D *_tex) { outputTexture_ = _tex; } OSGCAL_EXPORT void flushTextureCacheForAllBRT(); protected: void setupLastColorMaskPass(osg::Group *on); void setupAlphaPartPass(osg::Group *on, osg::Texture2D *textureToPutAlphaOn); std::vector technics_; std::vector orgLayers_; osg::ref_ptr outputTexture_; osg::ref_ptr colorMask_; osg::ref_ptr maskOn_; osg::ref_ptr alphaPart_; osg::ref_ptr modelview_abs_; osg::ref_ptr projection_; int width_, height_; osg::ref_ptr quads_[4]; }; } #endif