source: trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp @ 532

Revision 532, 20.5 KB checked in by mattausch, 18 years ago (diff)
  • Property svn:executable set to *
Line 
1#include "Mesh.h"
2#include "GlRenderer.h"
3#include "ViewCellsManager.h"
4#include "SceneGraph.h"
5#include "Pvs.h"
6#include "Viewcell.h"
7#include "Beam.h"
8#include "KdTree.h"
9
10#include <GL/glext.h>
11#include <Cg/cg.h>
12#include <Cg/cgGL.h>
13
14static CGcontext sCgContext = NULL;
15static CGprogram sCgFragmentProgram = NULL;
16static CGprofile sCgFragmentProfile;
17
18GLuint depthMap;
19const int depthMapSize = 512;
20static vector<int> sQueries;
21
22GlRendererWidget *rendererWidget = NULL;
23
24
25#ifdef _WIN32
26PFNGLGENOCCLUSIONQUERIESNVPROC glGenOcclusionQueriesNV;
27PFNGLBEGINOCCLUSIONQUERYNVPROC glBeginOcclusionQueryNV;
28PFNGLENDOCCLUSIONQUERYNVPROC glEndOcclusionQueryNV;
29PFNGLGETOCCLUSIONQUERYUIVNVPROC glGetOcclusionQueryuivNV;
30#endif
31
32GlRenderer::GlRenderer(SceneGraph *sceneGraph,
33                                           ViewCellsManager *viewCellsManager,
34                                           KdTree *tree):
35  Renderer(sceneGraph, viewCellsManager),
36  mKdTree(tree)
37{
38  mSceneGraph->CollectObjects(&mObjects);
39  mViewPoint = mSceneGraph->GetBox().Center();
40  mViewDirection = Vector3(0,0,1);
41  //  timerId = startTimer(10);
42  mFrame = 0;
43  mWireFrame = false;
44}
45
46GlRenderer::~GlRenderer()
47{
48        cgDestroyProgram(sCgFragmentProgram);
49        cgDestroyContext(sCgContext);
50}
51
52
53static void handleCgError()
54{
55    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
56    exit(1);
57}
58
59void
60GlRenderer::RenderIntersectable(Intersectable *object)
61{
62
63  SetupFalseColor(object->mId);
64
65  switch (object->Type()) {
66  case Intersectable::MESH_INSTANCE:
67        RenderMeshInstance((MeshInstance *)object);
68        break;
69  default:
70        cerr<<"Rendering this object not yet implemented\n";
71        break;
72  }
73}
74
75
76void
77GlRenderer::RenderMeshInstance(MeshInstance *mi)
78{
79  RenderMesh(mi->GetMesh());
80}
81
82void
83GlRenderer::SetupFalseColor(const int id)
84{
85  // swap bits of the color
86 
87  glColor3ub(id&255, (id>>8)&255, (id>>16)&255);
88}
89
90void
91GlRenderer::SetupMaterial(Material *m)
92{
93  if (m)
94        glColor3fv(&(m->mDiffuseColor.r));
95  else
96        glColor3f(1.0f, 1.0f, 1.0f);
97}
98
99void
100GlRenderer::RenderMesh(Mesh *mesh)
101{
102  int i = 0;
103
104  if (!mUseFalseColors)
105        SetupMaterial(mesh->mMaterial);
106 
107  for (i=0; i < mesh->mFaces.size(); i++) {
108        if (mWireFrame)
109          glBegin(GL_LINE_LOOP);
110        else
111          glBegin(GL_POLYGON);
112
113        Face *face = mesh->mFaces[i];
114        for (int j = 0; j < face->mVertexIndices.size(); j++) {
115          glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x);
116        }
117        glEnd();
118  }
119}
120       
121void
122GlRenderer::InitGL()
123{
124  glMatrixMode(GL_PROJECTION);
125  glLoadIdentity();
126 
127  glMatrixMode(GL_MODELVIEW);
128  glLoadIdentity();
129
130  glEnable(GL_CULL_FACE);
131  glShadeModel(GL_FLAT);
132  glEnable(GL_DEPTH_TEST);
133  glEnable(GL_CULL_FACE);
134 
135  glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)
136        wglGetProcAddress("glGenOcclusionQueriesNV");
137  glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)
138        wglGetProcAddress("glBeginOcclusionQueryNV");
139  glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)
140        wglGetProcAddress("glEndOcclusionQueryNV");
141  glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)
142        wglGetProcAddress("glGetOcclusionQueryuivNV");
143
144  // initialise second depth buffer texture
145  glGenTextures(1, &depthMap);
146  glBindTexture(GL_TEXTURE_2D, depthMap);
147 
148  glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
149                           depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
150  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
151  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
152  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
153  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
154
155  // cg initialization
156  cgSetErrorCallback(handleCgError);
157  sCgContext = cgCreateContext();
158
159  if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
160          sCgFragmentProfile = CG_PROFILE_ARBFP1;
161  else {
162          // try FP30
163          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
164            sCgFragmentProfile = CG_PROFILE_FP30;
165          else {
166                  fprintf(stderr, "Neither arbfp1 or fp30 fragment profiles supported on this system.\n");
167                  exit(1);
168          }
169  }
170
171  sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,             
172                                                                                           CG_SOURCE, "../src/dual_depth.cg",
173                                                                                           sCgFragmentProfile,
174                                                                                           NULL,
175                                                                                           NULL);
176
177  if (!cgIsProgramCompiled(sCgFragmentProgram))
178          cgCompileProgram(sCgFragmentProgram);
179
180  cgGLLoadProgram(sCgFragmentProgram);
181  cgGLBindProgram(sCgFragmentProgram);
182 // Debug << "LAST LISTING----" << cgGetLastListing(sCgContext) << "----\n";
183
184  Debug << "---- PROGRAM BEGIN ----\n" <<
185          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
186}
187
188
189
190void
191GlRenderer::SetupProjection(const int w, const int h)
192{
193  glViewport(0, 0, w, h);
194  glMatrixMode(GL_PROJECTION);
195  glLoadIdentity();
196  gluPerspective(70.0, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
197  glMatrixMode(GL_MODELVIEW);
198}
199
200void
201GlRenderer::SetupCamera()
202{
203  Vector3 target = mViewPoint + mViewDirection;
204  Vector3 up(0,1,0);
205 
206  glLoadIdentity();
207  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
208                        target.x, target.y, target.z,
209                        up.x, up.y, up.z);
210}
211
212void
213GlRenderer::RandomViewPoint()
214{
215  Vector3 pVector = Vector3(halton.GetNumber(1),
216                                                        halton.GetNumber(2),
217                                                        halton.GetNumber(3));
218 
219  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
220                                                        M_PI*halton.GetNumber(5),
221                                                        0.0f);
222 
223  mViewPoint = mSceneGraph->GetBox().GetPoint(pVector);
224 
225  mViewDirection = Normalize(Vector3(sin(dVector.x),
226                                                                         //                                                                      cos(dVector.y),
227                                                                         0.0f,
228                                                                         cos(dVector.x)));
229
230  halton.GenerateNext();
231}
232
233
234float
235GlRenderer::GetPixelError()
236{
237  float pErrorPixels = -1.0f;
238
239  glReadBuffer(GL_BACK);
240 
241  mUseFalseColors = true;
242
243  SetupCamera();
244  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
245  glEnable( GL_CULL_FACE );
246 
247  RenderScene();
248
249  // now check whether any backfacing polygon would pass the depth test
250  static int query = -1;
251  if (query == -1)
252        glGenOcclusionQueriesNV(1, (unsigned int *)&query);
253 
254  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
255  glDepthMask(GL_FALSE);
256  glDisable( GL_CULL_FACE );
257 
258  glBeginOcclusionQueryNV(query);
259 
260  RenderScene();
261 
262  glEndOcclusionQueryNV();
263
264  // at this point, if possible, go and do some other computation
265  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
266  glDepthMask(GL_TRUE);
267  glEnable( GL_CULL_FACE );
268 
269  unsigned int pixelCount;
270  // reenable other state
271  glGetOcclusionQueryuivNV(query,
272                                                   GL_PIXEL_COUNT_NV,
273                                                   &pixelCount);
274
275  if (pixelCount > 0)
276        return -1.0f; // backfacing polygon found -> not a valid viewspace sample
277
278  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
279 
280  if (viewcell) {
281        SetupCamera();
282        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
283
284        // Render PVS
285        std::map<Intersectable *,
286          PvsData<Intersectable *>,
287          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
288       
289        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
290          Intersectable *object = (*it).first;
291          RenderIntersectable(object);
292        }
293
294        glBeginOcclusionQueryNV(query);
295
296        SetupCamera();
297
298        RenderScene();
299       
300        glEndOcclusionQueryNV();
301       
302
303        unsigned int pixelCount;
304        // reenable other state
305        glGetOcclusionQueryuivNV(query,
306                                                         GL_PIXEL_COUNT_NV,
307                                                         &pixelCount);
308       
309        pErrorPixels = (100.f*pixelCount)/(GetWidth()*GetHeight());
310  }
311 
312  return pErrorPixels;
313}
314
315
316float
317GlRendererWidget::RenderErrors()
318{
319  float pErrorPixels = -1.0f;
320
321  glReadBuffer(GL_BACK);
322 
323  mUseFalseColors = true;
324
325  SetupCamera();
326  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
327  glEnable( GL_CULL_FACE );
328 
329  ObjectContainer::const_iterator oi = mObjects.begin();
330  for (; oi != mObjects.end(); oi++)
331        RenderIntersectable(*oi);
332
333  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
334 
335  QImage im1, im2;
336  QImage diff;
337 
338  if (viewcell) {
339        // read back the texture
340        im1 = grabFrameBuffer(true);
341       
342        SetupCamera();
343        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
344       
345        std::map<Intersectable *,
346          PvsData<Intersectable *>,
347          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
348       
349        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
350          Intersectable *object = (*it).first;
351          RenderIntersectable(object);
352        }
353
354        // read back the texture
355        im2 = grabFrameBuffer(true);
356       
357        diff = im1;
358        int x, y;
359        int errorPixels = 0;
360       
361        for (y = 0; y < im1.height(); y++)
362          for (x = 0; x < im1.width(); x++)
363                if (im1.pixel(x, y) == im2.pixel(x, y))
364                  diff.setPixel(x, y, qRgba(0,0,0,0));
365                else {
366                  diff.setPixel(x, y, qRgba(255,128,128,255));
367                  errorPixels++;
368                }
369        pErrorPixels = (100.f*errorPixels)/(im1.height()*im1.width());
370  }
371
372  // now render the pvs again
373  SetupCamera();
374  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
375  mUseFalseColors = false;
376       
377  oi = mObjects.begin();
378  for (; oi != mObjects.end(); oi++)
379        RenderIntersectable(*oi);
380
381  // now render im1
382  if (viewcell) {
383        if (mTopView) {
384          mWireFrame = true;
385          RenderMeshInstance(viewcell);
386          mWireFrame = false;
387        }
388       
389        // init ortographic projection
390        glMatrixMode(GL_PROJECTION);
391        glPushMatrix();
392       
393        glLoadIdentity();
394        gluOrtho2D(0, 1.0f, 0, 1.0f);
395       
396        glMatrixMode(GL_MODELVIEW);
397        glLoadIdentity();
398       
399        bindTexture(diff);
400       
401        glPushAttrib(GL_ENABLE_BIT);
402        glEnable( GL_ALPHA_TEST );
403        glDisable( GL_CULL_FACE );
404        glAlphaFunc( GL_GREATER, 0.5 );
405       
406        glEnable( GL_TEXTURE_2D );
407        glBegin(GL_QUADS);
408       
409        glTexCoord2f(0,0);
410        glVertex3f(0,0,0);
411       
412        glTexCoord2f(1,0);
413        glVertex3f( 1, 0, 0);
414       
415        glTexCoord2f(1,1);
416        glVertex3f( 1, 1, 0);
417       
418        glTexCoord2f(0,1);
419        glVertex3f(0, 1, 0);
420        glEnd();
421       
422        glPopAttrib();
423       
424        // restore the projection matrix
425        glMatrixMode(GL_PROJECTION);
426        glPopMatrix();
427        glMatrixMode(GL_MODELVIEW);
428  }
429
430  return pErrorPixels;
431}
432
433
434bool
435GlRenderer::RenderScene()
436{
437  static int glList = -1;
438  if (glList != -1) {
439        glCallList(glList);
440  } else {
441        glList = glGenLists(1);
442        glNewList(glList, GL_COMPILE_AND_EXECUTE);
443        ObjectContainer::const_iterator oi = mObjects.begin();
444        for (; oi != mObjects.end(); oi++)
445          RenderIntersectable(*oi);
446        glEndList();
447  }
448  return true;
449}
450
451
452void
453GlRendererBuffer::ClearErrorBuffer()
454{
455  for (int i=0; i < mPvsStatFrames; i++) {
456        mPvsErrorBuffer[i] = 1.0f;
457  }
458}
459
460
461void
462GlRendererBuffer::EvalPvsStat()
463{
464  mPvsStat.Reset();
465  halton.Reset();
466
467  makeCurrent();
468  SetupProjection(GetWidth(), GetHeight());
469 
470  for (int i=0; i < mPvsStatFrames; i++) {
471        float err;
472        RandomViewPoint();
473        if (mPvsErrorBuffer[i] > 0.0f) {
474          mPvsErrorBuffer[i] = GetPixelError();
475          cout<<"("<<i<<","<<mPvsErrorBuffer[i]<<")";
476          //      swapBuffers();
477        }
478       
479        err = mPvsErrorBuffer[i];
480       
481        if (err >= 0.0f) {
482          if (err > mPvsStat.maxError)
483                mPvsStat.maxError = err;
484          mPvsStat.sumError += err;
485          if (err == 0.0f)
486                mPvsStat.errorFreeFrames++;
487          mPvsStat.frames++;
488        }
489  }
490 
491  doneCurrent();
492
493  cout<<endl<<flush;
494  mRenderingFinished.wakeAll();
495}
496
497
498
499
500
501void
502GlRendererWidget::mousePressEvent(QMouseEvent *e)
503{
504  int x = e->pos().x();
505  int y = e->pos().y();
506
507  mousePoint.x = x;
508  mousePoint.y = y;
509 
510}
511
512void
513GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
514{
515  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
516  float TURN_SENSITIVITY=0.1f;
517  float TILT_SENSITIVITY=32.0 ;
518  float TURN_ANGLE= M_PI/36.0 ;
519
520  int x = e->pos().x();
521  int y = e->pos().y();
522 
523  if (e->modifiers() & Qt::ControlModifier) {
524        mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
525        mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
526  } else {
527        mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
528        float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
529        float angle = atan2(mViewDirection.x, mViewDirection.z);
530        mViewDirection.x = sin(angle+adiff);
531        mViewDirection.z = cos(angle+adiff);
532  }
533 
534  mousePoint.x = x;
535  mousePoint.y = y;
536 
537  updateGL();
538}
539
540void
541GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
542{
543
544
545}
546
547void
548GlRendererWidget::resizeGL(int w, int h)
549{
550  SetupProjection(w, h);
551  updateGL();
552}
553
554void
555GlRendererWidget::paintGL()
556{
557  RenderErrors();
558  mFrame++;
559}
560
561
562void
563GlRendererWidget::SetupCamera()
564{
565  if (!mTopView)
566        GlRenderer::SetupCamera();
567  else {
568        float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
569        Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
570                                                                                        -1,
571                                                                                        mViewDirection.y);
572       
573        Vector3 target = mViewPoint + dist*mViewDirection;
574        Vector3 up(0,1,0);
575       
576        glLoadIdentity();
577        gluLookAt(pos.x, pos.y, pos.z,
578                          target.x, target.y, target.z,
579                          up.x, up.y, up.z);
580  }
581
582}
583
584void
585GlRendererWidget::keyPressEvent ( QKeyEvent * e )
586{
587  switch (e->key()) {
588  case Qt::Key_T:
589        mTopView = !mTopView;
590        updateGL();
591        break;
592  default:
593        e->ignore();
594        break;
595  }
596 
597}
598
599
600void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
601                                                                                           Beam &beam,
602                                                                                           const int desiredSamples,
603                                                                                           BeamSampleStatistics &stat)
604{
605        // TODO: should not be done every time here
606        // only back faces are interesting for the depth pass
607        glShadeModel(GL_FLAT);
608        glDisable(GL_LIGHTING);
609        // needed to kill the fragments for the front buffer
610        glEnable(GL_ALPHA_TEST);
611        glAlphaFunc(GL_GREATER, 0);
612
613        // assumes that the beam is constructed and contains kd-tree nodes
614        // and viewcells which it intersects
615 
616 
617        // Get the number of viewpoints to be sampled
618        // Now it is a sqrt but in general a wiser decision could be made.
619        // The less viewpoints the better for rendering performance, since less passes
620        // over the beam is needed.
621        // The viewpoints could actually be generated outside of the bounding box which
622        // would distribute the 'efective viewpoints' of the object surface and thus
623        // with a few viewpoints better sample the vipoint space....
624 
625        int viewPointSamples = sqrt((float)desiredSamples);
626
627        // the number of direction samples per pass is given by the number of viewpoints
628        int directionalSamples = desiredSamples/viewPointSamples;
629       
630        for (int i = 0; i < viewPointSamples; ++ i)
631        {
632                Vector3 viewPoint = beam.mBox.GetRandomPoint();
633               
634                // perhaps the viewpoint should be shifted back a little bit so that it always lies
635                // inside the source object
636                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
637        // would require more complicated sampling (perhaps hierarchical rejection sampling of
638                // the object surface is an option here - only the mesh faces which are inside the box
639                // are considered as candidates)
640               
641                SampleViewpointContributions(sourceObject,
642                                                                         viewPoint,
643                                                                         beam,
644                                                                         directionalSamples,
645                                                                         stat);
646        }
647
648
649        // note:
650        // this routine would be called only if the number of desired samples is sufficiently
651        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
652        // distributing the work between cpu and gpu would also allow us to place more sophisticated
653        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
654        // in order that thios scheme is working well the gpu render buffer should run in a separate
655        // thread than the cpu sampler, which would not be such a big problem....
656}
657
658
659void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
660                                                                                                        const Vector3 viewPoint,
661                                                                                                        Beam &beam,
662                                                                                                        const int desiredSamples,
663                                                    BeamSampleStatistics &stat)
664{
665        // 1. setup the view port to match the desired samples
666        glViewport(0, 0, desiredSamples, desiredSamples);
667
668        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
669        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
670       
671        // 3. reset z-buffer to 0 and render the source object for the beam
672        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
673        //    save result to depth map
674        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
675        glEnable(GL_CULL_FACE);
676        glEnable(GL_STENCIL_TEST);
677        glCullFace(GL_FRONT);
678        glColorMask(0, 0, 0, 0);
679       
680        // stencil is increased where the source object is located
681        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
682        glStencilOp(GL_INCR, GL_INCR, GL_INCR);
683
684#if 0
685        static int glSourceObjList = -1;         
686        if (glSourceObjList != -1)
687        {
688                glSourceObjList = glGenLists(1);
689                glNewList(glSourceObjList, GL_COMPILE);
690
691                RenderIntersectable(sourceObject);
692       
693                glEndList();
694        }
695        glCallList(glSourceObjList);
696
697#else
698        RenderIntersectable(sourceObject);
699
700#endif 
701
702        // 4. set back to normal rendering and clear the ray termination depth buffer
703        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
704        glColorMask(1, 1, 1, 1);
705       
706        // 5. render all objects inside the beam using id based false color
707        //    (objects can be compiled to a gl list now so that subsequent rendering for
708        //     this beam is fast - the same hold for step 3)
709
710        if (beam.mFlags & !Beam::STORE_OBJECTS)
711        {
712                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
713
714                Intersectable::NewMail();
715                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
716                {
717                        mKdTree->CollectObjects(*it, beam.mObjects);
718                }
719        }
720
721        // list of objects intersected by the frustum
722#if 0
723        static int glObjList = -1;
724        if (glObjList != -1)
725        {
726                glObjList = glGenLists(1);
727                glNewList(glObjList, GL_COMPILE);
728       
729                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
730                for (it = beam.mObjects.begin(); it != it_end; ++ it)
731                        RenderIntersectable(*it);
732               
733                glEndList();
734        }
735        glCallList(glObjList);
736#else
737        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
738                for (it = beam.mObjects.begin(); it != it_end; ++ it)
739                        RenderIntersectable(*it);
740#endif
741
742        // remove objects again
743        if (beam.mFlags & !Beam::STORE_OBJECTS)
744                beam.mObjects.clear();
745
746        // bind ray origin depth buffer
747        glBindTexture(GL_TEXTURE_2D, depthMap);
748    glEnable(GL_TEXTURE_2D);
749       
750
751        //Read the depth buffer into the shadow map texture
752        glBindTexture(GL_TEXTURE_2D, depthMap);
753        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
754
755       
756        // 6. Now we have a two depth buffers defining the ray origin and termination
757        //    only rays which have non-zero entry in the origin buffer are valid since
758        //    they realy start on the object surface (this can also be tagged by setting a
759        //    stencil buffer bit at step 3)
760        glStencilFunc(GL_EQUAL, 0x1, 0x1);
761 
762        //cgGLBindProgram(sCgFragmentProgram);
763        cgGLEnableProfile(sCgFragmentProfile);
764
765        // 7. Use occlusion queries for all viewcell meshes associated with the beam ->
766        // a fragment passes if the corresponding stencil fragment is set and its depth is
767        // between origin and termination buffer
768
769        // create new queries if necessary
770        GenQueries((int)beam.mViewCells.size());
771
772        // now check whether any backfacing polygon would pass the depth test
773        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
774        glDepthMask(GL_FALSE);
775        glDisable(GL_CULL_FACE);
776 
777        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
778
779        int queryIdx = 0;
780
781        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
782        {
783                glBeginOcclusionQueryNV(sQueries[queryIdx ++]);
784
785                RenderIntersectable(*vit);
786               
787                glEndOcclusionQueryNV();
788        }
789
790        // at this point, if possible, go and do some other computation
791        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
792        glDepthMask(GL_TRUE);
793        glEnable(GL_CULL_FACE);
794
795        // 8. The number of visible pixels is the number of sample rays which see the source
796        //    object from the corresponding viewcell -> rember these values for later update
797        //   of the viewcell pvs - or update immediatelly?
798
799        //  In general it is not neccessary to rember to extract all the rays cast. I hope it
800        // would be sufficient to gain only the intergral statistics about the new contributions
801        // and so the rss tree would actually store no new rays (only the initial ones)
802        // the subdivision of the tree would only be driven by the statistics (the glrender could
803        // evaluate the contribution entropy for example)
804        // However might be an option to extract/store only those the rays which made a contribution
805        // (new viewcell has been discovered) or relative contribution greater than a threashold ...
806
807        cgGLDisableProfile(sCgFragmentProfile);
808        glDisable(GL_TEXTURE_2D);
809}
810
811
812void GlRendererBuffer::GenQueries(const int numQueries)
813{
814        if ((int)sQueries.size() < numQueries)
815        {
816                const int n = numQueries - (int)sQueries.size();
817                int *newQueries = new int[n];
818
819                glGenOcclusionQueriesNV(n, (unsigned int *)&newQueries);
820
821                for (int i = 0; i < n; ++ i)
822                {
823                        sQueries.push_back(newQueries[i]);
824                }
825
826                delete newQueries;
827        }
828}
829
830void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
831                                                                                                 const Beam &beam,
832                                                                                                 Intersectable *sourceObject)
833{
834        float left, right, bottom, top, znear, zfar;
835
836        beam.ComputeFrustum(left, right, bottom, top, znear, zfar,
837                                                mSceneGraph->GetBox());
838
839        glFrustum(left, right, bottom, top, znear, zfar);
840
841    const Vector3 eye = viewPoint + beam.GetMainDirection();
842        const Vector3 up;//AbitraryNormal(eye);
843
844        gluLookAt(eye.x, eye.y, eye.z,
845                          viewPoint.x, viewPoint.y, viewPoint.z,
846                          up.x, up.y, up.z);
847}                         
Note: See TracBrowser for help on using the repository browser.