OSL Image Manipulation

From Gaffer Wiki
Revision as of 17:15, 11 August 2024 by Murraystevenson (talk | contribs)
Jump to navigation Jump to search

The OSLImage node allows the use of OpenShadingLanguage shaders to generate or modify pixel values in an image.

Using an OSLImage node with a shader written in an OSLCode node to generate a fractal pattern.

Shaders can be built from an existing library of OSL shaders loaded via the OSLShader node, and arbitrary shader code can be evaluated via the OSLCode node. An image manipulation shader could be built entirely from existing nodes, written in a single OSLCode node, or assembled from a combination of OSL shaders and OSLCode nodes.

Shaders are evaluated per pixel in the image and typically would read that pixel value from one or more channels in the image, compute a value from those inputs and then output a new value that would replace the input pixel in an existing channel or layer, or create a new channel or layer.

Reading RGB values from and input image, using the OSL luminance shader to compute luminance values of those pixels, and outputting to a new channel named "luminance".

Writing channel data

Adding channels to OSLImage

Channels are written by adding inputs to the OSLImage node by clicking on the button in the Node Editor or by clicking or dragging a plug onto the on the left of the node in the Graph Editor.

Adding an input from the Node Editor
Adding an input from the Graph Editor

You can choose from common channel or layer names from the menu to write to RGB or RGBA layer, or to individual R, G, B, A channels.

Adding RGB and A plugs from the Node Editor.

You can also create arbitrary channels or layers via the Custom->Channel, Custom->Layer or Custom->LayerRGBA menu items. The channel or layer name can then be customised by by editing the name of the plug in the Node Editor.

Adding a custom named "luminance" channel, and "diffuse" layer to the image.

Behind the scenes, these actions are adding new child plugs to the `channels` plug of the OSLImage node.

The OSLImage node's channel inputs can either be a Color3fPlug or a FloatPlug, so choosing RGBA from the menu will create two plugs, a Color3fPlug for the RGB channels and a FloatPlug for the A channel.

Each channel or layer created provides an input connection ready to receive an OSL shader.

Disabling an output

Output layers and channels can be disabled by toggling their enabled plug.

Removing an output

Previously created output layers and channels can be removed by right clicking on the plug and selecting Delete from the context menu.

Reading channel data

Reading channels from shaders

The InChannel OSL shader can be used to read a specific channel from the processed image.

Shuffling channels with OSLImage by reading a single channel with an InChannel shader and writing the result to other channels.

The InLayer OSL shader can be used to read the R, G, B channels of a specified image layer.

Reading the R, G, B channels with an InLayer shader and shuffling them to a new "shuffled" layer.

Reading channels in an OSLCode node

When writing an OSL shader in an OSLCode node, Gaffer provides inChannel( channelName, defaultValue ) and inLayer( layerName, defaultValue ) functions to access the value of a specific channel or layer for the current pixel.

// Get the value of the "R" channel, returning 0 if the channel does not exist.
float R = inChannel( "R", 0.0 );

// Get the values of the "R", "G", "B" channels, returning black if the layer doesn't exist
// Providing "" as the layer name will return a color containing the value of the R, G, B channels.
color RGB = inLayer( "", color( 0.0 ) );

// Get the values of the "diffuse.R", "diffuse.G", "diffuse.B" channels, returning white if the layer doesn't exist
color diffuse = inLayer( "diffuse", color( 1.0 ) );

Channels can also be accessed via OSL's getattribute function.

// Get the value of the "R" channel for the current pixel
float R;
getattribute( "R", R );

// Get the value of the "R" channel from the "diffuse" layer for the current pixel
float diffuseR;
getattribute( "diffuse.R", diffuseR );
Shuffling channels using OSLCode.