forked from blender/blender
BLEN-326: Pass MaterialX to Hydra via hdMaterialNetwork #5
@ -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/*.*" )
|
||||
|
@ -86,4 +86,17 @@ set(LIB
|
||||
|
||||
blender_add_lib(bf_render_hydra "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
if(TARGET MaterialXCore AND TARGET MaterialXFormat)
|
||||
George-Shakula marked this conversation as resolved
|
||||
target_sources(bf_render_hydra PRIVATE
|
||||
sceneDelegate/mtlxHydraAdapter.h
|
||||
sceneDelegate/mtlxHydraAdapter.cc)
|
||||
target_compile_definitions(bf_render_hydra PRIVATE
|
||||
_MTLX_TRANSLATION_ENABLED)
|
||||
target_link_libraries(bf_render_hydra PRIVATE
|
||||
MaterialXCore
|
||||
MaterialXFormat)
|
||||
else()
|
||||
message(WARN "Compiling Hydra Scene Delegate without MaterialX-to-Hydra translation")
|
||||
endif()
|
||||
|
||||
add_dependencies(bf_render_hydra bf_rna)
|
||||
|
@ -343,7 +343,7 @@ VtValue BlenderSceneDelegate::GetMaterialResource(SdfPath const& id)
|
||||
{
|
||||
MaterialData *mat_data = material_data(id);
|
||||
if (mat_data) {
|
||||
return mat_data->material_resource();
|
||||
return mat_data->material_resource(this);
|
||||
}
|
||||
return VtValue();
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
@ -47,9 +49,24 @@ VtValue MaterialData::get_data(TfToken const &key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pxr::VtValue MaterialData::material_resource()
|
||||
pxr::VtValue MaterialData::material_resource(pxr::HdSceneDelegate *scene_delegate)
|
||||
{
|
||||
/* TODO: Implement return of HdMaterialNetwork */
|
||||
#if defined(_MTLX_TRANSLATION_ENABLED)
|
||||
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);
|
||||
}
|
||||
#else
|
||||
# pragma message("Compiling without MaterialX translation")
|
||||
#endif
|
||||
|
||||
return pxr::VtValue();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ class MaterialData: IdData {
|
||||
void remove_prim() override;
|
||||
void mark_prim_dirty(DirtyBits dirty_bits) override;
|
||||
|
||||
pxr::VtValue material_resource();
|
||||
pxr::VtValue material_resource(pxr::HdSceneDelegate *scene_delegate);
|
||||
George-Shakula marked this conversation as resolved
Bogdan Nagirniak
commented
`scene_delegate` is already available in MaterialData from IdData
|
||||
void export_mtlx();
|
||||
|
||||
private:
|
||||
|
@ -0,0 +1,86 @@
|
||||
/* 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
|
||||
|
||||
template<typename R> static bool _Read(UsdStagePtr stage, R &&reader)
|
||||
{
|
||||
try {
|
||||
auto doc = reader();
|
||||
if (doc) {
|
||||
UsdMtlxRead(doc, stage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (mx::ExceptionFoundCycle &x) {
|
||||
TF_RUNTIME_ERROR("MaterialX cycle found: %s\n", x.what());
|
||||
return false;
|
||||
}
|
||||
catch (mx::Exception &x) {
|
||||
TF_RUNTIME_ERROR("MaterialX error: %s\n", x.what());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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());
|
||||
auto stage = UsdStage::CreateInMemory(stageId, context);
|
||||
if (_Read(stage, [&mtlxPath]() { return UsdMtlxReadDocument(mtlxPath); })) {
|
||||
George-Shakula marked this conversation as resolved
Bogdan Nagirniak
commented
This part with 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.
|
||||
if (UsdPrim materials = stage->GetPrimAtPath(SdfPath("/MaterialX/Materials"))) {
|
||||
if (UsdPrimSiblingRange children = materials.GetChildren()) {
|
||||
if (auto material = UsdShadeMaterial(
|
||||
*children.begin())) { // TODO: specify which material to use from the mtlx
|
||||
if (UsdShadeShader mtlxSurface = material.ComputeSurfaceSource(renderContexts)) {
|
||||
BogdanNagirniak marked this conversation as resolved
Bogdan Nagirniak
commented
Change construction Change construction `if (...) if (...) .... ` to `if (!...) return; if (!...) return` as more understandable and easier to maintain.
|
||||
UsdImagingBuildHdMaterialNetworkFromTerminal(mtlxSurface.GetPrim(),
|
||||
HdMaterialTerminalTokens->surface,
|
||||
shaderSourceTypes,
|
||||
renderContexts,
|
||||
out,
|
||||
UsdTimeCode::Default());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PXR_NAMESPACE_CLOSE_SCOPE
|
24
source/blender/render/hydra/sceneDelegate/mtlxHydraAdapter.h
Normal file
24
source/blender/render/hydra/sceneDelegate/mtlxHydraAdapter.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MTLX_TRANSLATION_ENABLED)
|
||||
|
||||
# include <pxr/base/tf/token.h>
|
||||
# include <pxr/pxr.h>
|
||||
|
||||
# include <string>
|
||||
|
||||
PXR_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
struct HdMaterialNetworkMap;
|
||||
|
||||
void HdMtlxConvertToMaterialNetworkMap(std::string const &mtlxPath,
|
||||
BogdanNagirniak marked this conversation as resolved
Bogdan Nagirniak
commented
Can we move this function into MaterialData class as method? Can we move this function into MaterialData class as method?
George-Shakula
commented
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.
Bogdan Nagirniak
commented
I see, ok I see, ok
|
||||
TfTokenVector const &shaderSourceTypes,
|
||||
TfTokenVector const &renderContexts,
|
||||
HdMaterialNetworkMap *out);
|
||||
|
||||
PXR_NAMESPACE_CLOSE_SCOPE
|
||||
|
||||
#endif // _MTLX_TRANSLATION_ENABLED
|
@ -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
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
We expect that MaterialX is enabled for hydra_render project. Can be removed.