OpenGL透视图使场景扭曲的程度远超出沿z轴的预期 [英] OpenGL perspective distorting scene much more than expected along z axis
问题描述
我在LWJGL中工作,苦苦挣扎了一段时间来编写一个程序,该程序允许对场景进行简单的3D观看.我遇到的主要问题是,每当我应用透视图时,我的场景就会在z轴上延伸得非常远.
I'm working in LWJGL and have been struggling for a while to write a program that allows for simple 3d viewing of a scene. The major issue that I'm running into is that whenever I apply perspective, my scene is stretched very, very far in the z axis.
中间的正方形是用正投影投影的立方体(这里的立方体表示两边都相等").从左下角到中心 的形状也是一个立方体,但是使用透视投影绘制!
The square in the middle is a cube drawn with orthographic projection (here cube means "all sides are equal"). The shape trailing from the bottom left to the center is also a cube, but drawn with perspective projection!
显然,这看起来不像多维数据集.这是我的代码(有点像墙,所以我把它弄碎了):
Obviously, this does not not look like a cube. Here is my code (it is a bit of aa wall, so I've broken it up):
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次.
These are all in another class and are called 30 times a second.
//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);
}
这是打开透视图的功能.这可能是问题所在.
This is the function that switches perspective on. This is probably where the problem is.
//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);
}
这些函数用于转换.它们可能不相关,但是我认为将它们包括在内是很好的.
These functions are used for transformations. They may not be relevant, but I figured it was good to include them.
//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,但到目前为止,我尝试过的任何值都无法得出正确的投影.
I've played around with zNear and zFar, but no values that I have tried so far result in correct projection.
具体问题是:为什么第二个立方体看上去如此可怕地扭曲了,我该怎么做才能纠正它?
The specific question is this: why does the second cube appear so hideously distorted, and what can I do to correct it?
推荐答案
矩阵使用裁剪平面从3D环境投影到屏幕.因此,x和y裁剪平面需要考虑窗口的宽高比以及FOV.所以你应该有这样的东西:
The clipping planes are used by the matrix to project from the 3D environment to your screen. So the x and y clipping planes need to account for the aspect ratio of your window, and the FOV. So you should have something like this:
...
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,因此未经测试.它可以在我的代码中工作,所以应该没问题.
Note that I've just changed some of my c++ code to Java, so this isn't tested. It works in my code though, so should be fine.
这篇关于OpenGL透视图使场景扭曲的程度远超出沿z轴的预期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!