我的第1个OpenGL ES程序 for WinCE5 HTC TouchHD
我的第1个OpenGL ES程序 for WinCE5 HTC TouchHD
cheungmine
中午吃过饭,闲来无事,看着我的手机(HTC TouchHD),忽然想编一个OpenGL程序玩玩。CSDN上下载了OpenGL ES的开发包。
解压之后发现了:bin/arm/Release目录下有几个文件:
libGLES_CM.dll
libGLES_CM.lib
libGLES_CM.exp
等等。就准备把 libGLES_CM.dll 拷贝到我的手机的Windows下,提示已经有了这个文件,要不要覆盖?当然不覆盖。原来我的TouchHD支持OGL啊。太好了,马上编译例子Tutorial 1代码。其实就是新建一个Win32的移动程序空项目,平台是Windows Mobile 6.0Professional,然后把tutorial1.h和tutorial1.cpp文件拷贝到我的项目里,并添加到项目。编译不通过,提示文件目录不存在。马上添加包含目录和包含的库选项。编译通过。但是部署后,运行,失败。
网上搜,结果例子代码有问题,改正后的代码如下:
- #ifndef _TUTORIAL1_H
- #define _TUTORIAL1_H
- #include <windows.h> //needed include for window system calls
- //OpenGL ES Includes
- #include <GLES/gl.h>
- /*EGL is the "machine" that glues OpenGL ES with the underlying
- windowing system. We need it to create a suitable context and a drawable window*/
- #include <GLES/egl.h>
- /*Because we are building software device dependent (the PDA), we have care about
- its limitations. PDA's doesn't have a FPU unit, so all floating point operations
- are emulated in the CPU. To have real data type, PDA's uses reals with a fixed point
- format. For a fixed point number we only need an integer, with the same size (in bytes)
- that a float, that is, a normal int number. The first 16 bits of the int will be the
- "integer" part, and the last 16 bits will be the "real" part. This will cause a lack
- of precision, but it is better than emulate all FPU in the CPU. To convert an integer
- number to a fixed point number we need to displace its bits to the left, as the FixedFromInt
- function does. In this chapter we only will need the conversion int->fixed point.
- Other conversions will be showed when needed, in later chapters. A complete description of
- the fixed point maths is beyond the purpose of this set of tutorials, but the topic will
- be widely covered through the chapters.
- OpenGL ES offers us a set of functions that works with fixed point (Glfixed). These
- functions are available through the OpenGL ES OES_fixed_point extension.
- A little word about the OpenGL ES extensions: They are divided into two categories:
- those that are fully integrated into the profile definition (core additions); and those
- that remain extensions (profile extensions). Core additions do not use extension suffixes
- and does not requires initialization, whereas profile extensions retain their extension suffixes.
- OES_fixed_point is a core addition. The other extensions are listed and explained in the
- OpenGL ES 1.1 specification.*/
- #define PRECISION 16
- #define ONE (1 << PRECISION)
- #define ZERO 0
- inline GLfixed FixedFromInt(int value) {return value << PRECISION;};
- int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine,int nCmdShow);
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
- BOOL InitOGLES();// Our GL initialization function
- void Render(); // Our Render function
- void Clean(); //Our clean function. It will clean all used resources
- #endif
- #include "tutorial1.h" //We need the defines and prototypes of there
- // cheungmine
- #pragma comment(lib, "E:/GU2005/GCE/OpenGL_ES_WCE/ogl-es-bin-0.83/dist/bin/arm/Debug/libGLES_CM.lib")
- //Some useful global handles
- HINSTANCE hInst; //Will hold the current instance of the application
- HWND hWnd; // A handle to the window we will create
- HDC hDC; // A handle to the device context of the window. Needed to
- //create the OpenGL ES context
- // OpenGL variables
- EGLDisplay glesDisplay; // EGL display
- EGLSurface glesSurface; // EGL rendering surface
- EGLContext glesContext; // EGL rendering context
- TCHAR szAppName[] = L"OpenGLES"; /*The application name and the window caption*/
- /*This is the WinMain function. Here we will create the rendering window, initialize OpenGL ES, write the message loop, and, at the end, clean all and release all used resources*/
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
- {
- MSG msg; //This is the message variable for the message loop
- WNDCLASS wc; /*This structure will hold some init values for our window*/
- hInst = hInstance; // Initialization of our global variable
- bool done = FALSE;
- /*This block of code is to ensure that the user only can run one
- instance of the application. First we search for a window with the
- same class name, if found, we will focus it and return*/
- if(hWnd = FindWindow(szAppName, szAppName))
- {
- /* Set focus to foremost child window. The "| 0x01" is used to
- bring any owned windows to the foreground and activate them.*/
- SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
- return 0;
- }
- wc.style = CS_HREDRAW | CS_VREDRAW; /*Will force a redraw
- if the window is resized, both horizontally or vertically*/
- wc.lpfnWndProc = (WNDPROC) WndProc; /*this is a function pointer,
- to tell the OS what function should call when a message needs to be
- processed*/
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, NULL);//Load default icon
- wc.hCursor = 0; // Default cursor
- wc.hbrBackground = 0; //We don't care about the background color
- wc.lpszMenuName = NULL; //This application does not have a menu
- wc.lpszClassName = szAppName; /*Important, here we must fill the
- application class name (the class name is not the same than the
- caption of the window, but many times they are the same)*/
- //Before creating the window, we must register this new window class
- if(!RegisterClass(&wc))
- return FALSE;
- hWnd=CreateWindow(szAppName, //Class Name
- szAppName, //Caption string
- WS_VISIBLE,//Window style
- CW_USEDEFAULT,CW_USEDEFAULT,//Starting [x,y] pos.
- CW_USEDEFAULT, CW_USEDEFAULT, //Width and height
- NULL, NULL, //Parent window and menu handle
- hInst, NULL); /*Instance handle. Custom value to
- pass in the creation with the WM_CREATE message*/
- if(!hWnd) return FALSE;
- if(!InitOGLES()) return FALSE; //OpenGL ES Initialization
- //Bring the window to front, focus it and refresh it
- ShowWindow(hWnd, nCmdShow);
- UpdateWindow(hWnd);
- //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();
- }
- //Clean up all
- Clean();
- return 0;
- }
- //----------------------------------------------------------------------------
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch (message)
- {
- case WM_PAINT:
- ValidateRect(hWnd,NULL); //Needed to avoid new WM_PAINT messages
- return 0;
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- };
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- //----------------------------------------------------------------------------
- BOOL InitOGLES()
- {
- EGLint matchingConfigs;
- hDC = GetWindowDC(hWnd);
- glesDisplay = eglGetDisplay(hDC); //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, NULL, NULL ) == EGL_FALSE || eglGetError() != EGL_SUCCESS )
- return FALSE;
- // find out how many configurations 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[3] = { 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 = eglCreateWindowSurface(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);
- glShadeModel(GL_SMOOTH);
- /*In order to set a viewport that fits entirely our window, we need
- to know the window dimensions. They could be obtained through the
- WinCE call GetWindowRect, using our window handle*/
- RECT r;
- GetWindowRect(hWnd, &r);
- glViewport(r.left, r.top, r.right - r.left, r.bottom - r.top);
- /*Setup of the projection matrix. We will use an ortho cube centered
- at (0,0,0) with 100 units of edge*/
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthox(FixedFromInt(-50), FixedFromInt(50),
- FixedFromInt(-50), FixedFromInt(50),
- FixedFromInt(-50), FixedFromInt(50));
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- return TRUE;
- }
- //----------------------------------------------------------------------------
- void Render()
- {
- static int rotation = 0;
- /* Vertex 1 Vertex 2 Vertex 3*/
- GLshort vertexArray[9] = {-25,-25,0, 25,-25,0, 0,25,0 };
- GLubyte colorArray[12] = {255,0,0,0, 0,255,0,0, 0,0,255,0};
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glLoadIdentity();
- glTranslatex(0, 0, FixedFromInt(-10));
- glRotatex(FixedFromInt(rotation++), 0, ONE,0);
- //Enable the vertices array
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_SHORT, 0, vertexArray);
- //3 = XYZ coordinates, GL_SHORT = data type, 0 = 0 stride bytes
- //Enable the vertex color array
- glEnableClientState(GL_COLOR_ARRAY);
- glColorPointer(4,GL_UNSIGNED_BYTE, 0, colorArray);
- //4 = RGBA format, GL_UNSIGNED_BYTE = data type,0=0 stide bytes
- glDrawArrays(GL_TRIANGLES, 0, 3);
- /*We want draw triangles, 0 = first element(vertice), 3 = number of
- items (vertices) to draw from the array*/
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_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);
- }
- //We have to destroy the window too
- DestroyWindow(hWnd);
- UnregisterClass(szAppName, hInst);
- }
运行,结果出来了,很好。一个OGL窗口在我的手机里。中间一个缓缓转动的三角形。
好了,该干活了。就闲扯到这里。以后我还会陆续发布一些OGL ES的东西,无论我自己写的还是抄来的,权作茶余饭后的消遣。
下面是我看过的链接:
http://sourceforge.net/projects/ogl-es/files/
http://wiki.forum.nokia.com/index.php/OpenGL_ES%E7%AE%80%E4%BB%8B
http://blog.csdn.net/dymx101/archive/2010/02/03/5284348.aspx

浙公网安备 33010602011771号