iOS 4.1 OpenGL ES 1.1 не рисует текстуру - PullRequest
1 голос
/ 14 сентября 2010

По какой-то причине моя текстура не рисуется, хотя мой код выглядит точно так же, как старый проект, который делал. Пока что вершины и TexCoords выглядят хорошо, поскольку у меня нарисованы белые квадраты, где вместо этого должна быть нарисована текстура.

Пока идет процесс, Я загружаю Contoller и в loadView, я

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

Затем загружается мой рендер, который ничего не делает при построении После этого я загружаю мою текстуру в гл. Этот код является прямой копией моего старого проекта, и я знаю, что он работает.

- (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 и присваиваю ее положение в массиве рендерера в 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 и контекст настройки.

1 Ответ

1 голос
/ 14 сентября 2010

Edit: я проделал еще кое-что над этим, и оказалось, что это как-то связано с контекстом и буферами. Всякий раз, когда я делаю только контекст при включении 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 выпустила новый способ ведения дел, но, черт возьми. Это работает.

Обновление: Оказывается, я установил контекст перед загрузкой текстур.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...