BLEN-326: Pass MaterialX to Hydra via hdMaterialNetwork #5

Merged
Bogdan Nagirniak merged 4 commits from George-Shakula/blender:mtlx-translation into hydra-render 2023-03-02 12:35:51 +01:00
7 changed files with 135 additions and 2 deletions

View File

@ -794,7 +794,7 @@ set(POSTCONFIGURE_SCRIPT "" CACHE FILEPATH "Run given CMake script as the last s
mark_as_advanced(POSTCONFIGURE_SCRIPT)
# USD Hydra plugin.
if(WIN32 AND WITH_USD)
if(WIN32 AND WITH_USD AND WITH_MATERIALX)
option(WITH_HYDRA "Enable USD Hydra plugin" ON)
endif()

View File

@ -899,6 +899,13 @@ if(WITH_USD)
endif()
endif()
if(WITH_MATERIALX)
windows_find_package(MaterialX)
if(NOT MaterialX_FOUND)
include("${LIBDIR}/MaterialX/lib/cmake/MaterialX/MaterialXTargets.cmake")
endif()
endif()
if(WINDOWS_PYTHON_DEBUG)
# Include the system scripts in the blender_python_system_scripts project.
file(GLOB_RECURSE inFiles "${CMAKE_SOURCE_DIR}/release/scripts/*.*" )

View File

@ -1,6 +1,10 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2011-2022 Blender Foundation
if(NOT TARGET MaterialXCore OR NOT TARGET MaterialXFormat)
message(FATAL_ERROR "Hydra Scene Delegate requires MaterialX")
endif()
if(WIN32)
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -DBOOST_DEBUG_PYTHON)
endif()
@ -70,6 +74,8 @@ set(SRC
sceneDelegate/material.cc
sceneDelegate/mesh.h
sceneDelegate/mesh.cc
sceneDelegate/mtlxHydraAdapter.h
sceneDelegate/mtlxHydraAdapter.cc
sceneDelegate/light.h
sceneDelegate/light.cc
sceneDelegate/world.h
@ -86,4 +92,8 @@ set(LIB
blender_add_lib(bf_render_hydra "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
target_link_libraries(bf_render_hydra PRIVATE
MaterialXCore
MaterialXFormat)
add_dependencies(bf_render_hydra bf_rna)

View File

@ -5,6 +5,7 @@
#include <pxr/imaging/hd/tokens.h>
#include <pxr/imaging/hd/material.h>
#include <pxr/imaging/hd/renderDelegate.h>
#include "glog/logging.h"
@ -12,6 +13,7 @@
#include "BKE_lib_id.h"
#include "material.h"
#include "mtlxHydraAdapter.h"
using namespace pxr;
@ -49,7 +51,18 @@ VtValue MaterialData::get_data(TfToken const &key)
pxr::VtValue MaterialData::material_resource()
{
/* TODO: Implement return of HdMaterialNetwork */
std::string const &path = mtlx_path.GetResolvedPath();
if (!path.empty()) {
HdRenderDelegate *render_delegate = scene_delegate->GetRenderIndex().GetRenderDelegate();
TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
HdMaterialNetworkMap material_network_map;
HdMtlxConvertToMaterialNetworkMap(
path, shader_source_types, render_contexts, &material_network_map);
return VtValue(material_network_map);
}
return pxr::VtValue();
}

View File

@ -0,0 +1,77 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "mtlxHydraAdapter.h"
#include <pxr/base/arch/fileSystem.h>
#include <pxr/usd/ar/resolver.h>
#include <pxr/usd/ar/resolverContextBinder.h>
#include <pxr/usd/ar/resolverScopedCache.h>
#include <pxr/usd/usdMtlx/reader.h>
#include <pxr/usd/usdMtlx/utils.h>
#include <pxr/usd/usdShade/material.h>
#include <pxr/usd/usdShade/shader.h>
#include <pxr/usdImaging/usdImaging/materialParamUtils.h>
#include <pxr/imaging/hd/material.h>
#include <pxr/imaging/hd/tokens.h>
namespace mx = MaterialX;
PXR_NAMESPACE_OPEN_SCOPE
void HdMtlxConvertToMaterialNetworkMap(std::string const &mtlxPath,
TfTokenVector const &shaderSourceTypes,
TfTokenVector const &renderContexts,
HdMaterialNetworkMap *out)
{
if (mtlxPath.empty()) {
return;
}
std::string basePath = TfGetPathName(mtlxPath);
ArResolver &resolver = ArGetResolver();
const ArResolverContext context = resolver.CreateDefaultContextForAsset(mtlxPath);
ArResolverContextBinder binder(context);
ArResolverScopedCache resolverCache;
std::string mtlxName = TfGetBaseName(mtlxPath);
std::string stageId = TfStringPrintf(
"%s%s%s.usda", basePath.c_str(), ARCH_PATH_SEP, mtlxName.c_str());
UsdStageRefPtr stage = UsdStage::CreateInMemory(stageId, context);
try {
mx::DocumentPtr doc = UsdMtlxReadDocument(mtlxPath);
UsdMtlxRead(doc, stage);
}
catch (mx::ExceptionFoundCycle &x) {
TF_RUNTIME_ERROR("MaterialX cycle found: %s\n", x.what());
return;
}
catch (mx::Exception &x) {
TF_RUNTIME_ERROR("MaterialX error: %s\n", x.what());
return;
}
if (UsdPrim materials = stage->GetPrimAtPath(SdfPath("/MaterialX/Materials"))) {
if (UsdPrimSiblingRange children = materials.GetChildren()) {
if (auto material = UsdShadeMaterial(*children.begin())) {
if (UsdShadeShader mtlxSurface = material.ComputeSurfaceSource(renderContexts)) {
UsdImagingBuildHdMaterialNetworkFromTerminal(mtlxSurface.GetPrim(),
HdMaterialTerminalTokens->surface,
shaderSourceTypes,
George-Shakula marked this conversation as resolved
Review

This part with _Read() and lambda function is hard to maintain in future + used in one place, can you move it content of _Read here.

This part with `_Read()` and lambda function is hard to maintain in future + used in one place, can you move it content of `_Read` here.
renderContexts,
out,
UsdTimeCode::Default());
}
}
BogdanNagirniak marked this conversation as resolved
Review

Change construction if (...) if (...) .... to if (!...) return; if (!...) return as more understandable and easier to maintain.

Change construction `if (...) if (...) .... ` to `if (!...) return; if (!...) return` as more understandable and easier to maintain.
}
}
}
PXR_NAMESPACE_CLOSE_SCOPE

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
#include <pxr/base/tf/token.h>
#include <pxr/pxr.h>
#include <string>
PXR_NAMESPACE_OPEN_SCOPE
struct HdMaterialNetworkMap;
void HdMtlxConvertToMaterialNetworkMap(std::string const &mtlxPath,
TfTokenVector const &shaderSourceTypes,
TfTokenVector const &renderContexts,
BogdanNagirniak marked this conversation as resolved
Review

Can we move this function into MaterialData class as method?

Can we move this function into MaterialData class as method?
Review

Yes, we can. One of the reasons it is in a separate file is that Brian wanted to have this feature separated from anything else for convenient sharing with others. By keeping it in its own files we ensure this is easily relocatable and not obscured by anything else.

Yes, we can. One of the reasons it is in a separate file is that Brian wanted to have this feature separated from anything else for convenient sharing with others. By keeping it in its own files we ensure this is easily relocatable and not obscured by anything else.
Review

I see, ok

I see, ok
HdMaterialNetworkMap *out);
PXR_NAMESPACE_CLOSE_SCOPE

View File

@ -980,6 +980,9 @@ elseif(WIN32)
${LIBDIR}/materialx/bin/MaterialXGenMdl.dll
${LIBDIR}/materialx/bin/MaterialXGenOsl.dll
${LIBDIR}/materialx/bin/MaterialXGenShader.dll
${LIBDIR}/materialx/bin/MaterialXRender.dll
${LIBDIR}/materialx/bin/MaterialXRenderHw.dll
${LIBDIR}/materialx/bin/MaterialXRenderGlsl.dll
RELEASE
)
windows_install_shared_manifest(
@ -990,6 +993,9 @@ elseif(WIN32)
${LIBDIR}/materialx/bin/MaterialXGenMdl_d.dll
${LIBDIR}/materialx/bin/MaterialXGenOsl_d.dll
${LIBDIR}/materialx/bin/MaterialXGenShader_d.dll
${LIBDIR}/materialx/bin/MaterialXRender_d.dll
${LIBDIR}/materialx/bin/MaterialXRenderHw_d.dll
${LIBDIR}/materialx/bin/MaterialXRenderGlsl_d.dll
DEBUG
)