views:

346

answers:

1

For some reason my texture are not drawing, even though my code looks exactly the same as an old project that did. So far, the vertexes and TexCoords look fine, as I am having white squares being drawn, where the texture should be drawn instead.

The process so far goes, I load up a Contoller and in loadView, I

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

Then my renderer is loaded up, which does nothing on construction. After that I load up my Texture into gl. This code is a direct copy from my old project and I know it works.

- (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;
}

I then take the generate texture from gl and assign it's postion in the array of the Renderer at 0. I also did this in my old project and worked fine too. So far so good, I feel.

The Application then tells it to startAnimation, which it then calls setFramebuffer, which within it calls createFramebuffer as framebuffer is undefined. It then notifies the Renderer (btw, Renderer is a C++ class) that it has created the framebuffers.

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

It then calls the render on 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);
}

and then finally it then calls presentFramebuffer, which binds the renderBuffer and setup context.

A: 

Edit: I have done some more work on this, and it turns out it is something to do with the context and the buffers. Whenever I do just the context while enabling GL_TEXTURE_2D and GL_BLEND, as you do, the textures don't load. Yet do it when the buffers are loaded up and everything works.


I have got my texture to draw. I pulled all my code out and put it's own file. I will then start pulling it a part again and hopefully get everything working in the structure that I already have.

(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

Next 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

There is only one problem with this code. It's out of data. Apple released a new way of doing things, but hell. It works.

kuroutadori