/*========================================================================= Program: Visualization Toolkit Module: vtkOpenGLProperty.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 "vtkOpenGLRenderer.h" #include "vtkOpenGLProperty.h" #include "vtkOpenGL.h" #include "vtkObjectFactory.h" #include "vtkOpenGLExtensionManager.h" #include "vtkOpenGLGL2PSHelper.h" #include "vtkOpenGLTexture.h" #include "vtkTexture.h" #include "vtkgl.h" // vtkgl namespace #include "vtkShader2.h" #include "vtkShaderProgram2.h" #include "vtkUniformVariables.h" #include "vtkShader2Collection.h" #include "vtkTextureUnitManager.h" #include "vtkGLSLShaderDeviceAdapter2.h" #include "vtkOpenGLPainterDeviceAdapter.h" #include "vtkOpenGLRenderWindow.h" #include "vtkOpenGLError.h" #include namespace { void ComputeMaterialColor(GLfloat result[4], bool premultiply_colors_with_alpha, double color_factor, const double color[3], double opacity) { double opacity_factor = premultiply_colors_with_alpha? opacity : 1.0; for (int cc=0; cc < 3; cc++) { result[cc] = static_cast( opacity_factor * color_factor * color[cc]); } result[3] = opacity; } } vtkStandardNewMacro(vtkOpenGLProperty); extern const char *vtkOpenGLPropertyDefaultMain_vs; extern const char *vtkOpenGLPropertyDefaultMain_fs; extern const char *vtkOpenGLPropertyDefaultPropFunc_vs; extern const char *vtkOpenGLPropertyDefaultPropFunc_fs; vtkCxxSetObjectMacro(vtkOpenGLProperty,PropProgram,vtkShaderProgram2); vtkOpenGLProperty::vtkOpenGLProperty() { this->PropProgram = 0; this->CachedShaderProgram2 = 0; this->LastRendererShaderProgram2 = 0; this->LastPropProgram = 0; this->DefaultMainVS = 0; this->DefaultMainFS = 0; this->DefaultPropVS = 0; this->DefaultPropFS = 0; this->UseDefaultMainVS = false; this->UseDefaultMainFS = false; this->UseDefaultPropVS = false; this->UseDefaultPropFS = false; this->ShaderDeviceAdapter2 = 0; this->CurrentShaderProgram2 = 0; } vtkOpenGLProperty::~vtkOpenGLProperty() { this->SetPropProgram(0); if (this->CachedShaderProgram2) { this->CachedShaderProgram2->Delete(); this->CachedShaderProgram2 = 0; } if (this->DefaultMainVS) { this->DefaultMainVS->Delete(); this->DefaultMainVS = 0; } if (this->DefaultMainFS) { this->DefaultMainFS->Delete(); this->DefaultMainFS = 0; } if (this->DefaultPropVS) { this->DefaultPropVS->Delete(); this->DefaultPropVS = 0; } if (this->DefaultPropFS) { this->DefaultPropFS->Delete(); this->DefaultPropFS = 0; } if (this->ShaderDeviceAdapter2) { this->ShaderDeviceAdapter2->Delete(); this->ShaderDeviceAdapter2 = 0; } } vtkShaderDeviceAdapter2* vtkOpenGLProperty::GetShaderDeviceAdapter2() { return this->ShaderDeviceAdapter2; } // ---------------------------------------------------------------------------- void vtkOpenGLProperty::AddShaderVariable(const char *name, int numVars, int *x) { this->Superclass::AddShaderVariable(name, numVars, x); if (!this->PropProgram) { return; } vtkShader2Collection* shaders = this->PropProgram->GetShaders(); shaders->InitTraversal(); vtkShader2* shader = shaders->GetNextShader(); while (shader) { shader->GetUniformVariables()->SetUniformi(name, numVars, x); shader = shaders->GetNextShader(); } } // ---------------------------------------------------------------------------- void vtkOpenGLProperty::AddShaderVariable(const char *name, int numVars, float *x) { this->Superclass::AddShaderVariable(name, numVars, x); if (this->PropProgram) { if (this->PropProgram->GetUniformVariables()==0) { vtkUniformVariables *vars=vtkUniformVariables::New(); this->PropProgram->SetUniformVariables(vars); vars->Delete(); } this->PropProgram->GetUniformVariables()->SetUniformf(name, numVars, x); } } // ---------------------------------------------------------------------------- void vtkOpenGLProperty::AddShaderVariable(const char *name, int numVars, double *x) { float *xf = new float[numVars]; for (int i = 0; i < numVars; i++) { xf[i] = static_cast (x[i]); } this->AddShaderVariable(name, numVars, xf); delete [] xf; } // ---------------------------------------------------------------------------- bool vtkOpenGLProperty::RenderShaders(vtkActor* vtkNotUsed(anActor), vtkRenderer* ren) { // unbind any textures for starters vtkOpenGLRenderer *oRenderer = static_cast(ren); if (!oRenderer) { vtkErrorMacro("the vtkOpenGLProperty need a vtkOpenGLRenderer to render."); return false; } vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow()); vtkShaderProgram2* prog = oRenderer->GetShaderProgram(); if (prog) { assert("check: prog is initialized" && prog->GetContext() == context); } vtkOpenGLClearErrorMacro(); vtkShaderProgram2 *propProg; if (this->Shading) { propProg = this->PropProgram; } else { propProg = 0; } bool useShaders = false; if (prog || propProg) { bool shader_support = vtkShaderProgram2::IsSupported(context); // mesa doesn't support separate compilation units // os mesa: // 9.1.4 some tests failing vtkOpenGLExtensionManager *extensions = context->GetExtensionManager(); bool driver_support = !extensions->DriverIsMesa() || extensions->GetIgnoreDriverBugs( "Mesa support for separate compilation units"); if (shader_support && driver_support) { useShaders = true; } else { vtkErrorMacro(<<"Shaders are not supported by this context."); } } if (useShaders) { if (!this->CachedShaderProgram2) { this->CachedShaderProgram2 = vtkShaderProgram2::New(); this->CachedShaderProgram2->SetContext(context); } bool needCacheUpdate = (prog != this->LastRendererShaderProgram2) || (propProg != this->LastPropProgram); if (!needCacheUpdate && prog) { needCacheUpdate = this->CachedShaderProgram2->GetShaders()->GetMTime() < prog->GetShaders()->GetMTime(); } if (!needCacheUpdate && propProg) { needCacheUpdate = this->CachedShaderProgram2->GetShaders()->GetMTime() < propProg->GetShaders()->GetMTime(); } if (needCacheUpdate) { bool progHasVertex = (prog!=0 ? prog->HasVertexShaders() : false); bool progHasFragment = (prog!=0 ? prog->HasFragmentShaders() : false); bool needDefaultPropFuncVS = progHasVertex; bool needDefaultPropFuncFS = progHasFragment; bool needDefaultMainVS = false; bool needDefaultMainFS = false; if (propProg!=0) { needDefaultPropFuncVS = needDefaultPropFuncVS && !propProg->HasVertexShaders(); needDefaultPropFuncFS = needDefaultPropFuncFS && !propProg->HasFragmentShaders(); needDefaultMainVS = !progHasVertex && propProg->HasVertexShaders(); needDefaultMainFS = !progHasFragment && propProg->HasFragmentShaders(); } this->CachedShaderProgram2->ReleaseGraphicsResources(); this->CachedShaderProgram2->GetShaders()->RemoveAllItems(); this->CachedShaderProgram2->GetUniformVariables()->RemoveAllUniforms(); this->UseDefaultPropVS = false; this->UseDefaultPropFS = false; this->UseDefaultMainVS = false; this->UseDefaultMainFS = false; if (prog) { this->CachedShaderProgram2->GetShaders()->AddCollection( prog->GetShaders()); } if (propProg) { this->CachedShaderProgram2->GetShaders()->AddCollection( propProg->GetShaders()); } this->LastRendererShaderProgram2 = prog; this->LastPropProgram = propProg; if (needDefaultPropFuncVS) { if (!this->DefaultPropVS) { this->UseDefaultPropVS = false; this->DefaultPropVS = vtkShader2::New(); this->DefaultPropVS->SetType(VTK_SHADER_TYPE_VERTEX); this->DefaultPropVS->SetSourceCode( vtkOpenGLPropertyDefaultPropFunc_vs); this->DefaultPropVS->SetContext(context); } if (!this->UseDefaultPropVS) { this->CachedShaderProgram2->GetShaders()->AddItem( this->DefaultPropVS); this->UseDefaultPropVS = true; } } if (needDefaultPropFuncFS) { if (!this->DefaultPropFS) { this->UseDefaultPropFS = false; this->DefaultPropFS = vtkShader2::New(); this->DefaultPropFS->SetType(VTK_SHADER_TYPE_FRAGMENT); this->DefaultPropFS->SetSourceCode( vtkOpenGLPropertyDefaultPropFunc_fs); this->DefaultPropFS->SetContext(context); } vtkUniformVariables *v = this->DefaultPropFS->GetUniformVariables(); int value; value = 0; v->SetUniformi("useTexture", 1, &value); value = 0; // allocate texture unit? v->SetUniformi("uTexture", 1, &value); if (!UseDefaultPropFS) { this->CachedShaderProgram2->GetShaders()->AddItem( this->DefaultPropFS); this->UseDefaultPropFS=true; } } if (needDefaultMainVS) { if (!this->DefaultMainVS) { this->UseDefaultMainVS = false; this->DefaultMainVS = vtkShader2::New(); this->DefaultMainVS->SetType(VTK_SHADER_TYPE_VERTEX); this->DefaultMainVS->SetSourceCode(vtkOpenGLPropertyDefaultMain_vs); this->DefaultMainVS->SetContext(context); } if (!this->UseDefaultMainVS) { this->CachedShaderProgram2->GetShaders()->AddItem( this->DefaultMainVS); this->UseDefaultMainVS = true; } } if (needDefaultMainFS) { if (!this->DefaultMainFS) { this->UseDefaultMainFS = false; this->DefaultMainFS=vtkShader2::New(); this->DefaultMainFS->SetType(VTK_SHADER_TYPE_FRAGMENT); this->DefaultMainFS->SetSourceCode(vtkOpenGLPropertyDefaultMain_fs); this->DefaultMainFS->SetContext(context); } if (!this->UseDefaultMainFS) { this->CachedShaderProgram2->GetShaders()->AddItem( this->DefaultMainFS); this->UseDefaultMainFS = true; } } if (!this->ShaderDeviceAdapter2) { this->ShaderDeviceAdapter2 = vtkGLSLShaderDeviceAdapter2::New(); } this->ShaderDeviceAdapter2->SetShaderProgram(this->CachedShaderProgram2); } if (prog && (needCacheUpdate || this->CachedShaderProgram2->GetUniformVariables()->GetMTime() < prog->GetUniformVariables()->GetMTime())) { vtkUniformVariables *v = prog->GetUniformVariables(); this->CachedShaderProgram2->GetUniformVariables()->Merge(v); } if (propProg && (needCacheUpdate || this->CachedShaderProgram2->GetUniformVariables()->GetMTime() < propProg->GetUniformVariables()->GetMTime())) { vtkUniformVariables *v = propProg->GetUniformVariables(); this->CachedShaderProgram2->GetUniformVariables()->Merge(v); } this->CurrentShaderProgram2 = this->CachedShaderProgram2; } else { this->CurrentShaderProgram2 = 0; } if (this->CurrentShaderProgram2) { this->CurrentShaderProgram2->Build(); if (this->CurrentShaderProgram2->GetLastBuildStatus() != VTK_SHADER_PROGRAM2_LINK_SUCCEEDED) { vtkErrorMacro("Couldn't build the shader program. At this point , it can be an error in a shader or a driver bug."); this->CurrentShaderProgram2 = 0; this->CachedShaderProgram2->ReleaseGraphicsResources(); } else { this->CurrentShaderProgram2->Use(); if(!this->CurrentShaderProgram2->IsValid()) { vtkErrorMacro(<< "Using the current shader program is invalid with the current OpenGL state. Validation log=" << this->CurrentShaderProgram2->GetLastValidateLog()); } } } // Previous implementation of Render() used to test the prog variable to // determine if new style texture was to be used. We are letting that logic // be. return (prog != NULL); } // ---------------------------------------------------------------------------- // Implement base class method. void vtkOpenGLProperty::Render(vtkActor *anActor, vtkRenderer *ren) { bool rendered_shader_program2 = this->RenderShaders(anActor, ren); vtkOpenGLRenderWindow* context = vtkOpenGLRenderWindow::SafeDownCast( ren->GetRenderWindow()); if (!context) { // must be an OpenGL context. return; } // set interpolation switch (this->Interpolation) { case VTK_FLAT: glShadeModel(GL_FLAT); break; case VTK_GOURAUD: case VTK_PHONG: default: glShadeModel(GL_SMOOTH); break; } if (this->Lighting) // fixed-pipeline { glEnable(GL_LIGHTING); } else { glDisable(GL_LIGHTING); } // Set the PointSize glPointSize(this->PointSize); vtkOpenGLGL2PSHelper::SetPointSize(this->PointSize); // Set the LineWidth glLineWidth(this->LineWidth); vtkOpenGLGL2PSHelper::SetLineWidth(this->LineWidth); // Set the LineStipple if (this->LineStipplePattern != 0xFFFF) { glEnable(GL_LINE_STIPPLE); glLineStipple(this->LineStippleRepeatFactor, static_cast(this->LineStipplePattern)); vtkOpenGLGL2PSHelper::EnableStipple(); // must be called after glLineStipple } else { // still need to set this although we are disabling. else the ATI X1600 // (for example) still manages to stipple under certain conditions. glLineStipple(this->LineStippleRepeatFactor, static_cast(this->LineStipplePattern)); glDisable(GL_LINE_STIPPLE); vtkOpenGLGL2PSHelper::DisableStipple(); } glDisable(GL_TEXTURE_2D); // fixed-pipeline // disable alpha testing (this may have been enabled // by another actor in OpenGLTexture) glDisable (GL_ALPHA_TEST); glDisable(GL_COLOR_MATERIAL); // fixed-pipeline // turn on/off backface culling if (! this->BackfaceCulling && ! this->FrontfaceCulling) { glDisable (GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } else if (this->BackfaceCulling) { glCullFace (GL_BACK); glEnable (GL_CULL_FACE); } else //if both front & back culling on, will fall into backface culling { //if you really want both front and back, use the Actor's visibility flag glCullFace (GL_FRONT); glEnable (GL_CULL_FACE); } vtkOpenGLProperty::SetMaterialProperties( static_cast(GL_FRONT_AND_BACK), this->Ambient, this->AmbientColor, this->Diffuse, this->DiffuseColor, this->Specular, this->SpecularColor, this->SpecularPower, this->Opacity, context); this->RenderTextures(anActor, ren, rendered_shader_program2); this->Superclass::Render(anActor, ren); } //----------------------------------------------------------------------------- void vtkOpenGLProperty::SetMaterialProperties( unsigned int _face, double ambient, const double ambient_color[3], double diffuse, const double diffuse_color[3], double specular, const double specular_color[3], double specular_power, double opacity, vtkOpenGLRenderWindow* context) { GLenum face = static_cast(_face); // Dealing with having a correct alpha (none square) in the framebuffer // is only required if there is an alpha component in the framebuffer // (doh...) and if we cannot deal directly with BlendFuncSeparate. GLint alphaBits = context->GetAlphaBitPlanes(); bool premultiply_colors_with_alpha = (vtkgl::BlendFuncSeparate==0 && alphaBits>0); GLfloat ambientGL[4]; ComputeMaterialColor(ambientGL, premultiply_colors_with_alpha, ambient, ambient_color, opacity); GLfloat diffuseGL[4]; ComputeMaterialColor(diffuseGL, premultiply_colors_with_alpha, diffuse, diffuse_color, opacity); GLfloat specularGL[4]; ComputeMaterialColor(specularGL, premultiply_colors_with_alpha, specular, specular_color, opacity); glMaterialfv(face, GL_AMBIENT, ambientGL); glMaterialfv(face, GL_DIFFUSE, diffuseGL); glMaterialfv(face, GL_SPECULAR, specularGL); glMaterialf(face, GL_SHININESS, static_cast(specular_power)); // The material properties set above are used if shading is // enabled. This color set here is used if shading is // disabled. Shading is disabled in the // vtkOpenGLPolyDataMapper::Draw() method if points or lines // are encountered without normals. double composite_color[3]; vtkProperty::ComputeCompositeColor(composite_color, ambient, ambient_color, diffuse, diffuse_color, specular, specular_color); GLfloat colorGL[4]; ComputeMaterialColor(colorGL, premultiply_colors_with_alpha, 1.0, composite_color, opacity); glColor4fv(colorGL); } //----------------------------------------------------------------------------- bool vtkOpenGLProperty::RenderTextures(vtkActor*, vtkRenderer* ren, bool rendered_shader_program2) { vtkOpenGLRenderWindow* context = vtkOpenGLRenderWindow::SafeDownCast( ren->GetRenderWindow()); assert(context!=NULL); // render any textures. int numTextures = this->GetNumberOfTextures(); if (numTextures > 0) { if (!rendered_shader_program2) // fixed-pipeline multitexturing or old XML shaders. { this->LoadMultiTexturingExtensions(ren); if (vtkgl::ActiveTexture) { GLint numSupportedTextures; glGetIntegerv(vtkgl::MAX_TEXTURE_UNITS, &numSupportedTextures); for (int t = 0; t < numTextures; t++) { int texture_unit = this->GetTextureUnitAtIndex(t); if (texture_unit >= numSupportedTextures || texture_unit < 0) { vtkErrorMacro("Hardware does not support the number of textures defined."); continue; } vtkgl::ActiveTexture(vtkgl::TEXTURE0 + static_cast(texture_unit)); this->GetTextureAtIndex(t)->Render(ren); } vtkgl::ActiveTexture(vtkgl::TEXTURE0); } else { this->GetTextureAtIndex(0)->Render(ren); // one-texture fixed-pipeline } } else { // texture unit are assigned at each call to render, as render can // happen in different/multiple passes. vtkTextureUnitManager *m = context->GetTextureUnitManager(); for (int t = 0; t < numTextures; t++) { vtkTexture *tex = this->GetTextureAtIndex(t); int unit = m->Allocate(); if (unit == -1) { vtkErrorMacro(<<" not enough texture units."); return false; } this->SetTexture(unit,tex); vtkgl::ActiveTexture(vtkgl::TEXTURE0 + static_cast(unit)); // bind (and load if not yet loaded) tex->Render(ren); } vtkgl::ActiveTexture(vtkgl::TEXTURE0); } } vtkOpenGLCheckErrorMacro("failed after Render"); return (numTextures > 0); } //----------------------------------------------------------------------------- void vtkOpenGLProperty::PostRender(vtkActor *actor, vtkRenderer *renderer) { vtkOpenGLClearErrorMacro(); vtkOpenGLRenderer *oRenderer = static_cast(renderer); vtkShaderProgram2 *prog = oRenderer->GetShaderProgram(); // Reset the face culling now we are done, leaking into text actor etc. if (this->BackfaceCulling || this->FrontfaceCulling) { glDisable(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } if (this->CurrentShaderProgram2) // ie if shaders are supported { this->CurrentShaderProgram2->Restore(); this->CurrentShaderProgram2 = 0; } this->Superclass::PostRender(actor, renderer); // render any textures. int numTextures = this->GetNumberOfTextures(); if (numTextures > 0 && vtkgl::ActiveTexture) { if (!prog) // fixed-pipeline multitexturing or old XML shaders. { GLint numSupportedTextures; glGetIntegerv(vtkgl::MAX_TEXTURE_UNITS, &numSupportedTextures); for (int i = 0; i < numTextures; i++) { int texture_unit = this->GetTextureUnitAtIndex(i); if (texture_unit >= numSupportedTextures || texture_unit < 0) { vtkErrorMacro("Hardware does not support the number of textures defined."); continue; } vtkgl::ActiveTexture(vtkgl::TEXTURE0+ static_cast(texture_unit)); // Disable any possible texture. Wouldn't having a PostRender on // vtkTexture be better? glDisable(GL_TEXTURE_1D); glDisable(GL_TEXTURE_2D); glDisable(vtkgl::TEXTURE_3D); glDisable(vtkgl::TEXTURE_RECTANGLE_ARB); glDisable(vtkgl::TEXTURE_CUBE_MAP); } vtkgl::ActiveTexture(vtkgl::TEXTURE0); } else { vtkTextureUnitManager* m = static_cast(renderer->GetRenderWindow())->GetTextureUnitManager(); for (int t = 0; t < numTextures; t++) { int textureUnit=this->GetTextureUnitAtIndex(t); m->Free(textureUnit); } vtkgl::ActiveTexture(vtkgl::TEXTURE0); } } vtkOpenGLCheckErrorMacro("failed after PostRender"); } //----------------------------------------------------------------------------- // Implement base class method. void vtkOpenGLProperty::BackfaceRender(vtkActor *vtkNotUsed(anActor), vtkRenderer *ren) { vtkOpenGLRenderWindow* context = vtkOpenGLRenderWindow::SafeDownCast( ren->GetRenderWindow()); vtkOpenGLProperty::SetMaterialProperties( static_cast(GL_BACK), this->Ambient, this->AmbientColor, this->Diffuse, this->DiffuseColor, this->Specular, this->SpecularColor, this->SpecularPower, this->Opacity, context); } //----------------------------------------------------------------------------- void vtkOpenGLProperty::LoadMultiTexturingExtensions(vtkRenderer* ren) { if (!vtkgl::MultiTexCoord2d || !vtkgl::ActiveTexture) { vtkOpenGLExtensionManager* extensions = vtkOpenGLExtensionManager::New(); extensions->SetRenderWindow(ren->GetRenderWindow()); // multitexture is a core feature of OpenGL 1.3. // multitexture is an ARB extension of OpenGL 1.2.1 int supports_GL_1_3 = extensions->ExtensionSupported( "GL_VERSION_1_3" ); int supports_GL_1_2_1 = extensions->ExtensionSupported("GL_VERSION_1_2"); int supports_ARB_mutlitexture = extensions->ExtensionSupported( "GL_ARB_multitexture"); if (supports_GL_1_3) { extensions->LoadExtension("GL_VERSION_1_3"); } else if(supports_GL_1_2_1 && supports_ARB_mutlitexture) { extensions->LoadExtension("GL_VERSION_1_2"); extensions->LoadCorePromotedExtension("GL_ARB_multitexture"); } extensions->Delete(); } } //----------------------------------------------------------------------------- void vtkOpenGLProperty::ReleaseGraphicsResources(vtkWindow *win) { // release any textures. int numTextures = this->GetNumberOfTextures(); if (win && win->GetMapped() && numTextures > 0 && vtkgl::ActiveTexture) { vtkOpenGLClearErrorMacro(); GLint numSupportedTextures; glGetIntegerv(vtkgl::MAX_TEXTURE_UNITS, &numSupportedTextures); for (int i = 0; i < numTextures; i++) { if (vtkOpenGLTexture::SafeDownCast(this->GetTextureAtIndex(i))->GetIndex() == 0) { continue; } int texture_unit = this->GetTextureUnitAtIndex(i); if (texture_unit >= numSupportedTextures || texture_unit < 0) { vtkErrorMacro("Hardware does not support the texture unit " << texture_unit << "."); continue; } vtkgl::ActiveTexture(vtkgl::TEXTURE0 + static_cast(texture_unit)); this->GetTextureAtIndex(i)->ReleaseGraphicsResources(win); } vtkgl::ActiveTexture(vtkgl::TEXTURE0); vtkOpenGLCheckErrorMacro("failwed during ReleaseGraphicsResources"); } else if (numTextures > 0 && vtkgl::ActiveTexture) { for (int i = 0; i < numTextures; i++) { this->GetTextureAtIndex(i)->ReleaseGraphicsResources(win); } } this->Superclass::ReleaseGraphicsResources(win); if (this->CachedShaderProgram2) { this->CachedShaderProgram2->ReleaseGraphicsResources(); } if (this->PropProgram) { this->PropProgram->ReleaseGraphicsResources(); } if (this->DefaultMainVS) { this->DefaultMainVS->ReleaseGraphicsResources(); } if (this->DefaultMainFS) { this->DefaultMainFS->ReleaseGraphicsResources(); } if (this->DefaultPropVS) { this->DefaultPropVS->ReleaseGraphicsResources(); } if (this->DefaultPropFS) { this->DefaultPropFS->ReleaseGraphicsResources(); } } //---------------------------------------------------------------------------- void vtkOpenGLProperty::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Shader2Collection: "; if (this->PropProgram) { os << endl; this->PropProgram->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } if (this->CurrentShaderProgram2) { os << endl; this->CurrentShaderProgram2->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } if (this->ShaderDeviceAdapter2) { os << endl; this->ShaderDeviceAdapter2->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } }