Cinder-Pipeline
is an imaging pipeline to construct and evaluate chained shader-based effectors.
A Context
is the container around which nodes are created, connections are made and nodes are evaluated. Context
evaluates a Node
by walking up the tree through the node's input connections and constructs an ordered collection of dependencies.
A Node
may have multiple input NodePort
which are both keyed and typed. Several data types are supported:
enum class NodePortType {
FBOImage, // native input/output type for imaging node
Texture, // ci::gl::TextureRef
Bool, // bool
Float, // float
Int, // int
Vec2, // ci::Vec2
Color, // ci::ColorA
Index, // int used to index into port's value vector
FilePath // ci::fs::path
};
Although multiple data types are supported, being an imaging pipeline, dependencies are only calculated on NodePortType::FBOImage
ports. Supporting that, all Node
instances have a fixed single output port NodeOutputPortKeyImage
of type NodePortType::FBOImage
.
Currently there are two abstract derived node classes, SourceNode
and EffectorNode
. SourceNode
has two derived classes TextureSourceNode
and FileSourceNode
that will both bring textures into the pipeline. EffectorNode
is intended to act as a base for shader-based operators and the input ports can vary based on the specific need.
// setup context internals (FBO) at source texture size
auto context = Context::create();
context->setup(texture->getSize(), 2);
// create source
auto sourceNode = context->makeNode(new TextureSourceNode);
auto texture = gl::Texture::create(loadImage(loadAsset(RES_LENNA_IMAGE)));
sourceNode->setValueForInputPortKey(texture, TextureSourceNodeInputPortKeyTexture);
// create red color tint
auto tintNode = context->makeNode(new TintNode);
ColorAf color = ColorAf(1.0f, 0.0f, 0.0f, 1.0f);
tintNode->setValueForInputPortKey(tintColor, TintNodeInputPortKeyColor);
context->connectNodes(sourceNode, tintNode);
// create horizontal blur
auto blurNode = context->makeNode(new GaussianBlurNode);
int direction = static_cast<int>(GaussianBlurNode::BlurDirection::Horizontal);
blurNode->setValueForInputPortKey(direction, GaussianBlurNodeInputPortKeyDirection);
context->connectNodes(tintNode, blurNode);
// evaluate (source -> tint -> blur)
auto resultTexture = context->evaluate(blurNode);
// TODO
At present, there is little if any error checking, the dependency solver is very naïve and many features are missing - see the TODO for more detail.
- Heavily inspired by Rich Eakin's Cinder-Audio2
- Shake and Quartz Composer
- Neil Mendoza for ofxPostProcessing
- Patricio Gonzalezvivo for ofxFX