It was supposed to be a continuous tube, made out of 5000 instanced rings of 60 cubes each (12 triangles each) on my integrated laptop intel GPU card using OpenGL 3.3.
That was what I got. The distortions you see can also be seen when rendering 1000 or 500 rings, albeit at much lower quantity and severity.
What is causing it? I've disabled polygon smoothing, and it helped immensely, but didn't eliminate the problem. I've also found out that vertex shader variables are highp
by default. There is no front culling either.
Here it is how it is supposed to look (same rendering, but from front, where it is not distorted).
The FPS is about 10. NearZ is 0.01, FarZ is 100, also tried 1..1000, didn't change much, if anything.
Can this possibly be just because I render too many triangles and the solution would be to make less of them?
Shader codes:
const char *VERT_SRC_FSTR =
"#version 330 core\n"
"in vec3 pos;\n"
"flat out int vertexID, instanceID;\n"
"uniform vec3 mov[%d], eye;\n" // %d - RENDERER_MAX_INSTANCE_COUNT
"uniform mat4 proj, view;\n"
"void main(void)\n{\n"
" vertexID = gl_VertexID;\n"
" instanceID = gl_InstanceID;\n"
" vec4 p = proj * view * vec4(pos - eye + mov[gl_InstanceID], 1);\n"
" p.x *= %f;\n" // %f - inversed aspection ratio (9/16)
" gl_Position = p;\n}\n";
const char *FRAG_SRC_FSTR =
"#version 330 core\n"
"flat in int vertexID, instanceID;\n"
"out vec3 clr;\n"
"void main(void)\n{\n"
" clr = vec3(vertexID %% 2, 1, instanceID %% 2);\n}\n";
Is there anything else I can try? Could this be an issue with my driver/graphics card?
Edit: glxinfo
excerpt:
Extended renderer info (GLX_MESA_query_renderer):
Vendor: Intel Open Source Technology Center (0x8086)
Device: Mesa DRI Intel(R) Bay Trail (0xf31)
Version: 12.0.6
Accelerated: yes
Video memory: 1536MB
Unified memory: yes
Preferred profile: core (0x1)
Max core profile version: 3.3
Max compat profile version: 3.0
Max GLES1 profile version: 1.1
Max GLES[23] profile version: 3.0
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) Bay Trail
OpenGL core profile version string: 3.3 (Core Profile) Mesa 12.0.6
OpenGL core profile shading language version string: 3.30
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
Rendering code:
// Rendering draw function:
void rendererDraw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniform3fv(renderer.eyeLoc, 1, rendererInput.eye);
glUniformMatrix4fv(renderer.projLoc, 1, GL_FALSE, rendererInput.proj);
glUniformMatrix4fv(renderer.viewLoc, 1, GL_FALSE, rendererInput.view);
for (struct RendererDrawable *d = rendererInput.drawables; d->vao!=0; ++d)
{
glUniform3fv(renderer.movLoc, d->instanceCount, d->mov);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(d->vao);
glDrawArraysInstanced(d->drawMode, 0, d->pointCount, d->instanceCount);
glfwSwapBuffers(win);
}
glfwSwapBuffers(win);
}
Renderer header:
// Renderer public data:
extern struct RendererInput
{
Vector eye;
Matrix proj, view;
struct RendererDrawable *drawables; // terminated by (drawable->vao == 0)
} rendererInput;
extern struct RendererOutput
{
GLint posLoc;
} rendererOutput;
struct RendererDrawable
{
GLenum drawMode;
GLuint vao, pointCount, instanceCount;
Vector *mov;
};
Drawable setup in engine.c:
void engineInit(void)
{
rendererInput.drawables = calloc(2, sizeof(*rendererInput.drawables));
// rendererInput.drawables[0] - the RING, which is being
// drawn instanced multiple times with different offset (mov)
rendererInput.drawables[0] = drawableCubeCircle();
rendererInput.drawables[0].instanceCount = RENDERER_MAX_INSTANCE_COUNT;
rendererInput.drawables[0].mov[0][0] = 0;
rendererInput.drawables[0].mov[0][1] = 0;
for (int i = 0; i < RENDERER_MAX_INSTANCE_COUNT; ++i) rendererInput.drawables[0].mov[i][2] = i;
cameraInit();
timerFrameReset();
}
A single ring being renderered correctly:
The issue here is not the ring itself, but their "chaining". As you can see in the pictures, most of the time it works correctly, but sometimes there are distortions. Since I'm not generating a mesh and instantiating them instead, the problem could only lie within:
for (int i = 0; i < RENDERER_MAX_INSTANCE_COUNT; ++i) rendererInput.drawables[0].mov[i][2] = i;
but I don't see it there.