Problem with cel shading

I read the tutorial at nehe and found some other resources on the net and thought it would be cool to try. But I don’t get it to work, the shading looks more like a zebra than the effect i want. I’m sure the error is very obvious but i’ve looked at this code for ages now and I don’t understand what’s wrong.

This is the effect I get:
http://www-und.ida.liu.se/~andma776/biz.jpg
(it’s supposed to be a cube)

I’ll give a big cel shaded hug to the person who can help me :slight_smile:

import net.java.games.jogl.*;

import java.nio.FloatBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;

public class TestCelShade implements GLEventListener {
    private GL gl;
    private GLU glu;
    private GLDrawable glDrawable;
    private FloatBuffer cubeVertives;
    private FloatBuffer cubeNormals;
    private int numberOfVertices = 0;
    private int[] shaderTexture = new int[1];
    private int[] shaderProgram = new int[1];
    private String programString = "";
    private float rotz = 0;
    private float[] lp = new float[]{1,-2,-3};

    public void initShadow() {
        int[] shaderData = new int[]{127, 127, 127, 191, 191, 191, 191, 191,
                                     255, 255, 255, 255, 255, 255, 255, 255};

        gl.glGenTextures(1, shaderTexture);
        gl.glBindTexture(GL.GL_TEXTURE_1D, shaderTexture[0]);
        gl.glTexImage1D (GL.GL_TEXTURE_1D, 0, GL.GL_RGBA, 16, 0, GL.GL_LUMINANCE , GL.GL_UNSIGNED_BYTE, shaderData);

        gl.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
        gl.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);

        gl.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
        gl.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);
    }

    public void addVertice(float x, float y, float z) {
        cubeVertives.put(x);
        cubeVertives.put(y);
        cubeVertives.put(z);
        numberOfVertices++;
    }

    public void addNormal(float x, float y, float z) {
        for (int i = 0; i < 4; i++) {
            cubeNormals.put(x);
            cubeNormals.put(y);
            cubeNormals.put(z);
        }
    }

    public void initCube() {
        ByteBuffer verticeByteBuffer = ByteBuffer.allocateDirect(36000);
        verticeByteBuffer.order(ByteOrder.nativeOrder());
        cubeVertives = verticeByteBuffer.asFloatBuffer();


        addVertice(-1.0f, -1.0f, 1.0f);
        addVertice(1.0f, -1.0f, 1.0f);
        addVertice(1.0f, 1.0f, 1.0f);
        addVertice(-1.0f, 1.0f, 1.0f);

        addVertice(-1.0f, -1.0f, -1.0f);
        addVertice(-1.0f, 1.0f, -1.0f);
        addVertice(1.0f, 1.0f, -1.0f);
        addVertice(1.0f, -1.0f, -1.0f);

        addVertice(-1.0f, 1.0f, -1.0f);
        addVertice(-1.0f, 1.0f, 1.0f);
        addVertice(1.0f, 1.0f, 1.0f);
        addVertice(1.0f, 1.0f, -1.0f);

        addVertice(-1.0f, -1.0f, -1.0f);
        addVertice(1.0f, -1.0f, -1.0f);
        addVertice(1.0f, -1.0f, 1.0f);
        addVertice(-1.0f, -1.0f, 1.0f);

        addVertice(1.0f, -1.0f, -1.0f);
        addVertice(1.0f, 1.0f, -1.0f);
        addVertice(1.0f, 1.0f, 1.0f);
        addVertice(1.0f, -1.0f, 1.0f);

        addVertice(-1.0f, -1.0f, -1.0f);
        addVertice(-1.0f, -1.0f, 1.0f);
        addVertice(-1.0f, 1.0f, 1.0f);
        addVertice(-1.0f, 1.0f, -1.0f);

        ByteBuffer normalByteBuffer = ByteBuffer.allocateDirect(36000);
        normalByteBuffer.order(ByteOrder.nativeOrder());
        cubeNormals = normalByteBuffer.asFloatBuffer();

        addNormal(0, 0, 1);
        addNormal(0, 0, -1);
        addNormal(0, 1, 0);
        addNormal(0, -1, 0);
        addNormal(1, 0, 0);
        addNormal(-1, 0, 0);

    }

    public void init(GLDrawable drawable) {
        this.gl = drawable.getGL();
        this.glu = drawable.getGLU();
        this.glDrawable = drawable;


        this.glDrawable.setGL(new DebugGL(drawable.getGL()));
        gl.glEnable(GL.GL_TEXTURE_2D);
        gl.glDisable(GL.GL_LINE_SMOOTH);

        gl.glEnable(GL.GL_CULL_FACE);
        gl.glShadeModel(GL.GL_SMOOTH);
        gl.glClearColor(0.5f, 0.5f, 0.5f, 1f);
        gl.glClearDepth(1.0f);

        gl.glEnable(GL.GL_DEPTH_TEST);
        gl.glDepthFunc(GL.GL_LEQUAL);
        gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
        gl.glLineWidth(2f);

        try {
            BufferedReader input = new
                    BufferedReader(new InputStreamReader(new FileInputStream("shader.txt")));

            String line = input.readLine();
            while (line != null) {
                programString += line + "\n";
                line = input.readLine();
            }
            input.close();
        } catch (Exception e) {
            System.out.println("Error, vertex program not loaded");
        }
        gl.glGenProgramsNV(1, shaderProgram);
        gl.glLoadProgramNV(GL.GL_VERTEX_PROGRAM_NV, shaderProgram[0], programString.length(), programString);
        gl.glBindProgramNV(GL.GL_VERTEX_PROGRAM_NV, shaderProgram[0]);

        gl.glTrackMatrixNV(GL.GL_VERTEX_PROGRAM_NV, 0, GL.GL_MODELVIEW_PROJECTION_NV, GL.GL_IDENTITY_NV);


        initShadow();
        initCube();

        gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL.GL_FLOAT, 0, cubeVertives);

        gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
        gl.glNormalPointer(GL.GL_FLOAT, 0, cubeNormals);

    }



    public void display(GLDrawable drawable) {

        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();
        gl.glFrustum(-1, 1, -1, 1, 1, 20);
        float[] imm = new float[16];


        gl.glTranslatef(0.0f, 0.0f, -5.0f);

        gl.glRotatef(-45.0f, 1.0f, 0.0f, 0.0f);
        gl.glRotatef(rotz, 0.0f, 0.0f, 1.0f);
        gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, imm);

        float modelLightPosX = imm[0]*lp[0] + imm[1]*lp[1] + imm[2]*lp[2];
        float modelLightPosY = imm[4]*lp[0] + imm[5]*lp[1] + imm[6]*lp[2];
        float modelLightPosZ = imm[8]*lp[0] + imm[9]*lp[1] + imm[10]*lp[2];

        gl.glProgramParameter4fNV(GL.GL_VERTEX_PROGRAM_NV, 4,
                                  modelLightPosX, modelLightPosY,
                                  modelLightPosZ, 1f);



        gl.glColor4f(0.75f, 0.95f, 1.0f, 1.0f);
        gl.glDisable(GL.GL_TEXTURE_2D);
        gl.glBindTexture(GL.GL_TEXTURE_1D, shaderTexture[0]);
        gl.glEnable(GL.GL_TEXTURE_1D);
        gl.glEnable(GL.GL_VERTEX_PROGRAM_NV);
        gl.glDrawArrays(GL.GL_QUADS, 0, numberOfVertices);
        gl.glDisable(GL.GL_VERTEX_PROGRAM_NV);

        gl.glDisable(GL.GL_TEXTURE_1D);

        gl.glEnable(GL.GL_CULL_FACE);
        gl.glCullFace(GL.GL_FRONT);
        gl.glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
        gl.glPolygonMode(GL.GL_BACK, GL.GL_LINE);
        gl.glDrawArrays(GL.GL_QUADS, 0, numberOfVertices);
        gl.glCullFace(GL.GL_BACK);



        rotz -= 0.8f;

    }

    public void reshape(GLDrawable drawable, int x, int y, int width, int height) {

        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {
    }
}

and the vertex program


!!VP1.0
# Vertex Program for cel shading
# c[0]-c[3] modelviewProjection matrix
# c[4]      model space light position

# Compute position
DP4 o[HPOS].x, c[0], v[OPOS];
DP4 o[HPOS].y, c[1], v[OPOS];
DP4 o[HPOS].z, c[2], v[OPOS];
DP4 o[HPOS].w, c[3], v[OPOS];

#output color
MOV o[COL0], v[COL0];

#calculate tex coord
#R0=light vector
ADD R0, c[4], -v[OPOS];

#R1 = normalize R0
DP3 R1.w, R0, R0;
RSQ R1.w, R1.w;
MUL R1.xyz, R0, R1.w;

#dot with normal for tex0.x
DP3 o[TEX0].x, R1, v[NRML];

END