2

I want to display something in an NSOpenGLView, but since there is a total of zero bytes of documentation on it, and the sample code is as big and complex as the documentation should be, I can't get any wise out of it. This is my code so far, and my ANOpenGLView is an NSOpenGLView in a NIB subclassed as ANOpenGLView:

@implementation ANOpenGLView
@synthesize animationTimer;

// MEM
- (void)dealloc {
  [animationTimer release];

  [super dealloc];
}

// INIT
- (id)initWithFrame:(NSRect)frameRect {
  if (self = [super initWithFrame:frameRect]) {
    NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = {
      NSOpenGLPFADoubleBuffer,
      NSOpenGLPFADepthSize, 32,
      0
    };
    NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes];

    [self setOpenGLContext:[[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease]];
  }

  return self;
}

- (void)awakeFromNib {

  /* 60 FPS */
  animationTimer = [[NSTimer timerWithTimeInterval:(1.0f/60.0f) target:self selector:@selector(redraw:) userInfo:nil repeats:YES] retain];
  [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSDefaultRunLoopMode];
}

// DRAW
- (void)redraw:(NSTimer*)theTimer {
  [self drawRect:[self bounds]];
}

- (void)drawRect:(NSRect)dirtyRect {
  NSLog(@"Redraw");

  [[self openGLContext] clearDrawable];
  [[self openGLContext] setView:self];
  [[self openGLContext] makeCurrentContext];
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glDisable(GL_DEPTH_TEST);
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();

  glViewport(0, 0, [self frame].size.width, [self frame].size.height);  
  glMatrixMode(GL_PROJECTION); glLoadIdentity();
  glMatrixMode(GL_MODELVIEW); glLoadIdentity();

  glTranslatef(-1.5f, 0.0f, -6.0f);
  glBegin( GL_TRIANGLES );
  glColor3f(1.0f, 0.0f, 0.0f);
  glVertex2f(0.0f, 1.0f);
  glColor3f(0.0f, 1.0f, 0.0f);
  glVertex2f(-1.0f, -1.0f);
  glColor3f(0.0f, 0.0f, 1.0f);
  glVertex2f(1.0f, -1.0f);
  glEnd();

  [[self openGLContext] flushBuffer];
  [NSOpenGLContext clearCurrentContext];
}

@end

How can I get the triangle to show up? The only thing I get is a blank, white screen.


P.S. I want to draw in 2D.


EDIT I have updated my code, and this is what I have now: screenshot

cacau
  • 3,606
  • 3
  • 21
  • 42
  • In your edit, the picture shows that you are only calling the flush once without calling a glClear(GL_COLOR_BUFFER_BIT) and that is the only time it is called. Because the window (or fullscreen) has covered up that space, the pixels are not updated by the OSX window server causing the artifacts. In good practice, you should never call the drawRect: function yourself. Use the [self setNeedsDisplay: YES] to call drawRect (although I have had issues with setNeedsDisplay in the past). – Chase Walden Jun 02 '12 at 21:31

3 Answers3

1

I'm not sure that it's the only problem, but:

  1. You haven't defined the pixel format
  2. You haven't set up the matrices in the code
  3. You haven't set up the viewport

Here http://www.cocoadev.com/index.pl?NSOpenGLView is a short example, it's almost what you need, but there is perspective matrix set up while you need orthogonal to render in 2D space (function glOrtho). World & View can be identity in this case.

Since 2D is your target, you won't deal with this matrices too much, just set them once.

Gobra
  • 4,263
  • 2
  • 15
  • 20
  • I'm a little farther atm: everything on my screen is screwed up and the menubar is cut in pieces spread over the screen. But hey! It's better than white! =D –  Oct 18 '10 at 12:07
  • 1
    You have set PROJECTION matrix to identity, but it must be glOrtho(0, width, height, 0, 0, 1). I have googled an article about 2D in OpenGL, take a look: http://basic4gl.wikispaces.com/2D+Drawing+in+OpenGL – Gobra Oct 18 '10 at 13:28
1

For one thing, you've requested a double buffered context but you never swap them, so you're probably always drawing into the unseen back buffer. Add a call to glSwapAPPLE() after you flush.

I'm also a bit unsure about all your direct [self openGLContext] calls. Normally NSOpenGLView ought to handle this stuff for you, but in this case you're bypassing the set up of the view by calling drawRect directly from your timer, so things might be a bit messed up.

Have you tried just calling [self setNeedsDisplay:YES] from your timer method and letting the normal view setup occur? I would expect the redrawing still to be fast enough that way and it would make life easier...

walkytalky
  • 9,453
  • 2
  • 36
  • 44
0

Edit: @Peter is right, Still a great resource, just not applicable to this question.

Jeff Lamarche's openGL posts are a great introduction and they include a project template that handles most of the setup for you.

http://iphonedevelopment.blogspot.com/2009/05/opengl-es-from-ground-up-table-of.html

kubi
  • 48,104
  • 19
  • 94
  • 118
  • 2
    That's about OpenGL ES. It has nothing to do with NSOpenGLView and I question how applicable it is to OpenGL non-ES. – Peter Hosey Oct 17 '10 at 20:05