0

简介:我是 OpenGL 的新手。我首先在我的 PC 上熟悉 OpenGL 上的纹理映射和基本转换/翻译。现在看来我基本上是在重新学习一切,因为我试图使用 GLKit(GLKView 项目模板帮助很大)创建一个带有 PNG 纹理的简单多边形(四边形)。

事情是这样的:使用 GLKBasicEffect 渲染方式,使用项目模板的开箱即用实现,我实际上能够非常快速地启动和运行。但是,我在过去 24 小时内阅读了很多关于忽略这条路线并采用“OpenGL ES2”方式的建议。我对此的一般想法基本上是:固定流水线与可编程流水线。任何。

问题:使用“ES2”方法时,我可以看到我的四边形,但我无法在其上应用纹理。

问题:有人知道我可以遵循的简单教程/示例吗?或者更好的是,有人能弄清楚我做错了什么吗?

* 插入更新评论 *

我发现由于我的 openGL 设置中的两件事而引发了 glError:我正在调用 glEnable(GL_TEXTURE_2D) 和 glEnableClientState(GL_TEXTURE_COORD_ARRAY)。如果没有这些,我该如何启用纹理映射?或者也许某个地方有更大的错误?仅供参考,我正在使用 Opengl ES2。

* 更新插入结束 *

我的 ViewController 文件在下面。

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

// Uniform index.
enum
{
    UNIFORM_MODELVIEWPROJECTION_MATRIX,
    UNIFORM_NORMAL_MATRIX,
    NUM_UNIFORMS
};
GLint uniforms[NUM_UNIFORMS];

// Attribute index.
enum
{
    ATTRIB_VERTEX,
    ATTRIB_NORMAL,
    NUM_ATTRIBUTES
};

BOOL updateRotate = FALSE;
VertexData *p_meshVertexData = nil;
int g_numFaces = 0;
GLuint g_textures[2]; // 0: photo, 1: picture frame.

const int DataSize = 48;
GLfloat PortraitVertexData[DataSize] =
{
    // CCW
    -0.5f, 0.5f, 0.0f,          0.0f, 0.0f, 1.0f,   0,1,
    -0.5f, -0.5f, 0.0f,         0.0f, 0.0f, 1.0f,   0,0,
    0.5f, -0.5f, 0.0f,         0.0f, 0.0f, 1.0f,   1,0,

    -0.5f, 0.5f, 0.0f,          0.0f, 0.0f, 1.0f,   0,1,
    0.5f, -0.5f, 0.0f,         0.0f, 0.0f, 1.0f,   1,0,
    0.5f, 0.5f, 0.0f,         0.0f, 0.0f, 1.0f,   1,1,

};

@interface ViewController () {
    GLuint _program;

    GLKMatrix4 _modelViewProjectionMatrix;
    GLKMatrix3 _normalMatrix;
    float _rotation;

    GLuint _vertexArray;
    GLuint _vertexBuffer;
}
@property (strong, nonatomic) EAGLContext *context;
//@property (strong, nonatomic) GLKBaseEffect *effect;
@property (strong, nonatomic) GLKTextureInfo *texture;
@property (nonatomic, retain) CaptureEngine *engine;

- (void)setupGL;
- (void)tearDownGL;
- (BOOL)loadShaders;
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file;
- (BOOL)linkProgram:(GLuint)prog;
- (BOOL)validateProgram:(GLuint)prog;
@end

@implementation ViewController

@synthesize context = _context;
//@synthesize effect = _effect;
@synthesize texture = _texture;
@synthesize engine;


/// View did load.
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    if (!self.context) {
        NSLog(@"Failed to create ES context");
    }

    GLKView *view = (GLKView *)self.view;
    view.context = self.context;
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;

    [self initEngine];
    [self setupGL];
}

/// Initialize engine object.
- (void) initEngine
{
    self.engine = [[CaptureEngine alloc] init];

    g_numFaces = DataSize / 8;
    p_meshVertexData = (VertexData *)malloc(g_numFaces * sizeof(VertexData));

    int numIndex = 0;
    for (int i = 0; i < DataSize; i += 8)
    {
        float x = PortraitVertexData[i];
        float y = PortraitVertexData[i + 1];
        float z = PortraitVertexData[i + 2];

        float nx = PortraitVertexData[i + 3];
        float ny = PortraitVertexData[i + 4];
        float nz = PortraitVertexData[i + 5];

        float tx = PortraitVertexData[i + 6];
        float ty = PortraitVertexData[i + 7];

        VertexData data;
        data.vertex.x = x;
        data.vertex.y = y;
        data.vertex.z = z;
        data.normal.x = nx;
        data.normal.y = ny;
        data.normal.z = nz;
        data.textureCoord.x = tx;
        data.textureCoord.y = ty;

        p_meshVertexData[numIndex++] = data;
    }

   // UIImage *testImage = [UIImage imageNamed:@"frame.png"];
   // self.previewImage.image = [ImageLoader ConvertToGrayedImage:testImage];
}

// Dealloc.
- (void)dealloc
{    
    [self tearDownGL];

    if ([EAGLContext currentContext] == self.context) {
        [EAGLContext setCurrentContext:nil];
    }
}

// Memory warning.
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

    if ([self isViewLoaded] && ([[self view] window] == nil)) {
        self.view = nil;

        [self tearDownGL];

        if ([EAGLContext currentContext] == self.context) {
            [EAGLContext setCurrentContext:nil];
        }
        self.context = nil;
    }

    // Dispose of any resources that can be recreated.
}

// Setup OpenlGL.
- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];

    [self loadShaders];

    /*
    self.effect = [[GLKBaseEffect alloc] init];
    self.effect.light0.enabled = GL_TRUE;
    self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 1.0f, 1.0f, 0.5f);
    self.effect.lightingType = GLKLightingTypePerPixel;
    */

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * g_numFaces, p_meshVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), 0);

    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char *)12);

    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (char *)24);


    //// texture sample
  /*
    glActiveTexture(GL_TEXTURE0);
    NSString *path = [[NSBundle mainBundle] pathForResource:@"frame" ofType:@"png"];

    NSError *error;
    NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                        forKey:GLKTextureLoaderOriginBottomLeft];


    self.texture = [GLKTextureLoader textureWithContentsOfFile:path
                                                       options:options error:&error];
    if (self.texture == nil)
        NSLog(@"Error loading texture: %@", [error localizedDescription]);

    */
    /*
    GLKEffectPropertyTexture *tex = [[GLKEffectPropertyTexture alloc] init];
    tex.enabled = YES;
    tex.envMode = GLKTextureEnvModeDecal;
    tex.name = self.texture.name;

    self.effect.texture2d0.name = tex.name;
    */

    UIImage *textureImage = [UIImage imageNamed:@"frame.png"];
    [self ApplyTexture: textureImage];

    //// end of texture sample

    glBindVertexArrayOES(0);
}

// Dealloc OpenlGL.
- (void)tearDownGL
{
    [EAGLContext setCurrentContext:self.context];

    glDeleteBuffers(1, &_vertexBuffer);
    glDeleteVertexArraysOES(1, &_vertexArray);

    //self.effect = nil;

    if (_program)
    {
        glDeleteProgram(_program);
        _program = 0;
    }
}

#pragma mark - GLKView and GLKViewController delegate methods

// Update process.
- (void)update
{
    /// Default OpenGL project template (2 cubes) ///

    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(60.0f), aspect, 0.1f, 100.0f);

    //self.effect.transform.projectionMatrix = projectionMatrix;

    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -2.0f);
    baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);

    /*
    // Compute the model view matrix for the object rendered with GLKit
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 0, 1.0f, 0);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);

    self.effect.transform.modelviewMatrix = modelViewMatrix;
    */

    // Compute the model view matrix for the object rendered with ES2

    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0, 0, 0);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 0, 1.0f, 0);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
    _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
    _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);


    if (updateRotate)
    {
        _rotation += self.timeSinceLastUpdate * 0.5f;
    }
}

// Render process.
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(1, 1, 1, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArrayOES(_vertexArray);

    /*
    // Render the object with GLKit
    [self.effect prepareToDraw];
    glDrawArrays(GL_TRIANGLES, 0, g_numFaces);
    */

    // Render the object again with ES2
    glUseProgram(_program);

    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
    glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

    glDrawArrays(GL_TRIANGLES, 0, g_numFaces);

}

- (int) ApplyTexture:(UIImage *)image
{
    // 1
    CGImageRef spriteImage = image.CGImage;
    if (!spriteImage)
    {
        NSLog(@"Failed to apply texture.");
        return -1;
    }

    // 2
    size_t width = CGImageGetWidth(spriteImage);
    size_t height = CGImageGetHeight(spriteImage);
    GLubyte * spriteData = (GLubyte *) calloc(width * width * 4, sizeof(GLubyte));

    CGContextRef spriteContext = CGBitmapContextCreate(spriteData,
                                                       width,
                                                       width,
                                                       8,
                                                       width * 4,
                                                       CGImageGetColorSpace(spriteImage),
                                                       kCGImageAlphaPremultipliedLast);

    // 3
    CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
    CGContextRelease(spriteContext);

    // 4
    glGenTextures(1, &g_textures[0]);
    glBindTexture(GL_TEXTURE_2D, g_textures[0]);

    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
   // glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(spriteImage));
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, width, 0, GL_RGBA,
                 GL_UNSIGNED_BYTE, CFDataGetBytePtr(data));

    free(spriteData);
    return 0;
}

#pragma mark -  OpenGL ES 2 shader compilation

- (BOOL)loadShaders
{
    GLuint vertShader, fragShader;
    NSString *vertShaderPathname, *fragShaderPathname;

    // Create shader program.
    _program = glCreateProgram();

    // Create and compile vertex shader.
    vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
    if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
        NSLog(@"Failed to compile vertex shader");
        return NO;
    }

    // Create and compile fragment shader.
    fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
    if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
        NSLog(@"Failed to compile fragment shader");
        return NO;
    }

    // Attach vertex shader to program.
    glAttachShader(_program, vertShader);

    // Attach fragment shader to program.
    glAttachShader(_program, fragShader);

    // Bind attribute locations.
    // This needs to be done prior to linking.
    glBindAttribLocation(_program, GLKVertexAttribPosition, "position");
    glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");

    // Link program.
    if (![self linkProgram:_program]) {
        NSLog(@"Failed to link program: %d", _program);

        if (vertShader) {
            glDeleteShader(vertShader);
            vertShader = 0;
        }
        if (fragShader) {
            glDeleteShader(fragShader);
            fragShader = 0;
        }
        if (_program) {
            glDeleteProgram(_program);
            _program = 0;
        }

        return NO;
    }

    // Get uniform locations.
    uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
    uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");

    // Release vertex and fragment shaders.
    if (vertShader) {
        glDetachShader(_program, vertShader);
        glDeleteShader(vertShader);
    }
    if (fragShader) {
        glDetachShader(_program, fragShader);
        glDeleteShader(fragShader);
    }

    return YES;
}

- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
    GLint status;
    const GLchar *source;

    source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
    if (!source) {
        NSLog(@"Failed to load vertex shader");
        return NO;
    }

    *shader = glCreateShader(type);
    glShaderSource(*shader, 1, &source, NULL);
    glCompileShader(*shader);

#if defined(DEBUG)
    GLint logLength;
    glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetShaderInfoLog(*shader, logLength, &logLength, log);
        NSLog(@"Shader compile log:\n%s", log);
        free(log);
    }
#endif

    glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
    if (status == 0) {
        glDeleteShader(*shader);
        return NO;
    }

    return YES;
}

- (BOOL)linkProgram:(GLuint)prog
{
    GLint status;
    glLinkProgram(prog);

#if defined(DEBUG)
    GLint logLength;
    glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(prog, logLength, &logLength, log);
        NSLog(@"Program link log:\n%s", log);
        free(log);
    }
#endif

    glGetProgramiv(prog, GL_LINK_STATUS, &status);
    if (status == 0) {
        return NO;
    }

    return YES;
}

- (BOOL)validateProgram:(GLuint)prog
{
    GLint logLength, status;

    glValidateProgram(prog);
    glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0) {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(prog, logLength, &logLength, log);
        NSLog(@"Program validate log:\n%s", log);
        free(log);
    }

    glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
    if (status == 0) {
        return NO;
    }

    return YES;
}
4

1 回答 1

0

哇。看起来纹理映射的 glEnable 已被弃用。 https://gamedev.stackexchange.com/questions/20656/is-glenable-obsolete-unneeded-in-opengl-es-2

啊。我想我别无选择,只能学习这个像素/片段着色器火箭手术。

于 2013-04-22T06:25:43.180 回答