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

Revision 572, 28.8 KB checked in by bittner, 18 years ago (diff)

gl render error estimation changes for backface culling empty viewspace detection

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