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

Revision 556, 27.7 KB checked in by bittner, 18 years ago (diff)

debug version looking for glrenderer bug...

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