Skip to content

Commit

Permalink
Complete OSL implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
JGamache-autodesk committed Jul 4, 2024
1 parent f20acdd commit 46f8455
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 46 deletions.
45 changes: 45 additions & 0 deletions libraries/stdlib/genosl/lib/vector4_extra_ops.osl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Adds some syntactic sugar allowing mixing vector4 and color4 as
// arguments of some binary operators used by OCIO transform code.

vector4 __operator__mul__(matrix m, vector4 v)
{
return vector4(v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3],
v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3],
v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2] + v.w * m[2][3],
v.x * m[3][0] + v.y * m[3][1] + v.z * m[3][2] + v.w * m[3][3]);
}

vector4 __operator__mul__(color4 c, vector4 v)
{
return vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a) * v;
}

vector4 __operator__mul__(vector4 v, color4 c)
{
return v * vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a);
}

vector4 __operator__sub__(color4 c, vector4 v)
{
return vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a) - v;
}

vector4 __operator__add__(vector4 v, color4 c)
{
return v + vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a);
}

vector4 __operator__add__(color4 c, vector4 v)
{
return vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a) + v;
}

vector4 pow(color4 c, vector4 v)
{
return pow(vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a), v);
}

vector4 max(vector4 v, color4 c)
{
return max(v, vector4(c.rgb.r, c.rgb.g, c.rgb.b, c.a));
}
16 changes: 3 additions & 13 deletions source/MaterialXGenShader/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")

set(optionalLibraries "")

if(MATERIALX_BUILD_OCIO)
find_package(OpenColorIO REQUIRED)
list(APPEND optionalLibraries OpenColorIO::OpenColorIO)
endif()

mx_add_library(MaterialXGenShader
SOURCE_FILES
${materialx_source}
Expand All @@ -16,14 +9,11 @@ mx_add_library(MaterialXGenShader
LIBRARIES
MaterialXFormat
MaterialXCore
${optionalLibraries}
EXPORT_DEFINE
MATERIALX_GENSHADER_EXPORTS)

if(MATERIALX_BUILD_OCIO)
if (NOT MATERIALX_BUILD_MONOLITHIC)
target_compile_definitions(MaterialXGenShader PUBLIC MATERIALX_BUILD_OCIO)
else()
target_compile_definitions(${MATERIALX_MONOLITHIC_TARGET} PUBLIC MATERIALX_BUILD_OCIO)
endif()
find_package(OpenColorIO REQUIRED)
target_link_libraries(${TARGET_NAME} OpenColorIO::OpenColorIO)
target_compile_definitions(${TARGET_NAME} PUBLIC MATERIALX_BUILD_OCIO)
endif()
118 changes: 88 additions & 30 deletions source/MaterialXGenShader/Nodes/OpenColorIONode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace
{
// Internal OCIO strings:
constexpr const char OCIO_COLOR3[] = "color3";
constexpr const char COLOR4_SUFFIX[] = "_color4_temp";

// Lengths where needed:
constexpr auto OCIO_COLOR3_LEN = sizeof(OCIO_COLOR3) / sizeof(OCIO_COLOR3[0]);
Expand Down Expand Up @@ -62,12 +63,19 @@ void OpenColorIONode::emitFunctionDefinition(
OCIO::GpuShaderDescRcPtr shaderDesc = OCIO::GpuShaderDesc::CreateShaderDesc();

// TODO: Extend to essl and MDL and possibly SLang.
if (context.getShaderGenerator().getTarget() == "genglsl") {
bool isOSL = false;
if (context.getShaderGenerator().getTarget() == "genglsl")
{
shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_GLSL_4_0);
} else if (context.getShaderGenerator().getTarget() == "genmsl") {
}
else if (context.getShaderGenerator().getTarget() == "genmsl")
{
shaderDesc->setLanguage(OCIO::GPU_LANGUAGE_MSL_2_0);
} else if (context.getShaderGenerator().getTarget() == "genosl") {
}
else if (context.getShaderGenerator().getTarget() == "genosl")
{
shaderDesc->setLanguage(OCIO::LANGUAGE_OSL_1);
isOSL = true;
}

auto functionName = getFunctionName();
Expand All @@ -76,7 +84,26 @@ void OpenColorIONode::emitFunctionDefinition(

gpuProcessor->extractGpuShaderInfo(shaderDesc);

stage.addString(shaderDesc->getShaderText());
string shaderText = shaderDesc->getShaderText();

// For OSL, we need to extract the function from the shader OCIO creates.
if (isOSL)
{
const ShaderGenerator& shadergen = context.getShaderGenerator();
shadergen.emitLibraryInclude("stdlib/genosl/lib/vector4_extra_ops.osl", context, stage);
shadergen.emitLineBreak(stage);
auto startpos = shaderText.find(string{"color4 "} + shaderDesc->getFunctionName());
if (startpos != string::npos)
{
auto endpos = shaderText.find(string{"outColor = "} + shaderDesc->getFunctionName(), startpos);
if (endpos != string::npos)
{
shaderText = shaderText.substr(startpos, endpos - startpos);
}
}
}

stage.addString(shaderText);
stage.endLine(false);
}
}
Expand All @@ -91,47 +118,78 @@ void OpenColorIONode::emitFunctionCall(
auto functionName = getFunctionName();

// TODO: Adjust syntax for other languages.

// The OCIO function uses a vec4 parameter, so:
// Function call for color4: vec4 res = func(in);
// Function call for color3: vec3 res = func(vec4(in, 1.0)).rgb;
// TODO: Handle LUT samplers.
bool isColor3 = getName().back() == '3';
const bool isColor3 = getName().back() == '3';

const auto& shadergen = context.getShaderGenerator();
shadergen.emitLineBegin(stage);

const auto* output = node.getOutput();
const auto* colorInput = node.getInput(0);

shadergen.emitOutput(output, true, false, context, stage);
shadergen.emitString(" = ", stage);

shadergen.emitString(functionName + "(", stage);
if (isColor3)
if (context.getShaderGenerator().getTarget() == "genosl")
{
if (context.getShaderGenerator().getTarget() == "genglsl") {
shadergen.emitString("vec4(", stage);
} else if (context.getShaderGenerator().getTarget() == "genmsl") {
shadergen.emitString("float4(", stage);
} else if (context.getShaderGenerator().getTarget() == "genosl") {
shadergen.emitString("color4(", stage);
// For OSL, since swizzling the output of a function is not allowed, we need:
// Function call for color4: color4 res = func(in);
// Function call for color3:
// color4 res_color4 = func(color4(in, 1.0));
// color res = res_color4.rgb;
if (isColor3)
{
shadergen.emitString("color4 " + output->getVariable() + COLOR4_SUFFIX + " = ", stage);
shadergen.emitString(functionName + "(color4(", stage);
shadergen.emitInput(colorInput, context, stage);
shadergen.emitString(", 1.0))", stage);
shadergen.emitLineEnd(stage);
shadergen.emitLineBegin(stage);
shadergen.emitOutput(output, true, false, context, stage);
shadergen.emitString(" = " + output->getVariable() + COLOR4_SUFFIX + ".rgb", stage);
shadergen.emitLineEnd(stage);
}
else
{
shadergen.emitOutput(output, true, false, context, stage);
shadergen.emitString(" = ", stage);
shadergen.emitString(functionName + "(", stage);
shadergen.emitInput(colorInput, context, stage);
shadergen.emitString(")", stage);
shadergen.emitLineEnd(stage);
}
}
shadergen.emitInput(colorInput, context, stage);
if (isColor3)
else
{
shadergen.emitString(", 1.0)", stage);
}
// The OCIO function uses a vec4 parameter, so:
// Function call for color4: vec4 res = func(in);
// Function call for color3: vec3 res = func(vec4(in, 1.0)).rgb;
shadergen.emitOutput(output, true, false, context, stage);
shadergen.emitString(" = ", stage);

shadergen.emitString(functionName + "(", stage);
if (isColor3)
{
if (context.getShaderGenerator().getTarget() == "genglsl")
{
shadergen.emitString("vec4(", stage);
}
else if (context.getShaderGenerator().getTarget() == "genmsl")
{
shadergen.emitString("float4(", stage);
}
}
shadergen.emitInput(colorInput, context, stage);
if (isColor3)
{
shadergen.emitString(", 1.0)", stage);
}

shadergen.emitString(")", stage);
shadergen.emitString(")", stage);

if (isColor3)
{
shadergen.emitString(".rgb", stage);
if (isColor3)
{
shadergen.emitString(".rgb", stage);
}
shadergen.emitLineEnd(stage);
}

shadergen.emitLineEnd(stage);
}
}

Expand Down
8 changes: 5 additions & 3 deletions source/MaterialXGenShader/OpenColorIOManagementSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ const std::map<string, string> COLOR_SPACE_REMAP = {

OpenColorIOManagementSystemPtr OpenColorIOManagementSystem::create(const OCIO::ConstConfigRcPtr& config, const string& target)
{
if (target != "genglsl" && target != "genmsl" && target != "genosl") {
if (target != "genglsl" && target != "genmsl" && target != "genosl")
{
throw std::runtime_error("OCIO does not support this target");
}

Expand Down Expand Up @@ -166,7 +167,8 @@ bool OpenColorIOManagementSystem::hasImplementation(const string& implName) cons

ShaderNodeImplPtr OpenColorIOManagementSystem::createImplementation(const string& implName) const
{
if (_implementations.count(implName)) {
if (_implementations.count(implName))
{
return OpenColorIONode::create();
}
return {};
Expand All @@ -180,4 +182,4 @@ OCIO::ConstGPUProcessorRcPtr OpenColorIOManagementSystem::getGpuProcessor(const
}

MATERIALX_NAMESPACE_END
#endif
#endif

0 comments on commit 46f8455

Please sign in to comment.