#include "glInterface.h" #include "GlobalLinesRenderer.h" #include "common.h" #include "RenderTexture.h" #include "Preprocessor.h" #include "GlRenderer.h" #include "Exporter.h" #include "ViewCellsManager.h" // the devil library #include #include #include #include #include //#include namespace GtpVisibilityPreprocessor { static CGcontext sCgContext = NULL; static CGprogram sCgDepthPeelingProgram = NULL; static CGprogram sCgPassThroughProgram = NULL; static CGprofile sCgFragmentProfile; static CGparameter sTextureParam; static CGparameter sTexWidthParam; static CGparameter sStepSizeParam; GlobalLinesRenderer *globalLinesRenderer = NULL; static bool isDepth = true; static void InitDevIl() { ilInit(); ILuint ImageName; ilGenImages(1, &ImageName); ilBindImage(ImageName); ilEnable(IL_FILE_OVERWRITE); // ilRegisterFormat(IL_RGBA); // ilRegisterType(IL_FLOAT); // ilEnable(IL_ORIGIN_SET); // ilOriginFunc(IL_ORIGIN_UPPER_LEFT); } static void cgErrorCallback() { CGerror lastError = cgGetError(); if(lastError) { printf("%s\n\n", cgGetErrorString(lastError)); printf("%s\n", cgGetLastListing(sCgContext)); printf("Cg error, exiting...\n"); exit(0); } } static void PrintGLerror(char *msg) { GLenum errCode; const GLubyte *errStr; if ((errCode = glGetError()) != GL_NO_ERROR) { errStr = gluErrorString(errCode); fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg); } } void Reshape(int w, int h) { if (h == 0) h = 1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 3, 5000.0); //gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 0.5, 10.0); glOrtho(-1, 1, -1, 1, 0.5, 15); } void SetFrustum(const int sizeX, const int sizeY, const float nearPlane, const float farPlane) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-sizeX * 0.5, sizeX * 0.5, -sizeY * 0.5, sizeY * 0.5, nearPlane, farPlane); /*glOrtho(0, sizeX, 0, sizeY , nearPlane, farPlane);*/ } void Display() { //globalLinesRenderer->DrawGeometry(); //globalLinesRenderer->CastGlobalLines(Beam(), 0); globalLinesRenderer->DisplayBuffer(isDepth); PrintGLerror("display"); glutSwapBuffers(); } void Idle() { glutPostRedisplay(); } void Keyboard(unsigned char key, int x, int y) { switch(key) { case '2': { VssRayContainer rays; ++ globalLinesRenderer->mMaxDepth; globalLinesRenderer->ApplyDepthPeeling(rays); cout << "max depth: " << globalLinesRenderer->mMaxDepth << endl; CLEAR_CONTAINER(rays); return; } case '1': { VssRayContainer rays; -- globalLinesRenderer->mMaxDepth; cout << "max depth: " << globalLinesRenderer->mMaxDepth << endl; globalLinesRenderer->ApplyDepthPeeling(rays); CLEAR_CONTAINER(rays); return; } case '3': { globalLinesRenderer->ExportDepthBuffer(); return; } case '4': { globalLinesRenderer->ExportItemBuffer(); return; } case '8': { isDepth = !isDepth; return; } case '9': { VssRayContainer rays; globalLinesRenderer->ApplyDepthPeeling(rays); VssRayContainer outRays; VssRayContainer::const_iterator vit, vit_end = rays.end(); const float p = 8.0f / (float)rays.size(); for (vit = rays.begin(); vit != vit_end; ++ vit) { if (Random(1.0f) < p) { outRays.push_back(*vit); } } globalLinesRenderer->Visualize(rays); CLEAR_CONTAINER(rays); return; } case '0': { VssRayContainer rays; globalLinesRenderer->ApplyDepthPeeling(rays); CLEAR_CONTAINER(rays); return; } default: return; } } /*GlobalLinesRenderer::GlobalLinesRenderer(RenderTexture *buffer1, RenderTexture *buffer2, Preprocessor *preprocessor, GlRenderer *renderer) : mNewTexture(buffer1), mOldTexture(buffer2), mPreprocessor(preprocessor), mMaxDepth(100), mRenderer(renderer) { } */ GlobalLinesRenderer::GlobalLinesRenderer(Preprocessor *preprocessor, GlRenderer *renderer, const float mTexHeight, const float mTexWidth, const float eps): mNewTexture(NULL), mOldTexture(NULL), mMaxDepth(0), mRenderer(renderer), mPreprocessor(preprocessor), mTexHeight(mTexHeight), mTexWidth(mTexWidth), mEpsilon(eps) { } GlobalLinesRenderer::GlobalLinesRenderer(Preprocessor *preprocessor, GlRenderer *renderer): mNewTexture(NULL), mOldTexture(NULL), mMaxDepth(0), mRenderer(renderer), mPreprocessor(preprocessor), mTexHeight(128), mTexWidth(128), mEpsilon(0.0001) {} void GlobalLinesRenderer::DisplayBuffer(const bool isDepth) { if (!isDepth) mNewTexture->Bind(); else mNewTexture->BindDepth(); mNewTexture->EnableTextureTarget(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (mNewTexture->IsRectangleTexture()) { glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(-1, -1, -0.5f); glTexCoord2f(mNewTexture->GetWidth(), 0); glVertex3f( 1, -1, -0.5f); glTexCoord2f(mNewTexture->GetWidth(), mNewTexture->GetHeight()); glVertex3f( 1, 1, -0.5f); glTexCoord2f(0, mNewTexture->GetHeight()); glVertex3f(-1, 1, -0.5f); glEnd(); } else { glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(-1, -1, -0.5f); glTexCoord2f(1, 0); glVertex3f( 1, -1, -0.5f); glTexCoord2f(1, 1); glVertex3f( 1, 1, -0.5f); glTexCoord2f(0, 1); glVertex3f(-1, 1, -0.5f); glEnd(); } mNewTexture->DisableTextureTarget(); PrintGLerror("displaytexture"); } GlobalLinesRenderer::~GlobalLinesRenderer() { if (sCgDepthPeelingProgram) cgDestroyProgram(sCgDepthPeelingProgram); if (sCgContext) cgDestroyContext(sCgContext); // init the receiving buffers delete mNewDepthBuffer; delete mOldDepthBuffer; delete mNewItemBuffer; delete mOldItemBuffer; } void GlobalLinesRenderer::InitScene(const float alpha, const float beta) { AxisAlignedBox3 bbox = globalLinesRenderer->mPreprocessor->mKdTree->GetBox(); const float sceneSize = Magnitude(bbox.Diagonal()); // compute the center of the scene Vector3 midPoint = bbox.Center(); // add a small offset to provide some randomness in the sampling Vector3 offset(Random(sceneSize * 1e-3f), Random(sceneSize * 1e-3f), Random(sceneSize * 1e-3f)); midPoint += offset; mNear = 1; mFar = sceneSize * 2; mWidth = sceneSize; ComputeLookAt(alpha, beta, mEyeVec, mUpVec, mLeftVec); mViewPoint = midPoint - 0.5f * sceneSize * mEyeVec; cout << "mid point: " << midPoint << endl; cout << "view point: " << mViewPoint << endl; cout << "scene: " << bbox << endl; // setup the rendering context for the RenderTexture mNewTexture->BeginCapture(); { //Reshape(mTexWidth, mTexHeight); glViewport(0, 0, mTexWidth, mTexHeight); SetFrustum(mWidth, mWidth, mNear, mFar); // for item buffer: white means no color glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFrontFace(GL_CCW); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); //glEnable(GL_CULL_FACE); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z, midPoint.x, midPoint.y, midPoint.z, mUpVec.x, mUpVec.y, mUpVec.z); } mNewTexture->EndCapture(); // setup the rendering context for the other depth buffer mOldTexture->BeginCapture(); { // for item buffer: white means no color glClearColor(1, 1, 1, 1); //Reshape(mTexWidth, mTexHeight); glViewport(0, 0, mTexWidth, mTexHeight); SetFrustum(mWidth, mWidth, mNear, mFar); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glFrontFace(GL_CCW); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); //glEnable(GL_CULL_FACE); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z, midPoint.x, midPoint.y, midPoint.z, mUpVec.x, mUpVec.y, mUpVec.z); } mOldTexture->EndCapture(); cout << "eye: " << mEyeVec << " left: " << mLeftVec << " up: " << mUpVec << endl; } void GlobalLinesRenderer::CastGlobalLines(const float alpha, const float beta, //const int samples, VssRayContainer &rays) { InitScene(alpha, beta); // bind pixel shader implementing the front depth buffer functionality ApplyDepthPeeling(rays); } void GlobalLinesRenderer::RenderObject(Intersectable *obj) { mRenderer->RenderIntersectable(obj); } void GlobalLinesRenderer::DrawGeometry() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); { //glLoadIdentity(); ObjectContainer::const_iterator oit, oit_end = mPreprocessor->mObjects.end(); Intersectable::NewMail(); for (oit = mPreprocessor->mObjects.begin(); oit != oit_end; ++ oit) { //cout << (*oit)->GetId() << " "; RenderObject(*oit); } } glPopMatrix(); } void GlobalLinesRenderer::SwitchRenderTextures() { RenderTexture *buffer = mOldTexture; mOldTexture = mNewTexture; mNewTexture = buffer; } void GlobalLinesRenderer::ComputeLookAt(const float alpha, const float beta, Vector3 &eye, Vector3 &up, Vector3 &left) { //float x = cos(alpha); //float y = sin(alpha); eye.x = sin(alpha) * cos(beta); eye.y = sin(alpha) * sin(beta); eye.z = cos(alpha); //eye = Normalize(eye); eye.RightHandedBase(up, left); } void GlobalLinesRenderer::InitGl() { InitDevIl(); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowPosition(50, 50); glutInitWindowSize(512, 512); glutCreateWindow("TestRenderDepthTexture"); int err = glewInit(); if (GLEW_OK != err) { // problem: glewInit failed, something is seriously wrong fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err)); exit(-1); } glutKeyboardFunc(Keyboard); glutDisplayFunc(Display); glutIdleFunc(Idle); glutReshapeFunc(Reshape); Reshape(512, 512); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // initialise the receiving buffers mNewDepthBuffer = new float[mTexWidth * mTexHeight]; mNewItemBuffer = new unsigned char[mTexWidth * mTexHeight * 4]; mOldDepthBuffer = new float[mTexWidth * mTexHeight]; mOldItemBuffer = new unsigned char[mTexWidth * mTexHeight * 4]; for (int i = 0; i < mTexWidth * mTexHeight; ++ i) { mNewDepthBuffer[i] = 1; mOldDepthBuffer[i] = 1; mNewItemBuffer[i * 4] = 255; mNewItemBuffer[i * 4 + 1] = 255; mNewItemBuffer[i * 4 + 2] = 255; mNewItemBuffer[i * 4 + 3] = 255; mOldItemBuffer[i * 4] = 255; mOldItemBuffer[i * 4 + 1] = 255; mOldItemBuffer[i * 4 + 2] = 255; mOldItemBuffer[i * 4 + 3] = 255; } /*gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z, midPoint.x, midPoint.y, midPoint.z, 0, 1, 0); */ gluLookAt(0, 0, 3, 0, 0, 0, 0, 1, 0); //glDisable(GL_CULL_FACE); glEnable(GL_CULL_FACE); glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glEnable(GL_DEPTH_TEST); glClearColor(0.1, 0.2, 0.3, 1); // A square, mipmapped, anisotropically filtered 8-bit RGBA texture with // depth and stencil. // Note that RT_COPY_TO_TEXTURE is required for depth textures on ATI hardware mNewTexture = new RenderTexture(mTexWidth, mTexHeight, true, true); #ifdef ATI mNewTexture->Initialize(true, true, false, true, true, 8, 8, 8, 8, RenderTexture::RT_COPY_TO_TEXTURE); #else mNewTexture->Initialize(true, true, false, true, true, 8, 8, 8, 8);//, RenderTexture::RT_COPY_TO_TEXTURE); #endif mOldTexture = new RenderTexture(mTexWidth, mTexHeight, true, true); #ifdef ATI mOldTexture ->Initialize(true, true, false, true, true, 8, 8, 8, 8, RenderTexture::RT_COPY_TO_TEXTURE); #else mOldTexture ->Initialize(true, true, false, true, true, 8, 8, 8, 8);//, RenderTexture::RT_COPY_TO_TEXTURE); #endif // Setup Cg cgSetErrorCallback(cgErrorCallback); // Create cgContext. sCgContext = cgCreateContext(); // get the best profile for this hardware sCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); //assert(sCgFragmentProfile != CG_PROFILE_UNKNOWN); cgGLSetOptimalOptions(sCgFragmentProfile); sCgDepthPeelingProgram = cgCreateProgramFromFile(sCgContext, CG_SOURCE, mNewTexture->IsRectangleTexture() ? "../src/depth_peelingRect.cg" : "../src/depth_peeling2d.cg", GLEW_ARB_fragment_program ? CG_PROFILE_ARBFP1 : CG_PROFILE_FP30, NULL, NULL); if(sCgDepthPeelingProgram != NULL) { cgGLLoadProgram(sCgDepthPeelingProgram); sTextureParam = cgGetNamedParameter(sCgDepthPeelingProgram, "depthTex"); // we need size of texture for scaling if (!mNewTexture->IsRectangleTexture()) { sTexWidthParam = cgGetNamedParameter(sCgDepthPeelingProgram, "texWidth"); } sStepSizeParam = cgGetNamedParameter(sCgDepthPeelingProgram, "stepSize"); cgGLSetParameter1f(sTexWidthParam, (float)mTexWidth); cgGLSetParameter1f(sStepSizeParam, mEpsilon); } sCgPassThroughProgram = cgCreateProgramFromFile(sCgContext, CG_SOURCE, "../src/passthrough.cg", GLEW_ARB_fragment_program ? CG_PROFILE_ARBFP1 : CG_PROFILE_FP30, NULL, NULL); if(sCgPassThroughProgram != NULL) { cgGLLoadProgram(sCgPassThroughProgram); } const float alpha = 1.1; const float beta = 0.9; InitScene(alpha, beta); PrintGLerror("init"); } Intersectable *GlobalLinesRenderer::ExtractSamplePoint(float *depthBuffer, unsigned char *itemBuffer, const int x, const int y, Vector3 &hitPoint, const bool isFrontBuffer) const { const int depthIndex = x + mTexWidth * y; const int itemIndex = 4 * depthIndex; const float depth = depthBuffer[depthIndex]; const float eyeDist = mNear + (mFar - mNear) * depth; const float leftDist = -0.5f * mWidth + mWidth * ((float)x + 0.5f) / mTexWidth; //const float leftDist = 0.5f * mWidth - mWidth * ((float)x + 0.5f) / mTexWidth; const float upDist = -0.5f * mWidth + mWidth * ((float)y + 0.5f) / mTexHeight; //const float upDist = 0.5f * mWidth - mWidth * ((float)y + 0.5f) / mTexHeight; hitPoint = mViewPoint + eyeDist * mEyeVec + upDist * mUpVec + leftDist * mLeftVec; unsigned char r = itemBuffer[itemIndex]; unsigned char g = itemBuffer[itemIndex + 1]; unsigned char b = itemBuffer[itemIndex + 2]; // 3 times 255 means no valid object if ((r == 255) && (g == 255) && (b == 255)) return NULL; const int id = mRenderer->GetId(r, g, b); //cout << "r: " << (int)r << "g: " << (int)g << " b: " << (int)b << " id: " << id << "|"; Intersectable *intersect = mPreprocessor->GetObjectById(id); const Vector3 dir = isFrontBuffer ? mEyeVec : -mEyeVec; // HACK: assume triangle intersectable const Vector3 norm = intersect->GetNormal(0); // test for invalid view space if (DotProd(dir, norm) >= -Limits::Small) return NULL; return intersect; } void GlobalLinesRenderer::ProcessDepthBuffer(VssRayContainer &vssRays, const bool oldBufferInitialised, const int pass) { GrabDepthBuffer(mNewDepthBuffer, mNewTexture); GrabItemBuffer(mNewItemBuffer, mNewTexture); if (oldBufferInitialised) { GrabDepthBuffer(mOldDepthBuffer, mOldTexture); GrabItemBuffer(mOldItemBuffer, mOldTexture); } else { for (int i = 0; i < mTexWidth * mTexHeight; ++ i) { mOldDepthBuffer[i] = 0; mOldItemBuffer[i * 4] = 255; mOldItemBuffer[i * 4 + 1] = 255; mOldItemBuffer[i * 4 + 2] = 255; mOldItemBuffer[i * 4 + 3] = 255; } } for (int y = 0; y < mTexHeight; ++ y) { for (int x = 0; x < mTexWidth; ++ x) { Vector3 newPt, oldPt; Intersectable *termObj1 = ExtractSamplePoint(mNewDepthBuffer, mNewItemBuffer, x, y, newPt, true); Intersectable *termObj2 = ExtractSamplePoint(mOldDepthBuffer, mOldItemBuffer, x, y, oldPt, false); if (!termObj1 && !termObj2) // we do not create a ray continue; Vector3 clippedOldPt, clippedNewPt; ClipToViewSpaceBox(oldPt, newPt, clippedOldPt, clippedNewPt); //clippedOldPt = oldPt; //clippedNewPt = newPt; // create rays in both directions if (termObj1) { vssRays.push_back(new VssRay(clippedOldPt, clippedNewPt, NULL, termObj1, pass)); //cout << "new pt: " << newPt << endl; } if (termObj2) { vssRays.push_back(new VssRay(clippedNewPt, clippedOldPt, NULL, termObj2, pass)); //cout << "old pt: " << oldPt << endl; } } } } bool GlobalLinesRenderer::ClipToViewSpaceBox(const Vector3 &origin, const Vector3 &termination, Vector3 &clippedOrigin, Vector3 &clippedTermination) { Ray ray(origin, termination - origin, Ray::LINE_SEGMENT); ray.Precompute(); float tmin, tmax; //const AxisAlignedBox3 bbox = mPreprocessor->mViewCellsManager->GetViewSpaceBox(); // hack const AxisAlignedBox3 bbox = mPreprocessor->mKdTree->GetBox(); if ((!bbox.ComputeMinMaxT(ray, &tmin, &tmax)) || tmin>=tmax) { return false; } if (tmin >= 1.0f || tmax <=0.0f) return false; if (tmin > 0.0f) clippedOrigin = ray.Extrap(tmin); else clippedOrigin = origin; if (tmax < 1.0f) clippedTermination = ray.Extrap(tmax); else clippedTermination = termination; return true; } void GlobalLinesRenderer::Run() { glutMainLoop(); } void GlobalLinesRenderer::Visualize(const VssRayContainer &vssRays) { Exporter *exporter = Exporter::GetExporter("globalLines.wrl"); if (!exporter) return; exporter->SetWireframe(); //exporter->ExportGeometry(preprocessor->mObjects); exporter->SetFilled(); VssRayContainer::const_iterator vit, vit_end = vssRays.end(); VssRayContainer outRays; Intersectable::NewMail(); for (vit = vssRays.begin(); vit != vit_end; ++ vit) { VssRay *ray = *vit; Intersectable *obj = (*vit)->mTerminationObject; if (!obj->Mailed()) { obj->Mail(); exporter->ExportIntersectable(obj); } //if (ray->mPass == 4) outRays.push_back(ray); } exporter->ExportRays(outRays); delete exporter; } void GlobalLinesRenderer::GrabDepthBuffer(float *data, RenderTexture *rt) { rt->BindDepth(); rt->EnableTextureTarget(); const int texFormat = GL_DEPTH_COMPONENT; glGetTexImage(mNewTexture->GetTextureTarget(), 0, texFormat, GL_FLOAT, data); mNewTexture->DisableTextureTarget(); } void GlobalLinesRenderer::GrabItemBuffer(unsigned char *data, RenderTexture *rt) { rt->Bind(); rt->EnableTextureTarget(); const int texFormat = GL_RGBA; glGetTexImage(mNewTexture->GetTextureTarget(), 0, texFormat, GL_UNSIGNED_BYTE, data); mNewTexture->DisableTextureTarget(); } void GlobalLinesRenderer::ExportDepthBuffer() { mNewTexture->BindDepth(); mNewTexture->EnableTextureTarget(); cout << "depth: " << mNewTexture->GetDepthBits() << endl; const int components = 1;//mNewTexture->GetDepthBits() / 8; float *data = new float[mTexWidth * mTexHeight * components]; //const int texFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV; const int texFormat = GL_DEPTH_COMPONENT; //const int texFormat = GL_RGBA; glGetTexImage(mNewTexture->GetTextureTarget(), 0, texFormat, GL_FLOAT, data); string filename("depth.tga"); ilRegisterType(IL_FLOAT); const int depth = 1; const int bpp = components; ilTexImage(mTexWidth, mTexHeight, depth, bpp, IL_LUMINANCE, IL_FLOAT, data); ilSaveImage((char *const)filename.c_str()); cout << "finished" << endl; delete data; cout << "data deleted" << endl; mNewTexture->DisableTextureTarget(); PrintGLerror("grab texture"); } void GlobalLinesRenderer::ExportItemBuffer() { mNewTexture->Bind(); mNewTexture->EnableTextureTarget(); cout << "depth: " << mNewTexture->GetDepthBits() << endl; const int components = 4;//mNewTexture->GetDepthBits() / 8; unsigned char *data = new unsigned char [mTexWidth * mTexHeight * components]; //const int texFormat = WGL_TEXTURE_DEPTH_COMPONENT_NV; const int texFormat = GL_RGBA; glGetTexImage(mNewTexture->GetTextureTarget(), 0, texFormat, GL_UNSIGNED_BYTE, data); string filename("items.jpg"); ilRegisterType(IL_UNSIGNED_BYTE); const int depth = 1; const int bpp = components; ilTexImage(mTexWidth, mTexHeight, depth, bpp, IL_RGBA, IL_UNSIGNED_BYTE, data); ilSaveImage((char *const)filename.c_str()); cout << "finished" << endl; delete data; cout << "data deleted" << endl; mNewTexture->DisableTextureTarget(); PrintGLerror("grab texture"); } void GlobalLinesRenderer::ApplyDepthPeeling(VssRayContainer &rays) { mNewTexture->BeginCapture(); { //cgGLBindProgram(sCgPassThroughProgram); //cgGLEnableProfile(sCgFragmentProfile); DrawGeometry(); } mNewTexture->EndCapture(); PrintGLerror("firstpass"); if (mNewTexture->IsRectangleTexture()) cout << "rect" << endl; // process the buffers for the first layer ProcessDepthBuffer(rays, false, 0); for(int i = 1; i < mMaxDepth; ++ i) { // Peel another layer // switch pointer between rendertextures SwitchRenderTextures(); mNewTexture->BeginCapture(); { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); cgGLBindProgram(sCgDepthPeelingProgram); cgGLEnableProfile(sCgFragmentProfile); cgGLSetTextureParameter(sTextureParam, mOldTexture->GetDepthTextureID()); cgGLEnableTextureParameter(sTextureParam); DrawGeometry(); cgGLDisableTextureParameter(sTextureParam); cgGLDisableProfile(sCgFragmentProfile); } mNewTexture->EndCapture(); // process the buffers for following layer ProcessDepthBuffer(rays, true, i); } PrintGLerror("endpeeling"); } }