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

Revision 542, 27.7 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 frontDepthMap;
19GLuint backDepthMap;
20
21const int depthMapSize = 512;
22static vector<int> sQueries;
23
24GlRendererWidget *rendererWidget = NULL;
25GlDebuggerWidget *debuggerWidget = NULL;
26
27
28#ifdef _WIN32
29PFNGLGENOCCLUSIONQUERIESNVPROC glGenOcclusionQueriesNV;
30PFNGLBEGINOCCLUSIONQUERYNVPROC glBeginOcclusionQueryNV;
31PFNGLENDOCCLUSIONQUERYNVPROC glEndOcclusionQueryNV;
32PFNGLGETOCCLUSIONQUERYUIVNVPROC glGetOcclusionQueryuivNV;
33#endif
34
35GlRenderer::GlRenderer(SceneGraph *sceneGraph,
36                                           ViewCellsManager *viewCellsManager,
37                                           KdTree *tree):
38  Renderer(sceneGraph, viewCellsManager),
39  mKdTree(tree)
40{
41  mSceneGraph->CollectObjects(&mObjects);
42  mViewPoint = mSceneGraph->GetBox().Center();
43  mViewDirection = Vector3(0,0,1);
44  //  timerId = startTimer(10);
45  mFrame = 0;
46  mWireFrame = false;
47}
48
49GlRenderer::~GlRenderer()
50{
51        cgDestroyProgram(sCgFragmentProgram);
52        cgDestroyContext(sCgContext);
53}
54
55
56static void handleCgError()
57{
58    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
59    exit(1);
60}
61
62void
63GlRenderer::RenderIntersectable(Intersectable *object)
64{
65
66  SetupFalseColor(object->mId);
67
68  switch (object->Type()) {
69  case Intersectable::MESH_INSTANCE:
70        RenderMeshInstance((MeshInstance *)object);
71        break;
72  case Intersectable::VIEW_CELL:
73          RenderViewCell(dynamic_cast<ViewCell *>(object));
74          break;
75  default:
76        cerr<<"Rendering this object not yet implemented\n";
77        break;
78  }
79}
80
81
82void
83GlRenderer::RenderViewCell(ViewCell *vc)
84{
85        if (vc->GetMesh())
86                RenderMesh(vc->GetMesh());
87}
88
89void
90GlRenderer::RenderMeshInstance(MeshInstance *mi)
91{
92  RenderMesh(mi->GetMesh());
93}
94
95void
96GlRenderer::SetupFalseColor(const int id)
97{
98  // swap bits of the color
99 
100  glColor3ub(id&255, (id>>8)&255, (id>>16)&255);
101}
102
103
104int GlRenderer::GetId(int r, int g, int b) const
105{
106        return r + (g << 8) + (b << 16);
107}
108
109void
110GlRenderer::SetupMaterial(Material *m)
111{
112  if (m)
113        glColor3fv(&(m->mDiffuseColor.r));
114  else
115        glColor3f(1.0f, 1.0f, 1.0f);
116}
117
118void
119GlRenderer::RenderMesh(Mesh *mesh)
120{
121  int i = 0;
122
123  if (!mUseFalseColors)
124        SetupMaterial(mesh->mMaterial);
125 
126  for (i=0; i < mesh->mFaces.size(); i++) {
127        if (mWireFrame)
128          glBegin(GL_LINE_LOOP);
129        else
130          glBegin(GL_POLYGON);
131
132        Face *face = mesh->mFaces[i];
133        for (int j = 0; j < face->mVertexIndices.size(); j++) {
134          glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x);
135        }
136        glEnd();
137  }
138}
139       
140void
141GlRenderer::InitGL()
142{
143  glMatrixMode(GL_PROJECTION);
144  glLoadIdentity();
145 
146  glMatrixMode(GL_MODELVIEW);
147  glLoadIdentity();
148
149  glEnable(GL_CULL_FACE);
150  glShadeModel(GL_FLAT);
151  glEnable(GL_DEPTH_TEST);
152  glEnable(GL_CULL_FACE);
153 
154  glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)
155        wglGetProcAddress("glGenOcclusionQueriesNV");
156  glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)
157        wglGetProcAddress("glBeginOcclusionQueryNV");
158  glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)
159        wglGetProcAddress("glEndOcclusionQueryNV");
160  glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)
161        wglGetProcAddress("glGetOcclusionQueryuivNV");
162}
163
164
165
166void
167GlRenderer::SetupProjection(const int w, const int h)
168{
169  glViewport(0, 0, w, h);
170  glMatrixMode(GL_PROJECTION);
171  glLoadIdentity();
172  gluPerspective(70.0, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
173  glMatrixMode(GL_MODELVIEW);
174}
175
176void
177GlRenderer::SetupCamera()
178{
179  Vector3 target = mViewPoint + mViewDirection;
180  Vector3 up(0,1,0);
181 
182  glLoadIdentity();
183  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
184                        target.x, target.y, target.z,
185                        up.x, up.y, up.z);
186}
187
188void
189GlRenderer::RandomViewPoint()
190{
191  Vector3 pVector = Vector3(halton.GetNumber(1),
192                                                        halton.GetNumber(2),
193                                                        halton.GetNumber(3));
194 
195  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
196                                                        M_PI*halton.GetNumber(5),
197                                                        0.0f);
198 
199  mViewPoint = mSceneGraph->GetBox().GetPoint(pVector);
200 
201  mViewDirection = Normalize(Vector3(sin(dVector.x),
202                                                                         //                                                                      cos(dVector.y),
203                                                                         0.0f,
204                                                                         cos(dVector.x)));
205
206  halton.GenerateNext();
207}
208
209
210float
211GlRenderer::GetPixelError()
212{
213  float pErrorPixels = -1.0f;
214
215  glReadBuffer(GL_BACK);
216 
217  mUseFalseColors = true;
218
219  SetupCamera();
220  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
221  glEnable( GL_CULL_FACE );
222 
223  RenderScene();
224
225  // now check whether any backfacing polygon would pass the depth test
226  static int query = -1;
227  if (query == -1)
228        glGenOcclusionQueriesNV(1, (unsigned int *)&query);
229 
230  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
231  glDepthMask(GL_FALSE);
232  glDisable( GL_CULL_FACE );
233 
234  glBeginOcclusionQueryNV(query);
235 
236  RenderScene();
237 
238  glEndOcclusionQueryNV();
239
240  // at this point, if possible, go and do some other computation
241  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
242  glDepthMask(GL_TRUE);
243  glEnable( GL_CULL_FACE );
244 
245  unsigned int pixelCount;
246  // reenable other state
247  glGetOcclusionQueryuivNV(query,
248                                                   GL_PIXEL_COUNT_NV,
249                                                   &pixelCount);
250
251  if (pixelCount > 0)
252        return -1.0f; // backfacing polygon found -> not a valid viewspace sample
253
254  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
255 
256  if (viewcell) {
257        SetupCamera();
258        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
259
260        // Render PVS
261        std::map<Intersectable *,
262          PvsData<Intersectable *>,
263          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
264       
265        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
266          Intersectable *object = (*it).first;
267          RenderIntersectable(object);
268        }
269
270        glBeginOcclusionQueryNV(query);
271
272        SetupCamera();
273
274        RenderScene();
275       
276        glEndOcclusionQueryNV();
277       
278
279        unsigned int pixelCount;
280        // reenable other state
281        glGetOcclusionQueryuivNV(query,
282                                                         GL_PIXEL_COUNT_NV,
283                                                         &pixelCount);
284       
285        pErrorPixels = (100.f*pixelCount)/(GetWidth()*GetHeight());
286  }
287 
288  return pErrorPixels;
289}
290
291
292float
293GlRendererWidget::RenderErrors()
294{
295  float pErrorPixels = -1.0f;
296
297  glReadBuffer(GL_BACK);
298 
299  mUseFalseColors = true;
300
301  SetupCamera();
302  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
303  glEnable( GL_CULL_FACE );
304 
305  ObjectContainer::const_iterator oi = mObjects.begin();
306  for (; oi != mObjects.end(); oi++)
307        RenderIntersectable(*oi);
308
309  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
310 
311  QImage im1, im2;
312  QImage diff;
313 
314  if (viewcell) {
315        // read back the texture
316        im1 = grabFrameBuffer(true);
317       
318        SetupCamera();
319        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
320       
321        std::map<Intersectable *,
322          PvsData<Intersectable *>,
323          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
324       
325        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
326          Intersectable *object = (*it).first;
327          RenderIntersectable(object);
328        }
329
330        // read back the texture
331        im2 = grabFrameBuffer(true);
332       
333        diff = im1;
334        int x, y;
335        int errorPixels = 0;
336       
337        for (y = 0; y < im1.height(); y++)
338          for (x = 0; x < im1.width(); x++)
339                if (im1.pixel(x, y) == im2.pixel(x, y))
340                  diff.setPixel(x, y, qRgba(0,0,0,0));
341                else {
342                  diff.setPixel(x, y, qRgba(255,128,128,255));
343                  errorPixels++;
344                }
345        pErrorPixels = (100.f*errorPixels)/(im1.height()*im1.width());
346  }
347
348  // now render the pvs again
349  SetupCamera();
350  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
351  mUseFalseColors = false;
352       
353  oi = mObjects.begin();
354  for (; oi != mObjects.end(); oi++)
355        RenderIntersectable(*oi);
356
357  // now render im1
358  if (viewcell) {
359        if (mTopView) {
360          mWireFrame = true;
361          RenderMeshInstance(viewcell);
362          mWireFrame = false;
363        }
364       
365        // init ortographic projection
366        glMatrixMode(GL_PROJECTION);
367        glPushMatrix();
368       
369        glLoadIdentity();
370        gluOrtho2D(0, 1.0f, 0, 1.0f);
371       
372        glMatrixMode(GL_MODELVIEW);
373        glLoadIdentity();
374       
375        bindTexture(diff);
376       
377        glPushAttrib(GL_ENABLE_BIT);
378        glEnable( GL_ALPHA_TEST );
379        glDisable( GL_CULL_FACE );
380        glAlphaFunc( GL_GREATER, 0.5 );
381       
382        glEnable( GL_TEXTURE_2D );
383        glBegin(GL_QUADS);
384       
385        glTexCoord2f(0,0);
386        glVertex3f(0,0,0);
387       
388        glTexCoord2f(1,0);
389        glVertex3f( 1, 0, 0);
390       
391        glTexCoord2f(1,1);
392        glVertex3f( 1, 1, 0);
393       
394        glTexCoord2f(0,1);
395        glVertex3f(0, 1, 0);
396        glEnd();
397       
398        glPopAttrib();
399       
400        // restore the projection matrix
401        glMatrixMode(GL_PROJECTION);
402        glPopMatrix();
403        glMatrixMode(GL_MODELVIEW);
404  }
405
406  return pErrorPixels;
407}
408
409
410bool
411GlRenderer::RenderScene()
412{
413  static int glList = -1;
414  if (glList == -1)
415  {
416        glList = glGenLists(1);
417        glNewList(glList, GL_COMPILE);
418        ObjectContainer::const_iterator oi = mObjects.begin();
419        for (; oi != mObjects.end(); oi++)
420          RenderIntersectable(*oi);
421        glEndList();
422  }
423 
424  glCallList(glList);
425 
426  return true;
427}
428
429
430void
431GlRendererBuffer::ClearErrorBuffer()
432{
433  for (int i=0; i < mPvsStatFrames; i++) {
434        mPvsErrorBuffer[i] = 1.0f;
435  }
436}
437
438
439void
440GlRendererBuffer::EvalPvsStat()
441{
442  mPvsStat.Reset();
443  halton.Reset();
444
445  makeCurrent();
446  SetupProjection(GetWidth(), GetHeight());
447 
448  for (int i=0; i < mPvsStatFrames; i++) {
449        float err;
450        RandomViewPoint();
451        if (mPvsErrorBuffer[i] > 0.0f) {
452          mPvsErrorBuffer[i] = GetPixelError();
453          cout<<"("<<i<<","<<mPvsErrorBuffer[i]<<")";
454          //      swapBuffers();
455        }
456       
457        err = mPvsErrorBuffer[i];
458       
459        if (err >= 0.0f) {
460          if (err > mPvsStat.maxError)
461                mPvsStat.maxError = err;
462          mPvsStat.sumError += err;
463          if (err == 0.0f)
464                mPvsStat.errorFreeFrames++;
465          mPvsStat.frames++;
466        }
467  }
468 
469  doneCurrent();
470
471  cout<<endl<<flush;
472  mRenderingFinished.wakeAll();
473}
474
475
476
477
478
479void
480GlRendererWidget::mousePressEvent(QMouseEvent *e)
481{
482  int x = e->pos().x();
483  int y = e->pos().y();
484
485  mousePoint.x = x;
486  mousePoint.y = y;
487 
488}
489
490void
491GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
492{
493  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
494  float TURN_SENSITIVITY=0.1f;
495  float TILT_SENSITIVITY=32.0 ;
496  float TURN_ANGLE= M_PI/36.0 ;
497
498  int x = e->pos().x();
499  int y = e->pos().y();
500 
501  if (e->modifiers() & Qt::ControlModifier) {
502        mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
503        mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
504  } else {
505        mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
506        float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
507        float angle = atan2(mViewDirection.x, mViewDirection.z);
508        mViewDirection.x = sin(angle+adiff);
509        mViewDirection.z = cos(angle+adiff);
510  }
511 
512  mousePoint.x = x;
513  mousePoint.y = y;
514 
515  updateGL();
516}
517
518void
519GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
520{
521
522
523}
524
525void
526GlRendererWidget::resizeGL(int w, int h)
527{
528  SetupProjection(w, h);
529  updateGL();
530}
531
532void
533GlRendererWidget::paintGL()
534{
535        RenderErrors();
536       
537        mFrame++;
538}
539
540
541void
542GlRendererWidget::SetupCamera()
543{
544  if (!mTopView)
545        GlRenderer::SetupCamera();
546  else {
547        float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
548        Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
549                                                                                        -1,
550                                                                                        mViewDirection.y);
551       
552        Vector3 target = mViewPoint + dist*mViewDirection;
553        Vector3 up(0,1,0);
554       
555        glLoadIdentity();
556        gluLookAt(pos.x, pos.y, pos.z,
557                          target.x, target.y, target.z,
558                          up.x, up.y, up.z);
559  }
560
561}
562
563void
564GlRendererWidget::keyPressEvent ( QKeyEvent * e )
565{
566  switch (e->key()) {
567  case Qt::Key_T:
568        mTopView = !mTopView;
569        updateGL();
570        break;
571  default:
572        e->ignore();
573        break;
574  }
575 
576}
577
578
579void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
580                                                                                           Beam &beam,
581                                                                                           const int desiredSamples,
582                                                                                           BeamSampleStatistics &stat)
583{
584        // create beam mesh if not already doen
585        //TODO: should this be done here?
586       
587        beam.CreateMesh(2.0f * Magnitude(mSceneGraph->GetBox().Diagonal()));
588
589        // TODO: should not be done every time here
590        // only back faces are interesting for the depth pass
591        glShadeModel(GL_FLAT);
592        glDisable(GL_LIGHTING);
593        // needed to kill the fragments for the front buffer
594        glEnable(GL_ALPHA_TEST);
595        glAlphaFunc(GL_GREATER, 0);
596
597        // assumes that the beam is constructed and contains kd-tree nodes
598        // and viewcells which it intersects
599 
600 
601        // Get the number of viewpoints to be sampled
602        // Now it is a sqrt but in general a wiser decision could be made.
603        // The less viewpoints the better for rendering performance, since less passes
604        // over the beam is needed.
605        // The viewpoints could actually be generated outside of the bounding box which
606        // would distribute the 'efective viewpoints' of the object surface and thus
607        // with a few viewpoints better sample the vipoint space....
608  //TODO: remove
609        //int viewPointSamples = sqrt((float)desiredSamples);
610        int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
611       
612        // the number of direction samples per pass is given by the number of viewpoints
613        int directionalSamples = desiredSamples / viewPointSamples;
614       
615        Debug << "directional samples: " << directionalSamples << endl;
616        for (int i = 0; i < viewPointSamples; ++ i)
617        {
618                Vector3 viewPoint = beam.mBox.GetRandomPoint();
619               
620                // perhaps the viewpoint should be shifted back a little bit so that it always lies
621                // inside the source object
622                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
623        // would require more complicated sampling (perhaps hierarchical rejection sampling of
624                // the object surface is an option here - only the mesh faces which are inside the box
625                // are considered as candidates)
626               
627                SampleViewpointContributions(sourceObject,
628                                                                         viewPoint,
629                                                                         beam,
630                                                                         directionalSamples,
631                                                                         stat);
632        }
633
634
635        // note:
636        // this routine would be called only if the number of desired samples is sufficiently
637        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
638        // distributing the work between cpu and gpu would also allow us to place more sophisticated
639        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
640        // in order that thios scheme is working well the gpu render buffer should run in a separate
641        // thread than the cpu sampler, which would not be such a big problem....
642}
643
644
645void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
646                                                                                                        const Vector3 viewPoint,
647                                                                                                        Beam &beam,
648                                                                                                        const int samples,
649                                                    BeamSampleStatistics &stat)
650{
651    // 1. setup the view port to match the desired samples
652        glViewport(0, 0, GetWidth(), GetHeight());
653
654        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
655        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
656
657        // 3. reset z-buffer to 0 and render the source object for the beam
658        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
659        //    save result to depth map
660
661        // front depth buffer must bé initialised to 0
662        float clearDepth;
663        glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
664        glClearDepth(0.0f);
665       
666
667        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
668        //glFrontFace(GL_CW);
669        glEnable(GL_CULL_FACE);
670        glCullFace(GL_FRONT);
671        glColorMask(0, 0, 0, 0);
672       
673
674        // stencil is increased where the source object is located
675        glEnable(GL_STENCIL_TEST);     
676        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
677        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
678
679#if 0
680        static int glSourceObjList = -1;         
681        if (glSourceObjList != -1)
682        {
683                glSourceObjList = glGenLists(1);
684                glNewList(glSourceObjList, GL_COMPILE);
685
686                RenderIntersectable(sourceObject);
687       
688                glEndList();
689        }
690        glCallList(glSourceObjList);
691
692#else
693        RenderIntersectable(sourceObject);
694
695#endif 
696        // reset clear function
697        glClearDepth(clearDepth);
698
699        // copy contents of depth buffer into depth texture
700        // depth buffer holds ray origins
701        glBindTexture(GL_TEXTURE_2D, frontDepthMap);   
702        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
703
704
705#if 0
706        // only the samples which are inside the beam AND on the source object
707        // should be considered => only where stencil == 2
708        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
709        glStencilFunc(GL_ALWAYS, 0x2, 0x2);
710        glStencilOp(GL_INCR, GL_INCR, GL_INCR);
711
712        // render back face of frustum beam
713        RenderMesh(beam.mMesh);
714#endif
715
716
717        // 4. set back to normal rendering and clear the ray termination depth buffer
718        //    only rays which have non-zero entry in the origin buffer are valid since
719        //    they realy start on the object surface (this can also be tagged by setting a
720        //    stencil buffer bit at step 3)
721
722        //glDisable(GL_STENCIL_TEST);
723        glEnable(GL_STENCIL_TEST);
724        glStencilFunc(GL_EQUAL, 0x1, 0x1);
725        //glStencilFunc(GL_EQUAL, 0x2, 0x2);
726        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
727
728        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
729        glColorMask(1, 1, 1, 1);
730        glDepthMask(1);
731        glEnable(GL_DEPTH_TEST);
732        //glDisable(GL_STENCIL_TEST);   
733        glEnable(GL_CULL_FACE);
734        glCullFace(GL_BACK);
735
736
737        // 5. render all objects inside the beam using id based false color
738        //    (objects can be compiled to a gl list now so that subsequent rendering for
739        //     this beam is fast - the same hold for step 3)
740
741        if (beam.mFlags & !Beam::STORE_OBJECTS)
742        {
743                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
744
745                Intersectable::NewMail();
746                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
747                {
748                        mKdTree->CollectObjects(*it, beam.mObjects);
749                }
750        }
751
752        // list of objects intersected by the frustum
753#if 0
754        static int glObjList = -1;
755        if (glObjList != -1)
756        {
757                glObjList = glGenLists(1);
758                glNewList(glObjList, GL_COMPILE);
759       
760                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
761                for (it = beam.mObjects.begin(); it != it_end; ++ it)
762                {
763                        if (*it != sourceObject)
764                                RenderIntersectable(*it);
765                }
766               
767                glEndList();
768        }
769        glCallList(glObjList);
770#else
771        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
772        for (it = beam.mObjects.begin(); it != it_end; ++ it)
773        {       
774                if (*it != sourceObject)
775                        RenderIntersectable(*it);
776        }
777#endif
778
779       
780    // 6. Now we have a two depth buffers defining the ray origin and termination
781
782       
783        // bind depth texture
784        glEnable(GL_TEXTURE_2D);
785       
786        // bind depth cull pixel shader
787        cgGLBindProgram(sCgFragmentProgram);
788        cgGLEnableProfile(sCgFragmentProfile);
789
790        // 7. Use occlusion queries for all viewcell meshes associated with the beam ->
791        // a fragment passes if the corresponding stencil fragment is set and its depth is
792        // between origin and termination buffer
793
794        // create new queries if necessary
795        GenQueries((int)beam.mViewCells.size());
796
797        // now check whether any backfacing polygon would pass the depth test?
798        //matt: should check both back /front facing because of dual depth buffer
799        //and danger of cutting the near plane with front facing polys.
800        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
801        glDepthMask(GL_FALSE);
802        glDisable(GL_CULL_FACE);
803 
804        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
805
806        int queryIdx = 0;
807
808        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
809        {
810                glBeginOcclusionQueryNV(sQueries[queryIdx ++]);
811
812                RenderIntersectable(*vit);
813               
814                glEndOcclusionQueryNV();
815        }
816
817        // at this point, if possible, go and do some other computation
818
819        queryIdx = 0;
820        unsigned int pixelCount;
821
822        // 8. The number of visible pixels is the number of sample rays which see the source
823        //    object from the corresponding viewcell -> remember these values for later update
824        //   of the viewcell pvs - or update immediately?
825
826        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
827        {
828                // fetch queries
829                glGetOcclusionQueryuivNV(sQueries[queryIdx ++],
830                                                                 GL_PIXEL_COUNT_NV,
831                                                                 &pixelCount);
832                if (pixelCount)
833                        Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
834        }
835       
836
837        //  In general it is not neccessary to remember to extract all the rays cast. I hope it
838        // would be sufficient to gain only the intergral statistics about the new contributions
839        // and so the rss tree would actually store no new rays (only the initial ones)
840        // the subdivision of the tree would only be driven by the statistics (the glrender could
841        // evaluate the contribution entropy for example)
842        // However might be an option to extract/store only those the rays which made a contribution
843        // (new viewcell has been discovered) or relative contribution greater than a threshold ...
844
845        ObjectContainer pvsObj;
846        stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
847       
848       
849#if 0
850        // copy contents of back depth buffer into depth texture
851        // depth buffer holds ray origins
852        glBindTexture(GL_TEXTURE_2D, backDepthMap);     
853        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
854#endif
855        // reset state
856        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
857        glDepthMask(GL_TRUE);
858        glEnable(GL_CULL_FACE);
859        glDisable(GL_STENCIL_TEST);
860        cgGLDisableProfile(sCgFragmentProfile);
861        glDisable(GL_TEXTURE_2D);
862
863        // remove objects again
864        if (beam.mFlags & !Beam::STORE_OBJECTS)
865                beam.mObjects.clear();
866}
867
868
869void GlRendererBuffer::GenQueries(const int numQueries)
870{
871        if ((int)sQueries.size() < numQueries)
872        {
873                const int n = numQueries - (int)sQueries.size();
874                unsigned int *newQueries = new unsigned int[n];
875
876                glGenOcclusionQueriesNV(n, (unsigned int *)newQueries);
877
878                for (int i = 0; i < n; ++ i)
879                {
880                        sQueries.push_back(newQueries[i]);
881                }
882
883                delete [] newQueries;
884        }
885}
886
887
888void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
889                                                                                                   const Beam &beam,
890                                                                                                   Intersectable *sourceObject)
891{
892        float left, right, bottom, top, znear, zfar;
893
894        beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
895                                                                   mSceneGraph->GetBox());
896
897        //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
898        glMatrixMode(GL_PROJECTION);
899        glLoadIdentity();
900        glFrustum(left, right, bottom, top, znear, zfar);
901        //glFrustum(-1, 1, -1, 1, 1, 20000);
902
903    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3;
904        const Vector3 up =
905                Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
906
907#ifdef _DEBUG
908        Debug << "view point: " << viewPoint << endl;
909        Debug << "eye: " << center << endl;
910        Debug << "up: " << up << endl;
911#endif
912
913        glMatrixMode(GL_MODELVIEW);
914        glLoadIdentity();
915        gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z,
916                          center.x, center.y, center.z,                   
917                          up.x, up.y, up.z);
918}               
919
920 
921void GlRendererBuffer::InitGL()
922{
923        GlRenderer::InitGL();
924        // initialise dual depth buffer textures
925        glGenTextures(1, &frontDepthMap);
926        glBindTexture(GL_TEXTURE_2D, frontDepthMap);
927       
928        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
929                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
930        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
931        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
932        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
933        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
934
935        glGenTextures(1, &backDepthMap);
936        glBindTexture(GL_TEXTURE_2D, backDepthMap);
937       
938        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
939                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
940        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
941        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
942        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
943        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
944
945        // cg initialization
946        cgSetErrorCallback(handleCgError);
947        sCgContext = cgCreateContext();
948       
949        if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
950                sCgFragmentProfile = CG_PROFILE_ARBFP1;
951        else
952        {
953          // try FP30
954          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
955            sCgFragmentProfile = CG_PROFILE_FP30;
956          else
957          {
958                  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
959                  exit(1);
960          }
961  }
962
963  sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,             
964                                                                                           CG_SOURCE, "../src/dual_depth.cg",
965                                                                                           sCgFragmentProfile,
966                                                                                           NULL,
967                                                                                           NULL);
968
969  if (!cgIsProgramCompiled(sCgFragmentProgram))
970          cgCompileProgram(sCgFragmentProgram);
971
972  cgGLLoadProgram(sCgFragmentProgram);
973  cgGLBindProgram(sCgFragmentProgram);
974 
975  Debug << "---- PROGRAM BEGIN ----\n" <<
976          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
977}
978
979
980void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
981{
982        for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
983        {
984                //todo glGetTexImage()
985        }
986}
987
988
989
990inline bool ilt(Intersectable *obj1, Intersectable *obj2)
991{
992        return obj1->mId < obj2->mId;
993}
994
995
996int GlRendererBuffer::ComputePvs(ObjectContainer &objects,
997                                                                 ObjectContainer &pvs) const
998{
999        int pvsSize = 0;
1000        QImage image = toImage();
1001        Intersectable::NewMail();
1002
1003        std::stable_sort(objects.begin(), objects.end(), ilt);
1004
1005        MeshInstance dummy(NULL);
1006
1007        Intersectable *obj = NULL;
1008                       
1009        for (int x = 0; x < image.width(); ++ x)
1010        {
1011                for (int y = 0; y < image.height(); ++ y)
1012                {
1013                        QRgb pix = image.pixel(x, y);
1014                        const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix));
1015
1016                        dummy.SetId(id);
1017
1018                        ObjectContainer::iterator oit =
1019                                lower_bound(objects.begin(), objects.end(), &dummy, ilt);
1020                       
1021                       
1022                        if (//(oit != oit.end()) &&
1023                                ((*oit)->GetId() == id) &&
1024                                !obj->Mailed())
1025                        {
1026                                obj = *oit;
1027                                obj->Mail();
1028                                ++ pvsSize;
1029                                pvs.push_back(obj);
1030                        }
1031                }
1032        }
1033
1034        return pvsSize;
1035}
1036
1037/***********************************************************************/
1038/*                     GlDebuggerWidget implementation                             */
1039/***********************************************************************/
1040
1041
1042GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent)
1043      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
1044{
1045        // create the pbuffer
1046    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
1047    timerId = startTimer(20);
1048    setWindowTitle(("OpenGL pbuffers"));
1049}
1050
1051
1052GlDebuggerWidget::~GlDebuggerWidget()
1053{
1054        mRenderBuffer->releaseFromDynamicTexture();
1055        glDeleteTextures(1, &dynamicTexture);
1056       
1057        DEL_PTR(mRenderBuffer);
1058}
1059
1060
1061void GlDebuggerWidget::initializeGL()
1062{
1063        glMatrixMode(GL_PROJECTION);
1064        glLoadIdentity();
1065
1066        glFrustum(-1, 1, -1, 1, 10, 100);
1067        glTranslatef(-0.5f, -0.5f, -0.5f);
1068        glTranslatef(0.0f, 0.0f, -15.0f);
1069        glMatrixMode(GL_MODELVIEW);
1070
1071        glEnable(GL_CULL_FACE);
1072        initCommon();
1073        initPbuffer();
1074
1075}
1076
1077
1078void GlDebuggerWidget::resizeGL(int w, int h)
1079{
1080        glViewport(0, 0, w, h);
1081}
1082
1083
1084void GlDebuggerWidget::paintGL()
1085{
1086        // draw a spinning cube into the pbuffer..
1087        mRenderBuffer->makeCurrent();
1088       
1089        BeamSampleStatistics stats;
1090        mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
1091
1092        glFlush();
1093
1094        // rendering directly to a texture is not supported on X11, unfortunately
1095    mRenderBuffer->updateDynamicTexture(dynamicTexture);
1096   
1097    // and use the pbuffer contents as a texture when rendering the
1098    // background and the bouncing cubes
1099    makeCurrent();
1100    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
1101    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1102
1103    // draw the background
1104    glMatrixMode(GL_MODELVIEW);
1105    glPushMatrix();
1106    glLoadIdentity();
1107    glMatrixMode(GL_PROJECTION);
1108    glPushMatrix();
1109    glLoadIdentity();
1110
1111        glPopMatrix();
1112        glMatrixMode(GL_MODELVIEW);
1113        glPopMatrix();
1114}
1115
1116
1117void GlDebuggerWidget::initPbuffer()
1118{
1119        // set up the pbuffer context
1120    mRenderBuffer->makeCurrent();
1121        /*mRenderBuffer->InitGL();
1122
1123        glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
1124        glMatrixMode(GL_PROJECTION);
1125        glLoadIdentity();
1126        glOrtho(-1, 1, -1, 1, -99, 99);
1127        glTranslatef(-0.5f, -0.5f, 0.0f);
1128        glMatrixMode(GL_MODELVIEW);
1129        glLoadIdentity();
1130
1131        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
1132       
1133        // generate a texture that has the same size/format as the pbuffer
1134    dynamicTexture = mRenderBuffer->generateDynamicTexture();
1135
1136        // bind the dynamic texture to the pbuffer - this is a no-op under X11
1137        mRenderBuffer->bindToDynamicTexture(dynamicTexture);
1138        makeCurrent();
1139}
1140
1141void GlDebuggerWidget::initCommon()
1142{
1143        glEnable(GL_TEXTURE_2D);
1144        glEnable(GL_DEPTH_TEST);
1145
1146        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1147}
Note: See TracBrowser for help on using the repository browser.