Skip to content

Commit

Permalink
Merge pull request #6249 from boberfly/features/cyclesUSDLightSchema
Browse files Browse the repository at this point in the history
GafferUSD : Added Cycles-specific light parameters to USD Lux lights
  • Loading branch information
murraystevenson authored Feb 25, 2025
2 parents fc7a7ee + affe111 commit e47c979
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 38 deletions.
5 changes: 5 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
1.5.x.x (relative to 1.5.6.0)
=======

Features
--------

- USDLight : Added Cycles-specific light parameters.

Improvements
------------

Expand Down
10 changes: 10 additions & 0 deletions src/GafferCycles/IECoreCyclesPreview/ShaderNetworkAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,8 @@ const InternedString g_widthParameter( "width" );
const InternedString g_wrapSParameter( "wrapS" );
const InternedString g_wrapTParameter( "wrapT" );

const string g_cyclesNamespace( "cycles:" );

void transferUSDLightParameters( ShaderNetwork *network, InternedString shaderHandle, const Shader *usdShader, Shader *shader )
{
Color3f color = parameterValue( usdShader, g_colorParameter, Color3f( 1 ) );
Expand All @@ -967,6 +969,14 @@ void transferUSDLightParameters( ShaderNetwork *network, InternedString shaderHa
shader->parameters()[g_useGlossyParameter] = new BoolData( specular > 0.0f );

shader->parameters()[g_useMISParameter] = new BoolData( true );

for( const auto &[name, value] : usdShader->parameters() )
{
if( boost::starts_with( name.string(), g_cyclesNamespace ) )
{
shader->parameters()[name.string().substr(g_cyclesNamespace.size())] = value;
}
}
}

void transferUSDShapingParameters( ShaderNetwork *network, InternedString shaderHandle, const Shader *usdShader, Shader *shader )
Expand Down
53 changes: 53 additions & 0 deletions startup/GafferUSD/cyclesLights.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
##########################################################################
#
# Copyright (c) 2025, Alex Fuller. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided with
# the distribution.
#
# * Neither the name of John Haddon nor the names of
# any other contributors to this software may be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import pathlib

from pxr import Plug

# Register a USD plugin that adds Cycles-specific auto-apply schemas for
# UsdLux lights. We deliberately don't add this to the `PXR_PLUGINPATH_NAME`
# search path because we don't want it to be loaded in any third-party
# applications that Gaffer might launch as subprocessses. So instead we
# register it manually with `RegisterPlugins`. See `GafferCycles.usda`
# for more details.

try :
import GafferCycles
Plug.Registry().RegisterPlugins( str( pathlib.Path( GafferCycles.__file__ ).parents[2] / "plugin" / "GafferCycles" / "plugInfo.json" ) )
except ImportError :
# GafferCycles not available
pass
88 changes: 50 additions & 38 deletions startup/gui/lightEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,44 @@
import Gaffer
import GafferSceneUI

# UsdLux lights

Gaffer.Metadata.registerValue( GafferSceneUI.LightEditor.Settings, "attribute", "preset:USD", "light" )

GafferSceneUI.LightEditor.registerParameter( "light", "color" )
GafferSceneUI.LightEditor.registerParameter( "light", "intensity" )
GafferSceneUI.LightEditor.registerParameter( "light", "exposure" )
GafferSceneUI.LightEditor.registerParameter( "light", "colorTemperature" )
GafferSceneUI.LightEditor.registerParameter( "light", "enableColorTemperature" )
GafferSceneUI.LightEditor.registerParameter( "light", "normalize" )
GafferSceneUI.LightEditor.registerParameter( "light", "diffuse" )
GafferSceneUI.LightEditor.registerParameter( "light", "specular" )

GafferSceneUI.LightEditor.registerParameter( "light", "width", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "height", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "radius", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "treatAsPoint", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "length", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "treatAsLine", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "angle", "Geometry" )

GafferSceneUI.LightEditor.registerParameter( "light", "texture:file", "Texture" )
GafferSceneUI.LightEditor.registerParameter( "light", "texture:format", "Texture" )

GafferSceneUI.LightEditor.registerParameter( "light", "shaping:cone:angle", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:cone:softness", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:focus", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:focusTint", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:ies:file", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:ies:angleScale", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:ies:normalize", "Shaping" )

GafferSceneUI.LightEditor.registerParameter( "light", "shadow:enable", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:color", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:distance", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:falloff", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:falloffGamma", "Shadow" )

if os.environ.get( "CYCLES_ROOT" ) and os.environ.get( "GAFFERCYCLES_HIDE_UI", "" ) != "1" :

Gaffer.Metadata.registerValue( GafferSceneUI.LightEditor.Settings, "attribute", "preset:Cycles", "cycles:light" )
Expand All @@ -65,6 +103,18 @@

Gaffer.Metadata.registerValue( GafferSceneUI.LightEditor.Settings, "attribute", "userDefault", "cycles:light" )

# Register Cycles-specific parameters for USD lights.
for parameter in [
"lightgroup",
"use_mis", "use_camera", "use_diffuse", "use_glossy", "use_transmission", "use_scatter", "use_caustics",
"spread", "map_resolution", "max_bounces"
] :
GafferSceneUI.LightEditor.registerParameter(
"light", f"cycles:{parameter}", "Cycles",
columnName = parameter.replace( "cycles:", "" )
)


with IECore.IgnoredExceptions( ImportError ) :

# This import appears unused, but it is intentional; it prevents us from
Expand Down Expand Up @@ -92,44 +142,6 @@
Gaffer.Metadata.registerValue( GafferSceneUI.LightEditor.Settings, "attribute", "userDefault", "osl:light" )


# UsdLux lights

Gaffer.Metadata.registerValue( GafferSceneUI.LightEditor.Settings, "attribute", "preset:USD", "light" )

GafferSceneUI.LightEditor.registerParameter( "light", "color" )
GafferSceneUI.LightEditor.registerParameter( "light", "intensity" )
GafferSceneUI.LightEditor.registerParameter( "light", "exposure" )
GafferSceneUI.LightEditor.registerParameter( "light", "colorTemperature" )
GafferSceneUI.LightEditor.registerParameter( "light", "enableColorTemperature" )
GafferSceneUI.LightEditor.registerParameter( "light", "normalize" )
GafferSceneUI.LightEditor.registerParameter( "light", "diffuse" )
GafferSceneUI.LightEditor.registerParameter( "light", "specular" )

GafferSceneUI.LightEditor.registerParameter( "light", "width", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "height", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "radius", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "treatAsPoint", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "length", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "treatAsLine", "Geometry" )
GafferSceneUI.LightEditor.registerParameter( "light", "angle", "Geometry" )

GafferSceneUI.LightEditor.registerParameter( "light", "texture:file", "Texture" )
GafferSceneUI.LightEditor.registerParameter( "light", "texture:format", "Texture" )

GafferSceneUI.LightEditor.registerParameter( "light", "shaping:cone:angle", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:cone:softness", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:focus", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:focusTint", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:ies:file", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:ies:angleScale", "Shaping" )
GafferSceneUI.LightEditor.registerParameter( "light", "shaping:ies:normalize", "Shaping" )

GafferSceneUI.LightEditor.registerParameter( "light", "shadow:enable", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:color", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:distance", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:falloff", "Shadow" )
GafferSceneUI.LightEditor.registerParameter( "light", "shadow:falloffGamma", "Shadow" )

# Arnold lights

with IECore.IgnoredExceptions( ImportError ) :
Expand Down
13 changes: 13 additions & 0 deletions startup/gui/usd.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#
##########################################################################

import os
import Gaffer
import GafferUSD

Expand All @@ -54,3 +55,15 @@
"samples", "volume_samples", "resolution"
] ) :
Gaffer.Metadata.registerValue( GafferUSD.USDLight, f"parameters.arnold:{parameter}", "layout:index", 1000 + i )

# Change Cycles ordering.
for i, parameter in enumerate( [
"lightgroup",
"use_mis", "use_camera", "use_diffuse", "use_glossy", "use_transmission", "use_scatter", "use_caustics",
"spread", "map_resolution", "max_bounces"
] ) :
Gaffer.Metadata.registerValue( GafferUSD.USDLight, f"parameters.cycles:{parameter}", "layout:index", 2000 + i )

# Only show the Cycles parameters if Cycles exists and not hidden
Gaffer.Metadata.registerValue( GafferUSD.USDLight, "parameters", "layout:activator:cyclesUIEnabled", lambda x : os.environ.get( "CYCLES_ROOT" ) and os.environ.get( "GAFFERCYCLES_HIDE_UI", "" ) != "1" )
Gaffer.Metadata.registerValue( GafferUSD.USDLight, "parameters.cycles:*", "layout:visibilityActivator", "cyclesUIEnabled" )
130 changes: 130 additions & 0 deletions usdSchemas/GafferCycles.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#usda 1.0
(
subLayers = [
@usdLux/schema.usda@,
@usd/schema.usda@
]
)

over "GLOBAL" (
customData = {
string libraryName = "GafferCycles"
bool skipCodeGeneration = 1
bool useLiteralIdentifier = 1
}
)
{
}

# Here we define a bunch of codeless auto-apply API schemas for extending the
# standard UsdLux lights with inputs specific to Cycles. This approach is
# modelled on the one used by UsdRiPxr to add RenderMan-specific inputs, and
# we believe is the one Pixar intends everyone to use.

class "GafferCyclesLightAPI" (
customData = {
token[] apiSchemaAutoApplyTo = [ "DistantLight", "DiskLight", "DomeLight", "RectLight", "SphereLight" ]
string apiSchemaType = "singleApply"
string className = "GafferCyclesLightAPI"
}
inherits = </APISchemaBase>
)
{

string inputs:cycles:lightgroup = "" (
displayGroup = "Basic"
displayName = "Light Group (Cycles)"
)

bool inputs:cycles:use_mis = true (
displayGroup = "Refine"
displayName = "MIS (Cycles)"
)

bool inputs:cycles:use_camera = true (
displayGroup = "Refine"
displayName = "Camera (Cycles)"
)

bool inputs:cycles:use_diffuse = true (
displayGroup = "Refine"
displayName = "Diffuse (Cycles)"
)

bool inputs:cycles:use_glossy = true (
displayGroup = "Refine"
displayName = "Glossy (Cycles)"
)

bool inputs:cycles:use_transmission = true (
displayGroup = "Refine"
displayName = "Transmission (Cycles)"
)

bool inputs:cycles:use_scatter = true (
displayGroup = "Refine"
displayName = "Volume Scatter (Cycles)"
)

bool inputs:cycles:use_caustics = false (
displayGroup = "Refine"
displayName = "Shadow Caustics (Cycles)"
)

int inputs:cycles:max_bounces = 1024 (
displayGroup = "Refine"
displayName = "Max Bounces (Cycles)"
)

}

class "GafferCyclesDiskLightAPI" (
customData = {
token[] apiSchemaAutoApplyTo = ["DiskLight"]
string apiSchemaType = "singleApply"
string className = "GafferCyclesDiskLightAPI"
}
inherits = </APISchemaBase>
)
{

float inputs:cycles:spread = 180.0 (
displayGroup = "Geometry"
displayName = "Spread (Cycles)"
)

}

class "GafferCyclesQuadLightAPI" (
customData = {
token[] apiSchemaAutoApplyTo = ["RectLight"]
string apiSchemaType = "singleApply"
string className = "GafferCyclesQuadLightAPI"
}
inherits = </APISchemaBase>
)
{

float inputs:cycles:spread = 180.0 (
displayGroup = "Geometry"
displayName = "Spread (Cycles)"
)

}

class "GafferCyclesBackgroundLightAPI" (
customData = {
token[] apiSchemaAutoApplyTo = ["DomeLight"]
string apiSchemaType = "singleApply"
string className = "GafferCyclesBackgroundLightAPI"
}
inherits = </APISchemaBase>
)
{

int inputs:cycles:map_resolution = 1024 (
displayGroup = "Sampling"
displayName = "Map Resolution (Cycles)"
)

}

0 comments on commit e47c979

Please sign in to comment.