From 8f0d000845ba9836d53a1a29c8eeed63a4f5e71d Mon Sep 17 00:00:00 2001 From: tgvarik Date: Mon, 27 Nov 2023 15:12:15 -0800 Subject: [PATCH] [hdPrman] Consolidate and improve motion blur handling Rewrites the velocity motion blur scene index plugin to handle all types of motion blur processing for hdPrman. The plugin is renamed to HdPrman_MotionBlurSceneIndexPlugin, and redundant motion blur processing code previously scattered throughout hdPrman is removed. The revised motion blur scene index plugin is exclusively responsible for reshaping data sources for motion blur in hdPrman. No other part of hdPrman needs to concern itself with questions of whether and how to apply motion blur. Downstream consumers need only sample data sources to receive the correct number of samples. Tests are added to explicitly test transform blur (and blurScale, which was not previously applied to transform blur) on geometry and cameras. The velocity blur handling portions of the plugin have been expanded to support velocity blur on point instancers. However, since hdPrman currently does not support constant primvars on point instancers, the plugin is unable to see authored velocities or angularVelocities and so cannot apply velocity blur to point instancers yet. Accordingly, no test of this functionality has been added. This will be rectified in follow-up work. Note that in 2294852, we introduced a change that affected all non-points primvars with authored time samples. With that change, such primvars were sampled once at the midpoint of the requested interval. That behavior has been reverted. Non-blurable primvars are sampled at offset 0 regardless of interval to conform to the USDMotionAPI specification. Support for USD versions < 22.05 and Prman versions < 25.0 is removed from the affected files. Likewise, gating on the presence of the motion blur scene index plugin is also removed, since it is always loaded for USD versions >= 22.05. (Internal change: 2305710) (Internal change: 2305831) --- .../plugin/hdPrman/CMakeLists.txt | 2 +- .../plugin/hdPrman/basisCurves.cpp | 23 +- .../plugin/hdPrman/debugCodes.cpp | 1 + .../renderman-25/plugin/hdPrman/debugCodes.h | 3 +- .../renderman-25/plugin/hdPrman/gprim.h | 15 - .../renderman-25/plugin/hdPrman/mesh.cpp | 29 +- .../hdPrman/motionBlurSceneIndexPlugin.cpp | 1460 +++++++++++++++++ ...xPlugin.h => motionBlurSceneIndexPlugin.h} | 39 +- .../renderman-25/plugin/hdPrman/plugInfo.json | 4 +- .../renderman-25/plugin/hdPrman/points.cpp | 50 +- .../plugin/hdPrman/renderParam.cpp | 444 +---- .../renderman-25/plugin/hdPrman/renderParam.h | 38 - ...inalOutputInvalidatingSceneIndexPlugin.cpp | 21 +- .../renderman-25/plugin/hdPrman/tokens.h | 2 +- .../velocityMotionBlurSceneIndexPlugin.cpp | 1013 ------------ 15 files changed, 1540 insertions(+), 1604 deletions(-) create mode 100644 third_party/renderman-25/plugin/hdPrman/motionBlurSceneIndexPlugin.cpp rename third_party/renderman-25/plugin/hdPrman/{velocityMotionBlurSceneIndexPlugin.h => motionBlurSceneIndexPlugin.h} (56%) delete mode 100644 third_party/renderman-25/plugin/hdPrman/velocityMotionBlurSceneIndexPlugin.cpp diff --git a/third_party/renderman-25/plugin/hdPrman/CMakeLists.txt b/third_party/renderman-25/plugin/hdPrman/CMakeLists.txt index d89be46b48..7ecd3ae3ab 100644 --- a/third_party/renderman-25/plugin/hdPrman/CMakeLists.txt +++ b/third_party/renderman-25/plugin/hdPrman/CMakeLists.txt @@ -125,7 +125,7 @@ pxr_plugin(${PXR_PACKAGE} rileyRenderTargetPrim terminalSceneIndexObserver utils - velocityMotionBlurSceneIndexPlugin + motionBlurSceneIndexPlugin virtualStructResolvingSceneIndex PUBLIC_HEADERS diff --git a/third_party/renderman-25/plugin/hdPrman/basisCurves.cpp b/third_party/renderman-25/plugin/hdPrman/basisCurves.cpp index 0ffdab033f..15f4ee6edf 100644 --- a/third_party/renderman-25/plugin/hdPrman/basisCurves.cpp +++ b/third_party/renderman-25/plugin/hdPrman/basisCurves.cpp @@ -28,13 +28,8 @@ #include "hdPrman/material.h" #include "hdPrman/rixStrings.h" #include "pxr/imaging/hd/basisCurvesTopology.h" -#include "pxr/base/gf/matrix4f.h" -#include "pxr/base/gf/matrix4d.h" -#include "Riley.h" #include "RiTypesHelper.h" -#include "RixShadingUtils.h" -#include "RixPredefinedStrings.hpp" PXR_NAMESPACE_OPEN_SCOPE @@ -150,18 +145,12 @@ HdPrman_BasisCurves::_ConvertGeometry(HdPrman_RenderParam *renderParam, // Points float primvarTime = 0.0f; - if( HdPrman_RenderParam::HasSceneIndexPlugin( - HdPrmanPluginTokens->velocityBlur) ) { - HdPrman_ConvertPointsPrimvar( - sceneDelegate, - id, - renderParam->GetShutterInterval(), - primvars, - vertexPrimvarCount); - } else { - primvarTime = renderParam->ConvertPositions( - sceneDelegate, id, vertexPrimvarCount, primvars); - } + HdPrman_ConvertPointsPrimvar( + sceneDelegate, + id, + renderParam->GetShutterInterval(), + primvars, + vertexPrimvarCount); // Set element ID. Overloaded use of "__faceIndex" to support picking... std::vector elementId(numCurves); diff --git a/third_party/renderman-25/plugin/hdPrman/debugCodes.cpp b/third_party/renderman-25/plugin/hdPrman/debugCodes.cpp index 567ae3f676..013966389a 100644 --- a/third_party/renderman-25/plugin/hdPrman/debugCodes.cpp +++ b/third_party/renderman-25/plugin/hdPrman/debugCodes.cpp @@ -49,6 +49,7 @@ TF_REGISTRY_FUNCTION(TfDebug) "computations."); TF_DEBUG_ENVIRONMENT_SYMBOL(HDPRMAN_TERMINAL_SCENE_INDEX_OBSERVER, "Debug logging for HdPrman terminal scene index observer."); + TF_DEBUG_ENVIRONMENT_SYMBOL(HDPRMAN_MOTION_BLUR, "Motion blur"); } PXR_NAMESPACE_CLOSE_SCOPE diff --git a/third_party/renderman-25/plugin/hdPrman/debugCodes.h b/third_party/renderman-25/plugin/hdPrman/debugCodes.h index 951418d2a6..efdafcc7d8 100644 --- a/third_party/renderman-25/plugin/hdPrman/debugCodes.h +++ b/third_party/renderman-25/plugin/hdPrman/debugCodes.h @@ -42,7 +42,8 @@ TF_DEBUG_CODES( HDPRMAN_MESHLIGHT, HDPRMAN_RENDER_SETTINGS, HDPRMAN_RENDER_PASS, - HDPRMAN_TERMINAL_SCENE_INDEX_OBSERVER + HDPRMAN_TERMINAL_SCENE_INDEX_OBSERVER, + HDPRMAN_MOTION_BLUR ); PXR_NAMESPACE_CLOSE_SCOPE diff --git a/third_party/renderman-25/plugin/hdPrman/gprim.h b/third_party/renderman-25/plugin/hdPrman/gprim.h index 026b7795f1..42f3cc0b48 100644 --- a/third_party/renderman-25/plugin/hdPrman/gprim.h +++ b/third_party/renderman-25/plugin/hdPrman/gprim.h @@ -25,7 +25,6 @@ #define EXT_RMANPKG_25_0_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H #include "pxr/pxr.h" -#include "pxr/imaging/hd/enums.h" #include "pxr/usd/sdf/types.h" #include "pxr/base/gf/matrix4d.h" @@ -37,8 +36,6 @@ #include "hdPrman/utils.h" #include "Riley.h" -#include "RixShadingUtils.h" -#include "RixPredefinedStrings.hpp" PXR_NAMESPACE_OPEN_SCOPE @@ -181,18 +178,6 @@ HdPrman_Gprim::Sync(HdSceneDelegate* sceneDelegate, HdTimeSampleArray xf; sceneDelegate->SampleTransform(id, &xf); - // If blur is explicitly disabled, use single time 0 sample - const bool enableMotionBlur = - param->IsMotionBlurEnabled() && - HdPrman_IsMotionBlurPrimvarEnabled(sceneDelegate, id) && - HdPrman_GetNumXformSamples(sceneDelegate, id) >= 2; - - if (!enableMotionBlur) { - xf.values[0] = xf.Resample(0.f); - xf.times[0] = 0.f; - xf.Resize(1); - } - // Update visibility so thet rprim->IsVisible() will work in render pass if (HdChangeTracker::IsVisibilityDirty(*dirtyBits, id)) { BASE::_UpdateVisibility(sceneDelegate, dirtyBits); diff --git a/third_party/renderman-25/plugin/hdPrman/mesh.cpp b/third_party/renderman-25/plugin/hdPrman/mesh.cpp index c94eba4660..e7dcc50e9b 100644 --- a/third_party/renderman-25/plugin/hdPrman/mesh.cpp +++ b/third_party/renderman-25/plugin/hdPrman/mesh.cpp @@ -25,25 +25,14 @@ #include "hdPrman/mesh.h" #include "hdPrman/renderParam.h" #include "hdPrman/coordSys.h" -#include "hdPrman/instancer.h" #include "hdPrman/material.h" #include "hdPrman/rixStrings.h" -#include "pxr/base/gf/matrix4d.h" -#include "pxr/base/gf/matrix4f.h" -#include "pxr/base/gf/vec2f.h" -#include "pxr/base/gf/vec3f.h" -#include "pxr/base/gf/vec4f.h" -#include "pxr/imaging/hd/coordSys.h" #include "pxr/imaging/hd/meshTopology.h" -#include "pxr/imaging/hd/meshUtil.h" #include "pxr/imaging/pxOsd/subdivTags.h" #include "pxr/imaging/pxOsd/tokens.h" #include "pxr/usd/usdRi/rmanUtilities.h" -#include "Riley.h" #include "RiTypesHelper.h" -#include "RixShadingUtils.h" -#include "RixPredefinedStrings.hpp" #include @@ -169,18 +158,12 @@ HdPrman_Mesh::_ConvertGeometry(HdPrman_RenderParam *renderParam, // Point positions (P) // float primvarTime = 0.0f; - if( HdPrman_RenderParam::HasSceneIndexPlugin( - HdPrmanPluginTokens->velocityBlur) ) { - HdPrman_ConvertPointsPrimvar( - sceneDelegate, - id, - renderParam->GetShutterInterval(), - primvars, - npoints); - } else { - primvarTime = renderParam->ConvertPositions( - sceneDelegate, id, npoints, primvars); - } + HdPrman_ConvertPointsPrimvar( + sceneDelegate, + id, + renderParam->GetShutterInterval(), + primvars, + npoints); // Topology. primvars.SetIntegerDetail(RixStr.k_Ri_nvertices, nverts.cdata(), RtDetailType::k_uniform); diff --git a/third_party/renderman-25/plugin/hdPrman/motionBlurSceneIndexPlugin.cpp b/third_party/renderman-25/plugin/hdPrman/motionBlurSceneIndexPlugin.cpp new file mode 100644 index 0000000000..09f824c655 --- /dev/null +++ b/third_party/renderman-25/plugin/hdPrman/motionBlurSceneIndexPlugin.cpp @@ -0,0 +1,1460 @@ +// +// Copyright 2022 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "hdPrman/motionBlurSceneIndexPlugin.h" + +#include "hdPrman/debugCodes.h" +#include "hdPrman/tokens.h" + +#include "pxr/imaging/hd/filteringSceneIndex.h" +#include "pxr/imaging/hd/primvarsSchema.h" +#include "pxr/imaging/hd/retainedDataSource.h" +#include "pxr/imaging/hd/sceneIndexPluginRegistry.h" +#include "pxr/imaging/hd/tokens.h" +#include "pxr/imaging/hd/xformSchema.h" + +#include "pxr/base/vt/array.h" +#include "pxr/base/vt/typeHeaders.h" +#include "pxr/base/vt/visitValue.h" + +#include + +PXR_NAMESPACE_OPEN_SCOPE + +TF_DEFINE_PRIVATE_TOKENS( + _tokens, + (fps) + ((mblur, "ri:object:mblur")) + ((vblur, "ri:object:vblur")) + ((vblur_on, "Velocity Blur")) + ((ablur_on, "Acceleration Blur")) + ((vblur_off, "No Velocity Blur")) + ((geosamples, "ri:object:geosamples")) + ((xformsamples, "ri:object:xformsamples")) + (angularVelocities) // XXX: Why is this not in HdTokens? +); + +// XXX: These defaults are pulled from UsdMotionAPI, for which there is not yet +// a corresponding Hydra schema. +static const int _defaultNonlinearSampleCount = 3; +static const float _defaultBlurScale = 1.0f; +// There is no canonical source for these defaults. They were previously hard- +// coded in renderParam.cpp. +static const int _defaultXformSamples = 2; +static const int _defaultGeoSamples = 2; +static const bool _defaultMblur = true; +static const TfToken _defaultVblur = _tokens->ablur_on; + +// XXX: We need to encode the fps in the scene index (in a standard +// place). Note that fps is called timeCodesPerSecond in USD. +static const float _fps = 24.0f; + +static const float _minimumShutterInterval = 1.0e-10; + +// XXX: Set by HdPrman_MotionBlurSceneIndexPlugin::SetShutterInterval() +// and needed by _MotionBlurHelper. These are part of our shutter +// interval workaround. See comments on SetShutterInterval() at bottom of file. +static float _shutterOpen = 0.0f; +static float _shutterClose = 0.0f; + +using TfTokenSet = std::unordered_set; + +TF_REGISTRY_FUNCTION(TfType) +{ + HdSceneIndexPluginRegistry::Define(); +} + +TF_REGISTRY_FUNCTION(HdSceneIndexPlugin) +{ + // This plug-in should be inserted *after* the extComp plug-in, + // so that disabling of blur, etc. will also affect points from extComp + const HdSceneIndexPluginRegistry::InsertionPhase insertionPhase = 3; + + const HdContainerDataSourceHandle inputArgs = + HdRetainedContainerDataSource::New( + _tokens->fps, + HdRetainedSampledDataSource::New(VtValue(_fps))); + + for( auto const& pluginDisplayName : HdPrman_GetPluginDisplayNames() ) { + HdSceneIndexPluginRegistry::GetInstance().RegisterSceneIndexForRenderer( + pluginDisplayName, + HdPrmanPluginTokens->motionBlur, + inputArgs, + insertionPhase, + HdSceneIndexPluginRegistry::InsertionOrderAtStart); + } +} + +namespace +{ + +// Get fps from input arguments data source +float _GetFps(const HdContainerDataSourceHandle& inputArgs) +{ + if (!inputArgs) { + return _fps; + } + + const auto source = HdSampledDataSource::Cast(inputArgs->Get(_tokens->fps)); + if (!source) { + return _fps; + } + + const VtValue &value = source->GetValue(0.0f); + if (!value.IsHolding()) { + return _fps; + } + + return value.UncheckedGet(); +} + +// Unfortunately, when encountering a legacy prim, the scene index emulation +// calls GetContributingSampleTimesForInterval with startTime and endTime +// being the smallest and largest finite floating point number. It does this +// because it cannot query the scene delegate itself. +// +// We rely on the UsdImaging knowing the relevant camera and its +// shutter interval and returning a sample time for the beginning and +// end of the shutter interval. +std::pair +_GetSamplingInterval( + const HdSampledDataSourceHandle& samplesSource, + const float shutterOpen, const float shutterClose, + const HdSampledDataSource::Time startTime, + const HdSampledDataSource::Time endTime) +{ + if (std::numeric_limits::lowest() < startTime && + endTime < std::numeric_limits::max()) { + // Client gives us a valid shutter interval. Use it. + return { startTime, endTime }; + } + + // Do the shutter interval reconstruction described above. + + std::vector sampleTimes; + // Ignore return value - just examine sampleTimes instead + samplesSource->GetContributingSampleTimesForInterval( + startTime, endTime, &sampleTimes); + + // Not enough samples to reconstruct the shutter interval. + if (sampleTimes.size() < 2) { + // These fallback values are from the camera + return { shutterOpen, shutterClose }; + } + + const auto iteratorPair = + std::minmax_element(sampleTimes.begin(), + sampleTimes.end()); + return { *iteratorPair.first, *iteratorPair.second }; +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +/// \class _MotionBlurHelper +/// +/// Helper base class for motion blur. This class carries the implementations +/// for methods to retrieve motion blur parameters from the prim, to compute +/// contributing time samples, and to sample the given sampled data source. +/// This class encapsulates all the logic for transform, velocity, and +/// deformation motion blur. +/// +class _MotionBlurHelper +{ +public: + using Time = HdSampledDataSource::Time; + + /// samplesSource: the original data source + /// key: identifying name for samplesSource + /// primPath: path of sampleSource's parent prim (for diagnostics) + /// primType: type of sampleSource's parent prim + /// primvarsSource: data source for sampleSource's parent prim's primvars + /// inputArgs: data source from scene index plugin + _MotionBlurHelper( + const HdSampledDataSourceHandle& samplesSource, + const TfToken& key, + const SdfPath& primPath, + const TfToken& primType, + const HdContainerDataSourceHandle& primvarsSource, + const HdContainerDataSourceHandle& inputArgs) + : _samplesSource(samplesSource) + , _key(key) + , _primPath(primPath) + , _primType(primType) + , _primvarsSource(primvarsSource) + , _inputArgs(inputArgs) + { } + +protected: + bool + _GetContributingSampleTimesForInterval( + Time startTime, + Time endTime, + std::vector