OpenGL 不使用我自己的矩阵绘制

OpenGL doesn't draw with my own matrix

我正在尝试用 opengl.I 制作 2D 游戏 class 绘制 meshes.And 我制作了自己的 Matrix4f class.I 有 3D opengl 经验。 当我将我的 matrix4f 传递给着色器时,它不会 draw.But 当我将它从与三角形出现在 screen.I 上的位置相乘中删除时,它不会 draw.But 从我的 3D 游戏引擎中尝试我的 Matrix4f 但它不起作用还有。

矩阵4f class

package com.game.main.maths;

import java.nio.FloatBuffer;

import com.game.main.util.Util;


public class Matrix4f {

    private float[][] m;

    public Matrix4f() {
        m = new float[4][4];

        initIdentity();
    }

    public Matrix4f initIdentity() {
        for (int x = 0; x < 4; x++)
            for (int y = 0; y < 4; y++) {
                if (x == y)
                    m[x][y] = 1.0f;
                else
                    m[x][y] = 0;

            }

        return this;
    }

    public Matrix4f translate(float x, float y, float z) {
        initIdentity();

        m[0][3] = x;
        m[1][3] = y;
        m[2][3] = z;

        return this;
    }

    public Matrix4f translate(Vector3f pos) {
        initIdentity();

        m[0][3] = pos.getX();
        m[1][3] = pos.getY();
        m[2][3] = pos.getZ();

        return this;
    }

    public Matrix4f rotate(float angle) {
        initIdentity();
        float rad = (float) Math.toRadians(angle);
        float cos = (float) Math.cos(rad);
        float sin = (float) Math.sin(rad);
        m[0][0] = cos;
        m[1][0] = sin;

        m[0][1] = -sin;
        m[1][1] = cos;

        return this;
    }

    public Matrix4f initOrthographic(float left, float right, float bottom,
            float top, float near, float far) {
        initIdentity();

        m[0][0] = 2.0f / (right - left);
        m[1][1] = 2.0f / (top - bottom);
        m[2][2] = 2.0f / (near - far);

        m[0][3] = (left + right) / (left - right);
        m[1][3] = (bottom + top) / (bottom - top);
        m[2][3] = (near + far) / (far - near);

        return this;
    }

    public Matrix4f mul(Matrix4f matrix) {
        Matrix4f result = new Matrix4f();

        for (int y = 0; y < 4; y++) {
            for (int x = 0; x < 4; x++) {
                float sum = 0.0f;
                for (int index = 0; index < 4; index++)
                    sum += m[index][y] * matrix.get(x, index);

                result.set(x, y, sum);
            }
        }

        return result;
    }

    public float[][] getM() {
        return m;
    }

    public float get(int x, int y) {
        return m[x][y];
    }

    public void setM(float[][] m) {
        this.m = m;
    }

    public void set(int x, int y, float value) {
        m[x][y] = value;
    }

    public FloatBuffer toFloatBuffer() {
        return Util.createFlippedBufferBuffer(this);
    }
}

着色器class函数

public void setUniform(String uniformName, Matrix4f matrix){
        int uniformLocation = getUniformLocation(uniformName);

        glUniformMatrix4(uniformLocation, false, matrix.toFloatBuffer());
    }

实用程序class

package com.game.main.util;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import com.game.main.graphics.Vertex;
import com.game.main.maths.Matrix4f;

public class Util {

    public static FloatBuffer createFlippedBuffer(float[] data){
        FloatBuffer buffer = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        buffer.put(data).flip();

        return buffer;
    }

    public static IntBuffer createFlippedBuffer(int[] data){
        IntBuffer buffer = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder()).asIntBuffer();

        buffer.put(data).flip();

        return buffer;
    }

    public static IntBuffer createIntBuffer(int size){
        IntBuffer buffer = ByteBuffer.allocateDirect(size * 4).order(ByteOrder.nativeOrder()).asIntBuffer();
        return buffer;
    }

    public static FloatBuffer createFloatBuffer(int size){
        FloatBuffer buffer = ByteBuffer.allocateDirect(size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        return buffer;
    }

    public static FloatBuffer createFlippedBufferBuffer(Matrix4f matrix){
        FloatBuffer buffer = createFloatBuffer(4 * 4);

        for(int x = 0; x < 4; x++)
            for(int y = 0; y < 4; y++)
            buffer.put(matrix.get(x, y));

        buffer.flip();

        return buffer;
    }

    public static FloatBuffer createFlippedBuffer(Vertex[] vertecies){
        FloatBuffer buffer = createFloatBuffer(vertecies.length * Vertex.SIZE);

        for(int i = 0; i < vertecies.length; i++){
            buffer.put(vertecies[i].getPos().getX());
            buffer.put(vertecies[i].getPos().getY());
            buffer.put(vertecies[i].getPos().getZ());
            buffer.put(vertecies[i].getTexCoord().getX());
            buffer.put(vertecies[i].getTexCoord().getY());
        }

        buffer.flip();

        return buffer;
    }

}

正在初始化矩阵uniform

Matrix4f matrix = new Matrix4f().initOrthographic(0, 800, 0, 600, -1.0f, 1.0f);
        Shader.Object.setUniform("mat", matrix);

顶点着色器

#version 330

layout(location = 0) in vec3 pos;

uniform mat4 mat;

void main(){

gl_Position = mat * vec4(pos, 1.0f);
}

网格class

package com.game.main.graphics;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;

import com.game.main.util.Util;


public class Mesh {

    private int vbo, ibo, size;

    public Mesh(Vertex[] vertecies, int[] indices){
        vbo = glGenBuffers();
        ibo = glGenBuffers();
        size = indices.length;
        createMesh(vertecies, indices);
    }

    private void createMesh(Vertex[] vertecies, int[] indices){
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertecies), GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * 4, 0);
        glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * 4, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }

    public void bind(){
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    }

    public void unbind(){
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }

    public void drawWithBinding()
    {
        bind();
        glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
        unbind();
    }

    public void draw(){
        glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
    }

    public void destroy(){
        glDeleteBuffers(ibo);
        glDeleteBuffers(vbo);
    }
}

顶点class

package com.game.main.graphics;

import com.game.main.maths.Vector2f;
import com.game.main.maths.Vector3f;

public class Vertex {

    private Vector3f pos = new Vector3f();
    private Vector2f texCoord = new Vector2f();
    public static final int SIZE = 5;

    public Vertex(Vector3f pos){
        this(pos, new Vector2f());
    }

    public Vertex(Vector3f pos, Vector2f texCoord){
        this.pos = pos;
        this.texCoord = texCoord;
    }

    public Vector3f getPos() {
        return pos;
    }

    public void setPos(Vector3f pos) {
        this.pos = pos;
    }

    public Vector2f getTexCoord() {
        return texCoord;
    }

    public void setTexCoord(Vector2f texCoord) {
        this.texCoord = texCoord;
    }

}

转置码

public Matrix4f transpose() {
        float m00 = get(0, 0);
        float m01 = get(1, 0);
        float m02 = get(2, 0);
        float m03 = get(3, 0);
        float m10 = get(0, 1);
        float m11 = get(1, 1);
        float m12 = get(2, 1);
        float m13 = get(3, 1);
        float m20 = get(0, 2);
        float m21 = get(1, 2);
        float m22 = get(2, 2);
        float m23 = get(3, 2);
        float m30 = get(0, 3);
        float m31 = get(1, 3);
        float m32 = get(2, 3);
        float m33 = get(3, 3);

        set(0, 0, m00);
        set(0, 1, m01);
        set(0, 2, m02);
        set(0, 3, m03);
        set(1, 0, m10);
        set(1, 1, m11);
        set(1, 2, m12);
        set(1, 3, m13);
        set(2, 0, m20);
        set(2, 1, m21);
        set(2, 2, m22);
        set(2, 3, m23);
        set(3, 0, m30);
        set(3, 1, m31);
        set(3, 2, m32);
        set(3, 3, m33);

        return this;
    }

游戏class

package com.game.main;

import static org.lwjgl.opengl.GL11.*;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

import com.game.main.graphics.Mesh;
import com.game.main.graphics.Shader;
import com.game.main.graphics.Vertex;
import com.game.main.maths.Matrix4f;
import com.game.main.maths.Vector3f;

public class Game{

    private boolean running = false;
    private Mesh mesh;

    public Game(int width, int height){
        try {
            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.setTitle("2D Game");
            Display.create();
        } catch (LWJGLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Matrix4f matrix = new Matrix4f().initOrthographic(-1, 1, -1, 1, -1.0f, 1.0f);
        Shader.Object.setUniform("mat", matrix);

        Vertex[] vertecies = new Vertex[]{
                new Vertex(new Vector3f(0.5f, 0.5f, 0)),
                new Vertex(new Vector3f(0.5f, 0,0)),
                new Vertex(new Vector3f(0, 0.5f,0)),
                new Vertex(new Vector3f(0.5f, 0,0))

        };

        /*float[] vertecies = new float[]{
                -10f, -10f * 9.0f / 16.0f, 1,
                -10f, 10f * 9.0f / 16.0f,1,
                0, 10f * 9.0f / 1.0f,1,
                0, -10f * 9.0f / 6.0f,1
        };*/

        int[] ind = new int[]{
                0, 1, 2,
                2, 3, 0
        };

        mesh = new Mesh(vertecies, ind);
    }

private void init(){
    glEnable(GL_DEPTH_TEST);
}

public void start(){
if(running)
    return;

running = true;

gameLoop();
}

public void stop(){
    if(!running)
        return;

    running = false;
}

private void gameLoop(){
    init();

    long timer = System.currentTimeMillis();
    long lastTime = System.nanoTime();
    double delta = 0;
    int frames = 0, updates = 0;
    while(running){
        long now = System.nanoTime();

        delta += (now - lastTime) / (1000000000.0 / 60.0);

        lastTime = now;

        while(delta >= 1){
            if(Display.isCloseRequested())
                stop();

            update();
            updates++;
            delta--;
        }
        render();
        frames++;

        if(System.currentTimeMillis() - timer >= 1000){
            timer += 1000;
            Display.setTitle("Frames: "+frames+" Updates: "+updates);
            frames = updates = 0;
        }
    }

    destroy();
}

private void update(){

}

private void render(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    Shader.Object.bind();
    mesh.drawWithBinding();
    Shader.Object.unbind();
    Display.update();
}

private void destroy(){
    mesh.destroy();
    Display.destroy();
}

}

看起来你的矩阵是行主矩阵。在将其发送到着色器之前,您需要对其进行转置。

请注意,在 glUniformMatrix4f 中有一个名为 transpose 的布尔参数,但您不能在 opengl es 中使用它 - 文档说它必须为 false - 您必须自己转置它。

看来问题出在统一矩阵的设置上。 OpenGL 是一个状态机,不会记住统一的值。更重要的是,glUniformMatrix4必须在着色器使用时被调用.

目前,矩阵仅在初始化时设置(在 Game 构造函数中),当它需要在 render().

中时
Shader.Object.bind(); //glUseProgram(programHandle)
Shader.Object.setUniform(...) //glUniformMatrix4
mesh.drawWithBinding(); //glDrawElements
Shader.Object.unbind(); //glUseProgram(0), but not necessary unless you want fixed function rendering

如果 mat 没有被设置,它可能是一个零矩阵,它阻止了绘图。


除上述之外,还有两个潜在的问题:

  1. 查看屏幕左下角的像素是否已打开。我怀疑一切正常,just really small。如果以下有效:

    gl_Position = vec4(pos, 1.0f);
    

    本质上是单位矩阵的乘积,接近 ortho(-1,1,-1,1,-1,1)(除了 ortho 调用给出 mat[2][2]=-1),那么我猜你的网格大约是单位立方体的大小。

    引入 mat = initOrthographic(0, 800, 0, 600, -1.0f, 1.0f) 看起来它是为顶点以像素为单位的场景设置的。原点将在左下角,如果网格适合单位立方体,则最多绘制一个像素。

  2. 参见@Jerem 关于 row/column 主矩阵的回答。