Opengl fog and glupersepective

I have been having some trouble incorporating fog into a game I am developing… the games graphics are similar to old school doom in that all the graphics are 2 dimensional sprites drawn onto 2 dimensional planes… as the user you have a third person view of your character which is set up as follows…

	gl.glMatrixMode(GL10.GL_PROJECTION);
	gl.glLoadIdentity();
	GLU.gluPerspective(gl, 67, glGraphics.getWidth()/(float)glGraphics.getHeight(), 
			1, 100f);
	GLU.gluLookAt(gl, world.user.cam.pos.x,world.user.cam.pos.y, world.user.cam.pos.z, 
			  world.user.cam.lookat.x, world.user.cam.lookat.y, world.user.cam.lookat.z, 0, 1, 0);
	gl.glMatrixMode(GL10.GL_MODELVIEW);

for all objects that get rendered to the scene I use the modelview matrix and translate to the objects absolute position and then render it…
currently when I enable fog the fog seems to be kind of random in where it appears, I have read that part of the issue may have to do with calling glulookat on the projection matrix stack instead of the modelview, but when I call gluperspective on the modelview stack it throws off all my translations for the game objects(user, npc’s, etc). could anyone offer any insight on how I should change my setup so I can enable fog? Thanks

Hi

Rather call gluLookAt on the model view matrix.

You want to call gluPerspective on the PROJECTION matrix, which you’re doing. However, you should be calling gluLookAt on the MODELVIEW and not the PROJECTION matrix. This is because gluLookAt configures the VIEW part of the MODELVIEW matrix.

You can use glPushMatrix() and glPopMatrix() to easily reset your MODELVIEW back to what was set with gluLookAt:


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(...);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(...);

// for each sprite:
glPushMatrix();
glTransform();
glPopMatrix();

Thanks for the speedy respone… I changed it around a bit and my user is now rendered correctly on the floor, but all the other game objects are gone. just so I know I’m understanding this correctly could you confirm the following?

gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 67, glGraphics.getWidth()/(float)glGraphics.getHeight(),
1, 100f);

gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, world.user.cam.pos.x,world.user.cam.pos.y, world.user.cam.pos.z,
world.user.cam.lookat.x, world.user.cam.lookat.y, world.user.cam.lookat.z, 0, 1, 0);

then for every game object
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glTranslatef(world.user.pos.x, world.user.pos.y, world.user.pos.z);
//any other necesary transforms/rotations etc
gl.glPopMatrix();
renderObject();

thanks again

Sorry, I was a bit vague. Move renderObject() before glPopMatrix().

glPushMatrix() saves the current state before modifications by pushing it onto a stack. glPopMatrix() resets the state to the last call of glPushMatrix() by popping off a matrix from the stack. In this case, you save the view with glPushMatrix(), modify it to take into account the object’s translation, then you render it, then you pop it off to reset for the next object.

Lastly, the reason why your original problem caused issues with fog rendering is that OpenGL uses view-space fog. Since your view matrix was included in the projection, the fog calculations were seeing strange transformations.

I am still having issues figuring this all out, so I am going to post up a bunch of code and hopefully, with a little luck, and a wee bit of magic, somone can figure this out.

ok so I changed the project setup and now the camera seems to be fixed at a point in space instead of following the user.
just to recap, previously I had the glulook at on the projectionmatrix and that rendered everything correctly but did not allow me to incorporate fog which I desperately want to incorporate…

Thanks for your time, this is pretty ugly!


//gl.glEnable(GL10.GL_FOG); I wish!
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		
gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 67, glGraphics.getWidth()/(float)glGraphics.getHeight(), 
				1, 100f);
		
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, world.user.cam.pos.x,world.user.cam.pos.y, world.user.cam.pos.z, 
		           world.user.cam.lookat.x, world.user.cam.lookat.y, world.user.cam.lookat.z, 0, 1, 0);
	//the cameras position is determined by rotating the user look vector 180 degrees, scaling it a bit and then moving it up in the y
        //the lookat is just a copy of the users position
        // the idea is to create a third person view looking from above and behind the user

gl.glPushMatrix();
gl.glLoadIdentity();
gl.glTranslatef(world.user.pos.x, world.user.pos.y, world.user.pos.z); // translate to the users position which is the same as the cameras lookat
//gl.glRotatef(world.user.look2.angle() + 90, 0, 1, 0); // rotate the 2d plane 90 from the angle of the look so it appears perpendicular to camera
//The batcher.begin binds the texture
//batcher.drawsprite(x,y,width,height,textureRegion) draws a 2d plane at soecified x,y and width height and applies specified texture region	
	
batcher.beginBatch(ffcharacters);
	switch(world.user.direction){
		case Zombie.DOWN:
			batcher.drawSprite(0, 0, 1, 1, userAnimations[0].getKeyFrame(world.user.time, world.user.moving?      Animation.ANIMATION_LOOPING:Animation.ANIMATION_NONLOOPING));
			break;
		case Zombie.LEFT:
			batcher.drawSprite(0, 0, 1, 1, userAnimations[1].getKeyFrame(world.user.time, world.user.moving?Animation.ANIMATION_LOOPING:Animation.ANIMATION_NONLOOPING));
			break;
		case Zombie.RIGHT:
			batcher.drawSprite(0, 0, 1, 1, userAnimations[2].getKeyFrame(world.user.time, world.user.moving?Animation.ANIMATION_LOOPING:Animation.ANIMATION_NONLOOPING));
			break;
		case Zombie.UP:
			batcher.drawSprite(0, 0, 1, 1, userAnimations[3].getKeyFrame(world.user.time, world.user.moving?Animation.ANIMATION_LOOPING:Animation.ANIMATION_NONLOOPING));
			break;
		}
//end batch renders the plane
		batcher.endBatch();
		gl.glPopMatrix();


//METHODS WITHIN BATCHER CLASS
	public void beginBatch(Texture texture){
		texture.bind();
		numSprites = 0;
		bufferIndex = 0;
	}

	public void endBatch(){
		vertices.setVertices(verticesBuffer, 0, bufferIndex);
		vertices.bind();
		vertices.draw(GL10.GL_TRIANGLES, 0, numSprites * 6);
		vertices.unbind();
	}

public void drawSprite(float x, float y, float width, float height, TextureRegion region){
		float halfWidth = width / 2;
		float halfHeight = height /2;
		float x1 = x - halfWidth;
		float y1 = y - halfHeight;
		float x2 = x + halfWidth;
		float y2 = y + halfHeight;
		
		verticesBuffer[bufferIndex++] = x1;
		verticesBuffer[bufferIndex++] = y1;
		verticesBuffer[bufferIndex++] = region.u1;
		verticesBuffer[bufferIndex++] = region.v2;
		
		verticesBuffer[bufferIndex++] = x2;
		verticesBuffer[bufferIndex++] = y1;
		verticesBuffer[bufferIndex++] = region.u2;
		verticesBuffer[bufferIndex++] = region.v2;
		
		verticesBuffer[bufferIndex++] = x2;
		verticesBuffer[bufferIndex++] = y2;
		verticesBuffer[bufferIndex++] = region.u2;
		verticesBuffer[bufferIndex++] = region.v1;
		
		verticesBuffer[bufferIndex++] = x1;
		verticesBuffer[bufferIndex++] = y2;
		verticesBuffer[bufferIndex++] = region.u1;
		verticesBuffer[bufferIndex++] = region.v1;
		
		numSprites++;
	}
	

Don’t call glLoadIdentity() after glPushMatrix(). glTranslate() multiplies the current state of the matrix (i.e. the view configured by gluLookAt()) with a translation matrix. This means the MODELVIEW would translate the object to its world position, then transform the world position into view or camera space.

If you have that 2nd glLoadIdentity(), you just translate into world space and never complete it. Otherwise, your glPushMatrix() and glPopMatrix() and object rendering are all ordered correctly with respect to gluLookAt() and glTranslate()

ok so everything is being drawn in their respected places again and glulookat is being called on the modelview matrix, but my fog is still kind of random… for all my characters, user and npc’s it works, but the floor and skybox seem to randomly partially or completely disappear or come into full view with no fog as I rotate the viewing angle of the camera… I have the fog set up as follows, right now this is being called before every frame:


gl.glEnable(GL10.GL_FOG);
gl.glHint(GL10.GL_FOG, GL10.GL_NICEST);
gl.glFogf(GL10.GL_FOG_MODE, GL10.GL_LINEAR);
gl.glFogf(GL10.GL_FOG_START, 8);
gl.glFogf(GL10.GL_FOG_END, 15); 

Then I render the floor currently represented by a single large plane composed of 4 vertices rendered with six indices, followed by the skybox , then the characters and effects(which the fog is working on)… I thought the issue may have to do with per vertex fog calculations but it is my understanding that setting the fog mode to nicest results in per pixel calculations… any ideas?

My only thought is that there is some discrepancy with how you configure your MODELVIEW matrix for when you render your skybox and floor. If you could boil it down into a standalone class, I’d be happy to run it and fiddle around to see where the problem is.