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

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

I'm trying to write a simple OpenGL program that draws a simple line on the screen.

All OpenGL functions are dwelling inside a class named Engine.


class Engine
{
	public:
		~Engine();
		static Engine * GI();

		void Run();
		static void WmPaint();

	private:
		Engine();
		static Engine * m_Instance;

		HANDLE		m_hTimerQueue;
		ULONG_PTR	m_GdiPlusToken;

		static VOID CALLBACK WaitOrTimerCallback(_In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWaitFired);
		static void InitializeOpenGL();
		static void DestroyOpenGL();
};

I used my OpenGL text book to write this program. I don't understand what I wrote with OpenGL functions. I just copied them from my textbook. The OpenGL related class methods are:

Engine::WmPaint() : Called every time the window receives WM_PAINT message.

Engine::InitializeOpenGL() : Does initial operations.

Engine::DestroyOpenGL() : Does some necessary final operations before closing.

The class method definitions are as seen below.


#include "Engine.h"

#include <windows.h>
//#include <gdiplus.h>

#include <GL/GL.h>
#include <GL/GLU.h>
#pragma comment (lib, "opengl32.lib")

#include "Settings.h"
#include "Status.h"

Engine * Engine::m_Instance = 0;

Engine::Engine()
{
	WaitForSingleObject(Status::hEvent_GuiInitialized, INFINITE);
	HANDLE hTimer;
	m_hTimerQueue = CreateTimerQueue();
	BOOL bOk = CreateTimerQueueTimer(	/*_Out_     (PHANDLE)*/			&hTimer,
						/*_In_opt_  (HANDLE)*/			m_hTimerQueue,
						/*_In_      (WAITORTIMERCALLBACK)*/	WaitOrTimerCallback,
						/*_In_opt_  (PVOID)*/			NULL,
						/*_In_      (DWORD)*/			0,
						/*_In_      (DWORD)*/			Settings::RefreshPeriod_ms,
						/*_In_      (ULONG)*/			WT_EXECUTEDEFAULT);
	//Gdiplus::GdiplusStartupInput GdiPlusStartupInput;
	//Gdiplus::GdiplusStartup(&m_GdiPlusToken, &GdiPlusStartupInput, NULL);
	InitializeOpenGL();
}


Engine::~Engine()
{
	DeleteTimerQueue(m_hTimerQueue);
	//Gdiplus::GdiplusShutdown(m_GdiPlusToken);
	DestroyOpenGL();
}

Engine * Engine::GI()
{
	if (m_Instance == 0)
	{
		m_Instance = new Engine();
	}
	return m_Instance;
}

void Engine::Run()
{
	
}

void Engine::WmPaint()
{
	//glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	glColor3ub(255, 128, 80);
	glBegin(GL_POINTS);
	//for (int i=1; i<200; i++)
	//glVertex3i(i, i, 0);
	for (float i=-1.0; i<+1.0; i+=0.001)
	glVertex3f(i, i, 0);
	glEnd();
}

/*void Engine::WmPaint()
{
	static PAINTSTRUCT Ps;
	static HBRUSH hBrush1 = CreateSolidBrush(RGB(50,100,255));
	static HBRUSH hBrush2 = CreateSolidBrush(RGB(255,100,50));
	static Gdiplus::Image img(L"images\\myimage.png");
	static Gdiplus::SolidBrush brBlack(Gdiplus::Color::Black);
	HDC hDc = 0;
	PAINTSTRUCT ps;
	HDC hdc = BeginPaint(Status::hWndGraph, &ps);
		Gdiplus::Graphics g(hdc);
		//g.FillRectangle(&brBlack, 0, 0, Settings::GRAPHAREA_WIDTH, Settings::GRAPHAREA_HEIGHT);
		g.Clear(Gdiplus::Color(0, 0, 0));
		g.DrawImage(&img, Gdiplus::Rect(5, 5, 5 + img.GetWidth(), 5 + img.GetHeight()));
	EndPaint(Status::hWndGraph, &ps);
}*/

VOID CALLBACK Engine::WaitOrTimerCallback(_In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWaitFired)
{
	//RedrawWindow(Gui::GI()->MainWnd.GetGraphHandle(), NULL, NULL, RDW_UPDATENOW);
	//InvalidateRect(Status::hWndGraph, NULL, FALSE);
	//SendMessageW(Status::hWndGraph, WM_PRINT, 0, PRF_CLIENT);
	//UpdateWindow(Status::hWndGraph);
	//MessageBoxW(NULL, L"Timer", L"Timer", NULL);
}

void Engine::InitializeOpenGL()
{
	Status::hDC = GetDC(Status::hWndMain);
	if (Status::hDC == NULL) throw(1);

	PIXELFORMATDESCRIPTOR Pfd;
	ZeroMemory(&Pfd, sizeof(Pfd));
	Pfd.nSize = sizeof(Pfd);
	Pfd.nVersion = 1;
	Pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	Pfd.iPixelType = PFD_TYPE_RGBA;
	Pfd.cColorBits = 24;
	Pfd.cDepthBits = 16;
	Pfd.iLayerType = PFD_MAIN_PLANE;

	int iFormat = ChoosePixelFormat(Status::hDC, &Pfd);
	if (iFormat == 0) throw(2);

	bool bOK = SetPixelFormat(Status::hDC, iFormat, &Pfd);
	if (bOK == FALSE) throw(3);
	
	Status::hGLRC = wglCreateContext(Status::hDC);
	if (Status::hGLRC == NULL) throw(4);

	bool bReturn = wglMakeCurrent(Status::hDC, Status::hGLRC);
	if (bReturn == FALSE) throw(5);

        //std::string version = (char*)glGetString(GL_VERSION); 
        // Outputs: 2.1.0

	///////////////////

	glEnable(GL_DEPTH_TEST);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glViewport(0, 0, Settings::GRAPHAREA_WIDTH, Settings::GRAPHAREA_HEIGHT);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(52.0f, (GLfloat) Settings::GRAPHAREA_WIDTH / (GLfloat) Settings::GRAPHAREA_HEIGHT, 1.0f, 1000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void Engine::DestroyOpenGL()
{
	bool bReturn = wglMakeCurrent(Status::hDC, NULL);
	if (bReturn == FALSE) throw(1);
	bReturn = wglDeleteContext(Status::hGLRC);
	if (bReturn == FALSE) throw(2);
}

I am handling the WM_PAINT message like this:


case WM_PAINT:
	if (hWnd == Status::hWndGraph)		// The graphic area
	{
		Engine::GI()->WmPaint();
		return TRUE;
		//lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
		//return lResult;
	} 
	else if (hWnd == Status::hWndMain)	// The main window
	{
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	else
	{
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	break;

The graphic area is a second window which is embedded (child) inside the main window.

sicEzrX.png

Main Window

Class Styles : CS_HREDRAW | CS_VREDRAW

Window Styles : WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_TABSTOP | WS_GROUP | WS_VISIBLE

Window Ex-Styles : WS_EX_ACCEPTFILES | WS_EX_CONTROLPARENT | WS_EX_LEFT | WS_EX_LTRREADING

Graphic Area

Class Styles : CS_HREDRAW | CS_VREDRAW | CS_OWNDC

Window Styles : WS_CHILD | WS_VISIBLE

Window Ex-Styles : 0

Yesterday, I was able to run GDI+ code in the program structure. The GDI+ code is still there, commented out. Today, I'm trying to run OpenGL code. Whatever I did, I wasn't successful. Can you please find what I'm doing wrong here?

Advertisement
Is Engine::InitializeOpenGL called at all?

Also why is the error handling so horrible? Why do you throw ints instead of std::runtime_errors with an actually readable string?

The first thing I would try is getting a non-black color during glClear (via an appropriate call to glClearColor). The rendering code I see won't be any use. Even if the setup of the projection/model matrices and the other states actually worked like that, you are rendering degenerate triangles which will be either culled completely or likely invisible.

Well, you are rendering points, not triangles. But you are rendering them at z=0 and that's outside of your view frustum unless I missed something else. Since I seem to suffer from a caffeine undersupply this morning that looks decidedly possible. I'd start with trying to get a non-black clear color and then see where things are going.

Is Engine::InitializeOpenGL called at all?

Also why is the error handling so horrible? Why do you throw ints instead of std::runtime_errors with an actually readable string?

Engine::InitializeOpenGL() is called in the constructor.

Some parts may look horrible. This is just a start up project to learn how to use OpenGL.

Your perspective matrix has a znear of 1. Your modelview is identity. Your points are at z=0. They are outside of your view area. Try placing your points at z>=1. z <= -1. (Thanks Brother Bob!)

On another note you should probably invalidate your window somewhere. Windows are only redrawn if necessary. Look up InvalidateRect. To check if this is your culprit, try resizing your window with the mouse and see if something is displayed afterwards.

This checks if your general OpenGL setup is correct:

[quote name='BitMaster' timestamp='1417683122' post='5196204']
The first thing I would try is getting a non-black color during glClear (via an appropriate call to glClearColor).
[/quote

Your perspective matrix has a znear of 1. Your modelview is identity. Your points are at z=0. They are outside of your view area. Try placing your points at z>=1.

The symptom is correct, but it has to be z <= -1, because the Z-axis is pointing out from the screen towards you. It may be confusing, but the clip plane values are the distances along the negative Z-axis, which mean that a near clip plane value of 1 places the near clip plane value at Z = -1.

Your perspective matrix has a znear of 1. Your modelview is identity. Your points are at z=0. They are outside of your view area. Try placing your points at z>=1.

The symptom is correct, but it has to be z <= -1, because the Z-axis is pointing out from the screen towards you. It may be confusing, but the clip plane values are the distances along the negative Z-axis, which mean that a near clip plane value of 1 places the near clip plane value at Z = -1.

Doh, that's rightrolleyes.gif . Fixed.


On another note you should probably invalidate your window somewhere. Windows are only redrawn if necessary. Look up InvalidateRect. To check if this is your culprit, try resizing your window with the mouse and see if something is displayed afterwards.

I enabled that line in the timer function. Now it is called periodically. (I had it disabled, because GDI+ was running alright without it.)


VOID CALLBACK Engine::WaitOrTimerCallback(_In_ PVOID lpParameter, _In_ BOOLEAN TimerOrWaitFired)
{
	//RedrawWindow(Gui::GI()->MainWnd.GetGraphHandle(), NULL, NULL, RDW_UPDATENOW);
	InvalidateRect(Status::hWndGraph, NULL, FALSE);
	//SendMessageW(Status::hWndGraph, WM_PRINT, 0, PRF_CLIENT);
	//UpdateWindow(Status::hWndGraph);
	//MessageBoxW(NULL, L"Timer", L"Timer", NULL);
}


Your perspective matrix has a znear of 1. Your modelview is identity. Your points are at z=0. They are outside of your view area. Try placing your points at z <= -1.

I hope, I did it correctly:


// Previous:
gluPerspective(52.0f, (GLfloat) Settings::GRAPHAREA_WIDTH / (GLfloat) Settings::GRAPHAREA_HEIGHT, 1.0f, 1000.0f);

// Now:
gluPerspective(52.0f, (GLfloat) Settings::GRAPHAREA_WIDTH / (GLfloat) Settings::GRAPHAREA_HEIGHT, -2.0f, 5.0f);


I'd start with trying to get a non-black clear color and then see where things are going.

I changed the arguments of glClearColor() in the initialization method.


// Previous:
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

// Now:
glClearColor(0.0f, 0.5f, 0.5f, 0.0f);

Result:

Nothing changed. Nothing.


Your perspective matrix has a znear of 1. Your modelview is identity. Your points are at z=0. They are outside of your view area. Try placing your points at z <= -1.

I hope, I did it correctly:


// Previous:
gluPerspective(52.0f, (GLfloat) Settings::GRAPHAREA_WIDTH / (GLfloat) Settings::GRAPHAREA_HEIGHT, 1.0f, 1000.0f);

// Now:
gluPerspective(52.0f, (GLfloat) Settings::GRAPHAREA_WIDTH / (GLfloat) Settings::GRAPHAREA_HEIGHT, -2.0f, 5.0f);

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.


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'm sorry, I don't understand what you are saying. I'm a total newbie and this is my hello world project in OpenGL. Can you please tell me what do I have to do exactly by adding some sample code?

The call to gluPerspective in your first post was fine. What you need to change is the actual coordinates you pass to glVertex. The last parameter is the Z-coordinarte, which you set to zero in your first post. Set the Z-coordinate to something else, for example:


glVertex3f(i, i, -2);

instead of


glVertex3f(i, i, 0);

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.

This topic is closed to new replies.

Advertisement