Awesome
For a production-ready version of MNPR, please refer to MNPRX
MNPR
MNPR is an expressive non-photorealistic rendering framework for real-time, filter-based stylization pipelines within Maya (2016.5+). It extends the Maya API and simplifies the creation of Viewport 2.0 render overrides, while still preserving all the low-level options that the Maya API provides.
The framework was originally created by Santiago E. Montesdeoca during his PhD studies at the Nanyang Technological University (Singapore), as a product of his conducted research in:
His research was supervised in Singapore by Hock Soon Seah, Hans-Martin Rall and Davide Benvenuti, joined later with supervision in France from Joëlle Thollot, Pierre Bénard and Romain Vergne.
MNPR is now open-sourced under the MIT-license through the publication:
Valuable contributions coding MNPR were given by:
- Pierre Bénard
- Amir Semmo
- Yee Xin Chiew
Downloading MNPR
For animated projects, please refer to the actively maintained MNPRX.
The latest stable release of the MNPR prototype can be found here (Maya 2017 and 2018):
Building from source
The easiest way to build MNPR is using CMake, just make sure cmake is added to the system PATH.
If you've never built anything with CMAKE, please consider watching Chad Vernon's Compiling Maya Plug-ins with CMake tutorial.
Windows
Simple: Double click on the _buildWindows.bat file under plugins and follow instructions.
Advanced:: Open the command prompt (or PowerShell) and run the following commands
cd %MNPR_LOCATION%/plugins/build/
cmake ../ -G "Visual Studio 15 2017 Win64" -DMAYA_VERSION=%YEAR%
cmake --build . --config Release
You need to replace %MNPR_LOCATION% and %YEAR% with the location of MNPR on your computer and the Maya version year, respectively. You can also choose to build with Debug configuration, which enables the MSVC debugging tools.
Note: When building with Release configuration, the shaders need to be built, as well. Run or refer to the _compileHLSL.bat to compile the HLSL shaders.
MacOS
cd %MNPR-LOCATION%/plugins/build/
cmake -G "Unix Makefiles" -DMAYA_VERSION=%YEAR% %MNPR-LOCATION%/plugins
cmake --build . --config Release
You need to replace %MNPR_LOCATION% and %YEAR% with the location of MNPR on your computer and the Maya version year, respectively.
Linux
cd %MNPR-LOCATION%/plugins/build/
cmake -G "Unix Makefiles" -DMAYA_VERSION=%YEAR% %MNPR-LOCATION%/plugins
cmake --build . --config Release
You need to replace %MNPR_LOCATION% and %YEAR% with the location of MNPR on your computer and the Maya version year, respectively.
Stylization Semantics
Visual effects in non-photorealistic rendering can be generalized into four distinct categories:
- Pigment-based effects
- Substrate-based effects
- Edge-based effects
- Abstraction-based effects
These four groups can be used to directly correlate the stylization control parameters between different styles, using common semantics. The semantics need to be sufficiently generic, yet semantically meaningful to be adapted to different styles and accepted by the NPR development community. Additionally, these effects need to adhere to a control scheme, which defines what semantics goes to which channel in the stylization map---so that these can be interpreted by other styles.
The stylization control parameters are rendered by the MNPR object-space shaders into stylization maps, representing each effect group and following the following control scheme:
Channel | Pigment-based effects | Substrate-based effects | Edge-based effects | Abstraction-based effects |
---|---|---|---|---|
R | Pigment variation | Substrate distortion | Edge intensity | Detail |
G | Pigment application | U-inclination | Edge width | Shape |
B | Pigment density | V-inclination | Edge transition | Blending |
Stylization pipelines supporting the same effect categories, respecting the semantics and following the control scheme, would enable e.g., to map an art-directed rendering in a watercolor style to an oil or charcoal style.
Effect semantics, explained
Pigment-based effects
- R: Pigment variation, controls the degree at which the reflected color of a pigment deviates towards one or another color. E.g., green pigmentation that deviates to a more blue or yellow color in certain parts.
- G: Pigment application, controls how the pigment is placed over a substrate. This can be interpreted as the amount or pressure at which pigment is applied to achieve an effect. E.g., dry-brush application, thick application.
- B: Pigment density, controls the concentration of the pigment placed over a substrate. This is especially relevant to transparent and translucent media ( i.e., watercolor, ink, colored pencils), but can also influence opaque media. E.g., dilution, lightness, saturation.
Substrate-based effects
- R: Substrate distortion, controls the distortion caused by the substrate roughness on the rendered image. This is especially relevant for fluid media (i.e., watercolor, graffiti).
- G and B: U-inclination and V-inclination, control the inclination of the substrate, which generally affects the direction at which patterns or marks from fluid media evolve. However, generalizing upon this, these parameters are used to define the offset of existing patterns or marks in a horizontal or vertical direction. E.g., bleeding direction, cross-hatching direction, stroke direction.
Edge-based effects
- R: Edge intensity, controls the edge strength/intensity within the stylized render. E.g., linework darkness, edge darkening.
- G: Edge width, controls the edge thickness of the stylized render. E.g., linework width, edge darkening width.
- B: Edge transition, controls the edge transition of the subject in relation to neighboring elements. E.g., edge softening, gaps and overlaps.
Abstraction-based effects
- R: Detail, controls the amount of detail at different parts of the stylized render within the subject. E.g., detail blur.
- G: Shape, Controls the amount of shape abstraction/distortion of the subjects. E.g., hand tremors.
- B: Blending, controls the color blending at different parts of the stylized render. E.g., smudges, color bleeding.
By adhering to these semantics throughout the stylization pipeline, art-directed scenes can predictably change style and, for the most part, keep the intended effects and look of the expressive render. While these semantics are neither final, nor applicable to all styles and effects, they provide a starting point to address cross-stylization paradigms in expressive rendering.
Modifying MNPR
Creating your own stylization pipeline is quite straightforward, but it's best to learn by doing and taking a look at how existing stylizations are made. Here is a small breakdown of how things are set up in MNPR.
Please also read the Coding Guidelines and the Tips & Tricks
Add style to Framework
- Add style string to STYLES global variable (mnpr_renderer.cpp)
- Add your style as the default value in the engine settings (mnpr_renderer.h)
Create your stylization pipeline
- Copy and rename a style file (e.g., style_watercolor.hpp -> style_crosshatching.hpp)
- Adapt the new style source file
- Change to a custom namespace
- Add the desired render target(s)
- Add the desired render operation(s)
- Add switch clause in addCustomTargets() and addCustomOperations() (mnpr_renderer.cpp)
Create custom attributes in the config node
- Add attributes as engine settings (EngineSettings) or effect parameters (FXParameters) (mnpr_renderer.h)
- Copy and rename the node_watercolor.hpp file e.g., node_crosshatching.hpp
- Adapt the new node source file
- Add MObject representing the new attribute(s)
- Change to a custom namespace
- Initialize the attribute(s) in initializeParameters()
- Parse attribute(s) in computeParameters()
- Add switch clause in initializeCustomParameters() and computeCustomParameters() (mnpr_configNode.cpp)
Add a flag to the mnpr command
- Add short name and long name strings (mnpr_cmd.cpp)
- Add flag to newSyntax()
- Parse command in doIt()
Create your custom quad shaders
- Copy and rename a shader file (e.g., quadBlend10.fx -> quadHatch10.fx)
- Write your fragment shader
- Create a technique that uses your fragment shader
Note: as MNPR evolves and more stylizations are implemented within it, more shaders will be available for general use. Try to always reuse existing shader code, as this will enable you to iterate faster towards your stylistic goals.
Creating mapped and material effect control widgets for paintFX and noiseFX
- Open mnpr_FX.py and carefully read the schema
- Define your MNPR_FXs in the
getStyleFX()
function - Add the switch clause at the bottom of the
getStyleFX()
function - Double click on pFx and nFx buttons in the shelf to reload the python file and UI
Coding Guidelines
Some brief coding guidelines for the framework to have a consisting style.
Shader code (HLSL and GLSL)
Shader source code in MNPR is found in the shaders folder. In general, we recommend coding shaders mostly in HLSL and translating them to GLSL afterwards. Maya is not helpful when programming GLSL shaders, as it doesn't print out where some errors might be. This leads to a lot of trial and error and lost time finding the culprit of a single syntax error. HLSL development is straightforward to debug and altogether better supported within Maya.
Shader code in MNPR is sorted by operation type and is managed by techniques which run the required vertex and pixel shaders (and tesselation/geometry shaders if you set them up). The technique approach towards shader writing is inspired by the now deprecated effect files in DirectX. Autodesk seems to strongly advocate to this shader-writing convention, even proposing their own solution for techniques within GLSL shaders, as well.
There are convenience functions/shaders for quad (screen-space) shaders in both, HLSL and GLSL in the quadCommon shader files. These facilitate the development of shader code and avoid code repetition in technique based files.
Merging requirements
Shader code will only be merged into the Master branch if the shaders are working in both DirectX and OpenGL versions of the viewport. This is required to maximize the usability of the code in all platforms by artists and developers.
Naming convention
- camelCase is strongly encouraged throughout all coding languages used in MNPR. This means that files, variables and any kind of functions should respect the camelCase naming convention.
- Shader names should have their type at the end, e.g.
quadVert()
,resampleFrag()
. - Variables sent to the shader (uniforms) contain a
g
prefix, e.g.gColorTex
.
File names
By default, MShaderManager within the Maya API will append the file type extension depending on which drawing API the viewport is currently using. For HLSL, it will append 10.fx
, whereas for GLSL, .ogsfx
will be appended. For this reason, shader file names must present these suffixes in their names.
- Shader file in the root shader directory are general MNPR shaders
- Shader files that are specific to one stylization pipeline should be in their own folder (e.g., ch, op, wc)
Commenting
- Comments should be written following two forward slashes and a white space.
// This is a comment
- Inline comments should be written in small-caps (except names) following two spaces, two forward slashes and a white space.
Texture2D gSubstrateTex; // substrate texture (paper, canvas, etc)
Code file headers
Code file headers should be formatted as follows:
- File name with language in brackets
- Brief description of what the file contains
- Contributors that have added or fixed things in the shader code
- ASCII headers stating the type of operations available in the shader file
- Description of what kind of shaders the file contains.
The file header should look something like this:
////////////////////////////////////////////////////////////////////////////////////////////////////
// quadAdjustLoadMNPR10.fx (HLSL)
// Brief: Adjusting and loading render targets
// Contributors:
////////////////////////////////////////////////////////////////////////////////////////////////////
// _ _ _ _ _
// __ _ __| |(_)_ _ ___| |_ | | ___ __ _ __| |
// / _` |/ _` || | | | / __| __|____| |/ _ \ / _` |/ _` |
// | (_| | (_| || | |_| \__ \ ||_____| | (_) | (_| | (_| |
// \__,_|\__,_|/ |\__,_|___/\__| |_|\___/ \__,_|\__,_|
// |__/
////////////////////////////////////////////////////////////////////////////////////////////////////
// This shader file adjusts and loads any required elements for future stylization in MNPR
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "include\\quadCommon.fxh"
Sections
Sections are used to separate different fragment shaders that belong to the same group (e.g., edge detection -> sobel, DoG). Shader code sections feature the following
- ASCII headers followed by a description of the shader
- Three empty lines separate each section
// _
// _ __ ___ ___ __ _ _ __ ___ _ __ | | ___
// | '__/ _ \/ __|/ _` | '_ ` _ \| '_ \| |/ _ \
// | | | __/\__ \ (_| | | | | | | |_) | | __/
// |_| \___||___/\__,_|_| |_| |_| .__/|_|\___|
// |_|
// Contributors:
// Resamples any up- or down-sampled target to fit the viewport dimensions.
// Anti-aliasing is achieved by using bilinear filtering when sampling.
float4 resampleFrag(vertexOutputSampler i) : SV_Target {
return gColorTex.Sample(gSampler, i.uv);
}
// _______ __ _ _
// | ___\ \/ / / \ / \
// | |_ \ / / _ \ / _ \
// | _| / \ / ___ \ / ___ \
// |_| /_/\_\/_/ \_\/_/ \_\
//
// Contributors:
// Perform FXAA v3.11 anti-aliasing
// -> Based on FXAA of Timothy Lottes 2009
// [2009] FXAA
float4 FXAAFrag(vertexOutputSampler i) : SV_Target {
// etc
}
Groups
Shader code can also be grouped into specific assignment/operations as such:
- Use ALL-CAPS when grouping operations
- Two empty lines separate groups
// MAYA VARIABLES
float gNCP : NearClipPlane; // near clip plane distance
// TEXTURES
Texture2D gZBuffer; // ZBuffer
Texture2D gSubstrateTex; // substrate texture (paper, canvas, etc)
// VARIABLES
// post-processing effects
float gSaturation = 1.0;
float gContrast = 1.0;
float gBrightness = 1.0;
// engine settings
float2 gDepthRange = float2(8.0, 50.0);
float3 gSubstrateColor = float3(1.0, 1.0, 1.0);
float gSubstrateRoughness;
float gSubstrateTexScale;
float2 gSubstrateTexDimensions;
float2 gSubstrateTexUVOffset;
// MRT
struct fragmentOutput {
float4 stylizationOutput : SV_Target0;
float3 substrateOutput : SV_Target1;
float depthOutput : SV_Target2;
};
This documentation is still in progress... <!-- ## Modifying the object-space shader -->
C++ code
C++ source code in MNPR is found in the plugin folder, sorted by the type of code it contains and defined by its prefix.
- mnpr prefix is for MNPR source files required by the framework.
- node prefix is for custom stylization nodes.
- style prefix is for custom stylization pipelines.
- M prefix is for classes that extend the Maya API (following the convention of Autodesk).
You will mostly be working with style and node files to specify your stylization pipeline. However, you will also be including effect parameters and engine settings into the mnpr_renderer.h header file.
Merging requirements
Merging mnpr files will affect all stylizations. Therefore, these files will only be merged if edits are thoroughly tested, organized and generalized towards more than just a specific stylization.
Naming convention
- camelCase is strongly encouraged throughout all coding languages used in MNPR. This means that files, variables and any kind of functions should respect the camelCase naming convention.
- Custom node source files need to have the node prefix
- Custom stylizations source files need to have the style prefix
- MObject is prefixed with o e.g.,
oData
- Attribute MObjects are prefixed with a e.g.,
aContrast
- In general, please try to keep the naming conventions consistent with the rest of the code.
Commenting
- Comments should be written following two forward slashes and a white space.
// This is a comment
- Inline comments should be written in small-caps (except names) following two spaces, two forward slashes and a white space.
Texture2D gSubstrateTex; // substrate texture (paper, canvas, etc)
Code file headers
Code file headers should be formatted as follows:
- ASCII headers stating the source file header
- Brief description of what the file contains
- Description of what kind of code the file contains.
The file header should look something like this:
///////////////////////////////////////////////////////////////////////////////////
// __ _ _
// ___ ___ _ __ / _(_) __ _ _ __ ___ __| | ___
// / __/ _ \| '_ \| |_| |/ _` | | '_ \ / _ \ / _` |/ _ \
// | (_| (_) | | | | _| | (_| | | | | | (_) | (_| | __/
// \___\___/|_| |_|_| |_|\__, | |_| |_|\___/ \__,_|\___|
// |___/
//
// \brief Configuration node
// Contains the configuration parameters to define engine settings and fx parameters
///////////////////////////////////////////////////////////////////////////////////
Functions, methods and groups
Functions and groups are separated by two empty lines, methods (class functions) are separated by one empty line.
Python code
Python source code developed for MNPR is found in the scripts directory and manages the frontend communication with the plugin.
Merging requirements
Merging mnpr python files will affect the stylization workflow of all artists. Therefore, these files will only be merged if edits are thoroughly tested, organized and generalized towards more than just a specific stylization.
Naming convention
- camelCase is strongly encouraged throughout all coding languages used in MNPR. This means that files, variables and any kind of functions should respect the camelCase naming convention.
- Python code files developed for MNPR should have the prefix mnpr
- In general, please try to keep the naming conventions consistent with the rest of the code.
Commenting
- Use Google python docstring format when documenting your functions, classes and methods (PyCharm:
Settings -> Python Integrated Tools -> Docstrings -> Docstring format -> Google
). - Comments should be written following one hashtag and a white space.
# This is a comment
- Inline comments should be written in small-caps (except names) following two spaces, one hashtag and a white space.
cmds.mnpr(renderOperation=mnprOperations-2, s=0) # UI
Code file headers
Code file headers should be formatted as follows:
- license: MIT
- repository: https://github.com/semontesdeoca/MNPR
- ASCII headers representing the source file
- Summary description of what the file contains
The file header should look something like this:
"""
@license: MIT
@repository: https://github.com/semontesdeoca/MNPR
_ _ ___
_ __ ___ _ __ _ __ _ __ | | | |_ _|___
| '_ ` _ \| '_ \| '_ \| '__| | | | || |/ __|
| | | | | | | | | |_) | | | |_| || |\__ \
|_| |_| |_|_| |_| .__/|_| \___/|___|___/
|_|
@summary: Contains the pass breakdown and MNPR viewport renderer interfaces
"""
Functions, methods and groups
Spacing follow the PEP 8 blank line conventions, but names should be in camelCase.
Tips & Tricks
- You cannot render to multiple render targets of different sizes.
- There is no need to try to get Maya's own post-processing effects to work as parameter targets should also present these.
- If for some unknown reason rendering is slower than previously, restart your computer and check again (WINDOWS).
- Developing ogsfx shaders inside of Maya are a pain, but if you have to:
- Syntax errors won't show, the targets will simply display white and you need to find out where the error is. (
/**/
and a proper IDE are your best friends) - Loading the shader as an ogsfx (GLSL) material might give better information to troubleshoot.
if (color.a) {}
won't work without any error message, you need to explicitly stateif (color.a > 0) {}
- A Texture2D must have a sampler, otherwise Maya will crash
- Syntax errors won't show, the targets will simply display white and you need to find out where the error is. (