本文介绍了LWJGL投影矩阵-什么都不会发生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我正在尝试在LWJGL中创建Camera类,但是我一直遇到投影矩阵问题.由于某些原因,当我尝试将顶点乘以投影矩阵时,屏幕上什么也没有出现.

Currently, I'm attempting to create a Camera class in LWJGL, but I've been running into a problem with the projection matrix. For some reason, when I try to multiply the vertices by the projection matrix, nothing at all appears on screen.

相机类别

public class Camera {

private Vector3f position, rotation;
private Matrix4f view;

private final Vector3f xAxis, yAxis, zAxis;

private float fov, aspect, zNear, zFar;
private Matrix4f projection;

public Camera(float fov, float aspect, float zNear, float zFar){
    this.fov = fov;
    this.aspect = aspect;
    this.zNear = zNear;
    this.zFar = zFar;

    projection = createPerspectiveProjection(fov, aspect, zNear, zFar);

    position = new Vector3f();
    rotation = new Vector3f();
    view = new Matrix4f();
    view.setIdentity();

    xAxis = new Vector3f(1, 0, 0);
    yAxis = new Vector3f(0, 1, 0);
    zAxis = new Vector3f(0, 0, 1);
}

public void addRotation(float x, float y, float z){
    rotation.x += x;
    rotation.y += y;
    rotation.z += z;

    apply();
}

public void move(float x, float y, float z){
    position.x += x;
    position.y += y;
    position.z += z;

    apply();
}

public Matrix4f getView(){
    return view;
}

public Matrix4f getProjection(){
    return projection;
}

private void apply(){
    view.setIdentity();

    view.rotate(rotation.x, xAxis);
    view.rotate(rotation.y, yAxis);
    view.rotate(rotation.z, zAxis);

    view.translate(position);
}

private Matrix4f createPerspectiveProjection(float fov, float aspect, float zNear, float zFar){
    Matrix4f mat = new Matrix4f();

    float yScale = (float) (1 / (Math.tan(Math.toRadians(fov / 2))));
    float xScale = yScale / aspect;
    float frustrumLength = zFar - zNear;

    mat.m00 = xScale;
    mat.m11 = yScale;
    mat.m22 = -((zFar + zNear) / frustrumLength);
    mat.m23 = -1;
    mat.m32  = -((2 * zFar * zNear) / frustrumLength);
    mat.m33 = 0;

    return mat;
}

}

主班

public class Game implements Runnable {

public static final int WIDTH = 800;
public static final int HEIGHT = 600;

public static final DisplayMode dm = new DisplayMode(WIDTH, HEIGHT);

int vaoID;

ShaderProgram program;
Camera camera;

Model model;

public Game(){
    new Thread(this).start();
}

public void run(){
    init();

    while(true){
        if(Display.isCloseRequested())
            break;

        update(Timer.getElapsedTime());

        render();

        Display.sync(60);
        Display.update();
    }

    Display.destroy();
}

public void init(){
    try{
        Display.setTitle("Ludum Dare!");
        Display.setDisplayMode(dm);
        Display.create();
    }catch(LWJGLException e){
        e.printStackTrace();
        System.exit(1);
    }

    Timer.start();

    camera = new Camera(60.0f, WIDTH / HEIGHT, 0.1f, 100.0f);

    program = new ShaderProgram("res/shader/defaultshader.vert", "res/shader/defaultshader.frag");

    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

    vaoID = glGenVertexArrays();
    glBindVertexArray(vaoID);

    model = new Model(new float[] {
        -1, -1, 1,
        1, -1, 1,
        0, 1, 1
    });
}

public void update(float delta){

}

public void render(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    program.bind();

    program.setUniform("model_matrix", model.getModel());
    program.setUniform("view_matrix", camera.getView());
    program.setUniform("projection_matrix", camera.getProjection());

    model.render();

    program.unbind();
}

public static void main(String[] args){
    new Game();
}

}

顶点着色器

#version 330 core

layout(location = 0) in vec3 vertex_modelspace;

uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;

void main(){
    mat4 modelviewprojection_matrix = projection_matrix * view_matrix * model_matrix;
    vec4 vertex = vec4(vertex_modelspace, 1.0);

    gl_Position = modelviewprojection_matrix * vertex;
}

ShaderProgram类

public class ShaderProgram {

private int vertexShaderID, fragmentShaderID;
private int programID;

public ShaderProgram(String vertPath, String fragPath){
    programID = glCreateProgram();

    vertexShaderID = attachShader(vertPath, GL_VERTEX_SHADER);
    fragmentShaderID = attachShader(fragPath, GL_FRAGMENT_SHADER);
    link();
}

private int attachShader(String path, int type){
    StringBuilder shaderSource = new StringBuilder();

    try{
        BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
        String line;

        while((line = reader.readLine()) != null){
            shaderSource.append(line).append("\n");
        }

        reader.close();
    }catch(IOException e){
        e.printStackTrace();
        System.out.println("Error reading from shader " + path);
        System.exit(1);
    }

    System.out.println("Compiling shader " + path);
    int id = glCreateShader(type);
    glShaderSource(id, shaderSource);
    glCompileShader(id);

    if(glGetShaderi(id, GL_COMPILE_STATUS) == GL_FALSE){
        System.out.println(glGetShaderInfoLog(id, 1000));
        System.exit(1);
    }

    return id;
}

private void link(){
    System.out.println("Linking program...");
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, fragmentShaderID);
    glLinkProgram(programID);
}

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

public void unbind(){
    glUseProgram(0);
}

public void setUniform(String name, Matrix4f value){
    FloatBuffer matrix = BufferUtils.createFloatBuffer(16);
    value.store(matrix); matrix.flip();
    glUniformMatrix4(glGetUniformLocation(programID, name), false, matrix);
}

}

运行此命令时,不会显示我创建的VBO(三角形),但是当我将投影矩阵放在顶点着色器中的乘法运算之外时,它运行良好.我想念什么吗?

When I run this, the VBO that I create (A triangle) doesn't appear, but when I leave the projection matrix out of the multiplication in the vertex shader, it runs just fine. Am I missing something?

推荐答案

我假设model.getModel()将返回单位矩阵(就像您的视图矩阵是单位).在这种情况下,您将遇到以下情况:在平面z = 1.0中绘制一个三角形.如果还使用标识作为投影矩阵,则可以直接在剪辑空间中绘制,并且三角形将位于远平面上,因此它是可见的.

I'm making the assumption that model.getModel() will return the identity matrix (just like your view matrix is identity). In that case, you have the following situation: You draw a triangle in the plane z=1.0. If you use identity as projection matrix also, you directly draw in clip space, and the trianlge will be on the far plane, so it is visible.

但是,您的createPerspectiveProjection函数似乎是在考虑标准OpenGL约定的情况下编写的,因此几乎就像 glFrustum() . (您的代码缺少该联机帮助页中标为A和B的部分,因此您只能使用对称的平截头体,但这在大多数情况下都可以.)用于此矩阵的约定是相机正朝着-z方向看,并且实际上映射了zNearzFar参数,以使z_eye=-zNear处的点投射到近平面(z_ndc=-1) ,并且z_eye=-zFar处的点投影到远平面(z_ndc=1).因此,如果您应用该投影矩阵,则z = 1处的三角形就在相机的后面.

However, your createPerspectiveProjection function seems to be written with the standard OpenGL conventions in mind, so it is almost like what glFrustum(). (Your code is missing the parts which are labeled A and B in that manpage, so you are limited to a symmetric frustum, but that is fine in most cases.)The conventions used for this matrix were that the camera is looking into the -z direction, and the zNear and zFar parameters are actually maped such that a point at z_eye=-zNear is projected to the near plane (z_ndc=-1), and a point at z_eye=-zFar is projected to the far plane (z_ndc=1). So your triangle at z=1 is just behind the camera, if you apply that projection matrix.

这篇关于LWJGL投影矩阵-什么都不会发生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 18:14