glVertexAttribPointer не работает, но ошибок нет - PullRequest
1 голос
/ 24 апреля 2020

Я использовал 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;
}

1 Ответ

1 голос
/ 24 апреля 2020

Поскольку у вас есть отдельные массивы для координат вершин, цветов и координат текстуры, вы задаете отдельные буферы для атрибутов:

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 target, к указанному атрибуту (индексу), в векторе состояний текущего привязанного Vertex Array Object . (См. Спецификация вершины ). Следовательно, надлежащий буфер и VAO должны быть связаны до того, как glVertexAttribPointer.
(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);

Шаг и смещение должны быть указаны в байтах:

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