使用索引在 OpenGL 中渲染四边形的问题

Posted

技术标签:

【中文标题】使用索引在 OpenGL 中渲染四边形的问题【英文标题】:Problems with Rendering a quad in OpenGL by using indeces 【发布时间】:2016-12-23 21:55:33 【问题描述】:

我想用OpenGL 绘制一个四边形,但它不起作用,因为我引入了索引。如果没有索引,我的代码可以正常工作,我可以使用 glDrawArrays

#define GLEW_STATIC
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <GL\glew.h>
#include <glm.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#define WIDTH 800
#define HEIGHT 600
#define TITLE "Dynamic"

GLFWwindow* window;
int vaoID;


std::vector<float> vertices = -0.5f, 0.5f, 0,      -0.5f, -0.5f, 0,        0.5f, -0.5f, 0, 0,      0.5f, 0.5f, 0;
std::vector<int> indices =  0, 1, 3,   3, 1, 2 ;
void loadToVAO(std::vector<float> vertices, std::vector<int> indices);

void update() 
    loadToVAO(vertices, indices);
    while (!glfwWindowShouldClose(window)) 
        glfwPollEvents();
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(1, 0, 0, 1);
        //glDrawArrays(GL_TRIANGLES, 0, 6);
        glDrawElements(GL_TRIANGLES, 6, GL_INT, 0);
        glfwSwapBuffers(window);
    


int main() 
    if (!glfwInit())
        std::cout << "Couldn't initialize GLFW!" << std::endl;

    window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);

    if (GLEW_OK != glewInit())
        std::cout << "GLEW is not working!" << std::endl;

    std::cout << "Your GL version: " << glGetString(GL_VERSION) << std::endl;
    //glEnable(GL_CULL_FACE);
    //glCullFace(GL_BACK);
    update();


void loadToVAO(std::vector<float> vertices, std::vector<int> indices) 
    GLuint vertexVBO;
    GLuint indicesVBO;
    GLuint vaoID;
    glGenBuffers(1, &vertexVBO);
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);
    glGenBuffers(1, &indicesVBO);
    glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesVBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(int), &indices[0], GL_STATIC_DRAW);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * sizeof(float), &vertices[0], GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
    glEnableVertexAttribArray(0);

【问题讨论】:

【参考方案1】:

同样,sizeof 运算符是问题所在,因为它返回基础类型的大小,而不是指针指向的某些数据的大小。在行中

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) * sizeof(int), &indices[0], GL_STATIC_DRAW);

sizeof(indices) == sizeof(std::vector&lt;int&gt;) 是向量对象的大小,不是向量中包含的数据的大小。这里正确的代码是使用indices.size(),它返回向量中元素的数量:

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(int), &indices[0], GL_STATIC_DRAW);

顶点的上传也是如此。

编辑:除非绝对必要,否则您也不应该按值传递向量。当您将它们传递给loadToVAO 时,会复制两个向量的内容。如果将函数签名更改为

void loadToVAO(std::vector<float>& vertices, std::vector<int>& indices)

向量通过引用传递,数据不被复制。

【讨论】:

以上是关于使用索引在 OpenGL 中渲染四边形的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 OpenGL 中加载和渲染可能包含三角形、四边形或 N-Gons 的 OBJ 文件?

渲染大量四边形的有效方法(LibGDX/OpenGL ES)

Opengl 渲染四边形

如何为 OpenGL 文本渲染计算字符映射中的最佳字形边界

使用 OpenGL / LibGDX 的后处理问题 - 黑屏(FBO、着色器、四边形)

OpenGL/C++:使用顶点缓冲区进行从后到前渲染