当我尝试使用着色器(Java)时,OpenGL向我发送一个堆栈下溢错误

问题描述 投票:1回答:1

[我正在用Java用lwjgl 3开发游戏,并且运行正常,但是当我要使用着色器时,OpenGL发送STACK_UNDERFLOW错误(1284)。

我正在使用3个缓冲区:顶点缓冲区,颜色缓冲区,索引缓冲区;

我的旧代码:

    private int vbo;
    private int cbo;
    private int ibo;
    private FloatBuffer buffer;
    private FloatBuffer colorBuffer;
    private IntBuffer indexBuffer;

    private IcoSphere sphere;
    int radius = 200;

    @Override
    public void init() {
        sphere = new IcoSphere(9, radius);
        sphere.generate();
        generateBuffer();
    }

    private void generateBuffer() {
        buffer = BufferUtils.createFloatBuffer(sphere.getVertexCount() * 3);
        colorBuffer = BufferUtils.createFloatBuffer(sphere.getFacesCount() * 4 * 4);
        indexBuffer = BufferUtils.createIntBuffer(sphere.getFacesCount());

        Random r = new Random();
        OpenSimplexNoise noise = new OpenSimplexNoise();

        ArrayList<Vector3f> vertex = sphere.getVertex();
        float[] v = new float[vertex.size() * 3];
        for (int i = 0; i < vertex.size(); i++) {
            vertex.get(i).normalize();
            vertex.get(i).mul(sphere.getRadius() + (float) noise.eval(
                    vertex.get(i).x * 8,
                    vertex.get(i).y * 8,
                    vertex.get(i).z * 8
                ) * 12);
            v[i * 3 + 0] = vertex.get(i).x;
            v[i * 3 + 1] = vertex.get(i).y;
            v[i * 3 + 2] = vertex.get(i).z;
        }
        buffer.put(sphere.getVertexArray());

        indexBuffer.put(sphere.getIndexArray());

        for (int i = 0; i < sphere.getFacesCount(); i++) {
            colorBuffer.put(new float[] {
                    r.nextFloat(), r.nextFloat(), r.nextFloat(), 1,
                    r.nextFloat(), r.nextFloat(), r.nextFloat(), 1,
                    r.nextFloat(), r.nextFloat(), r.nextFloat(), 1
            });
        }

        buffer.flip();
        colorBuffer.flip();
        indexBuffer.flip();

        createBuffer();
    }

    private void createBuffer() {
        vbo = glGenBuffers();
        cbo = glGenBuffers();
        ibo = glGenBuffers();

        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER, cbo);
        glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }

    @Override
    public void update() {

    }

    @Override
    public void render() {
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);

        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glVertexPointer(3, GL_FLOAT, 0, 0);

        glBindBuffer(GL_ARRAY_BUFFER, cbo);
        glColorPointer(4, GL_FLOAT, 0, 0);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

        glDrawElements(GL_TRIANGLES, sphere.getFacesCount() * 3, GL_UNSIGNED_INT, 0);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
    }

添加着色器后的新代码:

GlUtils.glCall(()-> ..);用于捕获opengl错误。

    private int vbo;
    private int cbo;
    private int ibo;
    private FloatBuffer buffer;
    private FloatBuffer colorBuffer;
    private IntBuffer indexBuffer;

    private IcoSphere sphere;
    int radius = 200;

    @Override
    public void init() {
        sphere = new IcoSphere(9, radius);
        sphere.generate();
        generateBuffer();
    }

    private void generateBuffer() {
        buffer = BufferUtils.createFloatBuffer(sphere.getVertexCount() * 3);
        colorBuffer = BufferUtils.createFloatBuffer(sphere.getFacesCount() * 4 * 4);
        indexBuffer = BufferUtils.createIntBuffer(sphere.getFacesCount());

        Random r = new Random();
        OpenSimplexNoise noise = new OpenSimplexNoise();

        ArrayList<Vector3f> vertex = sphere.getVertex();
        float[] v = new float[vertex.size() * 3];
        for (int i = 0; i < vertex.size(); i++) {
            vertex.get(i).normalize();
            vertex.get(i).mul(sphere.getRadius() + (float) noise.eval(
                    vertex.get(i).x * 8,
                    vertex.get(i).y * 8,
                    vertex.get(i).z * 8
                ) * 12);
            v[i * 3 + 0] = vertex.get(i).x;
            v[i * 3 + 1] = vertex.get(i).y;
            v[i * 3 + 2] = vertex.get(i).z;
        }
        buffer.put(sphere.getVertexArray());

        indexBuffer.put(sphere.getIndexArray());

        for (int i = 0; i < sphere.getFacesCount(); i++) {
            colorBuffer.put(new float[] {
                    r.nextFloat(), r.nextFloat(), r.nextFloat(), 1,
                    r.nextFloat(), r.nextFloat(), r.nextFloat(), 1,
                    r.nextFloat(), r.nextFloat(), r.nextFloat(), 1
            });
        }

        buffer.flip();
        colorBuffer.flip();
        indexBuffer.flip();

        createBuffer();
    }

    private void createBuffer() {

        vbo = glGenBuffers();
        cbo = glGenBuffers();
        ibo = glGenBuffers();

        GlUtils.glCall(() -> glBindBuffer(GL_ARRAY_BUFFER, vbo));
        GlUtils.glCall(() -> glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW));
        GlUtils.glCall(() -> glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0));

        GlUtils.glCall(() -> glBindBuffer(GL_ARRAY_BUFFER, cbo));
        GlUtils.glCall(() -> glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW));
        GlUtils.glCall(() -> glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, 0));

        GlUtils.glCall(() -> glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo));
        GlUtils.glCall(() -> glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW));

        GlUtils.glCall(() -> glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
        GlUtils.glCall(() -> glBindBuffer(GL_ARRAY_BUFFER, 0));

    }

    @Override
    public void update() {

    }

    @Override
    public void render() {
        Shader.MAIN.bind();

        GlUtils.glCall(() -> glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0));

        GlUtils.glCall(() -> glEnableVertexAttribArray(0));
        GlUtils.glCall(() -> glEnableVertexAttribArray(1));


        GlUtils.glCall(() -> glDrawElements(GL_TRIANGLES, indexBuffer));

        GlUtils.glCall(() -> glDisableVertexAttribArray(0));
        GlUtils.glCall(() -> glDisableVertexAttribArray(1));

        Shader.MAIN.unbind();
    }

我的着色器:

碎片

#version 410

out vec4 vertColor;

void main(){
    gl_FragColor = vertColor;
}

Vert

#version 410

layout (location=0) in vec3 position;

void main()
{
    gl_Position = vec4(position, 1.0);
}
java opengl shader lwjgl
1个回答
0
投票

使用着色器程序时,可以使用客户端功能,以与以前相同的方式绘制网格。您要做的就是使用glEnableVertexAttribArrayglVertexAttribPointer而不是glEnableClientStateglVertexPointerglColorPointer

创建缓冲区:

vbo = glGenBuffers();
cbo = glGenBuffers();
ibo = glGenBuffers();

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, cbo);
glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW);

绘制网格

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, cbo);
glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, 0);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, sphere.getFacesCount() * 3, GL_UNSIGNED_INT, 0);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);

您实际要做的是使用默认的Vertex Array Object(0)作为规格。注意,默认的VAO(0)仅在兼容性配置文件OpenGL Context中有效。


这可以通过使用命名的Vertex Array Object进行改进。注意,您必须在核心配置文件OpenGL Context中使用命名的VAO:

private int vao;
vao = glGenVertexArrays();
vbo = glGenBuffers();
cbo = glGenBuffers();
ibo = glGenBuffers();

glBindVertexArray(vao);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, cbo);
glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW);

glBindVertexArray(0);

顶点数组规范在顶点数组对象中说明。因此,不需要glDisableVertexAttribArray。此外,Index buffersGL_ELEMENT_ARRAY_BUFFER)在VAO中也有说明。 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);将破坏绑定。

现在在绘制网格时绑定VAO就足够了:

glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, sphere.getFacesCount() * 3, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

您有2种颜色属性,即顶点坐标和颜色。这2个属性是Vertex Shader的输入。顶点坐标用于设置gl_Position。颜色必须传递到Fragment Shader。它是顶点着色器的输出,也是片段着色器的输入。在片段着色器中,颜色被写入gl_FragColor

顶点着色器:

layout (location=0) in vec3 position;
layout (location=1) in vec4 color;

void main()
{
    vertColor = color;
    gl_Position = vec4(position, 1.0);
}

片段着色器:

#version 410

in vec4 vertColor;

void main()
{
    gl_FragColor = vertColor;
}
© www.soinside.com 2019 - 2024. All rights reserved.