Hi Robert

How about this?
I've followed your lead regarding the two separate techniques.
I'm just not sure how to handle shader portability. The user can supply a 
program as argument with color uniform name. If none is supplied, it defaults 
to the minimal glsl 330 shader of my previous proposal.
What do you think?

Regards,
Rémi

Le 03/07/2015 08:16, Robert Osfield a écrit :
> Hi Remi,
>
> I have just done a quick review of your changes and feel that it would be 
> more useful if there was two separate techniques implemented - and old fixed 
> function approach and a new shader based one.  On GLES2+GL3+ one would not 
> implement the fixed function one and just have the shader one, while on other 
> GL variations one would be able to select either at runtime.
>
> Thoughts?
> Robert.
>
> On 2 July 2015 at 13:02, Thebault, Remi <[email protected] 
> <mailto:[email protected]>> wrote:
>
>     Hello
>
>     osgFX::Outline does not work in GL3 mode
>     I get the following warnings, and no outline rendered
>
>     Warning: PolygonMode::apply(State&) - only GL_FRONT_AND_BACK is supported.
>
>     Warning: Material::apply(State&) - not supported.
>
>
>     Attached is a simple fix.
>     I changed the line polygon mode from GL_BACK to GL_FRONT_AND_BACK.
>     I introduced a minimal shader program with material color uniform.
>
>     I surrounded changes with OSG_GL3_AVAILABLE preprocessor tests
>
>     now rendering works, and I don't get the warnings anymore.
>
>     please review
>
>     Cheers,
>     Rémi
>
>     _______________________________________________
>     osg-submissions mailing list
>     [email protected] 
> <mailto:[email protected]>
>     
> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
>
>
>
>
> _______________________________________________
> osg-submissions mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

// -*-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
 */

#ifndef OSGFX_OUTLINE_
#define OSGFX_OUTLINE_

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

namespace osgFX
{
    /**
     * Outline effect.
     * This effect draws a stencil buffer-based outline around an object.
     * Color and width of the outline can be modified.
     * To function correctly the context must be setup with a stencil buffer
     * and the stencil buffer must be cleared to zero before each render.
     *
     * osg::DisplaySettings::instance()->setMinimumNumStencilBits(1);
     * camera->setClearMask(clearMask | GL_STENCIL_BUFFER_BIT);
     * camera->setClearStencil(0);
     */
    class OSGFX_EXPORT Outline : public Effect
    {
    public:

        /// Contructor
        Outline();

        /// Copy constructor.
        Outline(const Outline& copy, const osg::CopyOp& op = 
osg::CopyOp::SHALLOW_COPY) : Effect(copy, op) {
            _width = copy._width;
            _color = copy._color;
            _fixedTechnique = copy._fixedTechnique;
            _shaderTechnique = copy._shaderTechnique;
            _program = copy._program;
            _colorUnifName = copy._colorUnifName;
        }

        // Effect class info
        META_Effect(osgFX, Outline, "Outline",
                    "Stencil buffer based object outline effect.\n"
                    "This effect needs a properly setup stencil buffer.",
                    "Ulrich Hertlein");


        float width() const { return _width; }
        void setWidth(float width);

        osg::Vec4 color() const { return _color; }
        void setColor(const osg::Vec4& color);

        osg::Program *program() const { return _program; }
        std::string colorUnifName() const { return _colorUnifName; }
        void setProgram(osg::Program *program, const std::string& 
colorUnifName);

    protected:
        virtual ~Outline();

        virtual bool define_techniques() override;

    private:

        class ShaderOutlineTechnique;
        ShaderOutlineTechnique *_shaderTechnique;

        class FixedOutlineTechnique;
        FixedOutlineTechnique *_fixedTechnique;

        float _width;
        osg::Vec4 _color;
        osg::ref_ptr<osg::Program> _program;
        std::string _colorUnifName;
    };

}

#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/Texture1D>


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


namespace osgFX
{

    class Outline::ShaderOutlineTechnique : public osgFX::Technique
    {
    public:
        /// Constructor.
        ShaderOutlineTechnique() : Technique(),
            _lineWidth(), _width(2),
            _matColorUnif(), _color(1,1,1,1) {
        }

        META_Technique(
                "ShaderOutlineTechnique",
                "Two-pass technique, requires ARB_vertex_shader and 
ARB_fragment_shader."
                )

        void getRequiredExtensions(std::vector<std::string>& extensions) const
        {
            extensions.push_back("GL_ARB_vertex_shader");
            extensions.push_back("GL_ARB_fragment_shader");
        }



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

        /// Set outline width.
        void setWidth(float w) {
            _width = w;
            if (_lineWidth.valid()) {
                _lineWidth->setWidth(w);
            }
        }

        /// Set outline color.
        void setColor(const osg::Vec4& color) {
            _color = color;
            if (_matColorUnif.valid()) {
                _matColorUnif->set(_color);
            }
        }

        void setProgram(osg::Program *program, const std::string& 
colorUnifName) {
            _program = program;
            _colorUnifName = colorUnifName;
            if (_matColorUnif.valid()) {
                _matColorUnif = new osg::Uniform(colorUnifName.c_str(), _color);
                dirtyPasses();
            }
        }

    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, ~0u);
                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, ~0u);
                stencil->setOperation(osg::Stencil::KEEP,
                                      osg::Stencil::KEEP,
                                      osg::Stencil::REPLACE);
                state->setAttributeAndModes(stencil, Override_On);

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

                // draw back-facing polygon lines
                osg::PolygonMode* polyMode = new osg::PolygonMode;
                polyMode->setMode(osg::PolygonMode::FRONT_AND_BACK, 
osg::PolygonMode::LINE);
                state->setAttributeAndModes(polyMode, Override_On);

                // outline width
                _lineWidth = new osg::LineWidth;
                setWidth(_width);
                state->setAttributeAndModes(_lineWidth.get(), Override_On);

                // outline program
                if (!_program) {
                    const char *vertex_shader =
                            "#version 330\n"
                            "in vec4 osg_Vertex;\n"
                            "uniform mat4 osg_ModelViewProjectionMatrix;\n"

                            "void main(void)\n"
                            "{\n"
                            "    gl_Position = osg_ModelViewProjectionMatrix * 
osg_Vertex;\n"
                            "}\n";
                    const char *fragment_shader =
                            "#version 330\n"
                            "uniform vec4 un_matColor;\n"
                            "out vec4 out_fragColor;\n"

                            "void main(void)\n"
                            "{\n"
                            "    out_fragColor = un_matColor;\n"
                            "}\n";
                    _program = new osg::Program;
                    osg::ref_ptr<osg::Shader> vs = new 
osg::Shader(osg::Shader::VERTEX, vertex_shader);
                    osg::ref_ptr<osg::Shader> fs = new 
osg::Shader(osg::Shader::FRAGMENT, fragment_shader);
                    _program->addShader(vs.get());
                    _program->addShader(fs.get());
                    _colorUnifName = "un_matColor";
                }
                state->setAttributeAndModes(_program.get(), Override_On);

                // outline color/material
                _matColorUnif = new osg::Uniform(_colorUnifName.c_str(), 
_color);
                state->addUniform(_matColorUnif.get(), Override_On);

                // disable modes
                state->setMode(GL_BLEND, 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 width.
        osg::ref_ptr<osg::LineWidth> _lineWidth;
        float _width;

        /// Outline Material.
        osg::ref_ptr<osg::Uniform> _matColorUnif;
        osg::Vec4 _color;

        /// Outline Program
        osg::ref_ptr<osg::Program> _program;
        std::string _colorUnifName;
    };



    class Outline::FixedOutlineTechnique : public osgFX::Technique
    {
    public:
        /// Constructor.
        FixedOutlineTechnique() : Technique(),
            _lineWidth(), _width(2),
            _material(), _color(1,1,1,1) {
        }


        META_Technique(
                "FixedOutlineTechnique",
                "Two-pass technique, using old fixed function pipeline"
                )


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

        /// Set outline width.
        void setWidth(float w) {
            _width = w;
            if (_lineWidth.valid()) {
                _lineWidth->setWidth(w);
            }
        }

        /// Set outline color.
        void setColor(const osg::Vec4& color) {
            _color = color;
            if (_material.valid()) {
                const osg::Material::Face face = osg::Material::FRONT_AND_BACK;
                _material->setAmbient(face, osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
                _material->setDiffuse(face, osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
                _material->setSpecular(face, osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
                _material->setEmission(face, color);
            }
        }

    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, ~0u);
                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, ~0u);
                stencil->setOperation(osg::Stencil::KEEP,
                                      osg::Stencil::KEEP,
                                      osg::Stencil::REPLACE);
                state->setAttributeAndModes(stencil, Override_On);

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

                // draw back-facing polygon lines
                osg::PolygonMode* polyMode = new osg::PolygonMode;
                polyMode->setMode(osg::PolygonMode::BACK, 
osg::PolygonMode::LINE);
                state->setAttributeAndModes(polyMode, Override_On);

                // outline width
                _lineWidth = new osg::LineWidth;
                setWidth(_width);
                state->setAttributeAndModes(_lineWidth.get(), Override_On);

                // outline color/material
                _material = new osg::Material;
                _material->setColorMode(osg::Material::OFF);
                setColor(_color);
                state->setAttributeAndModes(_material.get(), Override_On);

                // disable modes
                state->setMode(GL_BLEND, 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 width.
        osg::ref_ptr<osg::LineWidth> _lineWidth;
        float _width;

        /// Outline Material.
        osg::ref_ptr<osg::Material> _material;
        osg::Vec4 _color;
    };




    Outline::Outline() :
        _shaderTechnique(0), _fixedTechnique(0),
        _width(2.f), _color(0, 0, 0, 1),
        _program(), _colorUnifName()
    {
    }

    void Outline::setWidth(float w)
    {
        _width = w;
        if (_shaderTechnique) {
            _shaderTechnique->setWidth(w);
        }
        if (_fixedTechnique) {
            _fixedTechnique->setWidth(w);
        }
    }

    void Outline::setColor(const osg::Vec4& color)
    {
        _color = color;
        if (_shaderTechnique) {
            _shaderTechnique->setColor(color);
        }
        if (_fixedTechnique) {
            _fixedTechnique->setColor(color);
        }
    }

    void Outline::setProgram(osg::Program *program, const std::string 
&colorUnifName)
    {
        _program = program;
        _colorUnifName = colorUnifName;
        if (_shaderTechnique) {
            _shaderTechnique->setProgram(program, colorUnifName);
        }
        else {
            dirtyTechniques();
        }
    }

    Outline::~Outline()
    {

    }

    bool Outline::define_techniques()
    {
        _fixedTechnique = 0;

        _shaderTechnique = new ShaderOutlineTechnique;
        addTechnique(_shaderTechnique);

#if !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
        _fixedTechnique = new FixedOutlineTechnique;
        addTechnique(_fixedTechnique);
#endif

        setWidth(_width);
        setColor(_color);
        setProgram(_program.get(), _colorUnifName);

        return true;
    }

}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to