/*========================================================================= Program: Visualization Toolkit 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 "vtkOpenGLPointGaussianMapper.h" #include "vtkOpenGLHelper.h" #include "vtkCellArray.h" #include "vtkFloatArray.h" #include "vtkHardwareSelector.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkMatrix4x4.h" #include "vtkOpenGLActor.h" #include "vtkOpenGLCamera.h" #include "vtkOpenGLIndexBufferObject.h" #include "vtkOpenGLPolyDataMapper.h" #include "vtkOpenGLVertexArrayObject.h" #include "vtkOpenGLVertexBufferObject.h" #include "vtkOpenGLVertexBufferObjectGroup.h" #include "vtkPiecewiseFunction.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkProperty.h" #include "vtkRenderer.h" #include "vtkShaderProgram.h" #include "vtkPointGaussianVS.h" #include "vtkPolyDataFS.h" #include "vtk_glew.h" class vtkOpenGLPointGaussianMapperHelper : public vtkOpenGLPolyDataMapper { public: static vtkOpenGLPointGaussianMapperHelper* New(); vtkTypeMacro(vtkOpenGLPointGaussianMapperHelper, vtkOpenGLPolyDataMapper) vtkPointGaussianMapper *Owner; bool UsingPoints; float *OpacityTable; // the table double OpacityScale; // used for quick lookups double OpacityOffset; // used for quick lookups float *ScaleTable; // the table double ScaleScale; // used for quick lookups double ScaleOffset; // used for quick lookups double TriangleScale; protected: vtkOpenGLPointGaussianMapperHelper(); ~vtkOpenGLPointGaussianMapperHelper() override; // Description: // Create the basic shaders before replacement void GetShaderTemplate( std::map shaders, vtkRenderer *, vtkActor *) override; // Description: // Perform string replacments on the shader templates void ReplaceShaderColor( std::map shaders, vtkRenderer *, vtkActor *) override; void ReplaceShaderPositionVC( std::map shaders, vtkRenderer *, vtkActor *) override; // Description: // Set the shader parameters related to the Camera void SetCameraShaderParameters(vtkOpenGLHelper &cellBO, vtkRenderer *ren, vtkActor *act) override; // Description: // Set the shader parameters related to the actor/mapper void SetMapperShaderParameters(vtkOpenGLHelper &cellBO, vtkRenderer *ren, vtkActor *act) override; // Description: // Does the VBO/IBO need to be rebuilt bool GetNeedToRebuildBufferObjects(vtkRenderer *ren, vtkActor *act) override; // Description: // Update the VBO to contain point based values void BuildBufferObjects(vtkRenderer *ren, vtkActor *act) override; void RenderPieceDraw(vtkRenderer *ren, vtkActor *act) override; // create the table for opacity values void BuildOpacityTable(); // create the table for scale values void BuildScaleTable(); // Description: // Does the shader source need to be recomputed bool GetNeedToRebuildShaders(vtkOpenGLHelper &cellBO, vtkRenderer *ren, vtkActor *act) override; private: vtkOpenGLPointGaussianMapperHelper(const vtkOpenGLPointGaussianMapperHelper&) = delete; void operator=(const vtkOpenGLPointGaussianMapperHelper&) = delete; }; //----------------------------------------------------------------------------- vtkStandardNewMacro(vtkOpenGLPointGaussianMapperHelper) //----------------------------------------------------------------------------- vtkOpenGLPointGaussianMapperHelper::vtkOpenGLPointGaussianMapperHelper() { this->Owner = nullptr; this->OpacityTable = nullptr; this->ScaleTable = nullptr; this->UsingPoints = false; this->OpacityScale = 1.0; this->ScaleScale = 1.0; this->OpacityOffset = 0.0; this->ScaleOffset = 0.0; this->TriangleScale = 0.0; } //----------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapperHelper::GetShaderTemplate( std::map shaders, vtkRenderer *ren, vtkActor *actor) { this->Superclass::GetShaderTemplate(shaders,ren,actor); if (this->Owner->GetScaleFactor() == 0.0) { this->UsingPoints = true; } else { this->UsingPoints = false; // for splats use a special shader than handles the offsets shaders[vtkShader::Vertex]->SetSource(vtkPointGaussianVS); } } void vtkOpenGLPointGaussianMapperHelper::ReplaceShaderPositionVC( std::map shaders, vtkRenderer *ren, vtkActor *actor) { if (!this->UsingPoints) { std::string VSSource = shaders[vtkShader::Vertex]->GetSource(); std::string FSSource = shaders[vtkShader::Fragment]->GetSource(); vtkShaderProgram::Substitute(FSSource, "//VTK::PositionVC::Dec", "varying vec2 offsetVCVSOutput;"); vtkShaderProgram::Substitute(VSSource, "//VTK::Camera::Dec", "uniform mat4 VCDCMatrix;\n" "uniform mat4 MCVCMatrix;"); shaders[vtkShader::Vertex]->SetSource(VSSource); shaders[vtkShader::Fragment]->SetSource(FSSource); } this->Superclass::ReplaceShaderPositionVC(shaders,ren,actor); } void vtkOpenGLPointGaussianMapperHelper::ReplaceShaderColor( std::map shaders, vtkRenderer *ren, vtkActor *actor) { if (!this->UsingPoints) { std::string FSSource = shaders[vtkShader::Fragment]->GetSource(); if (this->Owner->GetSplatShaderCode() && strcmp(this->Owner->GetSplatShaderCode(), "") != 0) { vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", this->Owner->GetSplatShaderCode(), false); } else { vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl", // compute the eye position and unit direction "//VTK::Color::Impl\n" " float dist2 = dot(offsetVCVSOutput.xy,offsetVCVSOutput.xy);\n" " float gaussian = exp(-0.5*dist2);\n" " opacity = opacity*gaussian;" // " opacity = opacity*0.5;" , false); } shaders[vtkShader::Fragment]->SetSource(FSSource); } this->Superclass::ReplaceShaderColor(shaders,ren,actor); //cerr << shaders[vtkShader::Fragment]->GetSource() << endl; } //----------------------------------------------------------------------------- bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildShaders( vtkOpenGLHelper &cellBO, vtkRenderer* ren, vtkActor *actor) { this->LastLightComplexity[&cellBO] = 0; vtkHardwareSelector* selector = ren->GetSelector(); int picking = selector ? selector->GetCurrentPass() : -1; if (this->LastSelectionState != picking) { this->SelectionStateChanged.Modified(); this->LastSelectionState = picking; } vtkMTimeType renderPassMTime = this->GetRenderPassStageMTime(actor); // has something changed that would require us to recreate the shader? // candidates are // property modified (representation interpolation and lighting) // input modified // light complexity changed if (cellBO.Program == nullptr || cellBO.ShaderSourceTime < this->GetMTime() || cellBO.ShaderSourceTime < actor->GetMTime() || cellBO.ShaderSourceTime < this->CurrentInput->GetMTime() || cellBO.ShaderSourceTime < this->SelectionStateChanged || cellBO.ShaderSourceTime < renderPassMTime) { return true; } return false; } //----------------------------------------------------------------------------- vtkOpenGLPointGaussianMapperHelper::~vtkOpenGLPointGaussianMapperHelper() { if (this->OpacityTable) { delete [] this->OpacityTable; this->OpacityTable = nullptr; } if (this->ScaleTable) { delete [] this->ScaleTable; this->ScaleTable = nullptr; } } //----------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapperHelper::SetCameraShaderParameters(vtkOpenGLHelper &cellBO, vtkRenderer* ren, vtkActor *actor) { if (this->UsingPoints) { this->Superclass::SetCameraShaderParameters(cellBO,ren,actor); } else { vtkShaderProgram *program = cellBO.Program; vtkOpenGLCamera *cam = (vtkOpenGLCamera *)(ren->GetActiveCamera()); vtkMatrix4x4 *wcdc; vtkMatrix4x4 *wcvc; vtkMatrix3x3 *norms; vtkMatrix4x4 *vcdc; cam->GetKeyMatrices(ren,wcvc,norms,vcdc,wcdc); program->SetUniformMatrix("VCDCMatrix", vcdc); if (!actor->GetIsIdentity()) { vtkMatrix4x4 *mcwc; vtkMatrix3x3 *anorms; ((vtkOpenGLActor *)actor)->GetKeyMatrices(mcwc,anorms); vtkMatrix4x4::Multiply4x4(mcwc, wcvc, this->TempMatrix4); program->SetUniformMatrix("MCVCMatrix", this->TempMatrix4); } else { program->SetUniformMatrix("MCVCMatrix", wcvc); } // add in uniforms for parallel and distance cellBO.Program->SetUniformi("cameraParallel", cam->GetParallelProjection()); } } //----------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapperHelper::SetMapperShaderParameters( vtkOpenGLHelper &cellBO, vtkRenderer *ren, vtkActor *actor) { if (!this->UsingPoints) { cellBO.Program->SetUniformf("triangleScale",this->TriangleScale); } this->Superclass::SetMapperShaderParameters(cellBO,ren,actor); } namespace { template< typename PointDataType > PointDataType vtkOpenGLPointGaussianMapperHelperGetComponent( PointDataType* tuple, int nComponent, int component ) { // If this is a single component array, make sure we do not compute // a useless magnitude if (nComponent == 1) { component = 0; } // If we request a non-existing componeent, return the magnitude of the tuple PointDataType compVal = 0.0; if (component < 0 || component >= nComponent) { for (int iComp = 0; iComp < nComponent; iComp++) { PointDataType tmp = tuple[iComp]; compVal += tmp * tmp; } compVal = sqrt(compVal); } else { compVal = tuple[component]; } return compVal; } void vtkOpenGLPointGaussianMapperHelperComputeColor( unsigned char* rcolor, unsigned char *colors, int colorComponents, vtkIdType index, vtkDataArray *opacities, int opacitiesComponent, vtkOpenGLPointGaussianMapperHelper *self ) { unsigned char white[4] = {255, 255, 255, 255}; // if there are no per point sizes and the default size is zero // then just render points, saving memory and speed unsigned char *colorPtr = colors ? (colors + index*colorComponents) : white; rcolor[0] = *(colorPtr++); rcolor[1] = *(colorPtr++); rcolor[2] = *(colorPtr++); if (opacities) { double opacity = vtkOpenGLPointGaussianMapperHelperGetComponent( opacities->GetTuple(index), opacities->GetNumberOfComponents(), opacitiesComponent); if (self->OpacityTable) { double tindex = (opacity - self->OpacityOffset)*self->OpacityScale; int itindex = static_cast(tindex); if (itindex >= self->Owner->GetOpacityTableSize() - 1) { opacity = self->OpacityTable[self->Owner->GetOpacityTableSize() - 1]; } else if (itindex < 0) { opacity = self->OpacityTable[0]; } else { opacity = (1.0 - tindex + itindex)*self->OpacityTable[itindex] + (tindex - itindex)*self->OpacityTable[itindex+1]; } } rcolor[3] = static_cast(opacity*255.0); } else { rcolor[3] = (colorComponents == 4 ? *colorPtr : 255); } } void vtkOpenGLPointGaussianMapperHelperColors( vtkUnsignedCharArray *outColors, vtkIdType numPts, unsigned char *colors, int colorComponents, vtkDataArray *opacities, int opacitiesComponent, vtkOpenGLPointGaussianMapperHelper *self, vtkCellArray *verts) { unsigned char *vPtr = static_cast( outColors->GetVoidPointer(0)); // iterate over cells or not if (verts->GetNumberOfCells()) { vtkIdType* indices(nullptr); vtkIdType npts(0); for (verts->InitTraversal(); verts->GetNextCell(npts, indices); ) { for (int i = 0; i < npts; ++i) { vtkOpenGLPointGaussianMapperHelperComputeColor( vPtr, colors, colorComponents, indices[i], opacities, opacitiesComponent, self); if (!self->UsingPoints) { memcpy(vPtr + 4, vPtr, 4); memcpy(vPtr + 8, vPtr, 4); vPtr += 8; } vPtr += 4; } } } else { for (vtkIdType i = 0; i < numPts; i++) { vtkOpenGLPointGaussianMapperHelperComputeColor( vPtr, colors, colorComponents, i, opacities, opacitiesComponent, self); if (!self->UsingPoints) { memcpy(vPtr + 4, vPtr, 4); memcpy(vPtr + 8, vPtr, 4); vPtr += 8; } vPtr += 4; } } } float vtkOpenGLPointGaussianMapperHelperGetRadius( double radius, vtkOpenGLPointGaussianMapperHelper *self ) { if (self->ScaleTable) { double tindex = (radius - self->ScaleOffset)*self->ScaleScale; int itindex = static_cast(tindex); if (itindex >= self->Owner->GetScaleTableSize() - 1) { radius = self->ScaleTable[self->Owner->GetScaleTableSize() - 1]; } else if (itindex < 0) { radius = self->ScaleTable[0]; } else { radius = (1.0 - tindex + itindex)*self->ScaleTable[itindex] + (tindex - itindex)*self->ScaleTable[itindex+1]; } } radius *= self->Owner->GetScaleFactor(); radius *= self->TriangleScale; return static_cast(radius); } template< typename PointDataType > void vtkOpenGLPointGaussianMapperHelperSizes( vtkFloatArray *scales, PointDataType* sizes, int nComponent, int component, vtkIdType numPts, vtkOpenGLPointGaussianMapperHelper *self, vtkCellArray *verts) { float *it = static_cast(scales->GetVoidPointer(0)); float cos30 = cos(vtkMath::RadiansFromDegrees(30.0)); // iterate over cells or not if (verts->GetNumberOfCells()) { vtkIdType* indices(nullptr); vtkIdType npts(0); for (verts->InitTraversal(); verts->GetNextCell(npts, indices); ) { for (vtkIdType i = 0; i < npts; ++i) { PointDataType size = 1.0; if (sizes) { size = vtkOpenGLPointGaussianMapperHelperGetComponent( &sizes[indices[i] * nComponent], nComponent, component); } float radiusFloat = vtkOpenGLPointGaussianMapperHelperGetRadius(size, self); *(it++) = -2.0f*radiusFloat*cos30; *(it++) = -radiusFloat; *(it++) = 2.0f*radiusFloat*cos30; *(it++) = -radiusFloat; *(it++) = 0.0f; *(it++) = 2.0f*radiusFloat; } } } else { for (vtkIdType i = 0; i < numPts; i++) { PointDataType size = 1.0; if (sizes) { size = vtkOpenGLPointGaussianMapperHelperGetComponent( &sizes[i * nComponent], nComponent, component); } float radiusFloat = vtkOpenGLPointGaussianMapperHelperGetRadius(size, self); *(it++) = -2.0f*radiusFloat*cos30; *(it++) = -radiusFloat; *(it++) = 2.0f*radiusFloat*cos30; *(it++) = -radiusFloat; *(it++) = 0.0f; *(it++) = 2.0f*radiusFloat; } } } template< typename PointDataType > void vtkOpenGLPointGaussianMapperHelperPoints( vtkFloatArray *vcoords, PointDataType* points, vtkIdType numPts, vtkOpenGLPointGaussianMapperHelper *self, vtkCellArray *verts) { float *vPtr = static_cast(vcoords->GetVoidPointer(0)); PointDataType *pointPtr; // iterate over cells or not if (verts->GetNumberOfCells()) { vtkIdType* indices(nullptr); vtkIdType npts(0); for (verts->InitTraversal(); verts->GetNextCell(npts, indices); ) { for (int i = 0; i < npts; ++i) { pointPtr = points + indices[i]*3; // Vertices *(vPtr++) = pointPtr[0]; *(vPtr++) = pointPtr[1]; *(vPtr++) = pointPtr[2]; if (!self->UsingPoints) { *(vPtr++) = pointPtr[0]; *(vPtr++) = pointPtr[1]; *(vPtr++) = pointPtr[2]; *(vPtr++) = pointPtr[0]; *(vPtr++) = pointPtr[1]; *(vPtr++) = pointPtr[2]; } } } } else { for (vtkIdType i = 0; i < numPts; i++) { pointPtr = points + i*3; // Vertices *(vPtr++) = pointPtr[0]; *(vPtr++) = pointPtr[1]; *(vPtr++) = pointPtr[2]; if (!self->UsingPoints) { *(vPtr++) = pointPtr[0]; *(vPtr++) = pointPtr[1]; *(vPtr++) = pointPtr[2]; *(vPtr++) = pointPtr[0]; *(vPtr++) = pointPtr[1]; *(vPtr++) = pointPtr[2]; } } } } } // anonymous namespace //------------------------------------------------------------------------- bool vtkOpenGLPointGaussianMapperHelper::GetNeedToRebuildBufferObjects( vtkRenderer *vtkNotUsed(ren), vtkActor *act) { // picking state does not require a rebuild, unlike our parent if (this->VBOBuildTime < this->GetMTime() || this->VBOBuildTime < act->GetMTime() || this->VBOBuildTime < this->CurrentInput->GetMTime() || this->VBOBuildTime < this->Owner->GetMTime() || (this->Owner->GetScalarOpacityFunction() && this->VBOBuildTime < this->Owner->GetScalarOpacityFunction()->GetMTime()) || (this->Owner->GetScaleFunction() && this->VBOBuildTime < this->Owner->GetScaleFunction()->GetMTime()) ) { return true; } return false; } //------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapperHelper::BuildOpacityTable() { double range[2]; // if a piecewise function was provided, use it to map the opacities vtkPiecewiseFunction *pwf = this->Owner->GetScalarOpacityFunction(); int tableSize = this->Owner->GetOpacityTableSize(); delete [] this->OpacityTable; this->OpacityTable = new float [tableSize+1]; if (pwf) { // build the interpolation table pwf->GetRange(range); pwf->GetTable(range[0],range[1],tableSize,this->OpacityTable); // duplicate the last value for bilinear interp edge case this->OpacityTable[tableSize] = this->OpacityTable[tableSize-1]; this->OpacityScale = (tableSize - 1.0)/(range[1] - range[0]); this->OpacityOffset = range[0]; } } //------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapperHelper::BuildScaleTable() { double range[2]; // if a piecewise function was provided, use it to map the opacities vtkPiecewiseFunction *pwf = this->Owner->GetScaleFunction(); int tableSize = this->Owner->GetScaleTableSize(); delete [] this->ScaleTable; this->ScaleTable = new float [tableSize+1]; if (pwf) { // build the interpolation table pwf->GetRange(range); pwf->GetTable(range[0],range[1],tableSize,this->ScaleTable); // duplicate the last value for bilinear interp edge case this->ScaleTable[tableSize] = this->ScaleTable[tableSize-1]; this->ScaleScale = (tableSize - 1.0)/(range[1] - range[0]); this->ScaleOffset = range[0]; } } //------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapperHelper::BuildBufferObjects( vtkRenderer *ren, vtkActor *vtkNotUsed(act)) { vtkPolyData *poly = this->CurrentInput; if (poly == nullptr) { return; } // set the triangle scale this->TriangleScale = this->Owner->GetTriangleScale(); bool hasScaleArray = this->Owner->GetScaleArray() != nullptr && poly->GetPointData()->HasArray(this->Owner->GetScaleArray()); if (hasScaleArray && this->Owner->GetScaleFunction()) { this->BuildScaleTable(); } else { if (this->ScaleTable) { delete [] this->ScaleTable; this->ScaleTable = nullptr; } } if (this->Owner->GetScaleFactor() == 0.0) { this->UsingPoints = true; } else { this->UsingPoints = false; } // if we have an opacity array then get it and if we have // a ScalarOpacityFunction map the array through it bool hasOpacityArray = this->Owner->GetOpacityArray() != nullptr && poly->GetPointData()->HasArray(this->Owner->GetOpacityArray()); if (hasOpacityArray && this->Owner->GetScalarOpacityFunction()) { this->BuildOpacityTable(); } else { if (this->OpacityTable) { delete [] this->OpacityTable; this->OpacityTable = nullptr; } } // For vertex coloring, this sets this->Colors as side effect. // For texture map coloring, this sets ColorCoordinates // and ColorTextureMap as a side effect. // I moved this out of the conditional because it is fast. // Color arrays are cached. If nothing has changed, // then the scalars do not have to be regenerted. this->MapScalars(1.0); // Figure out how big each block will be, currently 6 floats. int splatCount = poly->GetPoints()->GetNumberOfPoints(); if (poly->GetVerts()->GetNumberOfCells()) { splatCount = poly->GetVerts()->GetNumberOfConnectivityEntries() - poly->GetVerts()->GetNumberOfCells(); } if (!this->UsingPoints) { splatCount *= 3; } vtkFloatArray *pts = vtkFloatArray::New(); pts->SetNumberOfComponents(3); pts->SetNumberOfTuples(splatCount); switch(poly->GetPoints()->GetDataType()) { vtkTemplateMacro( vtkOpenGLPointGaussianMapperHelperPoints( pts, static_cast(poly->GetPoints()->GetVoidPointer(0)), poly->GetPoints()->GetNumberOfPoints(), this, poly->GetVerts() )); } this->VBOs->CacheDataArray("vertexMC", pts, ren, VTK_FLOAT); pts->Delete(); if (!this->UsingPoints) { vtkFloatArray *offsets = vtkFloatArray::New(); offsets->SetNumberOfComponents(2); offsets->SetNumberOfTuples(splatCount); if (hasScaleArray) { vtkDataArray *sizes = poly->GetPointData()->GetArray( this->Owner->GetScaleArray()); switch (sizes->GetDataType()) { vtkTemplateMacro( vtkOpenGLPointGaussianMapperHelperSizes( offsets, static_cast(sizes->GetVoidPointer(0)), sizes->GetNumberOfComponents(), this->Owner->GetScaleArrayComponent(), poly->GetPoints()->GetNumberOfPoints(), this, poly->GetVerts() )); } } else { vtkOpenGLPointGaussianMapperHelperSizes( offsets, static_cast(nullptr), 0, 0, poly->GetPoints()->GetNumberOfPoints(), this, poly->GetVerts() ); } this->VBOs->CacheDataArray("offsetMC", offsets, ren, VTK_FLOAT); offsets->Delete(); } else { this->VBOs->CacheDataArray("offsetMC", nullptr, ren, VTK_FLOAT); } if (this->Colors) { vtkUnsignedCharArray *clrs = vtkUnsignedCharArray::New(); clrs->SetNumberOfComponents(4); clrs->SetNumberOfTuples(splatCount); vtkOpenGLPointGaussianMapperHelperColors( clrs, poly->GetPoints()->GetNumberOfPoints(), this->Colors ? (unsigned char *)this->Colors->GetVoidPointer(0) : (unsigned char*)nullptr, this->Colors ? this->Colors->GetNumberOfComponents() : 0, hasOpacityArray ? poly->GetPointData()->GetArray( this->Owner->GetOpacityArray()) : (vtkDataArray*)nullptr, this->Owner->GetOpacityArrayComponent(), this, poly->GetVerts() ); this->VBOs->CacheDataArray("scalarColor", clrs, ren, VTK_UNSIGNED_CHAR); clrs->Delete(); } this->VBOs->BuildAllVBOs(ren); // we use no IBO for (int i = PrimitiveStart; i < PrimitiveEnd; i++) { this->Primitives[i].IBO->IndexCount = 0; } this->Primitives[PrimitiveTris].IBO->IndexCount = splatCount; this->VBOBuildTime.Modified(); } //----------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapperHelper::RenderPieceDraw(vtkRenderer* ren, vtkActor *actor) { // draw polygons int numVerts = this->VBOs->GetNumberOfTuples("vertexMC"); if (numVerts) { // save off current state of src / dst blend functions GLint blendSrcA = GL_SRC_ALPHA; GLint blendDstA = GL_ONE; GLint blendSrcC = GL_SRC_ALPHA; GLint blendDstC = GL_ONE; if (this->Owner->GetEmissive() != 0) { glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcA); glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDstA); glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcC); glGetIntegerv(GL_BLEND_DST_RGB, &blendDstC); glBlendFunc( GL_SRC_ALPHA, GL_ONE); // additive for emissive sources } // First we do the triangles or points, update the shader, set uniforms, etc. this->UpdateShaders(this->Primitives[PrimitiveTris], ren, actor); if (this->UsingPoints) { glDrawArrays(GL_POINTS, 0, static_cast(numVerts)); } else { glDrawArrays(GL_TRIANGLES, 0, static_cast(numVerts)); } if (this->Owner->GetEmissive() != 0) { // restore blend func glBlendFuncSeparate(blendSrcC, blendDstC, blendSrcA, blendDstA); } } } //----------------------------------------------------------------------------- vtkStandardNewMacro(vtkOpenGLPointGaussianMapper) //----------------------------------------------------------------------------- vtkOpenGLPointGaussianMapper::vtkOpenGLPointGaussianMapper() { this->Helper = vtkOpenGLPointGaussianMapperHelper::New(); this->Helper->Owner = this; } vtkOpenGLPointGaussianMapper::~vtkOpenGLPointGaussianMapper() { this->Helper->Delete(); this->Helper = nullptr; } void vtkOpenGLPointGaussianMapper::RenderPiece(vtkRenderer *ren, vtkActor *act) { if (this->GetMTime() > this->HelperUpdateTime) { this->Helper->vtkPolyDataMapper::ShallowCopy(this); this->Helper->Modified(); this->HelperUpdateTime.Modified(); } this->Helper->RenderPiece(ren,act); } //----------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapper::ReleaseGraphicsResources(vtkWindow* win) { this->Helper->ReleaseGraphicsResources(win); this->Helper->SetInputData(nullptr); this->Modified(); } //----------------------------------------------------------------------------- bool vtkOpenGLPointGaussianMapper::GetIsOpaque() { if (this->Emissive) { return false; } return this->Superclass::GetIsOpaque(); } //----------------------------------------------------------------------------- void vtkOpenGLPointGaussianMapper::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); }