I'm having an issue in my OpenGL application where OpenGL appears to add a vertex at the origin of some of my meshes. The issue has me befuddled because it seems to only affect meshes composed of triangle strips. The basic procedure used to create the screenshot at the end of the post is as follows:
- Use simple math to generate vertices that lie on the unit sphere, as well as texture coordinates and element indices.
- Load the data from step 1 into buffers bound to a VAO.
- Every frame: bind the VAO and draw with
glDrawElements()
Prior to posting, I checked the vertex data for (a simplified version of) my mesh at each stage in the process, and at no time is there a vertex at the origin (in model-space). However, if you look at the screenshot at the end of the post, there is obviously a vertex at the center of the mesh, and its presence is deforming my mesh and causing issues with texturing.
I'm pretty inexperienced with 3D graphics, and have never heard of an issue like this before, so I'm not sure what other useful information I can provide. If there's anything else, let me know in the comments.
(The same model of the Earth drawn as GL_POINTS
, GL_LINE_LOOP
, and GL_TRIANGLE_STRIP
, respectively)
UPDATE: As requested, here's the code that sets up and draws my vertex arrays:
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");
}
0,0,0
) – Shahbaz