JOGL Y axis too large

Hi!

first off, I’m german, so sorry for bad language :slight_smile:

I have a problem with my JOGL code. The Y axis is much bigger than the other ones. If I try to create a circle with gluSphere it is distorted vertically. Also if I build a “box” with vertexes, i have to hold the y values very small.
I tried everything (gluPerspective, glViewport, etc etc) but nothing seemes to be the correct solution.

I hope you understand my problem… :confused:

greetings

This is a problem with your projection matrix (the lens on your camera). If you’re seeing squished, you don’t have the right aspect ratio sent to gluPerspective(). If your viewport has dimensions (width, height), the aspect ratio would be ((float) width / (float) height). If gluPerspective gets the wrong aspect ratio, what it renders won’t line up with the actual viewport.

mhm, I cant find it.
To get a FPS like movement, I set a FloatBuffer like this:

public void set(){
		matrix.put(0, cosc*cosb-sinc*sina*sinb);
		matrix.put(1, sinc*cosb+cosc*sina*sinb);
		matrix.put(2, -cosa*sinb);
		matrix.put(4, -sinc*cosa);
		matrix.put(5, cosc*cosa);
		matrix.put(6, sina);
		matrix.put(8, cosc*sinb+sinc*sina*cosb);
		matrix.put(9, sinc*sinb-cosc*sina*cosb);
		matrix.put(10, cosa*cosb);
		
		matrix.put(12, matrix.get(0)*x+matrix.get(4)*y+matrix.get(8)*z);
		matrix.put(13, matrix.get(1)*x+matrix.get(5)*y+matrix.get(9)*z);
		matrix.put(14, matrix.get(2)*x+matrix.get(6)*y+matrix.get(10)*z);
	
	}

and while rendering i load the matrix with this commands:


matrix.rewind();		
gl.glLoadMatrixf(matrix);

These are the movement functions:


public void setHeading(float amount){
		heading+=amount;
		cosb=(float)Math.toRadians(Math.cos(heading));
		sinb=(float)Math.toRadians(Math.sin(heading));
		cosz=(float)Math.toRadians(Math.cos(heading+_90));
		sinz=(float)Math.toRadians(Math.sin(heading+_90));
	
	}
	public void setPitch(float amount){
		pitch-=amount;
		if(pitch>_maxPitch)pitch=_maxPitch;
		if(pitch<-_maxPitch)pitch=-_maxPitch;
		cosa=(float)Math.cos(pitch);
		sina=(float)Math.sin(pitch);
	}
	public void setFord(float amount){
		x+=cosz*amount;
		z+=sinz*amount;
	}
	public void setBack(float amount){
		x-=cosz*amount;
		z-=sinz*amount;
	}
	public void setStrafel(float amount){
		x+=cosb*amount;
		z+=sinb*amount;
	}
	public void setStrafer(float amount){
		x-=cosb*amount;
		z-=sinb*amount;
	}
	public void setHeight(float amount){
		y=amount;
	}

Maybe here is something wrong with the matrix calculation? Because my viewPort etc are initialized like you said…
Please help me, I dont geht the error :’(

There are three common parts to the matrices used in OpenGL: model, view, and projection. In their code, the model and view matrices are combined into the modelview matrix by computing (view * model). The view matrix is often the inverse of the matrix representing the camera or view’s location and orientation in the world. The model matrix represents the location and orientation of the object being rendered in the world.

Looking at how you set up your FPS movement, you’re computing the view matrix. The only thing I see wrong there is that you’re missing a matrix.put(15, 1f) so that the value in the 4th row and column of the matrix has a 1.

Now, the reason you’re seeing the distorted spheres is because of the projection matrix. This is independent from the view matrix and FPS movement. The projection matrix lets you go from 3D to 2D and give it perspective. The gluPerspective function is a convenience function to set the projection matrix, and one of its arguments is the aspect ratio (width / height) of the viewport. I don’t know why you can’t find it since you mentioned you tried it in your first post.

Please post more complete code so I can see how you’re setting up your projection.

Mh, the adding of matrix.put(15,1f) didnt anything…

but here is my projection setup:

if (height <= 0) { height = 1; }
	final float h=(float)width/(float)height;
	gl.glViewport(0, 0, width, height);
	gl.glMatrixMode(gl.GL_PROJECTION);
	gl.glLoadIdentity();
	glu.gluPerspective(45.0f, h, 1.0, 10000.0);
	gl.glMatrixMode(gl.GL_MODELVIEW);
	gl.glLoadIdentity();

or if its still too few, here is my complete source: http://www.xup.in/dl,80364351/src.zip/
I hope its not too complicated :persecutioncomplex:

//Edit: It seems I also have some other problems. I’m also not able to render to texture.
I use this function to render to texture:

 
private void renderToTexture(GL gl, GLU glu) // Renders To A Texture
    {
        gl.glViewport(0, 0, 128, 128);    // Set Our Viewport (Match Texture Size)

        renderScene();      //renders the scene

        // Bind To The Blur Texture
        gl.glBindTexture(GL.GL_TEXTURE_2D, renderTexture);  

        // Copy Our ViewPort To The Blur Texture (From 0,0 To 128,128... No Border)
        gl.glCopyTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_LUMINANCE, 0, 0, 128, 128, 0);

        // Clear The Screen And Depth Buffer
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);      

        gl.glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);  // Set Viewport back to normal size
    }

And my lighting also seems to be wrong. If i enable a simple light, everything is same bright. There are no darker and brighter sides (for example at my box). I dont get it…i also tried to light via Shader, but its the same effect. Everything at the same brightness…

Hi!

Why not using gluLookAt to fill the model-view matrix correctly? Why not using the Texture class?

Sorry this took me so long to get back, I missed that you had posted an update. I looked through your code but unfortunately it crashed because I didn’t have any of the images or shaders.

However, I think I know why you were seeing distortion of your shapes. In Main, you create a window that is 1280x720. You call gluPerspective in two different places, in init() and reshape() in EventListener. Your EventListener.reshape() method is correct because it uses the width and height that are passed in to get the aspect ratio. In init(), you’re using the hardcoded variables w and h, but you’ve set them to 1024 and 768.

I don’t think reshape() is called until you actually resize the window but I might be wrong. In init() you also set the viewport to 1024x768 so I would think that the aspect ratio would be okay.

Anyway, here is some advice in general:

  1. Don’t start using shaders until you can get a simpler program working correctly, you’re just complicating things now
  2. You can get the width and height for your window from the GLAutoDrawable that’s passed into the init() so you don’t need to hardcode w and h in EventListener.
  3. You need to enable lighting in general and each light individually to get lighting to work. You do this glEnable(GL_LIGHTING) and glEnable(GL_LIGHT0) for the first available light. You can also use GL_LIGHT1/2/3 etc. for more lights (up to 8 total lights).
  4. You store a GL instance in Game that you pass in from the EventListener. This is bad design and should not be done. The GL instance is allowed to change and should only be kept within the scope of one of the event listener functions. If Game needs the GL, you should pass the GL as method arguments to the Game methods that need to do OpenGL work.

HTH

thanks for your help
i checked all your advices and changed the hardcoded w and h with the GLAutoDrawable getHeight and getWidth. But nothing changed. It is still distorted :frowning:
I also activated the lighting but now I just get this:

it seems that just the skybox is lightened up. But also not really correct. I dont know whats going on x_x

I’m afraid that the only thing I can help you with is to say start simpler. If you can’t get fixed-function lighting to work in your game, write a simple application that lights a sphere.

You can try and get the lighting and projection working correctly with only that. Right now you have a skybox, particles, textures and GLSL shaders in your game, all of which complicate what you’re trying to do, and where things can go wrong. And since that’s so much, it makes it hard for anyone to easily understand the code you wrote.

If you can create an app with a lit sphere in one Java file, that is a good place to start. If you have the app in one file but the lighting doesn’t work, it will be a lot easier for everyone to help.

yes you are right…anyways thats for you help!

Well, I tried a complete new project and simply put this in:


    public void init(GLAutoDrawable arg0)
    {
        GL2 gl = arg0.getGL().getGL2();
        GLU glu = new GLU();
       
        
        gl.glViewport(0, 0, arg0.getWidth(), arg0.getHeight());
        glu.gluPerspective(45.0f, (float)arg0.getWidth()/(float)arg0.getHeight(), 1.0f, 2000.0f);
	
		

    }
public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int width,
			int height) {
		// TODO Auto-generated method stub
		GL2 gl = arg0.getGL().getGL2();
        GLU glu = new GLU();
        
        
        
        gl.glViewport(0, 0, width, height);
        glu.gluPerspective(90.0f,(float)width/(float)height), 1.0f, 2000.0f);
        		
	}

and put a sphere in the render routine. If i set the screen size for example to 600x600, everything looks normal. But if I set it on 1280x720 for example, everything is streched horizontally. I tried everything on the viewports and it seems that gluPerspective does NOTHING. No matter what i type in as parameters the view is always the same. I guess this is not normal and maybe the problem??

thank you in advance!

In the code that you posted above, you haven’t changed the matrix mode to GL_PROJECTION. In OpenGL, all of the matrix editing commands work on one matrix at a time (these commands are glTranslate, glRotate, glMultMatrix, glLoadMatrix, glLoadIdentity, and gluPerspective). There are two main matrices: the modelview and the projection. By default, the current matrix is the modelview, so when you call gluPerspective(), you’re putting the projection matrix onto the modelview. This will lead to strange behavior, but I can’t determine exactly what because I don’t know if you’re editing the modelview later on or not.

Anyway, here is a full application that should have some simple lighting and correctly sets the projection matrix:


import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.gl2.GLUT;


public class SphereTest implements GLEventListener {
    public static void main(String[] args) {
        GLCanvas canvas = new GLCanvas();
        canvas.addGLEventListener(new SphereTest());
        
        JFrame window = new JFrame();
        window.setSize(800, 500);
        window.add(canvas);
        
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);
        
        Animator anim = new FPSAnimator(canvas, 60);
        anim.start();
    }

    @Override
    public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        
        gl.glEnable(GL2.GL_DEPTH_TEST);
        gl.glEnable(GL2.GL_LIGHTING);
        gl.glEnable(GL2.GL_LIGHT0); // Just use default light setup for now
        
        // These two lines make calls to glColor act like glMaterial for the
        // diffuse color of the material.
        gl.glColorMaterial(GL2.GL_FRONT_AND_BACK, GL2.GL_DIFFUSE);
        gl.glEnable(GL2.GL_COLOR_MATERIAL);
        
        setCamera(gl, drawable.getWidth(), drawable.getHeight());
    }

    @Override
    public void dispose(GLAutoDrawable drawable) {
        // do nothing
    }

    @Override
    public void display(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        
        gl.glClearColor(0f, 0f, 0f, 1f);
        gl.glClear(GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_COLOR_BUFFER_BIT);
        
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0f, 0f, -10f);
        
        gl.glColor3f(.5f, .5f, .5f);
        new GLUT().glutSolidSphere(4f, 16, 16);
    }

    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        setCamera(drawable.getGL().getGL2(), width, height);
    }
    
    private void setCamera(GL2 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
        
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        new GLU().gluPerspective(60f, width / (float) height, .1f, 100f);
    }
}

Here are some screenshots to show that it at least works for:


Very much THANKS!
Now it works correctly! Sorry for my noobishness!

Well, if its ok for you i have one last question, i tried to make a Framebuffer object, but always when i check the framebuffer with glCheckFramebufferStatus i get an error code, so that i cant use the frambuffer :frowning:
I set it up like this:


    void generateShadowFBO(GL2 gl)
    {
    	int shadowMapWidth = RENDER_WIDTH * SHADOW_MAP_RATIO;
    	int shadowMapHeight = RENDER_HEIGHT * SHADOW_MAP_RATIO;
    	
    	//GLfloat borderColor[4] = {0,0,0,0};
    	
    	int FBOstatus;
    	
    	// Try to use a texture depth component
    	gl.glGenTextures(1, depthTextureId);
    	gl.glBindTexture(GL2.GL_TEXTURE_2D, depthTextureId);
    	
    	// GL_LINEAR does not make sense for depth texture. However, next tutorial shows usage of GL_LINEAR and PCF. Using GL_NEAREST
    	gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
    	gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
    	
    	// Remove artefact on the edges of the shadowmap
    	gl.glTexParameterf( GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP );
    	gl.glTexParameterf( GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP );
    	
    	// This is to allow usage of shadow2DProj function in the shader
    	gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE);
    	gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_COMPARE_FUNC, GL2.GL_LEQUAL);
    	gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); 
    	
    	
    	
    	// No need to force GL_DEPTH_COMPONENT24, drivers usually give you the max precision if available 
    	gl.glTexImage2D( GL2.GL_TEXTURE_2D, 0, GL2.GL_DEPTH_COMPONENT, shadowMapWidth, shadowMapHeight, 0, GL2.GL_DEPTH_COMPONENT, GL2.GL_UNSIGNED_BYTE, 0);
    	gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);
    	
    	// create a framebuffer object
    	gl.glGenFramebuffers(1, fboId);
    	gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, fboId);
    	
    	// Instruct openGL that we won't bind a color texture with the currently binded FBO
    	gl.glDrawBuffer(GL2.GL_NONE);
    	gl.glReadBuffer(GL2.GL_NONE);
    	
    	// attach the texture to FBO depth attachment point
    	gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, GL2.GL_DEPTH_ATTACHMENT,GL2.GL_TEXTURE_2D, depthTextureId, 0);
    	
    	// check FBO status
    	FBOstatus = gl.glCheckFramebufferStatusEXT(GL2.GL_FRAMEBUFFER);
    	if(FBOstatus != GL2.GL_FRAMEBUFFER_COMPLETE)
    		System.out.println("GL_FRAMEBUFFER_COMPLETE_EXT failed, CANNOT use FBO\n");
    	
    	// switch back to window-system-provided framebuffer
    	gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
    }

I need it for a simple shadow. Would it also be possible to render the screen simply to a texture?
Thank you! and it would be ok if you dont want to help me anymore :smiley:

Off the top of my head, I don’t see much wrong with the code. I do have a couple of suggestions:

  1. It is odd that the last argument to glTexImage2D is 0. Normally the int/long argument is used to take data from a buffer object, but you’re not doing that (this might cause an OpenGL error which then breaks all your later commands …). Try passing in null instead to say no data is sent to the texture.
  2. Try moving the glTexImage2D command to before you set the glTexParameteri’s. Maybe your driver is getting confused when you do glTexImage2D and wiping out your previous parameters, which would no longer make your texture complete. This is a guess though.
  3. Similarly, move glFramebufferTexture2D to before you modify the glDrawBuffer and glReadBuffer
  4. Look at some FBO code I wrote here: http://code.google.com/p/ferox-gl/source/browse/trunk/ferox-jogl/src/com/ferox/renderer/impl/jogl/FramebufferObject.java. This does depend on my engine, but it should still be pretty readable. Also, it has a switch that checks the exact error that glCheckFramebufferStatusEXT is returning, so you can use that code to get a better reason for failure.

HTH

Mhm, i checked your code, and also tried your tips, but nothing helped.
Then I tried to call this lines:

System.out.println(glCapabilities.getPbufferRenderToTexture());
System.out.println(glCapabilities.getPbufferRenderToTextureRectangle());

And I got two times false. Could it be that my drivers dont support framebuffers / render to texture? or is this something other?

PbufferRenderToTexture() is something else. Pbuffers are heavyweight offscreen buffers that can be rendered into that came before FBOs were invented. At first they would do render-to-texture by copying their data to a texture with glCopyTexImage2D or similar. Then there was an extension to link a pbuffer’s contents with a texture, very similar to how FBOs work and that is what the getPbufferRenderToTexture() refers to.

My bet is that if that returns false, you have an old card and then it’s reasonable to think FBOs won’t work, or that you’re on an OS that didn’t get around to handling the pbuffer render-to-texture.

Off hand, if you tried my suggestions, what was the error code returned by glCheckFramebufferStatusEXT()?

Mhm, Im running on windows 7 x64 and a Radeon HD 6970 + Geforce 250 GT…

The error is FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT (code: 36055)

I tried using your code to set an FBO but I did not get any framebuffer completeness errors, everything worked fine. I did have to change your code a little to make it work. I passed null as the last argument to glTexImage2D(), and had to make fboId and depthTextureId int arrays. I think that was a typo on your part when posting, though, since it shouldn’t let you compile if fboId was just a simple int.

Anyway, here is my complete code that I used that ran everything correctly for me. If you run this and get errors, then I think there are problems with your graphics card and/or drivers and you’ll want to try updating them because your code looks and behaves fine on my computer.


import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;

import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.FPSAnimator;


public class FBOTest implements GLEventListener {
    public static void main(String[] args) {
        GLCanvas canvas = new GLCanvas();
        canvas.addGLEventListener(new FBOTest());
        
        JFrame window = new JFrame();
        window.setSize(800, 500);
        window.add(canvas);
        
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);
        
        Animator anim = new FPSAnimator(canvas, 60);
        anim.start();
    }

    @Override
    public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        
        int shadowMapWidth = 1024;
        int shadowMapHeight = 1024;
         
        int fboStatus;
         
        // Try to use a texture depth component
        int[] depthTextureId = new int[1];
        gl.glGenTextures(1, depthTextureId, 0);
        gl.glBindTexture(GL2.GL_TEXTURE_2D, depthTextureId[0]);
         
        // GL_LINEAR does not make sense for depth texture. However, next tutorial shows usage of GL_LINEAR and PCF. Using GL_NEAREST
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
         
        // Remove artefact on the edges of the shadowmap
        gl.glTexParameterf( GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP );
        gl.glTexParameterf( GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP );
         
        // This is to allow usage of shadow2DProj function in the shader
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_COMPARE_FUNC, GL2.GL_LEQUAL);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY);
         
         
         
        // No need to force GL_DEPTH_COMPONENT24, drivers usually give you the max precision if available
        gl.glTexImage2D( GL2.GL_TEXTURE_2D, 0, GL2.GL_DEPTH_COMPONENT, shadowMapWidth, shadowMapHeight, 0, GL2.GL_DEPTH_COMPONENT, GL2.GL_UNSIGNED_BYTE, null);
        gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);
         
        // create a framebuffer object
        int[] fboId = new int[1];
        gl.glGenFramebuffers(1, fboId, 0);
        gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, fboId[0]);
         
        // Instruct openGL that we won't bind a color texture with the currently binded FBO
        gl.glDrawBuffer(GL2.GL_NONE);
        gl.glReadBuffer(GL2.GL_NONE);
         
        // attach the texture to FBO depth attachment point
        gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, GL2.GL_DEPTH_ATTACHMENT,GL2.GL_TEXTURE_2D, depthTextureId[0], 0);
         
        // check FBO status
        fboStatus = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);
        if(fboStatus != GL2.GL_FRAMEBUFFER_COMPLETE)
            System.out.println("GL_FRAMEBUFFER_COMPLETE_EXT failed, CANNOT use FBO: " + fboStatus);
        else
            System.out.println("Framebuffer created successfully");
         
        // switch back to window-system-provided framebuffer
        gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
    }

    @Override
    public void dispose(GLAutoDrawable drawable) {
        // do nothing
    }

    @Override
    public void display(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        
        gl.glClearColor(0f, 0f, 0f, 1f);
        gl.glClear(GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_COLOR_BUFFER_BIT);
    }

    @Override
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
        // do nothing
    }
}

Wow!
That was really it!
I used IntBuffers for fboId and depthTextureId but it seems that this was wrong. changing them to int arrays solved the problem!!
VERY MUCH THANKS!! :slight_smile: