Hi Antiro,

I've cleaned up the example (removed the image mod, hdr etc.) and supplied vertex shaders (once you move towards aliasing, you basically need to replace ALL fixed function stuff).

You were right about the viewer.realize before setting up the aliasing however. This is due the the context not being available before
realizing it.


(Some additonal notes: you don't need to use texture rectangle. Instead in deferred steps simply use texelFetch in conjunction with textureSize on Texture2D targets.
)


Below you find the adapted example, giving the desired result:
#include <osg/GLExtensions>
#include <osg/Node>
#include <osg/Geometry>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/Texture2D>
#include <osg/TextureRectangle>
#include <osg/ColorMask>
#include <osg/Material>
#include <osg/Capability>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>

#include <osgViewer/Viewer>

#include <iostream>
#include <stdio.h>

#include <osg/PolygonMode>

static std::string vertex_shader =
{
        "#version 330\n"
        "layout(location = 0) in vec4 osg_Vertex;  \n"
        "layout(location = 1) in vec3 osg_Normal;  \n"
        "layout(location = 2) in vec4 osg_Color;   \n"
        "layout(location = 3) in vec4 osg_MultiTexCoord0; \n"
        "uniform mat4 osg_ModelViewProjectionMatrix; \n"
        "out vec2 texture_coords;"
        "void main(void) \n"
        "{ \n"
                "texture_coords = osg_MultiTexCoord0.st;\n"
        "  gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n"
        "}\n"
};

static std::string def_frag_shader =
{
        "#version 330\n"
        "uniform sampler2DRect textureID0;\n"

        "in vec2 texture_coords;"
        "out vec4 target;"
        "void main(void)\n"
        "{\n"
        "    target = vec4(texture( textureID0, texture_coords.st ).rgb, 1);  
\n"
        "}\n"
};

osg::Geode *createScreenQuad(float width,
        float height,
        float scale,
        osg::Vec3 corner)
{
        osg::Geometry* geom = osg::createTexturedQuadGeometry(
                corner,
                osg::Vec3(width, 0, 0),
                osg::Vec3(0, height, 0),
                0,
                0,
                scale,
                scale);
        osg::ref_ptr<osg::Geode> quad = new osg::Geode;
        quad->addDrawable(geom);
        int values = osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED;
        quad->getOrCreateStateSet()->setAttribute(
                new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,
                        osg::PolygonMode::FILL),
                values);
        quad->getOrCreateStateSet()->setMode(GL_LIGHTING, values);
        return quad.release();
}


osg::Camera *createHUDCamera(double left = 0,
        double right = 1,
        double bottom = 0,
        double top = 1)
{
        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
        camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
        camera->setClearMask(GL_DEPTH_BUFFER_BIT);
        camera->setRenderOrder(osg::Camera::POST_RENDER);
        camera->setAllowEventFocus(false);
camera->setProjectionMatrix(osg::Matrix::ortho2D(left, right, bottom, top)); camera->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
        return camera.release();
}

osg::ref_ptr<osg::Camera> createTextureDisplayQuad(
        const osg::Vec3 &pos,
        osg::StateAttribute *tex,
        float scale,
        float width = 0.3,
        float height = 0.2)
{
        osg::ref_ptr<osg::Camera> hc = createHUDCamera();
        hc->addChild(createScreenQuad(width, height, scale, pos));
        hc->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex);
        //need shader!!
        
        osg::ref_ptr<osg::Program> program = new osg::Program;
osg::ref_ptr<osg::Shader> vshader = new osg::Shader(osg::Shader::VERTEX, vertex_shader); osg::ref_ptr<osg::Shader> fshader = new osg::Shader(osg::Shader::FRAGMENT, def_frag_shader);
        program->addShader(vshader.get());
        program->addShader(fshader.get());
hc->getOrCreateStateSet()->setAttributeAndModes(program.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

        return hc;
}


#define NUM_TEXTURES 2

// The quad geometry is used by the render to texture camera to generate multiple textures. osg::Group* createRTTQuad(unsigned int tex_width, unsigned int tex_height, bool useHDR)
{
        osg::Group *top_group = new osg::Group;

        osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;

osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
                                                                                
                                                   // counter-clockwise
        quad_coords->push_back(osg::Vec3d(0, 0, -1));
        quad_coords->push_back(osg::Vec3d(1, 0, -1));
        quad_coords->push_back(osg::Vec3d(1, 1, -1));
        quad_coords->push_back(osg::Vec3d(0, 1, -1));

osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
        quad_tcoords->push_back(osg::Vec2(0, 0));
        quad_tcoords->push_back(osg::Vec2(tex_width, 0));
        quad_tcoords->push_back(osg::Vec2(tex_width, tex_height));
        quad_tcoords->push_back(osg::Vec2(0, tex_height));

        osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4);

        osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
        quad_colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));

        quad_geom->setVertexArray(quad_coords.get());
        quad_geom->setTexCoordArray(0, quad_tcoords.get());
        quad_geom->addPrimitiveSet(quad_da.get());
        quad_geom->setColorArray(quad_colors.get(), osg::Array::BIND_OVERALL);

        osg::StateSet *stateset = quad_geom->getOrCreateStateSet();
        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

        stateset->addUniform(new osg::Uniform("width", (int)tex_width));

// Attach shader, glFragData is used to create data for multiple render targets

        {
                static const char *shaderSource = {
                        "uniform int width;"
                        "void main(void)\n"
                        "{\n"
                        "    gl_FragData[0] = vec4(1,0,0,1);\n"
                        "    gl_FragData[1] = vec4(0,1,0,1);\n"
                        "    gl_FragData[2] = vec4(0,0,1,1);\n"
                        "    gl_FragData[3] = vec4(0,0,1,1);\n"
                        "}\n"
                };

osg::ref_ptr<osg::Shader> fshader = new osg::Shader(osg::Shader::FRAGMENT, shaderSource);
                osg::ref_ptr<osg::Program> program = new osg::Program;
osg::ref_ptr<osg::Shader> vshader = new osg::Shader(osg::Shader::VERTEX, vertex_shader);
                program->addShader(vshader.get());

                program->addShader(fshader.get());
stateset->setAttributeAndModes(program.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
        }

        quad_geode->addDrawable(quad_geom.get());

        top_group->addChild(quad_geode.get());

        return top_group;
}


osg::TextureRectangle* textureRect[NUM_TEXTURES] = { 0,0 }; //moved to global scope to easily view intermediate textures // Here a scene consisting of a single quad is created. This scene is viewed by the screen camera. // The quad is textured using a shader and the multiple textures generated in the RTT stage. osg::Node* createScene(osg::Node* cam_subgraph, unsigned int tex_width, unsigned int tex_height, bool useHDR, bool useImage, bool useMultiSample)
{
        if (!cam_subgraph) return 0;

        // create a group to contain the quad and the pre render camera.
        osg::Group* parent = new osg::Group;

        // textures to render to and to use for texturing of the final quad
        //osg::TextureRectangle* textureRect[NUM_TEXTURES] = {0,0,0,0};

        for (int i = 0; i < NUM_TEXTURES; i++)
        {
                textureRect[i] = new osg::TextureRectangle;
                textureRect[i]->setTextureSize(tex_width, tex_height);
                textureRect[i]->setInternalFormat(GL_RGBA);
textureRect[i]->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); textureRect[i]->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
        }

        // first create the geometry of the quad
        {
                osg::Geometry* polyGeom = new osg::Geometry();

                polyGeom->setSupportsDisplayList(false);

                osg::Vec3Array* vertices = new osg::Vec3Array;
                osg::Vec2Array* texcoords = new osg::Vec2Array;

                vertices->push_back(osg::Vec3d(0, 0, 0));
                texcoords->push_back(osg::Vec2(0, 0));

                vertices->push_back(osg::Vec3d(1, 0, 0));
                texcoords->push_back(osg::Vec2(tex_width, 0));

                vertices->push_back(osg::Vec3d(1, 0, 1));
                texcoords->push_back(osg::Vec2(tex_width, tex_height));

                vertices->push_back(osg::Vec3d(0, 0, 1));
                texcoords->push_back(osg::Vec2(0, tex_height));

                polyGeom->setVertexArray(vertices);
                polyGeom->setTexCoordArray(0, texcoords);

                osg::Vec4Array* colors = new osg::Vec4Array;
                colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
                polyGeom->setColorArray(colors, osg::Array::BIND_OVERALL);

polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));

                // now we need to add the textures (generated by RTT) to the 
Drawable.
                osg::StateSet* stateset = new osg::StateSet;
                for (int i = 0; i < NUM_TEXTURES; i++) {
stateset->setTextureAttributeAndModes(i, textureRect[i], osg::StateAttribute::ON);
                }

                polyGeom->setStateSet(stateset);
        
                // Attach a shader to the final quad to combine the input 
textures.
                {
                        static const char *shaderSource = {
                                "#version 330\n"
                                "uniform sampler2DRect textureID0;\n"
                                "uniform sampler2DRect textureID1;\n"
                                "uniform sampler2DRect textureID2;\n"
                                "uniform sampler2DRect textureID3;\n"

                                "in vec2 texture_coords;"
                                "void main(void)\n"
                                "{\n"
                                "    gl_FragData[0] = \n"
" vec4(texture2DRect( textureID0, texture_coords.st ).rgb, 1) + \n" " vec4(texture2DRect( textureID1, texture_coords.st ).rgb, 1) + \n" " vec4(texture2DRect( textureID2, texture_coords.st ).rgb, 1) + \n" " -0.5*vec4(texture2DRect( textureID3, texture_coords.st ).rgb, 1); \n"
                                "}\n"
                        };
osg::ref_ptr<osg::Shader> fshader = new osg::Shader(osg::Shader::FRAGMENT, shaderSource);
                        osg::ref_ptr<osg::Program> program = new osg::Program;
osg::ref_ptr<osg::Shader> vshader = new osg::Shader(osg::Shader::VERTEX, vertex_shader);
                        program->addShader(vshader.get());

                        program->addShader(fshader.get());
stateset->setAttributeAndModes(program.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

                }

                stateset->addUniform(new osg::Uniform("textureID0", 0));
                stateset->addUniform(new osg::Uniform("textureID1", 1));
                stateset->addUniform(new osg::Uniform("textureID2", 2));
                stateset->addUniform(new osg::Uniform("textureID3", 3));

                //stateset->setDataVariance(osg::Object::DYNAMIC);

                osg::Geode* geode = new osg::Geode();
                geode->addDrawable(polyGeom);

                parent->addChild(geode);
        }

        // now create the camera to do the multiple render to texture
        {
                osg::Camera* camera = new osg::Camera;

                // set up the background color and clear mask.
                camera->setClearColor(osg::Vec4(0.1f, 0.1f, 0.3f, 1.0f));
                camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                // the camera is going to look at our input quad
                camera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1, 0, 1));
                camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
                camera->setViewMatrix(osg::Matrix::identity());

                // set viewport
                camera->setViewport(0, 0, tex_width, tex_height);

                // set the camera to render before the main camera.
                camera->setRenderOrder(osg::Camera::PRE_RENDER);

                // tell the camera to use OpenGL frame buffer objects
                
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);

                // attach the textures to use
                for (int i = 0; i < NUM_TEXTURES; i++) {
camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0 + i), textureRect[i]);
                }




                // add the subgraph to render
                camera->addChild(cam_subgraph);

                parent->addChild(camera);
        }

        return parent;
}

int main(int argc, char **argv)
{
        // use an ArgumentParser object to manage the program arguments.
        osg::ArgumentParser arguments(&argc, argv);
                
        // construct the viewer.
        osgViewer::Viewer viewer(arguments);

        unsigned tex_width = 512;
        unsigned tex_height = 512;
        
        
        osg::Group* subGraph = createRTTQuad(tex_width, tex_height, false);

        osg::Group* rootNode = new osg::Group();
rootNode->addChild(createScene(subGraph, tex_width, tex_height, false, false, false));

rootNode->addChild(createScene(subGraph, tex_width, tex_height, false, false, false));


        //Some code to view the intermediate textures
        osg::ref_ptr<osg::Camera> testTex =
                createTextureDisplayQuad(osg::Vec3(0, 0.7, 0),
                        textureRect[0],
                        tex_width);
        osg::ref_ptr<osg::Camera> testTex2 =
                createTextureDisplayQuad(osg::Vec3(0, 0.35, 0),
                        textureRect[1],
                        tex_width);

        rootNode->addChild(testTex);
        rootNode->addChild(testTex2);

        // add model to the viewer.
        viewer.setSceneData(rootNode);
        viewer.realize();
        
viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);
        
viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);

        return viewer.run();
}

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

Reply via email to