gl_FragDepth破坏颜色。

4

看起来我的电脑上无法使用gl_FragDepth。除此之外,我的程序工作正常,没有glsl错误,glGetError返回0,但我无法从片段着色器中写入深度缓冲区。

此外,在gl_FragDepth中写入会改变像素颜色的红色分量。

这是我程序的简化版本。我删除了所有无用的东西(我猜?),但它并没有变得更好:

int        main(void)
{
//  These are custom structures for handling shader programs.
    t_glprog                prog;
    t_glprog                prog2;

    GLuint                  vbo;
    GLFWwindow              *window;
    static const GLfloat    vertab[] =
    {
        -1.0, -1.0, 1.0,
        1.0, -1.0, 1.0,
        1.0, 1.0, 1.0,
        -1.0, 1.0, 1.0
    };

    char const *vert =
        "attribute vec3 Coord;"
        "void main() {\
        gl_Position = vec4(Coord, 1.0);\
        }";

    char const *frag1 =
        "void main () {\
        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\
        gl_FragDepth = sin(gl_FragCoord.x * 0.1);\
        }";

    char const *frag2 =
        "void main () {\
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\
        gl_FragDepth = cos(gl_FragCoord.x * 0.1);\
        }";

    if (!glfwInit())
    {
        fprintf(stderr, "GLFW failed to init.\n");
        return (-1);
    }

    glfwWindowHint(GLFW_DEPTH_BITS, 64);
    window = glfwCreateWindow(640, 480, "TEST", NULL, NULL);
    if (window == NULL)
    {
        fprintf( stderr, "Failed to open GLFW window.\n" );
        glfwTerminate();
        return (-1);
    }
    glfwMakeContextCurrent(window);

//  For Windows.
    if (glewInit() != GLEW_OK)
    {
        fprintf(stderr, "Failed to initialize GLEW\n");
        return (-1);
    }

    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glClearDepth(1.0);
    glViewport(0, 0, 640, 480);

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertab), vertab, GL_STATIC_DRAW);

    create_shaders_prog(&prog, vert, frag1);
    create_shaders_prog(&prog2, vert, frag2);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glUseProgram(prog.prog);
    glDrawArrays(GL_QUADS, 0, 4);

    glUseProgram(prog2.prog);
    glDrawArrays(GL_QUADS, 0, 4);

    glFlush();
    glfwSwapBuffers(window);

    while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
            glfwWindowShouldClose(window) == 0)
    {
        glfwPollEvents();
    }
    return (0);
}

这段代码本应该画出红色和绿色条纹,但实际上只能看到模糊的红线。如果我删掉第二条命令,效果也是一样的。 在Windows系统下会出现这种情况。我在OSX上测试正常。

这里是从glGetString中获取到的一些规格:

    GL_VENDOR : Intel
    GL_RENDERER : Mobile Intel(R) 4 Series Express Chipset Family
    GL_VERSION : 2.1.0 - Build 8.15.10.1892
    GL_SHADING_LANGUAGE_VERSION : 1.20 - Intel Build 8.15.10.1892

你的应用程序能否使用OpenGL 3.2或更高版本,而不是OpenGL 2.1? - Matt Fichman
你不需要在事件循环内部绘制吗? - Reto Koradi
我的电脑不支持OpenGL 3.2,我以为gl_FragDepth自glsl 1.1起就可用。而且,我不需要循环,也没有动画。 - Procrade
@Procrade 你用的是什么集成显卡芯片组?我曾经有一台老旧的戴尔笔记本,在使用多个渲染目标时遇到了类似的问题。后来发现驱动程序有缺陷,所以我就无法使用那个功能了。如果你能提供芯片组信息,我们可以搜索一下,看看你的问题是否是已知问题。 - Matt Fichman
@MattFichman 这是一款英特尔的 GMA 4500M 显卡。 - Procrade
@Procrade,你最近尝试过升级你的GPU驱动程序吗? - Matt Fichman
1个回答

1

你的集成显卡驱动程序是否可能卡在这行代码上?

glfwWindowHint(GLFW_DEPTH_BITS, 64);

64位的深度缓冲区太多了。24位是更典型的值。如果不支持64位深度缓冲区,上下文创建应该失败,但我曾经看到一些OpenGL驱动程序在深度缓冲区没有正确设置时出现了奇怪的行为。


根据我阅读的GLFW文档,那只是一个提示而不是硬性限制。它应该尽可能获取更多的深度位数。 - JWWalker
1
是的,没错。但是这假设驱动程序在尝试使用错误的深度缓冲区设置时会向GLFW返回错误。不幸的是,驱动程序(特别是集成显卡的Windows OpenGL驱动程序)并不总是很好地遵循规范。无论如何,我想这可能值得一试,所以我发布了答案 :) - Matt Fichman
@JWWalker 我同意Matt的观点,大多数显卡只支持24位/深度缓冲区,一些更好的显卡支持32位(但通常仅在其他缓冲区具有较小的位宽或分辨率或两者都有时)。我从未见过比这更好的。一些糟糕的图形驱动程序甚至会允许您使用更大的深度缓冲区,即使硬件不支持它(我上次看到这是在集成SiS图形卡上)。请参见What is the proper OpenGL initialisation on Intel HD 3000?了解如何初始化像素格式... - Spektre
测试过了,使用glfwWindowHint(GLFW_DEPTH_BITS, 24),或者移除这个调用:什么都没有改变 :( - Procrade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接