# Cel-Shading: No matter what I do, it never works.

This topic is 3046 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I've been working on this Cel-Shading code for a long time and I've never for the life of me been able to get it to work! My code is based off of the NeHe tutorial (#37) and as far as I can tell, I've always followed it to the exact detail! So far, my geometry just comes out black always. Been at this for ages and still can't figure it out. What's going on?? Here's code below: Global variables & defines. The vertices make a Icosahedron and for each vertex, the normal is the same as the vertex value itself.
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
#define X	0.525731112119133606f
#define Z	0.850650808352039932f

// Vertices
static GLfloat VertexData[12][3] =
{
{-X, 0.0f, Z }, { X, 0.0f, Z }, {-X, 0.0f,-Z }, { X, 0.0f,-Z },
{ 0.0f, Z, X }, { 0.0f, Z,-X }, { 0.0f,-Z, X }, { 0.0f,-Z,-X },
{ Z, X, 0.0f }, {-Z, X, 0.0f }, { Z,-X, 0.0f }, {-Z,-X, 0.0f },
};

// Indices
static GLint TIndices[20][3] =
{
{0,4,1},  {0,9,4},  {9,5,4},  {4,5,8},  {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8},  {5,2,3},  {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5},  {7,2,11}
};

// Light angle
GLfloat fLightAngle[3] = { 0.0f, 0.0f, 1.0f };

// Floating point texture values
{
0.2, 0.2, 0.2, 0.2, 0.5, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

GLuint	uShaderTexture = 0;		// Handle to the shader texture


These are the math functions I've been using. They are the same as the NeHe tutorial as well.
//-----------------------------------------------------------------------------
// Basic math functions
//-----------------------------------------------------------------------------

inline float DotProduct3( float v1[3], float v2[3] )
{
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
}

inline float Magnitude( float v[3] )
{
return sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
}

void Normalize( float v[3] )
{
float m = Magnitude(v);

if( m != 0.0f )
{
v[0] /= m;
v[1] /= m;
v[2] /= m;
}
}

void RotateVector( float m[16], float v[3], float d[3] )
{
d[0] = (m[0]*v[0])+(m[4]*v[1])+(m[8] *v[2]);
d[1] = (m[1]*v[0])+(m[5]*v[1])+(m[8] *v[2]);
d[2] = (m[2]*v[0])+(m[6]*v[1])+(m[10]*v[2]);
}


This is where I initialized my default render states and the 1D cel-shading texture:
	//
// Set default render states
//

// Enable depth testing
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );
glClearDepth( 1.0f );

// Disable lighting
glDisable( GL_LIGHTING );
//	glEnable( GL_LIGHTING );

// Disable texture mapping (for now)
glDisable( GL_TEXTURE_2D );
// Enable 1D texture mapping
glEnable( GL_TEXTURE_1D );

// Disable blending
glDisable( GL_BLEND );

// Disable dithering
glDisable( GL_DITHER );

// Enable perspective correction and polygon smoothing
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );

// Change the default clear colour to blue
glClearColor( 0.0f, 0.0f, 0.5f, 1.0f );

// Create the shader texture
GLfloat textureData[32][3];

glGenTextures( 1, &uShaderTexture );

for( int i = 0; i > 32; i++ )
{
}

glBindTexture( GL_TEXTURE_1D, uShaderTexture );

glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

glTexImage1D( GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGB, GL_FLOAT, textureData );

Normalize( fLightAngle );


Okay, now for the rendering part.
// Move the camera back and rotate the object
glTranslatef( 0.0f, 0.0f,-3.0f );
glRotatef( rotY, 0.0f, 1.0f, 0.0f );

// Get the current matrix (after transformation)
glGetFloatv( GL_MODELVIEW_MATRIX, Matrix );

// Render in wireframe mode.
//	glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

//
//

// Enable 1D textures and bind the shader texture
glEnable( GL_TEXTURE_1D );
glBindTexture( GL_TEXTURE_1D, uShaderTexture );

// Default mesh colour
glColor3f( 1.0f, 1.0f, 1.0f );

// Render Icosahedron
glBegin(GL_TRIANGLES);

for( int i = 0; i < 20; i++ )
{
// This works fine for normal rendering (lighting included).
/*glNormal3fv(&VertexData[TIndices[0]][0]);
glVertex3fv(&VertexData[TIndices[0]][0]);
glNormal3fv(&VertexData[TIndices[1]][0]);
glVertex3fv(&VertexData[TIndices[1]][0]);
glNormal3fv(&VertexData[TIndices[2]][0]);
glVertex3fv(&VertexData[TIndices[2]][0]);*/

for( int j = 0; j < 3; j++ )
{
float tmpNormal[3], tmpVector[3], tmpShade;

tmpNormal[0] = VertexData[TIndices[j]][0];
tmpNormal[1] = VertexData[TIndices[j]][1];
tmpNormal[2] = VertexData[TIndices[j]][2];

RotateVector( Matrix, tmpNormal, tmpVector );

Normalize( tmpVector );

tmpShade = DotProduct3( tmpVector, fLightAngle );

if( tmpShade < 0.0f )

glVertex3fv( &VertexData[TIndices[j]][0] );
}
}

glEnd();


So hopefully one of the more experienced members of gamedev.net can give me a hand. They make it look easy, but I guess it isn't. This sucks. Any ideas? Thanks.

##### Share on other sites
The only thing I immediately noticed was
	for( int i = 0; i > 32; i++ )	{		textureData[0] = ShaderTexture;		textureData[1] = ShaderTexture;		textureData[2] = ShaderTexture;	}
Maybe you might want a less than instead of greater than. Don't know if that's the root of the issue but I thought I'd point it out!

[EDIT]
Look like you have some indexing issues in RotateVector also.

##### Share on other sites
Okay, I fixed the shading part. Switching from < to > did the trick, Thanks! But now the outline doesn't appear to work properly. It just renders as a wireframe copy of the mesh. I think it has to do with blending, but quite frankly, I don't understand what it's blending! Throughout the whole tutorial, I didn't see the alpha bit set not one time. This is what I have for the outline:

// Enable blending for the outline	glEnable( GL_BLEND );	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );	// Render back facing polygons as wireframe	glPolygonMode( GL_BACK, GL_LINE );	glLineWidth( 3.0f );	// Cull front facing polygons	glCullFace( GL_FRONT );	// Change the depth test mode to GL_LEQUAL	glDepthFunc( GL_LEQUAL );	glColor3f( 0.0f, 0.0f, 0.0f );	// Render the object again for the outlines	glBegin( GL_TRIANGLES );	for( i = 0; i < 20; i++ )	{		for( int j = 0; j < 3; j++ )		{			glVertex3fv( &VertexData[TIndices[j]][0] );		}	}	glEnd();	// Revert back to previous render states	glDepthFunc( GL_LESS );	glCullFace( GL_BACK );	glPolygonMode( GL_BACK, GL_FILL );	glDisable( GL_BLEND );

Either way, I'm still quite satisfied with the fact that the cel-shading part works. Thanks.

##### Share on other sites
I don't think I see you enabling culling anywhere [i.e., glEnable(GL_CULL_FACE)]. Nevertheless, I still find it funny that you'd see a wireframe model since the back-facing polygons should [mostly] fail the depth test, and the front facing polygons should probably render as filled polygons. I guess blending would cause that problem, so try the glEnable for culling and see what happens.

##### Share on other sites
Tried it. Now it appears as if the light is coming from the other direction. It didn't solve the outlining problem though.

##### Share on other sites
I tried integrating your code into the nehe tutorial's code, and had difficulties. From what I can tell though, I think your vertex indicies may not be correct, so try double checking those. Also verify that your winding order is correct. If it is correct all the way around, you might have to change the front facing polygons to be CW [i.e., glFrontFace(GL_CW)].

Also, make sure you're resetting the modelview matrix to the identity before applying glTranslate/glRotate, otherwise your operations will just stack on top of each other every time you draw.

That's about all I can suggest for now. Hope this helps!

• 11
• 18
• 12
• 22
• 9
• ### Forum Statistics

• Total Topics
631397
• Total Posts
2999822
×