1 /* OpenSceneGraph example, osgpackeddepthstencil.
2 *
3 *  Permission is hereby granted, free of charge, to any person obtaining a copy
4 *  of this software and associated documentation files (the "Software"), to deal
5 *  in the Software without restriction, including without limitation the rights
6 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 *  copies of the Software, and to permit persons to whom the Software is
8 *  furnished to do so, subject to the following conditions:
9 *
10 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 *  THE SOFTWARE.
17 */
18 
19 #include <osg/GLExtensions>
20 #include <osg/Node>
21 #include <osg/Geometry>
22 #include <osg/Notify>
23 #include <osg/Texture2D>
24 #include <osg/Stencil>
25 #include <osg/ColorMask>
26 #include <osg/Geode>
27 #include <osg/FrameBufferObject>
28 
29 #include <osgViewer/Viewer>
30 #include <osgViewer/ViewerEventHandlers>
31 
32 #include <iostream>
33 
createMask()34 osg::Geode* createMask()
35 {
36     osg::Vec3Array *vertices = new osg::Vec3Array;
37     vertices->push_back(osg::Vec3(-0.5, -0.5, 0.0));
38     vertices->push_back(osg::Vec3(0.5, -0.5, 0.0));
39     vertices->push_back(osg::Vec3(0.5, 0.5, 0.0));
40     vertices->push_back(osg::Vec3(-0.5, 0.5, 0.0));
41 
42     osg::Geometry *geom = new osg::Geometry;
43     geom->setVertexArray(vertices);
44     geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
45 
46     osg::Geode *geode = new osg::Geode;
47     geode->addDrawable(geom);
48 
49     osg::Stencil* stencil = new osg::Stencil;
50     stencil->setFunction(osg::Stencil::ALWAYS, 1, ~0u);
51     stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE);
52 
53     osg::StateSet *ss = geode->getOrCreateStateSet();
54     ss->setAttributeAndModes(stencil,
55         osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
56     ss->setAttribute(new osg::ColorMask(false, false, false, false),
57         osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
58 
59     return geode;
60 }
61 
createGeometry()62 osg::Geode* createGeometry()
63 {
64     osg::Vec3Array* vertices = new osg::Vec3Array;
65     vertices->push_back(osg::Vec3(-1.0, -1.0, 0.0));
66     vertices->push_back(osg::Vec3(1.0, -1.0, 0.0));
67     vertices->push_back(osg::Vec3(1.0, 1.0, 0.0));
68     vertices->push_back(osg::Vec3(-1.0, 1.0, 0.0));
69 
70     osg::Geometry* geom = new osg::Geometry;
71     geom->setVertexArray(vertices);
72     geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
73 
74     osg::Geode* geode = new osg::Geode;
75     geode->addDrawable(geom);
76 
77     osg::Stencil* stencil = new osg::Stencil;
78     stencil->setFunction(osg::Stencil::NOTEQUAL, 1, ~0u);
79     stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
80 
81     osg::StateSet *ss = geode->getOrCreateStateSet();
82     ss->setAttributeAndModes(stencil,
83         osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
84 
85     return geode;
86 }
87 
createTextureQuad(osg::Texture2D * texture)88 osg::Geode* createTextureQuad(osg::Texture2D *texture)
89 {
90     osg::Vec3Array *vertices = new osg::Vec3Array;
91     vertices->push_back(osg::Vec3(-0.8, 0.0, -0.8));
92     vertices->push_back(osg::Vec3(0.8, 0.0, -0.8));
93     vertices->push_back(osg::Vec3(0.8, 0.0, 0.8));
94     vertices->push_back(osg::Vec3(-0.8, 0.0, 0.8));
95 
96     osg::Vec2Array *texcoord = new osg::Vec2Array;
97     texcoord->push_back(osg::Vec2(0.0, 0.0));
98     texcoord->push_back(osg::Vec2(1.0, 0.0));
99     texcoord->push_back(osg::Vec2(1.0, 1.0));
100     texcoord->push_back(osg::Vec2(0.0, 1.0));
101 
102     osg::Geometry *geom = new osg::Geometry;
103     geom->setVertexArray(vertices);
104     geom->setTexCoordArray(0, texcoord);
105     geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
106 
107     osg::Geode *geode = new osg::Geode;
108     geode->addDrawable(geom);
109     geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
110 
111     return geode;
112 }
113 
114 
main(int argc,char ** argv)115 int main( int argc, char **argv )
116 {
117     // use an ArgumentParser object to manage the program arguments.
118     osg::ArgumentParser arguments(&argc,argv);
119 
120     arguments.getApplicationUsage()->addCommandLineOption("--fbo","Use Frame Buffer Object for render to texture, where supported.");
121     arguments.getApplicationUsage()->addCommandLineOption("--pbuffer-rtt","Use Pixel Buffer for render to texture, where supported.");
122     arguments.getApplicationUsage()->addCommandLineOption("--nopds", "Don't use packed depth stencil.");
123     arguments.getApplicationUsage()->addCommandLineOption("--fbo-samples","");
124     arguments.getApplicationUsage()->addCommandLineOption("--color-samples", "");
125 
126     // construct the viewer.
127     osgViewer::Viewer viewer(arguments);
128 
129     // add stats
130     viewer.addEventHandler( new osgViewer::StatsHandler() );
131 
132     // if user request help write it out to cout.
133     if (arguments.read("-h") || arguments.read("--help"))
134     {
135         arguments.getApplicationUsage()->write(std::cout);
136         return 1;
137     }
138 
139     osg::Camera::RenderTargetImplementation renderImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
140     int colorSamples = 0, samples = 0;
141     bool usePDS = true;
142 
143     while (arguments.read("--fbo")) { renderImplementation = osg::Camera::FRAME_BUFFER_OBJECT; }
144     while (arguments.read("--pbuffer-rtt")) { renderImplementation = osg::Camera::PIXEL_BUFFER_RTT; }
145     while (arguments.read("--nopds")) { usePDS = false; }
146     while (arguments.read("--fbo-samples", samples)) {}
147     while (arguments.read("--color-samples", colorSamples)) {}
148 
149 
150     osg::Group* rootNode = new osg::Group;
151     rootNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
152 
153     // creates texture to be rendered
154     osg::Texture2D *texture = new osg::Texture2D;
155     texture->setTextureSize(1024, 1024);
156     texture->setInternalFormat(GL_RGBA);
157     texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
158     texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
159     texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
160     texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
161     texture->setBorderColor(osg::Vec4(0, 0, 0, 0));
162 
163     // creates rtt camera
164     osg::ref_ptr<osg::Camera> rttCamera = new osg::Camera;
165     rttCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
166     rttCamera->setClearColor(osg::Vec4(0.0, 0.4, 0.5, 0.0));
167     rttCamera->setClearStencil(0);
168     rttCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
169     rttCamera->setViewMatrix(osg::Matrixd::identity());
170     rttCamera->setViewport(0, 0, 1024, 1024);
171     rttCamera->setRenderOrder(osg::Camera::PRE_RENDER);
172     rttCamera->setRenderTargetImplementation(renderImplementation);
173 
174     if(usePDS)
175     {
176         rttCamera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT);
177     }
178     else
179     {
180         // this doesn't work on NVIDIA/Vista 64bit
181         // FBO status = 0x8cd6 (FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT)
182         rttCamera->attach(osg::Camera::DEPTH_BUFFER, GL_DEPTH_COMPONENT);
183         rttCamera->attach(osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX8_EXT);
184     }
185 
186     rttCamera->attach(osg::Camera::COLOR_BUFFER, texture, 0, 0, false, samples, colorSamples);
187     rttCamera->setCullingMode(osg::Camera::VIEW_FRUSTUM_SIDES_CULLING);
188 
189     // creates rtt subtree
190     osg::Group* g0 = new osg::Group;
191     g0->addChild(createMask());
192     g0->addChild(createGeometry());
193     rttCamera->addChild(g0);
194     rootNode->addChild(rttCamera.get());
195 
196     // creates textured quad with result
197     rootNode->addChild(createTextureQuad(texture));
198 
199     // add model to the viewer.
200     viewer.setSceneData( rootNode );
201 
202     return viewer.run();
203 }
204