glVertexAttribPointer 问题(OpenGL 3.x 前向兼容上下文)
Posted
技术标签:
【中文标题】glVertexAttribPointer 问题(OpenGL 3.x 前向兼容上下文)【英文标题】:glVertexAttribPointer trouble (OpenGL 3.x forward-compatible context) 【发布时间】:2012-03-02 19:44:32 【问题描述】:按照现代标准,渲染多边形网格的首选方式似乎涉及使用Vertex Buffer Objects 和索引缓冲区(最终通过调用glDrawElements()
),这正是我试图包装我的围绕这些概念。另外,我坚持使用glVertexAttribPointer()
而不是deprecated glVertexPointer()
、glNormalPointer()
等。
我正在使用自定义的二进制 3d 文件格式(Wavefront .OBJ 衍生文件),其内容可以或多或少直接memcpy()
'd 到顶点数组。以下是我声明 vertex
结构的方式:
typedef struct vertex_
float vx,vy,vz;
float nx,ny,nz;
float padding[2]; // align to 32 bytes
vertex;
loadBObj()
函数返回一个索引缓冲区(实现为unsigned short int
s 的简单数组),并用相关的顶点/法线数据填充顶点数组(模型使用所有已导出为具有 per-vertex-normals 以获得更平滑的着色结果)。
indices = loadBObj("pharaoh.bobj", false, &VBOid);
加载代码本身经过验证可以正常工作。
现在,loadBObj()
中正在做的事情是正在创建一个新的 VBO,如下所示:
glGenBuffers(1, VBOid);
glBindBuffer(GL_ARRAY_BUFFER, *VBOid);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex)*vcount, &vertarray[0].vx, GL_STATIC_DRAW);
在loadBObj()
被调用后,一个索引缓冲区对象(可能不应该这样称呼)被创建如下:
glGenBuffers(1, &IBOid);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOid);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short int)*qfcount*4, indices, GL_STATIC_DRAW);
好的。在实际渲染网格时,我使用了以下代码:
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
...
glBindBuffer(GL_ARRAY_BUFFER, VBOid);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), BUFFER_OFFSET(0));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), BUFFER_OFFSET(3*sizeof(float)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOid);
glDrawElements(GL_QUADS, qfcount*4, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
这会产生绝对正确的几何图形,但阴影不太正确:
这是模型的图像,以立即模式呈现:img http://i44.tinypic.com/i36zcg.png
这是由上述程序生成的:我的 VBO 处理过程中发生了什么有趣的事情吗?
【问题讨论】:
在 gDEBugger 或类似的东西下运行它,并验证 VBO 中的所有数据是否正确。如果是,是时候检查着色器了。此外,GL_QUADS
已被弃用并从核心配置文件中消失。
@CatPlusPlus:好的,我现在已经彻底检查了 VBO 的内容(gDEBugger = fantabulous 实用程序顺便说一句,干杯),看起来没问题。现在,“检查着色器”到底是什么意思?
【参考方案1】:
您的法线似乎没有正确通过
这可能是由于您应该拥有的事实造成的
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
由于您同时指定了 0 和 1 指针。 (目前你只有第一行)
【讨论】:
- 添加行glEnableVertexAttribArray(1);
似乎没有任何效果。还是)感谢你的建议;无论如何,我都会把它留在那里。【参考方案2】:
你在使用着色器吗?您只应该将 glVertexAttribPointer 与着色器一起使用,并且您必须明确告诉它哪个属性数组与哪个输入变量一起使用。 (glGetAttribLocation/glBindAttribLocation)。
如果您使用的是固定管道,则必须坚持使用 glVertexPointer/glNormalPointer。
【讨论】:
经过测试:glVertexPointer
/ glNormalPointer
等效项产生类似的结果。事实上,即使我用零/随机数据初始化了法向量分量,结果也不会改变。我一直在提到OpenGL wiki VBO examples page,它确实提到了设置着色器:“另外,我们没有使用着色器,但您必须设置着色器并将顶点属性设置为着色器才能正常工作。”对于类似于即时模式图片的着色,我会使用什么样的着色器程序?
@elmov 它比我在这里介绍的要复杂得多,但我相信你可以在网上找到很多示例,搜索如何编写着色器以及如何实现光照和着色。跨度>
+1 当他不使用着色器时,这正是他的问题。它适用于位置属性的原因是(至少在 GL 3 之前或在兼容模式下)通用顶点属性 0 是内置 glVertex
属性的别名。【参考方案3】:
我认为这里可能发生的情况是三角形*颠倒了。您可以通过将每个第一个顶点与每个第三个顶点交换来进行测试。
由于您使用的是四边形,这显然不是错误。但是您可以尝试每秒与第三个顶点交换一次。【讨论】:
以上是关于glVertexAttribPointer 问题(OpenGL 3.x 前向兼容上下文)的主要内容,如果未能解决你的问题,请参考以下文章
Opengl顶点着色器为每个顶点设置布尔值(glVertexAttribPointer)
缓冲区和 glVertexAttribPointer 之间的关系
带有 glvertexattribpointer 问题的 glsl 布局
glVertexAttribPointer 出现 JOGL 错误