Author Topic: Guidance on Super Simple PP Node  (Read 1953 times)

Hey !!

Saw the talk from David at GDC, very cool. Been using pixel processor and converting code into graph, but looking at how David was playing with filter kernels got me interested.

My python is super rusty by the way !

DESIRED RESULT ONCE COMPILED: Image of what I am trying to do with just python:

I tried stripping down the file, but that does not seem to work. This sample is way over my head and I just want to get started on a very bare bones basic python file just to get me started, and I could figure out the rest.

Attempts: So far, my code compiles fine, but all it does is create an empty graph inside my .sbs. package and a function graph. Of course this was not what I was looking for.

I am having trouble understanding how to encapsulate this function graph inside my pixel processor node (that never got spawned inside my compiled .sbs file)


Heres the code

Code: [Select]
import argparse
import functools
import os

from pysbs import context
from pysbs import sbsenum
from pysbs import sbsgenerator

import demo_cmd
import demos
import sbsMath.sbsmath as sm
import sbsMath.sbsmath_tools as st

xOffset = [-200, 0, 0]
yOffset = [0, 200, 0]

def create_base_network(graph, doc):

    pp_node = graph.createCompFilterNode(sbsenum.FilterEnum.PIXEL_PROCESSOR,
    return pp_node

def basic(fn):
    Substance function for generating a uv coordinate from a sphere normal and a tiling factor

    :param fn: The function context to create the function in
    :type fn: FunctionContext
    :return: function, a function to call to instantiate the function
    x = fn.input_parameter('x', widget_type=sbsenum.WidgetEnum.COLOR_FLOAT1)
    y = fn.input_parameter('y', widget_type=sbsenum.WidgetEnum.COLOR_FLOAT1)

    return fn.generate(x+y)

def main():
    parser = argparse.ArgumentParser('myPixel')
    args = parser.parse_args()
    atk_dir = demo_cmd.get_automation_toolkit_directory(args)
    samples_dir = demo_cmd.get_automation_toolkit_samples_directory(args)
    packages_dir = demo_cmd.get_automation_toolkit_packages_directories(args)

    # Use the python api to find the command line tools
    sbs_context = context.Context()

    output_path = os.path.join(samples_dir, 'myPixel')
    output_file = os.path.join(output_path, '')
    # Make sure the output directory exist

    # Create our target document
    doc = sbsgenerator.createSBSDocument(sbs_context,

    st.generate_function(basic, doc, name='basic')

    # Create a simple network with a pixel processor
    # and some inputs
    # pp_node = create_base_network(graph, doc)
    #pp = pp_node.getPixProcFunction()


if __name__ == '__main__':


I have created a simple example file generating the graph you are looking for.
Code: [Select]

from pysbs import context
from pysbs import sbsenum
from pysbs import sbsgenerator
from pysbs import autograph as ag

def create_base_network(graph, doc):
    Creates a network consisting of a base color output, a pixel processor and a wood material

    :param graph: The graph to create the network in
    :type graph: pysbs.graph.graph.SBSGraph
    :param doc: The document to create the network in
    :type doc: pysbs.substance.substance.SBSDocument
    :return: The pixel processor node of the network
    # Create an output BaseColor node
    outBaseColor = graph.createOutputNode(aIdentifier='BaseColor',
                                          aUsages={sbsenum.UsageEnum.BASECOLOR: sbsenum.ComponentsEnum.RGBA})

    # Create pixelprocessor
    pp_node = graph.createCompFilterNode(sbsenum.FilterEnum.PIXEL_PROCESSOR)
    # Connect the pixel processor node to the BaseColor
    graph.connectNodes(aLeftNode=pp_node, aRightNode=outBaseColor)

    uniform1 = graph.createCompFilterNode(sbsenum.FilterEnum.UNIFORM,
        aParameters = {sbsenum.CompNodeParamEnum.COLOR_MODE : sbsenum.ColorModeEnum.GRAYSCALE,
                       sbsenum.CompNodeParamEnum.OUTPUT_COLOR : .5})
    uniform2 = graph.createCompFilterNode(sbsenum.FilterEnum.UNIFORM,
        aParameters = {sbsenum.CompNodeParamEnum.COLOR_MODE : sbsenum.ColorModeEnum.GRAYSCALE,
                       sbsenum.CompNodeParamEnum.OUTPUT_COLOR : .5})
    # Connect base color and roughness from the wood to the pixel processor
    graph.connectNodes(aLeftNode=uniform1, aRightNode=pp_node)
    graph.connectNodes(aLeftNode=uniform2, aRightNode=pp_node, aRightNodeInput='input:1')

    # Layout the graph

    return pp_node

def blend_func(fn):
    pixel_pos = fn.variable('$pos', widget_type=sbsenum.WidgetEnum.SLIDER_FLOAT2)
    a = fn.create_gray_sampler(pixel_pos, 0, sbsenum.FilteringEnum.BILINEAR)
    b = fn.create_gray_sampler(pixel_pos, 1, sbsenum.FilteringEnum.BILINEAR)
    return a + b

def main():
    output_file = ''
    sbs_context = context.Context()

    # Create our target document
    doc = sbsgenerator.createSBSDocument(sbs_context,
    graph = doc.getSBSGraph(aGraphIdentifier='test')

    pp_node = create_base_network(graph, doc)
    pp = pp_node.getPixProcFunction()

    ag.generate_function(blend_func, doc, fn_node=pp)


if __name__ == '__main__':

Let me know if this helps you to get started.


Yes, this is absolutely perfect ! It answered all my questions I had so far.

Thank you so much ! ;D