/*========================================================================= Program: Visualization Toolkit Module: vtkDepthPeelingPass.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkDepthPeelingPass.h" #include "vtkObjectFactory.h" #include #include "vtkRenderState.h" #include "vtkProp.h" #include "vtkRenderer.h" #include "vtkOpenGLRenderer.h" #include "vtkOpenGLRenderWindow.h" #include "vtkOpenGLExtensionManager.h" #include "vtkgl.h" #include #include "vtkShaderProgram2.h" #include "vtkShader2.h" #include "vtkShader2Collection.h" #include "vtkUniformVariables.h" #include "vtkTextureUnitManager.h" #include "vtkOpenGLError.h" vtkStandardNewMacro(vtkDepthPeelingPass); vtkCxxSetObjectMacro(vtkDepthPeelingPass,TranslucentPass,vtkRenderPass); // List of rgba layers, id are 2D rectangle texture Ids. class vtkDepthPeelingPassLayerList { public: std::list List; }; extern const char *vtkDepthPeeling_fs; // ---------------------------------------------------------------------------- vtkDepthPeelingPass::vtkDepthPeelingPass() { this->TranslucentPass=0; this->IsSupported=false; this->IsChecked=false; this->OcclusionRatio=0.0; this->MaximumNumberOfPeels=4; this->LastRenderingUsedDepthPeeling=false; this->DepthPeelingHigherLayer=0; this->Prog=vtkShaderProgram2::New(); this->Shader=vtkShader2::New(); this->Prog->GetShaders()->AddItem(this->Shader); this->Shader->SetSourceCode(vtkDepthPeeling_fs); this->Shader->SetType(VTK_SHADER_TYPE_FRAGMENT); vtkUniformVariables *v=this->Shader->GetUniformVariables(); this->ShadowTexUnit=-1; // not allocated this->OpaqueShadowTexUnit=-1; // not allocated int value; value=1; v->SetUniformi("shadowTex",1,&value); value=2; v->SetUniformi("opaqueShadowTex",1,&value); } // ---------------------------------------------------------------------------- vtkDepthPeelingPass::~vtkDepthPeelingPass() { if(this->TranslucentPass!=0) { this->TranslucentPass->Delete(); } this->Shader->Delete(); this->Prog->Delete(); } //----------------------------------------------------------------------------- // Description: // Destructor. Delete SourceCode if any. void vtkDepthPeelingPass::ReleaseGraphicsResources(vtkWindow *w) { assert("pre: w_exists" && w!=0); this->Shader->ReleaseGraphicsResources(); this->Prog->ReleaseGraphicsResources(); if(this->TranslucentPass) { this->TranslucentPass->ReleaseGraphicsResources(w); } } // ---------------------------------------------------------------------------- void vtkDepthPeelingPass::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "OcclusionRation: " << this->OcclusionRatio << endl; os << indent << "MaximumNumberOfPeels: " << this->MaximumNumberOfPeels << endl; os << indent << "LastRenderingUsedDepthPeeling: "; if(this->LastRenderingUsedDepthPeeling) { os << "On" << endl; } else { os << "Off" << endl; } os << indent << "TranslucentPass:"; if(this->TranslucentPass!=0) { this->TranslucentPass->PrintSelf(os,indent); } else { os << "(none)" <NumberOfRenderedProps=0; if(this->TranslucentPass==0) { vtkWarningMacro(<<"No TranslucentPass delegate set. Nothing can be rendered."); return; } // Any prop to render? bool hasTranslucentPolygonalGeometry=false; int i=0; while(!hasTranslucentPolygonalGeometry && iGetPropArrayCount()) { hasTranslucentPolygonalGeometry= s->GetPropArray()[i]->HasTranslucentPolygonalGeometry()==1; ++i; } if(!hasTranslucentPolygonalGeometry) { return; // nothing to render. } // check driver support vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(s->GetRenderer()->GetRenderWindow()); this->CheckSupport(context); vtkOpenGLExtensionManager *extensions = context->GetExtensionManager(); if(!this->IsSupported) { // just alpha blending this->LastRenderingUsedDepthPeeling=false; this->TranslucentPass->Render(s); this->NumberOfRenderedProps=this->TranslucentPass->GetNumberOfRenderedProps(); return; } vtkOpenGLClearErrorMacro(); // Depth peeling. vtkRenderer *r=s->GetRenderer(); if(s->GetFrameBuffer()==0) { // get the viewport dimensions r->GetTiledSizeAndOrigin(&this->ViewportWidth,&this->ViewportHeight, &this->ViewportX,&this->ViewportY); } else { int size[2]; s->GetWindowSize(size); this->ViewportWidth=size[0]; this->ViewportHeight=size[1]; this->ViewportX=0; this->ViewportY=0; } // get z bits GLint depthBits; glGetIntegerv(GL_DEPTH_BITS,&depthBits); if(depthBits==16) { this->DepthFormat=vtkgl::DEPTH_COMPONENT16_ARB; } else { this->DepthFormat=vtkgl::DEPTH_COMPONENT24_ARB; } // NOTE, this class expects texture unit already selected // don't change it. //vtkgl::ActiveTexture(vtkgl::TEXTURE1); // check if the GPU supports a viewport sized texture in // the formats we will use. If not then we should fallback // to alpha blending. // This check is really an anachronism since modern GPU // typically support full screen sized textures in all the // common formats. GLint depthTexSupport = 1; GLint colorTexSupport = 1; if ( extensions->DriverIsATI() && !extensions->GetIgnoreDriverBugs("ATI proxy query bug.") ) { // The ATI Radeon HD drivers currently choke on the proxy // query, but depth peeling has been confirmed to work. For // those driver fall back on the weaker max texture size // check. GLint maxTexSize = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); if ( (this->ViewportWidth > maxTexSize) || (this->ViewportHeight > maxTexSize) ) { depthTexSupport = 0; colorTexSupport = 0; } } else { // Not a buggy ATI driver, it's OK to make the proxy query. GLuint proxyQueryTex = 0; glGenTextures(1, &proxyQueryTex); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB, proxyQueryTex); // support for depth buffer format glTexImage2D(vtkgl::PROXY_TEXTURE_RECTANGLE_ARB, 0, this->DepthFormat, this->ViewportWidth, this->ViewportHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,0); glGetTexLevelParameteriv(vtkgl::PROXY_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH, &depthTexSupport); // support for color buffer glTexImage2D(vtkgl::PROXY_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, this->ViewportWidth, this->ViewportHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glGetTexLevelParameteriv(vtkgl::PROXY_TEXTURE_RECTANGLE_ARB, 0, GL_TEXTURE_WIDTH,&colorTexSupport); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB, 0); glDeleteTextures(1, &proxyQueryTex); } if (!(depthTexSupport && colorTexSupport)) { // GPU does not support a view sized texture in this format. // Do alpha blending technique instead. vtkWarningMacro( << "The GPU supports " << this->ViewportWidth << "x" << this->ViewportHeight << " texture: depth buffer " << (depthTexSupport?"yes":"no") << ", color buffer " << (colorTexSupport?"yes":"no")); this->LastRenderingUsedDepthPeeling = false; vtkgl::ActiveTexture(vtkgl::TEXTURE0); this->TranslucentPass->Render(s); this->NumberOfRenderedProps = this->TranslucentPass->GetNumberOfRenderedProps(); return; } // Have to be set before a call to UpdateTranslucentPolygonalGeometry() // because UpdateTranslucentPolygonalGeometry() will eventually call // vtkOpenGLActor::Render() that uses this flag. this->LastRenderingUsedDepthPeeling = true; this->SetLastRenderingUsedDepthPeeling(s->GetRenderer(), true); // 1. Grab the RGBAZ of the opaque layer. GLuint opaqueLayerZ=0; GLuint opaqueLayerRgba=0; glGenTextures(1,&opaqueLayerZ); this->OpaqueLayerZ=opaqueLayerZ; glGenTextures(1,&opaqueLayerRgba); // opaque z format // vtkgl::ActiveTexture(vtkgl::TEXTURE1 ); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,opaqueLayerZ); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB, vtkgl::TEXTURE_COMPARE_MODE, vtkgl::COMPARE_R_TO_TEXTURE); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB, vtkgl::TEXTURE_COMPARE_FUNC, GL_LESS); // Allocate memory glTexImage2D(vtkgl::TEXTURE_RECTANGLE_ARB,0,this->DepthFormat, this->ViewportWidth,this->ViewportHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); // Grab the z-buffer glCopyTexSubImage2D(vtkgl::TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->ViewportX, this->ViewportY,this->ViewportWidth, this->ViewportHeight); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,opaqueLayerRgba); // opaque rgba format glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Allocate memory glTexImage2D(vtkgl::TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, this->ViewportWidth,this->ViewportHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // Grab the rgba-buffer glCopyTexSubImage2D(vtkgl::TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->ViewportX, this->ViewportY,this->ViewportWidth, this->ViewportHeight); GLuint queryId; vtkgl::GenQueries(1,&queryId); int stop=0; int infiniteLoop=this->MaximumNumberOfPeels==0; unsigned int threshold=static_cast(this->ViewportWidth*this->ViewportHeight*OcclusionRatio); this->LayerList=new vtkDepthPeelingPassLayerList; // save the default blend function. glPushAttrib(GL_COLOR_BUFFER_BIT); int multiSampleStatus=glIsEnabled(vtkgl::MULTISAMPLE); if(multiSampleStatus) { glDisable(vtkgl::MULTISAMPLE); } glDisable(GL_BLEND); vtkUniformVariables *v=this->Shader->GetUniformVariables(); float value; value=this->ViewportX; v->SetUniformf("offsetX",1,&value); value=this->ViewportY; v->SetUniformf("offsetY",1,&value); this->Prog->SetContext(static_cast( s->GetRenderer()->GetRenderWindow())); this->Shader->SetContext(this->Prog->GetContext()); GLuint nbPixels=0; GLuint previousNbPixels=0; int l=0; while(!stop) { vtkgl::BeginQuery(vtkgl::SAMPLES_PASSED,queryId); stop=!this->RenderPeel(s,l); vtkgl::EndQuery(vtkgl::SAMPLES_PASSED); // blocking call previousNbPixels=nbPixels; if(!stop || l>0) // stop && l==0 <=> no translucent geometry { vtkgl::GetQueryObjectuiv(queryId,vtkgl::QUERY_RESULT,&nbPixels); ++l; if(!stop) { stop=(nbPixels<=threshold) || (nbPixels==previousNbPixels); if(!stop && !infiniteLoop) { stop=l>=this->MaximumNumberOfPeels; } } } } if(l>1) // some higher layer, we allocated some tex unit in RenderPeel() { vtkTextureUnitManager *m=context->GetTextureUnitManager(); m->Free(this->ShadowTexUnit); m->Free(this->OpaqueShadowTexUnit); this->ShadowTexUnit=-1; this->OpaqueShadowTexUnit=-1; } if(multiSampleStatus) { glEnable(vtkgl::MULTISAMPLE); } // The two following lines are taken from vtkOpenGLProperty to // reset texturing state after rendering the props. glDisable(GL_TEXTURE_2D); glDisable (GL_ALPHA_TEST); glDepthFunc(GL_LEQUAL); vtkgl::DeleteQueries(1,&queryId); if(this->TransparentLayerZ!=0) { GLuint transparentLayerZ=static_cast(this->TransparentLayerZ); glDeleteTextures(1,&transparentLayerZ); this->TransparentLayerZ=0; } // Finally, draw sorted opacity glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, this->ViewportWidth, 0, this->ViewportHeight, -1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glClearColor( static_cast(0),static_cast(0), static_cast(0),static_cast(0)); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); vtkgl::ActiveTexture(vtkgl::TEXTURE0 ); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(vtkgl::TEXTURE_RECTANGLE_ARB); // actor in wireframe may have change that glPolygonMode(GL_FRONT, GL_FILL); glDisable(GL_BLEND); // First the opaque layer glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,opaqueLayerRgba); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(this->ViewportWidth, 0); glVertex2f(this->ViewportWidth, 0); glTexCoord2f(this->ViewportWidth, this->ViewportHeight); glVertex2f(this->ViewportWidth, this->ViewportHeight); glTexCoord2f(0, this->ViewportHeight); glVertex2f(0, this->ViewportHeight); glEnd(); vtkgl::BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); // the transparent layers std::list::reverse_iterator it=this->LayerList->List.rbegin(); std::list::reverse_iterator itEnd=this->LayerList->List.rend(); while(it!=itEnd) { glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,(*it)); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(this->ViewportWidth, 0); glVertex2f(this->ViewportWidth, 0); glTexCoord2f(this->ViewportWidth, this->ViewportHeight); glVertex2f(this->ViewportWidth, this->ViewportHeight); glTexCoord2f(0, this->ViewportHeight); glVertex2f(0, this->ViewportHeight); glEnd(); ++it; } // Restore the default blend function for the next stage (overlay) glPopAttrib(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(vtkgl::TEXTURE_RECTANGLE_ARB); glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); // Destroy the layers size_t c=this->LayerList->List.size(); GLuint *ids=new GLuint[c]; std::list::const_iterator it2=this->LayerList->List.begin(); size_t layer=0; while(layer(c),ids); delete[] ids; delete this->LayerList; this->LayerList=0; glDeleteTextures(1,&opaqueLayerRgba); glDeleteTextures(1,&opaqueLayerZ); this->NumberOfRenderedProps=this->TranslucentPass->GetNumberOfRenderedProps(); vtkOpenGLCheckErrorMacro("failed after Render"); } // ---------------------------------------------------------------------------- void vtkDepthPeelingPass::CheckSupport(vtkOpenGLRenderWindow *w) { assert("pre: w_exists" && w!=0); vtkOpenGLClearErrorMacro(); vtkOpenGLExtensionManager *extensions=w->GetExtensionManager(); if(!this->IsChecked || w->GetContextCreationTime()>this->CheckTime) { this->IsChecked=true; this->CheckTime.Modified(); bool supports_GL_1_3=extensions->ExtensionSupported("GL_VERSION_1_3")==1; bool supports_GL_1_4=extensions->ExtensionSupported("GL_VERSION_1_4")==1; bool supports_GL_1_5=extensions->ExtensionSupported("GL_VERSION_1_5")==1; bool supports_GL_2_0=extensions->ExtensionSupported("GL_VERSION_2_0")==1; bool supports_vertex_shader; bool supports_fragment_shader; bool supports_shader_objects; if(supports_GL_2_0) { supports_vertex_shader=true; supports_fragment_shader=true; supports_shader_objects=true; } else { supports_vertex_shader=extensions->ExtensionSupported("GL_ARB_vertex_shader")==1; supports_fragment_shader=extensions->ExtensionSupported("GL_ARB_fragment_shader")==1; supports_shader_objects=extensions->ExtensionSupported("GL_ARB_shader_objects")==1; } bool supports_multitexture=supports_GL_1_3 || extensions->ExtensionSupported("GL_ARB_multitexture"); bool supports_occlusion_query; bool supports_shadow_funcs; if(supports_GL_1_5) { supports_occlusion_query=true; supports_shadow_funcs=true; } else { supports_occlusion_query=extensions->ExtensionSupported("GL_ARB_occlusion_query")==1; supports_shadow_funcs=extensions->ExtensionSupported("GL_EXT_shadow_funcs")==1; } bool supports_depth_texture; bool supports_shadow; bool supports_blend_func_separate; if(supports_GL_1_4) { supports_depth_texture=true; supports_blend_func_separate=true; supports_shadow=true; } else { supports_depth_texture=extensions->ExtensionSupported("GL_ARB_depth_texture")==1; supports_shadow=extensions->ExtensionSupported("GL_ARB_shadow")==1; supports_blend_func_separate=extensions->ExtensionSupported("GL_EXT_blend_func_separate")==1; } bool supports_GL_ARB_texture_rectangle=extensions->ExtensionSupported("GL_ARB_texture_rectangle")==1; // spec claims it is GL_SGIS_texture_edge_clamp, reality shows it is // GL_EXT_texture_edge_clamp on Nvidia. // part of OpenGL 1.2 core // there is no new function with this extension, we don't need to load // it. bool supports_edge_clamp=extensions->ExtensionSupported("GL_VERSION_1_2")==1; if(!supports_edge_clamp) { supports_edge_clamp=extensions->ExtensionSupported("GL_SGIS_texture_edge_clamp")==1; if(!supports_edge_clamp) { // nvidia cards. supports_edge_clamp=extensions->ExtensionSupported("GL_EXT_texture_edge_clamp")==1; } } GLint alphaBits; glGetIntegerv(GL_ALPHA_BITS, &alphaBits); bool supportsAtLeast8AlphaBits=alphaBits>=8; // force alpha blending // Mesa does not support true linking of shaders (VTK bug 8135) // and Mesa 7.2 just crashes during the try-compile. // os mesa 9.1.4 some tests fail // ATI Radeon HD XXXXX on Windows chokes on PROXY_TEXTURE_RECTANGLE_ARB // memory querries however if those are not used all the tests pass. // ATI Radeon HD on Mac OS X PROXY_TEXTURE_RECTANGLE_ARB are fine but // TestTranslucentLUTDepthPeeling fails. So leave it disabled on Apple int driver_support = (!(extensions->DriverIsATI() && (extensions->GetDriverGLVersionMajor() < 3)) && !extensions->DriverIsMesa()) || extensions->GetIgnoreDriverBugs("ATI and Mesa depth peeling bugs"); this->IsSupported = supports_depth_texture && supports_shadow && supports_blend_func_separate && supports_shadow_funcs && supports_vertex_shader && supports_fragment_shader && supports_shader_objects && supports_occlusion_query && supports_multitexture && supports_GL_ARB_texture_rectangle && supports_edge_clamp && supportsAtLeast8AlphaBits && driver_support; if(this->IsSupported) { vtkDebugMacro("depth peeling supported"); if(supports_GL_1_3) { extensions->LoadExtension("GL_VERSION_1_3"); } else { extensions->LoadCorePromotedExtension("GL_ARB_multitexture"); } // GL_ARB_depth_texture, GL_ARB_shadow and GL_EXT_shadow_funcs // don't introduce new functions. if(supports_GL_1_4) { extensions->LoadExtension("GL_VERSION_1_4"); } else { extensions->LoadCorePromotedExtension("GL_EXT_blend_func_separate"); } if(supports_GL_2_0) { extensions->LoadExtension("GL_VERSION_2_0"); } else { extensions->LoadCorePromotedExtension("GL_ARB_vertex_shader"); extensions->LoadCorePromotedExtension("GL_ARB_fragment_shader"); extensions->LoadCorePromotedExtension("GL_ARB_shader_objects"); } if(supports_GL_1_5) { extensions->LoadExtension("GL_VERSION_1_5"); } else { extensions->LoadCorePromotedExtension("GL_ARB_occlusion_query"); } extensions->LoadExtension("GL_ARB_texture_rectangle"); // Some OpenGL implementations such as ATI // claim to support both GLSL and GL_ARB_texture_rectangle but // don't actually support sampler2DRectShadow in a GLSL code. // Others (like Mesa) claim to support shaders but don't actually // support true linking of shaders (and declaration of functions). // To test that, we compile the shader, if it fails, we don't use // deph peeling GLuint shader = vtkgl::CreateShader(vtkgl::FRAGMENT_SHADER); vtkgl::ShaderSource( shader, 1, const_cast(&vtkDepthPeeling_fs), 0); vtkgl::CompileShader(shader); GLint params; vtkgl::GetShaderiv(shader,vtkgl::COMPILE_STATUS, ¶ms); this->IsSupported = params==GL_TRUE; vtkgl::DeleteShader(shader); if(!this->IsSupported) { vtkDebugMacro("this OpenGL implementation does not support " "GL_ARB_texture_rectangle in GLSL code or does" "not support true linking of shaders."); } } else { vtkDebugMacro(<<"depth peeling is not supported."); if(!supports_depth_texture) { vtkDebugMacro(<<"neither OpenGL 1.4 nor GL_ARB_depth_texture is supported"); } if(!supports_shadow) { vtkDebugMacro(<<"neither OpenGL 1.4 nor GL_ARB_shadow is supported"); } if(!supports_shadow_funcs) { vtkDebugMacro(<<"neither OpenGL 1.5 nor GL_EXT_shadow_funcs is supported"); } if(!supports_vertex_shader) { vtkDebugMacro(<<"neither OpenGL 2.0 nor GL_ARB_vertex_shader is supported"); } if(!supports_fragment_shader) { vtkDebugMacro(<<"neither OpenGL 2.0 nor GL_ARB_fragment_shader is supported"); } if(!supports_shader_objects) { vtkDebugMacro(<<"neither OpenGL 2.0 nor GL_ARB_shader_objects is supported"); } if(!supports_occlusion_query) { vtkDebugMacro(<<"neither OpenGL 1.5 nor GL_ARB_occlusion_query is supported"); } if(!supports_multitexture) { vtkDebugMacro(<<"neither OpenGL 1.3 nor GL_ARB_multitexture is supported"); } if(!supports_GL_ARB_texture_rectangle) { vtkDebugMacro(<<"GL_ARB_texture_rectangle is not supported"); } if(!supports_edge_clamp) { vtkDebugMacro(<<"neither OpenGL 1.2 nor GL_SGIS_texture_edge_clamp nor GL_EXT_texture_edge_clamp is not supported"); } if(!supportsAtLeast8AlphaBits) { vtkDebugMacro(<<"at least 8 alpha bits is not supported"); } if (!driver_support) { vtkDebugMacro(<<"buggy driver (Mesa or ATI)"); } } } vtkOpenGLClearErrorMacro(); } // ---------------------------------------------------------------------------- // Description: // Check the compilation status of some fragment shader source. void vtkDepthPeelingPass::CheckCompilation( unsigned int fragmentShader) { GLuint fs=static_cast(fragmentShader); GLint params; vtkgl::GetShaderiv(fs,vtkgl::COMPILE_STATUS,¶ms); if(params==GL_TRUE) { vtkDebugMacro(<<"shader source compiled successfully"); } else { vtkErrorMacro(<<"shader source compile error"); // include null terminator vtkgl::GetShaderiv(fs,vtkgl::INFO_LOG_LENGTH,¶ms); if(params>0) { char *buffer=new char[params]; vtkgl::GetShaderInfoLog(fs,params,0,buffer); vtkErrorMacro(<<"log: "<=0 int vtkDepthPeelingPass::RenderPeel(const vtkRenderState *s, int layer) { assert("pre: s_exists" && s!=0); assert("pre: positive_layer" && layer>=0); vtkOpenGLClearErrorMacro(); GLbitfield mask=GL_COLOR_BUFFER_BIT; if(layer>0) { mask=mask|GL_DEPTH_BUFFER_BIT; } glClearColor(0.0, 0.0, 0.0, 0.0); glClear(mask); // vtkgl::ActiveTexture(vtkgl::TEXTURE0+this->OpaqueShadowTexUnit); // glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,this->OpaqueLayerZ); // vtkgl::ActiveTexture(vtkgl::TEXTURE0+this->ShadowTexUnit); vtkOpenGLRenderer *oRenderer= static_cast(s->GetRenderer()); if(layer>0) { if(layer==1) { // allocate texture units. vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(this->Prog->GetContext()); vtkTextureUnitManager *m = context->GetTextureUnitManager(); // Avoid using texture unit 0 because the glBindTexture call's // below must specify unique active textures. If texture unit 0 // is used, the ActiveTexture TEXTURE0 and // TEXTURE0+ShadowTextUnit will both select TEXTURE0. Some // platforms, e.g. the Mac, may report the error: // "Samplers of different types use the same texture image unit." int tu; tu = m->Allocate(); if (tu == 0) { this->ShadowTexUnit=m->Allocate(); } else { this->ShadowTexUnit=tu; } if(this->ShadowTexUnit==-1) { vtkErrorMacro(<<"Ought. No texture unit left!"); return 0; } this->OpaqueShadowTexUnit=m->Allocate(); if(this->OpaqueShadowTexUnit==-1) { vtkErrorMacro(<<"Ought. No texture unit left!"); return 0; } if (tu != this->ShadowTexUnit) { m->Free(tu); } vtkUniformVariables *v=this->Shader->GetUniformVariables(); int ivalue; ivalue=this->ShadowTexUnit; // 1 v->SetUniformi("shadowTex",1,&ivalue); ivalue=this->OpaqueShadowTexUnit; //2 v->SetUniformi("opaqueShadowTex",1,&ivalue); } vtkgl::ActiveTexture(vtkgl::TEXTURE0+this->OpaqueShadowTexUnit); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,this->OpaqueLayerZ); vtkgl::ActiveTexture(vtkgl::TEXTURE0+this->ShadowTexUnit); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,this->TransparentLayerZ); oRenderer->SetShaderProgram(this->Prog); // this->Prog->Use(); } vtkgl::ActiveTexture(vtkgl::TEXTURE0 ); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); this->DepthPeelingHigherLayer=layer>0; this->TranslucentPass->Render(s); int numberOfRenderedProps=this->TranslucentPass->GetNumberOfRenderedProps(); if(layer>0) { this->DepthPeelingHigherLayer=0; oRenderer->SetShaderProgram(0); } // vtkgl::ActiveTexture(vtkgl::TEXTURE0+this->ShadowTexUnit); if(layer==0) { if(numberOfRenderedProps>0) { GLuint transparentLayerZ; glGenTextures(1,&transparentLayerZ); this->TransparentLayerZ=static_cast(transparentLayerZ); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,this->TransparentLayerZ); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, vtkgl::CLAMP_TO_EDGE); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, vtkgl::CLAMP_TO_EDGE); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB, vtkgl::TEXTURE_COMPARE_MODE, vtkgl::COMPARE_R_TO_TEXTURE); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB, vtkgl::TEXTURE_COMPARE_FUNC, GL_GREATER); // Allocate memory. verified that GPU supports // a texture of this size and format above. glTexImage2D(vtkgl::TEXTURE_RECTANGLE_ARB,0,this->DepthFormat, this->ViewportWidth,this->ViewportHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0); } } else { glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,this->TransparentLayerZ); } if((layer==0 && numberOfRenderedProps>0) || layer>0) { // Grab the z-buffer glCopyTexSubImage2D(vtkgl::TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->ViewportX, this->ViewportY,this->ViewportWidth, this->ViewportHeight); // Grab the rgba buffer GLuint rgba; glGenTextures(1,&rgba); glBindTexture(vtkgl::TEXTURE_RECTANGLE_ARB,rgba); // rgba format glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(vtkgl::TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Allocate memory. verified that GPU supports // a texture of this size and format above. glTexImage2D(vtkgl::TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, this->ViewportWidth,this->ViewportHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // Grab the rgba-buffer glCopyTexSubImage2D(vtkgl::TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->ViewportX, this->ViewportY,this->ViewportWidth, this->ViewportHeight); this->LayerList->List.push_back(rgba); vtkOpenGLCheckErrorMacro("failed after RenderPeel"); return 1; } else { vtkOpenGLCheckErrorMacro("failed after RenderPeel"); return 0; } }