OpenGL doesn't appear to be rendering

Started by
10 comments, last by thecoderlife 16 years, 3 months ago
I'm following a book called "OpenGL Game Development", and I'm up to the 2.1 example at the end of Chapter 2, but when I run it, nothing renders. I downloaded the source code that comes with the book from www.wordware.com/files/openglgd, and replaced my source code with the book's, but I still get the same problem. Yet when I run the .exe that comes with the code, I see exactly what it should be rendering, rendered! Here's what the source code-packaged .exe gets: http://img137.imageshack.us/img137/5618/mapeditorgoodyu2.jpg Here's what my code gets, and what I get when I replace my code with the book's code: http://img167.imageshack.us/img167/9890/mapeditorbaddx6.jpg I think it's possible he compiled the .exe with different code than what's in the book, per se, since the background color I have in my static window is different from the one in his. You can find the book's code at the link I posted, so I'll just put my code here:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")

#include <string>
#include <sstream>
#include "resource.h"
#include "RASTER.h"

const int DEFAULT_BUTTON_WIDTH = 100;
const int DEFAULT_BUTTON_HEIGHT = 20;

HINSTANCE GlobalInstance;
HMENU Menu;
HMENU PopupMenu;
HWND Window;
HWND RenderWindow;
HWND bCreateWall;

RASTER raster;

void ResizeGLWindow(long width, long height)
{
	glViewport(0, 0, (GLsizei)width, (GLsizei)height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-200, 200, -200, 200, -2000, 2000);
	glMatrixMode(GL_MODELVIEW);
}

void SetGLDefaults()
{
	glEnable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
}

void Render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.6f, 0.6f, 0.6f, 1.0f);

	glLoadIdentity();
	glPushMatrix();

	glBegin(GL_TRIANGLES);
		glVertex3f(0.0f, 0.0f, 0.0f);
		glVertex3f(0.0f, 1.0f, 0.0f);
		glVertex3f(1.0f, 0.0f, 0.0f);
	glEnd();

	glBegin(GL_QUADS);
		glVertex3f(0.05f, -0.05f, 0.0f);
		glVertex3f(0.95f, -0.05f, 0.0f);
		glVertex3f(0.95f, -0.95f, 0.0f);
		glVertex3f(0.05f, -0.95f, 0.0f);
	glEnd();

	glBegin(GL_POLYGON);
		glVertex3f(-0.250f, -0.250f, 0.0f);
		glVertex3f(-0.500f, -0.125f, 0.0f);
		glVertex3f(-0.750f, -0.250f, 0.0f);
		glVertex3f(-0.875f, -0.500f, 0.0f);
		glVertex3f(-0.750f, -0.750f, 0.0f);
		glVertex3f(-0.500f, -0.875f, 0.0f);
		glVertex3f(-0.250f, -0.750f, 0.0f);
		glVertex3f(-0.125f, -0.500f, 0.0f);
	glEnd();

	glBegin(GL_LINES);
		glVertex3f(-0.25f, 0.25f, 0.0f);
		glVertex3f(-0.75f, 0.75f, 0.0f);
	glEnd();

	glPopMatrix();
	SwapBuffers(raster.hDC);
}

LRESULT CALLBACK MapDetailsDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
		case WM_INITDIALOG:
			SetDlgItemText(hWnd, IDC_MAP_DETAILS_NAME, "Map Name");
			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_RESETCONTENT, 0, 0);
			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING, 0, LPARAM("Exit"));
			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_ADDSTRING, 0, LPARAM("Get Killed"));
			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_SETCURSEL, 0, 1);

			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_RESETCONTENT, 0, 0);
			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_ADDSTRING, 0, LPARAM("Single Player"));
			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_ADDSTRING, 0, LPARAM("Multi Player"));
			SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_SETCURSEL, 0, 1);
			break;
		case WM_COMMAND:
			if (wParam == IDOK)
			{
				long level_rule = (long)SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_RULES, LB_GETCURSEL, 0, 0);
				long level_type = (long)SendDlgItemMessage(hWnd, IDC_MAP_DETAILS_LEVEL_TYPE, CB_GETCURSEL, 0, 0);

				std::string temp = "Level Type: ";
				std::stringstream strstream;

				strstream << level_type << "\n";
				temp += strstream.str();
				strstream.str("");
				strstream << "Level Rule: " << level_rule;
				temp += strstream.str();

				MessageBox(hWnd, temp.c_str(), "OK", MB_OK);
				EndDialog(hWnd, 0);
			}
			else if (wParam == IDCANCEL)
				EndDialog(hWnd, 0);
			break;
	}

	return 0;
}

void DisplayPopupMenu(long x, long y)
{
	RECT windowLocation;
	GetWindowRect(Window, &windowLocation);

	HMENU temp = GetSubMenu(PopupMenu, 0);
	TrackPopupMenu(temp, TPM_LEFTALIGN | TPM_RIGHTBUTTON, windowLocation.left + x + 8, windowLocation.top + y + 48, 0, Window, 0);
}

void WMCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	if (lParam == (LPARAM)bCreateWall)
		MessageBox(Window, "You Pressed bCreateWall!", "Congrats!", MB_OK);
	else if (wParam == ID_FILE_EXIT)
		PostQuitMessage(0);
	else if (wParam == ID_MAP_DETAILS)
		DialogBox(GlobalInstance, MAKEINTRESOURCE(IDD_MAP_DETAILS), 0, DLGPROC(MapDetailsDlgProc));
	else if (wParam == ID_DRAWING_WIREFRAME)
	{
		CheckMenuItem(Menu, ID_DRAWING_WIREFRAME, MF_CHECKED);
		CheckMenuItem(Menu, ID_DRAWING_SOLID, MF_UNCHECKED);
	}
	else if (wParam == ID_DRAWING_SOLID)
	{
		CheckMenuItem(Menu, ID_DRAWING_WIREFRAME, MF_UNCHECKED);
		CheckMenuItem(Menu, ID_DRAWING_SOLID, MF_CHECKED);
	}
	else if (wParam == ID_POP_MOVE)
		MessageBox(Window, "Move", "Click", MB_OK);
	else if (wParam == ID_POP_DELETE)
		MessageBox(Window, "Delete", "Click", MB_OK);
	else if (wParam == ID_POP_TEXTURE)
		MessageBox(Window, "Texture", "Click", MB_OK);
	else if (wParam == ID_POP_DUPLICATE)
		MessageBox(Window, "Duplicate", "Click", MB_OK);
}

void WMSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	RECT rect;

	GetClientRect(Window, &rect);
	MoveWindow(RenderWindow, DEFAULT_BUTTON_WIDTH, 0, rect.right-rect.left-DEFAULT_BUTTON_WIDTH, rect.bottom-rect.top, true);

	GetClientRect(RenderWindow, &rect);
	ResizeGLWindow(rect.right - rect.left, rect.bottom - rect.top);
}

LRESULT CALLBACK WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_COMMAND:
			WMCommand(hWnd, msg, wParam, lParam);
			break;
		case WM_SIZE:
			WMSize(hWnd, msg, wParam, lParam);
			break;
		case WM_RBUTTONUP:
			DisplayPopupMenu(LOWORD(lParam), HIWORD(lParam));
			break;
	}
	
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nShowCmd)
{
	GlobalInstance = hInstance;

	WNDCLASS wc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "ME";
	wc.lpszMenuName = 0;
	wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;

	if (!RegisterClass(&wc))
	{
		MessageBox(0, "Error: Cannot Register Class", "ERROR!", MB_OK);
		return 1;
	}

	Window = CreateWindow("ME", "Map Editor", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, 0);

	if (!Window)
	{
		MessageBox(0, "Error: Failed to Create Window", "ERROR!", MB_OK);
		return 1;
	}

	RECT rect;
	GetClientRect(Window, &rect);

	RenderWindow = CreateWindow("STATIC", 0, WS_CHILD | WS_VISIBLE | WS_BORDER, DEFAULT_BUTTON_WIDTH, 0, rect.right - rect.left - DEFAULT_BUTTON_WIDTH, rect.bottom - rect.top - 20, Window, 0, hInstance, 0);
	if (!RenderWindow)
	{
		MessageBox(0, "Error: Failed to Create RenderWindow", "ERROR!", MB_OK);
		return 1;
	}

	bCreateWall = CreateWindow("BUTTON", "Create Wall", WS_CHILD | WS_VISIBLE, 0, 100, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT, Window, 0, hInstance, 0);

	if (!bCreateWall)
	{
		MessageBox(0, "Error: Failed to Create bCreateWall", "ERROR!", MB_OK);
		return 1;
	}

	Menu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
	SetMenu(Window, Menu);

	PopupMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_POPUP_MENU));

	if (!raster.Init(RenderWindow))
		return 1;

	GetClientRect(RenderWindow, &rect);
	ResizeGLWindow(rect.right - rect.left, rect.bottom - rect.top);

	MSG msg;

	while (true)
	{
		Render();
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
				break;

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	raster.Release(RenderWindow);

	return 0;
}

Here's RASTER.h (and RASTER.cpp):

//RASTER.h

#pragma once
#include <windows.h>

class RASTER
{
	public:
		HDC hDC;
		HGLRC glrc;

		RASTER();
		~RASTER();

		bool Init(HWND hWnd, unsigned char color_bits = 24, unsigned char depth_bits = 32);
		bool Release(HWND hWnd);
};

//--
// RASTER.cpp
//--

#include "RASTER.h"

RASTER::RASTER()
{}

RASTER::~RASTER()
{}

bool RASTER::Init(HWND hWnd, unsigned char color_bits, unsigned char depth_bits)
{
	HDC hDC = GetDC(hWnd);

	if (!hDC)
	{
		MessageBox(hWnd, "Error: Can't Get Device Context for Window", "ERROR", MB_OK | MB_ICONERROR);
		return false;
	}

	PIXELFORMATDESCRIPTOR pfd;

	memset(&pfd, 0, sizeof(pfd));
	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	pfd.cColorBits = color_bits;
	pfd.cDepthBits = depth_bits;

	int PixelFormat = ChoosePixelFormat(hDC, &pfd);

	if (!PixelFormat)
	{
		MessageBox(hWnd, "Error: Can't Choose Pixel Format", "ERROR", MB_OK | MB_ICONERROR);
		ReleaseDC(hWnd, hDC);
		hDC = 0;

		return false;
	}

	if (!SetPixelFormat(hDC, PixelFormat, &pfd))
	{
		MessageBox(hWnd, "Error: Can't Set The Pixel Format", "ERROR", MB_OK | MB_ICONERROR);
		ReleaseDC(hWnd, hDC);
		hDC = 0;

		return false;
	}

	HGLRC glrc = wglCreateContext(hDC);
	if (!glrc)
	{
		MessageBox(hWnd, "Error: Can't Create GL Context", "ERROR", MB_OK | MB_ICONERROR);
		ReleaseDC(hWnd, hDC);
		hDC = 0;

		return false;
	}

	if (!wglMakeCurrent(hDC, glrc))
	{
		MessageBox(hWnd, "Error: Can't Make Current GL Context", "ERROR", MB_OK | MB_ICONERROR);
		wglDeleteContext(glrc);
		ReleaseDC(hWnd, hDC);
		glrc = 0;
		hDC = 0;

		return false;
	}

	return true;
}

bool RASTER::Release(HWND hWnd)
{
	if (!hDC || !glrc)
		return false;

	if (!wglMakeCurrent(0, 0))
	{
		MessageBox(hWnd, "Error: Release of DC and RC Failed", "Release Error", MB_OK | MB_ICONERROR);
		return false;
	}

	if (!wglDeleteContext(glrc))
	{
		MessageBox(hWnd, "Error: Release of Rendering Context Failed", "Release Error", MB_OK | MB_ICONERROR);
		return false;
	}
	glrc = 0;

	if (!ReleaseDC(hWnd, hDC))
	{
		MessageBox(hWnd, "Error: Release of Device Context Failed", "Release Error", MB_OK | MB_ICONERROR);
		return false;
	}
	hDC = 0;

	return true;
}

Advertisement
You've posted quite a bit of code so I'm not sure where the problem is, but one thing kinda stood out:

In Render(), you call glPushMatrix() (and later glPopMatrix()), but you don't apply any transformations between those calls, so why are you calling those functions?

Also, You're not specifying any camera parameters. Try placing this call before the call to glPushMatrix() (but after glLoadIdentity()):

gluLookAt(0, 0, 5,    // Camera position          0, 0, 0,    // Camera target          0, 1, 0);   // Camera's up-vector
Like I said, I wrote this code directly off of the book, so if you see something weird, chances are it's the book's coding, not mine.

The book had a glRotatef(0.0f, 0.0f, 0.0f); in there, but I removed it. Including it doesn't help any, though.

Adding the gluLookAt call doesn't do anything either. This is really odd..
Seems like your issues is in the RASTER::Init

Change the line that reads

HDC hDC = GetDC(hWnd);

to

hDC = GetDC(hWnd);

You redeclared the class member then later attempted to use it in SwampBuffers but it was NULL! (Because the class member was never actually set, instead the new declaration that was made in RASTER::Init was set.)
Oh! That makes a lot of sense, I was thinking maybe the problem wasn't in the source (since obviously, his code worked in the .exe).

But it's still not working... I fixed the same problem with the HGLRC in the function too, and no luck.
That's strange. Good catch on the glrc. I fixed it on my copy as well, I changed the clear color to pink and it worked. Have you tried this on your end?
If I change the clear color to black, I see a sort of "large pixel" in the center of the window, made of four pixels shaped as a square. Hmm. At least it's rendering.
Ah! That's funny, when I reduce the parameters in glOrtho, I can see the four shapes, but they're "off in the distance". They were being rendered 2000 units away from the screen, no wonder they were just a "large pixel" before. (You see the glOrtho is at -2000, 2000?)

Is there something with my code that I did wrong to have to do this instead? I did exactly what the book said for the glOrtho function.
Sorry for the now-TRIPLE post...

Apparently it's just the left/right and top/bottom parameters that were the problem - the near/far had nothing to do with it. Yet the problem is still that I followed the book's glOrtho parameters and still got that small dot.
Yea you're right! I tried the same thing over here and I got the same results. Very strange, not sure why the book had those parameters set up.

This topic is closed to new replies.

Advertisement