LWJGL - чередующийся VAO/VBO не текстурируется

Я пытался перевести рендерер прототипа моей игры из реализации тестирования в непосредственном режиме в реальную реализацию VAO/VBO. VBO рендерится на экране, но отказывается от текстуры. Ниже приведен простейший тестовый класс, который показывает проблему:

public static void main(String[] args) throws Exception {

    //                          VertX,VertY         TexX,  TexY
    float[] data = new float[] {0.0f, 0.0f,     0.25f, 0.75f,
                                0.0f, 64.0f,    0.25f, 1.0f,
                                64.0f, 64.0f,   0.5f, 1.0f,

                                0.0f, 0.0f,     0.25f, 0.75f,
                                64.0f, 64.0f,   0.5f, 1.0f,
                                64.0f, 0.0f,    0.5f, 0.75f};

    glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.err));
    if (!glfwInit())
        throw new IllegalStateException("Unable to initialize GLFW");

    long window = GLFW.glfwCreateWindow(1600, 900, "TEST", 0, 0);
    GLFW.glfwMakeContextCurrent(window);

    GL.createCapabilities();

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, 1600, 900, 0, 0.000001, 100);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    int vboId = glGenBuffers();
    int vaoId = glGenVertexArrays();

    glClientActiveTexture(GL_TEXTURE0);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glBindVertexArray(vaoId);
    glBindBuffer(GL_ARRAY_BUFFER, vboId);

    glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, 4*Float.BYTES, 0);
    glTexCoordPointer(2, GL_FLOAT, 4*Float.BYTES, 4*Float.BYTES);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);   
    glDisableClientState(GL_VERTEX_ARRAY);

    glTranslatef(50, 50, 0);

    Texture t = new Texture(TEST.class.getClassLoader().getResourceAsStream("test/WallFloor.png"));

    while (!GLFW.glfwWindowShouldClose(window)) {
        GLFW.glfwPollEvents();
        GLFW.glfwSwapBuffers(window);

        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);


            glClientActiveTexture(GL_TEXTURE0);
            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);



            glBindVertexArray(vaoId);
            glEnableVertexAttribArray(0);

            t.bind();

            glDrawArrays(GL_TRIANGLES, 0, 6);


            glDisableVertexAttribArray(0);
            glBindVertexArray(0);

            glDisableClientState(GL_TEXTURE_COORD_ARRAY);   
            glDisableClientState(GL_VERTEX_ARRAY);

            /* Equivelent immediate mode code - that works
            t.bind();

            glBegin(GL_TRIANGLES);
            glTexCoord2f(0.25f, 0.75f);
            glVertex2f(0, 0);
            glTexCoord2f(0.25f, 1f);
            glVertex2f(0, 64);
            glTexCoord2f(0.5f, 0.75f);
            glVertex2f(64, 0);

            glTexCoord2f(0.5f, 1f);
            glVertex2f(64, 64);
            glTexCoord2f(0.25f, 1f);
            glVertex2f(0, 64);
            glTexCoord2f(0.5f, 0.75f);
            glVertex2f(64, 0);
            glEnd();
            */

    }
}

Вызов связывания текстуры выглядит следующим образом (где wrap = GL_REPEAT и filter = GL_NEAREST):

public void bind()
{
    glActiveTexture(GL_TEXTURE0);
    glClientActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(target, id);
    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
    glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
    glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
    glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
}

Проведя выходные в поисках ответа, не найдя ответа, я делаю что-то ужасно неправильно? Я также протестировал использование немедленного режима, который по-прежнему отображается с текстурой.

1 ответ

Кроме того, вы смешиваете код профиля ядра (glVertexAttribPointer) с непрофильным профилем (glTexCoordPointer)

Но настоящая проблема заключается в неправильном шаге и смещении. Stride определяет, насколько велики данные одной вершины, а смещение указывает, как далеко от начала каждой вершины начинаются фактические данные. В вашем случае каждая вершина состоит из 4-х чисел, поэтому шаг должен быть 4 * Float.BYTES, Позиции - это первые два числа с плавающей точкой в ​​каждой вершине (смещение 0), а координаты текстуры - это 3-е и 4-е число, что означает offset = 2 * Float.BYTES, Правильный код может выглядеть примерно так (обратите внимание на использование glVertexPointer вместо glVertexAttribPointer):

glVertexPointer(2, GL_FLOAT, false, 4*Float.BYTES, 0);
glTexCoordPointer(2, GL_FLOAT, 4*Float.BYTES, 2*Float.BYTES);

редактировать

Использование ваших VAO также неправильно. При инициализации вы сохраняете glVertexPointer/glTexCoordPointer в VAO vaoId, Но в коде рендеринга вы связываете VAO 0 вместо этого. Скорее всего, настройки атрибута отсутствуют при рисовании. Кроме того, я не совсем уверен, работают ли VAO вместе с вызовами фиксированных функций. В этом случае вы можете удалить все вызовы VAO.

Другие вопросы по тегам