Cartoon Painter

Hello, here are my comments, hope you don’t mind.


TEXTURES AND TRANSPARENCY
To get textured models and transparency you can do this :

uniform sampler2D k_diffuse : TEXUNIT0, //in shader inputs, custom texture
uniform sampler2D tex_0, //in shader inputs, first texture found in .egg

...

float4 albedo = tex2D(k_diffuse, l_texcoord.xy);
o_color.xyz =  (factor ) * albedo.xyz;
o_color.a = albedo.a;


IMPROVEMENTS
You can get better lighting results, if you do all your light calculation in pixel shader instead of vertex shader.

What you are doing currently is more of a rim light effect than a real toon shading with correct light position and self-shadows. If you want “correct” lighting and self-shadows, you need to make all your light calculations in world or view space instead of model space. Like this you won’t need to resynchronize the painted instances with their original nodepaths. Also if you want a directionnal light, you don’t need vertex position in light calculation. In current code your light is like a point light.

Here is the code I use for toon shading calculations, it’s very simple :

float3 N = normalize(mul(float3x3(trans_model_to_world), l_normal)); 
float3 L = normalize((wspos_A - wspos_B));

float intensity = dot(L, N);
float factor = 1.0;
if ( intensity < 0.1 ) factor = 0.2;

float4 albedo = tex2D(k_diffuse, l_texcoord.xy);

o_color.xyz =  (factor ) * albedo.xyz;
o_color.a = albedo.a;

A is the light position, B is origin of the world.
l_normal is the interpolated normals from the vertex shader.


RIM LIGHT
For a rim light effect, you can do this :

float4 rim = pow( 1 - dot( N, normalize(wspos_camera) ), 2 );

It’s like calculating the opposite of the specular component, the rim effect is function of camera position.


INK SHADING

The current limitation here is the thickness of the ink shading lines is function of camera distance, and I find it quite complex to use a separate normal buffer for it. What I do is use 2 offscreen buffers, one for lit models, one for bigger black colored dupplicated model. The problem is you have to use 2 models to get this, but you can have more possibilities with the ink shading, for example, have a simpler or round ink outline using the same model with fewer polygons.
You then composite the 2 buffers in a compositing shader, main problem is you’ll have to calculate the depth manually I think.


FXAA and others

Also, I think for toon shading you need to smouth out edges in some cases, you can use a last pass for FXAA, code is in my deferred shading thread. Only problem with FXAA is you can’t use basic shaders anymore.

I think also the separate normal buffer calculation could be used in a deferred shading system, so you could get deferred toon shading with tens of lights !


SCRENS
rim light:

transparency + texture:

note: the model here doesn’t look good (with toon shading) + some normals on the wings are wrong, but you see the effect.