OpenGL:顶点数组与 glBegin()

Posted

技术标签:

【中文标题】OpenGL:顶点数组与 glBegin()【英文标题】:OpenGL: vertexArray vs glBegin() 【发布时间】:2016-11-13 22:58:01 【问题描述】:

我正在关注一些关于 OpenGL 的教程,但遇到了问题。我构造了一个名为Mesh 的类,它在其构造函数中采用一个顶点数组并生成顶点数组等来进行绘图。问题是我什么也没看到。界面如下:

class Mesh

public:
    Mesh(Vertex * vertices, size_t numVertices);
    virtual ~Mesh();

    void Draw();
private:
    enum           POSITION_VB, NUM_BUFFERS    ;

    GLuint m_vertexArrayObject;
    GLuint m_vertexArrayBuffers;
    size_t m_drawCount;
;

这里是实现

#include "mesh.h"

Mesh::Mesh(Vertex *vertices, size_t numVertices)

    m_drawCount = numVertices;

    glGenVertexArrays(1, &m_vertexArrayObject);
    glBindVertexArray(m_vertexArrayObject);

    glGenBuffers(NUM_BUFFERS, &m_vertexArrayBuffers);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers);
    glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glBindVertexArray(0);


void Mesh::Draw()

    glBindVertexArray(m_vertexArrayObject);
    glDrawArrays(GL_TRIANGLES, 0, m_drawCount);
    glBindVertexArray(0);


Mesh::~Mesh()

    glDeleteVertexArrays(1, &m_vertexArrayObject);

Vertex 类型是一个简单的类,看起来像

class Vertex 
public:
    Vertex(glm::vec3 const & pos)      this->pos = pos;
private:
    glm::vec3 pos;
;

如果我将Mesh::Draw() 的实现更改为

glBegin(GL_TRIANGLES);              
glVertex3f(-1.0f, -0.25f, 0.0f);    //triangle first vertex
glVertex3f(-0.5f, -0.25f, 0.0f);    //triangle second vertex
glVertex3f(-0.75f, 0.25f, 0.0f);    //triangle third vertex
glEnd();                            //end drawing of triangles

我正在屏幕上打印一个三角形。我的问题是:这是否一定意味着Mesh'成员函数的实现存在错误,如果是这样,任何人都可以发现它吗?我想也许glBegin 方法绕过了代码中其他地方的一些错误,而vertexarray 方法无法绕过。如果有任何帮助,我将不胜感激。另外,如果需要,我可以发布其他代码!

着色器代码:

#version 120

void main()

    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);

【问题讨论】:

着色器呢? 我在其他地方设置了着色器,我很确定它们可以正常工作,因为它们还决定了可绘制的 glBegin 部分的颜色 @Slugger:不可能编写一个可以同时使用 both glVertex* 命令和 glVertexAttribPointer 命令的着色器。至少,并非不依赖 NVIDIA 的非标准行为。所以我想看看你的着色器。 我刚刚添加了着色器代码。抱歉回复晚了,我今天一整天都在大学 【参考方案1】:

你的网格类析构函数很可能是罪魁祸首:

Mesh::~Mesh()

    glDeleteVertexArrays(1, &m_vertexArrayObject);

您有一个隐式复制构造函数,只要需要您的Mesh 的副本,它就会对您的类成员进行逐字节的复制。该逐字节复制包含 OpenGL 管理的资源的名称 (m_vertexArrayObject),这意味着您现在有两个不同的对象引用同一资源。

一旦其中一个副本超出范围,它将删除仍被原始对象引用的 VAO。

解决此问题的最简单方法是禁用复制构造函数(C++11 对此有新的语法),然后在需要进行复制的任何时候都会出现编译器错误。

private:
    Mesh (const Mesh& original); // Copy ctor is inaccessible.

如果您确实希望支持多个Mesh 对象共享同一个顶点数组对象,则需要添加引用计数,并且只有在引用计数达到0时才释放 VAO。。 p>

【讨论】:

以上是关于OpenGL:顶点数组与 glBegin()的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL几种绘制方式

VBO 何时比“简单”的 OpenGL 基元 (glBegin()) 更快?

OpenGL入门程序

OpenGL 索引和数组纹理

我的OpenGL学习进阶之旅顶点属性顶点数组

我的OpenGL学习进阶之旅顶点属性顶点数组