OpenGL добавляет нежелательную вершину в начало координат при рисовании треугольных полос - PullRequest
1 голос
/ 18 сентября 2011

У меня возникла проблема в приложении OpenGL, в которой OpenGL добавляет вершину в некоторые из моих сеток.Этот вопрос меня озадачил, потому что, кажется, он затрагивает только сетки, состоящие из треугольных полос.Основная процедура, используемая для создания скриншота в конце поста, выглядит следующим образом:

  1. Использование простая математика для генерации вершин, которые лежат на единичной сфере, а также текстурыкоординаты и индексы элементов.
  2. Загрузка данных из шага 1 в буферы, привязанные к VAO.
  3. Каждый кадр: связать VAO и рисовать с помощью glDrawElements()

Перед публикацией,Я проверял данные вершин для (упрощенной версии) своей сетки на каждой стадии процесса, и ни разу не было вершины в начале координат (в модельном пространстве).Однако, если вы посмотрите на скриншот в конце поста, очевидно, что в центре меша есть вершина, и ее присутствие деформирует мой меш и вызывает проблемы с текстурированием.

Я не очень разбираюсь в 3D-графике и никогда раньше не слышал о подобных проблемах, поэтому я не уверен, какую другую полезную информацию я могу предоставить.Если есть что-то еще, дайте мне знать в комментариях.

A screenshot from my running application. A model of the Earth is rendered with, from left to right, GL_POINTS, GL_LINE_LOOP, GL_TRIANGLE_STRIP (та же модель Земли, что и GL_POINTS, GL_LINE_LOOP и GL_TRIANGLE_STRIP соответственно)

ОБНОВЛЕНИЕ: По запросу,вот код, который устанавливает и рисует мои массивы вершин:

public void init(GL3 gl){
    //If there is no graphics data, this object isn't going to get rendered and we should just leave
    if(gData == null){
        return;
    }

    //Prepare the index data
    short[] indexData = gData.getIndexArray();
    indexCount = indexData.length;

    //This is required because interleaving the data
    //screws with how the data is laid out in memory
    for(int i = 0; i < indexCount; i++){
        indexData[i] *= gData.getVertexData().size();
        indexData[i] = indexData[i] < 0 ? -1 : indexData[i]; 
    }

    //Put the program together
    glProgram = gl.glCreateProgram();
    for(Shader shader : gData.getShaders()){
        shader.compile(gl);
        gl.glAttachShader(glProgram, shader.location);
    }
    gl.glLinkProgram(glProgram);
    int[] result = new int[1];
    gl.glGetProgramiv(glProgram, GL3.GL_LINK_STATUS, result, 0);
    if(result[0] != GL3.GL_TRUE){
        byte[] info = new byte[512];
        gl.glGetProgramInfoLog(glProgram, 512, result, 0, info, 0);
        Logger.log(new String(info), Logger.ERROR, "GameObject -- init -- Link Error");
    }

    //Interleave the per-vertex data
    float[] vertexData = interleave(gData.getVertexData().toArray(new VertexData[0]));

    //Generate buffers
    gl.glGenVertexArrays(1, glBuffer, 0);
    gl.glGenBuffers(2, glBuffer, 1);
    if(checkGLErrors(gl, "After generating VAO and buffers")){
        sHandler.Quit();
    }

    //Bind the VAO, program, and buffers. In that order.
    gl.glBindVertexArray(glBuffer[0]);
    if(checkGLErrors(gl, "After binding VAO")){
        sHandler.Quit();
    }
    gl.glUseProgram(glProgram);
    if(checkGLErrors(gl, "After binding program")){
        sHandler.Quit();
    }
    gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, glBuffer[1]);
    gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, glBuffer[2]);
    if(checkGLErrors(gl, "After binding buffers")){
        sHandler.Quit();
    }

    //Send in the per-vertex data
    gl.glBufferData(
            GL3.GL_ARRAY_BUFFER,
            vertexData.length * SIZEOF_FLOAT,
            FloatBuffer.wrap(vertexData),
            GL3.GL_STATIC_DRAW);
    if(checkGLErrors(gl, "After loading data into the buffers")){
        sHandler.Quit();
    }

    //Set up pointers to the vertex attributes
    for(VertexData a : gData.getVertexData()){
        a.location = gl.glGetAttribLocation(glProgram, a.name);
        gl.glVertexAttribPointer(a.location, a.components, GL3.GL_FLOAT, false, a.stride * SIZEOF_FLOAT, a.offset * SIZEOF_FLOAT);
        gl.glEnableVertexAttribArray(a.location);
        if(checkGLErrors(gl, "After setting pointers to the vertex attributes")){
            sHandler.Quit();
        }
    }

    //Set up pointers to the uniform variables
    for(UniformData uniform : gData.getUniformData()){
        uniform.location = gl.glGetUniformLocation(glProgram, uniform.name);
        if(checkGLErrors(gl, "After setting pointers to the uniform variables")){
            sHandler.Quit();
        }
    }

    //Send in index data
    gl.glBufferData(
            GL3.GL_ELEMENT_ARRAY_BUFFER, 
            indexData.length * SIZEOF_SHORT, 
            ShortBuffer.wrap(indexData), 
            GL3.GL_STATIC_DRAW);
    if(checkGLErrors(gl, "After loading in index data")){
        sHandler.Quit();
    }

    //Load textures
    for(int i = 0; i < glTextures.length; i++){
        glTextures[i] = gData.getTextureData().get(i).loadTexture(gl);
        if(checkGLErrors(gl, "After loading texture "+i)){
            sHandler.Quit();
        }
    }

    //Bind only the first texture....
    if(glTextures.length >= 1){
        gl.glBindTexture(GL3.GL_TEXTURE_2D, glTextures[0]);
        if(checkGLErrors(gl, "After binding textures")){
            sHandler.Quit();
        }
    }

    //-----BEGIN OPENGL STATE SETTINGS-----

    //Depth Testing
    gl.glEnable(GL3.GL_DEPTH_TEST);
    gl.glDepthFunc(GL3.GL_LEQUAL);

    //Primitive Restart
    gl.glEnable(GL3.GL_PRIMITIVE_RESTART);
    gl.glPrimitiveRestartIndex(-1);

    //Enlargen points
    gl.glPointSize(5.0f);

    //-----END OPENGL STATE SETTINGS-----

    //...And we're done here.
    gl.glBindVertexArray(0);

    if(checkGLErrors(gl, "After completing Object Initialization")){
        sHandler.Quit();
    }
}

public void draw(GL3 gl){
    //Check to see if this object actually needs to be drawn
    if(gData == null){
        return;
    }

    //Bind the vertex array
    gl.glBindVertexArray(glBuffer[0]);
    gl.glUseProgram(glProgram);
    checkGLErrors(gl, "After binding vertex array");

    //Load the uniform data
    for(UniformData uniform: gData.getUniformData()){
        uniform.loadData(gl);
    }
    checkGLErrors(gl, "After loading uniform data");

    //Draw
    gl.glDrawElements(gData.getPrimitive(), indexCount, GL3.GL_UNSIGNED_SHORT, 0);

    //Unbind
    gl.glBindVertexArray(0);

    checkGLErrors(gl, "After finishing draw");
}

1 Ответ

1 голос
/ 18 сентября 2011

gl.glPrimitiveRestartIndex (-1);

Это выглядит неправильно, так как параметр для glPrimitiveRestartIndex не подписан.В результате индекс перезапуска устанавливается равным 4294967295.

gl.glDrawElements (gData.getPrimitive (), indexCount, GL3.GL_UNSIGNED_SHORT, 0);

Издесь индексы без знака короткие.(GLuint)-1 != (GLushort)-1, поэтому точки «перезапуска» в VBO не вызывают перезапуска, они вызывают использование индекса 65535, который вне диапазона данных обрабатывается как (0,0,0).

...