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.
299 lines
9.8 KiB
C++
299 lines
9.8 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkVolumeTexture.h
|
|
|
|
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.
|
|
|
|
=========================================================================*/
|
|
|
|
/**
|
|
* @class vtkVolumeTexture
|
|
* @brief Creates and manages the volume texture rendered by
|
|
* vtkOpenGLGPUVolumeRayCastMapper.
|
|
*
|
|
* Wraps a vtkTextureObject for which it selects the appropriate format
|
|
* (depending on the input vtkDataArray type, number of components, etc.) and
|
|
* loads input data. The class maintains a set of members of interest to the
|
|
* parent mapper, such as:
|
|
*
|
|
* * Active vtkDataArray scalar range.
|
|
* * Volume's scale and bias (pixel transfer functions).
|
|
* * HandleLargeDataType flag.
|
|
* * Texture to data transformations.
|
|
* * Block extents
|
|
* * Block loaded bounds
|
|
*
|
|
* This class supports streaming the volume data in separate blocks to make it
|
|
* fit in graphics memory (sometimes referred to as bricking). The data is split
|
|
* into a user-defined number of blocks in such a way that a single sub-block
|
|
* (brick) fits completely into GPU memory. A stride is passed to OpenGL so
|
|
* that it can access the underlying vtkDataArray adequately for each of the
|
|
* blocks to be streamed into GPU memory (back-to-front for correct
|
|
* composition).
|
|
*
|
|
* Streaming the volume as separate texture bricks certainly imposes a
|
|
* performance trade-off but acts as a graphics memory expansion scheme for
|
|
* devices that would not be able to render higher resoulution volumes
|
|
* otherwise.
|
|
*
|
|
* @warning There are certain caveats when texture streaming is enabled, given
|
|
* the locality constraint that rendering a single block imposes.
|
|
*
|
|
* - Quality might suffer near the block seams with ShadeOn() (gradient
|
|
* computation at the boundaries needs adjustment).
|
|
*
|
|
* - Not all of the features supported by the mapper currently work correctly.
|
|
* This is a list of known issues:
|
|
* -# Blending modes such as average and additive might compute a different
|
|
* value near the edges.
|
|
*
|
|
* - Future work will extend the API to be able to compute an ideal number of
|
|
* partitions and extents based on the platform capabilities.
|
|
*
|
|
* @warning This is an internal class of vtkOpenGLGPUVolumeRayCastMapper. It
|
|
* assumes there is an active OpenGL context in methods involving GL calls
|
|
* (MakeCurrent() is expected to be called in the mapper beforehand).
|
|
*/
|
|
|
|
#ifndef vtkVolumeTexture_h
|
|
#define vtkVolumeTexture_h
|
|
#include <map> // For ImageDataBlockMap
|
|
#include <vector> // For ImageDataBlocks
|
|
|
|
#include "vtkMatrix4x4.h" // For vtkMatrix4
|
|
#include "vtkNew.h" // For vtkNew
|
|
#include "vtkObject.h"
|
|
#include "vtkRenderingVolumeOpenGL2Module.h" // For export macro
|
|
#include "vtkSmartPointer.h" // For SmartPointer
|
|
#include "vtkTimeStamp.h" // For UploadTime
|
|
#include "vtkTuple.h" // For Size6 and Size3
|
|
|
|
class vtkDataArray;
|
|
class vtkImageData;
|
|
class vtkVolumeProperty;
|
|
class vtkRenderer;
|
|
class vtkTextureObject;
|
|
class vtkWindow;
|
|
|
|
class VTKRENDERINGVOLUMEOPENGL2_EXPORT vtkVolumeTexture : public vtkObject
|
|
{
|
|
typedef vtkTuple<int, 6> Size6;
|
|
typedef vtkTuple<int, 3> Size3;
|
|
|
|
public:
|
|
static vtkVolumeTexture* New();
|
|
|
|
struct VolumeBlock
|
|
{
|
|
VolumeBlock(vtkImageData* imData, vtkTextureObject* tex, Size3 const& texSize)
|
|
{
|
|
// Block extent is stored in vtkImageData
|
|
ImageData = imData;
|
|
TextureObject = tex;
|
|
TextureSize = texSize;
|
|
TupleIndex = 0;
|
|
|
|
this->Extents[0] = VTK_INT_MAX;
|
|
this->Extents[1] = VTK_INT_MIN;
|
|
this->Extents[2] = VTK_INT_MAX;
|
|
this->Extents[3] = VTK_INT_MIN;
|
|
this->Extents[4] = VTK_INT_MAX;
|
|
this->Extents[5] = VTK_INT_MIN;
|
|
}
|
|
|
|
vtkImageData* ImageData;
|
|
vtkTextureObject* TextureObject;
|
|
Size3 TextureSize;
|
|
vtkIdType TupleIndex;
|
|
vtkNew<vtkMatrix4x4> TextureToDataset;
|
|
vtkNew<vtkMatrix4x4> TextureToDatasetInv;
|
|
|
|
float CellStep[3];
|
|
double DatasetStepSize[3];
|
|
|
|
/**
|
|
* LoadedBounds are corrected for cell-data (if that is the case). So they
|
|
* are not equivalent to vtkImageData::GetBounds().
|
|
*/
|
|
double LoadedBounds[6];
|
|
double LoadedBoundsAA[6];
|
|
double VolumeGeometry[24];
|
|
int Extents[6];
|
|
};
|
|
|
|
vtkTypeMacro(vtkVolumeTexture, vtkObject);
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
|
|
|
/**
|
|
* Set a number of blocks per axis.
|
|
*/
|
|
void SetPartitions(int const i, int const j, int const k);
|
|
const Size3& GetPartitions();
|
|
|
|
/**
|
|
* Loads the data array into the texture in the case only a single block is
|
|
* is defined. Does not load when the input data is divided in multiple blocks
|
|
* (in which case they will be loaded into GPU memory by GetNextBlock()).
|
|
* Requires an active OpenGL context.
|
|
*/
|
|
bool LoadVolume(vtkRenderer* ren, vtkImageData* data, vtkDataArray* scalars, int const isCell,
|
|
int const interpolation);
|
|
|
|
/**
|
|
* It currently only calls SetInterpolation internally. Requires an active OpenGL
|
|
* context.
|
|
*/
|
|
void UpdateVolume(vtkVolumeProperty* property);
|
|
|
|
/**
|
|
* If streaming the data array as separate blocks, sort them back to front.
|
|
* This method does nothing if there is a single block.
|
|
*/
|
|
void SortBlocksBackToFront(vtkRenderer* ren, vtkMatrix4x4* volumeMat);
|
|
|
|
/**
|
|
* Return the next volume block to be rendered and load its data. If the
|
|
* current block is the last one, it will return nullptr.
|
|
*/
|
|
VolumeBlock* GetNextBlock();
|
|
/**
|
|
* Return the currently loaded block.
|
|
*/
|
|
VolumeBlock* GetCurrentBlock();
|
|
|
|
/**
|
|
* Clean-up acquired graphics resources.
|
|
*/
|
|
void ReleaseGraphicsResources(vtkWindow* win);
|
|
|
|
/**
|
|
* Get the scale and bias values given a VTK scalar type and a finite range.
|
|
* The scale and bias values computed using this method can be useful for
|
|
* custom shader code. For example, when looking up color values through the
|
|
* transfer function texture, the scalar value must be scaled and offset.
|
|
*/
|
|
static void GetScaleAndBias(const int scalarType, float* scalarRange, float& scale, float& bias);
|
|
vtkDataArray* GetLoadedScalars();
|
|
|
|
bool HandleLargeDataTypes;
|
|
float Scale[4];
|
|
float Bias[4];
|
|
float ScalarRange[4][2];
|
|
float CellSpacing[3];
|
|
int InterpolationType;
|
|
vtkTimeStamp UploadTime;
|
|
|
|
int IsCellData = 0;
|
|
vtkNew<vtkMatrix4x4> CellToPointMatrix;
|
|
float AdjustedTexMin[4];
|
|
float AdjustedTexMax[4];
|
|
|
|
protected:
|
|
vtkVolumeTexture();
|
|
~vtkVolumeTexture() override;
|
|
|
|
private:
|
|
vtkVolumeTexture(const vtkVolumeTexture&) = delete;
|
|
void operator=(const vtkVolumeTexture&) = delete;
|
|
|
|
/**
|
|
* Load an image block as defined in volBlock into GPU memory.
|
|
* Requires an active OpenGL context.
|
|
*/
|
|
bool LoadTexture(int const interpolation, VolumeBlock* volBlock);
|
|
|
|
/**
|
|
* Divide the image data in NxMxO user-defined blocks.
|
|
*/
|
|
void SplitVolume(vtkImageData* imageData, Size3 const& part);
|
|
|
|
void CreateBlocks(unsigned int const format, unsigned int const internalFormat, int const type);
|
|
|
|
void AdjustExtentForCell(Size6& extent);
|
|
Size3 ComputeBlockSize(int* extent);
|
|
|
|
/**
|
|
* Defines OpenGL's texture type, format and internal format based on the
|
|
* vtkDataArray type (scalarType) and the number of array components.
|
|
*/
|
|
void SelectTextureFormat(unsigned int& format, unsigned int& internalFormat, int& type,
|
|
int const scalarType, int const noOfComponents);
|
|
|
|
/**
|
|
* Clean-up any acquired host side resources (image blocks, etc.).
|
|
*/
|
|
void ClearBlocks();
|
|
|
|
/**
|
|
* Computes loaded bounds in data-coordinates.
|
|
*/
|
|
// can be combined into one call
|
|
void ComputeBounds(VolumeBlock* block);
|
|
void UpdateTextureToDataMatrix(VolumeBlock* block);
|
|
|
|
/**
|
|
* Compute transformation from cell texture-coordinates to point texture-coords
|
|
* (CTP). Cell data maps correctly to OpenGL cells, point data does not (VTK
|
|
* defines points at the cell corners). To set the point data in the center of the
|
|
* OpenGL texels, a translation of 0.5 texels is applied, and the range is rescaled
|
|
* to the point range.
|
|
*
|
|
* delta = TextureExtentsMax - TextureExtentsMin;
|
|
* min = vec3(0.5) / delta;
|
|
* max = (delta - vec3(0.5)) / delta;
|
|
* range = max - min
|
|
*
|
|
* CTP = translation * Scale
|
|
* CTP = range.x, 0, 0, min.x
|
|
* 0, range.y, 0, min.y
|
|
* 0, 0, range.z, min.z
|
|
* 0, 0, 0, 1.0
|
|
*/
|
|
void ComputeCellToPointMatrix(int extents[6]);
|
|
|
|
//@{
|
|
/**
|
|
* @brief Helper functions to catch potential issues when doing GPU
|
|
* texture allocations.
|
|
*
|
|
* They make use of the available OpenGL mechanisms to try to detect whether
|
|
* a volume would not fit in the GPU (due to MAX_TEXTURE_SIZE limitations,
|
|
* memory availability, etc.).
|
|
*/
|
|
bool AreDimensionsValid(
|
|
vtkTextureObject* texture, int const width, int const height, int const depth);
|
|
|
|
bool SafeLoadTexture(vtkTextureObject* texture, int const width, int const height,
|
|
int const depth, int numComps, int dataType, void* dataPtr);
|
|
//@}
|
|
|
|
void UpdateInterpolationType(int const interpolation);
|
|
void SetInterpolation(int const interpolation);
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkTimeStamp UpdateTime;
|
|
|
|
vtkSmartPointer<vtkTextureObject> Texture;
|
|
std::vector<vtkImageData*> ImageDataBlocks;
|
|
std::map<vtkImageData*, VolumeBlock*> ImageDataBlockMap;
|
|
std::vector<VolumeBlock*> SortedVolumeBlocks;
|
|
size_t CurrentBlockIdx;
|
|
bool StreamBlocks;
|
|
|
|
std::vector<Size3> TextureSizes;
|
|
Size6 FullExtent;
|
|
Size3 FullSize;
|
|
Size3 Partitions;
|
|
|
|
vtkDataArray* Scalars;
|
|
};
|
|
|
|
#endif // vtkVolumeTexture_h
|