Synopsis

Possumwood (named after Sandbox Tree) is a graph-based procedural sandbox, implementing concepts of graph-based visual programming in a simple interface. It is intended to provide a user-friendly and accessible UI for experimenting with common computer graphics algorithms and libraries (e.g., OpenGL, CGAL, WildMagic, OpenCV).
Possumwood is built on top of a simple graph-evaluation engine and a Qt-based node graph editor, with an OpenGL viewport. Its main strength is its extensibility - it is trivial to implement new plugins supporting new libraries and data types, which allows free and user-friendly experimentation with parameters of each algorithm.
Possumwood is a sandbox, not a production tool. As a sandbox, it is quite open to radical changes and redesign, and for the time being it does not guarantee any form of backwards compatibility.
Possumwood is currently in active development, and does not pretend to be feature complete. It is not by any means meant to be a production tool, at least not yet. Any help is appreciated!

Table of contents
Installation
Possumwood has been tested only on Linux (several distributions). While it should work on Windows, it has not been compiled or tested there. No support for MacOS is planned for the time being due to heavy dependency on OpenGL.
Launchpad PPA for Ubuntu 18.04+
On Ubuntu, the easiest way to install Possumwood is to use the snapshots PPA:
sudo add-apt-repository ppa:martin-prazak/possumwood
sudo apt-get update
sudo apt-get install possumwood
This will install Possumwood to your system, enabling to simply run possumwood command from any terminal.
Installation using Snap
Currently, Possumwood is released in Snap as a development/testing package only. The latest build and its status can be accessed here.
To install a testing version, please run:
sudo snap install --edge possumwood --devmode
This will download and install the latest successful build of Possumwood with its dependencies. To start the application, run possumwood from the command line. As a dev build, snap will not automatically update this installation. Moreover, snap skin support is currently rather rudimentary, making Possumwood not inherit the system look correctly.
Building from source
The project is structured as a standard CMake-built project. To build, just run these in the directory of the repository on any Linux distro:
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release && make
And the result could be just run via ./possumwood or ./build/possumwood.
Example setups
Possumwood comes with a number of example setups that can serve as a starting point for experimentation.
Opengl
|
|
A simple OpenGL demo
A simple demo showing how to load an .obj file (positions, normals and topology) and display it using OpenGL.
Named vertex attributes p and n are loaded from an .obj file, and passed through to an OpenGL vertex/fragment shader setup. In later demos, this setup is wrapped-up in a subnetwork.
|
|
|
|
Automatic normals
When an mesh file doesn’t include explicit normals, it is relatively easy to use a fragment shader to “autogenerate” normals using screen-space derivatives dFdx() and dFdy(). This demo shows how to do that in Possumwood - just have a look at fragment_shared source.
|
|
|
|
Turntable demo
A simple shader setup passing a time value (i.e., the timeline value) as a uniform into the shader (together with viewport parameters). This value is then converted in the vertex_shader to a transformation matrix used to rotate a model.
|
|
|
|
Wireframe using a geometry shader
Wireframe mode is one of the rendering modes of OpenGL. A similar but more controllable effect can be achieved by processing a model using a geometry shader, which allows to convert primitives to a different number of primitives of the same or different type.
This setup shows how to emit a line for each polygon edge of the input geometry using a program in geometry_shader. It also shows how to adjust the line width to screen resolution, maintaining the width independent to view parameters.
|
|
|
|
Mesh subdivision in a geometry shader
While modern GPUs contain a bespoke functionality for subdivision, this simple demo shows how a similar (if limited) effect can be achieved using a simple geometry shader.
This demo implements a simple interpolative sudvision scheme with normal-based displacement. All subdivision computation is done in a geometry shader, with additional vertices and topology emitted by calling a recusive function. This approach is just a toy example, as it is strictly limited by the capabilities of individual GPUs - in practical applications, bespoke tesselation shaders perform much better.
|
|
|
|
PN Triangles in a geometry shader
Curved PN Triangles is a simple geometry subdivision scheme, replacing all triangles with a bezier patch directly on the GPU. The shape interpolation uses a cubic spline, and normals are interpolated using a quadratic spline to maintain continuity.
This implementation uses a geometry shader for emitting additional polygons.
Vlachos, Alex, et al. “Curved PN triangles.” Proceedings of the 2001 symposium on Interactive 3D graphics. ACM, 2001.
|
|
|
|
Infinite ground plane
A simple way of generating procedural graphics using GLSL employs rendering a single polygon covering the whole frame, and a per-pixel fragment shader (with additional inputs) to compute the final colour. A number of examples of this approach can be found at ShaderToy.
This demo is a simple example of such approach - based on a ray generated from a near and far plane point corresponding to a screen pixel, it computes the position of ray’s intersection with the ground plane (y==0), and uses this information to synthesize an “infinite” ground plane covered in checkerboard, with a “spotlight”. The fragment shader does all the computation - from ray intersection, through colour and checkerboard generation, to depth-value computation to allow the ground plane to composit correctly with other objects in a scene.
|
|
|
|
Shadertoy
ShaderToy is a community of artists and programmers centered around generating interesting graphics content in GLSL using a single fragment shader.
One of the common techniques to generate procedural 3D content in a fragment shader is Raymarching - a simple method of tracing rays against shapes represented as Signed Distance Functions, and generating 3D content based on them.
This demo is a port of a ShaderToy demo by Indigo Quilezles, showing different SDFs and a few additional effects that can be achieved by raymarching. A comprehensive raymarching tutorial can be found at the RaymarchingWorkshop.
|
|
|
|
Skybox
A classical way of generating sky and background in games is to render a cube or spherical map on the far plane (behind all other objects). This method is called CubeMap, SkyBox or SkyDome.
This simple demo shows this technique on a spherical texture from HDRI Haven.
|
|
|
|
Reflection mapping
Reflection mapping is a simple image-based lighting technique for simulating purely reflective materials. It only behaves correcty for convex shapes, but even with this strict limitation, it has been long established as a simple method for reflective surfaces in computer graphics.
This demo combines a skybox with a “purely reflective” material.
|
|
|
|
Gourand shading
Gourand shading is one of the simplest method of polygonal mesh shading. It computes colour by linearly interpolating vertex colours in screen space, making it cheap but less physically accurate than Phong or physics-based shading methods.
This demo combines Gourand shading with Phong reflection model, reproducing an old “fixed-pipeline” shading model of OpenGL.
|
|
|
|
Phong shading
Phong shading computes lighting of a surface by interpolating per-pixel surface normal. Compared to Gourand shading, this method leads to smoother and more realistic surface looks better describing the shape of the object, and significantly more accurate high-frequency components computation (i.e., specular component in the Phong lighting model).
This demo implements Phong shading with a Phong reflection model and a single point light source. The setup is wrapped in a subnetwork - just double-click the blue node to “enter” it.
|
|
|
|
Material capture shader
MatCap or LitSphere is a simple technique for representing the properties of both the material and the environment light in a single texture. By “baking in” the two dimensions of BRDF representing incoming light, MatCap determines the final colour solely by using the difference vector between the view ray and the surface normal.
This simple approach can yield surprisingly realistic results, and has been used in games, scultping software and for capturing and representing artistic styles.
Sloan, Peter-Pike J., et al. “The lit sphere: A model for capturing NPR shading from art.” Graphics interface. Vol. 2001. 2001.
|
|
|
|
Normal mapping
Normal mapping is a simple method for adding texture-based geometry details to a coarse model. It uses a texture to represent normal perturbation that would result from a significantly more detail in the surface mesh, without having to represent that detail explicitly in the underlying geometry. In games, this technique is often used to represent a complex model with all its detail, without having to explicitly store a heavy geometry.
This simple demo demonstrates a combination of normal mapping implemented in a fragment shader, together with displacement mapping implemented as a geometry shader. The lighting is implemented as a simple single light-source Phong reflection model.
Blinn, James F. “Simulation of wrinkled surfaces.” ACM SIGGRAPH computer graphics. Vol. 12. No. 3. ACM, 1978.
Mikkelsen, Morten. “Simulation of wrinkled surfaces revisited.” (2008).
|
|
|
|
SDF-based text rendering
Rendering text in OpenGL is usually implemented using a simple texture. However, such text “pixelates” when viewed up-close. A simple method to improve on its appearance uses a Signed distance function to represent letter boundaries - by exploiting the interpolation abilities of GPU hardware, it is possible to represent a text boundary with significantly more precision by using the directional information represented in SDF texture differential.
This demo shows a simple implementation of this technique.
Green, Chris. “Improved alpha-tested magnification for vector textures and special effects.” ACM SIGGRAPH 2007 courses. ACM, 2007.
|
|
Cgal
|
|
OBJ file loading
This simple demo shows how to load an object from .obj file, and display it in the viewport.
The display code is contained in a subnetwork (double click the blue node to “enter” it), and is based on a trivial implementation of a vertex and fragment OpenGL shader.
|
|
|
|
Lua mesh generation
A simple setup demonstrating a way to generate a new mesh in Lua using simple mesh bindings, and display the result using OpenGL. The main functionality is contained within the script node, which functions in the environment constructed by its inputs, and produces a state with new values on its output. The mesh extract node then extracts a mesh from the state and feeds it into CGAL mesh display node.
|
|
|
|
CGAL normals generation
To display a polygonal mesh on a GPU, the model needs to contain surface-normal information for shading. While this information can be auto-generated, an explicitly represented normal can improve surface properties like smoothness or shape details.
This simple demo shows two methods of computing normals using the CGAL library.
|
|
|
|
CGAL mesh decimation
Mesh simplification (decimation) is a common operation in mesh processing - it aims to reduce the mesh complexity without removing its details, reducing the memory footprint without compromising the quality of the resulting model.
This demo shows how to use CGAL’s implementation of mesh decimation in Possumwood, allowing to experiment with its various parameters.
|
|
|
|
Mesh Subdivision in CGAL
This simple demo demonstrates the mesh subdivision functionality as implemented in CGAL.
There are four subdivision methods implemented in CGAL - Catmull Clark, Loop, Doo Sabin and Sqrt 3. In Possumwood, all these are implemented as a single node acting on the polyhedron type.
|
|
|
|
CSG in CGAL
CGAL implements CSG (Constructive Solid Geometry) through Nef Polyhedra, a boundary-representation datastructure that is closed under Boolean set of operations.
This demo shows how a simple CSG setup can be created in Possumwood. A subnetwork is used to generate a sphere through Lua scripting, and convert it to a Nef polyhedron. This is then used as an input to CSG Boolean operations, result of which is displayed using a conversion to standard CGAL Polyhedron and an OpenGL setup in a subnetwork.
|
|
|
|
Minkowski addition in CGAL
Minkowski addition allows to combine two polyhedra such that the result is a polyhedron where one of the object has been “swiped” around the other (please see the link for more accurate description).
In CGAL, Minowski addition is implemented on top of the Nef polyhedra. This example setup shows how Minkowski addition can be used to “expand” and “round edges” a polyhedron.
|
|
|
|
Convex Hull in CGAL
Convex hull algorithm, implemented in CGAL, generates the smallest possible convex polyhedron fully enclosing a set of points. In Possumwood, the input to convex hull is a set of points from input meshes, and output is a convex polyhedron enclosing all of them.
Convex hull is useful for mesh generation for 3D printing - alongside boolean operations, it allows for creating complex shapes out of very simple primitives.
|
|
|
|
Face selection in CGAL
Selection in CGAL’s mesh processing is primarily used to determine which region is supposed to be influenced by an operation.
This demo shows the most basic selection by mesh intersection - faces of a mesh within another mesh are selected, and displayed in a different color.
|
|
|
|
Face selection in CGAL
Selection in CGAL’s mesh processing is primarily used to determine which region is supposed to be influenced by an operation.
This demo shows “boolean” set operations on selections, allowing to procedurally create more complex selections from simple inputs.
|
|
|
|
Isotropic remeshing in CGAL
Isotropic remeshing alters the input mesh such that it consists of “well behaved” polygons - uniformly distributes polygons with similar area and edge lengths.
This demo shows how to use remeshing of whole meshes in Possumwood. The input for remeshing is a selection - it is also possible to remesh only a part of the input mesh.
Botsch, Mario, and Leif Kobbelt. “A remeshing approach to multiresolution modeling.” Proceedings of the 2004 Eurographics/ACM SIGGRAPH symposium on Geometry processing. 2004.
|
|
Polymesh
Lua
|
|
Lua addition node
This simple demo shows how to create a subnetwork performing simple addition (and exposing input parameters) with a simple Lua script.
Double click the node too see its content.
|
|
|
|
Lua multiplication node
This simple demo shows how to create a subnetwork performing simple multiplication (and exposing input parameters) with a simple Lua script.
Double click the node too see its content.
|
|
|
|
Animated cube
A simple demo showing how to use a Lua script to create animated data, which are then fed as an input to a vector input of the cube node, animating its position.
|
|
|
|
Lua-based image synthesis
Possumwood contains a simple integration of the Lua scripting language, allowing to manipulate in-scene objects using code contained in nodes.
This demo shows how to synthesize an image programatically. It “injects” the images plugin into the input Lua context (i.e., the environment for running a script), and generates an image, which is then extracted from the output state using an image extract node. The result is then passed on an image-display subnetwork.
|
|
|
|
Lua expression-based image synthesis
This demo builds on the Lua Grid setup, extending it by additional parameters, and wrapping it in a subnetwork (double click any blue nodes to “enter” them).
|
|
|
|
Lua image tonemapping
Lua expressions in Possumwood can be also used to manipulate HDR images.
This demo shows how to implement simple Gamma compression tonemapping operator in Lua, and how to wrap it into a subnetwork with exposed parameters. Possumwood allows arbitrary nesting of nodes in this way, allowing to abstract-away any unnecessary complexity into simple nodes with clean interfaces.
|
|
Opencv basics
|
|
OpenCV image loading and display
This simple demo shows how to load an image using OpenCV’s imread() method, and pass the resulting image data to OpenGL as a texture and a set of additional metadata represented by GLSL uniforms.
In following demos, this OpenGL setup is wrapped in a subnetwork.
|
|
|
|
Image loading
A simple demo showing how to load an image from a file, and display it using an OpenGL setup (wrapped in a subnetwork - enter it by double-clicking the blue node).
|
|
|
|
Fullscreen image display
While Possumwood’s viewport is primarily intended for viewing 3D content, using a set of shaders it is possible to alter it to display 2D textures as well.
This demo uses shaders that ignore the perspective projection matrix and draw 2D image in a 2D front-facing view in the viewport.
|
|
|
|
Grayscale conversion
Color conversion in OpenCV is implemented in the cvtColor() function. This demo shows how to use the corresponding color node to first convert to grayscale, and then back to BGR to allow the image to be passed to OpenGL as RGB data.
|
|
Opencv image ops
|
|
Face detection using Haar cascades
This demo follows the OpenCV’s Haar Cascade tutorial - it allows to load a Haar Cascade .xml file in OpenCV’s format, use it to detect faces in the input image, and then draw the result into the source image for display.
Lienhart, Rainer, and Jochen Maydt. “An extended set of haar-like features for rapid object detection.” Proceedings. international conference on image processing. Vol. 1. IEEE, 2002.
|
|
|
|
Grayscale image denoising
This tutorial closely follows the OpenCV’s denoising tutorial for grayscale images, removing the noise using the non-local means algorithm.
|
|
|
|
Color image denoising
This tutorial closely follows the OpenCV’s denoising tutorial for color images, removing the noise using the non-local means algorithm.
|
|
|
|
Visualising luminance noise
This tutorial follows the OpenCV’s denoising tutorial for grayscale images, but at the end of the processing it subtracts the denoised image from the original (leaving only extracted noise), and equalises the result using cv::equalizeHist() to show the noise structure.
|
|
|
|
Visualising color noise
This tutorial follows the OpenCV’s denoising tutorial for color images, but at the end of the processing it subtracts the denoised image from the original (leaving only extracted noise), and equalises the result using cv::equalizeHist() to show the noise structure.
|
|
|
|
The Discrete Fourier Transform (implemented in OpenCV) converts a signal (image) into its complex frequency spectrum. By manipulating the spectrum, it is possible to implement simple frequency filters.
This demo shows how to perform a DFT on an image, and implements a simple frequency cutoff low-pass filter, showing both the image before and after applying this filter.
|
|
|
|
Video frames
OpenCV’s VideoCapture object can be used to extract frames from a video file. This demo shows how to use a video_frame source together with a frame input to link the viewport timeline with a displayed video frame.
|
|
|
|
Dense optical flow
OpenCV provides a method to compute dense optical flow in the calcOpticalFlowFarneback() function, allowing to detect moving objects in frames without explicitly detecting feature points first.
This demo shows how to set up this type of optical flow in Possumwood, and how to display its results as colours on top of a grayscale animated image.
Farnebäck, Gunnar. “Two-frame motion estimation based on polynomial expansion.” Scandinavian conference on Image analysis. Springer, Berlin, Heidelberg, 2003.
|
|
|
|
Calibration pattern detection (circles)
Pattern detection is the first step of camera calibration for many computer vision algorithms. This demo shows how a pattern build of circles can be detected using Hough transformation, and assembled into a grid for the use of camera intrinsic and extrinsic calibration.
|
|
|
|
Calibration pattern detection (chessboard)
Pattern detection is the first step of camera calibration for many computer vision algorithms. This demo shows how a chessboard pattern can be detected using corners feature detection, and assembled into a grid for the use of camera intrinsic and extrinsic calibration.
|
|
|
|
Camera calibration
The calibration of a camera’s intrinsic parameters is an important step for most algorithms in machine vision.
This demo shows how to perform multi-image intrinsic camera calibration using a chessboard pattern, and how to use the solved parameters to undistort an image. This functionality is fully built using OpenCV’s functions, wrapped in a set of Possumwood nodes.
The left side of the graph detects a pattern in a set of 4 images, accumulating the results in a points array; the calibrate_camera node computes the intrinsic calibration from a set of input sample points; the undistort node then uses the resulting calibration to correct the distortion of an input image.
|
|
|
|
Image inpainting using Fast Marching
Image inpainting is an image reconstruction technique, allowing to fill-in missing parts of an image based on existing pixels.
Telea’s algorithm shown in this demo uses a Fast Marching method to inpaint pixels from a boundary based on surrounding pixels and boundary’s normal direction.
Telea, Alexandru. “An image inpainting technique based on the fast marching method.” Journal of graphics tools 9.1 (2004): 23-34.
|
|
|
|
Image inpainting using Fast Marching
Image inpainting is an image reconstruction technique, allowing to fill-in missing parts of an image based on existing pixels.
The Navier-Stokes-based algorithm shown in this demo uses a heuristic based on fluid dynamics to inpaint a large region of dark pixels in an image, obtained by image thresholding.
Bertalmio, Marcelo, Andrea L. Bertozzi, and Guillermo Sapiro. “Navier-stokes, fluid dynamics, and image and video inpainting.” Proceedings of the 2001 IEEE Computer Society Conference on Computer Vision and Pattern Recognition. CVPR 2001. Vol. 1. IEEE, 2001.
|
|
|
|
Inpainting for image restoration
Image inpainting can be also used to attempt to restore an image where a large portion of the original data is missing.
This setup shows how an image can be partially restored using inpainting from a very sparse set of sample points.
|
|
|
|
Inpainting using the smoothness prior
A slightly different take on image inpainting can use the smoothness prior to try to reconstruct missing pixels in a single linear global solve step.
Cohen-Or, Daniel, et al. A sampler of useful computational tools for applied geometry, computer graphics, and image processing. AK Peters/CRC Press, 2015.
|
|
|
|
Image reconstruction using the smoothness prior
The smoothness prior can be also used to try to reconstruct missing pixels in a sparse set of samples using a single linear global solve step.
Cohen-Or, Daniel, et al. A sampler of useful computational tools for applied geometry, computer graphics, and image processing. AK Peters/CRC Press, 2015.
|
|
|
|
Anisotropic Diffusion
A simple implementation of the Anisotropic Diffusion filter, based on the legendary Perona-Malik paper. Implementation based on discretisation by Mackiewich (1995).
Perona, Pietro, and Jitendra Malik. “Scale-space and edge detection using anisotropic diffusion.” IEEE Transactions on pattern analysis and machine intelligence 12.7 (1990): 629-639.
Mackiewich, Blair. Intracranial boundary detection and radio frequency correction in magnetic resonance images. Diss. Theses (School of Computing Science)/Simon Fraser University, 1995.
|
&nbs
README 内容过长,已截取部分内容。完整内容请前往 GitHub 仓库查看。
|
评论