Cap*_*uff 11 opengl-es objective-c ios5 glkit
我一直在寻找适用于iOS的新OpenGL框架,恰当地命名为GLKit,并且一直在将一些现有的OpenGL 1.0代码移植到OpenGL ES 2.0中,只是为了让我的脚趾浸入水中并掌握一切.
在阅读了API以及Apple和OpenGL文档提供的其他最佳实践的全部内容之后,我已经根深蒂固了我应该使用顶点缓冲对象并使用"元素"或更确切地说是顶点索引.似乎有很多关于通过在必要时使用填充来优化内存存储的提及,但这可能是另一天的对话;)
我刚才读到了关于使用NSMutableData而不是经典malloc/free的好处,并希望在编写我的VBO时尝试采用这种方法.到目前为止,我已经设法将一个看起来像我正在走向正确轨道的片段拼凑在一起,但我不完全确定VBO应该包含多少数据.这是我到目前为止所得到的:
//import headers
#import <GLKit/GLKit.h>
#pragma mark -
#pragma mark InterleavingVertexData
//vertex buffer object struct
struct InterleavingVertexData
{
//vertices
GLKVector3 vertices;
//normals
GLKVector3 normal;
//color
GLKVector4 color;
//texture coordinates
GLKVector2 texture;
};
typedef struct InterleavingVertexData InterleavingVertexData;
#pragma mark -
#pragma mark VertexIndices
//vertex indices struct
struct VertexIndices
{
//vertex indices
GLuint a;
GLuint b;
GLuint c;
};
typedef struct VertexIndices VertexIndices;
//create and return a vertex index with specified indices
static inline VertexIndices VertexIndicesMake(GLuint a, GLuint b, GLuint c)
{
//declare vertex indices
VertexIndices vertexIndices;
//set indices
vertexIndices.a = a;
vertexIndices.b = b;
vertexIndices.c = c;
//return vertex indices
return vertexIndices;
}
#pragma mark -
#pragma mark VertexBuffer
//vertex buffer struct
struct VertexBuffer
{
//vertex data
NSMutableData *vertexData;
//vertex indices
NSMutableData *indices;
//total number of vertices
NSUInteger totalVertices;
//total number of indices
NSUInteger totalIndices;
};
typedef struct VertexBuffer VertexBuffer;
//create and return a vertex buffer with allocated data
static inline VertexBuffer VertexBufferMake(NSUInteger totalVertices, NSUInteger totalIndices)
{
//declare vertex buffer
VertexBuffer vertexBuffer;
//set vertices and indices count
vertexBuffer.totalVertices = totalVertices;
vertexBuffer.totalIndices = totalIndices;
//set vertex data and indices
vertexBuffer.vertexData = nil;
vertexBuffer.indices = nil;
//check vertices count
if(totalVertices > 0)
{
//allocate data
vertexBuffer.vertexData = [[NSMutableData alloc] initWithLength:(sizeof(InterleavingVertexData) * totalVertices)];
}
//check indices count
if(totalIndices > 0)
{
//allocate data
vertexBuffer.indices = [[NSMutableData alloc] initWithLength:(sizeof(VertexIndices) * totalIndices)];
}
//return vertex buffer
return vertexBuffer;
}
//grow or shrink a vertex buffer
static inline void VertexBufferResize(VertexBuffer *vertexBuffer, NSUInteger totalVertices, NSUInteger totalIndices)
{
//check adjusted vertices count
if(vertexBuffer->totalVertices != totalVertices && totalVertices > 0)
{
//set vertices count
vertexBuffer->totalVertices = totalVertices;
//check data is valid
if(vertexBuffer->vertexData)
{
//allocate data
[vertexBuffer->vertexData setLength:(sizeof(InterleavingVertexData) * totalVertices)];
}
else
{
//allocate data
vertexBuffer->vertexData = [[NSMutableData alloc] initWithLength:(sizeof(InterleavingVertexData) * totalVertices)];
}
}
//check adjusted indices count
if(vertexBuffer->totalIndices != totalIndices && totalIndices > 0)
{
//set indices count
vertexBuffer->totalIndices = totalIndices;
//check data is valid
if(vertexBuffer->indices)
{
//allocate data
[vertexBuffer->indices setLength:(sizeof(VertexIndices) * totalIndices)];
}
else
{
//allocate data
vertexBuffer->indices = [[NSMutableData alloc] initWithLength:(sizeof(VertexIndices) * totalIndices)];
}
}
}
//release vertex buffer data
static inline void VertexBufferRelease(VertexBuffer *vertexBuffer)
{
//set vertices and indices count
vertexBuffer->totalVertices = 0;
vertexBuffer->totalIndices = 0;
//check vertices are valid
if(vertexBuffer->vertexData)
{
//clean up
[vertexBuffer->vertexData release];
vertexBuffer->vertexData = nil;
}
//check indices are valid
if(vertexBuffer->indices)
{
//clean up
[vertexBuffer->indices release];
vertexBuffer->indices = nil;
}
}
Run Code Online (Sandbox Code Playgroud)
目前,交错顶点数据包含足以存储每个顶点的顶点,法线,颜色和纹理坐标.我的印象是会有相同数量的顶点和索引,但实际上这显然并非如此,因此,索引是VBO的一部分而不是InterleavingVertexData.
问题更新:
在管理到将其变为工作状态之后,我已经更新了上面的代码.希望它将来会对某人有用.
现在我已经设法将所有内容设置好了,但是我无法通过将内容绑定到VBO来获得预期的结果.这是我到目前为止将数据加载到OpenGL中的代码:
//generate buffers
glGenBuffers(2, buffers);
//bind vertices buffer
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, (sizeof(InterleavingVertexData) * vertexBuffer.totalVertices), self.vertexData, GL_STATIC_DRAW);
//bind indices buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (sizeof(VertexIndices) * vertexBuffer.totalIndices), self.vertexIndices, GL_STATIC_DRAW);
//reset buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Run Code Online (Sandbox Code Playgroud)
以及渲染所有内容的代码:
//enable required attributes
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribNormal);
glEnableVertexAttribArray(GLKVertexAttribColor);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
//bind buffers
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
//set shape attributes
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(InterleavingVertexData), (void *)offsetof(InterleavingVertexData, vertices));
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_TRUE, sizeof(InterleavingVertexData), (void *)offsetof(InterleavingVertexData, normal));
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_TRUE, sizeof(InterleavingVertexData), (void *)offsetof(InterleavingVertexData, color));
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_TRUE, sizeof(InterleavingVertexData), (void *)offsetof(InterleavingVertexData, texture));
//draw shape
glDrawElements(GL_TRIANGLES, vertexBuffer.totalIndices, GL_UNSIGNED_INT, (void *)0);
//reset buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//disable atttributes
glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
glDisableVertexAttribArray(GLKVertexAttribColor);
glDisableVertexAttribArray(GLKVertexAttribNormal);
glDisableVertexAttribArray(GLKVertexAttribPosition);
Run Code Online (Sandbox Code Playgroud)
虽然我的iPhone尚未爆发出令人敬畏的独角兽用他们的眼睛拍摄彩虹的图形,我还是无法完整地渲染一个简单的形状而不会撕掉我的头发.
从渲染看,它看起来好像只绘制了每个形状的1/3,取决于视角,可能是1/2.似乎罪魁祸首将count参数传递给glDrawElements,因为摆弄它有不同的结果,但我已经阅读了文档并反复检查了这个值,它确实期望索引的总数(这就是我的意思)目前通过).
正如我在原始问题中提到的那样,我对VBO目前相当困惑,或者至少对实现而不是概念感到困惑.如果有人会如此善良地关注我的实施,那将是非常棒的,因为我确定我在路上的某处发生了一个菜鸟错误,但你知道当你盯着某些东西几个小时的时候是怎么回事结束没有进展.
谢谢阅读!
我想我看到了你的问题。
您有一个结构体,VertexIndices其中包含三个索引或一个三角形的索引。当您绑定 IBO(索引缓冲区对象,包含索引的缓冲区对象)时,您可以执行以下操作:
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (sizeof(VertexIndices) * vertexBuffer.totalIndices), self.vertexIndices, GL_STATIC_DRAW);
Run Code Online (Sandbox Code Playgroud)
这很好。sizein 中的参数以glBufferData字节为单位,因此您需要将 sizeof(3 floats) 乘以您拥有的 3 个浮点组的数量。伟大的。
但是当你实际调用 glDrawElements 时,你会这样做:
glDrawElements(GL_TRIANGLES, vertexBuffer.totalIndices, GL_UNSIGNED_INT, (void *)0);
Run Code Online (Sandbox Code Playgroud)
但是,vertexBuffer.totalIndices等于VertexIndices您拥有的结构体数量,等于索引总数 / 3 (或三角形总数)。因此,您需要执行以下操作之一:
glDrawElements(..., vertexBuffer.totalIndices * 3, ...);vertexBuffer.totalIndices应该包含您拥有的实际索引总数,而不是您正在渲染的三角形总数。您需要执行其中一项操作,因为现在 TotalIndices 包含您所获得的总数VertexIndices,并且每个索引都有 3 个索引。这里正确的做法是将totalIndices重命名为totalTriangles,或者在某处跟踪索引的实际总数。
| 归档时间: |
|
| 查看次数: |
3972 次 |
| 最近记录: |