【问题标题】:glVertexAttribPointer doesn't seem to work, but no errorsglVertexAttribPointer 似乎不起作用,但没有错误
【发布时间】:2020-04-23 23:47:01
【问题描述】:

我一直在使用 LWJGL 3 和 LearnOpenGL.com 上的教程来创建游戏引擎。但是,按照教程后,我发现glVertexAttribPointer 的使用不起作用。它在上传顶点位置和索引时有效,但是当我尝试上传颜色和纹理坐标时,什么都没有发生,我只是得到一个白框。我附上了渲染引擎、主类和着色器的源代码:

public class Mesh {
    public float[] vertices;
    public float[] colors;
    public float[] textureCoords;
    public int[] indices;

    public Mesh(float[] vertices, float[] colors, float[] textureCoords, int[] indices) {
        this.vertices = vertices;
        this.colors = colors;
        this.textureCoords = textureCoords;
        this.indices = indices;
    }
}

public class MasterRenderer {
    private int vbo;
    private int vao;
    private int ebo;

    private Mesh mesh;

    private ShaderProgram program;

    public void Init(Mesh mesh) {
        this.mesh = mesh;

        program = new ShaderProgram();

        vao = GL30.glGenVertexArrays();

        vbo = GL20.glGenBuffers();
        ebo = GL20.glGenBuffers();
    }

    public void Render(Color clearColor) {
        // Clear Screen
        GL11.glClearColor(clearColor.getRed(), clearColor.getGreen(), clearColor.getBlue(), clearColor.getAlpha());
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

        // Bind vao
        GL30.glBindVertexArray(vao);

        // Bind Buffers
        GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo);
        GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.vertices, GL20.GL_STATIC_DRAW);

        GL20.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, ebo);
        GL20.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, mesh.indices, GL20.GL_STATIC_DRAW);

        // Enable vertex attribPointers
        GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
        GL20.glEnableVertexAttribArray(0);

        // Handle Textures
        Texture texture = Utils.LoadTexture("resources//textures//test.png");

        // Uniforms


        // Use Program
        program.UseProgram();

        // Draw the shape
        GL20.glActiveTexture(GL20.GL_TEXTURE0);
        GL20.glBindTexture(GL20.GL_TEXTURE_2D, texture.getId());

        GL30.glBindVertexArray(vao);
        GL20.glDrawElements(GL20.GL_TRIANGLES, 6, GL20.GL_UNSIGNED_INT, 0);
    }
}

public class ShaderProgram {
    public int programID;

    public int vertexShaderID;
    public int fragmentShaderID;

    public ShaderProgram() {
        programID = GL20.glCreateProgram();

        try {
            CompileVertexShader(Utils.LoadResource("resources/shaders/default/defaultShader.vs"));
            CompileFragmentShader(Utils.LoadResource("resources/shaders/default/defaultShader.fs"));

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

            if(GL20.glGetShaderi(vertexShaderID, GL20.GL_COMPILE_STATUS) == 0) {
                Logger.LogErrorClose("Error compiling vertex shader code: " + GL20.glGetShaderInfoLog(vertexShaderID, 1024));
            }

            if(GL20.glGetShaderi(fragmentShaderID, GL20.GL_COMPILE_STATUS) == 0) {
                Logger.LogErrorClose("Error compiling fragment shader code: " + GL20.glGetShaderInfoLog(fragmentShaderID, 1024));
            }

            GL20.glLinkProgram(programID);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void UseProgram() {
        GL20.glUseProgram(programID);
        GL20.glDeleteShader(vertexShaderID);
        GL20.glDeleteShader(fragmentShaderID);
    }

    public void CompileVertexShader(String shaderCode) {
        vertexShaderID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);

        GL20.glShaderSource(vertexShaderID, shaderCode);
        GL20.glCompileShader(vertexShaderID);
    }

    public void CompileFragmentShader(String shaderCode) {
        fragmentShaderID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);

        GL20.glShaderSource(fragmentShaderID, shaderCode);
        GL20.glCompileShader(fragmentShaderID);
    }
}

public class Texture {
    private int id;

    public Texture(int id){
        this.id = id;
    }

    public int getId(){
        return id;
    }
}

public class FoodFight {
    public static void main(String[] args) {
        Logger.LogMessage("Running on LWJGL Version: " + Version.getVersion());

        Window w = new Window();

        long window = w.CreateWindow(640, 360, "Food Fight");

        MasterRenderer renderer = new MasterRenderer();

        float[] vertices = {
                 0.5f,  0.5f, 0f,
                 0.5f, -0.5f, 0f,
                -0.5f, -0.5f, 0f,
                -0.5f,  0.5f, 0f
        };
        float[] colors = {
                1f, 0f, 0f,
                0f, 1f, 0f,
                0f, 0f, 1f,
                1f, 1f, 0f
        };
        float[] textureCoords = {
                 1f, 1f,
                 1f, 0f,
                 0f, 0f,
                 0f, 1f
        };
        int[] indices = {
            0, 1, 3,
            1, 2, 3
        };

        Mesh m = new Mesh(vertices, colors, textureCoords, indices);

        renderer.Init(m);

        while(!w.ShouldClose(window)) {
            Input.ProcessInput(window);

            renderer.Render(Color.black);

            w.HandleWindow(window);
        }

        w.DestroyWindow(window);
    }
}

片段:

#version 330 core

in vec3 color;
in vec2 texCoords;

out vec4 fragColor;

uniform sampler2D inputTexture;

void main() {
    fragColor = texture(inputTexture, texCoords) * vec4(color, 1.0);
}

顶点:

#version 330 core

in vec3 aPos;
in vec3 aColor;
in vec2 aTexCoord;

out vec3 color;
out vec2 texCoord;

void main() {
    gl_Position = vec4(aPos, 1.0);
    color = aColor;
    texCoord = aTexCoord;
}

【问题讨论】:

    标签: java opengl glsl shader lwjgl


    【解决方案1】:

    由于顶点坐标、颜色和纹理坐标具有单独的数组,因此您必须为属性指定单独的缓冲区:

    vbo_ver = GL20.glGenBuffers();
    vbo_col = GL20.glGenBuffers();
    vbo_tex = GL20.glGenBuffers();
    

    创建并初始化缓冲区对象的数据存储

    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_ver);
    GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.vertices, GL20.GL_STATIC_DRAW);
    
    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_col);
    GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.colors, GL20.GL_STATIC_DRAW);
    
    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_tex);
    GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.textureCoords, GL20.GL_STATIC_DRAW);
    

    通过layout qualifiers在顶点着色器中指定属性索引:

    #version 330 core
    
    layout(location = 0) in vec3 aPos;
    layout(location = 1) in vec3 aColor;
    layout(location = 2) in vec2 aTexCoord;
    

    glVertexAttribPointer 将当前绑定到ARRAY_BUFFER 目标的缓冲区与当前绑定Vertex Array Object 的状态向量中的指定属性(索引)相关联。 (见Vertex Specification)。 因此,必须在 glVertexAttribPointer 之前绑定正确的缓冲区和 VAO。
    ELEMENT_ARRAY_BUFFER)在 VAO 中声明,因此必须在指定索引缓冲区之前绑定 VAO):

    GL30.glBindVertexArray(vao);
    
    GL20.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, ebo);
    GL20.glBufferData(GL20.GL_ELEMENT_ARRAY_BUFFER, mesh.indices, GL20.GL_STATIC_DRAW);
    
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);
    GL20.glEnableVertexAttribArray(2);
    
    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_ver);
    GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
    
    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_col);
    GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, 0, 0);
    
    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo_tex);
    GL20.glVertexAttribPointer(2, 2, GL11.GL_FLOAT, false, 0, 0);
    

    或者,您可以将顶点和属性放入 1 个数组:

    float[] attributes = {
    //   x      y     z     r   g   b     u   v
         0.5f,  0.5f, 0f,   1f, 0f, 0f,   1f, 1f,  
         0.5f, -0.5f, 0f,   0f, 1f, 0f,   1f, 0f,
        -0.5f, -0.5f, 0f,   0f, 0f, 1f,   0f, 0f,
        -0.5f,  0.5f, 0f,   1f, 1f, 0f    0f, 1f
    };
    
    vbo = GL20.glGenBuffers();
    
    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo);
    GL20.glBufferData(GL20.GL_ARRAY_BUFFER, mesh.attributes, GL20.GL_STATIC_DRAW);
    

    步幅和偏移量必须在 bates 中指定:

    GL20.glBindBuffer(GL20.GL_ARRAY_BUFFER, vbo);
    
    int stride = 8 * 4; // the tuple size is 8 (x y z r g b u v), sizeof float is 4
    
    GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, stride, 0);
    GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, stride, 3*4);
    GL20.glVertexAttribPointer(2, 2, GL11.GL_FLOAT, false, stride, 6*4);
    

    【讨论】:

    • 谢谢!教程说要把它们放在同一个数组中,但这对我来说没有意义。感谢您的帮助!
    • @Shakier 是的,当然,您可以将它们全部放在同一个数组中,但是顶点规范必须有点不同。您必须指定步幅和偏移量。我已经扩展了答案。
    • @Shakier 问题解决了吗?请阅读What should I do when someone answers my question?
    猜你喜欢
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多