glOrtho and a black screen

Moderator
Posts: 508
Joined: 2002.09
Post: #1
So, I'm starting to get the hang of programming in OpenGL and so far I'm very pleased with the results. However, I can't get glOrtho to work. When I use it I get a black screen, no graphics, no nothing.

Using gluPerspective does work.

here's some of my initialization code, perhaps there's something missing in there. I'm using Cocoa and so all the code you see here belongs in a subclass of NSOpenGLView

Code:
- (id)initWithCoder:(NSCoder*)coder {
    self = [super initWithCoder:coder];
    
    NSOpenGLPixelFormatAttribute attrs[] = {
        //NSOpenGLPFAFullScreen,
        NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
        NSOpenGLPFAColorSize, 24,
        NSOpenGLPFADepthSize, 16,
        NSOpenGLPFADoubleBuffer,
        NSOpenGLPFAAccelerated,
        0
    };
    
    NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
    [self setPixelFormat:pixelFormat];
    [pixelFormat release];
    pixelFormat = nil;
    
    [[self openGLContext] makeCurrentContext];
    
    [self initOpenGL];
    [self initObjects];
    
    refreshTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(refreshView:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:refreshTimer forMode:NSEventTrackingRunLoopMode];
    [[NSRunLoop currentRunLoop] addTimer:refreshTimer forMode:NSModalPanelRunLoopMode];
    
    return self;
}

- (void)initOpenGL {
    glShadeModel(GL_SMOOTH);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
    
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_COLOR_MATERIAL);
}

- (void)reshape {
    float ratio;
    NSSize bounds = [self bounds].size;
    ratio = bounds.width / bounds.height;
    
    glViewport(0, 0, [self frame].size.width, [self frame].size.height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    glOrtho(0.0f, [self frame].size.width, [self frame].size.height, 0.0f, -100.0f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

my camera is set at z = -5.0f, x and y are 0.0f

replacing glOrtho with gluPerspective(45.0, ratio, 0.1f, 100.0f); does show me my graphics.

Thanks in advance!

"When you dream, there are no rules..."
Quote this message in a reply
Vertizor
Unregistered
 
Post: #2
Lets look at the glOrtho() function:

void glOrtho(
GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble zNear,
GLdouble zFar
);

Parameters

left, right
The coordinates for the left-and right-vertical clipping planes.
bottom, top
The coordinates for the bottom- and top-horizontal clipping planes.
zNear, zFar
The distances to the nearer and farther depth clipping planes. These distances are negative if the plane is to be behind the viewer.


What you did was:

glOrtho(0.0f, [self frame].size.width, [self frame].size.height, 0.0f, -100.0f, 100.0f);

The coordinates have to be in OpenGL space, so it has nothing to do with the size of the rectangle of the actualy NSOpenGLView widget. So you can't use the *.size.width and *.size.height.

For example, if you drew a square that looks like:

top-left: -1.0x, 1.0y
top-right: 1.0x, 1.0y
bottom-left: -1.0x, -1.0y
bottom-right: 1.0x, -1.0y

then the left/right arguments of glOtho() have to be at least -1.0 and 1.0 in order to properly see your square. Decreasing the left value and increasing the right value relatively will sort of "zoom" in and out so you can see more/less of your scene.

So to recap, once you set the glMatrixMode(GL_PROJECTION), and then call glLoadIdentity(), the coordinate 0x,0y will be in the center of your view. glOrtho() will be used to set the view frustrum (clipping plane) relative to that 0x,0y origin.

glOrtho(-5.0f, 5.0f, -5.0f, 5.0f, -100.0f, 100.0f);

In the above example, anything that you draw within that 10x10 area (-5 to +5 is 10 units) will be visible.
Quote this message in a reply
Moderator
Posts: 508
Joined: 2002.09
Post: #3
After calling glOrtho() do I need to set glMatrixMode(GL_MODELVIEW); and glLoadIdentity(); ?

and when starting the rendering process, do I also call glLoadIdentity like I do with gluPerspective?

"When you dream, there are no rules..."
Quote this message in a reply
Vertizor
Unregistered
 
Post: #4
When use glMatrixMode(), subsequent calls to glRotate and glTranslate will affect that particular matrix. So when you call glMatrixMode(GL_PROJECTION), all your rotation and translation calls will affect the way the scene is projected. On the flip side, glMatrixMode(GL_MODELVIEW) and all your translate/rotate calls affect the way primatives etc. are drawn.

So to answer your question, first it's glMatrixMode(GL_PROJECTION) then glOrtho() and whatever other operation you need on the projection. Then before you begin actually drawing your scene and geometry, you'd call glMatrixMode(GL_MODELVIEW) so that the OpenGL subsystem will apply translation/rotation on the content and not the projection. Calling glLoadIdentity() after setting the current matrix to GL_MODELVIEW basically resets the "pen" to the 0x, 0y, 0z origin.

Think of it as a pen, your drawing tool. glLoadIdentity puts the pen at the origin on the canvas. When you make calls such as glBegin(GL_QUADS) and then send all your vetex data, those vertex coordinates are relative to this imaginary pen. To draw two boxes and make them look like they're next to each other: both boxes can have the same exact vertex coordinates. But before you draw the second box, you move your "pen" over a certain distance (using glTranslate) and then begin drawing the polygons using the same exact vertex coords.
Quote this message in a reply
Vertizor
Unregistered
 
Post: #5
Taxxodium Wrote:After calling glOrtho() do I need to set glMatrixMode(GL_MODELVIEW); and glLoadIdentity(); ?

and when starting the rendering process, do I also call glLoadIdentity like I do with gluPerspective?
I should probably answer this more specifically instead of throwing the Red Book (ha ha) at you with my long and boring explanation.

So you looked at some example code, and in the reshape: method they call glOrtho() and then at the end they call glMatrixMode(GL_MODELVIEW). The reason for this is, the only time you need to change the matrix mode is when you adjust the projection of the scene. So basically whenever you go from perspective to ortho, or when the physical dimensions of the viewport has changed. If you recall from my above post, after you set the current matrix mode, all glTranslate and glRotate calls will affect that matrix. So in the reshape: method you've changed the current matrix mode in order to adjust the projection. Return it to GL_MODELVIEW mode so that when the scene gets updated and rendered, all your translation and rotation calls will affect the scene content (primatives, lights, etc.) as it should.

Calling glLoadIdentity at the beginning of your rendering process is a good idea because, like I said in my "pen" analogy, whenever you use glTranslate and glRotate, the "pen" stays there. Suppose you wanted to draw objects that have depth in the Z axis, you want them to look like they're in line one after another, not all bunched up together in one space. You could adjust all the vertex coordinates so that they match the world coordinates but that would be a lot of work and not necessary. Just move the "pen" in world coordinates and you can draw objects in their local coordinate space.

If you've worked with 3D modeling apps before, you'll see a differentiation between world coordinate space, and model coordinate space. World coords mean the XYZ coords in relation to the entire scene. Model coords is relative to all the components of the model. So if your model consists of many polygons, each vertex has XYZ coords that are relative to each other. Suppose there are 2 vertices, one has an X coord of -1.0, the other's X coord is 1.0. If they're drawn starting with the world coord of 0,0 then the vertex with the -1.0x coord will be on the left side of the screen, the other on the right. If you use glTranslate to move the "pen" over to the right, then draw both vertices (without changing their vertex coords) they will both appear to be on the right side of the screen.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Discrad black parts in texture bonanza 7 5,671 Oct 27, 2011 01:05 AM
Last Post: bonanza
  OpenGL full screen mode leaves garbage on screen when exiting app Malarkey 5 5,192 Nov 19, 2008 12:51 PM
Last Post: Malarkey
  Fade Particle to black bonanza 8 5,329 Apr 3, 2008 05:24 AM
Last Post: bonanza
  HELP!!! Simple glOrtho problem! Marvin 3 3,953 Jun 27, 2007 10:23 AM
Last Post: Marvin
  OpenGL Texture in relation to GL orientation, and... glOrtho help. Jones 6 4,957 Jun 30, 2006 07:18 PM
Last Post: arekkusu