Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1943 lines
67 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkOpenGLVolumeTextureMapper3D.cxx,v $
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 "vtkWindows.h"
#include "vtkOpenGLVolumeTextureMapper3D.h"
#include "vtkImageData.h"
#include "vtkMatrix4x4.h"
#include "vtkObjectFactory.h"
#include "vtkPlane.h"
#include "vtkPlaneCollection.h"
#include "vtkPointData.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkTimerLog.h"
#include "vtkVolumeProperty.h"
#include "vtkTransform.h"
#include "vtkLightCollection.h"
#include "vtkLight.h"
#include "vtkCamera.h"
#include "vtkMath.h"
#include "vtkOpenGLExtensionManager.h"
#include "vtkgl.h"
extern const char* vtkVolumeTextureMapper3D_OneComponentShadeFP;
extern const char* vtkVolumeTextureMapper3D_OneComponentNoShadeFP;
extern const char* vtkVolumeTextureMapper3D_TwoDependentNoShadeFP;
extern const char* vtkVolumeTextureMapper3D_TwoDependentShadeFP;
extern const char* vtkVolumeTextureMapper3D_FourDependentNoShadeFP;
extern const char* vtkVolumeTextureMapper3D_FourDependentShadeFP;
// Apple OS X doesn't have glTexImage3DEXT, but it does have glTexImage3D
#if defined(__APPLE__) && defined(GL_VERSION_1_4)
#ifdef TexImage3DEXT
#undef TexImage3DEXT
#endif
#define TexImage3DEXT TexImage3D
#ifdef TEXTURE_3D_EXT
#undef TEXTURE_3D_EXT
#endif
#define TEXTURE_3D_EXT TEXTURE_3D
#endif /* defined(__APPLE__) && defined(GL_VERSION_1_4) */
//extern "C" void (*glXGetProcAddressARB(const GLubyte *procName))( void );
//#ifdef _WIN32
//#endif
#define PrintError(S) \
{ \
GLenum errorCode; \
if ( (errorCode = glGetError()) != GL_NO_ERROR ) \
{ \
cout << S << endl; \
cout << "ERROR" << endl; \
switch (errorCode) \
{ \
case GL_INVALID_ENUM: cout << "invalid enum" << endl; break; \
case GL_INVALID_VALUE: cout << "invalid value" << endl; break; \
case GL_INVALID_OPERATION: cout << "invalid operation" << endl; break; \
case GL_STACK_OVERFLOW: cout << "stack overflow" << endl; break; \
case GL_STACK_UNDERFLOW: cout << "stack underflow" << endl; break; \
case GL_OUT_OF_MEMORY: cout << "out of memory" << endl; break; \
default: cout << "unknown error" << endl; \
} \
}}
//#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkOpenGLVolumeTextureMapper3D, "$Revision: 1.7.2.1 $");
vtkStandardNewMacro(vtkOpenGLVolumeTextureMapper3D);
//#endif
vtkOpenGLVolumeTextureMapper3D::vtkOpenGLVolumeTextureMapper3D()
{
this->Initialized = 0;
this->Volume1Index = 0;
this->Volume2Index = 0;
this->Volume3Index = 0;
this->ColorLookupIndex = 0;
this->RenderWindow = NULL;
}
vtkOpenGLVolumeTextureMapper3D::~vtkOpenGLVolumeTextureMapper3D()
{
}
// Release the graphics resources used by this texture.
void vtkOpenGLVolumeTextureMapper3D::ReleaseGraphicsResources(vtkWindow
*renWin)
{
if (( this->Volume1Index || this->Volume2Index ||
this->Volume3Index || this->ColorLookupIndex) && renWin)
{
((vtkRenderWindow *) renWin)->MakeCurrent();
#ifdef GL_VERSION_1_1
// free any textures
this->DeleteTextureIndex( &this->Volume1Index );
this->DeleteTextureIndex( &this->Volume2Index );
this->DeleteTextureIndex( &this->Volume3Index );
this->DeleteTextureIndex( &this->ColorLookupIndex );
this->DeleteTextureIndex( &this->AlphaLookupIndex );
#endif
}
this->Volume1Index = 0;
this->Volume2Index = 0;
this->Volume3Index = 0;
this->ColorLookupIndex = 0;
this->RenderWindow = NULL;
this->Modified();
}
void vtkOpenGLVolumeTextureMapper3D::Render(vtkRenderer *ren, vtkVolume *vol)
{
ren->GetRenderWindow()->MakeCurrent();
if ( !this->Initialized )
{
this->Initialize();
}
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NO_METHOD )
{
vtkErrorMacro( "required extensions not supported" );
return;
}
vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
vtkPlaneCollection *clipPlanes;
vtkPlane *plane;
int numClipPlanes = 0;
double planeEquation[4];
// build transformation
vol->GetMatrix(matrix);
matrix->Transpose();
glPushAttrib(GL_ENABLE_BIT |
GL_COLOR_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT |
GL_POLYGON_BIT |
GL_TEXTURE_BIT);
int i;
// Use the OpenGL clip planes
clipPlanes = this->ClippingPlanes;
if ( clipPlanes )
{
numClipPlanes = clipPlanes->GetNumberOfItems();
if (numClipPlanes > 6)
{
vtkErrorMacro(<< "OpenGL guarantees only 6 additional clipping planes");
}
for (i = 0; i < numClipPlanes; i++)
{
glEnable((GLenum)(GL_CLIP_PLANE0+i));
plane = (vtkPlane *)clipPlanes->GetItemAsObject(i);
planeEquation[0] = plane->GetNormal()[0];
planeEquation[1] = plane->GetNormal()[1];
planeEquation[2] = plane->GetNormal()[2];
planeEquation[3] = -(planeEquation[0]*plane->GetOrigin()[0]+
planeEquation[1]*plane->GetOrigin()[1]+
planeEquation[2]*plane->GetOrigin()[2]);
glClipPlane((GLenum)(GL_CLIP_PLANE0+i),planeEquation);
}
}
// insert model transformation
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glMultMatrixd(matrix->Element[0]);
glColor4f( 1.0, 1.0, 1.0, 1.0 );
// Turn lighting off - the polygon textures already have illumination
glDisable( GL_LIGHTING );
switch ( this->RenderMethod )
{
case vtkVolumeTextureMapper3D::NVIDIA_METHOD:
this->RenderNV(ren,vol);
break;
case vtkVolumeTextureMapper3D::FRAGMENT_PROGRAM_METHOD:
this->RenderFP(ren,vol);
break;
}
// pop transformation matrix
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
matrix->Delete();
glPopAttrib();
glFlush();
glFinish();
this->Timer->StopTimer();
this->TimeToDraw = (float)this->Timer->GetElapsedTime();
// If the timer is not accurate enough, set it to a small
// time so that it is not zero
if ( this->TimeToDraw == 0.0 )
{
this->TimeToDraw = 0.0001;
}
}
void vtkOpenGLVolumeTextureMapper3D::RenderFP( vtkRenderer *ren, vtkVolume *vol )
{
glAlphaFunc (GL_GREATER, (GLclampf) 0);
glEnable (GL_ALPHA_TEST);
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
int components = this->GetInput()->GetNumberOfScalarComponents();
switch ( components )
{
case 1:
if ( !vol->GetProperty()->GetShade() )
{
this->RenderOneIndependentNoShadeFP(ren,vol);
}
else
{
this->RenderOneIndependentShadeFP(ren,vol);
}
break;
case 2:
if ( !vol->GetProperty()->GetShade() )
{
this->RenderTwoDependentNoShadeFP(ren,vol);
}
else
{
this->RenderTwoDependentShadeFP(ren,vol);
}
break;
case 3:
case 4:
if ( !vol->GetProperty()->GetShade() )
{
this->RenderFourDependentNoShadeFP(ren,vol);
}
else
{
this->RenderFourDependentShadeFP(ren,vol);
}
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glDisable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glDisable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glDisable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
}
void vtkOpenGLVolumeTextureMapper3D::RenderNV( vtkRenderer *ren, vtkVolume *vol )
{
glAlphaFunc (GL_GREATER, (GLclampf) 0);
glEnable (GL_ALPHA_TEST);
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
int components = this->GetInput()->GetNumberOfScalarComponents();
switch ( components )
{
case 1:
if ( !vol->GetProperty()->GetShade() )
{
this->RenderOneIndependentNoShadeNV(ren,vol);
}
else
{
this->RenderOneIndependentShadeNV(ren,vol);
}
break;
case 2:
if ( !vol->GetProperty()->GetShade() )
{
this->RenderTwoDependentNoShadeNV(ren,vol);
}
else
{
this->RenderTwoDependentShadeNV(ren,vol);
}
break;
case 3:
case 4:
if ( !vol->GetProperty()->GetShade() )
{
this->RenderFourDependentNoShadeNV(ren,vol);
}
else
{
this->RenderFourDependentShadeNV(ren,vol);
}
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glDisable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glDisable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glDisable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
glDisable( vtkgl::TEXTURE_SHADER_NV );
glDisable(vtkgl::REGISTER_COMBINERS_NV);
}
void vtkOpenGLVolumeTextureMapper3D::DeleteTextureIndex( GLuint *index )
{
if (glIsTexture(*index))
{
GLuint tempIndex;
tempIndex = *index;
glDeleteTextures(1, &tempIndex);
*index = 0;
}
}
void vtkOpenGLVolumeTextureMapper3D::CreateTextureIndex( GLuint *index )
{
GLuint tempIndex=0;
glGenTextures(1, &tempIndex);
*index = (long) tempIndex;
}
void vtkOpenGLVolumeTextureMapper3D::RenderPolygons( vtkRenderer *ren,
vtkVolume *vol,
int stages[4] )
{
vtkRenderWindow *renWin = ren->GetRenderWindow();
if ( renWin->CheckAbortStatus() )
{
return;
}
double bounds[27][6];
float distance2[27];
int numIterations;
int i, j, k;
// No cropping case - render the whole thing
if ( !this->Cropping )
{
// Use the input data bounds - we'll take care of the volume's
// matrix during rendering
this->GetInput()->GetBounds(bounds[0]);
numIterations = 1;
}
// Simple cropping case - render the subvolume
else if ( this->CroppingRegionFlags == 0x2000 )
{
this->GetCroppingRegionPlanes(bounds[0]);
numIterations = 1;
}
// Complex cropping case - render each region in back-to-front order
else
{
// Get the camera position
double camPos[4];
ren->GetActiveCamera()->GetPosition(camPos);
double volBounds[6];
this->GetInput()->GetBounds(volBounds);
// Pass camera through inverse volume matrix
// so that we are in the same coordinate system
vtkMatrix4x4 *volMatrix = vtkMatrix4x4::New();
vol->GetMatrix( volMatrix );
camPos[3] = 1.0;
volMatrix->Invert();
volMatrix->MultiplyPoint( camPos, camPos );
volMatrix->Delete();
if ( camPos[3] )
{
camPos[0] /= camPos[3];
camPos[1] /= camPos[3];
camPos[2] /= camPos[3];
}
// These are the region limits for x (first four), y (next four) and
// z (last four). The first region limit is the lower bound for
// that axis, the next two are the region planes along that axis, and
// the final one in the upper bound for that axis.
float limit[12];
for ( i = 0; i < 3; i++ )
{
limit[i*4 ] = volBounds[i*2];
limit[i*4+1] = this->CroppingRegionPlanes[i*2];
limit[i*4+2] = this->CroppingRegionPlanes[i*2+1];
limit[i*4+3] = volBounds[i*2+1];
}
// For each of the 27 possible regions, find out if it is enabled,
// and if so, compute the bounds and the distance from the camera
// to the center of the region.
int numRegions = 0;
int region;
for ( region = 0; region < 27; region++ )
{
int regionFlag = 1<<region;
if ( this->CroppingRegionFlags & regionFlag )
{
// what is the coordinate in the 3x3x3 grid
int loc[3];
loc[0] = region%3;
loc[1] = (region/3)%3;
loc[2] = (region/9)%3;
// compute the bounds and center
float center[3];
for ( i = 0; i < 3; i++ )
{
bounds[numRegions][i*2 ] = limit[4*i+loc[i]];
bounds[numRegions][i*2+1] = limit[4*i+loc[i]+1];
center[i] =
(bounds[numRegions][i*2 ] +
bounds[numRegions][i*2+1])/2.0;
}
// compute the distance squared to the center
distance2[numRegions] =
(camPos[0]-center[0])*(camPos[0]-center[0]) +
(camPos[1]-center[1])*(camPos[1]-center[1]) +
(camPos[2]-center[2])*(camPos[2]-center[2]);
// we've added one region
numRegions++;
}
}
// Do a quick bubble sort on distance
for ( i = 1; i < numRegions; i++ )
{
for ( j = i; j > 0 && distance2[j] > distance2[j-1]; j-- )
{
float tmpBounds[6];
float tmpDistance2;
for ( k = 0; k < 6; k++ )
{
tmpBounds[k] = bounds[j][k];
}
tmpDistance2 = distance2[j];
for ( k = 0; k < 6; k++ )
{
bounds[j][k] = bounds[j-1][k];
}
distance2[j] = distance2[j-1];
for ( k = 0; k < 6; k++ )
{
bounds[j-1][k] = tmpBounds[k];
}
distance2[j-1] = tmpDistance2;
}
}
numIterations = numRegions;
}
// loop over all regions we need to render
for ( int loop = 0;
loop < numIterations;
loop++ )
{
// Compute the set of polygons for this region
// according to the bounds
this->ComputePolygons( ren, vol, bounds[loop] );
// Loop over the polygons
for ( i = 0; i < this->NumberOfPolygons; i++ )
{
if ( i%64 == 1 )
{
glFlush();
glFinish();
}
if ( renWin->CheckAbortStatus() )
{
return;
}
float *ptr = this->PolygonBuffer + 36*i;
glBegin( GL_TRIANGLE_FAN );
for ( j = 0; j < 6; j++ )
{
if ( ptr[0] < 0.0 )
{
break;
}
for ( k = 0; k < 4; k++ )
{
if ( stages[k] )
{
vtkgl::MultiTexCoord3fvARB( vtkgl::TEXTURE0_ARB + k, ptr );
}
}
glVertex3fv( ptr+3 );
ptr += 6;
}
glEnd();
}
}
}
void vtkOpenGLVolumeTextureMapper3D::Setup3DTextureParameters( vtkVolumeProperty *property )
{
if ( property->GetInterpolationType() == VTK_NEAREST_INTERPOLATION )
{
glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
}
else
{
glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP );
}
void vtkOpenGLVolumeTextureMapper3D::SetupOneIndependentTextures( vtkRenderer *vtkNotUsed(ren),
vtkVolume *vol )
{
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glEnable( vtkgl::TEXTURE_SHADER_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT);
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glEnable( vtkgl::TEXTURE_SHADER_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT);
}
// Update the volume containing the 2 byte scalar / gradient magnitude
if ( this->UpdateVolumes( vol ) || !this->Volume1Index || !this->Volume2Index )
{
int dim[3];
this->GetVolumeDimensions(dim);
this->DeleteTextureIndex(&this->Volume3Index);
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL);
this->DeleteTextureIndex(&this->Volume1Index);
this->CreateTextureIndex(&this->Volume1Index);
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index);
vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume1 );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL);
this->DeleteTextureIndex(&this->Volume2Index);
this->CreateTextureIndex(&this->Volume2Index);
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index);
vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGBA8, dim[0], dim[1], dim[2], 0,
GL_RGB, GL_UNSIGNED_BYTE, this->Volume2 );
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index);
this->Setup3DTextureParameters( vol->GetProperty() );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index);
this->Setup3DTextureParameters( vol->GetProperty() );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glEnable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV,
vtkgl::DEPENDENT_AR_TEXTURE_2D_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE0_ARB);
}
// Update the dependent 2D color table mapping scalar value and
// gradient magnitude to RGBA
if ( this->UpdateColorLookup( vol ) || !this->ColorLookupIndex )
{
this->DeleteTextureIndex( &this->ColorLookupIndex );
this->DeleteTextureIndex( &this->AlphaLookupIndex );
this->CreateTextureIndex( &this->ColorLookupIndex );
glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0,
GL_RGBA, GL_UNSIGNED_BYTE, this->ColorLookup );
}
glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex);
}
void vtkOpenGLVolumeTextureMapper3D::SetupRegisterCombinersNoShadeNV( vtkRenderer *vtkNotUsed(ren),
vtkVolume *vtkNotUsed(vol),
int components )
{
if ( components < 3 )
{
vtkgl::ActiveTextureARB(vtkgl::TEXTURE2_ARB);
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, GL_NONE);
if ( components == 1 )
{
vtkgl::ActiveTextureARB(vtkgl::TEXTURE3_ARB);
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, GL_NONE);
}
}
glEnable(vtkgl::REGISTER_COMBINERS_NV);
vtkgl::CombinerParameteriNV(vtkgl::NUM_GENERAL_COMBINERS_NV, 1);
vtkgl::CombinerParameteriNV(vtkgl::COLOR_SUM_CLAMP_NV, GL_TRUE);
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_A_NV, GL_ZERO, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_B_NV, GL_ZERO, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_C_NV, GL_ZERO, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
if ( components < 3 )
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_D_NV, vtkgl::TEXTURE1_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
else
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_D_NV, vtkgl::TEXTURE0_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
if ( components == 1 )
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE1_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA);
}
else
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE3_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA);
}
}
void vtkOpenGLVolumeTextureMapper3D::SetupRegisterCombinersShadeNV( vtkRenderer *ren,
vtkVolume *vol,
int components )
{
if ( components == 1 )
{
vtkgl::ActiveTextureARB(vtkgl::TEXTURE3_ARB);
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, GL_NONE);
}
GLfloat white[4] = {1,1,1,1};
GLfloat lightDirection[2][4];
GLfloat lightDiffuseColor[2][4];
GLfloat lightSpecularColor[2][4];
GLfloat halfwayVector[2][4];
GLfloat ambientColor[4];
// Gather information about the light sources. Although we gather info for multiple light sources,
// in this case we will only use the first one, and will duplicate it (in opposite direction) to
// approximate two-sided lighting.
this->GetLightInformation( ren, vol, lightDirection, lightDiffuseColor,
lightSpecularColor, halfwayVector, ambientColor );
float specularPower = vol->GetProperty()->GetSpecularPower();
glEnable(vtkgl::REGISTER_COMBINERS_NV);
glEnable( vtkgl::PER_STAGE_CONSTANTS_NV );
vtkgl::CombinerParameteriNV(vtkgl::NUM_GENERAL_COMBINERS_NV, 8);
vtkgl::CombinerParameteriNV(vtkgl::COLOR_SUM_CLAMP_NV, GL_TRUE);
// Stage 0
//
// N dot L is computed into vtkgl::SPARE0_NV
// -N dot L is computed into vtkgl::SPARE1_NV
//
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER0_NV, vtkgl::CONSTANT_COLOR0_NV, lightDirection[0] );
vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NORMAL_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NEGATE_NV, GL_RGB );
vtkgl::CombinerOutputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, vtkgl::DISCARD_NV,
GL_NONE, GL_NONE, GL_TRUE, GL_TRUE, GL_FALSE );
// Stage 1
//
// lightColor * max( 0, (N dot L)) + lightColor * max( 0, (-N dot L)) is computed into vtkgl::SPARE0_NV
//
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER1_NV, vtkgl::CONSTANT_COLOR0_NV, lightDiffuseColor[0] );
vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerOutputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::DISCARD_NV, vtkgl::DISCARD_NV,
vtkgl::SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// Stage 2
//
// result from Stage 1 is added to the ambient color and stored in vtkgl::PRIMARY_COLOR_NV
//
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER2_NV, vtkgl::CONSTANT_COLOR0_NV, white );
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER2_NV, vtkgl::CONSTANT_COLOR1_NV, ambientColor );
vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::CONSTANT_COLOR1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerOutputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::DISCARD_NV, vtkgl::DISCARD_NV,
vtkgl::PRIMARY_COLOR_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// Stage 3
//
// N dot H is computed into vtkgl::SPARE0_NV
// -N dot H is computed into vtkgl::SPARE1_NV
//
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER3_NV, vtkgl::CONSTANT_COLOR0_NV, halfwayVector[0] );
vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NORMAL_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NEGATE_NV, GL_RGB );
vtkgl::CombinerOutputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV,
vtkgl::DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_TRUE, GL_FALSE );
// Stage 4
//
// if the specular power is greater than 1, then
//
// N dot H squared is computed into vtkgl::SPARE0_NV
// -N dot H squared is computed into vtkgl::SPARE1_NV
//
// otherwise these registers are simply multiplied by white
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER4_NV, vtkgl::CONSTANT_COLOR0_NV, white );
vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
if ( specularPower > 1.0 )
{
vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
else
{
vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
vtkgl::CombinerOutputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, vtkgl::DISCARD_NV,
GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// Stage 5
//
// if the specular power is greater than 3, then
//
// N dot H to the fourth is computed into vtkgl::SPARE0_NV
// -N dot H to the fourth is computed into vtkgl::SPARE1_NV
//
// otherwise these registers are simply multiplied by white
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER5_NV, vtkgl::CONSTANT_COLOR0_NV, white );
vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
if ( specularPower > 3.0 )
{
vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
else
{
vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
vtkgl::CombinerOutputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, vtkgl::DISCARD_NV,
GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// Stage 6
//
// if the specular power is greater than 6, then
//
// N dot H to the eighth is computed into vtkgl::SPARE0_NV
// -N dot H to the eighth is computed into vtkgl::SPARE1_NV
//
// otherwise these registers are simply multiplied by white
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER6_NV, vtkgl::CONSTANT_COLOR0_NV, white );
vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
if ( specularPower > 6.0 )
{
vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
else
{
vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
vtkgl::CombinerOutputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV,
vtkgl::DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
// Stage 7
//
// Add the two specular contributions and multiply each by the specular color.
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER7_NV, vtkgl::CONSTANT_COLOR0_NV, lightSpecularColor[0] );
vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER7_NV, vtkgl::CONSTANT_COLOR1_NV, lightSpecularColor[1] );
vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_A_NV,
vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_B_NV,
vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_C_NV,
vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_D_NV,
vtkgl::CONSTANT_COLOR1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::CombinerOutputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::DISCARD_NV,
vtkgl::DISCARD_NV, vtkgl::SPARE0_NV,
GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE );
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_A_NV, vtkgl::PRIMARY_COLOR_NV,
vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
if ( components < 3 )
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_B_NV, vtkgl::TEXTURE1_ARB,
vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
else
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_B_NV, vtkgl::TEXTURE0_ARB,
vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
}
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_C_NV, GL_ZERO,
vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_D_NV, vtkgl::SPARE0_NV,
vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB );
if ( components == 1 )
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE1_ARB,
vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA);
}
else
{
vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE3_ARB,
vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA);
}
}
void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentNoShadeNV( vtkRenderer *ren,
vtkVolume *vol )
{
this->SetupOneIndependentTextures( ren, vol );
// Start the timer now
this->Timer->StartTimer();
this->SetupRegisterCombinersNoShadeNV( ren, vol, 1 );
int stages[4] = {1,0,0,0};
this->RenderPolygons( ren, vol, stages );
}
void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentShadeNV( vtkRenderer *ren,
vtkVolume *vol )
{
this->SetupOneIndependentTextures( ren, vol );
// Start the timer now
this->Timer->StartTimer();
this->SetupRegisterCombinersShadeNV( ren, vol, 1 );
int stages[4] = {1,0,1,0};
this->RenderPolygons( ren, vol, stages );
}
void vtkOpenGLVolumeTextureMapper3D::SetupTwoDependentTextures( vtkRenderer *vtkNotUsed(ren),
vtkVolume *vol )
{
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glEnable( vtkgl::TEXTURE_SHADER_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT);
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glEnable( vtkgl::TEXTURE_SHADER_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT);
}
// Update the volume containing the 3 byte scalars / gradient magnitude
if ( this->UpdateVolumes( vol ) || !this->Volume1Index || !this->Volume2Index )
{
int dim[3];
this->GetVolumeDimensions(dim);
this->DeleteTextureIndex(&this->Volume3Index);
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL);
this->DeleteTextureIndex(&this->Volume1Index);
this->CreateTextureIndex(&this->Volume1Index);
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index);
vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGB8, dim[0], dim[1], dim[2], 0,
GL_RGB, GL_UNSIGNED_BYTE, this->Volume1 );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL);
this->DeleteTextureIndex(&this->Volume2Index);
this->CreateTextureIndex(&this->Volume2Index);
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index);
vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGBA8, dim[0], dim[1], dim[2], 0,
GL_RGB, GL_UNSIGNED_BYTE, this->Volume2 );
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index);
this->Setup3DTextureParameters( vol->GetProperty() );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index);
this->Setup3DTextureParameters( vol->GetProperty() );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glEnable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV,
vtkgl::DEPENDENT_AR_TEXTURE_2D_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE0_ARB);
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB );
glEnable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV,
vtkgl::DEPENDENT_GB_TEXTURE_2D_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE0_ARB);
}
// Update the dependent 2D color table mapping scalar value and
// gradient magnitude to RGBA
if ( this->UpdateColorLookup( vol ) ||
!this->ColorLookupIndex || !this->AlphaLookupIndex )
{
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glBindTexture(GL_TEXTURE_2D, (GLuint)NULL);
this->DeleteTextureIndex(&this->ColorLookupIndex);
this->CreateTextureIndex(&this->ColorLookupIndex);
glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, 256, 256, 0,
GL_RGB, GL_UNSIGNED_BYTE, this->ColorLookup );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB );
glBindTexture(GL_TEXTURE_2D, (GLuint)NULL);
this->DeleteTextureIndex(&this->AlphaLookupIndex);
this->CreateTextureIndex(&this->AlphaLookupIndex);
glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA8, 256, 256, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, this->AlphaLookup );
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex);
vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB );
glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex);
}
void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentNoShadeNV( vtkRenderer *ren,
vtkVolume *vol )
{
this->SetupTwoDependentTextures(ren, vol);
// Start the timer now
this->Timer->StartTimer();
this->SetupRegisterCombinersNoShadeNV( ren, vol, 2 );
int stages[4] = {1,0,0,0};
this->RenderPolygons( ren, vol, stages );
}
void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentShadeNV( vtkRenderer *ren,
vtkVolume *vol )
{
this->SetupTwoDependentTextures( ren, vol );
// Start the timer now
this->Timer->StartTimer();
this->SetupRegisterCombinersShadeNV( ren, vol, 2 );
int stages[4] = {1,0,1,0};
this->RenderPolygons( ren, vol, stages );
}
void vtkOpenGLVolumeTextureMapper3D::SetupFourDependentTextures( vtkRenderer *vtkNotUsed(ren),
vtkVolume *vol )
{
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glEnable( vtkgl::TEXTURE_SHADER_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT);
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glEnable( vtkgl::TEXTURE_SHADER_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT);
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glDisable( GL_TEXTURE_2D );
glEnable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glEnable( vtkgl::TEXTURE_SHADER_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT);
}
// Update the volume containing the 3 byte scalars / gradient magnitude
if ( this->UpdateVolumes( vol ) || !this->Volume1Index ||
!this->Volume2Index || !this->Volume3Index )
{
int dim[3];
this->GetVolumeDimensions(dim);
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL);
this->DeleteTextureIndex(&this->Volume1Index);
this->CreateTextureIndex(&this->Volume1Index);
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index);
vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGB8, dim[0], dim[1], dim[2], 0,
GL_RGB, GL_UNSIGNED_BYTE, this->Volume1 );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL);
this->DeleteTextureIndex(&this->Volume2Index);
this->CreateTextureIndex(&this->Volume2Index);
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index);
vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume2 );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL);
this->DeleteTextureIndex(&this->Volume3Index);
this->CreateTextureIndex(&this->Volume3Index);
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume3Index);
vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGB8, dim[0], dim[1], dim[2], 0,
GL_RGB, GL_UNSIGNED_BYTE, this->Volume3 );
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index);
this->Setup3DTextureParameters( vol->GetProperty() );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index);
this->Setup3DTextureParameters( vol->GetProperty() );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB );
glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume3Index);
this->Setup3DTextureParameters( vol->GetProperty() );
vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB );
glEnable( GL_TEXTURE_2D );
glDisable( vtkgl::TEXTURE_3D_EXT );
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD )
{
glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV,
vtkgl::DEPENDENT_AR_TEXTURE_2D_NV );
glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE1_ARB);
}
// Update the dependent 2D table mapping scalar value and
// gradient magnitude to opacity
if ( this->UpdateColorLookup( vol ) || !this->AlphaLookupIndex )
{
this->DeleteTextureIndex(&this->ColorLookupIndex);
vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB );
glBindTexture(GL_TEXTURE_2D, (GLuint)NULL);
this->DeleteTextureIndex(&this->AlphaLookupIndex);
this->CreateTextureIndex(&this->AlphaLookupIndex);
glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA8, 256, 256, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, this->AlphaLookup );
}
vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB );
glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex);
}
void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentNoShadeNV( vtkRenderer *ren,
vtkVolume *vol )
{
this->SetupFourDependentTextures(ren, vol);
// Start the timer now
this->Timer->StartTimer();
this->SetupRegisterCombinersNoShadeNV( ren, vol, 4 );
int stages[4] = {1,1,0,0};
this->RenderPolygons( ren, vol, stages );
}
void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentShadeNV( vtkRenderer *ren,
vtkVolume *vol )
{
this->SetupFourDependentTextures( ren, vol );
// Start the timer now
this->Timer->StartTimer();
this->SetupRegisterCombinersShadeNV( ren, vol, 4 );
int stages[4] = {1,1,1,0};
this->RenderPolygons( ren, vol, stages );
}
void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentNoShadeFP( vtkRenderer *ren,
vtkVolume *vol )
{
glEnable( vtkgl::FRAGMENT_PROGRAM_ARB );
GLuint fragmentProgram;
vtkgl::GenProgramsARB( 1, &fragmentProgram );
vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram );
vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB,
vtkgl::PROGRAM_FORMAT_ASCII_ARB,
strlen(vtkVolumeTextureMapper3D_OneComponentNoShadeFP),
vtkVolumeTextureMapper3D_OneComponentNoShadeFP );
this->SetupOneIndependentTextures( ren, vol );
// Start the timer now
this->Timer->StartTimer();
int stages[4] = {1,0,0,0};
this->RenderPolygons( ren, vol, stages );
glDisable( vtkgl::FRAGMENT_PROGRAM_ARB );
vtkgl::DeleteProgramsARB( 1, &fragmentProgram );
}
void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentShadeFP( vtkRenderer *ren,
vtkVolume *vol )
{
glEnable( vtkgl::FRAGMENT_PROGRAM_ARB );
GLuint fragmentProgram;
vtkgl::GenProgramsARB( 1, &fragmentProgram );
vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram );
vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB,
vtkgl::PROGRAM_FORMAT_ASCII_ARB,
strlen(vtkVolumeTextureMapper3D_OneComponentShadeFP),
vtkVolumeTextureMapper3D_OneComponentShadeFP );
this->SetupOneIndependentTextures( ren, vol );
this->SetupProgramLocalsForShadingFP( ren, vol );
// Start the timer now
this->Timer->StartTimer();
int stages[4] = {1,1,1,0};
this->RenderPolygons( ren, vol, stages );
glDisable( vtkgl::FRAGMENT_PROGRAM_ARB );
vtkgl::DeleteProgramsARB( 1, &fragmentProgram );
}
void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentNoShadeFP( vtkRenderer *ren,
vtkVolume *vol )
{
glEnable( vtkgl::FRAGMENT_PROGRAM_ARB );
GLuint fragmentProgram;
vtkgl::GenProgramsARB( 1, &fragmentProgram );
vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram );
vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB,
vtkgl::PROGRAM_FORMAT_ASCII_ARB,
strlen(vtkVolumeTextureMapper3D_TwoDependentNoShadeFP),
vtkVolumeTextureMapper3D_TwoDependentNoShadeFP );
this->SetupTwoDependentTextures(ren, vol);
// Start the timer now
this->Timer->StartTimer();
int stages[4] = {1,0,0,0};
this->RenderPolygons( ren, vol, stages );
glDisable( vtkgl::FRAGMENT_PROGRAM_ARB );
vtkgl::DeleteProgramsARB( 1, &fragmentProgram );
}
void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentShadeFP( vtkRenderer *ren,
vtkVolume *vol )
{
glEnable( vtkgl::FRAGMENT_PROGRAM_ARB );
GLuint fragmentProgram;
vtkgl::GenProgramsARB( 1, &fragmentProgram );
vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram );
vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB,
vtkgl::PROGRAM_FORMAT_ASCII_ARB,
strlen(vtkVolumeTextureMapper3D_TwoDependentShadeFP),
vtkVolumeTextureMapper3D_TwoDependentShadeFP );
this->SetupTwoDependentTextures(ren, vol);
this->SetupProgramLocalsForShadingFP( ren, vol );
// Start the timer now
this->Timer->StartTimer();
int stages[4] = {1,0,1,0};
this->RenderPolygons( ren, vol, stages );
glDisable( vtkgl::FRAGMENT_PROGRAM_ARB );
vtkgl::DeleteProgramsARB( 1, &fragmentProgram );
}
void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentNoShadeFP( vtkRenderer *ren,
vtkVolume *vol )
{
glEnable( vtkgl::FRAGMENT_PROGRAM_ARB );
GLuint fragmentProgram;
vtkgl::GenProgramsARB( 1, &fragmentProgram );
vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram );
vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB,
vtkgl::PROGRAM_FORMAT_ASCII_ARB,
strlen(vtkVolumeTextureMapper3D_FourDependentNoShadeFP),
vtkVolumeTextureMapper3D_FourDependentNoShadeFP );
this->SetupFourDependentTextures(ren, vol);
// Start the timer now
this->Timer->StartTimer();
int stages[4] = {1,1,0,0};
this->RenderPolygons( ren, vol, stages );
glDisable( vtkgl::FRAGMENT_PROGRAM_ARB );
vtkgl::DeleteProgramsARB( 1, &fragmentProgram );
}
void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentShadeFP( vtkRenderer *ren,
vtkVolume *vol )
{
glEnable( vtkgl::FRAGMENT_PROGRAM_ARB );
GLuint fragmentProgram;
vtkgl::GenProgramsARB( 1, &fragmentProgram );
vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram );
vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB,
vtkgl::PROGRAM_FORMAT_ASCII_ARB,
strlen(vtkVolumeTextureMapper3D_FourDependentShadeFP),
vtkVolumeTextureMapper3D_FourDependentShadeFP );
this->SetupFourDependentTextures(ren, vol);
this->SetupProgramLocalsForShadingFP( ren, vol );
// Start the timer now
this->Timer->StartTimer();
int stages[4] = {1,1,1,0};
this->RenderPolygons( ren, vol, stages );
glDisable( vtkgl::FRAGMENT_PROGRAM_ARB );
vtkgl::DeleteProgramsARB( 1, &fragmentProgram );
}
void vtkOpenGLVolumeTextureMapper3D::GetLightInformation( vtkRenderer *ren,
vtkVolume *vol,
GLfloat lightDirection[2][4],
GLfloat lightDiffuseColor[2][4],
GLfloat lightSpecularColor[2][4],
GLfloat halfwayVector[2][4],
GLfloat ambientColor[4] )
{
float ambient = vol->GetProperty()->GetAmbient();
float diffuse = vol->GetProperty()->GetDiffuse();
float specular = vol->GetProperty()->GetSpecular();
vtkTransform *volumeTransform = vtkTransform::New();
volumeTransform->SetMatrix( vol->GetMatrix() );
volumeTransform->Inverse();
vtkLightCollection *lights = ren->GetLights();
lights->InitTraversal();
vtkLight *light[2];
light[0] = lights->GetNextItem();
light[1] = lights->GetNextItem();
int lightIndex = 0;
double cameraPosition[3];
double cameraFocalPoint[3];
ren->GetActiveCamera()->GetPosition( cameraPosition );
ren->GetActiveCamera()->GetFocalPoint( cameraFocalPoint );
double viewDirection[3];
volumeTransform->TransformPoint( cameraPosition, cameraPosition );
volumeTransform->TransformPoint( cameraFocalPoint, cameraFocalPoint );
viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0];
viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1];
viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2];
vtkMath::Normalize( viewDirection );
ambientColor[0] = 0.0;
ambientColor[1] = 0.0;
ambientColor[2] = 0.0;
ambientColor[3] = 0.0;
for ( lightIndex = 0; lightIndex < 2; lightIndex++ )
{
float dir[3] = {0,0,0};
float half[3] = {0,0,0};
if ( light[lightIndex] == NULL ||
light[lightIndex]->GetSwitch() == 0 )
{
lightDiffuseColor[lightIndex][0] = 0.0;
lightDiffuseColor[lightIndex][1] = 0.0;
lightDiffuseColor[lightIndex][2] = 0.0;
lightDiffuseColor[lightIndex][3] = 0.0;
lightSpecularColor[lightIndex][0] = 0.0;
lightSpecularColor[lightIndex][1] = 0.0;
lightSpecularColor[lightIndex][2] = 0.0;
lightSpecularColor[lightIndex][3] = 0.0;
}
else
{
float lightIntensity = light[lightIndex]->GetIntensity();
double lightColor[3];
light[lightIndex]->GetColor( lightColor );
double lightPosition[3];
double lightFocalPoint[3];
light[lightIndex]->GetTransformedPosition( lightPosition );
light[lightIndex]->GetTransformedFocalPoint( lightFocalPoint );
volumeTransform->TransformPoint( lightPosition, lightPosition );
volumeTransform->TransformPoint( lightFocalPoint, lightFocalPoint );
dir[0] = lightPosition[0] - lightFocalPoint[0];
dir[1] = lightPosition[1] - lightFocalPoint[1];
dir[2] = lightPosition[2] - lightFocalPoint[2];
vtkMath::Normalize( dir );
lightDiffuseColor[lightIndex][0] = lightColor[0]*diffuse*lightIntensity;
lightDiffuseColor[lightIndex][1] = lightColor[1]*diffuse*lightIntensity;
lightDiffuseColor[lightIndex][2] = lightColor[2]*diffuse*lightIntensity;
lightDiffuseColor[lightIndex][3] = 1.0;
lightSpecularColor[lightIndex][0] = lightColor[0]*specular*lightIntensity;
lightSpecularColor[lightIndex][1] = lightColor[1]*specular*lightIntensity;
lightSpecularColor[lightIndex][2] = lightColor[2]*specular*lightIntensity;
lightSpecularColor[lightIndex][3] = 0.0;
half[0] = dir[0] - viewDirection[0];
half[1] = dir[1] - viewDirection[1];
half[2] = dir[2] - viewDirection[2];
vtkMath::Normalize( half );
ambientColor[0] += ambient*lightColor[0];
ambientColor[1] += ambient*lightColor[1];
ambientColor[2] += ambient*lightColor[2];
}
lightDirection[lightIndex][0] = (dir[0]+1.0)/2.0;
lightDirection[lightIndex][1] = (dir[1]+1.0)/2.0;
lightDirection[lightIndex][2] = (dir[2]+1.0)/2.0;
lightDirection[lightIndex][3] = 0.0;
halfwayVector[lightIndex][0] = (half[0]+1.0)/2.0;
halfwayVector[lightIndex][1] = (half[1]+1.0)/2.0;
halfwayVector[lightIndex][2] = (half[2]+1.0)/2.0;
halfwayVector[lightIndex][3] = 0.0;
}
volumeTransform->Delete();
}
void vtkOpenGLVolumeTextureMapper3D::SetupProgramLocalsForShadingFP( vtkRenderer *ren,
vtkVolume *vol )
{
GLfloat lightDirection[2][4];
GLfloat lightDiffuseColor[2][4];
GLfloat lightSpecularColor[2][4];
GLfloat halfwayVector[2][4];
GLfloat ambientColor[4];
float ambient = vol->GetProperty()->GetAmbient();
float diffuse = vol->GetProperty()->GetDiffuse();
float specular = vol->GetProperty()->GetSpecular();
float specularPower = vol->GetProperty()->GetSpecularPower();
vtkTransform *volumeTransform = vtkTransform::New();
volumeTransform->SetMatrix( vol->GetMatrix() );
volumeTransform->Inverse();
vtkLightCollection *lights = ren->GetLights();
lights->InitTraversal();
vtkLight *light[2];
light[0] = lights->GetNextItem();
light[1] = lights->GetNextItem();
int lightIndex = 0;
double cameraPosition[3];
double cameraFocalPoint[3];
ren->GetActiveCamera()->GetPosition( cameraPosition );
ren->GetActiveCamera()->GetFocalPoint( cameraFocalPoint );
volumeTransform->TransformPoint( cameraPosition, cameraPosition );
volumeTransform->TransformPoint( cameraFocalPoint, cameraFocalPoint );
double viewDirection[4];
viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0];
viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1];
viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2];
viewDirection[3] = 0.0;
vtkMath::Normalize( viewDirection );
ambientColor[0] = 0.0;
ambientColor[1] = 0.0;
ambientColor[2] = 0.0;
ambientColor[3] = 0.0;
for ( lightIndex = 0; lightIndex < 2; lightIndex++ )
{
float dir[3] = {0,0,0};
float half[3] = {0,0,0};
if ( light[lightIndex] == NULL ||
light[lightIndex]->GetSwitch() == 0 )
{
lightDiffuseColor[lightIndex][0] = 0.0;
lightDiffuseColor[lightIndex][1] = 0.0;
lightDiffuseColor[lightIndex][2] = 0.0;
lightDiffuseColor[lightIndex][3] = 0.0;
lightSpecularColor[lightIndex][0] = 0.0;
lightSpecularColor[lightIndex][1] = 0.0;
lightSpecularColor[lightIndex][2] = 0.0;
lightSpecularColor[lightIndex][3] = 0.0;
}
else
{
float lightIntensity = light[lightIndex]->GetIntensity();
double lightColor[3];
light[lightIndex]->GetColor( lightColor );
double lightPosition[3];
double lightFocalPoint[3];
light[lightIndex]->GetTransformedPosition( lightPosition );
light[lightIndex]->GetTransformedFocalPoint( lightFocalPoint );
volumeTransform->TransformPoint( lightPosition, lightPosition );
volumeTransform->TransformPoint( lightFocalPoint, lightFocalPoint );
dir[0] = lightPosition[0] - lightFocalPoint[0];
dir[1] = lightPosition[1] - lightFocalPoint[1];
dir[2] = lightPosition[2] - lightFocalPoint[2];
vtkMath::Normalize( dir );
lightDiffuseColor[lightIndex][0] = lightColor[0]*diffuse*lightIntensity;
lightDiffuseColor[lightIndex][1] = lightColor[1]*diffuse*lightIntensity;
lightDiffuseColor[lightIndex][2] = lightColor[2]*diffuse*lightIntensity;
lightDiffuseColor[lightIndex][3] = 0.0;
lightSpecularColor[lightIndex][0] = lightColor[0]*specular*lightIntensity;
lightSpecularColor[lightIndex][1] = lightColor[1]*specular*lightIntensity;
lightSpecularColor[lightIndex][2] = lightColor[2]*specular*lightIntensity;
lightSpecularColor[lightIndex][3] = 0.0;
half[0] = dir[0] - viewDirection[0];
half[1] = dir[1] - viewDirection[1];
half[2] = dir[2] - viewDirection[2];
vtkMath::Normalize( half );
ambientColor[0] += ambient*lightColor[0];
ambientColor[1] += ambient*lightColor[1];
ambientColor[2] += ambient*lightColor[2];
}
lightDirection[lightIndex][0] = dir[0];
lightDirection[lightIndex][1] = dir[1];
lightDirection[lightIndex][2] = dir[2];
lightDirection[lightIndex][3] = 0.0;
halfwayVector[lightIndex][0] = half[0];
halfwayVector[lightIndex][1] = half[1];
halfwayVector[lightIndex][2] = half[2];
halfwayVector[lightIndex][3] = 0.0;
}
volumeTransform->Delete();
vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 0,
lightDirection[0][0],
lightDirection[0][1],
lightDirection[0][2],
lightDirection[0][3] );
vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 1,
halfwayVector[0][0],
halfwayVector[0][1],
halfwayVector[0][2],
halfwayVector[0][3] );
vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 2,
ambient, diffuse, specular, specularPower );
vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 3,
lightDiffuseColor[0][0],
lightDiffuseColor[0][1],
lightDiffuseColor[0][2],
lightDiffuseColor[0][3] );
vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 4,
lightSpecularColor[0][0],
lightSpecularColor[0][1],
lightSpecularColor[0][2],
lightSpecularColor[0][3] );
vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 5,
viewDirection[0],
viewDirection[1],
viewDirection[2],
viewDirection[3] );
vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 6, 2.0, -1.0, 0.0, 0.0 );
}
int vtkOpenGLVolumeTextureMapper3D::IsRenderSupported( vtkVolumeProperty *property )
{
if ( !this->Initialized )
{
this->Initialize();
}
if ( this->RenderMethod == vtkVolumeTextureMapper3D::NO_METHOD )
{
return 0;
}
if ( !this->GetInput() )
{
return 0;
}
if ( this->GetInput()->GetNumberOfScalarComponents() > 1 &&
property->GetIndependentComponents() )
{
return 0;
}
return 1;
}
void vtkOpenGLVolumeTextureMapper3D::Initialize()
{
this->Initialized = 1;
vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New();
extensions->SetRenderWindow(NULL); // set render window to current render window
int supports_GL_EXT_texture3D = extensions->ExtensionSupported( "GL_EXT_texture3D" );
int supports_GL_ARB_multitexture = extensions->ExtensionSupported( "GL_ARB_multitexture" );
int supports_GL_NV_texture_shader2 = extensions->ExtensionSupported( "GL_NV_texture_shader2" );
int supports_GL_NV_register_combiners2 = extensions->ExtensionSupported( "GL_NV_register_combiners2" );
int supports_GL_ATI_fragment_shader = extensions->ExtensionSupported( "GL_ATI_fragment_shader" );
int supports_GL_ARB_fragment_program = extensions->ExtensionSupported( "GL_ARB_fragment_program" );
int supports_GL_ARB_vertex_program = extensions->ExtensionSupported( "GL_ARB_vertex_program" );
int supports_GL_NV_register_combiners = extensions->ExtensionSupported( "GL_NV_register_combiners" );
if(supports_GL_EXT_texture3D)
{
extensions->LoadExtension("GL_EXT_texture3D");
}
if(supports_GL_ARB_multitexture)
{
extensions->LoadExtension("GL_ARB_multitexture" );
}
if(supports_GL_NV_texture_shader2)
{
extensions->LoadExtension("GL_NV_texture_shader2" );
}
if(supports_GL_NV_register_combiners2)
{
extensions->LoadExtension( "GL_NV_register_combiners2" );
}
if(supports_GL_ATI_fragment_shader)
{
extensions->LoadExtension( "GL_ATI_fragment_shader" );
}
if(supports_GL_ARB_fragment_program)
{
extensions->LoadExtension( "GL_ARB_fragment_program" );
}
if(supports_GL_ARB_vertex_program)
{
extensions->LoadExtension( "GL_ARB_vertex_program" );
}
if(supports_GL_NV_register_combiners)
{
extensions->LoadExtension( "GL_NV_register_combiners" );
}
extensions->Delete();
#if defined(__APPLE__) && defined(GL_VERSION_1_4)
// Apple doesn't have glTexImage3D_EXT, but it does have
// OpenGL 1.4 which supports glTexImage3D directly
supports_GL_EXT_texture3D = 1;
#endif
int canDoFP = 0;
int canDoNV = 0;
if ( supports_GL_EXT_texture3D &&
supports_GL_ARB_multitexture &&
supports_GL_ARB_fragment_program &&
supports_GL_ARB_vertex_program &&
vtkgl::TexImage3DEXT &&
vtkgl::ActiveTextureARB &&
vtkgl::MultiTexCoord3fvARB &&
vtkgl::GenProgramsARB &&
vtkgl::DeleteProgramsARB &&
vtkgl::BindProgramARB &&
vtkgl::ProgramStringARB &&
vtkgl::ProgramLocalParameter4fARB )
{
canDoFP = 1;
}
else if ( supports_GL_EXT_texture3D &&
supports_GL_ARB_multitexture &&
supports_GL_NV_texture_shader2 &&
supports_GL_NV_register_combiners2 &&
supports_GL_NV_register_combiners &&
vtkgl::TexImage3DEXT &&
vtkgl::ActiveTextureARB &&
vtkgl::MultiTexCoord3fvARB &&
vtkgl::CombinerParameteriNV &&
vtkgl::CombinerStageParameterfvNV &&
vtkgl::CombinerInputNV &&
vtkgl::CombinerOutputNV &&
vtkgl::FinalCombinerInputNV )
{
canDoNV = 1;
}
// can't do either
if ( !canDoFP && !canDoNV )
{
this->RenderMethod = vtkVolumeTextureMapper3D::NO_METHOD;
}
// can only do FragmentProgram
else if ( canDoFP && !canDoNV )
{
this->RenderMethod = vtkVolumeTextureMapper3D::FRAGMENT_PROGRAM_METHOD;
}
// can only do NVidia method
else if ( !canDoFP && canDoNV )
{
this->RenderMethod = vtkVolumeTextureMapper3D::NVIDIA_METHOD;
}
// can do both - pick the preferred one
else
{
this->RenderMethod = this->PreferredRenderMethod;
}
}
int vtkOpenGLVolumeTextureMapper3D::IsTextureSizeSupported( int size[3] )
{
if ( this->GetInput()->GetNumberOfScalarComponents() < 4 )
{
if ( size[0]*size[1]*size[2] > 128*256*256 )
{
return 0;
}
vtkgl::TexImage3DEXT( vtkgl::PROXY_TEXTURE_3D_EXT, 0, GL_RGBA8, size[0]*2,
size[1]*2, size[2], 0, GL_RGBA, GL_UNSIGNED_BYTE, this->Volume2 );
}
else
{
if ( size[0]*size[1]*size[2] > 128*128*128 )
{
return 0;
}
vtkgl::TexImage3DEXT( vtkgl::PROXY_TEXTURE_3D_EXT, 0, GL_RGBA8, size[0]*2,
size[1]*2, size[2]*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->Volume2 );
}
GLint params[1];
glGetTexLevelParameteriv ( vtkgl::PROXY_TEXTURE_3D_EXT, 0, GL_TEXTURE_WIDTH, params );
if ( params[0] != 0 )
{
return 1;
}
else
{
return 0;
}
}
// Print the vtkOpenGLVolumeTextureMapper3D
void vtkOpenGLVolumeTextureMapper3D::PrintSelf(ostream& os, vtkIndent indent)
{
vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New();
extensions->SetRenderWindow(NULL); // set render window to current render window
os << indent << "Initialized " << this->Initialized << endl;
if ( this->Initialized )
{
os << indent << "Supports GL_EXT_texture3D:"
<< extensions->ExtensionSupported( "GL_EXT_texture3D" ) << endl;
os << indent << "Supports GL_ARB_multitexture: "
<< extensions->ExtensionSupported( "GL_ARB_multitexture" ) << endl;
os << indent << "Supports GL_NV_texture_shader2: "
<< extensions->ExtensionSupported( "GL_NV_texture_shader2" ) << endl;
os << indent << "Supports GL_NV_register_combiners2: "
<< extensions->ExtensionSupported( "GL_NV_register_combiners2" ) << endl;
os << indent << "Supports GL_ATI_fragment_shader: "
<< extensions->ExtensionSupported( "GL_ATI_fragment_shader" ) << endl;
os << indent << "Supports GL_ARB_fragment_program: "
<< extensions->ExtensionSupported( "GL_ARB_fragment_program" ) << endl;
}
extensions->Delete();
this->Superclass::PrintSelf(os,indent);
}