After my recent work, I started to learn OpenGL. I thought that wince also supports OpenGL, but embedded OpenGL ES. Therefore, I tried to write an OpenGL test program under wince to implement the drawing of cubes and textures. As follows:
Note that OpenGL program development on the wince system requires the following conditions:
1. Support for processors. embedded processors must support 3D accelerated rendering (telichips 8901 is used for testing );
2. Support for the wince kernel. OpenGL ES components must be added for Kernel customization.
The following is a specific reference code:
/*************************************** * **************************** Filename: winceOpenGLDemo. cppcreated: 2011-01-05author: firehoodpurpose: openGL ES is used to plot cubes and textures ****************************** ***************************************/ // WinceOpenGLDemo. cpp: defines the entry point of the application. // # Include "stdafx. h "# include" WinceOpenGLDemo. h "# include <windows. h> # include <commctrl. h> # include "ImgLoader. h "// OpenGL ES except des # include <GLES/gl. h> # include <GLES/glext. h> # include <EGL/egl. h> # include <EGL/eglext. h> // OpenGL lib # pragma comment (lib, "OpenGlLib \ libGLESv1_CM.lib") # pragma comment (lib, "OpenGlLib \ libEGL. lib ") // global variable: HINSTANCEg_hInst; // The current instance TCHAR szAppName [] = L" OpenGLES ";/* Application name and the window caption */CImgLoader g_Image; // OpenGL variables EGLDisplay glesDisplay; // EGL display EGLSurface glesSurface; // EGL rendering surface EGLContext glesContext; // EGL rendering context GLuint texture [6] = {0}; // coordinate 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}; // The texture coordinate GLshort texCoords [] = {, 0, ,}; // Triangle Index data GLbyte indices1 [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; GLbyte indices2 [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; GLbyte indices3 [] = {0, 0, 0, 0, 0, 0, 8, 9, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0}; GLbyte indices4 [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 15, 14, 0, 0, 0, 0, 0, 0}; GLbyte indices5 [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 0,}; GLbyte indices6 [] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21,}; // The Forward Declaration of the function contained in this Code module: ATOMMyRegisterClass (HINSTANCE, LPTSTR); BOOLInitInstance (HINSTANCE, int); L RESULT evaluate (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; // execute application initialization: if (! InitInstance (hInstance, nCmdShow) {return FALSE;} BOOL done = FALSE; // main message loop: 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;} // function: MyRegisterClass () /// purpose: register the window class. /// Note: // 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; re Turn RegisterClass (& wc) ;}/// function: InitInstance (HINSTANCE, int) /// purpose: Save the instance handle and create the main window /// note: //// in this function, we save the instance handle in global variables and // create and display the main program window. // BOOL InitInstance (HINSTANCE hInstance, int nCmdShow) {HWND hWnd; g_hInst = hInstance; // store the instance handle in the global variable if (! Values (hInstance, szAppName) {return FALSE;} hWnd = CreateWindow (szAppName, szAppName, WS_VISIBLE,: 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 ;} //// function: WndProc (HWND, UINT, WPARAM, LPARAM) /// objective: to process messages in the main window. /// WM_COMMAND-process application menu // WM_PAINT-draw the main window // WM_DESTROY-Send the Exit message and return /// 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); // TODO: add any drawing code here... 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); // Ask for an available display if (glesDisplay = EGL_NO_DISPLAY | eglGetError ()! = EGL_SUCCESS) return FALSE; EGLConfig * configs_list; EGLint num_configs; // Display initialization (we don't care about the OGLES version numbers) if (eglInitialize (glesDisplay, & majorVersion, & minorVersion) = EGL_FALSE) {printf ("eglInitialize failed, eglGetError = 0x % 04x \ n", eglGetError (); return FALSE ;} // find out how many comprehensions are supported 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; // Get Configurations if (eglGetConfigs (glesDisplay, configs_list, num_configs, & num_configs) = EGL_FALSE | eglGetError ()! = EGL_SUCCESS) return FALSE; // Obtain the first configuration with a depth buffer of 16 bits 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 there isn't any configuration enough good if (matchingConfigs <1) return FALSE;/* eglCreateWindowSurface creates an onscreen EGLSurface and returns a handle to it. any EGL rendering context created with a compatible EGLConfig can be used to render into this surface. */glesSurface = egl CreateWindowSurface (glesDisplay, configs_list [0], hWnd, 0); if (! GlesSurface) return FALSE; // Let's create our rendering context glesContext = eglCreateContext (glesDisplay, configs_list [0], 0, 0); if (! GlesContext) return FALSE; // Now we will activate the context for rendering eglMakeCurrent (glesDisplay, glesSurface, glesSurface, glesContext);/* Remember: because we are programming for a mobile device, we cant use any of the OpenGL ES functions that finish in 'F', we must use the fixed point version (they finish in 'X' */glClearColorx (0, 0, 0, 0, 0); glShadeModel (GL_SMOOTH); RECT rc; GetWindowRect (h Wnd, & rc); UINT width = rc. right-rc. left; UINT height = rc. bottom-rc. top; // set the glViewport (rc. left, rc. top, width, height); // sets the projection matrix glMatrixMode (GL_PROJECTION); glLoadIdentity (); // Projection Transformation (Perspective Projection) float ratio = (float) width/height; glFrustumf (-ratio, ratio,-1, 1, 2, 10); // glOrthox (FixedFromInt (-50), FixedFromInt (50), FixedFromInt (-50 ), fixedFromInt (50), FixedFromInt (-50), FixedFromInt (50); // select the model observation matrix glMatrixMode (GL_MODELVIEW); // reset the model observation matrix glLoadIdentity (); return TRUE;} void CreateSurface () {glDisable (GL_DITHER ); // notify the system to modify glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST) for the perspective; // glClearColor (0, 0, 0, 0) for the black background; // enable glShadeModel (GL_SMOOTH) for the shadow ); // set the deep cache glClearDepthf (1.0f); // enable the deep test GL_DEPTH_TEST; // glDepthFunc (GL_LEQUAL) Type of the deep test ); // enable 2D Texture glable (GL_TEXTURE _ 2D); // load the texture 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; // clear Screen and depth cache glClear (GL_COLOR_BUFFER_BIT | cached); glMatrixMode (GL_MODELVIEW); // reset the current model observation matrix glLoadIdentity (); // Coordinate Transformation glTranslatef (0.0f, 0.0f, -5.0f); // set the rotation glRotatef (rotation ++, 0.0f, 1.0f, 0.0f); glRotatef (rotation ++, 1.0f, 0.0f, 0.0f); glableclientstate (GL_VERTEX_ARRAY ); glableclientstate (GL_TEXTURE_COORD_ARRAY); glVertexPointer (3, GL_SHORT, 0, vertices); glTexCoordPointer (2, GL _ SHORT, 0, texCoords); // draw the cube and bind the glBindTexture (watermark, texture [0]); glDrawElements (numbers, 4, numbers, indices1); glBindTexture (GL_TEXTURE_2D, texture [1]); glDrawElements (numbers, 8, numbers, indices2); glBindTexture (GL_TEXTURE_2D, texture [2]); glDrawElements (numbers, 12, numbers, indices3 ); glBindTexture (GL_TEXTURE_2D, texture [3]); g LDrawElements (numbers, 16, numbers, indices4); glBindTexture (GL_TEXTURE_2D, texture [4]); glDrawElements (numbers, 20, numbers, indices5); glBindTexture (numbers, numbers, texture [5]); glDrawElements (numbers, 24, numbers, indices6); glDisableClientState (numbers); glDisableClientState (GL_VERTEX_ARRAY); eglSwapBuffers (glesDisplay, glesS Urface);} void Clean () {if (glesDisplay) {eglMakeCurrent (glesDisplay, 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; // create a texture glGenTextures (1, id); // bind the texture glBindTexture (Region, * id); glTexParameteri (GL_TEXTURE_2D, region, GL_NEAREST ); glTexParameteri (temperature, temperature, GL_NEAREST); glTexImage2D (temperature, 0, GL_RGB, g_Image.Width (), g_Image.Height (), 0, GL_RGB, temperature, g_image.getbmp image (); g_Image.Free (); return TRUE ;}
The following provides a file loading class to convert external image resources into bitmap data needed to draw textures. The reference code is as follows:
/*************************************** * **************************** Filename: cimgloader. hcreated: 2011-01-05author: firehoodpurpose: file loading class. Convert external image resources into bitmap data image formats required for texture rendering. The formats include BMP, PNG, and jpg. **************************************** * ***************************/# pragma onceclass cimgloader {public: cimgloader (void );~ Cimgloader (void); Public: // load the image resource bool load (lpctstr lpfilename); // obtain the bitmap data unsigned char * getbmp image (void ); // release the image resource void free (); // obtain the image width int width (); // obtain the Image Height int height (); Private: int m_width; // Image Width int m_height; // Image Height unsigned char * m_pimage; // pointer to image data };
/*************************************** * **************************** Filename: CImgLoader. cppcreated: 2011-01-05author: firehoodpurpose: file loading class, which converts external image resources into bitmap data image formats required for texture rendering. The formats include bmp, png, and jpg. **************************************** * ****************************/# include "StdAfx. h "# include" ImgLoader. h "// IImage uploder # include <imaging. h> # include <initguid. h> # include // IImage lib # pragma comment (Lib, "Imaging. lib") CImgLoader: CImgLoader (void) {m_pImage = NULL; m_Width = 0; m_Height = 0;} CImgLoader ::~ CImgLoader (void) {}// Load image resources BOOL CImgLoader: Load (LPCTSTR lpFileName) {IImagingFactory * pImgFactory = NULL; IImage * pImage = NULL; IBitmapImage * pBmpImg = NULL; // CoInitializeEx (NULL, COINIT_MULTITHREADED); if (! SUCCEEDED (CoCreateInstance (CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **) & pImgFactory) return FALSE; if (! SUCCEEDED (pImgFactory-> CreateImageFromFile (lpFileName, & pImage) return FALSE; // obtain image size information ImageInfo ImgInfo; pImage-> GetImageInfo (& ImgInfo); m_Width = ImgInfo. width; m_Height = ImgInfo. height; if (FAILED (pImgFactory-> values (pImage, m_Width, m_Height, PixelFormat24bppRGB, InterpolationHintDefault, & pBmpImg) {return FALSE;} RECT rect = {0, 0, m_Width, m_Height}; BitmapData * bmp data = new BitmapData; if (FAILED (pBmpImg-> LockBits (& rect, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, BMP data) {return FALSE ;} int line = BMP data-> Stride; LPBYTE lpData, lpLine, lpCurPixel; lpData = lpLine = (LPBYTE) BMP data-> Scan0; // obtain the address pointer of the actual value of the BMP bitmap. // if it is a Bottom-Up (Bottom-Up) bitmap, it points to the end of the buffer. // if it is Top-Down (Top-Down) to the beginning of the buffer. // int nBytesPP = nBPP> 3; // divide the three places by 8, get the number of bytes per pixel of the image m_pImage = new unsigned char [m_Width * m_Height * 3]; memset (m_pImage, 0, m_Width * m_Height * 3); if (m_pImage = NULL) return FALSE; if (line> 0) {int pos = m_Width * m_Height * 3-1; for (int I = 0; I <m_Height; I ++) // row {lpLine = lpData + I * line; // obtain the address pointer of each row of the image for (int j = m_Width-1; j>-1; j --) // column {lpCurPixel = lpLine + j * 3; // obtain the URL pointer m_pImage [pos --] = * lpCurPixel for each row; // Rm_pImage [pos --] = * (lpCurPixel + 1); // Gm_pImage [pos --] = * (lpCurPixel + 2 ); // B }}} else {int pos = 0; for (int I = m_Height-1; I>-1; I --) // row {lpLine = lpData + I * line; // obtain the address pointer of each row of the image for (int j = 0; j <m_Width; j ++) // column {lpCurPixel = lpLine + j * 3; // obtain the URL pointer m_pImage [pos ++] = * (lpCurPixel + 2) for each row per pixel; // Rm_pImage [pos ++] = * (lpCurPixel + 1 ); // Gm_pImage [pos ++] = * lpCurPixel; // B }}if (FAILED (pBmpImg-> UnlockBits (BMP data) {return FALSE;} delete BMP data; pBmpImg = NULL; pImage-> Release (); pImgFactory-> Release (); return TRUE;} // obtain the image data unsigned char * CImgLoader: getbmp image (void) {return m_pImage;} // get the image Width int CImgLoader: Width () {return m_Width;} // get the Image Height int CImgLoader: Height () {return m_Height ;} // release the image resource void CImgLoader: Free () {if (m_pImage) {delete [] m_pImage; m_pImage = NULL ;}}