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