绘制三角形条时,OpenGL会在原点添加不需要的顶点

时间:2011-09-18 00:06:13

标签: opengl 3d jogl

我的OpenGL应用程序中存在一个问题,OpenGL似乎在我的某些网格的原点添加了一个顶点。这个问题让我感到困惑,因为它似乎只影响由三角形条带组成的网格。在帖子末尾用于创建屏幕截图的基本过程如下:

  1. 使用simple math生成位于单位球体上的顶点,以及纹理坐标和元素索引。
  2. 将步骤1中的数据加载到绑定到VAO的缓冲区中。
  3. 每一帧:绑定VAO并使用glDrawElements()
  4. 绘制

    在发布之前,我在过程的每个阶段检查了我的网格的(简化版本)顶点数据,并且在原点(模型空间)中没有任何顶点。但是,如果您查看帖子末尾的屏幕截图,网格中心显然有一个顶点,它的存在会使我的网格变形并导致纹理问题。

    我对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_POINTSGL_LINE_LOOPGL_TRIANGLE_STRIP

    UPDATE:根据要求,这是设置和绘制顶点数组的代码:

    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 个答案:

答案 0 :(得分:1)

  

gl.glPrimitiveRestartIndex(-1);

这看起来不正确,因为the parameter to glPrimitiveRestartIndex是无符号的。结果是重启索引设置为4294967295。

  

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

在这里,指数是无符号的。 (GLuint)-1 != (GLushort)-1,因此VBO中的“重启”点不会导致重启,它们导致使用索引65535(超出数据范围)被视为(0,0,0)