OPENGL之GLBindBuffer

          在模仿OPENGLES教程中的代码时,首先看了一遍代码,能粗通代码的意思,但是开始自己写时碰到了不少问题,经常性的得不到正确的图形,而是一堆不知道为什么会是这样的图形,在自习研究如下代码后我知道了原因
#import "AGLKVertexAttribArrayBuffer.h"

@interface AGLKVertexAttribArrayBuffer ()

@property (nonatomic, assign) GLsizeiptr
   bufferSizeBytes;

@property (nonatomic, assign) GLsizei
   stride;

@end


@implementation AGLKVertexAttribArrayBuffer

@synthesize name;
@synthesize bufferSizeBytes;
@synthesize stride;


/
// This method creates a vertex attribute array buffer in
// the current OpenGL ES context for the thread upon which this 
// method is called.
- (id)initWithAttribStride:(GLsizei)aStride
   numberOfVertices:(GLsizei)count
   bytes:(const GLvoid *)dataPtr
   usage:(GLenum)usage;
{
   NSParameterAssert(0 < aStride);
   NSAssert((0 < count && NULL != dataPtr) ||
      (0 == count && NULL == dataPtr),
      @"data must not be NULL or count > 0");
      
   if(nil != (self = [super init]))
   {
      stride = aStride;
      bufferSizeBytes = stride * count;
      
      glGenBuffers(1,                // STEP 1
         &name);
      glBindBuffer(GL_ARRAY_BUFFER,  // STEP 2
         self.name); 
      glBufferData(                  // STEP 3
         GL_ARRAY_BUFFER,  // Initialize buffer contents
         bufferSizeBytes,  // Number of bytes to copy
         dataPtr,          // Address of bytes to copy
         usage);           // Hint: cache in GPU memory
         
      NSAssert(0 != name, @"Failed to generate name");
   }
   
   return self;
}   


/
// This method loads the data stored by the receiver.
- (void)reinitWithAttribStride:(GLsizei)aStride
   numberOfVertices:(GLsizei)count
   bytes:(const GLvoid *)dataPtr;
{
   NSParameterAssert(0 < aStride);
   NSParameterAssert(0 < count);
   NSParameterAssert(NULL != dataPtr);
   NSAssert(0 != name, @"Invalid name");

   self.stride = aStride;
   self.bufferSizeBytes = aStride * count;
   
   glBindBuffer(GL_ARRAY_BUFFER,  // STEP 2
      self.name); 
   glBufferData(                  // STEP 3
      GL_ARRAY_BUFFER,  // Initialize buffer contents
      bufferSizeBytes,  // Number of bytes to copy
      dataPtr,          // Address of bytes to copy
      GL_DYNAMIC_DRAW); 
}


/
// A vertex attribute array buffer must be prepared when your 
// application wants to use the buffer to render any geometry. 
// When your application prepares an buffer, some OpenGL ES state
// is altered to allow bind the buffer and configure pointers.
- (void)prepareToDrawWithAttrib:(GLuint)index
   numberOfCoordinates:(GLint)count
   attribOffset:(GLsizeiptr)offset
   shouldEnable:(BOOL)shouldEnable
{
   NSParameterAssert((0 < count) && (count < 4));
   NSParameterAssert(offset < self.stride);
   NSAssert(0 != name, @"Invalid name");

   glBindBuffer(GL_ARRAY_BUFFER,     // STEP 2
      self.name);

   if(shouldEnable)
   {
      glEnableVertexAttribArray(     // Step 4
         index); 
   }

   glVertexAttribPointer(            // Step 5
      index,               // Identifies the attribute to use
      count,               // number of coordinates for attribute
      GL_FLOAT,            // data is floating point
      GL_FALSE,            // no fixed point scaling
      (self.stride),       // total num bytes stored per vertex
      NULL + offset);      // offset from start of each vertex to 
                           // first coord for attribute
#ifdef DEBUG
   {  // Report any errors 
      GLenum error = glGetError();
      if(GL_NO_ERROR != error)
      {
         NSLog(@"GL Error: 0x%x", error);
      }
   }
#endif
}


/
// Submits the drawing command identified by mode and instructs
// OpenGL ES to use count vertices from the buffer starting from
// the vertex at index first. Vertex indices start at 0.
- (void)drawArrayWithMode:(GLenum)mode
   startVertexIndex:(GLint)first
   numberOfVertices:(GLsizei)count
{
   NSAssert(self.bufferSizeBytes >= 
      ((first + count) * self.stride),
      @"Attempt to draw more vertex data than available.");
      
   glDrawArrays(mode, first, count); // Step 6
}


/
// Submits the drawing command identified by mode and instructs
// OpenGL ES to use count vertices from previously prepared 
// buffers starting from the vertex at index first in the 
// prepared buffers
+ (void)drawPreparedArraysWithMode:(GLenum)mode
   startVertexIndex:(GLint)first
   numberOfVertices:(GLsizei)count;
{
   glDrawArrays(mode, first, count); // Step 6
}


/
// This method deletes the receiver's buffer from the current
// Context when the receiver is deallocated.
- (void)dealloc
{
    // Delete buffer from current context
    if (0 != name)
    {
        glDeleteBuffers (1, &name); // Step 7 
        name = 0;
    }
}

@end
在该类中,类维持着一个opengl缓存标志符,在刚开始学OpenGL的时候我觉得这个标识符没用,其实是大错特错,以至于后来自己写代码出现一些非预期的图形自己死活找不到原因,只能照着example重新写一遍。缓存标识符标识当前活动的GPU内存,当你想配置某一块内存或者你想绘制这一块内存的内容时,你需要调用GLBindbuffer函数,并且该函数第二个参数要设置成你想操作内存的标识,然后接下来的操作都是针对这一块内存进行的,操作完过后记得再次调用GLBindBuffer(GL_ARRAY_BUFFER,0),将当前活动内存设置为空,非必需,但是这样做会是个好习惯.下面是我写的一些代码,在ObjectMesh类中大家可以将prepareToDraw,draw函数中的glbindbuffer函数全部注释,然后看下是否能得到想要的图形。
@interface ObjectMesh()
@property(nonatomic,strong)NSData *indicesData;
@property(nonatomic,assign)GLsizei vertsNum;
@property(nonatomic,assign)GLsizei indiceCount;
@property(nonatomic,assign)GLuint name;
@property(nonatomic,assign)GLuint index;
@end
@implementation ObjectMesh
@synthesize name;
@synthesize index;
-(id)initWithVertexData:(NSData *)data Indices:(NSData *)indices{
    self=[super init];
    if(self){
        glGenBuffers(1, &name);
        glBindBuffer(GL_ARRAY_BUFFER, name);
        _vertsNum=(GLsizei)data.length/sizeof(ObjectMeshVertex);
        glBufferData(GL_ARRAY_BUFFER, data.length, data.bytes, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        if(indices){
            glGenBuffers(GL_ELEMENT_ARRAY_BUFFER, &index);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.length, indices.bytes, GL_STATIC_DRAW);
        }
    }
    return self;
}

-(id)initWithPositionData:(GLfloat *)data normalData:(GLfloat *)normal texCoordsData:(GLfloat *)texCoords vertexCount:(GLsizei)count indexData:(GLfloat *)indices indicesCount:(GLsizei)indiceCount{
    if(nil==data || nil ==normal){
        return nil;
    }
    NSMutableData *vert=[NSMutableData data];
    NSData *indicedata;
    for(int i=0;i<count;++i){
        ObjectMeshVertex meshVertex;
        meshVertex.position.x=data[i*3];
        meshVertex.position.y=data[i*3+1];
        meshVertex.position.z=data[i*3+2];
        meshVertex.normal.x=normal[i*3];
        meshVertex.normal.y=normal[i*3+1];
        meshVertex.normal.z=normal[i*3+2];
        if(texCoords){
            meshVertex.texCoords0.s=texCoords[2*i];
            meshVertex.texCoords0.t=texCoords[2*i+1];
        }else{
            meshVertex.texCoords0.s=0;
            meshVertex.texCoords0.t=0;
        }
        [vert appendBytes:&meshVertex length:sizeof(meshVertex)];
    }
    indicedata=[NSData dataWithBytes:indices length:sizeof(GLfloat)*indiceCount];
    return [self initWithVertexData:vert Indices:indicedata];
}

-(void)prepareToDraw{
    glBindBuffer(GL_ARRAY_BUFFER, name);
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(ObjectMeshVertex), NULL+offsetof(ObjectMeshVertex, position));
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(ObjectMeshVertex), NULL+offsetof(ObjectMeshVertex, normal));
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(ObjectMeshVertex), NULL+offsetof(ObjectMeshVertex, texCoords0));
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

-(void)draw{
    if(_indicesData){
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
        glDrawElements(GL_TRIANGLES, (GLsizei)_indicesData.length/sizeof(GLfloat), GL_UNSIGNED_SHORT, _indicesData.bytes);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }else{
        glBindBuffer(GL_ARRAY_BUFFER, name);
        glDrawArrays(GL_TRIANGLES, 0, _vertsNum);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
}
完整源代码请参照: 点击打开链接该代码没有给对象添加移动的效果,请自行添加
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值