OpenGL- glDrawElements 只绘制第一个元素

Posted

技术标签:

【中文标题】OpenGL- glDrawElements 只绘制第一个元素【英文标题】:OpenGL- glDrawElements only draws first element 【发布时间】:2015-12-11 23:47:59 【问题描述】:

大家好,我正在为我的游戏制作一个小 3d 引擎,并且我为顶点数组和 VBO 创建了一个类。它一直在工作,直到我尝试向顶点数组添加索引。现在它只绘制索引的第一个元素!

这是生成 VAO 和 VBO 的函数构建。

void build() 
vboID = new GLuint[vboS];

if (vertexIndexing) 
    for (int n = 0, m = 0, i = 0; n < vertexes.size(); m++) 
        if (i + m >= vertexes.size()) 
            break;
        
        indices.push_back((GLushort)(i+m));
        if (m >= s) 
            m = 0;
            n++;
            i+=s/2;
            std::cout << "\n";
        
        std::cout << i + m << " , ";
    
    std::cout << "\n";


shader->use();

glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
glGenBuffers(vboS, vboID);

if (vertexIndexing) 
    glGenBuffers(1, &IBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0], GL_STATIC_DRAW);


int n = 0;

if (options.vertex) 
    shader->addAttribute("vertex");
    glBindBuffer(GL_ARRAY_BUFFER, vboID[n]);
    glBufferData(GL_ARRAY_BUFFER, pos.size() * sizeof(GLfloat), &pos[0], GL_STATIC_DRAW);
    glVertexAttribPointer(shader->attribute("vertex"), 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(shader->attribute("vertex"));
    n++;


if (options.color) 
    shader->addAttribute("color");
    glBindBuffer(GL_ARRAY_BUFFER, vboID[n]);
    glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLfloat), &colors[0], GL_STATIC_DRAW);
    glVertexAttribPointer(shader->attribute("color"), 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(shader->attribute("color"));
    n++;


if (options.normal) 
    shader->addAttribute("normal");
    glBindBuffer(GL_ARRAY_BUFFER, vboID[n]);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(GLfloat), &normals[0], GL_STATIC_DRAW);
    glVertexAttribPointer(shader->attribute("normal"), 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(shader->attribute("normal"));
    n++;


if (options.texcoord) 
    shader->addAttribute("texcoord");
    glBindBuffer(GL_ARRAY_BUFFER, vboID[n]);
    glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(GLfloat), &texcoords[0], GL_STATIC_DRAW);
    glVertexAttribPointer(shader->attribute("texcoord"), 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(shader->attribute("texcoord"));
    n++;

glBindVertexArray(0);
shader->disable();

这里是绘制VAO的函数draw。

void draw() 
glBindVertexArray(vaoID);
if (vertexIndexing) 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
    shader->use();
    glDrawElements(mode, indices.size(), GL_UNSIGNED_SHORT, 0);
    shader->disable();
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

else 
    shader->use();
    glDrawArrays(mode, 0, vertexes.size());
    shader->disable();

glBindVertexArray(0);

注意:我删除了 glEnableClientState(GL_VERTEX_ARRAY) 因为它没有做任何事情。

【问题讨论】:

哇,glEnableClientState(GL_VERTEX_ARRAY)!这让人想起很久很久以前的事。它不属于这里。 这段代码有点乱。看起来您正在尝试做一些非常通用的事情,其中​​一段代码可以完成所有事情。如果您从根本不通用的东西开始,但设计用于一种特定的着色器程序和一种特定的顶点格式,那将是一个更好的主意。这样想:你宁愿做一个简单的游戏引擎成功,还是宁愿做一个复杂的游戏引擎失败? 嗯,我已经做了很多事情,我有照明、着色器支持、地形、加载 3D 模型、纹理、窗口、相机,我认为现在回来为时已晚。但是你知道问题出在哪里吗?我一直在寻找,但找不到任何对我有帮助的东西。 它之前也可以正常工作,一切都很完美,但是当我添加索引时,它只绘制第一个元素。请帮忙。 【参考方案1】:

好的,我修好了。这不是openGL的问题。 它与索引生成有关。

新的指数生成:

for (int n = 0, m = 0, i = 0; n < vertexes.size(); m++) 
    if (i + m >= vertexes.size()) 
        break;
    
    if (m >= s) 
        m = 0;
        n++;
        i+=s/2;
    
    indices.push_back((GLushort)(i + m));

【讨论】:

谢谢!我遇到了一个类似的问题,只有第一个对象被渲染。我以为我已经正确设置了所有缓冲区。原来,当我需要将近四千时,我只包括了六个指数。您的回答帮助我意识到了问题。

以上是关于OpenGL- glDrawElements 只绘制第一个元素的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES - glDrawElements - 无法理解索引

OpenGL glDrawElements

glDrawElement 的 OpenGL 渲染问题

OpenGL - glDrawElements vs 顶点数组对象

OpenGL- glDrawElements 只绘制第一个元素

OpenGL glDrawElements 没有颜色