OpenSceneGraph Forum Forum Index OpenSceneGraph Forum
Official forum which mirrors the existent OSG mailing lists. Messages posted here are forwarded to the mailing list and vice versa.
 
   FAQFAQ    SearchSearch    MemberlistMemberlist    RulesRules    UsergroupsUsergroups    RegisterRegister 
 Mail2Forum SettingsMail2Forum Settings  ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
   AlbumAlbum  OpenSceneGraph IRC ChatOpenSceneGraph IRC Chat   SmartFeedSmartFeed 

using modern shaders with osg - setting vertex attribute layout

Goto page 1, 2  Next
 
Post new topic   Reply to topic    OpenSceneGraph Forum Forum Index -> General
View previous topic :: View next topic  
Author Message
antiro42
User


Joined: 01 Sep 2017
Posts: 40

PostPosted: Fri Sep 01, 2017 9:30 am    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi,

I am converting a project written in pure opengl to use OSG to improve compatibility and reduce maintenance. The original project used a deferred rendering pipeline with a pretty big set of custom shaders. I would like to reuse these shaders with minimum adjustments.

In order to do this I want to use the same uniform names and the same layout for the VAO. I figured out that I can add callbacks to set the ModelView / Projection / etc matrices to uniforms with the same names as used in in the shaders, so that is taken care of.

I do however not know how to specify the vertex attribute layout. My shaders all start with the following:
#version 330 core //so can't use gl_Normal etc
layout(location = 0) in vec3 position
layout(location = 1) in vec3 normal
layout(location = 2) in vec2 texCoords
layout(location = ....

I'm currently just using osgDB::readNodeFile() to read in the geometry and I'm assuming I need to do something more sophisticated to control how the vertex attributes are organized, but have been unable to figure out what.

If anyone could point me in the right direction, that would be most helpful!


Thank you!

Cheers,
antiro
Back to top
View user's profile Send private message
SMesserschmidt (Sebastian Messerschmidt)
Forum Moderator


Joined: 10 Sep 2013
Posts: 796

PostPosted: Fri Sep 01, 2017 9:48 am    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi Antiro,

Quote:
Hi,

I am converting a project written in pure opengl to use OSG to improve compatibility and reduce maintenance. The original project used a deferred rendering pipeline with a pretty big set of custom shaders. I would like to reuse these shaders with minimum adjustments.

In order to do this I want to use the same uniform names and the same layout for the VAO. I figured out that I can add callbacks to set the ModelView / Projection / etc matrices to uniforms with the same names as used in in the shaders, so that is taken care of.

I do however not know how to specify the vertex attribute layout. My shaders all start with the following:
#version 330 core //so can't use gl_Normal etc
layout(location = 0) in vec3 position
layout(location = 1) in vec3 normal
layout(location = 2) in vec2 texCoords
layout(location = ....

I'm currently just using osgDB::readNodeFile() to read in the geometry and I'm assuming I need to do something more sophisticated to control how the vertex attributes are organized, but have been unable to figure out what.

If anyone could point me in the right direction, that would be most helpful!

The easiest way is to convert the shaders to use the osg_ -prefix and to
turn on the vertex attribute aliasing (basically all OSG will provide
all gl_ inputs)

A list:

//OSG inputs
layout(location = 0) in vec4 osg_Vertex;
layout(location = 1) in vec3 osg_Normal;
layout(location = 2) in vec4 osg_Color;
layout(location = 3)in vec4 osg_MultiTexCoord0;
layout(location = 4)in vec4 osg_MultiTexCoord1;
layout(location = 5)in vec4 osg_MultiTexCoord2;
layout(location = 6)in vec4 osg_MultiTexCoord3;
layout(location = 7)in vec4 osg_MultiTexCoord4;
layout(location = 8)in vec4 osg_MultiTexCoord5;
layout(location = 9)in vec4 osg_MultiTexCoord6;
layout(location = 10)in vec4 osg_MultiTexCoord7;


In order to turn on aliasing:

viewer->getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);
viewer->getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);

Note, that the first line will set up the gl_XYZMatrix aliases, so no
need for a custom callback for this (at least for the std-matrices)

So you get these:
uniform mat4 osg_ModelViewProjectionMatrix;
uniform mat4 osg_ModelViewMatrix;
uniform mat4 osg_ViewMatrixInverse;
uniform mat3 osg_NormalMatrix;
uniform mat4 osg_ViewMatrix;
etc.

Cheers
Sebastian


Quote:


Thank you!

Cheers,
antiro

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71584#71584









------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
antiro42
User


Joined: 01 Sep 2017
Posts: 40

PostPosted: Fri Sep 01, 2017 10:13 am    Post subject:
Reply with quote

Hi Sebastian,

Thanks for the quick response. The osg_XXX matrices work perfectly. The setUseVertexAttributeAliasing() however does not seem to work. Where I had some output before, now don't get anything with it enabled

Does osg always give the exact layout which you posted? or is this dependent on the data that is loaded?

for refence, here is a stripped down version of a geometry pass which I'm currently testing with (all 3 outputs are black with the attributeAliasing turned on):

Code:
#version 330 core
layout (location = 0) in vec4 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec4 color;
layout (location = 3) in vec4 texCoords;

/*OSG input layout
layout(location = 0) in vec4 osg_Vertex;
layout(location = 1) in vec3 osg_Normal;
layout(location = 2) in vec4 osg_Color;
layout(location = 3)in vec4 osg_MultiTexCoord0;
layout(location = 4)in vec4 osg_MultiTexCoord1;*/

out vec3 Normal;
out vec2 TexCoords;
out vec3 WorldPos;

uniform mat4 osg_ModelViewMatrix;
uniform mat3 osg_NormalMatrix;
uniform mat4 osg_ProjectionMatrix;


void main()
{
    gl_Position = osg_ProjectionMatrix * osg_ModelViewMatrix * position;
    WorldPos = (osg_ModelViewMatrix * position).xyz;
    Normal = osg_NormalMatrix * normal;
    TexCoords = texCoords.xy;
}


and the fragment shader:
Code:
#version 330

in vec2 TexCoords;
in vec3 Normal;
in vec3 WorldPos;

layout (location = 0) out vec3 gWorldPos;
layout (location = 1) out vec4 gColorSpec;
layout (location = 2) out vec3 gNormalOut;

uniform vec3 gDiffuseColor=vec3(1,0,0);

void main()
{
    gWorldPos = WorldPos;
    gColorSpec.rgb=gDiffuseColor;
    gNormalOut = normalize(Normal);
}


For the actual creation and compilation of the shader program I'm using the EffectCompositor recipe from the OSG cookbook.

Thank you!

Cheers,
antiro[/code]
Back to top
View user's profile Send private message
SMesserschmidt (Sebastian Messerschmidt)
Forum Moderator


Joined: 10 Sep 2013
Posts: 796

PostPosted: Fri Sep 01, 2017 10:32 am    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi Antiro,> Hi Sebastian,
Quote:

Thanks for the quick response. The osg_XXX matrices work perfectly. The setUseVertexAttributeAliasing() however does not seem to work. Where I had some output before, now don't get anything with it enabled

Does osg always give the exact layout which you posted? or is this dependent on the data that is loaded?

for refence, here is a stripped down version of a geometry pass which I'm currently testing with (all 3 outputs are black with the attributeAliasing turned on):



Your code doesn't use the osg_ prefixed aliases at all. You really need
to make the name and slot match...

Cheers
Sebastian


------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
antiro42
User


Joined: 01 Sep 2017
Posts: 40

PostPosted: Fri Sep 01, 2017 10:56 am    Post subject:
Reply with quote

Hi Sebastian,

I was under the impression that the "layout(...) in ..." command was essentially a variable declaration and that hence only the location and type needed to match. I now also changed the name, this does not seem to have any effect though..

new vertex shader code:
Code:
#version 330 core
layout(location = 0) in vec4 osg_Vertex;
layout(location = 1) in vec3 osg_Normal;
layout(location = 2) in vec4 osg_Color;
layout(location = 3)in vec4 osg_MultiTexCoord0;
layout(location = 4)in vec4 osg_MultiTexCoord1;
layout(location = 5)in vec4 osg_MultiTexCoord2;
layout(location = 6)in vec4 osg_MultiTexCoord3;
layout(location = 7)in vec4 osg_MultiTexCoord4;
layout(location = 8)in vec4 osg_MultiTexCoord5;
layout(location = 9)in vec4 osg_MultiTexCoord6;
layout(location = 10)in vec4 osg_MultiTexCoord7;

out vec3 Normal;
out vec2 TexCoords;
out vec3 WorldPos;

uniform mat4 osg_ModelViewMatrix;
uniform mat3 osg_NormalMatrix;
uniform mat4 osg_ProjectionMatrix;


void main()
{
    gl_Position = osg_ProjectionMatrix * osg_ModelViewMatrix * osg_Vertex;
    WorldPos = (osg_ModelViewMatrix * osg_Vertex).xyz;
    Normal = osg_NormalMatrix * osg_Normal;
    TexCoords = osg_MultiTexCoord0.xy;

}


If I use the shader without the UseVertexAttributeAliasing enabled I see red silhouettes for the different models, when looking at the normals texture output (as if all normals are <1,0,0> ), which I expect is caused by the shader reading wrong on unitialized attributes.

with UseVertexAttributeAliasing enabled I get no output.



Thank you!

Cheers,
antiro
Back to top
View user's profile Send private message
SMesserschmidt (Sebastian Messerschmidt)
Forum Moderator


Joined: 10 Sep 2013
Posts: 796

PostPosted: Fri Sep 01, 2017 1:28 pm    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi Antiro,

I don't have an idea why it is not working.
For which camera's state set did you enable it?
Have you tried to check this with a simplistic non-MRT/FBO setup?
Which OSG-Version do you use (its working with 3.4.x definitively)

I've been using this for years, so there must be some error somewhere else.

Cheers
Sebastian
Quote:
Hi Sebastian,

I was under the impression that the "layout(...) in ..." command was essentially a variable declaration and that hence only the location and type needed to match. I now also changed the name, this does not seem to have any effect though..

new vertex shader code:

Code:
#version 330 core
layout(location = 0) in vec4 osg_Vertex;
layout(location = 1) in vec3 osg_Normal;
layout(location = 2) in vec4 osg_Color;
layout(location = 3)in vec4 osg_MultiTexCoord0;
layout(location = 4)in vec4 osg_MultiTexCoord1;
layout(location = 5)in vec4 osg_MultiTexCoord2;
layout(location = 6)in vec4 osg_MultiTexCoord3;
layout(location = 7)in vec4 osg_MultiTexCoord4;
layout(location = 8)in vec4 osg_MultiTexCoord5;
layout(location = 9)in vec4 osg_MultiTexCoord6;
layout(location = 10)in vec4 osg_MultiTexCoord7;

out vec3 Normal;
out vec2 TexCoords;
out vec3 WorldPos;

uniform mat4 osg_ModelViewMatrix;
uniform mat3 osg_NormalMatrix;
uniform mat4 osg_ProjectionMatrix;


void main()
{
gl_Position = osg_ProjectionMatrix * osg_ModelViewMatrix * osg_Vertex;
WorldPos = (osg_ModelViewMatrix * osg_Vertex).xyz;
Normal = osg_NormalMatrix * osg_Normal;
TexCoords = osg_MultiTexCoord0.xy;

}



If I use the shader without the UseVertexAttributeAliasing enabled I see red silhouettes for the different models, when looking at the normals texture output (as if all normals are <1,0,0> ), which I expect is caused by the shader reading wrong on unitialized attributes.

with UseVertexAttributeAliasing enabled I get no output.



Thank you!

Cheers,
antiro

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71588#71588









------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
antiro42
User


Joined: 01 Sep 2017
Posts: 40

PostPosted: Fri Sep 01, 2017 2:10 pm    Post subject:
Reply with quote

Hi Sebastian,

I'm using the latest stable version from git (which is indeed 3.4.something).
I applied it to the camera of the viewer. Should I have also changed the state of the camera's which are used to render to the textures (they are part of the scenegraph of the viewer)?

After trying every imaginable change the shaders I've started to suspect that that there is something wrong with (my usage of) the EffectCompositor recipe from the OSG Cookbook, which I'm using to load the shaders and compile the shader program. Hence I'm now changing the code to create the osg::Program and load the osg::Shaders manually.



Thank you!

Cheers,
antiro
Back to top
View user's profile Send private message
SMesserschmidt (Sebastian Messerschmidt)
Forum Moderator


Joined: 10 Sep 2013
Posts: 796

PostPosted: Fri Sep 01, 2017 2:17 pm    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi Antiro,

I'd start of with a simple viewer that simply adds the aliasing and adds
a shader. If the problem remains, we could try to take a look into the
minimal example.

Cheers
Sebastian
Quote:
Hi Sebastian,

I'm using the latest stable version from git (which is indeed 3.4.something).
I applied it to the camera of the viewer. Should I have also changed the state of the camera's which are used to render to the textures (they are part of the scenegraph of the viewer)?

After trying every imaginable change the shaders I've started to suspect that that there is something wrong with (my usage of) the EffectCompositor recipe from the OSG Cookbook, which I'm using to load the shaders and compile the shader program. Hence I'm now changing the code to create the osg::Program and load the osg::Shaders manually.



Thank you!

Cheers,
antiro

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71591#71591









------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
ckuliukas
User


Joined: 22 Nov 2014
Posts: 32

PostPosted: Sat Sep 02, 2017 2:40 am    Post subject:
Reply with quote

I'm also transitioning a legacy GL OSG project with a mix of custom shaders to modern GL bit by bit. And I've also had lots of trouble and headache with the built-in modern GL vertex attrib aliasing setting.

It seems crazy that the official advice is to write shaders and use OSG just like legacy GL, and OSG will then change your shader code and reinterpret deprecated calls to make it work via "modern" GL: Obviously in years to come when GL newcomers want to use OSG the official line can't be "learn how GL was 20 years ago, write your OSG code like that, and the system will make it work".

So I'm afraid this isn't as simple as it could be, but of course it's still easier than converting raw GL calls..


Here is my only advice since I'm not yet finished myself:

My recommendation is just leave that attrib aliasing setting alone; you can use modern GL anyway. Just make sure that you use the setVertexAttribute() calls instead of setTextureCoords() / setNormals() / etc, and use the same attrib location numbering convention as OSG (I believe NVidia's drivers enforce those conventions, so you can get the vertex positions at loc=0).

Then you'll want to get a copy of the ShaderGen class so you can customize because you'll likely want to modify it yourself. You can use this code to hook into osgDB::readNode()'s behavior to setup your shaders/attribs/etc the way you want.

You then need to set useModelViewUniforms, which seems to be less harmful than useVertexAttribAliasing and will make sure osg_ModelViewMatrix is set.


Interested to compare notes on how you go anyway

_________________
http://www.hrwallingford.com/facilities/ship-simulation-centre
Back to top
View user's profile Send private message
antiro42
User


Joined: 01 Sep 2017
Posts: 40

PostPosted: Sat Sep 02, 2017 10:25 am    Post subject:
Reply with quote

Hi,

When using the shaders to render only one of color/normal/position to a normal viewer/camera (not to a texture) they all seem to work.

I continued to modify a small MRT example which used older shader code which relied on gl_Vertex / gl_Normal etc. The moment I added a setUseVertexAttributeAliasing(true) it stopped working even with changes to the shader which replaced gl_Vertex with osg_Vertex etc.

I could not find any MRT / deferred rendering code online which uses more modern glsl and setUseVertexAttributeAliasing(true).

<b>My main question now is</b>: Do you (or anyone else) happen to have some example code for multi-target rendering which uses setUseVertexAttributeAliasing(true) ?

In response to ckuliukas: Is that really the official advice? My other project was already using modern GLSL and can't be converted back to ancient glsl easily (nor do I want to). Perhaps I'll have a look at your suggestion if all else fails. I'm still hoping I can reuse the existing shaders with minimal changes.

In general my experience with OSG is that the code is well organized and pretty easy to read, however there is a real lack of documentation, both with regards to comments in the code and in the form of an (up to date) wiki / manual / etc. I don't mind a learning curve, but I have no idea where to start. Reading through the osg quick start guide didn't get me anywhere and the few recipes in the OSG cookbook which touched upon more advanced opengl using shaders were using ancient GLSL code. If anyone has some advice with regards to other learning resources focussed on more advanced usage that would be very helpful.

Thanks in advance!

Cheers,
antiro
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 11238

PostPosted: Sat Sep 02, 2017 11:42 am    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi Chris,
On 2 September 2017 at 03:40, Chris Kuliukas < (
Only registered users can see emails on this board!
Get registred or enter the forums!
)> wrote:
Quote:
It seems crazy that the official advice is to write shaders and use OSG just like legacy GL, and OSG will then change your shader code and reinterpret deprecated calls to make it work via "modern" GL: Obviously in years to come when GL newcomers want to use OSG the official line can't be "learn how GL was 20 years ago, write your OSG code like that, and the system will make it work".


No one has suggested you should learn how GL was 20  years ago.  Pure BS. Please leave such nonsense off the list/forum as it doesn't help anyone.


What has been suggested is that the OSG's management of mdelview and projection matrices works well for both fixed function and shaders, the OSG is a scene graph it does lots of helpful stuff for application developers, one of these useful things is it's management of modelview and projection matrices.


If you are fighting against this design that doesn't fit with your preconceptions then this is likely why you are struggling.  Once you stop trying to fit the OSG around think it should work and leverage it's power then things should be easier.


Lots of people use the OSG with shaders and have done for well over a decade - the OSG actually support GLSL even before the ARB officially released it (3DLabs used the OSG as a testbed).  OpenGL has evolved a lot since the early days of GLSL and the OSG with it,  Both continue to evolve.




Robert. 


 

------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
antiro42
User


Joined: 01 Sep 2017
Posts: 40

PostPosted: Sat Sep 02, 2017 3:15 pm    Post subject:
Reply with quote

Hi,

I'm still struggling with getting setUseVertexAttributeAliasing(true) to combine rendering to textures.

To this end, I made made a tiny change to the osgmultiplerendertargets example to see if I could adapt that example to work with setUseVertexAttributeAliasing(true).

Aside from adding some lines to view the intermediate textures, my only change was enabling VertexAttributeAliasing as follows:

Code:
viewer.realize();
viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);


Given that the code only uses some fragment shaders, which use fixed colors and don't rely on things like gl_Vertex or gl_Normal I assumed no changes to them would be needed. Yet enabling VertexAttribute shaders breaks rendering, disabling it again fixes it.

Maybe I'm completely misunderstanding the idea behind VertexAttributeAliasing, all I want is to reuse the shaders from my other project, which requires control over the vertex attribute layout...
If anyone can tell me what I'm doing wrong or has a working example of MRT with setUseVertexAttributeAliasing(true), that would be highly appreciated.

For reference, here is the entire modified code:
Code:

/* OpenSceneGraph example, osgmultiplerendertargets.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

#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 "RenderingUtility.h" //to easily view intermediate textures
//
// Below is relatively straight forward example of using the OpenGL multiple render targets (MRT) extension
// to FrameBufferObjects/GLSL shaders.
//
// Another, more sophisticated MRT example can be found in the osgstereomatch example.
//


// The callback modifies an input image.
struct MyCameraPostDrawCallback : public osg::Camera::DrawCallback
{
    MyCameraPostDrawCallback(osg::Image* image):
        _image(image)
    {
    }

    virtual void operator () (const osg::Camera& /*camera*/) const
    {
        if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_UNSIGNED_BYTE)
        {
            // we'll pick out the center 1/2 of the whole image,
            int column_start = _image->s()/4;
            int column_end = 3*column_start;

            int row_start = _image->t()/4;
            int row_end = 3*row_start;

            // and then halve their contribution
            for(int r=row_start; r<row_end; ++r)
            {
                unsigned char* data = _image->data(column_start, r);
                for(int c=column_start; c<column_end; ++c)
                {
                    (*data) = (*data)/2; ++data;
                    (*data) = (*data)/2; ++data;
                    (*data) = (*data)/2; ++data;
                    (*data) = 255; ++data;
                }
            }

            _image->dirty();
        }
        else if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_FLOAT)
        {
            // we'll pick out the center 1/2 of the whole image,
            int column_start = _image->s()/4;
            int column_end = 3*column_start;

            int row_start = _image->t()/4;
            int row_end = 3*row_start;

            // and then halve their contribution
            for(int r=row_start; r<row_end; ++r)
            {
                float* data = (float*)_image->data(column_start, r);
                for(int c=column_start; c<column_end; ++c)
                {
                    (*data) = (*data)/2.0; ++data;
                    (*data) = (*data)/2.0; ++data;
                    (*data) = (*data)/2.0; ++data;
                    (*data) = 1.0f; ++data;
                }
            }

            _image->dirty();

            //print out the first three values
            float* data = (float*)_image->data(0, 0);
            fprintf(stderr,"Float pixel data: r %e g %e b %e\n", data[0], data[1], data[2]);
        }
    }

    osg::Image* _image;
};

#define NUM_TEXTURES 4

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

    if (useHDR) {
        static const char *shaderSource = {
            "uniform int width;"
            "void main(void)\n"
            "{\n"
            "    gl_FragData[0] = vec4(-1e-12,0,0,1);\n"
            "    gl_FragData[1] = vec4(0,1e-12,0,1);\n"
            "    gl_FragData[2] = vec4(0,0,1e-12,1);\n"
            "    gl_FragData[3] = vec4(0,0,1e-12,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;
        program->addShader(fshader.get());
        stateset->setAttributeAndModes(program.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
    } else {
            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;
        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,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);

        if (useHDR)
        {
            // Default HDR format
            textureRect[i]->setInternalFormat(GL_RGBA32F_ARB);

            // GL_FLOAT_RGBA32_NV might be supported on pre 8-series GPUs
            //textureRect[i]->setInternalFormat(GL_FLOAT_RGBA32_NV);

            // GL_RGBA16F_ARB can be used with this example,
            // but modify e-12 and e12 in the shaders accordingly
            //textureRect[i]->setInternalFormat(GL_RGBA16F_ARB);

            textureRect[i]->setSourceFormat(GL_RGBA);
            textureRect[i]->setSourceType(GL_FLOAT);
        }
    }

    // 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.
        if (useHDR) {
            static const char *shaderSource = {
                "uniform sampler2DRect textureID0;\n"
                "uniform sampler2DRect textureID1;\n"
                "uniform sampler2DRect textureID2;\n"
                "uniform sampler2DRect textureID3;\n"
                "uniform float width;\n"
                "uniform float height; \n"
                "void main(void)\n"
                "{\n"
                "    gl_FragData[0] = \n"
                "     vec4(  -1e12 * texture2DRect( textureID0, gl_TexCoord[0].st ).rgb, 1) + \n"
                "     vec4(   1e12 * texture2DRect( textureID1, gl_TexCoord[0].st ).rgb, 1) + \n"
                "     vec4(   1e12 * texture2DRect( textureID2, gl_TexCoord[0].st ).rgb, 1) + \n"
                "     vec4(-0.5e12 * texture2DRect( textureID3, gl_TexCoord[0].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;
            program->addShader( fshader.get());
            stateset->setAttributeAndModes( program.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
        } else {
            static const char *shaderSource = {
                "uniform sampler2DRect textureID0;\n"
                "uniform sampler2DRect textureID1;\n"
                "uniform sampler2DRect textureID2;\n"
                "uniform sampler2DRect textureID3;\n"
                "void main(void)\n"
                "{\n"
                "    gl_FragData[0] = \n"
                "          vec4(texture2DRect( textureID0, gl_TexCoord[0].st ).rgb, 1) + \n"
                "          vec4(texture2DRect( textureID1, gl_TexCoord[0].st ).rgb, 1) + \n"
                "          vec4(texture2DRect( textureID2, gl_TexCoord[0].st ).rgb, 1) + \n"
                "     -0.5*vec4(texture2DRect( textureID3, gl_TexCoord[0].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;
            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++) {
            if (useMultiSample)
                camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), textureRect[i], 0, 0, false, 4, 4);
            else
                camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), textureRect[i]);


        }

#if 0
        // test for new glEnablei/glDisablei functionality.
        camera->getOrCreateStateSet()->setAttribute(new osg::Enablei(GL_BLEND, 0));
        camera->getOrCreateStateSet()->setAttribute(new osg::Disablei(GL_BLEND, 1));
#endif

        // we can also read back any of the targets as an image, modify this image and push it back
        if (useImage) {
            // which texture to get the image from
            const int tex_to_get = 0;

            osg::Image* image = new osg::Image;
            if (useHDR) {
                image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_FLOAT);
            } else {
                image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
            }

            // attach the image so its copied on each frame.
            camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0 + tex_to_get), image);

            camera->setPostDrawCallback(new MyCameraPostDrawCallback(image));

            // push back the image to the texture
            textureRect[tex_to_get]->setImage(0, image);
        }

        // 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);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " demonstrates the use of multiple render targets (MRT) with frame buffer objects (FBOs). A render to texture (RTT) camera is used to render to four textures using a single shader. The four textures are then combined to texture the viewed geometry.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information.");
    arguments.getApplicationUsage()->addCommandLineOption("--width","Set the width of the render to texture.");
    arguments.getApplicationUsage()->addCommandLineOption("--height","Set the height of the render to texture.");
    arguments.getApplicationUsage()->addCommandLineOption("--image","Render one of the targets to an image, then apply a post draw callback to modify it and use this image to update the final texture. Print some texture values when using HDR.");
    arguments.getApplicationUsage()->addCommandLineOption("--hdr","Use high dynamic range (HDR). Create floating point textures to render to.");

    // construct the viewer.
    osgViewer::Viewer viewer(arguments);

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    unsigned tex_width = 512;
    unsigned tex_height = 512;
    while (arguments.read("--width", tex_width)) {}
    while (arguments.read("--height", tex_height)) {}

    bool useHDR = false;
    while (arguments.read("--hdr")) { useHDR = true; }

    bool useImage = false;
    while (arguments.read("--image")) { useImage = true; }

    bool useMultiSample = false;
    while (arguments.read("--ms")) { useMultiSample = true; }

    osg::Group* subGraph = createRTTQuad(tex_width, tex_height, useHDR);

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

      rootNode->addChild(createScene(subGraph, tex_width, tex_height, useHDR, useImage, useMultiSample));


      //added some code to view the intermediate textures, removing this does not influence the final rendering
       osg::ref_ptr<osg::Camera> testTex =
            Game::Graphics::createTextureDisplayQuad(osg::Vec3(0, 0.7, 0),
                                                 textureRect[0],
                                                 tex_width);
osg::ref_ptr<osg::Camera> testTex2 =
            Game::Graphics::createTextureDisplayQuad(osg::Vec3(0, 0.35, 0),
                                                 textureRect[1],
                                                 tex_width);
osg::ref_ptr<osg::Camera> testTex3 =
            Game::Graphics::createTextureDisplayQuad(osg::Vec3(0.1, 0.0, 0),
                                                 textureRect[2],
                                                 tex_width);
osg::ref_ptr<osg::Camera> testTex4 =
            Game::Graphics::createTextureDisplayQuad(osg::Vec3(0.7, 0.7, 0),
                                                 textureRect[3],
                                                 tex_width);

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

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

      return viewer.run();
}


Cheers,
antiro
Back to top
View user's profile Send private message
SMesserschmidt (Sebastian Messerschmidt)
Forum Moderator


Joined: 10 Sep 2013
Posts: 796

PostPosted: Sat Sep 02, 2017 6:02 pm    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi Antiro,
Quote:
Hi,

I'm still struggling with getting setUseVertexAttributeAliasing(true) to combine rendering to textures.

To this end, I made made a tiny change to the osgmultiplerendertargets example to see if I could adapt that example to work with setUseVertexAttributeAliasing(true).

Aside from adding some lines to view the intermediate textures, my only change was enabling VertexAttributeAliasing as follows:


Code:
viewer.realize();
viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);
That's interesting. I've just checked my code-base and I definitively
set up the aliasing very early before adding anything to the scene graph.
Quote:



Given that the code only uses some fragment shaders, which use fixed colors and don't rely on things like gl_Vertex or gl_Normal I assumed no changes to them would be needed. Yet enabling VertexAttribute shaders breaks rendering, disabling it again fixes it.

Maybe I'm completely misunderstanding the idea behind VertexAttributeAliasing, all I want is to reuse the shaders from my other project, which requires control over the vertex attribute layout...
If anyone can tell me what I'm doing wrong or has a working example of MRT with setUseVertexAttributeAliasing(true), that would be highly appreciated.
Enabling the aliasing will also replace all gl_ things in the shaders
you pass to the scene graph and it will simple add vertex attributes for
all default attributes. See the State.cpp resetVertexAttributeAlias for
reference.
There is no magic involved. Unfortunately I don't have any spare time to
check your code sample, but I can promise that this definitively working
without trouble. I've been using MRT with modern shaders for years in my
deferred pipeline, and I don't recall having any problems at all. If
you're using NVidia under windows you might consider using NSight to
check your bindings.
What kind of GPU are you using? I experienced a lot of trouble using Intel.

Cheers
Sebastian
Quote:

For reference, here is the entire modified code:

Code:

/* OpenSceneGraph example, osgmultiplerendertargets.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#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 "RenderingUtility.h" //to easily view intermediate textures
//
// Below is relatively straight forward example of using the OpenGL multiple render targets (MRT) extension
// to FrameBufferObjects/GLSL shaders.
//
// Another, more sophisticated MRT example can be found in the osgstereomatch example.
//


// The callback modifies an input image.
struct MyCameraPostDrawCallback : public osg::Camera::DrawCallback
{
MyCameraPostDrawCallback(osg::Image* image):
_image(image)
{
}

virtual void operator () (const osg::Camera& /*camera*/) const
{
if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_UNSIGNED_BYTE)
{
// we'll pick out the center 1/2 of the whole image,
int column_start = _image->s()/4;
int column_end = 3*column_start;

int row_start = _image->t()/4;
int row_end = 3*row_start;

// and then halve their contribution
for(int r=row_start; r<row_end; ++r)
{
unsigned char* data = _image->data(column_start, r);
for(int c=column_start; c<column_end; ++c)
{
(*data) = (*data)/2; ++data;
(*data) = (*data)/2; ++data;
(*data) = (*data)/2; ++data;
(*data) = 255; ++data;
}
}

_image->dirty();
}
else if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_FLOAT)
{
// we'll pick out the center 1/2 of the whole image,
int column_start = _image->s()/4;
int column_end = 3*column_start;

int row_start = _image->t()/4;
int row_end = 3*row_start;

// and then halve their contribution
for(int r=row_start; r<row_end; ++r)
{
float* data = (float*)_image->data(column_start, r);
for(int c=column_start; c<column_end; ++c)
{
(*data) = (*data)/2.0; ++data;
(*data) = (*data)/2.0; ++data;
(*data) = (*data)/2.0; ++data;
(*data) = 1.0f; ++data;
}
}

_image->dirty();

//print out the first three values
float* data = (float*)_image->data(0, 0);
fprintf(stderr,"Float pixel data: r %e g %e b %e\n", data[0], data[1], data[2]);
}
}

osg::Image* _image;
};

#define NUM_TEXTURES 4

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

if (useHDR) {
static const char *shaderSource = {
"uniform int width;"
"void main(void)\n"
"{\n"
" gl_FragData[0] = vec4(-1e-12,0,0,1);\n"
" gl_FragData[1] = vec4(0,1e-12,0,1);\n"
" gl_FragData[2] = vec4(0,0,1e-12,1);\n"
" gl_FragData[3] = vec4(0,0,1e-12,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;
program->addShader(fshader.get());
stateset->setAttributeAndModes(program.get(), osg::StateAttribute:ShockedN | osg::StateAttribute::OVERRIDE );
} else {
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;
program->addShader(fshader.get());
stateset->setAttributeAndModes(program.get(), osg::StateAttribute:ShockedN | 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,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);

if (useHDR)
{
// Default HDR format
textureRect[i]->setInternalFormat(GL_RGBA32F_ARB);

// GL_FLOAT_RGBA32_NV might be supported on pre 8-series GPUs
//textureRect[i]->setInternalFormat(GL_FLOAT_RGBA32_NV);

// GL_RGBA16F_ARB can be used with this example,
// but modify e-12 and e12 in the shaders accordingly
//textureRect[i]->setInternalFormat(GL_RGBA16F_ARB);

textureRect[i]->setSourceFormat(GL_RGBA);
textureRect[i]->setSourceType(GL_FLOAT);
}
}

// 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:ShockedN);
}

polyGeom->setStateSet(stateset);

// Attach a shader to the final quad to combine the input textures.
if (useHDR) {
static const char *shaderSource = {
"uniform sampler2DRect textureID0;\n"
"uniform sampler2DRect textureID1;\n"
"uniform sampler2DRect textureID2;\n"
"uniform sampler2DRect textureID3;\n"
"uniform float width;\n"
"uniform float height; \n"
"void main(void)\n"
"{\n"
" gl_FragData[0] = \n"
" vec4( -1e12 * texture2DRect( textureID0, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4( 1e12 * texture2DRect( textureID1, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4( 1e12 * texture2DRect( textureID2, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4(-0.5e12 * texture2DRect( textureID3, gl_TexCoord[0].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;
program->addShader( fshader.get());
stateset->setAttributeAndModes( program.get(), osg::StateAttribute:ShockedN | osg::StateAttribute::OVERRIDE );
} else {
static const char *shaderSource = {
"uniform sampler2DRect textureID0;\n"
"uniform sampler2DRect textureID1;\n"
"uniform sampler2DRect textureID2;\n"
"uniform sampler2DRect textureID3;\n"
"void main(void)\n"
"{\n"
" gl_FragData[0] = \n"
" vec4(texture2DRect( textureID0, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4(texture2DRect( textureID1, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4(texture2DRect( textureID2, gl_TexCoord[0].st ).rgb, 1) + \n"
" -0.5*vec4(texture2DRect( textureID3, gl_TexCoord[0].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;
program->addShader( fshader.get());
stateset->setAttributeAndModes( program.get(), osg::StateAttribute:ShockedN | 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++) {
if (useMultiSample)
camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), textureRect[i], 0, 0, false, 4, 4);
else
camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), textureRect[i]);


}

#if 0
// test for new glEnablei/glDisablei functionality.
camera->getOrCreateStateSet()->setAttribute(new osg::Enablei(GL_BLEND, 0));
camera->getOrCreateStateSet()->setAttribute(new osg::Disablei(GL_BLEND, 1));
#endif

// we can also read back any of the targets as an image, modify this image and push it back
if (useImage) {
// which texture to get the image from
const int tex_to_get = 0;

osg::Image* image = new osg::Image;
if (useHDR) {
image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_FLOAT);
} else {
image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
}

// attach the image so its copied on each frame.
camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0 + tex_to_get), image);

camera->setPostDrawCallback(new MyCameraPostDrawCallback(image));

// push back the image to the texture
textureRect[tex_to_get]->setImage(0, image);
}

// 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);

// set up the usage document, in case we need to print out how to use this program.
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " demonstrates the use of multiple render targets (MRT) with frame buffer objects (FBOs). A render to texture (RTT) camera is used to render to four textures using a single shader. The four textures are then combined to texture the viewed geometry.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] ...");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information.");
arguments.getApplicationUsage()->addCommandLineOption("--width","Set the width of the render to texture.");
arguments.getApplicationUsage()->addCommandLineOption("--height","Set the height of the render to texture.");
arguments.getApplicationUsage()->addCommandLineOption("--image","Render one of the targets to an image, then apply a post draw callback to modify it and use this image to update the final texture. Print some texture values when using HDR.");
arguments.getApplicationUsage()->addCommandLineOption("--hdr","Use high dynamic range (HDR). Create floating point textures to render to.");

// construct the viewer.
osgViewer::Viewer viewer(arguments);

// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{
arguments.getApplicationUsage()->write(std::cout);
return 1;
}

unsigned tex_width = 512;
unsigned tex_height = 512;
while (arguments.read("--width", tex_width)) {}
while (arguments.read("--height", tex_height)) {}

bool useHDR = false;
while (arguments.read("--hdr")) { useHDR = true; }

bool useImage = false;
while (arguments.read("--image")) { useImage = true; }

bool useMultiSample = false;
while (arguments.read("--ms")) { useMultiSample = true; }

osg::Group* subGraph = createRTTQuad(tex_width, tex_height, useHDR);

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

rootNode->addChild(createScene(subGraph, tex_width, tex_height, useHDR, useImage, useMultiSample));


//added some code to view the intermediate textures, removing this does not influence the final rendering
osg::ref_ptr<osg::Camera> testTex =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0, 0.7, 0),
textureRect[0],
tex_width);
osg::ref_ptr<osg::Camera> testTex2 =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0, 0.35, 0),
textureRect[1],
tex_width);
osg::ref_ptr<osg::Camera> testTex3 =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0.1, 0.0, 0),
textureRect[2],
tex_width);
osg::ref_ptr<osg::Camera> testTex4 =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0.7, 0.7, 0),
textureRect[3],
tex_width);

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

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

return viewer.run();
}



Cheers,
antiro

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71604#71604









------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
SMesserschmidt (Sebastian Messerschmidt)
Forum Moderator


Joined: 10 Sep 2013
Posts: 796

PostPosted: Sat Sep 02, 2017 6:12 pm    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi Chris,
Quote:
I'm also transitioning a legacy GL OSG project with a mix of custom shaders to modern GL bit by bit. And I've also had lots of trouble and headache with the built-in modern GL vertex attrib aliasing setting.

It seems crazy that the official advice is to write shaders and use OSG just like legacy GL, and OSG will then change your shader code and reinterpret deprecated calls to make it work via "modern" GL: Obviously in years to come when GL newcomers want to use OSG the official line can't be "learn how GL was 20 years ago, write your OSG code like that, and the system will make it work".

So I'm afraid this isn't as simple as it could be, but of course it's still easier than converting raw GL calls..
Who told you something like this? OSG is totally capable of using modern
GLSL. For some legacy support you might need to write appropriate
visitors, but there is nothing stopping you using modern approaches.
Quote:


Here is my only advice since I'm not yet finished myself:
My recommendation is just leave that attrib aliasing setting alone; you can use modern GL anyway. Just make sure that you use the setVertexAttribute() calls instead of setTextureCoords() / setNormals() / etc, and use the same attrib location numbering convention as OSG (I believe NVidia's drivers enforce those conventions, so you can get the vertex positions at loc=0).
Basically you're duplicating the vertexAttributeAliasing mechanism.
There might be problems with non-conforming drivers, but in general the
mapping is fixed on all conforming OpenGL drivers I've used (And the
mechanism works on a lot of heterogeneous machines)


Quote:

Then you'll want to get a copy of the ShaderGen class so you can customize because you'll likely want to modify it yourself. You can use this code to hook into osgDB::readNode()'s behavior to setup your shaders/attribs/etc the way you want.
I don't see how this is related to ShaderGen (I suppose you're talking
about the old class). I strongly suggest to write your own shaders and
use the setDefine (#pragmatic shader composition) mechanism to create
shader variations.

Cheers
Sebastian
Quote:
You then need to set useModelViewUniforms, which seems to be less harmful than useVertexAttribAliasing and will make sure osg_ModelViewMatrix is set.


Interested to compare notes on how you go anyway

------------------------
http://www.hrwallingford.com/facilities/ship-simulation-centre (http://www.hrwallingford.com/facilities/ship-simulation-centre)

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71598#71598









------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
SMesserschmidt (Sebastian Messerschmidt)
Forum Moderator


Joined: 10 Sep 2013
Posts: 796

PostPosted: Sat Sep 02, 2017 6:15 pm    Post subject:
using modern shaders with osg - setting vertex attribute layout
Reply with quote

Hi,

Unfortunately your example doesn't compile. If you provide a minimal
(i.e. compileable ) example showing the problem we could take a look
into it.
Due to copyright reasons I cannot give you an example from my code base.

Cheers
Sebastian
Quote:
Hi,

I'm still struggling with getting setUseVertexAttributeAliasing(true) to combine rendering to textures.

To this end, I made made a tiny change to the osgmultiplerendertargets example to see if I could adapt that example to work with setUseVertexAttributeAliasing(true).

Aside from adding some lines to view the intermediate textures, my only change was enabling VertexAttributeAliasing as follows:


Code:
viewer.realize();
viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);




Given that the code only uses some fragment shaders, which use fixed colors and don't rely on things like gl_Vertex or gl_Normal I assumed no changes to them would be needed. Yet enabling VertexAttribute shaders breaks rendering, disabling it again fixes it.

Maybe I'm completely misunderstanding the idea behind VertexAttributeAliasing, all I want is to reuse the shaders from my other project, which requires control over the vertex attribute layout...
If anyone can tell me what I'm doing wrong or has a working example of MRT with setUseVertexAttributeAliasing(true), that would be highly appreciated.

For reference, here is the entire modified code:

Code:

/* OpenSceneGraph example, osgmultiplerendertargets.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#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 "RenderingUtility.h" //to easily view intermediate textures
//
// Below is relatively straight forward example of using the OpenGL multiple render targets (MRT) extension
// to FrameBufferObjects/GLSL shaders.
//
// Another, more sophisticated MRT example can be found in the osgstereomatch example.
//


// The callback modifies an input image.
struct MyCameraPostDrawCallback : public osg::Camera::DrawCallback
{
MyCameraPostDrawCallback(osg::Image* image):
_image(image)
{
}

virtual void operator () (const osg::Camera& /*camera*/) const
{
if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_UNSIGNED_BYTE)
{
// we'll pick out the center 1/2 of the whole image,
int column_start = _image->s()/4;
int column_end = 3*column_start;

int row_start = _image->t()/4;
int row_end = 3*row_start;

// and then halve their contribution
for(int r=row_start; r<row_end; ++r)
{
unsigned char* data = _image->data(column_start, r);
for(int c=column_start; c<column_end; ++c)
{
(*data) = (*data)/2; ++data;
(*data) = (*data)/2; ++data;
(*data) = (*data)/2; ++data;
(*data) = 255; ++data;
}
}

_image->dirty();
}
else if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_FLOAT)
{
// we'll pick out the center 1/2 of the whole image,
int column_start = _image->s()/4;
int column_end = 3*column_start;

int row_start = _image->t()/4;
int row_end = 3*row_start;

// and then halve their contribution
for(int r=row_start; r<row_end; ++r)
{
float* data = (float*)_image->data(column_start, r);
for(int c=column_start; c<column_end; ++c)
{
(*data) = (*data)/2.0; ++data;
(*data) = (*data)/2.0; ++data;
(*data) = (*data)/2.0; ++data;
(*data) = 1.0f; ++data;
}
}

_image->dirty();

//print out the first three values
float* data = (float*)_image->data(0, 0);
fprintf(stderr,"Float pixel data: r %e g %e b %e\n", data[0], data[1], data[2]);
}
}

osg::Image* _image;
};

#define NUM_TEXTURES 4

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

if (useHDR) {
static const char *shaderSource = {
"uniform int width;"
"void main(void)\n"
"{\n"
" gl_FragData[0] = vec4(-1e-12,0,0,1);\n"
" gl_FragData[1] = vec4(0,1e-12,0,1);\n"
" gl_FragData[2] = vec4(0,0,1e-12,1);\n"
" gl_FragData[3] = vec4(0,0,1e-12,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;
program->addShader(fshader.get());
stateset->setAttributeAndModes(program.get(), osg::StateAttribute:ShockedN | osg::StateAttribute::OVERRIDE );
} else {
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;
program->addShader(fshader.get());
stateset->setAttributeAndModes(program.get(), osg::StateAttribute:ShockedN | 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,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);

if (useHDR)
{
// Default HDR format
textureRect[i]->setInternalFormat(GL_RGBA32F_ARB);

// GL_FLOAT_RGBA32_NV might be supported on pre 8-series GPUs
//textureRect[i]->setInternalFormat(GL_FLOAT_RGBA32_NV);

// GL_RGBA16F_ARB can be used with this example,
// but modify e-12 and e12 in the shaders accordingly
//textureRect[i]->setInternalFormat(GL_RGBA16F_ARB);

textureRect[i]->setSourceFormat(GL_RGBA);
textureRect[i]->setSourceType(GL_FLOAT);
}
}

// 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:ShockedN);
}

polyGeom->setStateSet(stateset);

// Attach a shader to the final quad to combine the input textures.
if (useHDR) {
static const char *shaderSource = {
"uniform sampler2DRect textureID0;\n"
"uniform sampler2DRect textureID1;\n"
"uniform sampler2DRect textureID2;\n"
"uniform sampler2DRect textureID3;\n"
"uniform float width;\n"
"uniform float height; \n"
"void main(void)\n"
"{\n"
" gl_FragData[0] = \n"
" vec4( -1e12 * texture2DRect( textureID0, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4( 1e12 * texture2DRect( textureID1, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4( 1e12 * texture2DRect( textureID2, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4(-0.5e12 * texture2DRect( textureID3, gl_TexCoord[0].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;
program->addShader( fshader.get());
stateset->setAttributeAndModes( program.get(), osg::StateAttribute:ShockedN | osg::StateAttribute::OVERRIDE );
} else {
static const char *shaderSource = {
"uniform sampler2DRect textureID0;\n"
"uniform sampler2DRect textureID1;\n"
"uniform sampler2DRect textureID2;\n"
"uniform sampler2DRect textureID3;\n"
"void main(void)\n"
"{\n"
" gl_FragData[0] = \n"
" vec4(texture2DRect( textureID0, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4(texture2DRect( textureID1, gl_TexCoord[0].st ).rgb, 1) + \n"
" vec4(texture2DRect( textureID2, gl_TexCoord[0].st ).rgb, 1) + \n"
" -0.5*vec4(texture2DRect( textureID3, gl_TexCoord[0].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;
program->addShader( fshader.get());
stateset->setAttributeAndModes( program.get(), osg::StateAttribute:ShockedN | 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++) {
if (useMultiSample)
camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), textureRect[i], 0, 0, false, 4, 4);
else
camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), textureRect[i]);


}

#if 0
// test for new glEnablei/glDisablei functionality.
camera->getOrCreateStateSet()->setAttribute(new osg::Enablei(GL_BLEND, 0));
camera->getOrCreateStateSet()->setAttribute(new osg::Disablei(GL_BLEND, 1));
#endif

// we can also read back any of the targets as an image, modify this image and push it back
if (useImage) {
// which texture to get the image from
const int tex_to_get = 0;

osg::Image* image = new osg::Image;
if (useHDR) {
image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_FLOAT);
} else {
image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
}

// attach the image so its copied on each frame.
camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0 + tex_to_get), image);

camera->setPostDrawCallback(new MyCameraPostDrawCallback(image));

// push back the image to the texture
textureRect[tex_to_get]->setImage(0, image);
}

// 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);

// set up the usage document, in case we need to print out how to use this program.
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " demonstrates the use of multiple render targets (MRT) with frame buffer objects (FBOs). A render to texture (RTT) camera is used to render to four textures using a single shader. The four textures are then combined to texture the viewed geometry.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] ...");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information.");
arguments.getApplicationUsage()->addCommandLineOption("--width","Set the width of the render to texture.");
arguments.getApplicationUsage()->addCommandLineOption("--height","Set the height of the render to texture.");
arguments.getApplicationUsage()->addCommandLineOption("--image","Render one of the targets to an image, then apply a post draw callback to modify it and use this image to update the final texture. Print some texture values when using HDR.");
arguments.getApplicationUsage()->addCommandLineOption("--hdr","Use high dynamic range (HDR). Create floating point textures to render to.");

// construct the viewer.
osgViewer::Viewer viewer(arguments);

// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{
arguments.getApplicationUsage()->write(std::cout);
return 1;
}

unsigned tex_width = 512;
unsigned tex_height = 512;
while (arguments.read("--width", tex_width)) {}
while (arguments.read("--height", tex_height)) {}

bool useHDR = false;
while (arguments.read("--hdr")) { useHDR = true; }

bool useImage = false;
while (arguments.read("--image")) { useImage = true; }

bool useMultiSample = false;
while (arguments.read("--ms")) { useMultiSample = true; }

osg::Group* subGraph = createRTTQuad(tex_width, tex_height, useHDR);

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

rootNode->addChild(createScene(subGraph, tex_width, tex_height, useHDR, useImage, useMultiSample));


//added some code to view the intermediate textures, removing this does not influence the final rendering
osg::ref_ptr<osg::Camera> testTex =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0, 0.7, 0),
textureRect[0],
tex_width);
osg::ref_ptr<osg::Camera> testTex2 =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0, 0.35, 0),
textureRect[1],
tex_width);
osg::ref_ptr<osg::Camera> testTex3 =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0.1, 0.0, 0),
textureRect[2],
tex_width);
osg::ref_ptr<osg::Camera> testTex4 =
Game::Graphics::createTextureDisplayQuad(osg::Vec3(0.7, 0.7, 0),
textureRect[3],
tex_width);

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

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

return viewer.run();
}



Cheers,
antiro

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71604#71604









------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OpenSceneGraph Forum Forum Index -> General All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum

Similar Topics
Topic Author Forum Replies Posted
No new posts Transform matrix as Uniform to shaders freqfly General 3 Thu Oct 05, 2017 4:19 am View latest post
No new posts How to pre-compile shaders before act... kornerr General 1 Thu Sep 28, 2017 8:42 pm View latest post
No new posts Post Processing Effect - Vertex Shade... guyv General 27 Sat Sep 16, 2017 3:48 am View latest post
No new posts Pro Process Effect Vertex Shader not ... guyv General 1 Fri Sep 15, 2017 10:22 pm View latest post
No new posts Post Process Effect Vertex Shader guyv General 1 Fri Sep 15, 2017 8:29 pm View latest post


Board Security Anti Bot Question MOD - phpBB MOD against Spam Bots
Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP