OpenGL编程指南第版本学习笔记 --- OpenGL程序实现过程(win32 + OpenGL)


1. 先上代码

头文件glCommon.h

#include <GL/glew.h>
#include <GL/GL.h>
#include <GL/GLU.h>

#define MAX_LEN 2048

void GLLog(const char *pszFormat, ...);
void SetupPixelFomat( HWND hWnd, HDC &hDC );
bool InitGL(HDC hDC, HGLRC &hRC);
void DestroyGL(HDC hDC, HGLRC hRC);

源文件

#include <stdio.h>
#include "glCommon.h"


void SetupPixelFomat( HWND hWnd, HDC &hDC )
{
	hDC = GetDC(hWnd);
	
	PIXELFORMATDESCRIPTOR pfd =
	{
		sizeof(PIXELFORMATDESCRIPTOR),  // size
		1,                          // version
		PFD_SUPPORT_OPENGL |        // OpenGL window
		PFD_DRAW_TO_WINDOW |        // render to window
		PFD_DOUBLEBUFFER,           // support double-buffering
		PFD_TYPE_RGBA,              // color type
		32,                         // preferred color depth
		0, 0, 0, 0, 0, 0,           // color bits (ignored)
		0,                          // no alpha buffer
		0,                          // alpha bits (ignored)
		0,                          // no accumulation buffer
		0, 0, 0, 0,                 // accum bits (ignored)
		24,                         // depth buffer
		8,                          // no stencil buffer
		0,                          // no auxiliary buffers
		PFD_MAIN_PLANE,             // main layer
		0,                          // reserved
		0, 0, 0,                    // no layer, visible, damage masks
	};
	
	int pixelFormat = ChoosePixelFormat(hDC, &pfd);
    SetPixelFormat(hDC, pixelFormat, &pfd);
}

bool InitGL( HDC hDC, HGLRC &hRC )
{
	hRC = wglCreateContext(hDC);
	wglMakeCurrent(hDC, hRC);

	const GLubyte *glVersion = glGetString(GL_VERSION);
	GLLog("OpenGL version = %s", glVersion);

	if (atof((const char *)glVersion) < 1.5)
	{
		char strComplain[256] = {0};
		sprintf_s(strComplain, 256,"OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card.",
			glVersion);
		MessageBox(NULL,(LPCWSTR)strComplain, _T("OpenGL version too old"),MB_OK);
		return false;
	}

	GLenum GlewInitResult = glewInit();
	if (GLEW_OK != GlewInitResult)
	{
		MessageBox(NULL,(LPCWSTR)glewGetErrorString(GlewInitResult), _T("OpenGL version too old"),MB_OK);
		return false;
	}
	
	return true;
}

void GLLog( const char *pszFormat, ... )
{
	char szBuf[MAX_LEN];

	va_list ap;
	va_start(ap, pszFormat);
	vsnprintf_s(szBuf, MAX_LEN, MAX_LEN, pszFormat, ap);
	va_end(ap);

	WCHAR wszBuf[MAX_LEN] = {0};
	MultiByteToWideChar(CP_UTF8, 0, szBuf, -1, wszBuf, sizeof(wszBuf));
	OutputDebugStringW(wszBuf);
	OutputDebugStringA("\n");

	WideCharToMultiByte(CP_ACP, 0, wszBuf, sizeof(wszBuf), szBuf, sizeof(szBuf), NULL, FALSE);
	printf("%s\n", szBuf);
}

void DestroyGL( HDC hDC, HGLRC hRC )
{
	if (hDC != NULL && hRC != NULL)
	{
		wglMakeCurrent(hDC, NULL);
		wglDeleteContext(hRC);
	}
}

#include "glCommon.h"


HACCEL g_hAccelTable = NULL;
HGLRC g_hRC;
HDC g_hDC;

static GLuint VAOs[1];
static GLuint Buffers[1];

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void DrawScene();
void SceneInit();
void ReSizeScene(int w, int h);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	bool bRet = false;
	static TCHAR szAppName[] = TEXT ("triangles");
	HWND         hwnd;
	MSG          msg;
	WNDCLASSEX   wndclassex = {0};
	wndclassex.cbSize        = sizeof(WNDCLASSEX);
	wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
	wndclassex.lpfnWndProc   = WndProc;
	wndclassex.cbClsExtra    = 0;
	wndclassex.cbWndExtra    = 0;
	wndclassex.hInstance     = hInstance;
	wndclassex.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
	wndclassex.hCursor       = LoadCursor (NULL, IDC_ARROW);
	wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
	wndclassex.lpszMenuName  = NULL;
	wndclassex.lpszClassName = szAppName;
	wndclassex.hIconSm       = wndclassex.hIcon;

	if (!RegisterClassEx (&wndclassex))
	{
		MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
		return 0;
	}
	hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, 
		szAppName, 
		TEXT ("WindowTitle"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 
		CW_USEDEFAULT, 
		500, 
		500, 
		NULL, 
		NULL, 
		hInstance,
		NULL); 
	
	SetupPixelFomat(hwnd, g_hDC);
	bRet = InitGL(g_hDC, g_hRC);
	if(!bRet)
		DestroyGL(g_hDC, g_hRC);
	ShowWindow (hwnd, iCmdShow);

	SceneInit();

	while (true)
	{
		if(!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE ))
		{
			DrawScene();
			
			::SwapBuffers(g_hDC);
			continue;
		}

		if (msg.message == WM_QUIT)
			break;
		
		// Deal with windows message.
		if (! g_hAccelTable || ! TranslateAccelerator(msg.hwnd, g_hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	switch (message)
	{
	case WM_CREATE:
		return (0);

	case WM_PAINT:
		hdc = BeginPaint (hwnd, &ps);
		EndPaint (hwnd, &ps);
		return (0);
	case WM_SIZE:
		{
			int w = LOWORD(wParam);
			int h = HIWORD(wParam);
			//ReSizeScene(w, h);
		}
		return (0);
	case WM_DESTROY:
		DestroyGL(g_hDC, g_hRC);
		ReleaseDC(hwnd,g_hDC);
		PostQuitMessage (0);
		return (0);
	case WM_CLOSE:
		PostQuitMessage(0);
		return (0);
	}
	return DefWindowProc (hwnd, message, wParam, lParam);
}

void DrawScene()
{
	glClear(GL_COLOR_BUFFER_BIT);

	glBindVertexArray(VAOs[0]);
	glDrawArrays(GL_TRIANGLES, 0, 6);
}

void SceneInit()
{
	glGenVertexArrays(1 ,VAOs);
	glBindVertexArray(VAOs[0]);

	GLfloat vertices[6][2] = {
		{-0.9f, -0.9f},
		{0.85f, -0.9f},
		{-0.9f, 0.85f},
		{0.9f, -0.85f},
		{0.9f, 0.9f},
		{-0.85f, 0.9f},
	};

	glGenBuffers(1, Buffers);
	glBindBuffer(GL_ARRAY_BUFFER, Buffers[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
}

void ReSizeScene( int w, int h )
{
	SceneInit();
}

2. OpenGL的初始化过程

2.1 初始化顶点数组对象 --> glGenVertexArrays, glBindVertexArrays,

2.2 分配顶点缓存对象 ---> glGenBuffers, glBindBuffer

2.3 将数据载入缓存对象 ---> glBufferData

2.4 初始化顶点与片段着色器(之前的代码已把此部分删除)

2.5 顶点着色器里面的数据关联到顶点属性数组 --> glVertexAttribPointer

2.6 启动顶点属性数组 ---> glEnableVertexAttribArray

3. OpenGL 渲染过程

3.1 清除屏幕 ---> glClear

3.2 激活顶点数组 ---> glBindVertexArrays

3.3 使用OpenGL绘制函数 ---> glDrawArrays etc

posted @ 2014-12-19 19:48  zyh_think  阅读(1599)  评论(0编辑  收藏  举报