顶点缓冲区对象干扰OpenGL ES 2.0中的纹理

时间:2013-07-13 05:18:59

标签: ios opengl-es-2.0 glkit

我正在使用IOS 6.1,尝试绘制纹理和顶点缓冲区对象。

我设置了这样的纹理:

typedef struct{
    CGPoint geometryVertex;
    CGPoint textureVertex;
} TexturedVertex;

typedef struct {
    TexturedVertex bl;
    TexturedVertex br;
    TexturedVertex tl;
    TexturedVertex tr;
} TexturedQuad;

NSError         *error;
NSString        *path = [[NSBundle mainBundle] pathForResource:@"img.png" ofType:nil];
NSDictionary    *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], GLKTextureLoaderOriginBottomLeft, nil];
self.textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];
TexturedQuad quad;
quad.bl.geometryVertex  = CGPointMake(0, 0);
quad.br.geometryVertex  = CGPointMake(self.textureInfo.width, 0);
quad.tl.geometryVertex  = CGPointMake(0, self.textureInfo.height);
quad.tr.geometryVertex  = CGPointMake(self.textureInfo.width, self.textureInfo.height);
quad.bl.textureVertex   = CGPointMake(0, 0);
quad.br.textureVertex   = CGPointMake(1, 0);
quad.tl.textureVertex   = CGPointMake(0, 1);
quad.tr.textureVertex   = CGPointMake(1, 1);
self.quad = quad;

glClearColor(0, 0, 0, 0.5);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);

然后画出来:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClear(GL_COLOR_BUFFER_BIT);
    self.baseEffect.texture2d0.name = self.textureInfo.name;
    self.baseEffect.transform.modelviewMatrix = [self modelMatrix];
    [self.baseEffect prepareToDraw];

    long offset = (long)&_quad;
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *)(offset + offsetof(TexturedVertex, geometryVertex)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *)(offset + offsetof(TexturedVertex, textureVertex)));
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

一切正常,没问题。我接下来要做的是绘制另一个存储在不是纹理的顶点缓冲区对象中的对象。所以我将其添加到设置代码中:

typedef struct {
    float Position[3];
} Vertex;

const Vertex Vertices[] = {
    {100, -100, 0},
    {100, 100, 0},
    {-100, 100, 0},
    {-100, -100, 0}
};

GLuint _vertexBuffer;

glGenBuffers(1, &_vertexBuffer); // (1)
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); // (2)
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); // (3)

但即使没有尝试绘制新对象,这些行也会使我的应用程序崩溃。我发现只有第(1)行它不会崩溃。使用(1)+(2)它仍然不会崩溃但是使用Instruments进行分析会告诉我纹理'超出数组缓冲区边界'的绘制调用并使用'未初始化的缓冲区数据',尽管它仍然可以很好地绘制纹理。添加第(3)行会导致应用程序崩溃,而仪器会告诉我没有GL数据。

有谁知道为什么会这样?

1 个答案:

答案 0 :(得分:0)

VBO显然干扰了对glVertexAttribPointer的调用。像这样取消绑定会阻止崩溃:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClear(GL_COLOR_BUFFER_BIT);
    self.baseEffect.texture2d0.name = self.textureInfo.name;
    self.baseEffect.transform.modelviewMatrix = [self modelMatrix];
    [self.baseEffect prepareToDraw];

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    long offset = (long)&_quad;
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *)(offset + offsetof(TexturedVertex, geometryVertex)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *)(offset + offsetof(TexturedVertex, textureVertex)));
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

纹理不使用VBO,因此在进行glVertexAttribPointer调用时不应该有一个绑定。