🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Cel Shading

Started by
1 comment, last by Steve132 18 years, 3 months ago
Hi all, I am experimenting with cel shading for my school project. I have read tutorial 37 but don't really understand how to implement it without loading an object file for the model. How should I get the each vertex coordinates and its normal if I draw a cube or sphere using GLU functions? Hope someone can help out here. Thanks a lot. Kang
Advertisement
Well, This isn't REAL Cel-Shading, but I know of a neat little hack that will run on just about anything out there, and can simulate Cel Shading decently well for a simple convex shapes without any knowledge of the vertex information.

It works by using sphere mapping, and a texture that is the view independant equivilent of black lines around the edges.

(Oh yeah, if you want to just see it instead of understanding it, you can skip a bit)

Think of it this way: The Sphere mapping effect is unsatisfactory as a high-def mirroring surface because it is view-dependent. That is, with standard issue sphere mapping, the map itself is always the same relative to the camera position.

One of the big hurdles to Cel Shading is the fact that you have to recalculate the view-independant-version of the vertex each time, to discover if it is an edge vertex, etc, etc.

Here is a quick hack to use both of these problems to your advantage.

A sphere map works by something also known as angular mapping...the closer to the view-independent perpendicular the vertex's normal points, the closer to the edge of a big circle on the texture the texture coordinate is mapped to. It can be stated reasonably truthfully that with convex objects, the vertexes closest to the edge of the model are the ones with normals facing perpendicular the most.

Thus, to color the edge vertexes to black, simply apply sphere mapping with a texture that has a threshold of blackness around a white circle (kind of like a target). As the normals tend towards the edge, they will eventually become black as they are more and more on the edge. The result? black edges with white everything else (perfect for multiplying a color through multi-texture).

To see this, try downloading lesson 23 and replacing the reflection texture with a reflection of this type. Get One Here Run it with the verbatim code(! :) !)


Even though the effect looks odd on the cube (there isn't enough tesselated vertices) and VERY odd on the cone (not convex/closed form), the results for the sphere and cylinders show that with completely closed, reasonably tesselated models, this VERY cheap and simple cube mapping.

To make the effect greater or smaller (change the width of the line), simply adjust the width of the black line on the edge) It should be easy to generate this texture procedurally as well, for greater line control interactively. As per the code below.

int GenCelSphereTex(byte **src,int tex_width,byte line_percent)/* src=dst pointer,tex_width=width of square tex=256 or w/e, line_percent=n/255=percent of circle radius is black*/{    (*src)=(byte*)malloc(src,tex_width*tex_width*3); /*allocate memory*/    byte* tmpptr=(*src);    int radius=((tex_width/2)*(255-line_percent))/255; /*radius of white circle*/    int x,y,tx,ty;     byte bw=0xFF;     for(x=0;x<tex_width;x++)        for(y=0;y<tex_width;y++)        {             tx=x-tex_width/2;             ty=y-tex_width/2;             /*if distance squared to center is greater than radius squared, set bytes to black.  else set to white*/             bw=(tx*tx + ty*ty >= radius*radius ? 0x00 : 0xFF);             tmpptr[y*tex_width*3+x*3] =              tmpptr[y*tex_width*3+x*3 + 1] =             tmpptr[y*tex_width*3+x*3 + 2] = bw;        }     return 0;}







Well, This isn't REAL Cel-Shading, but I know of a neat little hack that will run on just about anything out there, and can simulate Cel Shading decently well for a simple convex shapes without any knowledge of the vertex information.

It works by using sphere mapping, and a texture that is the view independant equivilent of black lines around the edges.

(Oh yeah, if you want to just see it instead of understanding it, you can skip a bit)

Think of it this way: The Sphere mapping effect is unsatisfactory as a high-def mirroring surface because it is view-dependent. That is, with standard issue sphere mapping, the map itself is always the same relative to the camera position.

One of the big hurdles to Cel Shading is the fact that you have to recalculate the view-independant-version of the vertex each time, to discover if it is an edge vertex, etc, etc.

Here is a quick hack to use both of these problems to your advantage.

A sphere map works by something also known as angular mapping...the closer to the view-independent perpendicular the vertex's normal points, the closer to the edge of a big circle on the texture the texture coordinate is mapped to. It can be stated reasonably truthfully that with convex objects, the vertexes closest to the edge of the model are the ones with normals facing perpendicular the most.

Thus, to color the edge vertexes to black, simply apply sphere mapping with a texture that has a threshold of blackness around a white circle (kind of like a target). As the normals tend towards the edge, they will eventually become black as they are more and more on the edge. The result? black edges with white everything else (perfect for multiplying a color through multi-texture).

To see this, try downloading lesson 23 and replacing the reflection texture with a reflection of this type. Get One Here Run it with the verbatim code(! :) !) Move the quadrics with right and left, and cycle them with spacebar.


Even though the effect looks odd on the cube (there isn't enough tesselated vertices) and VERY odd on the cone (not convex/closed form), the results for the sphere and cylinders show that with completely closed, reasonably tesselated models, this VERY cheap and simple sphere map can fool the eye into a neato little cel shading simulation.

To make the effect greater or smaller (change the width of the line), simply adjust the width of the black line on the edge) It should be easy to generate this texture procedurally as well, for greater line control interactively. As per the code below.

int GenCelSphereTex(byte **src,int tex_width,byte line_percent)/* src=dst pointer,tex_width=width of square tex=256 or w/e, line_percent=n/255=percent of circle radius is black*/{    (*src)=(byte*)malloc(src,tex_width*tex_width*3); /*allocate memory*/    byte* tmpptr=(*src);    int radius=((tex_width/2)*(255-line_percent))/255; /*radius of white circle*/    int x,y,tx,ty;     byte bw=0xFF;     for(x=0;x<tex_width;x++)        for(y=0;y<tex_width;y++)        {             tx=x-tex_width/2;             ty=y-tex_width/2;             /*if distance squared to center is greater than radius squared, set bytes to black.  else set to white*/             bw=(tx*tx + ty*ty >= radius*radius ? 0x00 : 0xFF);             tmpptr[y*tex_width*3+x*3] =              tmpptr[y*tex_width*3+x*3 + 1] =             tmpptr[y*tex_width*3+x*3 + 2] = bw;        }     return 0;}







This topic is closed to new replies.

Advertisement