1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkOpenGLGPUVolumeRayCastMapper.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 /** 16 * @class vtkOpenGLGPUVolumeRayCastMapper 17 * @brief OpenGL implementation of volume rendering through ray-casting. 18 * 19 * @section multi Multiple Inputs 20 21 * When multiple inputs are rendered simultaneously, it is possible to 22 * composite overlapping areas correctly. Inputs are connected directly to 23 * the mapper and their parameters (transfer functions, transformations, etc.) 24 * are specified through standard vtkVolume instances. These vtkVolume 25 * instances are to be registered in a special vtkProp3D, vtkMultiVolume. 26 * 27 * Structures related to a particular active input are stored in a helper 28 * class (vtkVolumeInputHelper) and helper structures are kept in a 29 * port-referenced map (VolumeInputMap). The order of the inputs in the 30 * map is important as it defines the order in which parameters are 31 * bound to uniform variables (transformation matrices, bias, scale and every 32 * other required rendering parameter). 33 * 34 * A separate code path is used when rendering multiple-inputs in order to 35 * facilitate the co-existance of these two modes (single/multiple), due to 36 * current feature incompatibilities with multiple inputs (e.g. texture-streaming, 37 * cropping, etc.). 38 * 39 * @note A limited set of the mapper features are currently supported for 40 * multiple inputs: 41 * 42 * - Blending 43 * - Composite (front-to-back) 44 * 45 * - Transfer functions (defined separately for per input) 46 * - 1D color 47 * - 1D scalar opacity 48 * - 1D gradient magnitude opacity 49 * - 2D scalar-gradient magnitude 50 * 51 * - Point and cell data 52 * - With the limitation that all of the inputs are assumed to share the same 53 * name/id. 54 * 55 * @sa vtkGPUVolumeRayCastMapper vtkVolumeInputHelper vtkVolumeTexture 56 * vtkMultiVolume 57 * 58 */ 59 60 #ifndef vtkOpenGLGPUVolumeRayCastMapper_h 61 #define vtkOpenGLGPUVolumeRayCastMapper_h 62 #include <map> // For methods 63 64 #include "vtkNew.h" // For vtkNew 65 #include "vtkRenderingVolumeOpenGL2Module.h" // For export macro 66 #include "vtkGPUVolumeRayCastMapper.h" 67 #include "vtkShader.h" // For methods 68 #include "vtkSmartPointer.h" // For smartptr 69 70 71 class vtkGenericOpenGLResourceFreeCallback; 72 class vtkImplicitFunction; 73 class vtkOpenGLCamera; 74 class vtkOpenGLTransferFunctions2D; 75 class vtkOpenGLVolumeGradientOpacityTables; 76 class vtkOpenGLVolumeOpacityTables; 77 class vtkOpenGLVolumeRGBTables; 78 class vtkShaderProgram; 79 class vtkTextureObject; 80 class vtkVolume; 81 class vtkVolumeInputHelper; 82 class vtkVolumeTexture; 83 class vtkOpenGLUniforms; 84 85 class VTKRENDERINGVOLUMEOPENGL2_EXPORT vtkOpenGLGPUVolumeRayCastMapper : 86 public vtkGPUVolumeRayCastMapper 87 { 88 public: 89 static vtkOpenGLGPUVolumeRayCastMapper* New(); 90 91 enum Passes 92 { 93 RenderPass, 94 DepthPass = 1 95 }; 96 97 vtkTypeMacro(vtkOpenGLGPUVolumeRayCastMapper, vtkGPUVolumeRayCastMapper); 98 void PrintSelf( ostream& os, vtkIndent indent ) override; 99 100 // Description: 101 // Low level API to enable access to depth texture in 102 // RenderToTexture mode. It will return either nullptr if 103 // RenderToImage was never turned on or texture captured 104 // the last time RenderToImage was on. 105 vtkTextureObject* GetDepthTexture(); 106 107 // Description: 108 // Low level API to enable access to color texture in 109 // RenderToTexture mode. It will return either nullptr if 110 // RenderToImage was never turned on or texture captured 111 // the last time RenderToImage was on. 112 vtkTextureObject* GetColorTexture(); 113 114 // Description: 115 // Low level API to export the depth texture as vtkImageData in 116 // RenderToImage mode. 117 void GetDepthImage(vtkImageData* im) override; 118 119 // Description: 120 // Low level API to export the color texture as vtkImageData in 121 // RenderToImage mode. 122 void GetColorImage(vtkImageData* im) override; 123 124 // Description: 125 // Mapper can have multiple passes and internally it will set 126 // the state. The state can not be set externally explicitly 127 // but can be set indirectly depending on the options set by 128 // the user. 129 vtkGetMacro(CurrentPass, int); 130 131 // Sets a depth texture for this mapper to use 132 // This allows many mappers to use the same 133 // texture reducing GPU usage. If this is set 134 // the standard depth texture code is skipped 135 // The depth texture should be activated 136 // and deactivated outside of this class 137 void SetSharedDepthTexture(vtkTextureObject *nt); 138 139 /** 140 * Set a fixed number of partitions in which to split the volume 141 * during rendring. This will force by-block rendering without 142 * trying to compute an optimum number of partitions. 143 */ 144 void SetPartitions(unsigned short x, unsigned short y, unsigned short z); 145 146 /** 147 * Load the volume texture into GPU memory. Actual loading occurs 148 * in vtkVolumeTexture::LoadVolume. The mapper by default loads data 149 * lazily (at render time), so it is most commonly not necessary to call 150 * this function. This method is only exposed in order to support on-site 151 * loading which is useful in cases where the user needs to know a-priori 152 * whether loading will succeed or not. 153 */ 154 bool PreLoadData(vtkRenderer* ren, vtkVolume* vol); 155 156 //@{ 157 /** 158 * This function enables you to apply your own substitutions 159 * to the shader creation process. The shader code in this class 160 * is created by applying a bunch of string replacements to a 161 * shader template. Using this function you can apply your 162 * own string replacements to add features you desire. 163 */ 164 void AddShaderReplacement( 165 vtkShader::Type shaderType, // vertex, fragment, etc 166 const std::string& originalValue, 167 bool replaceFirst, // do this replacement before the default 168 const std::string& replacementValue, 169 bool replaceAll); 170 void ClearShaderReplacement( 171 vtkShader::Type shaderType, // vertex, fragment, etc 172 const std::string& originalValue, 173 bool replaceFirst); 174 void ClearAllShaderReplacements(vtkShader::Type shaderType); 175 void ClearAllShaderReplacements(); 176 //@} 177 178 //@{ 179 /** 180 * Allow the program to set the shader codes used directly 181 * instead of using the built in templates. Be aware, if 182 * set, this template will be used for all cases, 183 * primitive types, picking etc. 184 */ 185 vtkSetStringMacro(VertexShaderCode); 186 vtkGetStringMacro(VertexShaderCode); 187 vtkSetStringMacro(FragmentShaderCode); 188 vtkGetStringMacro(FragmentShaderCode); 189 //@} 190 191 //@{ 192 /** 193 * The Uniforms object allows to set custom uniform variables 194 * that are used in replacement shader code. 195 */ 196 vtkGetObjectMacro(FragmentCustomUniforms,vtkOpenGLUniforms); 197 vtkGetObjectMacro(VertexCustomUniforms,vtkOpenGLUniforms); 198 //@} 199 200 // Description: 201 // Delete OpenGL objects. 202 // \post done: this->OpenGLObjectsCreated==0 203 void ReleaseGraphicsResources(vtkWindow *window) override; 204 205 protected: 206 vtkOpenGLGPUVolumeRayCastMapper(); 207 ~vtkOpenGLGPUVolumeRayCastMapper() override; 208 209 vtkGenericOpenGLResourceFreeCallback *ResourceCallback; 210 211 // Description: 212 // Build vertex and fragment shader for the volume rendering 213 void BuildDepthPassShader(vtkRenderer* ren, vtkVolume* vol, 214 int noOfComponents, 215 int independentComponents); 216 217 // Description: 218 // Build vertex and fragment shader for the volume rendering 219 void BuildShader(vtkRenderer* ren); 220 221 // TODO Take these out as these are no longer needed 222 // Methods called by the AMR Volume Mapper. PreRender(vtkRenderer * vtkNotUsed (ren),vtkVolume * vtkNotUsed (vol),double vtkNotUsed (datasetBounds)[6],double vtkNotUsed (scalarRange)[2],int vtkNotUsed (noOfComponents),unsigned int vtkNotUsed (numberOfLevels))223 void PreRender(vtkRenderer * vtkNotUsed(ren), 224 vtkVolume *vtkNotUsed(vol), 225 double vtkNotUsed(datasetBounds)[6], 226 double vtkNotUsed(scalarRange)[2], 227 int vtkNotUsed(noOfComponents), 228 unsigned int vtkNotUsed(numberOfLevels)) override {}; 229 230 // \pre input is up-to-date RenderBlock(vtkRenderer * vtkNotUsed (ren),vtkVolume * vtkNotUsed (vol),unsigned int vtkNotUsed (level))231 void RenderBlock(vtkRenderer *vtkNotUsed(ren), 232 vtkVolume *vtkNotUsed(vol), 233 unsigned int vtkNotUsed(level)) override {} 234 PostRender(vtkRenderer * vtkNotUsed (ren),int vtkNotUsed (noOfComponents))235 void PostRender(vtkRenderer *vtkNotUsed(ren), 236 int vtkNotUsed(noOfComponents)) override {} 237 238 // Description: 239 // Rendering volume on GPU 240 void GPURender(vtkRenderer *ren, vtkVolume *vol) override; 241 242 // Description: 243 // Method that performs the actual rendering given a volume and a shader 244 void DoGPURender(vtkRenderer* ren, 245 vtkOpenGLCamera* cam, 246 vtkShaderProgram* shaderProgram); 247 248 // Description: 249 // Update the reduction factor of the render viewport (this->ReductionFactor) 250 // according to the time spent in seconds to render the previous frame 251 // (this->TimeToDraw) and a time in seconds allocated to render the next 252 // frame (allocatedTime). 253 // \pre valid_current_reduction_range: this->ReductionFactor>0.0 && this->ReductionFactor<=1.0 254 // \pre positive_TimeToDraw: this->TimeToDraw>=0.0 255 // \pre positive_time: allocatedTime>0 256 // \post valid_new_reduction_range: this->ReductionFactor>0.0 && this->ReductionFactor<=1.0 257 void ComputeReductionFactor(double allocatedTime); 258 259 // Description: 260 // Empty implementation. GetReductionRatio(double * ratio)261 void GetReductionRatio(double* ratio) override 262 { 263 ratio[0] = ratio[1] = ratio[2] = 1.0; 264 } 265 266 267 // Description: 268 // Empty implementation. IsRenderSupported(vtkRenderWindow * vtkNotUsed (window),vtkVolumeProperty * vtkNotUsed (property))269 int IsRenderSupported(vtkRenderWindow *vtkNotUsed(window), 270 vtkVolumeProperty *vtkNotUsed(property)) override 271 { 272 return 1; 273 } 274 275 //@{ 276 /** 277 * \brief vtkOpenGLRenderPass API 278 */ 279 vtkMTimeType GetRenderPassStageMTime(vtkVolume* vol); 280 281 /** 282 * Create the basic shader template strings before substitutions 283 */ 284 void GetShaderTemplate(std::map<vtkShader::Type, vtkShader*>& shaders); 285 286 /** 287 * Perform string replacements on the shader templates 288 */ 289 void ReplaceShaderValues(std::map<vtkShader::Type, vtkShader*>& shaders, 290 vtkRenderer* ren, vtkVolume* vol, int numComps); 291 292 /** 293 * RenderPass string replacements on shader templates called from 294 * ReplaceShaderValues. 295 */ 296 void ReplaceShaderCustomUniforms( 297 std::map<vtkShader::Type, vtkShader*>& shaders ); 298 void ReplaceShaderBase(std::map<vtkShader::Type, vtkShader*>& shaders, 299 vtkRenderer* ren, vtkVolume* vol, int numComps); 300 void ReplaceShaderTermination(std::map<vtkShader::Type, vtkShader*>& shaders, 301 vtkRenderer* ren, vtkVolume* vol, int numComps); 302 void ReplaceShaderShading(std::map<vtkShader::Type, vtkShader*>& shaders, 303 vtkRenderer* ren, vtkVolume* vol, int numComps); 304 void ReplaceShaderCompute(std::map<vtkShader::Type, vtkShader*>& shaders, 305 vtkRenderer* ren, vtkVolume* vol, int numComps); 306 void ReplaceShaderCropping(std::map<vtkShader::Type, vtkShader*>& shaders, 307 vtkRenderer* ren, vtkVolume* vol, int numComps); 308 void ReplaceShaderClipping(std::map<vtkShader::Type, vtkShader*>& shaders, 309 vtkRenderer* ren, vtkVolume* vol, int numComps); 310 void ReplaceShaderMasking(std::map<vtkShader::Type, vtkShader*>& shaders, 311 vtkRenderer* ren, vtkVolume* vol, int numComps); 312 void ReplaceShaderPicking(std::map<vtkShader::Type, vtkShader*>& shaders, 313 vtkRenderer* ren, vtkVolume* vol, int numComps); 314 void ReplaceShaderRTT(std::map<vtkShader::Type, vtkShader*>& shaders, 315 vtkRenderer* ren, vtkVolume* vol, int numComps); 316 void ReplaceShaderRenderPass(std::map<vtkShader::Type, vtkShader*>& shaders, 317 vtkVolume* vol, bool prePass); 318 319 /** 320 * Update parameters from RenderPass 321 */ 322 void SetShaderParametersRenderPass(); 323 324 /** 325 * Caches the vtkOpenGLRenderPass::RenderPasses() information. 326 * Note: Do not dereference the pointers held by this object. There is no 327 * guarantee that they are still valid! 328 */ 329 vtkNew<vtkInformation> LastRenderPassInfo; 330 //@} 331 332 double ReductionFactor; 333 int CurrentPass; 334 char *VertexShaderCode; 335 char *FragmentShaderCode; 336 std::map<const vtkShader::ReplacementSpec, vtkShader::ReplacementValue> 337 UserShaderReplacements; 338 339 vtkNew<vtkOpenGLUniforms> FragmentCustomUniforms; 340 vtkNew<vtkOpenGLUniforms> VertexCustomUniforms; 341 342 public: 343 using VolumeInput = vtkVolumeInputHelper; 344 using VolumeInputMap = std::map<int, vtkVolumeInputHelper>; 345 VolumeInputMap AssembledInputs; 346 347 private: 348 class vtkInternal; 349 vtkInternal* Impl; 350 351 friend class vtkVolumeTexture; 352 353 vtkOpenGLGPUVolumeRayCastMapper( 354 const vtkOpenGLGPUVolumeRayCastMapper&) = delete; 355 void operator=(const vtkOpenGLGPUVolumeRayCastMapper&) = delete; 356 }; 357 358 #endif // vtkOpenGLGPUVolumeRayCastMapper_h 359