You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/3rd/VTK7.1/source/VTK-7.1.1/Rendering/OpenGL/vtkDepthPeelingPass.cxx

960 lines
31 KiB
C++

/*=========================================================================
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 <cassert>
#include "vtkRenderState.h"
#include "vtkProp.h"
#include "vtkRenderer.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLExtensionManager.h"
#include "vtkgl.h"
#include <list>
#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<GLuint> 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)" <<endl;
}
}
// ----------------------------------------------------------------------------
// Description:
// Perform rendering according to a render state \p s.
// \pre s_exists: s!=0
void vtkDepthPeelingPass::Render(const vtkRenderState *s)
{
assert("pre: s_exists" && s!=0);
this->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 && i<s->GetPropArrayCount())
{
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<unsigned int>(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<vtkOpenGLRenderWindow *>(
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<GLuint>(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<GLclampf>(0),static_cast<GLclampf>(0),
static_cast<GLclampf>(0),static_cast<GLclampf>(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<GLuint>::reverse_iterator it=this->LayerList->List.rbegin();
std::list<GLuint>::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<GLuint>::const_iterator it2=this->LayerList->List.begin();
size_t layer=0;
while(layer<c)
{
ids[layer]=(*it2);
++layer;
++it2;
}
glDeleteTextures(static_cast<GLsizei>(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<const char **>(&vtkDepthPeeling_fs), 0);
vtkgl::CompileShader(shader);
GLint params;
vtkgl::GetShaderiv(shader,vtkgl::COMPILE_STATUS,
&params);
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<GLuint>(fragmentShader);
GLint params;
vtkgl::GetShaderiv(fs,vtkgl::COMPILE_STATUS,&params);
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,&params);
if(params>0)
{
char *buffer=new char[params];
vtkgl::GetShaderInfoLog(fs,params,0,buffer);
vtkErrorMacro(<<"log: "<<buffer);
delete[] buffer;
}
else
{
vtkErrorMacro(<<"no log");
}
}
vtkOpenGLClearErrorMacro();
}
// ----------------------------------------------------------------------------
// Description:
// Render a peel layer. If there is no more GPU RAM to save the texture,
// return false otherwise returns true. Also if layer==0 and no prop have
// been rendered (there is no translucent geometry), it returns false.
// \pre s_exists: s!=0
// \pre positive_layer: layer>=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<vtkOpenGLRenderer *>(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<unsigned int>(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;
}
}