WINCE系统上开发OpenGL程序需具备以下条件: 1. 处理器的支持,嵌入式处理器需支持3D加速渲染(测试使用的是Telichips 8901); 2. WINCE内核的支持,定制内核时需添加OpenGL ES相关组件。 以下是具体的参考代码: [cpp] view plain copy #include "stdafx.h" #include "WinceOpenGLDemo.h" #include <windows.h> #include <commctrl.h> #include "ImgLoader.h" #include <GLES/gl.h> #include <GLES/glext.h> #include <EGL/egl.h> #include <EGL/eglext.h> #pragma comment(lib, "OpenGlLib\\libGLESv1_CM.lib") #pragma comment(lib, "OpenGlLib\\libEGL.lib") HINSTANCE g_hInst; TCHAR szAppName[] = L"OpenGLES"; CImgLoader g_Image; EGLDisplay glesDisplay; EGLSurface glesSurface; EGLContext glesContext; GLuint texture[6] = {0}; GLshort vertices[] = { -1,-1,1, 1,-1,1, 1,1,1, -1,1,1, -1,-1,-1, -1,1,-1, 1,1,-1, 1,-1,-1, -1,1,-1, -1,1,1, 1,1,1, 1,1,-1, -1,-1,-1, 1,-1,-1, 1,-1,1, -1,-1,1, 1,-1,-1, 1,1,-1, 1,1,1, 1,-1,1, -1,-1,-1, -1,-1,1, -1,1,1, -1,1,-1 }; GLshort texCoords[] = { 0,0,1,0,1,1,0,1, 0,0,1,0,1,1,0,1, 0,0,1,0,1,1,0,1, 0,0,1,0,1,1,0,1, 0,0,1,0,1,1,0,1, 0,0,1,0,1,1,0,1, }; GLbyte indices1[] = { 0,1,3,2, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; GLbyte indices2[] = { 0,0,0,0, 4,5,7,6, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; GLbyte indices3[] = { 0,0,0,0, 0,0,0,0, 8,9,11,10, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; GLbyte indices4[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 12,13,15,14, 0,0,0,0, 0,0,0,0 }; GLbyte indices5[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 16,17,19,18, 0,0,0,0 }; GLbyte indices6[] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 20,21,23,22 }; ATOM MyRegisterClass(HINSTANCE, LPTSTR); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitOGLES(HWND hWnd); void CreateSurface(); BOOL LoadTexture(LPCTSTR lpFileName,GLuint *id); void Render(); void Clean(); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; if (!InitInstance(hInstance, nCmdShow)) { return FALSE; } BOOL done = FALSE; while(!done) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { if(msg.message==WM_QUIT) done = TRUE; else { TranslateMessage(&msg); DispatchMessage(&msg); } } else { Render(); }; } return (int) msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINCEOPENGLDEMO)); wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = szWindowClass; return RegisterClass(&wc); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; g_hInst = hInstance; if (!MyRegisterClass(hInstance, szAppName)) { return FALSE; } hWnd = CreateWindow( szAppName, szAppName, WS_VISIBLE, 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } if(!InitOGLES(hWnd)) { printf("InitOGLES failed\n"); return FALSE; } CreateSurface(); ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; case WM_DESTROY: { Clean(); PostQuitMessage(0); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } BOOL InitOGLES(HWND hWnd) { EGLint matchingConfigs; EGLint majorVersion = 0; EGLint minorVersion = 0; glesDisplay = eglGetDisplay(GetDC(hWnd)); if( glesDisplay == EGL_NO_DISPLAY || eglGetError() != EGL_SUCCESS ) return FALSE; EGLConfig *configs_list; EGLint num_configs; if( eglInitialize( glesDisplay, &majorVersion, &minorVersion) == EGL_FALSE) { printf("eglInitialize failed, eglGetError = 0x%04x\n",eglGetError()); return FALSE; } if ( eglGetConfigs( glesDisplay, NULL, 0, &num_configs)==EGL_FALSE || eglGetError() != EGL_SUCCESS ) return FALSE; configs_list = (EGLConfig*) malloc(num_configs * sizeof(EGLConfig)); if (configs_list == NULL) return FALSE; if( eglGetConfigs( glesDisplay, configs_list, num_configs, &num_configs)== EGL_FALSE || eglGetError() != EGL_SUCCESS ) return FALSE; EGLint attrs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 16, EGL_NONE }; if (!eglChooseConfig(glesDisplay, attrs, configs_list, num_configs, &matchingConfigs)) { return eglGetError(); } if (matchingConfigs < 1) return FALSE; glesSurface = eglCreateWindowSurface(glesDisplay, configs_list[0], hWnd, 0); if(!glesSurface) return FALSE; glesContext=eglCreateContext(glesDisplay, configs_list[0], 0, 0); if(!glesContext) return FALSE; eglMakeCurrent(glesDisplay, glesSurface, glesSurface, glesContext); glClearColorx(0, 0, 0, 0); glShadeModel(GL_SMOOTH); RECT rc; GetWindowRect(hWnd, &rc); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; glViewport(rc.left, rc.top, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float ratio = (float) width / height; glFrustumf(-ratio, ratio, -1, 1, 2, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return TRUE; } void CreateSurface() { glDisable(GL_DITHER); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glClearColor(0, 0, 0, 0); glShadeModel(GL_SMOOTH); glClearDepthf(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glEnable(GL_TEXTURE_2D); LoadTexture(_T("\\NAND2\\OpenGlRes\\1.png"),&texture[0]); LoadTexture(_T("\\NAND2\\OpenGlRes\\1.png"),&texture[1]); LoadTexture(_T("\\NAND2\\OpenGlRes\\1.png"),&texture[2]); LoadTexture(_T("\\NAND2\\OpenGlRes\\1.png"),&texture[3]); LoadTexture(_T("\\NAND2\\OpenGlRes\\1.png"),&texture[4]); LoadTexture(_T("\\NAND2\\OpenGlRes\\1.png"),&texture[5]); } void Render() { static float rotation = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -5.0f); glRotatef(rotation++, 0.0f, 1.0f, 0.0f); glRotatef(rotation++, 1.0f, 0.0f, 0.0f); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_SHORT, 0, vertices); glTexCoordPointer(2, GL_SHORT, 0, texCoords); glBindTexture(GL_TEXTURE_2D, texture[0]); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices1); glBindTexture(GL_TEXTURE_2D, texture[1]); glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, indices2); glBindTexture(GL_TEXTURE_2D, texture[2]); glDrawElements(GL_TRIANGLE_STRIP, 12, GL_UNSIGNED_BYTE, indices3); glBindTexture(GL_TEXTURE_2D, texture[3]); glDrawElements(GL_TRIANGLE_STRIP, 16, GL_UNSIGNED_BYTE, indices4); glBindTexture(GL_TEXTURE_2D, texture[4]); glDrawElements(GL_TRIANGLE_STRIP, 20, GL_UNSIGNED_BYTE, indices5); glBindTexture(GL_TEXTURE_2D, texture[5]); glDrawElements(GL_TRIANGLE_STRIP, 24, GL_UNSIGNED_BYTE, indices6); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); eglSwapBuffers(glesDisplay, glesSurface); } void Clean() { if(glesDisplay) { eglMakeCurrent(glesDisplay, NULL, NULL, NULL); if(glesContext) eglDestroyContext(glesDisplay, glesContext); if(glesSurface) eglDestroySurface(glesDisplay, glesSurface); eglTerminate(glesDisplay); } } BOOL LoadTexture(LPCTSTR lpFileName,GLuint *id) { if(!g_Image.Load(lpFileName)) return FALSE; glGenTextures(1, id); glBindTexture(GL_TEXTURE_2D, *id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, g_Image.Width(), g_Image.Height(), 0, GL_RGB, GL_UNSIGNED_BYTE, g_Image.GetBmpImage()); g_Image.Free(); return TRUE; }
以下实现了一个文件加载类,用以将外部图片资源转化成绘制纹理时所需的位图数据。参考代码如下:
[cpp] view plain copy #pragma once class CImgLoader { public: CImgLoader(void); ~CImgLoader(void); public: BOOL Load(LPCTSTR lpFileName); unsigned char* GetBmpImage(void); void Free(); int Width(); int Height(); private: int m_Width; int m_Height; unsigned char *m_pImage; };
|