首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >LWJGL 3投影/透视矩阵不显示?

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

Stack Overflow用户
提问于 2018-06-12 00:56:27
回答 1查看 0关注 0票数 0

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

创建投影矩阵

代码语言:javascript
复制
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;
}

着色器类

代码语言:javascript
复制
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();
}
}

导入矩阵

代码语言:javascript
复制
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);
}
}

渲染器类

代码语言:javascript
复制
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);
}
}

顶点着色器

代码语言:javascript
复制
#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;
}
EN

回答 1

Stack Overflow用户

发布于 2018-06-12 10:54:17

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

无论是m23m32必须交换:

代码语言:javascript
复制
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);

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

代码语言:javascript
复制
GL20.glUniformMatrix4fv(location, true, buffer); // focus on "true"

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

代码语言:javascript
复制
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投影矩阵看起来像这样:

代码语言:javascript
复制
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

其中:

代码语言:javascript
复制
a = w / h
ta = tan( fov_y / 2 );

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

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

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100001666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档