OpenGLES 2.0用于顶点,颜色和纹理坐标的独立缓冲区

pol*_*ick 10 textures opengl-es vbo vertex opengl-es-2.0

我已经学习OpenGL几天了,通过一些教程和编写我自己的一些实验.但有一件事我真的不明白是阻止我继续下去的.我一直在谷歌搜索几个小时,但我的问题还没有找到答案.

我应该在哪里为每个顶点指定每个单独的颜色值和纹理坐标?这些属性是否应始终列在与顶点位置相同的数组(结构)中?像这样:

const Vertex Vertices[] = {
    // Front
    {{1, -1, 0}, {1, 0, 0, 1}, {TEX_COORD_MAX, 0}},
    {{1, 1, 0}, {0, 1, 0, 1}, {TEX_COORD_MAX, TEX_COORD_MAX}},
    {{-1, 1, 0}, {0, 0, 1, 1}, {0, TEX_COORD_MAX}},
    {{-1, -1, 0}, {0, 0, 0, 1}, {0, 0}},

    ...
Run Code Online (Sandbox Code Playgroud)

或者有没有办法将颜色值和纹理坐标放在单独的数组中?但问题出现了:如何glDrawElements使用单独的数组调用?

如果你想知道我为什么要分离这些值:我现在正在obj-c中创建我自己的.obj解析器,我想知道:如果加载没有纹理的模型并且只想在颜色上显示颜色怎么办?宾语?或者:如果你想加载一个只有一个纹理映射到它但每个顶点没有单独颜色的模型怎么办?并且:不会将过多的数据放在Vertex结构中的颜色值和纹理坐标膨胀.

小智 21

实际上,这是使用几个数组/缓冲区将顶点数据分成位置,颜色等的常用方法.

上次我接触ES 2.0是在WebGL的背景下(其规格略有不同,但最终基于ES 2.0).

基本上做的是使用数据将数据写入单独的缓冲区

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), positions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), colors, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

...

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,位置和颜色是包含顶点数据的浮点数组和包含索引的索引作为unsigned short.

要渲染此数据,您需要使用指向着色器的缓冲区和属性指针:

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(vertexPositionAttribute, 3,  GL_FLOAT, false, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glVertexAttribPointer(vertexColorAttribute, 4, GL_FLOAT, false, 0, 0);
Run Code Online (Sandbox Code Playgroud)

最后绑定索引缓冲区:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
Run Code Online (Sandbox Code Playgroud)

并呈现:

glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0);
Run Code Online (Sandbox Code Playgroud)

获取属性:

glUseProgram(shaderProgram);

vertexPositionAttribute= glGetAttribLocation(shaderProgram, "vertexPosition");
glEnableVertexAttribArray(vertexPositionAttribute);

vertexColorAttribute = glGetAttribLocation(shaderProgram, "vertexColor");
glEnableVertexAttribArray(vertexColorAttribute );

...
Run Code Online (Sandbox Code Playgroud)

如果您没有自定义着色器(使用固定功能),您可以使用

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexPointer(3,  GL_FLOAT, false, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glColorPointer(4, GL_FLOAT, false, 0, 0);
Run Code Online (Sandbox Code Playgroud)

代替.不过,我建议反对它,因为它已经过时了(如果在ES 2.0中完全可用).如果您仍想使用它,您可以完全跳过整个缓冲区业务并使用

glVertexPointer(3, GL_FLOAT, false, 0, positions);
glColorPointer(4, GL_FLOAT, false, 0, colors);
Run Code Online (Sandbox Code Playgroud)

glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, indices);
Run Code Online (Sandbox Code Playgroud)

我希望这不是太混乱,有点帮助.为了进一步阅读,虽然针对OpenGL,我建议使用Nehe教程.