Reputation: 125
I'm developing simple game (Kula world clone) for mobile devices (currently on android devices). The problem is that sometimes I get additional (no missing) triangles on random models in game, all in undeterministic fashion (triangles appears on random models on random places between application runs). Also it is sometimes almost unnoticeable on my HTC phone, but always massive on my Nexus 7 tablet.
I am using OpenGL ES 2 and SDL2. Application is written in C++ for code portability.
I was thinking about some buggy model loading code, but I think that it would be deterministic and there would be also some missing triangles not only additional. But the fact that it's non-deterministic and device depended leads me that it is more likely some bug in rendering.
Here are some screenshots:
From my HTC Desire C:
and
Much worse on my Nexus 7:
Vertex shader source:
attribute vec3 position;
attribute vec2 tc;
uniform mat4 mvp;
varying vec2 coord;
varying vec3 color;
void main() { gl_Position = mvp*vec4(position,1); coord = tc; }
and model drawing code:
void Entity::draw(GLuint HpositionAttrib, GLuint HtcAttrib, GLuint HtextureUniform, GLuint HmvpUniform, glm::mat4 tmvp)
{
glUniformMatrix4fv(HmvpUniform, 1, GL_FALSE, glm::value_ptr(localTransforms(tmvp)));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glUniform1i(HtextureUniform, 0);
glEnableVertexAttribArray(HpositionAttrib);
glEnableVertexAttribArray(HtcAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glVertexAttribPointer(HpositionAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLubyte *)NULL + offsetof(vertex, position));
glVertexAttribPointer(HtcAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLubyte *)NULL + offsetof(vertex, uvmap));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
#ifdef DEBUG
SDL_Log("buffer: %d vertex: %d elements: %d\n",VBOSize, sizeof(GLushort), VBOSize/sizeof(GLushort));
#endif
glDrawElements(GL_TRIANGLES, VBOSize/sizeof(unsigned short), GL_UNSIGNED_SHORT, NULL);
glDrawElements(GL_TRIANGLES, VBOSize/sizeof(GLushort), GL_UNSIGNED_SHORT, NULL);
glDisableVertexAttribArray(HpositionAttrib);
glDisableVertexAttribArray(HtcAttrib);
}
//Edit: I have addresed issues metioned by Andon M. Coleman
And there is definition of VBOSize: It is instance variable declared:
size_t VBOSize, EBOSize;
and is initialized as follows:
VBOSize(vertices.size()*sizeof(vertex)), EBOSize(indexes.size()*sizeof(GLushort))
Where vertices is:
std::vector<vertex> vertices;
std::vector<GLushort> indexes;
These vectors are initialised from external file.
And I am using it like this:
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, VBOSize, &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &elementBufferObject);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObject);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, EBOSize, &indexes[0], GL_STATIC_DRAW);
Upvotes: 0
Views: 466
Reputation: 43319
Why are you using GLuint
for some things, but where it really matters you are matching GL_UNSIGNED_SHORT
with your C compiler's intrinsic unsigned short
? GLushort
is the proper typedef to use, the majority of the time GLushort
will probably be unsigned short
, but if there were ever a time where this typedef was not the same it would definitely be on an embedded platform.
Also, do not cast the result of offsetof
to (void *)
. size_t
(which the offsetof
macro uses) does not have to be the same size as your platform's native data pointer type (if anything, it will be less than or equal to the pointer size). Consider (GLubyte *)NULL + offsetof (...)
instead. Using a size_t
value in pointer arithmetic is safe, but casting size_t
to a pointer is not.
Neither one of these things is likely to fix your problem, but they are portability issues that you should avoid. The real problem is almost certainly related to overrunning your element array. GL can use indices that are out-of-range without crashing, in fact outside of WebGL most OpenGL and OpenGL ES implementations do not even define any common behavior for out-of-range buffer access.
I would like to know how VBOSize
is defined, as this is most likely the culprit.
You are using the wrong size in your call to glDrawElements (...)
it should be the number of elements in your Index Buffer (EBOSize
you have called it). Thus, glDrawElements(GL_TRIANGLES, EBOSize/sizeof(GLushort), GL_UNSIGNED_SHORT, NULL);
should fix your problem.
Upvotes: 1