Java OpenGL没有';我不能用我自己的矩阵画画

Java OpenGL没有';我不能用我自己的矩阵画画,java,opengl,glsl,Java,Opengl,Glsl,我正在尝试用opengl制作一个2D游戏。我制作了绘制网格的类。我还制作了自己的Matrix4f类。我有3D opengl的经验。 当我将matrix4f传递给着色器时,它不会绘制。但是当我将其从与屏幕上显示的三角形位置相乘的过程中移除时,我尝试从3D游戏引擎中使用matrix4f,但效果不佳 Matrix4f类 package com.game.main.maths; import java.nio.FloatBuffer; import com.game.main.util.Util;

我正在尝试用opengl制作一个2D游戏。我制作了绘制网格的类。我还制作了自己的Matrix4f类。我有3D opengl的经验。 当我将matrix4f传递给着色器时,它不会绘制。但是当我将其从与屏幕上显示的三角形位置相乘的过程中移除时,我尝试从3D游戏引擎中使用matrix4f,但效果不佳

Matrix4f类

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);
    }
}
Util类

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;
    }

}
顶点着色器

#version 330

layout(location = 0) in vec3 pos;

uniform mat4 mat;

void main(){

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

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);
    }
}
顶点类

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;
    }
游戏课

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

目前,矩阵仅在初始化时设置(在
游戏
构造函数中),当它需要在
渲染()中时设置

如果未设置
mat
,则可能是一个零矩阵,阻止了绘图


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

  • 查看屏幕左下角,看看那个像素是否亮起。我怀疑一切正常。如果以下各项有效:

    gl_Position = vec4(pos, 1.0f);
    
    它本质上是单位矩阵的乘法,几乎是正交(-1,1,-1,1,-1,1)
  • (除了正交调用给出的
    mat[2][2]=-1
    ),那么我猜你的网格大约是一个单位立方体的大小

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

  • 请参阅@Jerem关于行/列主矩阵的回答


  • 你能提供你画物体的代码吗?我会的,但我不认为这是问题所在。我的形状是在不将矩阵乘以位置的情况下绘制的。我会在回到学校时添加代码。我试图转换它,但它没有;它不起作用。它做了什么?你能在代码中发布你所更改的内容吗?我看到了lwjgl如何转换它;s matrix,我试过了。我编辑了我的帖子,看到了那里的代码。我做了,但仍然不起作用。看到帖子上的代码。我在设置制服之前转置了矩阵。我什么都没试过。我想知道为什么我做3D时,我的矩阵在这里不起作用。@user3723184尝试传递身份矩阵。当你开始工作时,调用
    initOrthographic(-1,1,-1,1,-1,1)
    。除否定
    z
    外,应相同。我还认为Jerem关于行主矩阵的看法是正确的。请尝试一些不同的值,并在作为统一值传递之前对其进行转置。@user3723184,用于在着色器处于使用/活动状态时调用
    glUniformMatrix4
    。目前看来,当
    游戏
    初始化时,您只能调用它一次;我没看见,谢谢。但它仍然不起作用。你能检查一下我的转置方法对不对。
    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();
    }
    
    }
    
    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
    
    gl_Position = vec4(pos, 1.0f);