OpenGL ES 2.0 顶点数据错误

Posted

技术标签:

【中文标题】OpenGL ES 2.0 顶点数据错误【英文标题】:OpenGL ES 2.0 Vertex Data wrong 【发布时间】:2013-12-03 06:58:57 【问题描述】:

我正在尝试在 ios 上渲染一些点精灵,但一些顶点数据似乎总是为 0。经过数小时的调试后,我将其范围缩小到这个非常简单的示例,尝试只渲染一个粒子。

顶点着色器:

uniform mat4 projection;
uniform mat4 modelView;

attribute vec3 position;
attribute vec3 positionEnd;

void main()

  vec3 result = position + positionEnd;
  gl_Position = u_projection * u_model_view * vec4(result.x, result.y, result.z, 1.0);
  gl_PointSize = 15.0;

片段着色器:

uniform sampler2D texture;

void main()

  gl_FragColor = texture2D(u_texture, gl_PointCoord);

顶点数据上传:

vertices = std::vector<float>(6);
//attribute position
vertices[0] = 0;
vertices[1] = 0;
vertices[2] = 0;
//attribute positionEnd
vertices[3] = 0;
vertices[4] = 0;
vertices[5] = 0;

glGenVertexArraysOES(1, &mVao);
glBindVertexArrayOES(mVao);

glGenBuffers(1, &mVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);

auto positionLocation = glGetAttribLocation(3, "position");
auto positionEndLocation = glGetAttribLocation(3, "positionEnd");

glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid *)0);
glEnableVertexAttribArray(positionEndLocation);
glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid *)3);

glBindVertexArrayOES(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

绘图:

glBindVertexArrayOES(mVao);
glDrawArrays(GL_POINTS, 0, 1);

现在我已将所有顶点设置为零,这会将精灵呈现在屏幕中间,这很好,但是,如果我将顶点数据更改为

//attribute position
vertices[0] = 20;
vertices[1] = 0;
vertices[2] = 0;
//attribute positionEnd
vertices[3] = -20;
vertices[4] = 0;
vertices[5] = 0;

它应该再次绘制在屏幕中间(使用上面的顶点着色器),对吧?除了不是,而是向右渲染了 20 个单位。我假设 positionEnd (因此 -20)从未在顶点着色器中正确设置,但我做错了什么?

【问题讨论】:

【参考方案1】:

问题是你的缓冲区偏移量(最后一个参数):

glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 
                      6 * sizeof(float), (GLvoid*)3);

您将其设置为3,因为您可能的意思是“稍后开始 3 个浮点数(一个属性)”,但实际上它的意思是 “稍后开始 3 个字节”。因此,您实际上需要将步幅设置为 3 个浮点数的大小以字节为单位,因此 3 * sizeof(float)

glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 
                      6 * sizeof(float), (GLvoid*)(3*sizeof(float)));

或者使用指针算法:

glVertexAttribPointer(positionEndLocation, 3, GL_FLOAT, GL_FALSE, 
                      6 * sizeof(float), (float*)0 + 3);

顺便说一句,你的glGetAttribLocation 电话也很奇怪。作为第一个参数,他们需要一个 GLSL 程序对象(从glCreateProgram 获得的 ID)。我从未见过有人在其中使用实际数字(尽管 GL 对象对于外界来说确实只是数字,因此出于调试目的,即使真的很奇怪,也可以硬连线它)。

【讨论】:

呃,这么简单的事情浪费了这么多时间,谢谢!正如您所说的那样,实际数字只是为了调试,因为我知道该程序将被分配数字 3。

以上是关于OpenGL ES 2.0 顶点数据错误的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 2.0 渲染管线 学习笔记

OpenGL ES 2.0,使用多个顶点缓冲区进行绘制

OpenGL ES 2.0 每个顶点使用多个法线向量

OpenGL ES 2.0:似乎无法渲染第二个 VBO?

切换到使用交错 VBO - 编译但没有绘制 - opengl es 2.0

是否可以在顶点着色器内持续更改 iPhone OpenGL ES 2.0 上的 VBO 值?