尝试使用LWJGL运行一个简单的GLSL着色器程序,但此代码不起作用

时间:2014-12-11 09:35:00

标签: java opengl glsl lwjgl

我正在尝试使用LWJGL运行这个简单的GLSL着色器代码,但显示仍为黑色。 (toFloatBuffer(float [] array)方法在类中指定并且有效)。

try {
        Display.create();
        Display.setDisplayMode(new DisplayMode(800, 600));
    } catch (LWJGLException e) {
        e.printStackTrace();
    }

    GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());


    //Using buffers
    //bufferStuff();
    //shaderStuff();
    System.out.println(GL11.glGetString(GL11.GL_VERSION) + "\n");

    String vertexShaderSource = 
        "#version 400 core                           \n" +
        "                                            \n" +
        "void main()                                 \n" +
        "{                                           \n" +
        "    gl_Position = vec4(0.0, 0.0, 0.0, 0.0); \n" +
        "}                                           \n";

    String fragmentShaderSource =
        "#version 400 core                            \n" +
        "                                             \n" +
        "out vec4 color;                              \n" +
        "                                             \n" +
        "void main()                                  \n" +
        "{                                            \n" +
        "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" +
        "}                                            \n";

    int vertexShader = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
    GL20.glShaderSource(vertexShader, vertexShaderSource);
    GL20.glCompileShader(vertexShader);
    System.out.println(GL20.glGetShaderInfoLog(vertexShader, GL20.glGetShaderi(vertexShader, GL20.GL_INFO_LOG_LENGTH)));

    int fragmentShader = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
    GL20.glShaderSource(fragmentShader, fragmentShaderSource);
    GL20.glCompileShader(fragmentShader);
    System.out.println(GL20.glGetShaderInfoLog(fragmentShader, GL20.glGetShaderi(fragmentShader, GL20.GL_INFO_LOG_LENGTH)));

    int program = GL20.glCreateProgram();
    GL20.glAttachShader(program, vertexShader);
    GL20.glAttachShader(program, fragmentShader);
    GL20.glLinkProgram(program);
    System.out.println(GL20.glGetProgramInfoLog(program, GL20.glGetProgrami(program, GL20.GL_INFO_LOG_LENGTH)));

    GL20.glDeleteShader(vertexShader);
    GL20.glDeleteShader(fragmentShader);

    int VAO = GL30.glGenVertexArrays();
    GL30.glBindVertexArray(VAO);
    GL11.glPointSize(4);

    while(!Display.isCloseRequested())
    {
        GL30.glClearBuffer(GL11.GL_COLOR, 0, toFloatBuffer(new float[]{0, 0, 0, 1}));

        GL20.glUseProgram(program);

        GL11.glDrawArrays(GL11.GL_POINTS, 0, 3);

        Display.sync(60);
        Display.update();
    }

程序的输出是这个

4.2.11733 Compatibility Profile Context

Vertex shader was successfully compiled to run on hardware.

Fragment shader was successfully compiled to run on hardware.

Vertex shader(s) linked, fragment shader(s) linked.

着色器似乎已经正确编译和链接,并且由我的OpenGL版本支持。 知道我为什么会出现黑屏吗?

2 个答案:

答案 0 :(得分:3)

在你的顶点着色器中,输出总是 vec4(0, 0, 0, 0)这总是位于剪辑空间之外。因为在顶点着色器之后,GPU会将所有组件与第4个组件分开(如果为0)则默认情况下该点位于剪辑空间之外。

因为这是顶点着色器唯一可能的输出,着色器永远不会在屏幕上绘制任何内容。如果用vec4(0.0, 0.0, 0.0, 1.0)替换它,那么屏幕中央会出现一个红点。

答案 1 :(得分:2)

您的片段着色器定位#version 400,并且您已明确告诉它您希望将自己限制为core(顺便说一下,这是默认配置文件)。

gl_FragColor不是 核心 GLSL内置的有效GL。如果要向#version 400 compatibility写任何内容,则需要使用gl_FragColor编写着色器。

您有两个选择:

  1. 重新编写定位#version 400 compatibility

    的着色器
    • 我怀疑这是你想要的,因为你已经开始宣布一个变量:out vec4 color

  2. 输出到color而不是gl_FragColor

  3. 我怀疑你想要选项#2 。虽然在任何情况下都不应该在片段着色器中同时使用用户声明的out变量并写入gl_FragColor,但这是无效的。


      

    OpenGL Shading Language 4.00.9 Specification - 7个内置变量 - p。 87

         
        

    不推荐使用: 写入gl_FragColor指定后续固定功能管道将使用的片段颜色。如果后续的固定功能使用片段颜色并且片段着色器可执行文件的执行不会将值写入gl_FragColor,则消耗的片段颜色未定义。

      

    规范的后续版本使这一点更加清晰:

      

    OpenGL Shading Language 4.20.11 Specification - 7个内置变量 - p。 106

         
        

    使用 兼容性 配置文件时,片段着色器中提供以下片段输出变量:

     out vec4 gl_FragColor;
     out vec4 gl_FragData[gl_MaxDrawBuffers];