// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause /** * @class vtkOpenGLLowMemoryPolyDataMapper * @brief PolyDataMapper using OpenGL to render surface meshes. * * This mapper targets webassembly, mobile and other platforms where * memory is scarce and geometry shaders are unavailable or inefficient. */ #ifndef vtkOpenGLLowMemoryPolyDataMapper_h #define vtkOpenGLLowMemoryPolyDataMapper_h #include "vtkPolyDataMapper.h" #include "vtkCellGraphicsPrimitiveMap.h" // For CellTypeMapperOffsets #include "vtkDrawTexturedElements.h" // For parent helper class #include "vtkHardwareSelector.h" // For ivar #include "vtkOpenGLShaderDeclaration.h" // For ivar #include "vtkRenderingOpenGL2Module.h" // For export macro #include "vtkWrappingHints.h" // For VTK_MARSHALAUTO #include // for array #include // for set #include // for pair #include // for TextureInfo VTK_ABI_NAMESPACE_BEGIN class vtkGenericOpenGLResourceFreeCallback; class vtkOpenGLLowMemoryCellTypeAgent; class vtkOpenGLLowMemoryVerticesAgent; class vtkOpenGLLowMemoryLinesAgent; class vtkOpenGLLowMemoryPolygonsAgent; class VTKRENDERINGOPENGL2_EXPORT VTK_MARSHALAUTO vtkOpenGLLowMemoryPolyDataMapper : public vtkPolyDataMapper #ifndef __VTK_WRAP__ , public vtkDrawTexturedElements #endif { public: static vtkOpenGLLowMemoryPolyDataMapper* New(); vtkTypeMacro(vtkOpenGLLowMemoryPolyDataMapper, vtkPolyDataMapper); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Make a shallow copy of this mapper. */ void ShallowCopy(vtkAbstractMapper* m) override; /** * Unique hash based on availability of scalars, normals, tcoords, lookup tables * and related attributes that distinguish the rendering requirements of different * polydata. */ MapperHashType GenerateHash(vtkPolyData* polydata) override; vtkPolyData* CurrentInput = nullptr; void RenderPiece(vtkRenderer* renderer, vtkActor* actor) override; virtual void RenderPieceStart(vtkRenderer* renderer, vtkActor* actor); virtual void RenderPieceDraw(vtkRenderer* renderer, vtkActor* actor); virtual void RenderPieceFinish(vtkRenderer* renderer, vtkActor* actor); /// Release any graphics resources associated with the \a window. void ReleaseGraphicsResources(vtkWindow*) override; VTK_MARSHALEXCLUDE(VTK_MARSHAL_EXCLUDE_REASON_IS_INTERNAL) vtkGetMacro(PopulateSelectionSettings, bool); VTK_MARSHALEXCLUDE(VTK_MARSHAL_EXCLUDE_REASON_IS_INTERNAL) void SetPopulateSelectionSettings(bool v) { this->PopulateSelectionSettings = v; } void SetVBOShiftScaleMethod(int method) override; /** * WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE * DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS * Used by vtkHardwareSelector to determine if the prop supports hardware * selection. */ bool GetSupportsSelection() override { return true; } ///@{ /** * By default, this class uses the dataset's point and cell ids during * rendering. However, one can override those by specifying cell and point * data arrays to use instead. Currently, only vtkIdType array is supported. * Set to NULL string (default) to use the point ids instead. */ vtkSetStdStringFromCharMacro(PointIdArrayName); vtkGetCharFromStdStringMacro(PointIdArrayName); vtkSetStdStringFromCharMacro(CellIdArrayName); vtkGetCharFromStdStringMacro(CellIdArrayName); ///@} ///@{ /** * If this class should override the process id using a data-array, * set this variable to the name of the array to use. It must be a * point-array. * The array's DataType *MUST* be VTK_UNSIGNED_INT. */ vtkSetStdStringFromCharMacro(ProcessIdArrayName); vtkGetCharFromStdStringMacro(ProcessIdArrayName); ///@} ///@{ /** * Generally, this class can render the composite id when iterating * over composite datasets. However in some cases (as in AMR), the rendered * structure may not correspond to the input data, in which case we need * to provide a cell array that can be used to render in the composite id in * selection passes. Set to NULL (default) to not override the composite id * color set by vtkCompositePainter if any. * The array *MUST* be a cell array. * The array's DataType *MUST* be VTK_UNSIGNED_INT. */ vtkSetStdStringFromCharMacro(CompositeIdArrayName); vtkGetCharFromStdStringMacro(CompositeIdArrayName); ///@} /// If you removed all mods, call this to go back to default setting. virtual void ResetModsToDefault(); void AddMod(const std::string& className); void AddMods(const std::vector& classNames); void RemoveMod(const std::string& className); void RemoveAllMods(); /** * Select a data array from the point/cell data * and map it to a generic vertex attribute. * vertexAttributeName is the name of the vertex attribute. * dataArrayName is the name of the data array. * fieldAssociation indicates when the data array is a point data array or * cell data array (vtkDataObject::FIELD_ASSOCIATION_POINTS or * (vtkDataObject::FIELD_ASSOCIATION_CELLS). * componentno indicates which component from the data array must be passed as * the attribute. If -1, then all components are passed. */ void MapDataArrayToVertexAttribute(const char* vertexAttributeName, const char* dataArrayName, int fieldAssociation, int componentno = -1) override; // This method will Map the specified data array for use as // a texture coordinate for texture tname. The actual // attribute will be named tname_coord so as to not // conflict with the texture sampler definition which will // be tname. void MapDataArrayToMultiTextureAttribute(const char* tname, const char* dataArrayName, int fieldAssociation, int componentno = -1) override; /** * Remove a vertex attribute mapping. */ void RemoveVertexAttributeMapping(const char* vertexAttributeName) override; /** * Remove all vertex attributes. */ void RemoveAllVertexAttributeMappings() override; /** * allows a mapper to update a selections color buffers * Called from a prop which in turn is called from the selector */ void ProcessSelectorPixelBuffers( vtkHardwareSelector* sel, std::vector& pixeloffsets, vtkProp* prop) override; protected: vtkOpenGLLowMemoryPolyDataMapper(); ~vtkOpenGLLowMemoryPolyDataMapper() override; enum class ShaderColorSourceAttribute { // Color is obtained by mapping point scalar array. shader will interpolate colors. Point, // Color is obtained by mapping cell scalar array. entire cell will have the same color. Cell, // Similar to `Point`, in addition, mapper already interpolated the scalars and provided a // ColorTextureCoordinate and a ColorTexture. PointTexture, // The color of the entire geometry is specified by the actor's vtkProperty instance. Uniform }; enum class ShaderNormalSourceAttribute { // Uses point normals. Point, // Uses cell normals. Cell, // Shader computes a normal for the provoking vertex and passes it down to fragment shader. Primitive }; ShaderColorSourceAttribute DetermineShaderColorSource(vtkPolyData* mesh); ShaderNormalSourceAttribute DetermineShaderNormalSource(vtkActor* actor, vtkPolyData* mesh); void MapDataArray(const char* vertexAttributeName, const char* dataArrayName, const char* texturename, int fieldAssociation, int componentno); bool IsUpToDate(vtkRenderer* renderer, vtkActor* actor); bool IsShaderUpToDate(vtkRenderer* renderer, vtkActor* actor); virtual bool IsDataObjectUpToDate(); virtual bool IsShaderColorSourceUpToDate(vtkActor* actor); virtual bool IsShaderNormalSourceUpToDate(vtkActor* actor); void DeleteTextureBuffers(); virtual bool BindArraysToTextureBuffers(vtkRenderer* renderer, vtkActor* actor, vtkCellGraphicsPrimitiveMap::CellTypeMapperOffsets& offsets); void InstallArrayTextureShaderDeclarations(); virtual void UpdateShaders(vtkRenderer* renderer, vtkActor* actor); void ReplaceShaderValues( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderPosition( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderNormal( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); virtual void ReplaceShaderColor( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderImplementationCustomUniforms( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderPointSize( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderWideLines( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderEdges( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderSelection( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void ReplaceShaderTCoord( vtkRenderer* renderer, vtkActor* actor, std::string& vsSource, std::string& fsSource); void SetShaderParameters(vtkRenderer* renderer, vtkActor* actor); // compute and set the maximum point and cell ID used in selection void UpdateMaximumPointCellIds(vtkRenderer* ren, vtkActor* actor); bool GetCoordShiftAndScaleEnabled(); int GetCoordShiftAndScaleMethod(); void SetShiftValues(double x, double y, double z); void SetScaleValues(double x, double y, double z); void ComputeShiftScale(vtkRenderer* renderer, vtkActor* actor, vtkDataArray* arrays); void ComputeCameraBasedShiftScale(vtkRenderer* renderer, vtkActor* actor, vtkPolyData* mesh); void ComputeShiftScaleTransform(vtkRenderer* renderer, vtkActor* actor); virtual void UpdateShiftScale(vtkRenderer* renderer, vtkActor* actor); virtual vtkDataArray* GetColors(vtkPolyData* mesh); vtkDataArray* GetPointNormals(vtkPolyData* mesh); vtkDataArray* GetPointTangents(vtkPolyData* mesh); vtkDataArray* GetTextureCoordinates(vtkPolyData* mesh); vtkDataArray* GetColorTextureCoordinates(vtkPolyData* mesh); vtkDataArray* GetCellNormals(vtkPolyData* mesh); using TextureInfo = std::pair; bool HaveTextures(vtkActor* actor); unsigned int GetNumberOfTextures(vtkActor* actor); std::vector GetTextures(vtkActor* actor); std::pair GetTextureCoordinateAndSamplerBufferNames(const char* tname); void UpdatePBRStateCache(vtkRenderer* renderer, vtkActor* actor); void UpdateGLSLMods(vtkRenderer* renderer, vtkActor* actor); class ExtraAttributeValue { public: std::string DataArrayName; int FieldAssociation; int ComponentNumber; std::string TextureName; }; std::map ExtraAttributes; /// @name Color and Normal sources ShaderColorSourceAttribute ShaderColorSource = ShaderColorSourceAttribute::Uniform; ShaderNormalSourceAttribute ShaderNormalSource = ShaderNormalSourceAttribute::Primitive; /// @name Mods /// These are the names of classes which are subclasess of vtkGLSLRuntimeModBase. /// The mods will be loaded one by one and applied in the order they were added. std::vector ModNames; std::set ModNamesUnique; static std::vector DefaultModNames; /// @name Shader declarations in an organized form using GLSLAttributeType = vtkOpenGLShaderDeclaration::GLSLAttributeType; using GLSLDataType = vtkOpenGLShaderDeclaration::GLSLDataType; using GLSLPrecisionType = vtkOpenGLShaderDeclaration::GLSLPrecisionType; using GLSLQualifierType = vtkOpenGLShaderDeclaration::GLSLQualifierType; std::vector ShaderDecls; /// @name Last render information used to check whether shader program needs an update. vtkNew LastRenderPassInfo; int LastSelectionState = vtkHardwareSelector::MIN_KNOWN_PASS - 1; vtkTimeStamp RenderTimeStamp; vtkTimeStamp SelectionStateTimeStamp; vtkTimeStamp ShaderBuildTimeStamp; vtkTimeStamp ShiftScaleTimeStamp; /// @name Coordinate shift scale for datasets whose bounding box is far from origin. std::array ShiftValues; std::array ScaleValues; bool CoordinateShiftAndScaleInUse; vtkNew SSInverseTransform; // Inverse transform which can undo shift + scale. vtkNew SSMatrix; // Transpose of the above inverse transform. struct CellGroupInformation { vtkCellGraphicsPrimitiveMap::CellTypeMapperOffsets Offsets; vtkIdType NumberOfElements = 0; bool CanRender = false; bool UsesEdgeValueBuffer = false; bool UsesCellMapBuffer = false; friend std::ostream& operator<<(std::ostream& os, const CellGroupInformation& cg) { os << cg.Offsets << '\n' << "NumberOfElements: " << cg.NumberOfElements << '\n' << "CanRender: " << cg.CanRender << '\n' << "UsesEdgeValueBuffer: " << cg.UsesEdgeValueBuffer << '\n' << "UsesCellMapBuffer: " << cg.UsesCellMapBuffer << '\n'; return os; } }; /// @name Primitives /// @brief vtkPolyData has four celltypes. Each gets it's own cell type mapper with it's own cell /// groups. struct PrimitiveInformation { std::unique_ptr Agent; std::function GeneratorFunction; std::vector CellGroups; }; std::array Primitives; bool DrawingVertices = false; bool HasColors = false; bool HasTangents = false; bool HasPointNormals = false; bool HasCellNormals = false; bool HasPointTextureCoordinates = false; // if set to true, tcoords will be passed to the // VBO even if the mapper knows of no texture maps // normally tcoords are only added to the VBO if the // mapper has identified a texture map as well. bool ForceTextureCoordinates = false; /// @name ColorTextureMap vtkOpenGLTexture* InternalColorTexture = nullptr; /// @name Selection data bool PopulateSelectionSettings = true; bool PointPicking = false; // additional picking indirection std::string PointIdArrayName; std::string CellIdArrayName; std::string ProcessIdArrayName; std::string CompositeIdArrayName; /// @name Cached PBR information bool HasAnisotropy = false; bool HasClearCoat = false; bool UsesNormalMap = false; bool UsesCoatNormalMap = false; bool UsesRotationMap = false; vtkTimeStamp PBRStateTimeStamp; private: vtkOpenGLLowMemoryPolyDataMapper(const vtkOpenGLLowMemoryPolyDataMapper&) = delete; void operator=(const vtkOpenGLLowMemoryPolyDataMapper&) = delete; friend class vtkOpenGLLowMemoryCellTypeAgent; friend class vtkOpenGLLowMemoryVerticesAgent; friend class vtkOpenGLLowMemoryLinesAgent; friend class vtkOpenGLLowMemoryPolygonsAgent; }; VTK_ABI_NAMESPACE_END #endif // vtkOpenGLLowMemoryPolyDataMapper_h