Hi,
for visualizing tetrahedra, I’ve implemented a geometry shader that uses the four indices of GL_LINES_ADJACENCY_EXT to represent and to render one tetrahedron. In the geometry shader I use this information to generate four triangles that represent the boundary of the scaled element.
This worked fine, till the driver update from version 306.97 to 310.7: There, a strange jitter effect came up, which looks like the triangles are bouncing.
This bug is also present with the latest drivers. I tested it on several nVidia cards (Geforce GTX 590, GTX 680, GTX 560Ti …) with same result, but on an ATI/AMD card it is working fine.
Am I doing something, or is it a driver problem? Can someone please have a look into this?
Please find a minimal sample code below. Remark: If you change the value of tetScale to 1.0 the rendering is fine. If you need additional information, please let me know. I could also provide a video showing the effect.
Best regards, thank you!
Daniel
Code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define STRINGIFY(A) #A
static const char * vsCode = STRINGIFY
(
void main()
{
gl_Position = ftransform();
}
);
static const char *fsCode = STRINGIFY
(
void main()
{
gl_FragColor = vec4(0.5,0.5,0.5,1.0);
}
);
extern const char *gsCode = STRINGIFY
(
#version 120\n
#extension GL_EXT_geometry_shader4 : enable \n
void main()
{
//float tetScale = 1.0;
float tetScale = 0.5;
vec4 vertices[4];
vec4 baryCenter;
for(int i = 0; i < 4; ++i)
{
vertices[i] = gl_PositionIn[i];
baryCenter += vertices[i];
}
baryCenter *= 0.25;
for(int i = 0; i < 4; ++i)
{
vertices[i] = tetScale * vertices[i] + (1.0 - tetScale) * baryCenter;
}
for(int i = 0; i < 4; ++i)
{
for(int j = 0; j < 3; ++j)
{
int modJ = (i % 2 == 1) ? j : 2 - j;
int index = (i + modJ) % 4;
gl_Position = vertices[index];
EmitVertex();
}
EndPrimitive();
}
EndPrimitive();
}
);
GLuint compileProgram(const char *vsource, const char *fsource, const char *gsource)
{
if(GLEW_EXT_geometry_shader4)
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
GLuint geometryShader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
glShaderSource(vertexShader, 1, &vsource, 0);
glShaderSource(fragmentShader, 1, &fsource, 0);
glShaderSource(geometryShader, 1, &gsource, 0);
glCompileShader(vertexShader);
glCompileShader(fragmentShader);
glCompileShader(geometryShader);
GLuint program = glCreateProgram();
int error = glGetError();
glProgramParameteriEXT( program, GL_GEOMETRY_INPUT_TYPE_EXT, GL_LINES_ADJACENCY_EXT);
error = glGetError();
glProgramParameteriEXT( program, GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLES);
error = glGetError();
glProgramParameteriEXT( program, GL_GEOMETRY_VERTICES_OUT_EXT, 12);
error = glGetError();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glAttachShader(program, geometryShader);
glLinkProgram(program);
glDeleteShader(vertexShader); // just flagged for deletion
glDeleteShader(fragmentShader);
glDeleteShader(geometryShader);
// check if program linked
GLint success = 0;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success)
{
glDeleteProgram(program);
program = 0;
}
return program;
}
else
return 0;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "TetViewer", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glewInit();
GLuint tetShaderID = compileProgram(vsCode, fsCode, gsCode);
glUseProgram(tetShaderID);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); //clear background screen to black
//Clear information from last draw
glClear( GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glScalef(0.5,0.5,0.5);
glTranslatef(-0.5,-0.5,0);
glBegin(GL_LINES_ADJACENCY_EXT);
glVertex3f(0, 0, 0);
glVertex3f(0, 0, 1);
glVertex3f(0, 1, 0);
glVertex3f(1, 0, 0);
glEnd();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}