My "Hello World" OpenGL application doesn't display anything

Started by
17 comments, last by Avilius 9 years, 4 months ago


You did not. The clip plane distances have to be positive. You have to change the coordinates of your vertices, either by setting the Z-coordinates directly or indirectly by translating the model view matrix.

I have been investigating the issue. I learned that glPerspective() has an alternative called glOrtho(), and it is more suitable for 2D projection. I think I also learned how to use it. Please correct me if I'm wrong in any part. We first change current matrix by glMatrixMode(GL_PROJECTION). Now we can load a projection matrix to take a projection of the 3D world on the the 2D screen. There are infinitely many projection matrix alternatives, but (as far as I know) two of them are standard alternatives. One is "perspective" projection, the other is "orthogonal". We take the perspective projection by calling the glPerspective() function. While we take orthogonal projection by calling the glOrtho() function. When we load a new projection matrix, it is multiplied by the current one. So we reset it first by loading identity matrix to it by calling glLoadIdentity().

A proper projection matrix initialization may be like this:


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(/*GLdouble left*/	-2.0,
        /*GLdouble right*/	+2.0,
        /*GLdouble bottom*/	-2.0,
        /*GLdouble top*/	+2.0,
        /*GLdouble zNear*/	-2.0,
        /*GLdouble zFar*/	+2.0);
//gluPerspective(52.0f, (GLfloat) Settings::GRAPHAREA_WIDTH / (GLfloat) Settings::GRAPHAREA_HEIGHT, -2.0f, 5.0f);

With an initialization like this, any object withing the cube [(-2,+2),(-2,+2),(-2,+2)] will be orthogonally projected to the x-y plane at z=-2.

Am I correct? I don't think so. Because I still don't see anything on my screen. I'm waiting for someone to counter-prove me by correcting my mistakes in my explanation.

I changed the z-dimension component of my vertexes as seen below.


void Engine::WmPaint()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glColor3ub(255, 128, 80);
	glBegin(GL_POINTS);
	for (float i=-1.0; i<+1.0; i+=0.001) glVertex3f(i, +i, -0.5f);
	for (float i=-1.0; i<+1.0; i+=0.001) glVertex3f(i, -i, +0.5f);
	glEnd();
}
Advertisement

But even if this is a problem, your object probably won't show up anyway. You said that changing the clear color didn't work either, so there are other more fundamental problems as well.


As I already said, and Brother Bob just reinforced again, talking about vertex positions is useless if you cannot even get a different clear color working.

I think glClearColor is doing nothing because you only call it in InitializeOpenGL() (you probably intended to clear the background every redraw correct?).

You are also forgetting to flush the buffer in your Engine::WmPaint()

SwapBuffers() is the OpenGL function that takes the backbuffer and draws it to the screen. OpenGL is double buffered so if you never swap with the backbuffer then what you draw remains hidden.

I think glClearColor is doing nothing because you only call it in InitializeOpenGL() (you probably intended to clear the background every redraw correct?).


glClearColor sets the color to which the color buffer is cleared during a call to glClear. So calling it once during initialization would be enough.

You are also forgetting to flush the buffer in your Engine::WmPaint()

SwapBuffers() is the OpenGL function that takes the backbuffer and draws it to the screen. OpenGL is double buffered so if you never swap with the backbuffer then what you draw remains hidden.

OF COURSE!! That damn SwapBuffers()! I knew something was missing.

5k6dMFK.png


void Engine::WmPaint()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glColor3ub(255, 128, 80);
	glBegin(GL_POINTS);
	for (float i=-1.0; i<+1.0; i+=0.001) glVertex3f(i, -i, -0.5f);
	for (float i=-1.0; i<+1.0; i+=0.001) glVertex3f(i, +i, +0.5f);
	for (float i=-1.0; i<+1.0; i+=0.001) glVertex3f(i, -0.5 * i, -2.0f);
	for (float i=-1.0; i<+1.0; i+=0.001) glVertex3f(i, +0.5 * i, +2.0f);
	glEnd();
	SwapBuffers(Status::hDC);
}

Now it works alright. Thank you everybody for sharing your time with me.

Is there any reason why you put your opengl rendering code in your WM_PAINT handling code?

This is perfectly legit for a window that is only redrawn rarely (like when its resized or stuff) and not applicable for any sort or real time rendering.

For games you'd put a call to your rendering code inside of the infinite loop that has your win32 message pump code.

Most games try to pump out as many frames as possible but you can reduce CPU usage by doing something like Sleep( 3 ).

Its perfectly legal in win32-land to render to your window outside of a WM_PAINT event (in fact, other processes can even render to your window! ).

I'm going to write a 2D platform game which won't have a lot of animation. I'm going to refresh the screen with a Win32 API timer. I'm not going to throttle the system resources like most other games do; I personally hate it.

I'm going to write a 2D platform game which won't have a lot of animation. I'm going to refresh the screen with a Win32 API timer. I'm not going to throttle the system resources like most other games do; I personally hate it.


"Animation" here also means "moving objects." A platformer game most certainly needs smoothly moving objects. Think of when the player jumps and then falls; you want that to be displayed without the user having to hit a key to get each next frame.

In general, though, I'd steer you well away from even using the Win32 API in the first place. SDL2 (and similar libraries like GLFW or SFML) do everything you need, do it easier and simpler and with fewer error cases, and are portable. Even bigger game engines have in many cases migrated to SDL2 or its ilk. You should never have to write any raw Win32 window management or WGL code unless you're doing some very special and intrinsically Windows-specific. You should rarely have to write any Win32 anything outside of some rare high-performance IO/networking/threading code (and even then, there's high-quality, simpler, easier, portable libraries like asio, tbb, and so on to prefer over the Win32 versions).

Sean Middleditch – Game Systems Engineer – Join my team!

In general, though, I'd steer you well away from even using the Win32 API in the first place. SDL2 (and similar libraries like GLFW or SFML) do everything you need, do it easier and simpler and with fewer error cases, and are portable. Even bigger game engines have in many cases migrated to SDL2 or its ilk. You should never have to write any raw Win32 window management or WGL code unless you're doing some very special and intrinsically Windows-specific. You should rarely have to write any Win32 anything outside of some rare high-performance IO/networking/threading code (and even then, there's high-quality, simpler, easier, portable libraries like asio, tbb, and so on to prefer over the Win32 versions).

Well, pretty much only hobbyist engines and a few commercial engines like Source internally use SDL2 for window management AFAIK (and it's not uncommon for a few to only use SDL2 for it's Mac OSX and Linux ports). You shouldn't tell someone to shy away from Win32 just because you don't like it. It's fine to use, and if anything you'll get experience out of the endeavor.

This topic is closed to new replies.

Advertisement