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