2010-09-13 133 views
1

出於某種原因,我的紋理未繪製,即使我的代碼看起來與舊項目完全相同。到目前爲止,頂點和TexCoords看起來很好,因爲我正在繪製白色方塊,而應繪製紋理。iOS 4.1 OpenGL ES 1.1未繪製紋理

的進程迄今所說, 我加載了一個位指示和的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的生成紋理,並指定它的渲染器然後在0陣列我也這樣做在我的老項目,也沒關係曾在現在的位置。我感覺到目前爲止這麼好。

然後,應用程序告訴它startAnimation,然後它調用setFramebuffer,它內部調用createFramebuffer,因爲framebuffer是未定義的。然後通知Renderer(btw,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); 
} 

然後它在渲染器上調用渲染。

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上下文綁定起來。

+0

發佈您的紋理加載代碼。 – 2010-09-13 23:58:26

+0

我已經根據您的要求添加了紋理加載代碼。 – NebulaFox 2010-09-14 09:59:15

回答

1

編輯:我已經做了一些更多的工作,事實證明這是與上下文和緩衝區有關。每當我在啓用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 

只有一個與此代碼的問題。它已過時。蘋果公司發佈了一種新的做事方式,但地獄。有用。

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

+1

也許你的意思是你沒有在加載紋理之前設置上下文?在我的情況下,我已經在加載我的紋理之前在EAGLView中將setFrameBuffer註釋掉了,這會導致紋理呈現白色(可能會被更多的API返回檢查!))。 – 2011-06-07 15:44:41