Cell Shading Script

how do i use this script?

Basic Cel Shader

Piran Tremethick 06/2007

import GameLogic
objects = GameLogic.getCurrentScene().getObjectList()

ShaderObjects = [objects[“OBSuzanne”]]
MaterialIndexList = [ 0,1 ]

VertexShader = “”"

varying vec3 vLight;
varying vec4 vDiff;
varying vec4 vView;
varying vec3 vNormal;
varying vec4 vMat;

void main()
vec3 vtx =(gl_ModelViewMatrix * gl_Vertex).xyz;
vLight = (gl_LightSource[0].position).xyz - vtx;

vView = gl_Vertex - gl_ModelViewMatrix[3];

vNormal = gl_NormalMatrix * gl_Normal;
vMat = gl_Color * gl_LightSource[0].diffuse;

gl_Position = ftransform();


FragmentShader = “”"

varying vec3 vLight;
varying vec4 vDiff;
varying vec4 vView;
varying vec3 vNormal;
varying vec4 vMat;

uniform vec4 vWidths;

void main(){
vec3 vNorm = normalize(vNormal);
vec4 vColour = vMat;

vec3 vViewN = normalize(vView.xyz);
float ndotv = dot(vNorm, vViewN);

vec3 vLightN = normalize(vLight);
float ndotl = dot(vNorm, vLightN);

if ( ndotl < vWidths.x )
    vColour *= 0.75;
if ( ndotl < vWidths.y )
    vColour *= 0.5;
if ( ndotl < vWidths.z )
    vColour *= 0.5;
if ( ndotv < vWidths.w ) 
    vColour *= 0.0;

gl_FragColor = vColour;


def MainLoop ():
# for each object
for obj in ShaderObjects:

    mesh_index = 0
    mesh = obj.getMesh(mesh_index)

    while mesh != None:

        for mat in mesh.materials:
            # regular TexFace materials do NOT have this function
            if not hasattr(mat, "getMaterialIndex"):
            mat_index = mat.getMaterialIndex()

            # find an index                
            found = 0
            for i in range(len(MaterialIndexList)):
                if mat_index == MaterialIndexList[i]:
            if not found: continue

            shader = mat.getShader()
            if not shader.isValid():

                shader.setSource(VertexShader, FragmentShader,1)
                shader.setUniform4f('vWidths', obj.Cel1, obj.Cel2, obj.Cel3, obj.LineWidth)

        mesh_index += 1
        mesh = obj.getMesh(mesh_index)




I would check out your source for that script. To me, it looks like some of it was written in C/C++ and some was written in python. I didn’t think you could run C/C++ scripts in the BGE. Not only that, there are two “functions” labeled “main()”, instead of just one (in C/C++). My first, and mostly uneducated guess is that it won’t work.

To try it and see what happens, create an object (suzy) and name it “Suzanne”. Load the script into a text window and call it “celshader.py” (or whatever you want). Go into logic (f4) and set them up as so:
ALWAYS — Python: celshader.py

I’d make sure to have a console/terminal open so you can look for errors.

in the apricot builds you can use the cell shading in the material buttons, they work in the game engine, no script/code required :slight_smile: but there is a working cell shader, try searching the forums

@J09… that’s a python script with a GLSL shader in it… GLSL is written in code which is has similarities to c and c++

i got the code from a game thread…

and, it doesn’t seem to work…

i didn’t know the apricot build could do that.
how do i get the real time shadows?

thanks! that’s good to know. how does blender figure out what you’re trying to do, though? Is the main() statement enough?

Well as I wrote it I guess I should jump in here…
That was the old way of using GLSL, basically you define the vertex and fragment shaders as strings (note the GLSL code above is encased in triple quotes: “”"), then call the python functions to bind those shaders to the objects material. Which is why it’s a mix of Python and GLSL.
I don’t know if it’ll work in newer builds, but you should just be able to do what J09 states, hook up an always sensor->python controller and you’re good to go.
And yes, it does work, although maybe not in newer builds and as RagingChaos points out, it’s pretty much redundant now anyway.


i think only spotlights have shadows so far, but add a spotlight with shadow buffers i think, and make sure you have glsl shaders enabled

it doesn’t work…

Which one doesn’t work? The script or the shadows?

The script needs to be formatted, like all the tabs and spaces at the start of the lines need to be in place for python to make sense of it. Can you link the tutorial where you got the script from?

To get the realtime shadows you need to turn on Blender GLSL Materials in the Game menu in the main window and use a spot light to cast the shadows.

You need a SVN build of the Apricot branch to use the realtime GLSL materials and realtime shadows, but the script should work in Blender 2.46 when you run the game.

Edit: For future reference, the formatting of code is kept if you put it between code brackets by selecting the code and pressing the # key at the top of the window to post your comments:

So code appears like this
                    and you can start typing away from the start of the line

Edit 2: Below is a link to a thread that has some really great examples of scripts like the one you posted in action. Check out the scripts in the text editor (you only need Blender 2.46 for this, not one of the Apricot builds):

i got the script from a game progress thread.

and, ok, i’ll try that shadow thing.



and the shadows don’t work. i need some images…

can your hardware support glsl?

i dunno…

whats that mean?

google GLSL… basically if your card doesn’t support GLSL then it can’t do all the fancy cartoon shaders other special effects… most recent cards have been supporting it for at least 3 years by now…

And you have to assign the script to a Susanne. Only.

I know Mico27 has a really nice toon shader script. It works very well, and it is easy to tweak to your needs. If you search the forums for toon shading, which is another name for cell shading, you should find a thread with Mico27’s script.


i got an old radeon 7500.
i doubt its supported.

well, there goes my hope for making games with shadows…