簡體   English   中英

iOS 4.1 OpenGL ES 1.1無法繪制紋理

[英]iOS 4.1 OpenGL ES 1.1 not drawing Texture

由於某種原因,我的紋理沒有繪制,即使我的代碼看起來與舊項目完全一樣。 到目前為止,頂點和TexCoords看起來不錯,因為我正在繪制白色正方形,而應該在其中繪制紋理。

到目前為止,我已經加載了Contoller,並在loadView中

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

然后,我的渲染器被加載,這對構造沒有任何作用。 之后,我將我的Texture載入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。我也在我的舊項目中做到這一點,並且工作得很好。 到目前為止,我感覺很好。

然后,應用程序告訴它要啟動動畫,然后調用setFramebuffer,因為未定義幀緩沖區,因此它在內部調用createFramebuffer。 然后,它通知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和設置上下文。

編輯:我對此做了更多工作,事實證明這與上下文和緩沖區有關。 每當我在啟用GL_TEXTURE_2D和GL_BLEND時僅執行上下文時,就不會加載紋理。 但是,當緩沖區加載完畢並且一切正常時,就可以這樣做。


我有要繪制的紋理。 我提取了所有代碼並將其放入自己的文件中。 然后,我將再次拉開它的一部分,並希望使所有工作都在我已經擁有的結構中進行。

(目標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

此代碼只有一個問題。 已經過時了 蘋果發布了一種新的做事方式,可惜。 有用。

更新:事實證明,我在加載紋理之前已經設置了上下文。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM