OPENGL之GLBindBuffer

最新推荐文章于 2025-11-22 04:13:23 发布

原创

最新推荐文章于 2025-11-22 04:13:23 发布

·

6.4k 阅读

·

1

·

1

·

CC 4.0 BY-SA版权

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

文章标签:

#OPENGLES

#GLBindBuffer的作用

#碰碰车

OPENGL-ES

专栏收录该内容

9 篇文章

订阅专栏

本文深入探讨OpenGL ES中缓存标识符的作用及其在图形绘制中的重要性。通过实例讲解如何正确使用缓存标识符来避免图形显示错误,强调了在绘制前后正确绑定和解除缓存的重要性。

部署运行你感兴趣的模型镜像一键部署

在模仿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

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);

}

}完整源代码请参照:

点击打开链接该代码没有给对象添加移动的效果,请自行添加

您可能感兴趣的与本文相关的镜像

Wan2.2-I2V-A14B

图生视频

Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

一键部署运行