glVertexAttribPointer似乎不工作,但没有错误。

我一直在使用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);
    }
}

Fragment:

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

解决方案:

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

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

在顶点着色器中,通过以下方式指定属性索引。布局限定词:

#version 330 core

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;

glVertexAttribPointer 将当前绑定的缓冲区关联到以下地址: ARRAY_BUFFER 目标,到指定的属性(索引),在当前绑定的状态向量中。顶点阵列对象. (见 顶点规格).因此,适当的缓冲区和VAO必须在绑定之前 glVertexAttribPointer. (The 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);

或者你可以把顶点和属性放到一个数组中。

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

stride和偏移量必须在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);

给TA打赏
共{{data.count}}人
人已打赏
未分类

如何通过分配和分组obj?

2022-9-8 18:58:25

未分类

如果用户输入错误,如何将用户重定向回开始。

2022-9-8 18:58:27

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索