OpenGL透视扭曲场景比沿z轴预期的要多得多

我在LWJGL工作,并且一直在努力编写一个程序,允许简单的3D观看场景。 我遇到的主要问题是每当我应用透视时,我的场景在z轴上非常非常远。 不好

中间的正方形是用正投影绘制的立方体(这里的立方体意味着“所有边都相等”)。 从左下角到中心的形状也是一个立方体,但是用透视投影绘制!

显然,这看起来不像一个立方体。 这是我的代码(它有点像墙,所以我把它分解了):

public class OpenGL { //width and height of the screen, plus the depth of the 3d space public static final int WIDTH = 800, HEIGHT = 600, DEPTH = 1000; //called once at startup private static void initGl() { GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glViewport(0,0,WIDTH,HEIGHT); GL11.glDepthFunc(GL11.GL_LESS); GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); GL11.glClearColor(0,0,0,0); GL11.glShadeModel(GL11.GL_SMOOTH); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glOrtho(0, WIDTH, HEIGHT, 0, DEPTH, -DEPTH); GL11.glMatrixMode(GL11.GL_MODELVIEW); DEFAULT_FONT.addAsciiGlyphs(); DEFAULT_FONT.addGlyphs(400, 600); DEFAULT_FONT.getEffects().add(new ColorEffect(java.awt.Color.WHITE)); try { DEFAULT_FONT.loadGlyphs(); } catch (SlickException e) { e.printStackTrace(); } } } 

这些都在另一个类中,每秒被调用30次。

 //main rendering function. public void render() { //these two just input values for different variables, allowing for //movement of the camera and testing different values of znear and zfar. //nothing OpenGL-related is changed. update(); updatePerspectiveTest(); GL11.glMatrixMode(GL11.GL_MODELVIEW); p.render(); //draws the normal cube, the "player" if (perspective) { perspective(); } GL11.glMatrixMode(GL11.GL_MODELVIEW); loadRotationalMatrix(yaw,pitch,roll); loadPositionalMatrix(-y,-x,-z); env.render(); //draws the distorted cube, the "environment" GL11.glLoadIdentity(); ortho(); //render debug data } //resets to orthographic projection public static void ortho() { int i = GL11.glGetInteger(GL11.GL_MATRIX_MODE); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glOrtho(-OpenGL.WIDTH/2, OpenGL.WIDTH/2, OpenGL.HEIGHT/2, -OpenGL.HEIGHT/2, OpenGL.DEPTH/2, -OpenGL.DEPTH/2); GL11.glMatrixMode(i); } 

这是切换视角的function。 这可能是问题所在。

 //activate perspective projection. Maybe something wrong here? public static void perspective() { int i = GL11.glGetInteger(GL11.GL_MATRIX_MODE); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glFrustum(-OpenGL.WIDTH/2, OpenGL.WIDTH/2, OpenGL.HEIGHT/2, -OpenGL.HEIGHT/2, pzNear, pzFar); GL11.glMatrixMode(i); } 

这些函数用于转换。 它们可能不相关,但我认为包含它们是好的。

 //translates the camera via matrix multiplication. public static void loadPositionalMatrix(float x, float y, float z) { FloatBuffer m = BufferUtils.createFloatBuffer(16); m.put(new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }); m.flip(); GL11.glMultMatrix(m); } //sets yaw, pitch and roll using rotational matrices. Not really being used now. public static void loadRotationalMatrix(double pitch, double yaw, double roll) { FloatBuffer Ry = BufferUtils.createFloatBuffer(16); FloatBuffer Rx = BufferUtils.createFloatBuffer(16); FloatBuffer Rz = BufferUtils.createFloatBuffer(16); Rx.put(new float[] { 1, 0, 0, 0, 0, (float) cos(pitch), (float) sin(pitch), 0, 0, (float) -sin(pitch), (float) cos(pitch), 0, 0, 0, 0, 1 }); Ry.put(new float[] { (float) cos(yaw), 0, (float) -sin(yaw), 0, 0, 1, 0, 0, (float) sin(yaw), 0, (float) cos(yaw), 0, 0, 0, 0, 1 }); Rz.put(new float[] { (float) cos(roll), (float) sin(roll), 0, 0, (float) -sin(roll), (float) cos(roll), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }); Rx.flip(); Ry.flip(); Rz.flip(); GL11.glMultMatrix(Rz); GL11.glMultMatrix(Ry); GL11.glMultMatrix(Rx); } 

我玩过zNear和zFar,但到目前为止我没有尝试过的任何值都能产生正确的投影效果。

具体问题是:为什么第二个立方体看起来如此可怕地扭曲,我该怎么做才能纠正它?

矩阵使用剪切平面从3D环境投射到屏幕。 因此,x和y剪裁平面需要考虑窗口的纵横比和FOV。 所以你应该有这样的事情:

 ... double fovyInDegrees = 50; // Change this if you want. double ymax, xmax, aspectRatio; aspectRatio = OpenGL.WIDTH / OpenGL.HEIGHT; ymax = znear * Math.tan(fovyInDegrees * Math.PI / 360); xmax = ymax * aspectRatio; GL11.glFrustum(-xmax, xmax, -ymax, ymax, znear, zfar); ... 

请注意,我刚刚将一些c ++代码更改为Java,因此未对此进行测试。 它在我的代码中工作,所以应该没问题。