1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12 */
13
14 #include <osgViewer/config/WoWVxDisplay>
15 #include <osgViewer/Renderer>
16 #include <osgViewer/View>
17 #include <osgViewer/GraphicsWindow>
18
19 #include <osg/io_utils>
20
21 #include <osg/TextureRectangle>
22 #include <osg/Texture1D>
23 #include <osg/Texture2D>
24 #include <osg/TexMat>
25 #include <osg/Stencil>
26 #include <osg/PolygonStipple>
27 #include <osg/ValueObject>
28
29 using namespace osgViewer;
30
configure(osgViewer::View & view) const31 void WoWVxDisplay::configure(osgViewer::View& view) const
32 {
33 OSG_INFO<<"WoWVxDisplay::configure(...)"<<std::endl;
34
35 osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
36 if (!wsi)
37 {
38 OSG_NOTICE<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
39 return;
40 }
41
42 osg::GraphicsContext::ScreenIdentifier si;
43 si.readDISPLAY();
44
45 // displayNum has not been set so reset it to 0.
46 if (si.displayNum<0) si.displayNum = 0;
47
48 si.screenNum = _screenNum;
49
50 unsigned int width, height;
51 wsi->getScreenResolution(si, width, height);
52
53 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
54 traits->hostName = si.hostName;
55 traits->displayNum = si.displayNum;
56 traits->screenNum = si.screenNum;
57 traits->x = 0;
58 traits->y = 0;
59 traits->width = width;
60 traits->height = height;
61 traits->windowDecoration = false;
62 traits->doubleBuffer = true;
63 traits->sharedContext = 0;
64
65
66 osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
67 if (!gc)
68 {
69 OSG_NOTICE<<"GraphicsWindow has not been created successfully."<<std::endl;
70 return;
71 }
72
73 int tex_width = width;
74 int tex_height = height;
75
76 int camera_width = tex_width;
77 int camera_height = tex_height;
78
79 osg::Texture2D* texture = new osg::Texture2D;
80 texture->setTextureSize(tex_width, tex_height);
81 texture->setInternalFormat(GL_RGB);
82 texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
83 texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
84
85 osg::Texture2D* textureD = new osg::Texture2D;
86 textureD->setTextureSize(tex_width, tex_height);
87 textureD->setInternalFormat(GL_DEPTH_COMPONENT);
88 textureD->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
89 textureD->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
90
91 // front face
92 {
93 #if 0
94 osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW;
95 GLenum buffer = GL_FRONT;
96 #else
97 osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
98 GLenum buffer = GL_FRONT;
99 #endif
100
101 osg::ref_ptr<osg::Camera> camera = new osg::Camera;
102 camera->setName("Front face camera");
103 camera->setGraphicsContext(gc.get());
104 camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
105 camera->setDrawBuffer(buffer);
106 camera->setReadBuffer(buffer);
107 camera->setAllowEventFocus(false);
108 // tell the camera to use OpenGL frame buffer object where supported.
109 camera->setRenderTargetImplementation(renderTargetImplementation);
110
111 // attach the texture and use it as the color buffer.
112 camera->attach(osg::Camera::COLOR_BUFFER, texture);
113 camera->attach(osg::Camera::DEPTH_BUFFER, textureD);
114
115 view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
116 }
117
118 // WoW display set up.
119 {
120 osg::Texture1D *textureHeader = new osg::Texture1D();
121 // Set up the header
122 {
123 unsigned char header[]= {0xF1,_wow_content,_wow_factor,_wow_offset,0x00,0x00,0x00,0x00,0x00,0x00};
124 // Calc the CRC32
125 {
126 unsigned long _register = 0;
127 for(int i = 0; i < 10; ++i) {
128 unsigned char mask = 0x80;
129 unsigned char byte = header[i];
130 for (int j = 0; j < 8; ++j)
131 {
132 bool topBit = (_register & 0x80000000) != 0;
133 _register <<= 1;
134 _register ^= ((byte & mask) != 0? 0x1: 0x0);
135 if (topBit)
136 {
137 _register ^= 0x04c11db7;
138 }
139 mask >>= 1;
140 }
141 }
142 unsigned char *p = (unsigned char*) &_register;
143 for(size_t i = 0; i < 4; ++i)
144 {
145 header[i+6] = p[3-i];
146 }
147 }
148
149 osg::ref_ptr<osg::Image> imageheader = new osg::Image();
150 imageheader->allocateImage(256,1,1,GL_LUMINANCE,GL_UNSIGNED_BYTE);
151 {
152 unsigned char *cheader = imageheader->data();
153 for (int x=0; x<256; ++x){
154 cheader[x] = 0;
155 }
156 for (int x=0; x<=9; ++x){
157 for (int y=7; y>=0; --y){
158 int i = 2*(7-y)+16*x;
159 cheader[i] = (((1<<(y))&(header[x])) << (7-(y)));
160 }
161 }
162 }
163 textureHeader->setImage(imageheader.get());
164 }
165
166 // Create the Screen Aligned Quad
167 osg::Geode* geode = new osg::Geode();
168 {
169 osg::Geometry* geom = new osg::Geometry;
170
171 osg::Vec3Array* vertices = new osg::Vec3Array;
172 vertices->push_back(osg::Vec3(0,height,0));
173 vertices->push_back(osg::Vec3(0,0,0));
174 vertices->push_back(osg::Vec3(width,height,0));
175 vertices->push_back(osg::Vec3(width,0,0));
176 geom->setVertexArray(vertices);
177
178 osg::Vec2Array* tex = new osg::Vec2Array;
179 tex->push_back(osg::Vec2(0,1));
180 tex->push_back(osg::Vec2(0,0));
181 tex->push_back(osg::Vec2(1,1));
182 tex->push_back(osg::Vec2(1,0));
183 geom->setTexCoordArray(0,tex);
184
185 geom->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP,0,4));
186 geode->addDrawable(geom);
187
188
189 // new we need to add the textures to the quad, and setting up the shader.
190 osg::StateSet* stateset = geode->getOrCreateStateSet();
191 stateset->setTextureAttributeAndModes(0, textureHeader,osg::StateAttribute::ON);
192 stateset->setTextureAttributeAndModes(1, texture,osg::StateAttribute::ON);
193 stateset->setTextureAttributeAndModes(2, textureD,osg::StateAttribute::ON);
194 stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
195
196 osg::ref_ptr<osg::Program> programShader = new osg::Program();
197 stateset->setAttribute(programShader.get(), osg::StateAttribute::ON);
198 stateset->addUniform( new osg::Uniform("wow_width", (int)width));
199 stateset->addUniform( new osg::Uniform("wow_height", (int)height));
200 stateset->addUniform( new osg::Uniform("wow_disparity_M", _wow_disparity_M));
201 stateset->addUniform( new osg::Uniform("wow_disparity_Zd", _wow_disparity_Zd));
202 stateset->addUniform( new osg::Uniform("wow_disparity_vz", _wow_disparity_vz));
203 stateset->addUniform( new osg::Uniform("wow_disparity_C", _wow_disparity_C));
204
205 stateset->addUniform(new osg::Uniform("wow_header", 0));
206 stateset->addUniform(new osg::Uniform("wow_tcolor", 1));
207 stateset->addUniform(new osg::Uniform("wow_tdepth", 2));
208
209 osg::Shader *frag = new osg::Shader(osg::Shader::FRAGMENT);
210 frag->setShaderSource(" "\
211 " uniform sampler1D wow_header; " \
212 " uniform sampler2D wow_tcolor; " \
213 " uniform sampler2D wow_tdepth; " \
214 " " \
215 " uniform int wow_width; " \
216 " uniform int wow_height; " \
217 " uniform float wow_disparity_M; " \
218 " uniform float wow_disparity_Zd; " \
219 " uniform float wow_disparity_vz; " \
220 " uniform float wow_disparity_C; " \
221 " " \
222 " float disparity(float Z) " \
223 " { " \
224 " return (wow_disparity_M*(1.0-(wow_disparity_vz/(Z-wow_disparity_Zd+wow_disparity_vz))) " \
225 " + wow_disparity_C) / 255.0; " \
226 " } " \
227 " " \
228 " void main() " \
229 " { " \
230 " vec2 pos = (gl_FragCoord.xy / vec2(wow_width/2,wow_height) ); " \
231 " if (gl_FragCoord.x > float(wow_width/2)) " \
232 " { " \
233 " gl_FragColor = vec4(disparity(( texture2D(wow_tdepth, pos - vec2(1,0))).z)); " \
234 " } " \
235 " else{ " \
236 " gl_FragColor = texture2D(wow_tcolor, pos); " \
237 " } " \
238 " if ( (gl_FragCoord.y >= float(wow_height-1)) && (gl_FragCoord.x < 256.0) ) " \
239 " { " \
240 " float pos = gl_FragCoord.x/256.0; " \
241 " float blue = texture1D(wow_header, pos).b; " \
242 " if ( blue < 0.5) " \
243 " gl_FragColor.b = 0.0; " \
244 " else " \
245 " gl_FragColor.b = 1.0; " \
246 " } " \
247 " } " );
248
249 programShader->addShader(frag);
250 }
251
252 // Create the Camera
253 {
254 osg::ref_ptr<osg::Camera> camera = new osg::Camera;
255 camera->setGraphicsContext(gc.get());
256 camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
257 camera->setClearColor( osg::Vec4(0.0,0.0,0.0,1.0) );
258 camera->setViewport(new osg::Viewport(0, 0, width, height));
259 GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
260 camera->setDrawBuffer(buffer);
261 camera->setReadBuffer(buffer);
262 camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
263 camera->setAllowEventFocus(false);
264 camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE);
265 //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
266
267 camera->setProjectionMatrixAsOrtho2D(0,width,0,height);
268 camera->setViewMatrix(osg::Matrix::identity());
269
270 // add subgraph to render
271 camera->addChild(geode);
272
273 camera->setName("WoWCamera");
274
275 view.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false);
276 }
277 }
278 }
279