Cycles: Add support for "stageMetersPerUnit" Hydra render setting
This can be useful to match transforms to what native Cycles would see in Blender, as USD typically uses centimeters, but Blender uses meters. This patch also fixes the hardcoded focal length multiplicator, which is now using the same units as everything else. Default of "stageMetersPerUnit" is 0.01 to match the USD default of centimeters. Differential Revision: https://developer.blender.org/D14630
This commit is contained in:
parent
3a88f151c4
commit
c31b89e76e
|
@ -3,6 +3,7 @@
|
|||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/camera.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/camera.h"
|
||||
|
||||
#include <pxr/base/gf/frustum.h>
|
||||
|
@ -12,6 +13,19 @@
|
|||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
extern Transform convert_transform(const GfMatrix4d &matrix);
|
||||
Transform convert_camera_transform(const GfMatrix4d &matrix, float metersPerUnit)
|
||||
{
|
||||
Transform t = convert_transform(matrix);
|
||||
// Flip Z axis
|
||||
t.x.z *= -1.0f;
|
||||
t.y.z *= -1.0f;
|
||||
t.z.z *= -1.0f;
|
||||
// Scale translation
|
||||
t.x.w *= metersPerUnit;
|
||||
t.y.w *= metersPerUnit;
|
||||
t.z.w *= metersPerUnit;
|
||||
return t;
|
||||
}
|
||||
|
||||
#if PXR_VERSION < 2102
|
||||
// clang-format off
|
||||
|
@ -61,13 +75,20 @@ void HdCyclesCamera::Sync(HdSceneDelegate *sceneDelegate,
|
|||
if (*dirtyBits & DirtyBits::DirtyTransform) {
|
||||
sceneDelegate->SampleTransform(id, &_transformSamples);
|
||||
|
||||
bool transform_found = false;
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i) {
|
||||
if (_transformSamples.times[i] == 0.0f) {
|
||||
_transform = _transformSamples.values[i];
|
||||
_data.SetTransform(_transform);
|
||||
transform_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!transform_found && _transformSamples.count) {
|
||||
_transform = _transformSamples.values[0];
|
||||
_data.SetTransform(_transform);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (*dirtyBits & DirtyBits::DirtyViewMatrix) {
|
||||
|
@ -236,18 +257,21 @@ void HdCyclesCamera::Finalize(HdRenderParam *renderParam)
|
|||
HdCamera::Finalize(renderParam);
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(Camera *cam) const
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam, Camera *cam) const
|
||||
{
|
||||
ApplyCameraSettings(_data, _windowPolicy, cam);
|
||||
ApplyCameraSettings(renderParam, _data, _windowPolicy, cam);
|
||||
|
||||
const float metersPerUnit = static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
array<Transform> motion(_transformSamples.count);
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i)
|
||||
motion[i] = convert_transform(_transformSamples.values[i]) *
|
||||
transform_scale(1.0f, 1.0f, -1.0f);
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i) {
|
||||
motion[i] = convert_camera_transform(_transformSamples.values[i], metersPerUnit);
|
||||
}
|
||||
cam->set_motion(motion);
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(const GfCamera &dataUnconformedWindow,
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam,
|
||||
const GfCamera &dataUnconformedWindow,
|
||||
CameraUtilConformWindowPolicy windowPolicy,
|
||||
Camera *cam)
|
||||
{
|
||||
|
@ -261,20 +285,22 @@ void HdCyclesCamera::ApplyCameraSettings(const GfCamera &dataUnconformedWindow,
|
|||
GfCamera::Orthographic == CAMERA_ORTHOGRAPHIC);
|
||||
cam->set_camera_type(static_cast<CameraType>(data.GetProjection()));
|
||||
|
||||
const float metersPerUnit = static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
auto viewplane = data.GetFrustum().GetWindow();
|
||||
auto focalLength = 1.0f;
|
||||
if (data.GetProjection() == GfCamera::Perspective) {
|
||||
viewplane *= 2.0 / viewplane.GetSize()[1]; // Normalize viewplane
|
||||
focalLength = data.GetFocalLength() * 1e-3f;
|
||||
focalLength = data.GetFocalLength() * GfCamera::FOCAL_LENGTH_UNIT * metersPerUnit;
|
||||
|
||||
cam->set_fov(GfDegreesToRadians(data.GetFieldOfView(GfCamera::FOVVertical)));
|
||||
}
|
||||
|
||||
cam->set_sensorwidth(data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT);
|
||||
cam->set_sensorheight(data.GetVerticalAperture() * GfCamera::APERTURE_UNIT);
|
||||
cam->set_sensorwidth(data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT * metersPerUnit);
|
||||
cam->set_sensorheight(data.GetVerticalAperture() * GfCamera::APERTURE_UNIT * metersPerUnit);
|
||||
|
||||
cam->set_nearclip(data.GetClippingRange().GetMin());
|
||||
cam->set_farclip(data.GetClippingRange().GetMax());
|
||||
cam->set_nearclip(data.GetClippingRange().GetMin() * metersPerUnit);
|
||||
cam->set_farclip(data.GetClippingRange().GetMax() * metersPerUnit);
|
||||
|
||||
cam->set_viewplane_left(viewplane.GetMin()[0]);
|
||||
cam->set_viewplane_right(viewplane.GetMax()[0]);
|
||||
|
@ -282,14 +308,15 @@ void HdCyclesCamera::ApplyCameraSettings(const GfCamera &dataUnconformedWindow,
|
|||
cam->set_viewplane_top(viewplane.GetMax()[1]);
|
||||
|
||||
if (data.GetFStop() != 0.0f) {
|
||||
cam->set_focaldistance(data.GetFocusDistance());
|
||||
cam->set_focaldistance(data.GetFocusDistance() * metersPerUnit);
|
||||
cam->set_aperturesize(focalLength / (2.0f * data.GetFStop()));
|
||||
}
|
||||
|
||||
cam->set_matrix(convert_transform(data.GetTransform()) * transform_scale(1.0f, 1.0f, -1.0f));
|
||||
cam->set_matrix(convert_camera_transform(data.GetTransform(), metersPerUnit));
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(const GfMatrix4d &worldToViewMatrix,
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam,
|
||||
const GfMatrix4d &worldToViewMatrix,
|
||||
const GfMatrix4d &projectionMatrix,
|
||||
const std::vector<GfVec4d> &clipPlanes,
|
||||
Camera *cam)
|
||||
|
@ -298,7 +325,7 @@ void HdCyclesCamera::ApplyCameraSettings(const GfMatrix4d &worldToViewMatrix,
|
|||
GfCamera data;
|
||||
data.SetFromViewAndProjectionMatrix(worldToViewMatrix, projectionMatrix);
|
||||
|
||||
ApplyCameraSettings(data, CameraUtilFit, cam);
|
||||
ApplyCameraSettings(renderParam, data, CameraUtilFit, cam);
|
||||
#else
|
||||
TF_CODING_ERROR("Not implemented");
|
||||
#endif
|
||||
|
|
|
@ -17,12 +17,14 @@ class HdCyclesCamera final : public PXR_NS::HdCamera {
|
|||
HdCyclesCamera(const PXR_NS::SdfPath &sprimId);
|
||||
~HdCyclesCamera() override;
|
||||
|
||||
void ApplyCameraSettings(CCL_NS::Camera *targetCamera) const;
|
||||
void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam, CCL_NS::Camera *targetCamera) const;
|
||||
|
||||
static void ApplyCameraSettings(const PXR_NS::GfCamera &cameraData,
|
||||
static void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam,
|
||||
const PXR_NS::GfCamera &cameraData,
|
||||
PXR_NS::CameraUtilConformWindowPolicy windowPolicy,
|
||||
CCL_NS::Camera *targetCamera);
|
||||
static void ApplyCameraSettings(const PXR_NS::GfMatrix4d &worldToViewMatrix,
|
||||
static void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam,
|
||||
const PXR_NS::GfMatrix4d &worldToViewMatrix,
|
||||
const PXR_NS::GfMatrix4d &projectionMatrix,
|
||||
const std::vector<PXR_NS::GfVec4d> &clipPlanes,
|
||||
CCL_NS::Camera *targetCamera);
|
||||
|
|
|
@ -153,7 +153,11 @@ void HdCyclesGeometry<Base, CyclesBase>::Sync(HdSceneDelegate *sceneDelegate,
|
|||
|
||||
// Update transforms of all instances
|
||||
for (size_t i = 0; i < transforms.size(); ++i) {
|
||||
const Transform tfm = convert_transform(_geomTransform * transforms[i]);
|
||||
const float metersPerUnit =
|
||||
static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
const Transform tfm = transform_scale(make_float3(metersPerUnit)) *
|
||||
convert_transform(_geomTransform * transforms[i]);
|
||||
_instances[i]->set_tfm(tfm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,11 +54,16 @@ void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
|
|||
const SdfPath &id = GetId();
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyTransform) {
|
||||
const float metersPerUnit =
|
||||
static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
const Transform tfm = transform_scale(make_float3(metersPerUnit)) *
|
||||
#if PXR_VERSION >= 2011
|
||||
const Transform tfm = convert_transform(sceneDelegate->GetTransform(id));
|
||||
convert_transform(sceneDelegate->GetTransform(id));
|
||||
#else
|
||||
const Transform tfm = convert_transform(
|
||||
sceneDelegate->GetLightParamValue(id, HdTokens->transform).Get<GfMatrix4d>());
|
||||
convert_transform(
|
||||
sceneDelegate->GetLightParamValue(id, HdTokens->transform)
|
||||
.Get<GfMatrix4d>());
|
||||
#endif
|
||||
_light->set_tfm(tfm);
|
||||
|
||||
|
|
|
@ -33,11 +33,12 @@ TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
|||
);
|
||||
|
||||
TF_DEFINE_PRIVATE_TOKENS(HdCyclesRenderSettingsTokens,
|
||||
(stageMetersPerUnit)
|
||||
((device, "cycles:device"))
|
||||
((threads, "cycles:threads"))
|
||||
((time_limit, "cycles:time_limit"))
|
||||
((timeLimit, "cycles:time_limit"))
|
||||
((samples, "cycles:samples"))
|
||||
((sample_offset, "cycles:sample_offset"))
|
||||
((sampleOffset, "cycles:sample_offset"))
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
|
@ -424,7 +425,7 @@ HdRenderSettingDescriptorList HdCyclesDelegate::GetRenderSettingDescriptors() co
|
|||
|
||||
descriptors.push_back({
|
||||
"Time Limit",
|
||||
HdCyclesRenderSettingsTokens->time_limit,
|
||||
HdCyclesRenderSettingsTokens->timeLimit,
|
||||
VtValue(0.0),
|
||||
});
|
||||
descriptors.push_back({
|
||||
|
@ -434,7 +435,7 @@ HdRenderSettingDescriptorList HdCyclesDelegate::GetRenderSettingDescriptors() co
|
|||
});
|
||||
descriptors.push_back({
|
||||
"Sample Offset",
|
||||
HdCyclesRenderSettingsTokens->sample_offset,
|
||||
HdCyclesRenderSettingsTokens->sampleOffset,
|
||||
VtValue(0),
|
||||
});
|
||||
|
||||
|
@ -452,7 +453,11 @@ void HdCyclesDelegate::SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS
|
|||
Scene *const scene = _renderParam->session->scene;
|
||||
Session *const session = _renderParam->session;
|
||||
|
||||
if (key == HdCyclesRenderSettingsTokens->time_limit) {
|
||||
if (key == HdCyclesRenderSettingsTokens->stageMetersPerUnit) {
|
||||
_renderParam->SetStageMetersPerUnit(
|
||||
VtValue::Cast<double>(value).GetWithDefault(_renderParam->GetStageMetersPerUnit()));
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->timeLimit) {
|
||||
session->set_time_limit(
|
||||
VtValue::Cast<double>(value).GetWithDefault(session->params.time_limit));
|
||||
}
|
||||
|
@ -462,7 +467,7 @@ void HdCyclesDelegate::SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS
|
|||
samples = std::min(std::max(1, samples), max_samples);
|
||||
session->set_samples(samples);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
|
||||
else if (key == HdCyclesRenderSettingsTokens->sampleOffset) {
|
||||
session->params.sample_offset = VtValue::Cast<int>(value).GetWithDefault(
|
||||
session->params.sample_offset);
|
||||
++_settingsVersion;
|
||||
|
@ -484,19 +489,22 @@ VtValue HdCyclesDelegate::GetRenderSetting(const TfToken &key) const
|
|||
Scene *const scene = _renderParam->session->scene;
|
||||
Session *const session = _renderParam->session;
|
||||
|
||||
if (key == HdCyclesRenderSettingsTokens->device) {
|
||||
if (key == HdCyclesRenderSettingsTokens->stageMetersPerUnit) {
|
||||
return VtValue(_renderParam->GetStageMetersPerUnit());
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->device) {
|
||||
return VtValue(TfToken(Device::string_from_type(session->params.device.type)));
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->threads) {
|
||||
return VtValue(session->params.threads);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->time_limit) {
|
||||
else if (key == HdCyclesRenderSettingsTokens->timeLimit) {
|
||||
return VtValue(session->params.time_limit);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->samples) {
|
||||
return VtValue(session->params.samples);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
|
||||
else if (key == HdCyclesRenderSettingsTokens->sampleOffset) {
|
||||
return VtValue(session->params.sample_offset);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -117,10 +117,11 @@ void HdCyclesRenderPass::_Execute(const HdRenderPassStateSharedPtr &renderPassSt
|
|||
#endif
|
||||
|
||||
if (const auto camera = static_cast<const HdCyclesCamera *>(renderPassState->GetCamera())) {
|
||||
camera->ApplyCameraSettings(scene->camera);
|
||||
camera->ApplyCameraSettings(_renderParam, scene->camera);
|
||||
}
|
||||
else {
|
||||
HdCyclesCamera::ApplyCameraSettings(renderPassState->GetWorldToViewMatrix(),
|
||||
HdCyclesCamera::ApplyCameraSettings(_renderParam,
|
||||
renderPassState->GetWorldToViewMatrix(),
|
||||
renderPassState->GetProjectionMatrix(),
|
||||
renderPassState->GetClipPlanes(),
|
||||
scene->camera);
|
||||
|
|
|
@ -29,6 +29,16 @@ class HdCyclesSession final : public PXR_NS::HdRenderParam {
|
|||
|
||||
void UpdateScene();
|
||||
|
||||
double GetStageMetersPerUnit() const
|
||||
{
|
||||
return _stageMetersPerUnit;
|
||||
}
|
||||
|
||||
void SetStageMetersPerUnit(double stageMetersPerUnit)
|
||||
{
|
||||
_stageMetersPerUnit = stageMetersPerUnit;
|
||||
}
|
||||
|
||||
PXR_NS::HdRenderPassAovBinding GetDisplayAovBinding() const
|
||||
{
|
||||
return _displayAovBinding;
|
||||
|
@ -52,6 +62,7 @@ class HdCyclesSession final : public PXR_NS::HdRenderParam {
|
|||
|
||||
private:
|
||||
const bool _ownCyclesSession;
|
||||
double _stageMetersPerUnit = 0.01;
|
||||
PXR_NS::HdRenderPassAovBindingVector _aovBindings;
|
||||
PXR_NS::HdRenderPassAovBinding _displayAovBinding;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue