Files
UnrealEngine/Engine/Source/ThirdParty/MaterialX/MaterialX-1.38.10/source/MaterialXView/Viewer.h
2025-05-18 13:04:45 +08:00

466 lines
13 KiB
C++

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#ifndef MATERIALXVIEW_VIEWER_H
#define MATERIALXVIEW_VIEWER_H
#include <MaterialXView/Editor.h>
#include <MaterialXView/RenderPipeline.h>
#include <MaterialXRender/ShaderMaterial.h>
#include <MaterialXRender/Camera.h>
#include <MaterialXRender/GeometryHandler.h>
#include <MaterialXRender/LightHandler.h>
#include <MaterialXRender/ImageHandler.h>
#include <MaterialXRender/Timer.h>
#include <MaterialXCore/Unit.h>
namespace mx = MaterialX;
namespace ng = nanogui;
class DocumentModifiers
{
public:
mx::StringMap remapElements;
mx::StringSet skipElements;
std::string filePrefixTerminator;
};
class Viewer : public ng::Screen
{
friend class RenderPipeline;
friend class GLRenderPipeline;
friend class MetalRenderPipeline;
public:
Viewer(const std::string& materialFilename,
const std::string& meshFilename,
const std::string& envRadianceFilename,
const mx::FileSearchPath& searchPath,
const mx::FilePathVec& libraryFolders,
int screenWidth,
int screenHeight,
const mx::Color3& screenColor);
~Viewer() { }
// Initialize the viewer for rendering.
void initialize();
// Set the rotation of the current mesh as Euler angles.
void setMeshRotation(const mx::Vector3& rotation)
{
_meshRotation = rotation;
}
// Set the scale of the current mesh.
void setMeshScale(float scale)
{
_meshScale = scale;
}
// Set whether turntable rendering is enabled.
void setTurntableEnabled(bool val)
{
_turntableEnabled = val;
}
// Set the total number of steps for one 360 degree rotation.
void setTurntableSteps(int steps)
{
_turntableSteps = steps;
}
// Set the world-space position of the camera.
void setCameraPosition(const mx::Vector3& position)
{
_cameraPosition = position;
}
// Set the world-space target of the camera.
void setCameraTarget(const mx::Vector3& target)
{
_cameraTarget = target;
}
// Set the view angle of the camera.
void setCameraViewAngle(float angle)
{
_cameraViewAngle = angle;
}
// Set the zoom scale of the camera.
void setCameraZoom(float zoom)
{
_cameraZoom = zoom;
}
// Set the method for specular environment rendering.
void setSpecularEnvironmentMethod(mx::HwSpecularEnvironmentMethod method)
{
_genContext.getOptions().hwSpecularEnvironmentMethod = method;
}
// Set the number of environment samples.
void setEnvSampleCount(int count)
{
_lightHandler->setEnvSampleCount(count);
}
// Set the environment light intensity.
void setEnvLightIntensity(float intensity)
{
_lightHandler->setEnvLightIntensity(intensity);
}
// Set the rotation of the lighting environment about the Y axis.
void setLightRotation(float rotation)
{
_lightRotation = rotation;
}
// Enable or disable shadow maps.
void setShadowMapEnable(bool enable)
{
_genContext.getOptions().hwShadowMap = enable;
}
// Enable or disable drawing environment as the background.
void setDrawEnvironment(bool enable)
{
_drawEnvironment = enable;
}
// Set the modifiers to be applied to loaded documents.
void setDocumentModifiers(const DocumentModifiers& modifiers)
{
_modifiers = modifiers;
}
// Set the target width for texture baking.
void setBakeWidth(unsigned int bakeWidth)
{
_bakeWidth = bakeWidth;
}
// Set the target height for texture baking.
void setBakeHeight(unsigned int bakeHeight)
{
_bakeHeight = bakeHeight;
}
// Set the output document filename for texture baking.
void setBakeFilename(const mx::FilePath& bakeFilename)
{
_bakeFilename = bakeFilename;
}
// Return true if all inputs should be shown in the property editor.
bool getShowAllInputs() const
{
return _showAllInputs;
}
// Return the underlying NanoGUI window.
ng::Window* getWindow() const
{
return _window;
}
// Return the active image handler.
mx::ImageHandlerPtr getImageHandler() const
{
return _imageHandler;
}
// Return the selected material.
mx::MaterialPtr getSelectedMaterial() const
{
if (_selectedMaterial < _materials.size())
{
return _materials[_selectedMaterial];
}
return nullptr;
}
// Return the selected mesh partition.
mx::MeshPartitionPtr getSelectedGeometry() const
{
if (_selectedGeom < _geometryList.size())
{
return _geometryList[_selectedGeom];
}
return nullptr;
}
// Request a capture of the current frame, writing it to the given filename.
void requestFrameCapture(const mx::FilePath& filename)
{
_captureRequested = true;
_captureFilename = filename;
}
// Request that the viewer be closed after the next frame is rendered.
void requestExit()
{
_exitRequested = true;
}
// Bake textures to disk using the current render pipeline.
void bakeTextures()
{
_renderPipeline->bakeTextures();
}
private:
void draw_contents() override;
bool keyboard_event(int key, int scancode, int action, int modifiers) override;
bool scroll_event(const ng::Vector2i& p, const ng::Vector2f& rel) override;
bool mouse_motion_event(const ng::Vector2i& p, const ng::Vector2i& rel, int button, int modifiers) override;
bool mouse_button_event(const ng::Vector2i& p, int button, bool down, int modifiers) override;
void initContext(mx::GenContext& context);
void loadMesh(const mx::FilePath& filename);
void loadEnvironmentLight();
void applyDirectLights(mx::DocumentPtr doc);
void loadDocument(const mx::FilePath& filename, mx::DocumentPtr libraries);
void reloadShaders();
void loadStandardLibraries();
void saveShaderSource(mx::GenContext& context);
void loadShaderSource();
void saveDotFiles();
// Compute the resolution for texture baking.
mx::UnsignedIntPair computeBakingResolution(mx::ConstDocumentPtr doc);
// Translate the current material to the target shading model.
mx::DocumentPtr translateMaterial();
// Assign the given material to the given geometry, or remove any
// existing assignment if the given material is nullptr.
void assignMaterial(mx::MeshPartitionPtr geometry, mx::MaterialPtr material);
// Mark the given material as currently selected in the viewer.
void setSelectedMaterial(mx::MaterialPtr material)
{
for (size_t i = 0; i < _materials.size(); i++)
{
if (material == _materials[i])
{
_selectedMaterial = i;
break;
}
}
}
// Generate a base output filepath for data derived from the current material.
mx::FilePath getBaseOutputPath();
// Return an element predicate for documents written from the viewer.
mx::ElementPredicate getElementPredicate();
void initCamera();
void updateCameras();
void updateGeometrySelections();
void updateMaterialSelections();
void updateMaterialSelectionUI();
void updateDisplayedProperties();
void createLoadMeshInterface(Widget* parent, const std::string& label);
void createLoadMaterialsInterface(Widget* parent, const std::string& label);
void createLoadEnvironmentInterface(Widget* parent, const std::string& label);
void createSaveMaterialsInterface(Widget* parent, const std::string& label);
void createPropertyEditorInterface(Widget* parent, const std::string& label);
void createAdvancedSettings(Widget* parent);
// Return the ambient occlusion image, if any, associated with the given material.
mx::ImagePtr getAmbientOcclusionImage(mx::MaterialPtr material);
// Split the given radiance map into indirect and direct components,
// returning a new indirect map and directional light document.
void splitDirectLight(mx::ImagePtr envRadianceMap, mx::ImagePtr& indirectMap, mx::DocumentPtr& dirLightDoc);
mx::MaterialPtr getEnvironmentMaterial();
mx::MaterialPtr getWireframeMaterial();
mx::ImagePtr getShadowMap();
void invalidateShadowMap();
mx::ImagePtr renderWedge();
void renderTurnable();
void renderScreenSpaceQuad(mx::MaterialPtr material);
// Update the directional albedo table.
void updateAlbedoTable();
// Toggle turntable
void toggleTurntable(bool enable);
// Set shader interface type
void setShaderInterfaceType(mx::ShaderInterfaceType interfaceType);
private:
ng::Window* _window;
RenderPipelinePtr _renderPipeline;
mx::FilePath _materialFilename;
mx::FileSearchPath _materialSearchPath;
mx::FilePath _meshFilename;
mx::FilePath _envRadianceFilename;
mx::FileSearchPath _searchPath;
mx::FilePathVec _libraryFolders;
mx::Vector3 _meshTranslation;
mx::Vector3 _meshRotation;
float _meshScale;
bool _turntableEnabled;
int _turntableSteps;
int _turntableStep;
mx::ScopedTimer _turntableTimer;
mx::Vector3 _cameraPosition;
mx::Vector3 _cameraTarget;
mx::Vector3 _cameraUp;
float _cameraViewAngle;
float _cameraNearDist;
float _cameraFarDist;
float _cameraZoom;
bool _userCameraEnabled;
mx::Vector3 _userTranslation;
mx::Vector3 _userTranslationStart;
bool _userTranslationActive;
mx::Vector2 _userTranslationPixel;
// Document management
mx::DocumentPtr _stdLib;
DocumentModifiers _modifiers;
mx::StringSet _xincludeFiles;
// Lighting information
mx::FilePath _lightRigFilename;
mx::DocumentPtr _lightRigDoc;
float _lightRotation;
// Light processing options
bool _normalizeEnvironment;
bool _splitDirectLight;
bool _generateReferenceIrradiance;
bool _saveGeneratedLights;
// Shadow mapping
mx::MaterialPtr _shadowMaterial;
mx::MaterialPtr _shadowBlurMaterial;
mx::ImagePtr _shadowMap;
unsigned int _shadowSoftness;
// Ambient occlusion
float _ambientOcclusionGain;
// Geometry selections
std::vector<mx::MeshPartitionPtr> _geometryList;
size_t _selectedGeom;
ng::Label* _geomLabel;
ng::ComboBox* _geometrySelectionBox;
// Material selections
std::vector<mx::MaterialPtr> _materials;
mx::MaterialPtr _wireMaterial;
size_t _selectedMaterial;
ng::Label* _materialLabel;
ng::ComboBox* _materialSelectionBox;
PropertyEditor _propertyEditor;
// Material assignments
std::map<mx::MeshPartitionPtr, mx::MaterialPtr> _materialAssignments;
// Cameras
mx::CameraPtr _identityCamera;
mx::CameraPtr _viewCamera;
mx::CameraPtr _envCamera;
mx::CameraPtr _shadowCamera;
// Resource handlers
mx::GeometryHandlerPtr _geometryHandler;
mx::ImageHandlerPtr _imageHandler;
mx::LightHandlerPtr _lightHandler;
// Supporting materials and geometry.
mx::GeometryHandlerPtr _envGeometryHandler;
mx::MaterialPtr _envMaterial;
mx::MeshPtr _quadMesh;
// Shader generator contexts
mx::GenContext _genContext;
#ifndef MATERIALXVIEW_METAL_BACKEND
mx::GenContext _genContextEssl;
#endif
#if MATERIALX_BUILD_GEN_OSL
mx::GenContext _genContextOsl;
#endif
#if MATERIALX_BUILD_GEN_MDL
mx::GenContext _genContextMdl;
#endif
// Unit registry
mx::UnitConverterRegistryPtr _unitRegistry;
// Viewing options
bool _drawEnvironment;
bool _outlineSelection;
// Render options
bool _renderTransparency;
bool _renderDoubleSided;
// Framebuffer Color Texture
void* _colorTexture;
// Scene options
mx::StringVec _distanceUnitOptions;
mx::LinearUnitConverterPtr _distanceUnitConverter;
// Mesh loading options
bool _splitByUdims;
// Material loading options
bool _mergeMaterials;
bool _showAllInputs;
bool _flattenSubgraphs;
// Shader translation
std::string _targetShader;
// Frame capture
bool _captureRequested;
mx::FilePath _captureFilename;
bool _exitRequested;
// Wedge rendering
bool _wedgeRequested;
mx::FilePath _wedgeFilename;
std::string _wedgePropertyName;
float _wedgePropertyMin;
float _wedgePropertyMax;
unsigned int _wedgeImageCount;
// Texture baking
bool _bakeHdr;
bool _bakeAverage;
bool _bakeOptimize;
bool _bakeRequested;
unsigned int _bakeWidth;
unsigned int _bakeHeight;
bool _bakeDocumentPerMaterial;
mx::FilePath _bakeFilename;
};
extern const mx::Vector3 DEFAULT_CAMERA_POSITION;
extern const float DEFAULT_CAMERA_VIEW_ANGLE;
extern const float DEFAULT_CAMERA_ZOOM;
#endif // MATERIALXVIEW_VIEWER_H