LWJGL 3投影/透视矩阵不显示?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (69)

我到处寻找同样的问题,所有解决方案都无法正常工作。如果我拿出我的投影/透视矩阵,它会呈现正确的,但是当我把它放入时,它会混乱起来。我似乎无法找到它。另外,我正在使用JOML 1.9.9。

创建投影矩阵

public static Matrix4f createProjectionMatrix(float fov, float width, float height, float zNear, float zFar) {
    float aspectRatio = width / height;
    float yScale = (float) ((1f / Math.tan(Math.toRadians(fov / 2f))) * aspectRatio);
    float xScale = yScale / aspectRatio;
    float frustumLength = zFar - zNear;

    Matrix4f projectionMatrix = new Matrix4f();
    projectionMatrix.m00(xScale);
    projectionMatrix.m11(yScale);
    projectionMatrix.m22(-((zFar + zNear) / frustumLength));
    projectionMatrix.m32(-1);
    projectionMatrix.m23(-((2 * zFar * zNear) / frustumLength));
    projectionMatrix.m33(0);
    return projectionMatrix;
}

着色器类

package engine.shaders;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.FloatBuffer;

import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;

public abstract class Shader {
private int programID, vertexShaderID, fragmentShaderID;
private String vertexFile, fragmentFile;

public Shader(String vertexFile, String fragmentFile){
    this.vertexFile = vertexFile;
    this.fragmentFile = fragmentFile;
}

public void create() {
    vertexShaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
    GL20.glShaderSource(vertexShaderID, readFile(vertexFile));
    GL20.glCompileShader(vertexShaderID);
    if (GL20.glGetShaderi(vertexShaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE){
        System.err.println("Error: Vertex Shader - " + GL20.glGetShaderInfoLog(vertexShaderID));
        System.exit(-1);
    }

    fragmentShaderID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
    GL20.glShaderSource(fragmentShaderID, readFile(fragmentFile));
    GL20.glCompileShader(fragmentShaderID);
    if (GL20.glGetShaderi(fragmentShaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE){
        System.err.println("Error: Fragment Shader - " + GL20.glGetShaderInfoLog(fragmentShaderID));
        System.exit(-1);
    }

    programID = GL20.glCreateProgram();

    GL20.glAttachShader(programID, vertexShaderID);
    GL20.glAttachShader(programID, fragmentShaderID);

    bindAttributes();

    GL20.glLinkProgram(programID);
    if (GL20.glGetProgrami(programID, GL20.GL_LINK_STATUS) == GL11.GL_FALSE){
        System.err.println("Error: Program Linking - " + GL20.glGetProgramInfoLog(programID));
        System.exit(-1);
    }

    GL20.glValidateProgram(programID);
    if (GL20.glGetProgrami(programID, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE){
        System.err.println("Error: Program Validating - " + GL20.glGetProgramInfoLog(programID));
        System.exit(-1);
    }
}

public void bind() {
    GL20.glUseProgram(programID);
}

public void remove() {
    GL20.glUseProgram(0);
    GL20.glDetachShader(programID, vertexShaderID);
    GL20.glDetachShader(programID, fragmentShaderID);
    GL20.glDeleteShader(vertexShaderID);
    GL20.glDeleteShader(fragmentShaderID);
    GL20.glDeleteProgram(programID);
}

protected abstract void bindAttributes();

protected void bindAttribute(int attribute, String variableName) {
    GL20.glBindAttribLocation(programID, attribute, variableName);
}

protected abstract void getAllUniforms();

protected int getUniform(String name) {
    return GL20.glGetUniformLocation(programID, name);
}

protected void loadFloatUniform(int location, float value) {
    GL20.glUniform1f(location, value);
}

protected void loadIntUniform(int location, int value) {
    GL20.glUniform1i(location, value);
}

protected void loadVectorUniform(int location, Vector3f value) {
    GL20.glUniform3f(location, value.x, value.y, value.z);
}

protected void loadMatrixUniform(int location, Matrix4f value) {
    FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
    value.get(buffer);
    GL20.glUniformMatrix4fv(location, false, buffer);
}

private String readFile(String file) {
    StringBuilder string = new StringBuilder();
    try {
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line;
        while ((line = reader.readLine()) != null){
            string.append(line).append("\n");
        }
        reader.close();
    } catch (IOException e) {
        System.err.println("Error: Couldn't find file");
        System.exit(-1);
    }
    return string.toString();
}
}

导入矩阵

package engine.shaders;

import org.joml.Matrix4f;

public class BasicShader extends Shader {

private static final String VERTEX_FILE = "src/engine/shaders/basicVertexShader.glsl";
private static final String FRAGMENT_FILE = "src/engine/shaders/basicFragmentShader.glsl";

private int transformationLocation, projectionLocation;

public BasicShader() {
    super(VERTEX_FILE, FRAGMENT_FILE);
}

@Override
protected void bindAttributes() {
    super.bindAttribute(0, "position");
    super.bindAttribute(1, "textCoords");
}

@Override
protected void getAllUniforms() {
    transformationLocation = super.getUniform("transformation");
    projectionLocation = super.getUniform("projection");
}

public void loadTransformationMatrix(Matrix4f matrix) {
    super.loadMatrixUniform(transformationLocation, matrix);
}

public void loadProjectionMatrix(Matrix4f matrix) {
    super.loadMatrixUniform(projectionLocation, matrix);
}
}

渲染器类

package engine.rendering;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;

import engine.maths.MatrixMaths;
import engine.rendering.models.ModelEntity;
import engine.rendering.models.TexturedModel;
import engine.rendering.models.UntexturedModel;
import engine.shaders.BasicShader;

public class Renderer {
private BasicShader shader;

public Renderer(BasicShader shader) {
    this.shader = shader;
    shader.create();
    shader.bind();
    shader.loadProjectionMatrix(MatrixMaths.createProjectionMatrix(70.0f, 800.0f, 600.0f, 0.01f, 1000.0f));
}

public void renderModel(UntexturedModel model){
    GL30.glBindVertexArray(model.getVertexArrayID());
    GL20.glEnableVertexAttribArray(0);
    GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
    GL20.glDisableVertexAttribArray(0);
    GL30.glBindVertexArray(0);
}

public void renderTexturedModel(TexturedModel model){
    GL30.glBindVertexArray(model.getVertexArrayID());
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getMaterial().getTextureID());
    GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);
}

public void renderModelEntity(ModelEntity entity){
    GL30.glBindVertexArray(entity.getModel().getVertexArrayID());
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);
    shader.loadTransformationMatrix(entity.getTransformationMatrix());

    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, entity.getModel().getMaterial().getTextureID());
    GL11.glDrawElements(GL11.GL_TRIANGLES, entity.getModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);
}
}

顶点着色器

#version 150

in vec3 position;
in vec2 textCoords;

out vec2 passTextCoords;

uniform mat4 transformation;
uniform mat4 projection;

void main(void) {
    vec4 worldPos = transformation * vec4(position, 1.0);
    gl_Position = projection * worldPos;
    passTextCoords = textCoords;
}
提问于
用户回答回答于

设置一个列 - 主要顺序矩阵。有三种可能的解决方案:

无论是m23m32必须交换:

Matrix4f projectionMatrix = new Matrix4f();
projectionMatrix.m00(xScale);
projectionMatrix.m11(yScale);
projectionMatrix.m22(-((zFar + zNear) / frustumLength));
projectionMatrix.m32(-((2 * zFar * zNear) / frustumLength));
projectionMatrix.m23(-1);
projectionMatrix.m33(0);

或者矩阵必须在设置时转置:

GL20.glUniformMatrix4fv(location, true, buffer); // focus on "true"

当然,也可以在顶点着色器中将向量从左边乘以矩阵,因为将左边的向量乘以矩阵对应于将它从右边乘以转置矩阵:

gl_Position = worldPos * projection;

要通过指定向量或标量来初始化矩阵,这些分量将按列 - 主次序分配给矩阵元素。 mat4(float, float, float, float, // first column float, float, float, float, // second column float, float, float, float, // third column float, float, float, float); // fourth column

请注意,相比之下,一般的数学矩阵以行优先顺序表示。如果一个矩阵以列为主,那么轴或转换的x,y,z分量直接在存储器中连续存在。访问轴向量或矩阵的平移向量时,这是一个很大的优势。

这意味着一个OpenGL的persepctive投影矩阵看起来像这样:

r = right, l = left, b = bottom, t = top, n = near, f = far

2*n/(r-l)      0              0                0
0              2*n/(t-b)      0                0
(r+l)/(r-l)    (t+b)/(t-b)    -(f+n)/(f-n)    -1    
0              0              -2*f*n/(f-n)     0

其中:

a = w / h
ta = tan( fov_y / 2 );

2 * n / (r-l) = 1 / (ta * a)
2 * n / (t-b) = 1 / ta

如果投影是对称的,那么视线是对称轴的平截头体,那么可以简化矩阵:

1/(ta*a)  0     0              0
0         1/ta  0              0
0         0    -(f+n)/(f-n)   -1    
0         0    -2*f*n/(f-n)    0

所属标签

可能回答问题的人

  • 人生的旅途

    10 粉丝484 提问5 回答
  • 无聊至极

    4 粉丝504 提问5 回答
  • 嗨喽你好

    7 粉丝480 提问4 回答
  • Richel

    8 粉丝0 提问3 回答

扫码关注云+社区

领取腾讯云代金券