打开 GL ES 2.0 为啥我的 VBO 不工作?

Posted

技术标签:

【中文标题】打开 GL ES 2.0 为啥我的 VBO 不工作?【英文标题】:Open GL ES 2.0 Why is my VBO not working?打开 GL ES 2.0 为什么我的 VBO 不工作? 【发布时间】:2019-03-03 18:04:27 【问题描述】:

嘿,我试图通过 vbo 在 OpenGL 中绘制一个带有 2 个三角形的简单四边形。 但是,我已经多次查看我的代码,但没有看到我缺少什么。 我不是 Open GL 专家,代码在没有任何缓冲区的情况下运行良好,但是当我切换到 VBO 时,我再也看不到任何东西了。 OpenGL 也不提供任何有用的错误。

Image::Image(Graphics * GFX)


    glm::vec2 corners[2];
    corners[0] = glm::vec2(0, 0);
    corners[1] = glm::vec2(1, 1);

    vertices = new GLfloat[30]
    
        //Vertices XYZ                      TexCoord X,Y
        corners[0].x, corners[0].y, 0.0f,   0,0,
        corners[0].x, corners[1].y, 0.0f,   0,1,
        corners[1].x, corners[0].y, 0.0f,   1,0,

        corners[1].x,corners[1].y,0.0f,     1,1,
        corners[0].x, corners[1].y,0.0f,    0,1,
        corners[1].x, corners[0].y, 0.0f,   1,0
    ;

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

    //Setting up some stuff
    const char *vertexShaderSource =
        "attribute vec4 vPosition; \n"
        "attribute vec2 vTexCoord; \n"
        "void main() \n"
        " \n"
        " gl_Position = vPosition; \n"
        " \n";
    const char *fragmentShaderSource =
        "precision mediump float; \n"
        "void main() \n"
        " \n"
        " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n"
        " \n";


    // Load and compile the vertex/fragment shaders
    vertexShader = GFX->LoadShader(GL_VERTEX_SHADER, (const char*)vertexShaderSource);
    fragmentShader = GFX->LoadShader(GL_FRAGMENT_SHADER, (const char*)fragmentShaderSource);

    // Create the program object    
    programObject = glCreateProgram();


    // now we have the V and F shaders  attach them to the progam object
    glAttachShader(programObject, vertexShader);
    glAttachShader(programObject, fragmentShader);

    // Link the program
    glLinkProgram(programObject);
    // Check the link status

    // Link the program
    GLint AreTheylinked;
    glGetProgramiv(programObject, GL_LINK_STATUS, &AreTheylinked);
    if (!AreTheylinked)
    
        GLint RetinfoLen = 0;
        // check and report any errors
        glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &RetinfoLen);
        if (RetinfoLen > 1)
        
            GLchar* infoLog = (GLchar*)malloc(sizeof(char) * RetinfoLen);
            glGetProgramInfoLog(programObject, RetinfoLen, NULL, infoLog);
            fprintf(stderr, "Error linking program:\n%s\n", infoLog);
            free(infoLog);
        
        glDeleteProgram(programObject);
    

    positionLocation = glGetAttribLocation(programObject, "vPosition");
    textureCoordLocation = glGetAttribLocation(programObject, "vTexCoord");

    if (glGetError() == GL_NO_ERROR) 
    else
        printf("Init failed!\n");
    //End setting up



Image::~Image()



void Image::Draw()

    std::cout << "Calling Draw on Image" << std::endl;
    glUseProgram(programObject);
    glEnable(GL_DEPTH_TEST);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    GLsizei stride = (5) * sizeof(GLfloat);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    if (glGetError() != GL_NO_ERROR)
    
        printf("UI Draw error\n");
    
    glDisableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);


以及我如何加载着色器:

GLuint Graphics::LoadShader(GLenum type, const char *shaderSrc)

    // 1st create the shader object
    GLuint TheShader = glCreateShader(type);

    if (TheShader == 0) return FALSE; // can't allocate so stop.

// pass the shader source then compile it
    glShaderSource(TheShader, 1, &shaderSrc, NULL);
    glCompileShader(TheShader);

    GLint  IsItCompiled;

    // After the compile we need to check the status and report any errors
    glGetShaderiv(TheShader, GL_COMPILE_STATUS, &IsItCompiled);
    if (!IsItCompiled)
    
        GLint RetinfoLen = 0;
        glGetShaderiv(TheShader, GL_INFO_LOG_LENGTH, &RetinfoLen);
        if (RetinfoLen > 1)
         // standard output for errors
            char* infoLog = (char*)malloc(sizeof(char) * RetinfoLen);
            glGetShaderInfoLog(TheShader, RetinfoLen, NULL, infoLog);
            fprintf(stderr, "Error compiling this shader:\n%s\n", infoLog);
            free(infoLog);
        
        glDeleteShader(TheShader);
        return FALSE;
    
    return TheShader;

之前在没有缓冲区的情况下也可以正常工作,并且使用以下方法看到了一个白色方块:

glVertexAttribPointer(0, 6, GL_FLOAT, GL_FALSE, 0, vertices);

但现在我想通过 VBO 将纹理坐标添加到我的四边形,但没有任何显示。

Smoothy101

【问题讨论】:

【参考方案1】:

您的缓冲区创建看起来不错 - 问题在于您的属性指针设置。您添加的纹理坐标已更改每个顶点的数据布局,但您尚未在代码中处理。

你需要这样的东西:

glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(textureCoordLocation, 2, GL_FLOAT, GL_FALSE, stride, 8);

...不是这个:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);

【讨论】:

感谢您的快速回复!但是,这不意味着我需要在着色器中使用 textureCoorLocation 吗?由于我现在没有使用它,所以它设置为 -1 @solidpixel 啊,错过了 - 我看到了它的查询,但不是着色器没有使用它的事实 - 抱歉。您目前正在为 glEnableAttribArrayglVertexAttribPointer 硬编码 0 - 这两个都应该是 positionLocation glUseProgram(programObject); glEnable(GL_DEPTH_TEST); glBindBuffer(GL_ARRAY_BUFFER, vbo); GLsizei stride = (5) * sizeof(GLfloat); glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, stride, (void*)0); glEnableVertexAttribArray(0); glDrawArrays(GL_TRIANGLES, 0, 6); if (glGetError() != GL_NO_ERROR) printf("UI Draw error\n"); glDisableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); 这就是我现在拥有的,遗憾的是仍然没有白色四边形 只是检查一下,如果为 positionLocation 返回的位置是 0 以外的任何值,glEnableVertexAttribArray(0) 将不起作用。您应该在该调用中使用 positionLocation 不想这么说但还是没有运气glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, stride, (void*)0);glEnableVertexAttribArray(positionLocation);glDrawArrays(GL_TRIANGLES, 0, 6);

以上是关于打开 GL ES 2.0 为啥我的 VBO 不工作?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 2.0 VBO 问题

OpenGL ES 2.0:似乎无法渲染第二个 VBO?

OpenGL ES 2.0 vbo 白屏

安卓 OpenGL ES 2.0 VBO

在 Android 上的 OpenGL ES 2.0 中使用 VBO/IBO

iOS OpenGL ES 2.0 VBO 混淆