iphone opengl es 2.0,如何使用objective-c类来存储原始数据?
Posted
技术标签:
【中文标题】iphone opengl es 2.0,如何使用objective-c类来存储原始数据?【英文标题】:iphone opengl es 2.0, how to use objective-c class to store primitive data? 【发布时间】:2012-07-25 03:32:13 【问题描述】:我正在尝试使用名为 Primitive 的objective-c 类的nsarray,它存储顶点、纹理坐标、vertexBuffer、indexBuffer 和纹理缓冲区等原始数据。
但它不是用纹理绘制矩形。 当我尝试包含相同信息的 c 结构时,它画得很好。
我不确定我在哪里失踪 谁能给我一些提示?
//Here is my primitive class.
//It also has Vertex class which has vertex positions and texture coordinates
// This represents one primitive, in this app, it is rectangle
@interface Primitive : NSObject
@public
GLuint vertexBuffer;
GLuint indexBuffer;
GLuint textureBuffer;
@property (nonatomic, copy) NSArray * vertices; //consist 4 vertices
- (id)initWithVertices:(NSArray *)vertices;
@end
@interface Vertex : NSObject
@property (nonatomic, copy) NSArray * position; //(x,y,z) per vertex
@property (nonatomic, copy) NSArray * textureCoordinate; //(s,t) per vertex
- (id)initWithPointX:(float)x Y:(float)y Z:(float)z;
- (void)printVal;
@end
@implementation Primitive
@synthesize vertices = m_vertices;
- (id)initWithVertices:(NSArray *)vertices
self = [super init];
if(self)
m_vertices = [[NSArray alloc] initWithArray:vertices];
return self;
@end
@implementation Vertex
@synthesize position = m_position;
@synthesize textureCoordinate = m_textureCoordinate;
- (id)initWithPointX:(float)x Y:(float)y Z:(float)z
self = [super init];
if(self)
m_position = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:x],
[NSNumber numberWithFloat:y],
[NSNumber numberWithFloat:z], nil];
return self;
// and here is how I generate vbo. it's in other file
- (void)setupVertexBufferObjects
for(Primitive * primitive in m_primitives)
NSLog(@"setting vbo");
glGenBuffers(1, &primitive->vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, primitive->vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(primitive.vertices),
(__bridge void *)primitive.vertices, GL_STATIC_DRAW);
glGenBuffers(1, &primitive->indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, primitive->indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
// and this is how I render, this is also in other file than Primitive and above method
// this one worked fine when I had c struct to provide vertices and texture coordinate
glClearColor(0, 104.0/255, 55.0/255, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
GLuint positionSlot = glGetAttribLocation(m_programHandle, "Position");
glEnableVertexAttribArray(positionSlot);
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE,
[m_candleModel sizeOfVertex], 0);
GLuint texCoordSlot = glGetAttribLocation(m_programHandle, "TexCoordIn");
glEnableVertexAttribArray(texCoordSlot);
GLuint textureUniform = glGetUniformLocation(m_programHandle, "Texutre");
glVertexAttribPointer(texCoordSlot, 2, GL_FLOAT, GL_FALSE,
[m_candleModel sizeOfVertex], (GLvoid *)(sizeof(float) * 3));
GLuint floorTexture = [m_candleModel getTexture];
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, floorTexture);
glUniform1i(textureUniform, 0);
glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
glDisableVertexAttribArray(positionSlot);
[m_context presentRenderbuffer:GL_RENDERBUFFER];
【问题讨论】:
【参考方案1】:如果您只是想制作一个不会改变形状的刚性对象,我建议您获取位置、比例、旋转等信息,然后更改顶点以适应信息。这是我目前正在研究的一个类,它制作一个黑色正方形,可以进行旋转、不透明度、位置和大小。希望对你有帮助
typedef struct
float Position[3];
float Color[4];
Vertex;
@interface GameSprite : NSObject
GLuint positionAttrib;
GLuint colorAttrib;
GLuint programHandle;
GLuint modelviewUniform;
CGSize spriteSize;
CGPoint position;
float rotation;
float alpha;
BOOL HasRotated;
-(id) init;
-(id) initWithSize:(CGSize)size AndPosition:(CGPoint)spritePosition;
-(void) render;
-(void) setPosition:(CGPoint)newPosition;
-(void) setRotation:(float)newRotation;
-(void) setAlpha:(float)newAlpha;
@property (readonly, nonatomic) CGPoint getPosition;
@property (readonly, nonatomic) float getRotation;
@property (readonly, nonatomic) float getAlpha;
@property (readonly, nonatomic) CGSize getSize;
@end
实施...
#define kPI180 0.017453
#define k180PI 57.295780
#define degreesToRadians(x) (x * kPI180)
#define radiansToDegrees(x) (x * k180PI)
const Vertex GameSpriteVertices[] =
1, 1, 0, 0, 0, 0, 1,
1, 2, 0, 0, 0, 0, 1,
2, 1, 0, 0, 0, 0, 1,
2, 2, 0, 0, 0, 0, 1
;
const GLubyte GameSpriteIndices[] =
0, 1, 2,
2, 3, 1
;
@implementation GameSprite
@synthesize getPosition, getRotation, getAlpha, getSize;
-(id) initWithSize:(CGSize)size AndPosition:(CGPoint)spritePosition
if (self = [super init])
position = spritePosition;
getPosition = position;
rotation = 0;
getRotation = rotation;
alpha = 1.0;
getAlpha = alpha;
spriteSize = size;
getSize = spriteSize;
GLuint VertexShader = [self compileShader:@"VertexShader" withType:GL_VERTEX_SHADER];
GLuint FragmentShader = [self compileShader:@"FragmentShader" withType:GL_FRAGMENT_SHADER];
programHandle = glCreateProgram();
glAttachShader(programHandle, VertexShader);
glAttachShader(programHandle, FragmentShader);
glLinkProgram(programHandle);
glUseProgram(programHandle);
positionAttrib = glGetAttribLocation(programHandle, "Position");
colorAttrib = glGetAttribLocation(programHandle, "SourceColor");
glEnableVertexAttribArray(positionAttrib);
glEnableVertexAttribArray(colorAttrib);
modelviewUniform = glGetUniformLocation(programHandle, "Modelview");
return self;
-(id) init
if (self = [super init])
GLuint VertexShader = [self compileShader:@"VertexShader" withType:GL_VERTEX_SHADER];
GLuint FragmentShader = [self compileShader:@"FragmentShader" withType:GL_FRAGMENT_SHADER];
programHandle = glCreateProgram();
glAttachShader(programHandle, VertexShader);
glAttachShader(programHandle, FragmentShader);
glLinkProgram(programHandle);
glUseProgram(programHandle);
positionAttrib = glGetAttribLocation(programHandle, "Position");
colorAttrib = glGetAttribLocation(programHandle, "SourceColor");
glEnableVertexAttribArray(positionAttrib);
glEnableVertexAttribArray(colorAttrib);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GameSpriteVertices), GameSpriteVertices, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GameSpriteIndices), GameSpriteIndices, GL_STATIC_DRAW);
modelviewUniform = glGetUniformLocation(programHandle, "Modelview");
return self;
-(void) render
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// Add the position to the square
Vertex TempVertices[] =
position.x - spriteSize.width/2, position.y - spriteSize.height/2, 0, 0, 0, 0, alpha,
position.x - spriteSize.width/2, position.y + spriteSize.height/2, 0, 0, 0, 0, alpha,
position.x + spriteSize.width/2, position.y - spriteSize.height/2, 0, 0, 0, 0, alpha,
position.x + spriteSize.width/2, position.y + spriteSize.height/2, 0, 0, 0, 0, alpha
;
// Add the rotation to the square
for (int i = 0; i < sizeof(TempVertices)/sizeof(TempVertices[0]); i++)
CGPoint vertex = CGPointMake(TempVertices[i].Position[0], TempVertices[i].Position[1]);
TempVertices[i].Position[0] = [self rotatePoint:vertex by:rotation around:position].x;
TempVertices[i].Position[1] = [self rotatePoint:vertex by:rotation around:position].y;
const GLubyte TempIndices[] =
0, 1, 2,
2, 3, 1
;
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(TempVertices), TempVertices, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(TempIndices), TempIndices, GL_STATIC_DRAW);
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
glDrawElements(GL_TRIANGLES, sizeof(GameSpriteIndices)/sizeof(GameSpriteIndices[0]), GL_UNSIGNED_BYTE, 0);
glDisable(GL_BLEND);
/*
Porgrammer access methods
*/
-(void) setPosition:(CGPoint)newPosition
position = newPosition;
getPosition = position;
-(void) setRotation:(float)newRotation
rotation = newRotation;
getRotation = rotation;
-(void) setAlpha:(float)newAlpha
alpha = newAlpha;
getAlpha = alpha;
/*
Helper methods
*/
-(GLuint) compileShader:(NSString *)path withType:(GLenum)shaderType
NSString *shaderPath = [[NSBundle mainBundle] pathForResource:path ofType:@"glsl"];
NSError *error;
NSString *shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
GLuint shaderHandle = glCreateShader(shaderType);
const char * shaderStringUTF8 = [shaderString UTF8String];
int shaderStringLength = [shaderString length];
glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
glCompileShader(shaderHandle);
return shaderHandle;
-(CGPoint) rotatePoint:(CGPoint)point by:(float)theta around:(CGPoint)origin
theta = degreesToRadians(theta);
CGPoint newPoint;
newPoint.x = cosf(theta) * (point.x - origin.x) - sinf(theta) * (point.y - origin.y) + origin.x;
newPoint.y = sinf(theta) * (point.x - origin.x) + cosf(theta) * (point.y - origin.y) + origin.y;
return newPoint;
@end
【讨论】:
以上是关于iphone opengl es 2.0,如何使用objective-c类来存储原始数据?的主要内容,如果未能解决你的问题,请参考以下文章
iPhone 成本与收益 - OpenGL ES 1.x 与 2.0
iPhone 上的 OpenGL ES 2.0:无法超过小索引/顶点数
iPad 或 iPhone 是不是支持 OpenGL ES 2.0?
是否可以在顶点着色器内持续更改 iPhone OpenGL ES 2.0 上的 VBO 值?