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 值?

iPhone OpenGL ES 2.0 奇怪的图案在 COLLADA 文件中的球体上渲染纹理

OpenGL ES 2.0 - iOS - 使用 FBO 渲染到纹理