#include "Mesh.h" #include "glInterface.h" #include "OcclusionQuery.h" #include "GlRenderer.h" #include "ViewCellsManager.h" #include "SceneGraph.h" #include "Pvs.h" #include "Viewcell.h" #include "Beam.h" #include "KdTree.h" #include "Environment.h" #include "Triangle3.h" #include "IntersectableWrapper.h" #include "BvHierarchy.h" #include "KdTree.h" //#include //#include namespace GtpVisibilityPreprocessor { static bool arbQuerySupport = false; static bool nvQuerySupport = false; GLuint frontDepthMap; GLuint backDepthMap; const int depthMapSize = 512; static void InitExtensions() { GLenum err = glewInit(); if (GLEW_OK != err) { // problem: glewInit failed, something is seriously wrong cerr << "Error: " << glewGetErrorString(err) << endl; exit(1); } if (GLEW_ARB_occlusion_query) arbQuerySupport = true; if (GLEW_NV_occlusion_query) nvQuerySupport = true; if (!arbQuerySupport && !nvQuerySupport) { cout << "I require the GL_ARB_occlusion_query or the GL_NV_occlusion_query OpenGL extension to work.\n"; exit(1); } } GlRenderer::GlRenderer(SceneGraph *sceneGraph, ViewCellsManager *viewCellsManager, KdTree *tree): Renderer(sceneGraph, viewCellsManager), mKdTree(tree) { mSceneGraph->CollectObjects(&mObjects); // mViewCellsManager->GetViewPoint(mViewPoint); mViewPoint = mSceneGraph->GetBox().Center(); mViewDirection = Vector3(0,0,1); // mViewPoint = Vector3(991.7, 187.8, -271); // mViewDirection = Vector3(0.9, 0, -0.4); // timerId = startTimer(10); // debug coords for atlanta // mViewPoint = Vector3(3473, 6.778, -1699); // mViewDirection = Vector3(-0.2432, 0, 0.97); mFrame = 0; mWireFrame = false; Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace); mSnapErrorFrames = true; mSnapPrefix = "snap/"; mUseForcedColors = false; mRenderBoxes = false; // mUseGlLists = true; mUseGlLists = false; } GlRenderer::~GlRenderer() { cerr<<"gl renderer destructor..\n"; //CLEAR_CONTAINER(sQueries); CLEAR_CONTAINER(mOcclusionQueries); cerr<<"done."<GetItem(); glBegin(GL_TRIANGLES); glVertex3f(t.mVertices[0].x, t.mVertices[0].y, t.mVertices[0].z); glVertex3f(t.mVertices[1].x, t.mVertices[1].y, t.mVertices[1].z); glVertex3f(t.mVertices[2].x, t.mVertices[2].y, t.mVertices[2].z); glEnd(); } void GlRenderer::RenderIntersectable(Intersectable *object) { if (object->Mailed()) return; object->Mail(); glPushAttrib(GL_CURRENT_BIT); if (mUseFalseColors) SetupFalseColor(object->mId); switch (object->Type()) { case Intersectable::MESH_INSTANCE: RenderMeshInstance((MeshInstance *)object); break; case Intersectable::VIEW_CELL: RenderViewCell(dynamic_cast(object)); break; case Intersectable::TRANSFORMED_MESH_INSTANCE: RenderTransformedMeshInstance(dynamic_cast(object)); break; case Intersectable::TRIANGLE_INTERSECTABLE: RenderTriangle(dynamic_cast(object)); break; case Intersectable::BVH_INTERSECTABLE: { BvhNode *node = dynamic_cast(object); if (mRenderBoxes) RenderBox(node->GetBoundingBox()); else RenderBvhNode(node); break; } case Intersectable::KD_INTERSECTABLE: { KdNode *node = (dynamic_cast(object))->GetItem(); if (mRenderBoxes) RenderBox(mKdTree->GetBox(node)); else RenderKdNode(node); break; } default: cerr<<"Rendering this object not yet implemented\n"; break; } glPopAttrib(); } void GlRenderer::RenderRays(const VssRayContainer &rays) { VssRayContainer::const_iterator it = rays.begin(), it_end = rays.end(); glBegin(GL_LINES); for (; it != it_end; ++it) { VssRay *ray = *it; float importance = log10(1e3*ray->mWeightedPvsContribution)/3.0f; // cout<<"w="<mWeightedPvsContribution<<" r="<mWeightedPvsContribution; glColor3f(importance, importance, importance); glVertex3fv(&ray->mOrigin.x); glVertex3fv(&ray->mTermination.x); } glEnd(); } void GlRenderer::RenderViewCell(ViewCell *vc) { if (vc->GetMesh()) { if (!mUseFalseColors) { if (vc->GetValid()) glColor3f(0,1,0); else glColor3f(0,0,1); } RenderMesh(vc->GetMesh()); } else { // render viewcells in the subtree if (!vc->IsLeaf()) { ViewCellInterior *vci = (ViewCellInterior *) vc; ViewCellContainer::iterator it = vci->mChildren.begin(); for (; it != vci->mChildren.end(); ++it) { RenderViewCell(*it); } } else { // cerr<<"Empty viewcell mesh\n"; } } } void GlRenderer::RenderMeshInstance(MeshInstance *mi) { RenderMesh(mi->GetMesh()); } void GlRenderer::RenderTransformedMeshInstance(TransformedMeshInstance *mi) { // apply world transform before rendering Matrix4x4 m; mi->GetWorldTransform(m); glPushMatrix(); /* cout << "\n"; for (int i = 0; i < 4; ++ i) for (int j = 0; j < 4; ++ j) cout << m.x[i][j] << " "; cout << "\n"*/ glMultMatrixf((float *)m.x); /*GLfloat dummy[16]; glGetFloatv(GL_MODELVIEW_MATRIX, dummy); for (int i = 0; i < 16; ++ i) cout << dummy[i] << " "; cout << endl;*/ RenderMesh(mi->GetMesh()); glPopMatrix(); } void GlRenderer::SetupFalseColor(const int id) { // swap bits of the color glColor3ub(id&255, (id>>8)&255, (id>>16)&255); } int GlRenderer::GetId(int r, int g, int b) const { return r + (g << 8) + (b << 16); } void GlRenderer::SetupMaterial(Material *m) { if (m) glColor3fv(&(m->mDiffuseColor.r)); } void GlRenderer::RenderMesh(Mesh *mesh) { int i = 0; if (!mUseFalseColors && !mUseForcedColors) SetupMaterial(mesh->mMaterial); for (i=0; i < mesh->mFaces.size(); i++) { if (mWireFrame) glBegin(GL_LINE_LOOP); else glBegin(GL_POLYGON); Face *face = mesh->mFaces[i]; for (int j = 0; j < face->mVertexIndices.size(); j++) { glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x); } glEnd(); } } void GlRenderer::InitGL() { mSphere = (GLUquadric *)gluNewQuadric(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glFrontFace(GL_CCW); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); InitExtensions(); #if 0 GLfloat mat_ambient[] = { 0.5, 0.5, 0.5, 1.0 }; /* mat_specular and mat_shininess are NOT default values */ GLfloat mat_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_specular[] = { 0.3, 0.3, 0.3, 1.0 }; GLfloat mat_shininess[] = { 1.0 }; GLfloat light_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; GLfloat light_diffuse[] = { 0.4, 0.4, 0.4, 1.0 }; GLfloat light_specular[] = { 0.3, 0.3, 0.3, 1.0 }; GLfloat lmodel_ambient[] = { 0.3, 0.3, 0.3, 1.0 }; // default Material glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); // a light glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); // set position of the light GLfloat infinite_light[] = { 1.0, 0.8, 1.0, 0.0 }; glLightfv (GL_LIGHT0, GL_POSITION, infinite_light); // set position of the light2 GLfloat infinite_light2[] = { -0.3, 1.5, 1.0, 0.0 }; glLightfv (GL_LIGHT1, GL_POSITION, infinite_light2); glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); // glColorMaterial( GL_FRONT_AND_BACK, GL_SPECULAR); glEnable(GL_COLOR_MATERIAL); glShadeModel( GL_FLAT ); glDepthFunc( GL_LESS ); glEnable( GL_DEPTH_TEST ); #endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); glEnable( GL_NORMALIZE ); glClearColor(0.0f, 0.0f, 1.0f, 1.0f); } void GlRenderer::SetupProjection(const int w, const int h, const float angle) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(angle, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal())); glMatrixMode(GL_MODELVIEW); } void GlRenderer::SetupCamera() { Vector3 target = mViewPoint + mViewDirection; Vector3 up(0,1,0); if (abs(DotProd(mViewDirection, up)) > 0.99f) up = Vector3(1, 0, 0); glLoadIdentity(); gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z, target.x, target.y, target.z, up.x, up.y, up.z); } void GlRenderer::_RenderScene() { ObjectContainer::const_iterator oi = mObjects.begin(); for (; oi != mObjects.end(); oi++) RenderIntersectable(*oi); } bool GlRenderer::RenderScene() { Intersectable::NewMail(); static int glList = -1; if (mUseGlLists) { if (glList == -1) { glList = glGenLists(1); glNewList(glList, GL_COMPILE); _RenderScene(); glEndList(); } glCallList(glList); } else _RenderScene(); return true; } void GlRendererBuffer::EvalQueryWithItemBuffer( //RenderCostSample &sample ) { // read back the texture glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, mPixelBuffer); unsigned int *p = mPixelBuffer; for (int y = 0; y < GetHeight(); y++) { for (int x = 0; x < GetWidth(); x++, p++) { unsigned int id = (*p) & 0xFFFFFF; if (id != 0xFFFFFF) ++ mObjects[id]->mCounter; } } } /****************************************************************/ /* GlRendererBuffer implementation */ /****************************************************************/ GlRendererBuffer::GlRendererBuffer(SceneGraph *sceneGraph, ViewCellsManager *viewcells, KdTree *tree): GlRenderer(sceneGraph, viewcells, tree) { Environment::GetSingleton()->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames); mPvsErrorBuffer.resize(mPvsStatFrames); ClearErrorBuffer(); mPixelBuffer = NULL; // implement width and height in subclasses } void GlRendererBuffer::EvalQueryWithOcclusionQueries( //RenderCostSample &sample ) { glDepthFunc(GL_LEQUAL); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_FALSE); // simulate detectemptyviewspace using backface culling if (mDetectEmptyViewSpace) { glEnable(GL_CULL_FACE); //cout << "culling" << endl; } else { //cout << "not culling" << endl; glDisable(GL_CULL_FACE); } //const int numQ = 1; const int numQ = (int)mOcclusionQueries.size(); //glFinish(); #if 0 //-- now issue queries for all objects for (int j = 0; j < (int)mObjects.size(); ++ j) { mOcclusionQueries[j]->BeginQuery(); RenderIntersectable(mObjects[j]); mOcclusionQueries[j]->EndQuery(); unsigned int pixelCount; pixelCount = mOcclusionQueries[j]->GetQueryResult(); mObjects[j]->mCounter += pixelCount; } #else int q = 0; //-- now issue queries for all objects for (int j = 0; j < (int)mObjects.size(); j += q) { for (q = 0; ((j + q) < (int)mObjects.size()) && (q < numQ); ++ q) { //glFinish(); mOcclusionQueries[q]->BeginQuery(); RenderIntersectable(mObjects[j + q]); mOcclusionQueries[q]->EndQuery(); //glFinish(); } //cout << "q: " << q << endl; // collect results of the queries for (int t = 0; t < q; ++ t) { unsigned int pixelCount; //-- reenable other state #if 0 bool available; do { available = mOcclusionQueries[t]->ResultAvailable(); if (!available) cout << "W"; } while (!available); #endif pixelCount = mOcclusionQueries[t]->GetQueryResult(); //if (pixelCount > 0) // cout <<"o="<mCounter += pixelCount; } //j += q; } #endif //glFinish(); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); glEnable(GL_CULL_FACE); } void GlRendererBuffer::RandomViewPoint() { // do not use this function since it could return different viewpoints for // different executions of the algorithm // mViewCellsManager->GetViewPoint(mViewPoint); while (1) { Vector3 pVector = Vector3(halton.GetNumber(1), halton.GetNumber(2), halton.GetNumber(3)); mViewPoint = mViewCellsManager->GetViewSpaceBox().GetPoint(pVector); ViewCell *v = mViewCellsManager->GetViewCell(mViewPoint); if (v && v->GetValid()) break; // generate a new vector halton.GenerateNext(); } Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4), M_PI*halton.GetNumber(5), 0.0f); mViewDirection = Normalize(Vector3(sin(dVector.x), // cos(dVector.y), 0.0f, cos(dVector.x))); halton.GenerateNext(); } void GlRenderer::RenderBox(const AxisAlignedBox3 &box) { glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Min().z ); glVertex3d(box.Min().x, box.Min().y, box.Min().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Min().y, box.Max().z ); glVertex3d(box.Max().x, box.Min().y, box.Max().z ); glVertex3d(box.Max().x, box.Max().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Max().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Max().x, box.Min().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Max().z ); glVertex3d(box.Max().x, box.Max().y, box.Max().z ); glVertex3d(box.Max().x, box.Max().y, box.Min().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Min().y, box.Min().z ); glVertex3d(box.Min().x, box.Min().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Min().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Min().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Min().z ); glVertex3d(box.Max().x, box.Min().y, box.Max().z ); glVertex3d(box.Min().x, box.Min().y, box.Max().z ); glEnd(); glBegin(GL_LINE_LOOP); glVertex3d(box.Min().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Max().y, box.Min().z ); glVertex3d(box.Max().x, box.Max().y, box.Max().z ); glVertex3d(box.Min().x, box.Max().y, box.Max().z ); glEnd(); } void GlRenderer::RenderBvhNode(BvhNode *node) { if (node->IsLeaf()) { BvhLeaf *leaf = (BvhLeaf *) node; #if 0 if (leaf->mGlList == 0) { leaf->mGlList = glGenLists(1); if (leaf->mGlList != 0) glNewList(leaf->mGlList, GL_COMPILE); for (int i=0; i < leaf->mObjects.size(); i++) RenderIntersectable(leaf->mObjects[i]); if (leaf->mGlList != 0) glEndList(); } if (leaf->mGlList != 0) glCallList(leaf->mGlList); #else for (int i=0; i < leaf->mObjects.size(); i++) RenderIntersectable(leaf->mObjects[i]); #endif } else { BvhInterior *in = (BvhInterior *)node; RenderBvhNode(in->GetBack()); RenderBvhNode(in->GetFront()); } //cout << "leaf obj " << i << endl; } void GlRenderer::RenderKdNode(KdNode *node) { if (node->IsLeaf()) { KdLeaf *leaf = (KdLeaf *) node; for (int i=0; i < leaf->mObjects.size(); i++) { RenderIntersectable(leaf->mObjects[i]); } } else { KdInterior *in = (KdInterior *)node; RenderKdNode(in->mBack); RenderKdNode(in->mFront); } } void GlRendererBuffer::EvalRenderCostSample(RenderCostSample &sample, const bool useOcclusionQueries, const int threshold ) { // choose a random view point mViewCellsManager->GetViewPoint(mViewPoint); sample.mPosition = mViewPoint; //cout << "viewpoint: " << mViewPoint << endl; // take a render cost sample by rendering a cube Vector3 directions[6]; directions[0] = Vector3(1,0,0); directions[1] = Vector3(0,1,0); directions[2] = Vector3(0,0,1); directions[3] = Vector3(-1,0,0); directions[4] = Vector3(0,-1,0); directions[5] = Vector3(0,0,-1); sample.mVisibleObjects = 0; // reset object counters ObjectContainer::const_iterator it, it_end = mObjects.end(); for (it = mObjects.begin(); it != it_end; ++ it) { (*it)->mCounter = 0; } ++ mFrame; //glCullFace(GL_FRONT); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); // query all 6 directions for a full point sample for (int i = 0; i < 6; ++ i) { mViewDirection = directions[i]; SetupCamera(); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); mUseFalseColors = true; // the actual scene rendering fills the depth (for occlusion queries) // and the frame buffer (for item buffer) RenderScene(); if (0) { char filename[256]; sprintf(filename, "snap/frame-%04d-%d.png", mFrame, i); // QImage im = toImage(); // im.save(filename, "PNG"); } // evaluate the sample if (useOcclusionQueries) { EvalQueryWithOcclusionQueries(); } else { EvalQueryWithItemBuffer(); } } // now evaluate the statistics over that sample // currently only the number of visible objects is taken into account sample.Reset(); for (it = mObjects.begin(); it != it_end; ++ it) { Intersectable *obj = *it; if (obj->mCounter >= threshold) { ++ sample.mVisibleObjects; sample.mVisiblePixels += obj->mCounter; } } //cout << "RS=" << sample.mVisibleObjects << " "; } GlRendererBuffer::~GlRendererBuffer() { #if USE_CG if (sCgFragmentProgram) cgDestroyProgram(sCgFragmentProgram); if (sCgContext) cgDestroyContext(sCgContext); #endif } void GlRendererBuffer::SampleRenderCost(const int numSamples, vector &samples, const bool useOcclusionQueries, const int threshold ) { MakeCurrent(); if (mPixelBuffer == NULL) mPixelBuffer = new unsigned int[GetWidth()*GetHeight()]; // using 90 degree projection to capture 360 view with 6 samples SetupProjection(GetHeight(), GetHeight(), 90.0f); //samples.resize(numSamples); halton.Reset(); // the number of queries queried in batch mode const int numQ = 500; //const int numQ = (int)mObjects.size(); if (useOcclusionQueries) { cout << "\ngenerating " << numQ << " queries ... "; OcclusionQuery::GenQueries(mOcclusionQueries, numQ); cout << "finished" << endl; } // sampling queries for (int i = 0; i < numSamples; ++ i) { cout << "."; EvalRenderCostSample(samples[i], useOcclusionQueries, threshold); } DoneCurrent(); } void GlRendererBuffer::ClearErrorBuffer() { for (int i=0; i < mPvsStatFrames; i++) { mPvsErrorBuffer[i].mError = 1.0f; } } void GlRendererBuffer::EvalPvsStat() { mPvsStat.Reset(); halton.Reset(); MakeCurrent(); SetupProjection(GetWidth(), GetHeight()); cout<<"mPvsStatFrames="<= 0.0f) { if (err > mPvsStat.maxError) mPvsStat.maxError = err; mPvsStat.sumError += err; mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize; if (err == 0.0f) mPvsStat.errorFreeFrames++; mPvsStat.frames++; } } glFinish(); DoneCurrent(); cout< extract objects if (beam.mFlags & !Beam::STORE_OBJECTS) { vector::const_iterator it, it_end = beam.mKdNodes.end(); Intersectable::NewMail(); for (it = beam.mKdNodes.begin(); it != it_end; ++ it) { mKdTree->CollectObjects(*it, beam.mObjects); } } // (objects can be compiled to a gl list now so that subsequent rendering for // this beam is fast - the same hold for step 3) // Afterwards we have two depth buffers defining the ray origin and termination #if 0 static int glObjList = -1; if (glObjList != -1) { glObjList = glGenLists(1); glNewList(glObjList, GL_COMPILE); ObjectContainer::const_iterator it, it_end = beam.mObjects.end(); for (it = beam.mObjects.begin(); it != it_end; ++ it) { // render all objects except the source object if (*it != sourceObject) RenderIntersectable(*it); } glEndList(); } glCallList(glObjList); #else ObjectContainer::const_iterator it, it_end = beam.mObjects.end(); for (it = beam.mObjects.begin(); it != it_end; ++ it) { // render all objects except the source object if (*it != sourceObject) RenderIntersectable(*it); } #endif // 6. Use occlusion queries for all viewcell meshes associated with the beam -> // a fragment passes if the corresponding stencil fragment is set and its depth is // between origin and termination buffer // create new queries if necessary OcclusionQuery::GenQueries(mOcclusionQueries, (int)beam.mViewCells.size()); // check whether any backfacing polygon would pass the depth test? // matt: should check both back /front facing because of dual depth buffer // and danger of cutting the near plane with front facing polys. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_FALSE); glDisable(GL_CULL_FACE); ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end(); int queryIdx = 0; for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit) { mOcclusionQueries[queryIdx ++]->BeginQuery(); RenderIntersectable(*vit); mOcclusionQueries[queryIdx]->EndQuery(); ++ queryIdx; } // at this point, if possible, go and do some other computation // 7. The number of visible pixels is the number of sample rays which see the source // object from the corresponding viewcell -> remember these values for later update // of the viewcell pvs - or update immediately? queryIdx = 0; for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit) { // fetch queries unsigned int pixelCount = mOcclusionQueries[queryIdx ++]->GetQueryResult(); if (pixelCount) Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl; } // 8. Copmpute rendering statistics // In general it is not neccessary to remember to extract all the rays cast. I hope it // would be sufficient to gain only the intergral statistics about the new contributions // and so the rss tree would actually store no new rays (only the initial ones) // the subdivision of the tree would only be driven by the statistics (the glrender could // evaluate the contribution entropy for example) // However might be an option to extract/store only those the rays which made a contribution // (new viewcell has been discovered) or relative contribution greater than a threshold ... ObjectContainer pvsObj; stat.pvsSize = ComputePvs(beam.mObjects, pvsObj); // to gain ray source and termination // copy contents of ray termination buffer into depth texture // and compare with ray source buffer #if 0 VssRayContainer rays; glBindTexture(GL_TEXTURE_2D, backDepthMap); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize); ComputeRays(Intersectable *sourceObj, rays); #endif //-- cleanup // reset gl state glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); glEnable(GL_CULL_FACE); glDisable(GL_STENCIL_TEST); #if USE_CG cgGLDisableProfile(sCgFragmentProfile); #endif glDisable(GL_TEXTURE_2D); // remove objects from beam if (beam.mFlags & !Beam::STORE_OBJECTS) beam.mObjects.clear(); } void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint, const Beam &beam, Intersectable *sourceObject) { float left, right, bottom, top, znear, zfar; beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar, mSceneGraph->GetBox()); //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(left, right, bottom, top, znear, zfar); //glFrustum(-1, 1, -1, 1, 1, 20000); const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f; const Vector3 up = Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal)); #ifdef GTP_DEBUG Debug << "view point: " << viewPoint << endl; Debug << "eye: " << center << endl; Debug << "up: " << up << endl; #endif glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z, center.x, center.y, center.z, up.x, up.y, up.z); } void GlRendererBuffer::InitGL() { MakeCurrent(); GlRenderer::InitGL(); #if 1 // initialise dual depth buffer textures glGenTextures(1, &frontDepthMap); glBindTexture(GL_TEXTURE_2D, frontDepthMap); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glGenTextures(1, &backDepthMap); glBindTexture(GL_TEXTURE_2D, backDepthMap); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize, depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); #if USE_CG // cg initialization cgSetErrorCallback(handleCgError); sCgContext = cgCreateContext(); if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1)) sCgFragmentProfile = CG_PROFILE_ARBFP1; else { // try FP30 if (cgGLIsProfileSupported(CG_PROFILE_FP30)) sCgFragmentProfile = CG_PROFILE_FP30; else { Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl; exit(1); } } sCgFragmentProgram = cgCreateProgramFromFile(sCgContext, CG_SOURCE, "../src/dual_depth.cg", sCgFragmentProfile, NULL, NULL); if (!cgIsProgramCompiled(sCgFragmentProgram)) cgCompileProgram(sCgFragmentProgram); cgGLLoadProgram(sCgFragmentProgram); cgGLBindProgram(sCgFragmentProgram); Debug << "---- PROGRAM BEGIN ----\n" << cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n"; #endif #endif DoneCurrent(); } void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays) { for (int i = 0; i < depthMapSize * depthMapSize; ++ i) { //todo glGetTexImage() } } }