GLSL Lighting a 3D box

Hey guys, long time lurker, first (well second really) time poster,

I’m a bit of a newbie when it comes to OGL, and I recently started playing around with shaders in lwjgl. I wanted to try lighting out first, and borrowed code for a simple vertex and fragment shader, which is as follows:

Vertex Shader


varying float diffuse_value;

void main() {            
    vec3 vertex_normal = normalize(gl_NormalMatrix * gl_Normal);
    vec3 vertex_light_position = gl_LightSource[0].position.xyz;
    diffuse_value = max(dot(vertex_normal, vertex_light_position), 0.0);

    gl_FrontColor = gl_Color;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Fragment Shader


varying float diffuse_value;

void main() {
    gl_FragColor = gl_Color * diffuse_value;
}

Now, I’m drawing a basic 3D box to go along with this, which is just basic quads put together. However, when the program is run, instead of getting “lighting” so to speak, each face receives the same color/amount of light, thus the box goes in and out of being black and being colored.

Any help would be greatly appreciated!

-Quaker762

I think this is more of a problem with how you have set up the light rather than the shader.

How should I got about setting up my lights then? Could you possibly link to some good tutorials to get started?

At the moment I’m using:


		glViewport(0, 0, width, height);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		GLU.gluPerspective(60.0f, (float) width / (float) height, 0.1f, 100.0f); // Set
																					// up
																					// our
																					// 3D
																					// perspective
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glPushMatrix();
		
		FloatBuffer position = ByteBuffer.allocateDirect(16).asFloatBuffer();
	    position.mark();
	    position.put(new float[] {0f, 0f, 0f, 0f }); // even values about 10e3 for the first three parameters aren't changing anything
	    position.reset();
		//Enable lighting
		glLight(GL_LIGHT0, GL_POSITION, position);
		
		FloatBuffer ambient = ByteBuffer.allocateDirect(16).asFloatBuffer();
	    ambient.mark();
	    ambient.put(new float[] { 0.5f, 0.5f, 0.5f, 1f });
	    ambient.reset();
	    glLight(GL_LIGHT0, GL_AMBIENT, ambient);
	    
		glEnable(GL_DEPTH_TEST);
		glDepthMask(true);
		glEnable(GL_CULL_FACE);
		
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);
		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
		glClearColor(1f, 1f, 1f, 1f);

However, this makes my box completely black now.
Sorry to ask really simple questions, I’m just so unsure how to even enable lighting properly.

-Quaker762

OK, here is your problem. Your shader is designed to work for directional lights. A directional light is one considered to be infinitely far away which has two effects: 1) It (can be considered to have) has a uniform intensity. 2) The rays of light (can be considered to be) are parallel. An example of a real world directional light is the sun. So obviously a directional light doesn’t really have a position, only a direction.

Now in fixed function pipeline OpenGL lighting, the direction of a directional light was set with the light’s position. I don’t know why this is, probably to ease the implementation, but whoever wrote your shader has emulated this behaviour, getting the light’s direction from it’s position. Now you setting the position to (0, 0, 0) essentially kills the light. But that isn’t your only problem, hence why setting it to (10E3, 10E3, 10E3) didn’t work either. And it is capital ‘E’ btw. Lower case e is natural logarithm base.

The dot product only works in the way you are using it when both vectors are normalized. (10E3, 10E3, 10E3) is obviously not normalized giving you undefined results. Either normalize it in the shader or better yet normalize it cpu side before setting it.

Two last things. Since you are using your own shaders, enabling GL_LIGHTING and GL_LIGHT0 does absolutely nothing. And if you want to read about how OpenGL used to do these lighting calculations: http://www.glprogramming.com/red/chapter05.html. It is a good read for explaining lighting things.

Hope I’ve helped.

You shouldn’t reset the buffers, you should rewind them.

Yeah, either [icode]buffer.rewind();[/icode] or [icode]buffer.flip();[/icode].
With rewind the buffer becomes readable, while with flip you can write to it too.

I’d suggest to read the javadocs. reset(), flip(), clear() and rewind() alter the position and limit of a buffer, and has nothing to do with readability/writability.

Copied straight from the Javadocs:

[quote]In addition to methods for accessing the position, limit, and capacity values and for marking and resetting, this class also defines the following operations upon buffers:

clear() makes a buffer ready for a new sequence of channel-read or relative put operations: It sets the limit to the capacity and the position to zero.

flip() makes a buffer ready for a new sequence of channel-write or relative get operations: It sets the limit to the current position and then sets the position to zero.

rewind() makes a buffer ready for re-reading the data that it already contains: It leaves the limit unchanged and sets the position to zero.
[/quote]
So they clearly alter the readability/writeability of a buffer, just not in a direct way but with settings the appropriate variables to the correct values.

Those are example use-cases, they have nothing to do with the buffer’s properties.

buffer.rewind() is the equivalent of buffer.position(0)
buffer.clear() is the equivalent of buffer.position(0) + buffer.limit(buffer.capacity())
buffer.flip() is the equivalent of buffer.limit(buffer.position()) + buffer.position(0)
buffer.reset() is the equivalent of buffer.position(mark);

buffer.clear() does not affect the readability or writability of a buffer, neither directly nor indirectly. it’s just common that one starts writing after a clear, and reading after a flip.

this is typically exactly what you would not do after a flip.