我无法更改片段着色器

时间:2016-08-30 21:07:43

标签: java opengl shader lwjgl

我正在学习OpenGL,我试图绘制一个红色三角形,但我的三角形保持黑色。

这是我的片段着色器的代码:

#version 330 core

out vec4 color;

void main()
{
    color = vec4(1,0,0,1);
}

我的着色器编译没有问题,我使用这个类来使用着色器:

public class ShaderProgram
{
    private final int programId;

    private int vertexShaderId;

    private int fragmentShaderId;

    public ShaderProgram() throws Exception
    {
        programId = glCreateProgram();
        if (programId == 0) {
            throw new Exception("Could not create Shader");
        }
    }

    public void createVertexShader(String shaderCode) throws Exception {
        vertexShaderId = createShader(shaderCode, GL_VERTEX_SHADER);
    }

    public void createFragmentShader(String shaderCode) throws Exception {
        fragmentShaderId = createShader(shaderCode, GL_FRAGMENT_SHADER);
    }

    protected int createShader(String shaderCode, int shaderType) throws Exception {
        int shaderId = glCreateShader(shaderType);
        if (shaderId == 0) {
            throw new Exception("Error creating shader. Code: " + shaderId);
        }

        glShaderSource(shaderId, shaderCode);
        glCompileShader(shaderId);

        if (glGetShaderi(shaderId, GL_COMPILE_STATUS) == 0) {
            throw new Exception("Error compiling Shader code: " + glGetShaderInfoLog(shaderId, 1024));
        }

        glAttachShader(programId, shaderId);

        return shaderId;
    }

    public void link() throws Exception {
        glLinkProgram(programId);
        if (glGetProgrami(programId, GL_LINK_STATUS) == 0) {
            throw new Exception("Error linking Shader code: " + glGetShaderInfoLog(programId, 1024));
        }

        glValidateProgram(programId);
        if (glGetProgrami(programId, GL_VALIDATE_STATUS) == 0) {
            System.err.println("Warning validating Shader code: " + glGetShaderInfoLog(programId, 1024));
        }

    }

    public void bind() {
        glUseProgram(programId);
    }

    public void unbind() {
        glUseProgram(0);
    }

    public void cleanup() {
        unbind();
        if (programId != 0) {
            if (vertexShaderId != 0) {
                glDetachShader(programId, vertexShaderId);
            }
            if (fragmentShaderId != 0) {
                glDetachShader(programId, fragmentShaderId);
            }
            glDeleteProgram(programId);
        }
    }
}

然后这是我的Game类:

public class Game {

    int vertexArrayID;
    int vertexBufferID;

    ShaderProgram fragmentShader;
    ShaderProgram vertexShader;

    float[] vertexData =
        {
            -1.0f, -1.0f, 0.0f,
            1.0f, -1.0f, 0.0f,
            0.0f,  1.0f, 0.0f,
        };

    FloatBuffer vertexBuffer;

    public Game() throws Exception {
        vertexArrayID = glGenVertexArrays();
        glBindVertexArray(vertexArrayID);

        vertexBufferID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);

        vertexBuffer = BufferUtils.createFloatBuffer(vertexData.length);
        vertexBuffer.put(vertexData);
        vertexBuffer.flip();

        glBufferData(GL_ARRAY_BUFFER, vertexBuffer,GL_STATIC_DRAW);

        fragmentShader = new ShaderProgram();
        vertexShader = new ShaderProgram();

        fragmentShader.createFragmentShader(loadShader("fragmentShader.glsl"));
        vertexShader.createVertexShader(loadShader("vertexShader.glsl"));

        fragmentShader.link();
        vertexShader.link();
    }

    public void update()
    {
        fragmentShader.bind();
        vertexShader.bind();

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,vertexBufferID);
        glVertexAttribPointer(0,3,GL_FLOAT,false,0,0);

        glDrawArrays(GL_TRIANGLES,0,3);
        glDisableVertexAttribArray(0);

        fragmentShader.unbind();
        vertexShader.unbind();
    }

    private String loadShader(String input) {
        String r = "";

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(Game.class.getResourceAsStream("/shaders/" + input)));
            String buffer = "";
            while ((buffer = reader.readLine()) != null) {
                r += buffer + "\n";
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return r;
    }
}

为什么我的三角形在此之后保持黑色?

1 个答案:

答案 0 :(得分:6)

您似乎误解了在OpenGL中使用程序和着色器。

Shader个对象对应于" Shader Stages"在OpenGL中,即顶点着色器或片段着色器或OpenGL图形管道中的其他可编程阶段之一。

Program个对象对应于Shader Stages的组合链,有时也称为完整的Shader"。

然而,在你的程序中,你似乎正在做的是创建两个程序,将顶点着色器附加到一个程序并将片段着色器附加到另一个,并使用它们。据我所知,这不会导致OpenGL抛出错误(它只是在缺少哪个阶段使用基本的直通着色器)但这也意味着只有其中一个阶段会在任何时候,否定对方。在您的情况下,update函数中的代码:

fragmentShader.bind();
vertexShader.bind();

表示只使用了顶点着色器,这就是为什么对片段着色器进行更改无效。

要解决此问题,请仅创建一个ShaderProgram对象,并将Vertex和Fragment着色器源代码附加到该对象,并分别调用create[X]Shader。将其链接一次,然后在update函数中,只需拨打use一次。一旦你完成了这个程序,该程序应该按预期工作。