iOS 4.1 OpenGL ES 1.1没有绘制纹理

时间:2010-09-13 23:09:35

标签: iphone objective-c opengl-es ios4 textures

由于某些原因,我的纹理没有绘制,即使我的代码看起来与旧项目完全相同。到目前为止,顶点和TexCoords看起来很好,因为我正在绘制白色方块,而是应该绘制纹理。

到目前为止的过程, 我加载了一个控制器,在loadView中,我

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR);

然后我的渲染器被加载,这对构造没有任何作用。之后我将纹理加载到gl中。这段代码是我原来项目的直接副本,我知道它有效。

- (GLuint)textureFromPath:(NSString *)path
{
    GLuint texture;
    glGenTextures(1, &texture);

    UIImage *img = [[UIImage alloc] initWithContentsOfFile:path];

    if (!img) {
        NSLog(@"Image \"%@\" could not be loaded and was not bound", path);
        return 0;
    }

    CGImageRef cgimage = img.CGImage;

    float width = CGImageGetWidth(cgimage);
    float height = CGImageGetHeight(cgimage);
    CGRect bounds = CGRectMake(0, 0, width, height);
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();

    void *image = malloc(width * height * 4);
    CGContextRef context = CGBitmapContextCreate(image, width, height, 8, 4 * width, colourSpace, kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colourSpace);
    CGContextClearRect(context, bounds);
    CGContextTranslateCTM (context, 0, height);
    CGContextScaleCTM (context, 1.0, -1.0);
    CGContextDrawImage(context, bounds, cgimage);

    CGContextRelease(context);

    glBindTexture(GL_TEXTURE_2D, texture);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);    

    [img release];
    free(image);

    return texture;
}

然后我从gl获取生成纹理,并在Renderer的数组中将它的位置指定为0.我也在我的旧项目中做了这个并且工作得很好。到目前为止,我觉得很好。

然后,应用程序告诉它startAnimation,然后它调用setFramebuffer,它在其中调用createFramebuffer,因为framebuffer未定义。然后它通知Renderer(顺便说一句,Renderer是一个C ++类),它已经创建了帧缓冲区。

void bufferHasBeenCreated() const {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(-160.0f, 160.0f, -240.0f, 240.0f, -5.0f, 1.0f);
    glViewport(0, 0, 320, 480);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_SRC_COLOR);
}

然后在Renderer上调用渲染。

void render() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glClearColor(0.325f, 0.0f, 0.325f, 1.0f);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    static float rot = 0.0f;

    glRotatef(rot, 0.0f, 0.0f, 1.0f);

    //glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glBindTexture(GL_TEXTURE_2D, texture_[0]);

    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
        printf("Error. glError: 0x%04X\n", err);

    glVertexPointer(2, GL_FLOAT, 0, pos[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, black);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glVertexPointer(2, GL_FLOAT, 0, pos[1]);
    glTexCoordPointer(2, GL_FLOAT, 0, black);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glVertexPointer(2, GL_FLOAT, 0, pos[2]);
    glTexCoordPointer(2, GL_FLOAT, 0, black);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    rot += 0.5f;

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

然后最后调用presentFramebuffer,它绑定了renderBuffer和setup上下文。

1 个答案:

答案 0 :(得分:1)

编辑:我已经做了更多的工作,结果发现它与上下文和缓冲区有关。每当我在启用GL_TEXTURE_2D和GL_BLEND时执行上下文操作时,纹理都不会加载。然而,当缓冲区加载并且一切正常时,请执行此操作。


我有自己的纹理。我把所有代码都拿出来放了自己的文件。然后,我将再次开始拉动它,并希望在我已经拥有的结构中完成所有工作。

(Objective-C)ES1Renderer.h

#import <QuartzCore/QuartzCore.h>
#import "OpenGLES.h"

@interface ES1Renderer : UIView {
@private
    GLint backingWidth;
    GLint backingHeight;
    EAGLContext *context;

    GLuint viewFramebuffer, viewRenderbuffer;

    GLuint texture[1];

    BOOL animating;
    BOOL displayLinkSupported;
    NSInteger animationFrameInterval;
    // Use of the CADisplayLink class is the preferred method for controlling your animation timing.
    // CADisplayLink will link to the main display and fire every vsync when added to a given run-loop.
    // The NSTimer class is used only as fallback when running on a pre 3.1 device where CADisplayLink
    // isn't available.
    id displayLink;
    NSTimer *animationTimer;
}

@property (readonly, nonatomic, getter=isAnimating) BOOL animating;
@property (nonatomic) NSInteger animationFrameInterval;

- (void) startAnimation;
- (void) stopAnimation;

- (void)render;

@end

下一步ES1Renderer.m

#import "ES1Renderer.h"


@implementation ES1Renderer

@synthesize animating;
@dynamic animationFrameInterval;

+ (Class)layerClass
{
    return [CAEAGLLayer class];
}

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {

        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

        if (!context || ![EAGLContext setCurrentContext:context])
        {
            [self release];
            return nil;
        }

        // Generate buffers
        glGenFramebuffersOES(1, &viewFramebuffer);
        glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

        glGenRenderbuffersOES(1, &viewRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);


        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        // Disable Depth
        glDisable(GL_DEPTH_TEST);

        // Load textures
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE, GL_SRC_COLOR);

        glGenTextures(1, texture);

        UIImage *img = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"colour" ofType:@"png"]];

        if (!img) {
            NSLog(@"Image \"colour.png\" could not be loaded and was not bound");
            [self release];
            return nil;
        }

        CGImageRef cgimage = img.CGImage;

        float width = CGImageGetWidth(cgimage);
        float height = CGImageGetHeight(cgimage);
        CGRect bounds = CGRectMake(0, 0, width, height);
        CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();

        void *image = malloc(width * height * 4);
        CGContextRef imgContext = CGBitmapContextCreate(image,
                                                                                                 width, height,
                                                                                                 8, 4 * width, colourSpace,
                                                                                                 kCGImageAlphaPremultipliedLast);

        CGColorSpaceRelease(colourSpace);
        CGContextClearRect(imgContext, bounds);
        CGContextTranslateCTM (imgContext, 0, height);
        CGContextScaleCTM (imgContext, 1.0, -1.0);
        CGContextDrawImage(imgContext, bounds, cgimage);

        CGContextRelease(imgContext);

        glBindTexture(GL_TEXTURE_2D, texture[0]);

        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

        GLenum err = glGetError();
        if (err != GL_NO_ERROR)
            NSLog(@"Error. glError: 0x%04X\n", err);

        free(image);
        [img release];

        animating = FALSE;
        displayLinkSupported = FALSE;
        animationFrameInterval = 1;
        displayLink = nil;
        animationTimer = nil;

        // A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
        // class is used as fallback when it isn't available.
        NSString *reqSysVer = @"3.1";
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
            displayLinkSupported = TRUE;
    }

    return self;
}

- (void)drawView:(id)sender
{
    [self render];

    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
        NSLog(@"Error. glError: 0x%04X\n", err);
}

- (void) render
{
    //glDisable(GL_TEXTURE_2D);

    [EAGLContext setCurrentContext:context];
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

    static const float textureVertices[] = {
        -0.5f, -0.33f,
        0.5f, -0.33f,
        -0.5f,  0.33f,
        0.5f,  0.33f,   
    };

    static const float textureCoords[] = {
        0.0f, 0.0f,
        0.0f, 0.515625f,
        0.12890625f, 0.0f,
        0.12890625f, 0.515625f,
    };

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glBindTexture(GL_TEXTURE_2D, texture[0]);

    //glColor4f(0.0f, 0.0f, 0.0f, 1.0f);

    glVertexPointer(2, GL_FLOAT, 0, textureVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

- (void)layoutSubviews
{   
    [EAGLContext setCurrentContext:context];

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer *)self.layer];
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0, 0, backingWidth, backingHeight);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
        NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
}

- (void) dealloc
{
    // Tear down GL
    if (viewFramebuffer)
    {
        glDeleteFramebuffersOES(1, &viewFramebuffer);
        viewFramebuffer = 0;
    }

    if (viewRenderbuffer)
    {
        glDeleteRenderbuffersOES(1, &viewRenderbuffer);
        viewRenderbuffer = 0;
    }

    // Tear down context
    if ([EAGLContext currentContext] == context)
        [EAGLContext setCurrentContext:nil];

    [context release];
    context = nil;

    displayLink = nil;
    animationTimer = nil;

    [super dealloc];
}

- (NSInteger) animationFrameInterval
{
    return animationFrameInterval;
}

- (void) setAnimationFrameInterval:(NSInteger)frameInterval
{
    // Frame interval defines how many display frames must pass between each time the
    // display link fires. The display link will only fire 30 times a second when the
    // frame internal is two on a display that refreshes 60 times a second. The default
    // frame interval setting of one will fire 60 times a second when the display refreshes
    // at 60 times a second. A frame interval setting of less than one results in undefined
    // behavior.
    if (frameInterval >= 1)
    {
        animationFrameInterval = frameInterval;

        if (animating)
        {
            [self stopAnimation];
            [self startAnimation];
        }
    }
}

- (void) startAnimation
{
    if (!animating)
    {
        if (displayLinkSupported)
        {
            // CADisplayLink is API new to iPhone SDK 3.1. Compiling against earlier versions will result in a warning, but can be dismissed
            // if the system version runtime check for CADisplayLink exists in -initWithCoder:. The runtime check ensures this code will
            // not be called in system versions earlier than 3.1.

            displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(drawView:)];
            [displayLink setFrameInterval:animationFrameInterval];
            [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        }
        else 
            animationTimer = [NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)((1.0 / 60.0) * animationFrameInterval) target:self selector:@selector(drawView:) userInfo:nil repeats:TRUE];

        animating = TRUE;
    }
}

- (void)stopAnimation
{
    if (animating)
    {
        if (displayLinkSupported)
        {
            [displayLink invalidate];
            displayLink = nil;
        }
        else
        {
            [animationTimer invalidate];
            animationTimer = nil;
        }

        animating = FALSE;
    }
}


@end

此代码只有一个问题。它已经过时了。 Apple发布了一种新的做事方式,但地狱。它有效。

<强>更新 事实证明我在加载纹理之前已经设置了上下文。