nilsk

glsl clipPlane bugs

Discussion created by nilsk on Oct 11, 2012
Latest reply on Oct 22, 2012 by nilsk

Using geometry shaders results in all kinds of strange behaviour regarding clip planes. I cobbled together a small test case demonstrating the issues.

First in case 0 it looks like gl_ClipVertex gets ignored completely if it is written in the geometry shader. If only a vertex shader is used or if neither the vertex shader nor the geometry shader write to ClipVertex clipping works as expected.

In case 1 writing to gl_ClipDistance[i] fails for all indices but 0, unrolling the loop works though.

Case 2 shouldn't work at all, pos should be vec4[3] but the program compiles, links and is validated but visual studio reports two access violations while debugging and following draw calls with that shader fail and generate errors.

I experimented with different #version settings but got buggy results whatever i tried.

 

Os: Windows 7 64

Graphics Chipset    ATI Radeon HD 5800 Series

Device ID    6898

Driver Packaging Version    8.982-120727a-145524C-ATI

Catalyst Version: 12.8

OpenGL Version: 6.14.10.11762

 

 

Header 1

#include "stdafx.h"

#include "GL/glew.h"

#include "GL/glut.h"

#include <vector>

 

GLuint program;

 

 

#define CASE_0

//#define CASE_1

//#define CASE_2

 

#define WORKING

//#define BUGED

 

//adding a geometry shader and writing gl_ClipVertex will be ignored

#ifdef CASE_0

#ifdef WORKING

#define USE_GEOMETRY_SHADER

const char *vs_source =

"#version 120\n"

"void main(void) {                        "

"  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"

"}";

const char *gs_source =

"//#extension GL_EXT_geometry_shader4 : require\n"

"void main(void) {\n        "

"    for(int i = 0; i < 3; ++i){\n"

"        gl_Position = gl_PositionIn[i];\n"

"    EmitVertex();\n"

"    }"

"}\n";

#endif

#ifdef BUGED

#define USE_GEOMETRY_SHADER

const char *vs_source =

"#version 120\n"

"void main(void) {                        "

"  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"

"  gl_ClipVertex = gl_ModelViewMatrix*gl_Vertex;\n"

"}";

const char *gs_source =

"//#extension GL_EXT_geometry_shader4 : require\n"

"void main(void) {\n        "

"    for(int i = 0; i < 3; ++i){\n"

"        gl_Position = gl_PositionIn[i];\n"

"        gl_ClipVertex = gl_ClipVertexIn[i];\n"

"    EmitVertex();\n"

"    }"

"}\n";

#endif

#endif

 

//writing gl_ClipDistance[i] in a loop ignores the ClipDistance[1], unrolling the loop works as expected

#ifdef CASE_1

#define USE_GEOMETRY_SHADER

const char *vs_source =

"#version 120\n"

"varying vec4 pos\n;"

"void main(void) {"

"  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"

"  pos = gl_ModelViewMatrix * gl_Vertex;\n"

"}\n";

#ifdef WORKING

const char *gs_source =

"//#version 150\n"

"#extension GL_EXT_geometry_shader4 : require\n"

"varying in vec4 pos[3];\n"

"void main(void) {\n"

"    for(int i = 0; i < 3; ++i){\n"

"        gl_Position = gl_PositionIn[i];\n"

"        gl_ClipDistance[0] = dot(pos[i], gl_ClipPlane[0]);\n"

"        gl_ClipDistance[1] = dot(pos[i], gl_ClipPlane[1]);\n"

"        EmitVertex();\n"

"    }"

"}\n";

#endif

#ifdef BUGED

#define USE_GEOMETRY_SHADER

const char *gs_source =

"//#version 150\n"

"#extension GL_EXT_geometry_shader4 : require\n"

"varying in vec4 pos[3];\n"

"void main(void) {\n"

"    for(int i = 0; i < 3; ++i){\n"

"        gl_Position = gl_PositionIn[i];\n"

"        for(int k = 0; k < 2; ++k){\n"

"            gl_ClipDistance[k] = dot(pos[i], gl_ClipPlane[k]);\n"

"        }\n"

"        EmitVertex();\n"

"    }"

"}\n";

#endif

#endif

 

 

//pos should be vec4[3] but it compiles, links and validates but genaretes access violation at runtime and drawing fails afterwards

#ifdef CASE_2

#define USE_GEOMETRY_SHADER

const char *vs_source =

"#version 120\n"

"varying vec4 pos\n;"

"void main(void) {"

"  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"

"  pos = gl_ModelViewMatrix * gl_Vertex;\n"

"}\n";

#ifdef BUGED

const char *gs_source =

"//#version 150\n"

"#extension GL_EXT_geometry_shader4 : require\n"

"varying in vec4 pos;\n"

"void main(void) {\n"

"    for(int i = 0; i < 3; ++i){\n"

"        gl_Position = gl_PositionIn[i];\n"

"        gl_ClipDistance[0] = dot(pos, gl_ClipPlane[0]);\n"

"        EmitVertex();\n"

"    }"

"}\n";

#endif

#endif

 

const char *fs_source =

"#version 120\n"

"void main(void) {\n"

"  gl_FragColor = vec4(1.0, 0,0,1);\n"

"}\n";

 

void printCompileError(GLuint obj){

    GLint logLength;

    glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);

    std::vector<GLcharARB> errorLog(logLength,0);

    glGetInfoLogARB(obj, logLength,0,&errorLog[0]);

    fprintf(stderr, &errorLog[0]);

}

 

int init_resources(){

    GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;

    program = glCreateProgram();

 

    GLuint vs = glCreateShader(GL_VERTEX_SHADER);

    glShaderSource(vs, 1, &vs_source, NULL);

    glCompileShader(vs);

    glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok);

    if (0 == compile_ok){

        fprintf(stderr, "Error in vertex shader\n");

        printCompileError(vs);

        return 0;

    }

 

    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(fs, 1, &fs_source, NULL);

    glCompileShader(fs);

    glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok);

    if (!compile_ok){

        fprintf(stderr, "Error in fragment shader\n");

        printCompileError(fs);

        return 0;

    }

 

    glAttachShader(program, vs);

    glAttachShader(program, fs);

 

#ifdef USE_GEOMETRY_SHADER

    GLuint gs = glCreateShader(GL_GEOMETRY_SHADER);

    glShaderSource(gs, 1, &gs_source, NULL);

    glCompileShader(gs);

    glGetShaderiv(gs, GL_COMPILE_STATUS, &compile_ok);

    if (!compile_ok){

        fprintf(stderr, "Error in geometry shader\n");

        printCompileError(gs);

        return 0;

    }

    glAttachShader(program, gs);

 

    glProgramParameteriARB(program, GL_GEOMETRY_INPUT_TYPE_ARB, GL_TRIANGLES);

    glProgramParameteriARB(program, GL_GEOMETRY_OUTPUT_TYPE_ARB, GL_TRIANGLE_STRIP);

    glProgramParameteriARB(program, GL_GEOMETRY_VERTICES_OUT_ARB, 3);

#endif

 

    glLinkProgram(program);

    glGetProgramiv(program, GL_LINK_STATUS, &link_ok);

    if (!link_ok) {

        fprintf(stderr, "glLinkProgram:");

        printCompileError(program);

        return 0;

    }           

    glutReportErrors();

    return 1;

}

 

 

void onDisplay()

{

    glClearColor(0.0, 0.0, 0.0, 1.0);

    glClear(GL_COLOR_BUFFER_BIT);

    double plane0[4] = {1.0, 0.0, 0.0, 0.3};

    double plane1[4] = {-1.0, 0.0, 0.0, 0.3};

    glEnable(GL_CLIP_PLANE0);

    glClipPlane(GL_CLIP_PLANE0, plane0);

    glEnable(GL_CLIP_PLANE1);

    glClipPlane(GL_CLIP_PLANE1, plane1);

 

 

    glUseProgram(program);

    glValidateProgram(program);

    int valid;

    glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &valid);

    if(!valid){

        fprintf(stderr, "validation failed");

        return;

    }

 

    glutSolidOctahedron();

    glutReportErrors();

    glutSwapBuffers();

}

 

int main(int argc, char** argv)

{

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);

    glutInitWindowSize(640, 480);

    glutCreateWindow("gltestcase");

 

    GLenum glew_status = glewInit();

    if (glew_status != GLEW_OK)

    {

        fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));

        return EXIT_FAILURE;

    }

 

    if (1 == init_resources())    {

        glutDisplayFunc(onDisplay);

        glutMainLoop();

    }

 

    return 0;

}

Attachments

Outcomes