随笔 - 833  文章 - 1  评论 - 106  阅读 - 200万

osg轮廓特效 【转】

// -*-c++-*-

/*
 * OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
 */

/*
 * osgFX::Outline - Copyright (C) 2004,2009 Ulrich Hertlein
 */

#ifndef OSGFX_OUTLINE_
#define OSGFX_OUTLINE_

#include <osgFX/Export>
#include <osgFX/Effect>

namespace osgFX
{
    /**
     * Outline effect.
     */
    class Outline : public Effect
    {
    public:
        /// Constructor.
        Outline();
        Outline(const Outline& copy,
                const osg::CopyOp& op = osg::CopyOp::SHALLOW_COPY)
            : Effect(copy, op) {
            _width = copy._width;
            _color = copy._color;
        }

        // Effect class info
        META_Effect(osgFX, Outline, "Outline",
                    "Stencil buffer based object outlining.",
                    "Ulrich Hertlein <u.hertlein@sandbox.de>");

        /// Set outline width.
        void setWidth(float w) {
            _width = w;
        }

        /// Get outline width.
        float getWidth() const {
            return _width;
        }

        /// Set outline color.
        void setColor(const osg::Vec4& col) {
            _color = col;
        }

        /// Get outline color.
        const osg::Vec4& getColor() const {
            return _color;
        }

    protected:
        /// Destructor.
        virtual ~Outline() {
        }

        /// Define available techniques.
        bool define_techniques();

    private:
        /// Outline width.
        float _width;

        /// Outline color.
        osg::Vec4 _color;
    };
};

#endif

// -*-c++-*-

/*
 * OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
 */

/*
 * osgFX::Outline - Copyright (C) 2004,2009 Ulrich Hertlein
 */

#include <osgFX/Outline>
#include <osgFX/Registry>

#include <osg/Group>
#include <osg/Stencil>
#include <osg/CullFace>
#include <osg/PolygonMode>
#include <osg/LineWidth>
#include <osg/Material>

#include <osg/NodeCallback>
#include <osgUtil/CullVisitor>

#include <iostream>


const unsigned int Override_On = osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE;
const unsigned int Override_Off = osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE;


namespace osgFX
{
    /// Register prototype.
    Registry::Proxy proxy(new Outline);

    /**
     * Outline technique.
     */
    class OutlineTechnique : public Technique
    {
    public:
        /// Constructor.
        OutlineTechnique(const Outline& outline) : Technique() {
            _outline = &outline;
        }

        /// Validate.
        bool validate(osg::State&) const {
            return true;
        }

    protected:
        /// Define render passes.
        void define_passes() {

            /*
             * draw
             * - set stencil buffer to ref=1 where draw occurs
             * - clear stencil buffer to 0 where test fails
             */
            {
                osg::StateSet* state = new osg::StateSet;

                // stencil op
                osg::Stencil* stencil  = new osg::Stencil;
                stencil->setFunction(osg::Stencil::ALWAYS, 1, ~0);
                stencil->setOperation(osg::Stencil::KEEP,
                                      osg::Stencil::KEEP,
                                      osg::Stencil::REPLACE);
                state->setAttributeAndModes(stencil, Override_On);

                addPass(state);
            }

            /*
             * post-draw
             * - only draw where draw didn't set the stencil buffer
             * - draw only back-facing polygons
             * - draw back-facing polys as lines
             * - disable depth-test, lighting & texture
             */
            {
                osg::StateSet* state = new osg::StateSet;

                // stencil op
                osg::Stencil* stencil  = new osg::Stencil;
                stencil->setFunction(osg::Stencil::NOTEQUAL, 1, ~0);
                stencil->setOperation(osg::Stencil::KEEP,
                                      osg::Stencil::KEEP,
                                      osg::Stencil::REPLACE);
                state->setAttributeAndModes(stencil, Override_On);

                // cull front-facing polys
                osg::CullFace* cf = new osg::CullFace;
                cf->setMode(osg::CullFace::FRONT);
                state->setAttributeAndModes(cf, Override_On);

                // poly mode for back-facing polys
                osg::PolygonMode* pm = new osg::PolygonMode;
                pm->setMode(osg::PolygonMode::BACK, osg::PolygonMode::LINE);
                state->setAttributeAndModes(pm, Override_On);

                // outline width
                osg::LineWidth* lw = new osg::LineWidth;
                lw->setWidth(_outline->getWidth());
                state->setAttributeAndModes(lw, Override_On);

                // outline color/material
                const osg::Material::Face face = osg::Material::FRONT_AND_BACK;
                osg::Material* mtl = new osg::Material;
                mtl->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
                mtl->setAmbient(face, _outline->getColor());
                mtl->setDiffuse(face, _outline->getColor());
                mtl->setEmission(face, _outline->getColor());
                state->setAttributeAndModes(mtl, Override_On);

                // disable modes
                state->setMode(GL_BLEND, Override_Off);
                state->setMode(GL_DEPTH_TEST, Override_Off);
                state->setTextureMode(0, GL_TEXTURE_1D, Override_Off);
                state->setTextureMode(0, GL_TEXTURE_2D, Override_Off);
                state->setTextureMode(0, GL_TEXTURE_3D, Override_Off);

                addPass(state);
            }
        }

    private:
        /// Outline effect.
        osg::ref_ptr<const Outline> _outline;
    };

    /**
     * Enable stencil clear callback.
     */
    class EnableStencilCallback : public osg::NodeCallback
    {
    public:
        EnableStencilCallback() {}

        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {

            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv) {
                // enable stencil clear on render stage
                osgUtil::RenderStage* render = cv->getRenderStage();
                unsigned int mask = render->getClearMask();
                if ((mask & GL_STENCIL_BUFFER_BIT) == 0) {
                    render->setClearMask(mask | GL_STENCIL_BUFFER_BIT);
                    render->setClearStencil(0);
                    //std::cerr << "osgFX::Outline activated stencil/n";
                }
            }

            traverse(node, nv);
        }

    private:
    };

    /// Constructor.
    Outline::Outline() : Effect()
    {
        _width = 3.0f;
        _color.set(1.0f,1.0f,1.0f,1.0f);
        addCullCallback(new EnableStencilCallback);
    }

    /// Define available techniques.
    bool Outline::define_techniques()
    {
        addTechnique(new OutlineTechnique(*this));
        return true;
    }
};

posted on   3D入魔  阅读(1826)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2011-06-24 std::set用法(转)
2011-06-24 STL中map用法详解(转)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示