OpenGL VBO 绘图
Posted
技术标签:
【中文标题】OpenGL VBO 绘图【英文标题】:OpenGL VBO Drawing 【发布时间】:2012-09-25 18:47:55 【问题描述】:我似乎在使用 VBO 在 OpenGL 中绘制对象时遇到了一些问题。我试图从http://www.opengl.org/wiki/VBO_-_just_examples(第 2 号)复制示例,但我无法让飞机出现在屏幕上。
顶点.h:
#include <freeglut>
struct Vertex
GLfloat position[3];
GLfloat normal[3];
GLfloat *uvs[2];
unsigned short uvCount;
;
三角形.h:
#include <GL/glew.h>
#include "Vertex.h"
class Triangles
public:
Triangles(GLuint program, Vertex *vertices, unsigned int vertexCount, unsigned int *indices[3], unsigned int indiceCount);
~Triangles();
void Draw();
private:
GLuint program;
GLuint VertexVBOID;
GLuint IndexVBOID;
GLuint VaoID;
unsigned int *indices[3];
unsigned int indiceCount;
;
三角形.cpp:
#include "Triangles.h"
#include <stdio.h>
#include <stddef.h>
Triangles::Triangles(GLuint program, unsigned int *indices[3], unsigned int indiceCount)
memcpy(this->indices, indices, sizeof(int) * indiceCount * 3);
this->indiceCount = indiceCount;
this->program = program;
glGenVertexArrays(1, &VaoID);
glBindVertexArray(VaoID);
glGenBuffers(1, &VertexVBOID);
glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertexCount, vertices, GL_STATIC_DRAW);
GLuint attributeLocation = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(attributeLocation);
glVertexAttribPointer(attributeLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)(offsetof(Vertex, position)));
attributeLocation = glGetAttribLocation(program, "normal");
glEnableVertexAttribArray(attributeLocation);
glVertexAttribPointer(attributeLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *)(offsetof(Vertex, normal)));
glGenBuffers(1, &IndexVBOID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 3 * indiceCount, indices, GL_STATIC_DRAW);
;
Triangles::~Triangles()
glDisableVertexAttribArray(glGetAttribLocation(program, "position"));
glDisableVertexAttribArray(glGetAttribLocation(program, "normal"));
glDeleteBuffers(1, &VertexVBOID);
glDeleteBuffers(1, &IndexVBOID);
glDeleteVertexArrays(1, &VaoID);
void Triangles::Draw()
glBindVertexArray(VaoID);
glDrawElements(GL_TRIANGLES, indiceCount, GL_UNSIGNED_INT, 0);
;
摘自 main.cpp(创建 triagle 对象):
Vertex vertices[4];
vertices[0].position[0] = -1;
vertices[0].position[1] = 1;
vertices[0].position[2] = 0;
vertices[0].normal[0] = 0;
vertices[0].normal[0] = 0;
vertices[0].normal[0] = 1;
vertices[0].uvCount = 0;
vertices[1].position[0] = 1;
vertices[1].position[1] = 1;
vertices[1].position[2] = 0;
vertices[1].normal[0] = 0;
vertices[1].normal[0] = 0;
vertices[1].normal[0] = 1;
vertices[1].uvCount = 0;
vertices[2].position[0] = 1;
vertices[2].position[1] = -1;
vertices[2].position[2] = 0;
vertices[2].normal[0] = 0;
vertices[2].normal[0] = 0;
vertices[2].normal[0] = 1;
vertices[2].uvCount = 0;
vertices[3].position[0] = -1;
vertices[3].position[1] = -1;
vertices[3].position[2] = 0;
vertices[3].normal[0] = 0;
vertices[3].normal[0] = 0;
vertices[3].normal[0] = 1;
vertices[3].uvCount = 0;
unsigned int **indices;
indices = new unsigned int*[2];
indices[0] = new unsigned int[3];
indices[0][0] = 0;
indices[0][1] = 1;
indices[0][2] = 2;
indices[1] = new unsigned int[3];
indices[1][0] = 2;
indices[1][1] = 3;
indices[1][2] = 0;
Triangles *t = new Triangles(program, vertices, 4 indices, 2);
createShader(GLenum , char *):
GLuint createShader(GLenum type, char *file)
GLuint shader = glCreateShader(type);
const char *fileData = textFileRead(file);
glShaderSource(shader, 1, &fileData, NULL);
glCompileShader(shader);
return shader;
着色器加载:
GLuint v = createShader(GL_VERTEX_SHADER);
GLuint f = createShader(GL_FRAGMENT_SHADER, "fragmentShader.frag");
program = glCreateProgram();
glAttachShader(program, v);
glAttachShader(program, f);
glLinkProgram(program);
glUseProgram(program);
vertexShader.vert:
in vec3 position;
in vec3 normal;
out vec3 a_normal;
void main()
gl_Position = vec4(position, 1.0);
fragmentShader.frag:
in vec3 a_normal;
out vec4 out_color;
void main()
out_color = vec4(1.0, 1.0, 1.0, 1.0);
如果需要更多代码,请告诉我。作为旁注,一切都编译得很好,我只是看不到我在屏幕上构建的飞机(可能是因为我没有使用颜色?)
我的OpenGL信息如下:
供应商:ATI Technologies Inc. 渲染器:ATI Radeon HD 5700 系列 版本:3.2.9756 兼容性配置文件上下文 扩展:扩展 = GL_AMDX_name_gen_delete GL_AMDX_random_access_target GL_AMDX_vertex_shader_tessellator GL_AMD_conservative_depth GL_AMD_draw_buffers_blend GL_AMD_performance_monitor GL_AMD_seamless_cubemap_per_texture GL_AMD_shader_stencil_export GL_AMD_texture【问题讨论】:
一些注释,没有特别的顺序:你做错误检查(glGetError
)吗? modelviewproj 设置在哪里?如果您使用自定义 mvp 矩阵,为什么要使用 glRotate/Translate/PopMatrix?你确定你的属性索引是0
和1
?
不幸的是我没有做错误检查,我主要只是复制了这个例子,我正在尝试运行它的代码。我使用矩阵函数是因为我没有意识到顶点着色器会影响它。我假设矩阵设置为堆栈顶部的矩阵(我在绘制之前推送的那个)。至于索引,我不确定你的意思。我只是在纸上画了顶点,并以此为基础确定了索引。除非您指的是 glEnableVertexArrayAttrib() 中的法线和位置值,否则我只是使用了示例中的值,我不确定如何更改它们或它们会产生什么影响。
在我的项目中,我还绘制了一个立方体(使用 glBegin 和 glEnd)作为测试,当着色器处于活动状态并正常工作时,它似乎消失了。这可能是着色器问题的迹象吗?如果是,有谁知道我该如何解决?
你能试着把你的程序精简到绘制三角形所需的绝对准系统吗?摆脱所有的平移和旋转代码,用漫射照明和法线注释掉任何东西?您添加的复杂性越多,存在的潜在问题就越多。无论您的最新代码是什么,请尽量让您的问题保持最新,看到很多多余的代码会令人困惑。
我把它删减了一点。我在着色器中取出了额外的东西(因为我只是想让一些东西出现),稍微移动了三角形代码并取出了矩阵的东西(因为它不起作用)你基本上可以忽略三角形下面的所有内容.cpp,这些东西主要是参考。我认为我在创建 VBO 和绘图方面做的一切都是正确的,我非常确信我一定是在不知何故的着色器上失败了。如果需要,我可以只提取有关着色器的内容,但我认为这应该是我实际绘制形状所需的一切。
【参考方案1】:
回应您的 cmets:
很遗憾我不做错误检查
你应该总是添加一些 OpenGL 错误检查,它会让你免于很多问题。它应该如下所示:
int err = glGetError();
if(err != 0)
//throw exception or log message or die or something
我使用矩阵函数是因为我没有意识到顶点着色器会影响它。我假设矩阵设置为堆栈顶部的矩阵(我在绘制之前推送的那个。)
这是一个错误的假设。唯一引用已弃用矩阵堆栈的变量是特殊(尽管已弃用)变量gl_ModelViewProjectionMatrix
。您目前拥有的只是一个未使用的、未初始化的矩阵,它完全忽略了您的矩阵堆栈。
至于索引,我不太清楚你的意思。我只是在纸上画了顶点,并以此为基础确定了索引。
我指的不是索引缓冲区中三角形的索引,而是 glAttrib* 函数的第一个参数。我想“属性位置”是一个比索引更正确的术语。
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, ... //attrib location 0
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, ... //attrib location 1
您似乎只是随机假设“0”和“1”映射到“位置”和“正常”。这不是一个安全的假设。您应该使用 glGetAttribLocation 查询“位置”和“正常”的属性位置值,然后将该值用于 glEnableVertexAttribArray 和 glVertexAttribPointer。
【讨论】:
好的,所以我对代码进行了一些更改。我不确定将 glGetError 的东西放在哪里,因为我不知道哪些方法会产生错误(而且我不想在 gl 方法调用之后这样做)我将着色器程序传递给三角形构造函数所以它可以与 glGetAttribLocation 一起使用。我还删除了着色器中的矩阵内容,因为我真的不知道如何初始化它。既然您提到不推荐使用矩阵的东西,我不确定如何正确转换我的顶点。现在似乎找不到属性,所以我不确定这是否修复。 glGetError 需要反复试验才能找到实际问题。任何 OpenGL 命令都可能产生错误,并且无论何时发生,它都会被保存到下一次调用 glGetError 为止。因此,如果您调用 glGetError 并报告错误,则它可能来自从当前行到上次调用 glGetError 的任何函数。至少您可以在渲染循环结束时进行一次错误检查。如果你产生了任何错误,你会在这里看到它,然后你可以向后寻找它。 @BenjaminDangerJohnson 好吧,看来我加载着色器的方式会产生错误。我将更新问题以包含我的着色器加载代码。 错误代码:1282 |错误信息:“OpenGL 错误:无效操作” 您的着色器代码有些欠缺,因为您的程序似乎没有片段着色器,而且您没有测试编译和链接是否成功。我推荐阅读一些教程,也许这一个适合初学者:arcsynthesis.org/gltut/Basics/Tut01%20Making%20Shaders.html以上是关于OpenGL VBO 绘图的主要内容,如果未能解决你的问题,请参考以下文章