-1

我使用 Mesa 10.1.3 能够在我的 Linux 计算机上使用 OpenGL 3.3。我在创建窗口时请求核心配置文件,因为只有核心配置文件具有 OpenGL 3.3。但是当我尝试编写一个简单的程序来在屏幕上显示一个三角形时,我什么也没得到。所以我以为我在代码的某个地方搞砸了,但我重新检查了它,它是正确的。为了测试这一点,我尝试在 Windows 中运行该程序,它可以正常工作。所以我对代码进行了更多的实验;我将顶点着色器中的顶点位置乘以 0.001,然后我才能看到我的三角形,但即便如此,它也无法正常工作。我看到的三角形是直角三角形,而我希望它是等边三角形(在 Windows 中,我看到的是等边三角形)。所以我的猜测是使用 OpenGL Core 配置文件时顶点位置有所不同,但我不太清楚如何解决这个问题。我做错了什么,我应该怎么做?

顺便说一句,这是我的顶点着色器的样子:

#version 330

in vec3 position;

void main()
{
  gl_Position = vec4(0.001*position, 1.0);
}

片段着色器:

#version 330

out vec4 fragColor;

void main()
{
  fragColor = vec4(0.0, 1.0, 1.0, 1.0);
}

着色器类:

public Shader()
    {
    program = glCreateProgram();
    if(program == 0)
    {
        System.err.println("Shader creation failed: Could not find valid memory location");
        System.exit(1);
    }
    }

    public void bind()
    {
    glBindAttribLocation(program, 0, "position");
    glUseProgram(program);
    }

    public void addVertexShader(String text)
    {
    addProgram(text, GL_VERTEX_SHADER);
    }

    public void addFragmentShader(String text)
    {
    addProgram(text, GL_FRAGMENT_SHADER);
    }

    public void addGeometryShader(String text)
    {
    addProgram(text, GL_GEOMETRY_SHADER);
    }

    public void compile()
    {
    glLinkProgram(program);

    if(glGetProgrami(program, GL_LINK_STATUS) == 0)
    {
        System.err.println(glGetProgramInfoLog(program, 1024));
        System.exit(1);
    }

    glValidateProgram(program);

    if(glGetProgrami(program, GL_VALIDATE_STATUS) == 0)
    {
        System.err.println(glGetProgramInfoLog(program, 1024));
        System.exit(1);
    }
    }

    public void addProgram(String text, int type)
    {
    int shader = glCreateShader(type);

    if(shader == 0)
    {
        System.err.println("Shader creation failed");
        System.exit(1);
    }

    glShaderSource(shader, text);
    glCompileShader(shader);

    if(glGetShaderi(shader, GL_COMPILE_STATUS) == 0)
    {
        System.err.println(glGetShaderInfoLog(shader, 1024));
        System.exit(1);
    }

    glAttachShader(program, shader);

    }

还有我正在创建 VBO 的顶点数组:

Vertex[] data = new Vertex[] {            
new Vertex(new Vector3f(-0.1f, -0.1f, 0)),
new Vertex(new Vector3f(0,  1, 0)),
new Vertex(new Vector3f( 1,  -1, 0))};

我的绘制方法:

public void draw()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//Vertex is a class which only holds a Vector3f for position, currently, so size is set to 3
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glDrawArrays(GL_TRIANGLES, 0, size);
glDisableVertexAttribArray(0);
}

这是我得到的结果: 在此处输入图像描述

4

1 回答 1

1

你的glBindAttribLocation()电话来得太晚了:

glBindAttribLocation(program, 0, "position");
glUseProgram(program);

glBindAttribLocation()需要在 之前调用才能产生glLinkProgram()任何效果。您可以移动它,或glGetAttribLocation()在链接后使用以获取链接器分配给属性的位置。或者更简单,因为您使用 GLSL 3.30,您可以在着色器代码中指定位置:

layout(location = 0) in vec3 position;

使用 Core Profile 时,您还需要使用 Vertex Array Objects (VAO)。如果您的代码中没有类似glGenVertexArrays()andglBindVertexArray()的调用,您将需要这些调用。如果您搜索“OpenGL VAO”或“OpenGL Vertex Array Object”,那么在 SO 或 Internet 的其他地方应该有很多示例,所以我不会重复太多。粗略地说,在你开始初始化你的顶点状态之前,你会得到这样的东西:

GLuint vaoId = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// calls to glVertexAttribPointer, glEnableVertexAttribArray

然后当你准备画画时:

glBindVertexArray(vao);

您的顶点数据定义看起来也可能是麻烦的根源:

Vertex[] data = new Vertex[] {            
new Vertex(new Vector3f(-0.1f, -0.1f, 0)),
new Vertex(new Vector3f(0,  1, 0)),
new Vertex(new Vector3f( 1,  -1, 0))};

虽然没有显示将其填充到 VBO 中的代码,但传递给的数据glBufferData()需要是一个平面的、连续的浮点数组/缓冲区,而这是一个向量对象引用的数组。

于 2014-09-11T06:10:15.460 回答