Skip to content

Commit

Permalink
Merge pull request #6211 from johnhaddon/contextProcessorsInShaders
Browse files Browse the repository at this point in the history
Shader : Support inline ContextProcessors
  • Loading branch information
johnhaddon authored Jan 17, 2025
2 parents 41cef12 + 22ac984 commit e32af24
Show file tree
Hide file tree
Showing 15 changed files with 857 additions and 189 deletions.
7 changes: 7 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Features
Improvements
------------

- Shader, ShaderPlug : Added support for ContextProcessor, Loop and Spreadsheet nodes to be used inline between shader nodes and as the terminal node connected to
ShaderAssignment and other shader-consuming nodes.
- VisualiserTool : Changed `dataName` input widget for choosing the primitive variable to visualise to a list of available variable names for the current selection.
- Tweaks nodes : Moved list of tweaks to a collapsible "Tweaks" section in the NodeEditor.
- Viewer :
Expand All @@ -23,6 +25,9 @@ Fixes
- Fixed bug where the value dragged from the visualiser would be slightly different from the initial value on button press. (#6191)
- Fixed error when trying to visualise data unsupported data.
- TweakPlug : Fixed preservation of geometric interpretation when tweaking V3f values.
- Shader :
- Fixed handling of multiple consecutive Switch nodes in a shader network.
- Fixed leak of private `scene:shader:outputParameter` context variable.
- ApplicationTest : Extended grace period when testing process name on slower hosts.
- OpDialogue : Fixed `DefaultButton` handling.

Expand All @@ -35,6 +40,8 @@ API
- The API is esoteric and was introduced extremely recently, so we believe nobody to be depending on it yet.
- Without the ABI change, the API isn't usable for its original intended purpose anyway.
- Backward compatibility is not trivial to maintain in this case.
- PlugAlgo : Added `contextSensitiveSource()` method.
- ShaderPlug : Added Python binding for `parameterSource()` method.

1.5.2.0 (relative to 1.5.1.0)
=======
Expand Down
11 changes: 11 additions & 0 deletions include/Gaffer/PlugAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
namespace Gaffer
{

IE_CORE_FORWARDDECLARE( Context )
IE_CORE_FORWARDDECLARE( GraphComponent )
IE_CORE_FORWARDDECLARE( ValuePlug )

Expand Down Expand Up @@ -77,6 +78,16 @@ std::invoke_result_t<Predicate, Plug *> findDestination( Plug *plug, Predicate &
template<typename Predicate>
std::invoke_result_t<Predicate, Plug *> findSource( Plug *plug, Predicate &&predicate );

/// Similar to `Plug::source()`, but also traversing upstream through Switch,
/// Spreadsheet, ContextProcessor and Loop nodes, taking into account their
/// operation in the current context. Returns the source plug and also the context
/// it is evaluated in.
///
/// > Note : If the current context contains a Canceller, then the returned context
/// > will reference it too. If the context is stored for later usage, the canceller
/// > should be removed.
GAFFER_API std::tuple<const Plug *, ConstContextPtr> contextSensitiveSource( const Plug *plug );

/// Conversion to and from `IECore::Data`
/// =====================================

Expand Down
5 changes: 4 additions & 1 deletion include/GafferScene/ShaderPlug.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
namespace GafferScene
{

class Shader;

/// Plug that accepts a Shader::outPlug() as input, and provides
/// access to the shading network generated by the shader.
class GAFFERSCENE_API ShaderPlug : public Gaffer::Plug
Expand Down Expand Up @@ -79,7 +81,8 @@ class GAFFERSCENE_API ShaderPlug : public Gaffer::Plug

private:

const Gaffer::Plug *shaderOutPlug() const;
struct ShaderContext;
const Gaffer::Plug * shaderOutPlug( ShaderContext &shaderContext ) const;

};

Expand Down
83 changes: 83 additions & 0 deletions python/GafferSceneTest/ShaderPlugTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
##########################################################################
#
# Copyright (c) 2025, Cinesite VFX Ltd. 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 unittest

import imath

import Gaffer
import GafferScene
import GafferSceneTest

class ShaderPlugTest( GafferSceneTest.SceneTestCase ) :

def testContextProcessorInput( self ) :

shader1 = GafferSceneTest.TestShader()
shader1["type"].setValue( "test:surface" )
shader1["parameters"]["c"].setValue( imath.Color3f( 1 ) )
shader2 = GafferSceneTest.TestShader()
shader2["type"].setValue( "test:surface" )
shader2["parameters"]["c"].setValue( imath.Color3f( 2 ) )

nameSwitch = Gaffer.NameSwitch()
nameSwitch.setup( shader2["out"] )
nameSwitch["selector"].setValue( "${which}")
nameSwitch["in"][0]["name"].setValue( "one" )
nameSwitch["in"][0]["value"].setInput( shader1["out"] )
nameSwitch["in"][1]["name"].setValue( "two" )
nameSwitch["in"][1]["value"].setInput( shader2["out"] )

contextVariables = Gaffer.ContextVariables()
contextVariables.setup( nameSwitch["out"]["value"] )
contextVariables["in"].setInput( nameSwitch["out"]["value"] )
contextVariables["variables"].addChild( Gaffer.NameValuePlug( "which", "two" ) )

shaderPlug = GafferScene.ShaderPlug()
shaderPlug.setInput( contextVariables["out"] )

self.assertEqual( shaderPlug.attributes()["test:surface"].outputShader().parameters["c"].value, imath.Color3f( 2 ) )

def testRejectsScenePlugInputFromContextProcessor( self ) :

contextVariables = Gaffer.ContextVariables()
contextVariables.setup( GafferScene.ScenePlug() )

shaderPlug = GafferScene.ShaderPlug()
self.assertFalse( shaderPlug.acceptsInput( contextVariables["out"] ) )

if __name__ == "__main__":
unittest.main()
Loading

0 comments on commit e32af24

Please sign in to comment.