OpenGL 正交矩阵无法正常工作
OpenGL Orthographic Matrix Isn't Working Properly
我使用 OpenGL 创建了一个由图块组成的简单 2D 区域。默认情况下,这些图块已相对于屏幕的纵横比进行了拉伸。为了解决这个问题,我尝试使用正交投影矩阵。这是我创建它的方式:
public void createProjectionMatrix() {
float left = 0;
float right = DisplayManager.getScreenWidth();
float top = 0;
float bottom = DisplayManager.getScreenHeight();
float near = 1;
float far = -1;
projectionMatrix.m00 = 2 / (r - l);
projectionMatrix.m11 = 2 / (t - b);
projectionMatrix.m22 = -2 / (f - n);
projectionMatrix.m30 = - (r + l) / (r - l);
projectionMatrix.m31 = - (t + b) / (t - b);
projectionMatrix.m32 = - (f + n) / (f - n);
projectionMatrix.m33 = 1;
}
问题可能出在这里,但我就是找不到。然后我通过创建我的渲染器调用这个方法,将它存储在一个统一变量中并在顶点着色器中使用它,如下所示:
vec4 worldPosition = transformationMatrix * vec4(position, 0, 1);
gl_Position = projectionMatrix * viewMatrix * worldPosition;
其中 projectionMatrix 是一个 mat4,对应于之前创建的正交投影矩阵。
现在除了清晰的颜色渲染外什么都没有。
编辑:
在创建渲染器和创建着色器后立即创建正交投影矩阵并将其加载到着色器中。
public Renderer() {
createOrthoMatrix();
terrainShader.start();
terrainShader.loadProjectionMatrix(projectionMatrix);
terrainShader.stop();
GL11.glEnable(GL13.GL_MULTISAMPLE);
GL11.glClearColor(0, 0, 0.5f, 1);
}
其余矩阵在每次渲染时使用 loadUniforms() 方法传入。
for(Terrain t : batch) {
loadUniforms(t, terrainManager, camera, lights);
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
}
private void loadUniforms(Terrain t, TerrainManager tm, Camera camera, List<Light> lights) {
Matrix4f matrix = Maths.createTransformationMatrix(t.getPosition(), 0, 0, 0, 1);
terrainShader.loadTransformationMatrix(matrix);
terrainShader.loadViewMatrix(camera);
terrainShader.loadNumberOfRows(tm.getNumberOfRows());
terrainShader.loadOffset(t.getOffset());
terrainShader.loadLights(lights);
}
顶点着色器的最终效果如下:
#version 400 core
in vec2 position;
uniform mat4 transformationMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
void main(void) {
vec4 worldPosition = transformationMatrix * vec4(position, 0, 1);
gl_Position = projectionMatrix * viewMatrix * worldPosition;
}
这是一项漫长而艰巨的任务(如果我自己听起来不称职的话)。但是我已经找到了解决我的问题的方法,可能有更好的方法来解决它,但我就是这样做的。
我将 createProjectionMatrix() 更改为
public void createProjectionMatrix() {
float width = Display.getWidth();
float height = Display.getHeight();
float left = -width;
float right = width * 1f;
float top = height * 1f;
float bottom = -height;
float near = 0;
float far = 10;
projectionMatrix.m00 = (2f / (right - left)) * 1000;
projectionMatrix.m11 = (2f / (top - bottom)) * 1000;
projectionMatrix.m22 = 2f / (far - near);
projectionMatrix.m30 = - (right + left) / (right - left);
projectionMatrix.m31 = - (top + bottom) / (top - bottom);
projectionMatrix.m32 = -(far + near) / (far - near);
projectionMatrix.m33 = 1;
}
将 m00 和 m11 乘以一个大数是除了清晰的颜色之外我还能看到任何东西的唯一方法。如果我没记错的话,那是因为渲染器以小于一个像素的速度渲染。 @NicoSchertler 向我提出了这个想法。非常感谢!着色器看起来一样,现在运行良好。如果有人有较少的盗版解决方案,请分享它,因为我很高兴看到它是如何解决的。这是对我很有帮助的link,OpenGL 3+ with orthographic projection of directional light。
我使用 OpenGL 创建了一个由图块组成的简单 2D 区域。默认情况下,这些图块已相对于屏幕的纵横比进行了拉伸。为了解决这个问题,我尝试使用正交投影矩阵。这是我创建它的方式:
public void createProjectionMatrix() {
float left = 0;
float right = DisplayManager.getScreenWidth();
float top = 0;
float bottom = DisplayManager.getScreenHeight();
float near = 1;
float far = -1;
projectionMatrix.m00 = 2 / (r - l);
projectionMatrix.m11 = 2 / (t - b);
projectionMatrix.m22 = -2 / (f - n);
projectionMatrix.m30 = - (r + l) / (r - l);
projectionMatrix.m31 = - (t + b) / (t - b);
projectionMatrix.m32 = - (f + n) / (f - n);
projectionMatrix.m33 = 1;
}
问题可能出在这里,但我就是找不到。然后我通过创建我的渲染器调用这个方法,将它存储在一个统一变量中并在顶点着色器中使用它,如下所示:
vec4 worldPosition = transformationMatrix * vec4(position, 0, 1);
gl_Position = projectionMatrix * viewMatrix * worldPosition;
其中 projectionMatrix 是一个 mat4,对应于之前创建的正交投影矩阵。
现在除了清晰的颜色渲染外什么都没有。
编辑:
在创建渲染器和创建着色器后立即创建正交投影矩阵并将其加载到着色器中。
public Renderer() {
createOrthoMatrix();
terrainShader.start();
terrainShader.loadProjectionMatrix(projectionMatrix);
terrainShader.stop();
GL11.glEnable(GL13.GL_MULTISAMPLE);
GL11.glClearColor(0, 0, 0.5f, 1);
}
其余矩阵在每次渲染时使用 loadUniforms() 方法传入。
for(Terrain t : batch) {
loadUniforms(t, terrainManager, camera, lights);
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
}
private void loadUniforms(Terrain t, TerrainManager tm, Camera camera, List<Light> lights) {
Matrix4f matrix = Maths.createTransformationMatrix(t.getPosition(), 0, 0, 0, 1);
terrainShader.loadTransformationMatrix(matrix);
terrainShader.loadViewMatrix(camera);
terrainShader.loadNumberOfRows(tm.getNumberOfRows());
terrainShader.loadOffset(t.getOffset());
terrainShader.loadLights(lights);
}
顶点着色器的最终效果如下:
#version 400 core
in vec2 position;
uniform mat4 transformationMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
void main(void) {
vec4 worldPosition = transformationMatrix * vec4(position, 0, 1);
gl_Position = projectionMatrix * viewMatrix * worldPosition;
}
这是一项漫长而艰巨的任务(如果我自己听起来不称职的话)。但是我已经找到了解决我的问题的方法,可能有更好的方法来解决它,但我就是这样做的。
我将 createProjectionMatrix() 更改为
public void createProjectionMatrix() {
float width = Display.getWidth();
float height = Display.getHeight();
float left = -width;
float right = width * 1f;
float top = height * 1f;
float bottom = -height;
float near = 0;
float far = 10;
projectionMatrix.m00 = (2f / (right - left)) * 1000;
projectionMatrix.m11 = (2f / (top - bottom)) * 1000;
projectionMatrix.m22 = 2f / (far - near);
projectionMatrix.m30 = - (right + left) / (right - left);
projectionMatrix.m31 = - (top + bottom) / (top - bottom);
projectionMatrix.m32 = -(far + near) / (far - near);
projectionMatrix.m33 = 1;
}
将 m00 和 m11 乘以一个大数是除了清晰的颜色之外我还能看到任何东西的唯一方法。如果我没记错的话,那是因为渲染器以小于一个像素的速度渲染。 @NicoSchertler 向我提出了这个想法。非常感谢!着色器看起来一样,现在运行良好。如果有人有较少的盗版解决方案,请分享它,因为我很高兴看到它是如何解决的。这是对我很有帮助的link,OpenGL 3+ with orthographic projection of directional light。