惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - Orca

IOS程序崩溃报告管理解决方案(Crashlytics 在2014-09-24) 商业模式到底是什么?(转载) 实现不同行业不同职位的体验 OpenGL中主要的4种矩阵如何理解(使用类比方式以便于方便理解) 从定时任务看NSRunLoop和Autorelease(转载) NSTimer与Run loop Modes(转载) 多线程:NSThread和runloop(转载) iOS内存暴增问题追查与使用陷阱 (转载) 需要时显示——论App中的功能可见性(转) 如果爱,请深爱:10大iOS开发者最喜爱的类库(转载) 完整地翻译了一份ASIHttpRequest的文档 (转载) IOS 多线程编程指南【中文完整翻译版】(转载) IOS 5 Storyboard全解析-第二部分(转载) IOS 5 Storyboard全解析-第一部分(转载) IOS 学习总结(不断更新中) IOS 5 中@synthesize window = _window是什么意思呢 IOS 5 中为什么outlet 输出口总是设定成弱类型(weak)呢 浅谈iOS MVC 学习基础(转) iOS里的MVC(转)
OpenGL ES入门指南-原理(转载)
Orca · 2012-12-11 · via 博客园 - Orca

原文地址:http://dev.uphoneapp.com/doc/view.xhtml?id=52260

OpenGL ES入门指南

  • 作者:王雨
  •  
  • 更新时间:2010-11-15
  •  
  • 版本号:4.0
  •  
  • 查看次数:5053 次

摘 要:

本篇文档从零开始,深入简出,跟大家介绍一下OpenGL ES的原理和开发。

前言

OpenGL ES是Khronos Group创建的一系列API中的一种(官方组织是:http://www.khronos.org/)。在桌面计算机上有两套标准的3DAPI:Direct3D和OpenGL。Direct3D实际上是运行在windows操作系统上的标准3DAPI,而OpenGL则是跨平台的,适用于Linux、多种UNIX、MAC OS X和windows。由于OpenGL得到了广范围的认可,所以,基于嵌入式的3DAPI---OpenGL ES也就应运而生。
沃Phone使用的芯片高通7227,它能很好的提供对OpenGL ES的支持,了解OpenGL ES的种种特性,不仅能开发出很好的适用于沃Phone的3D游戏、3D应用等。借助于OpenGL ES的平台无关性,只要稍微修改EGL,理论上就可以将开发的3D游戏、3D应用移植到任何支持OpenGL ES的平台上去。
本篇文档就从零开始,深入简出,跟大家介绍一下OpenGL ES的原理和开发。

OpenGL ES简介

什么是OpenGL ES

OpenGL ES是一套适用于手持嵌入式设备的3DAPI。比如手机、PDA、汽车、航空等等上面都可以使用到OpenGL ES。OpenGL ES是免授权费的、跨平台的、功能完善的2D和3D图形应用程序接口API,它是桌面OpenGL的子集,是从OpenGL裁剪定制而来的。由于手持设备的相关局限性,OpenGL ES相对于OpenGL不可避免的进行了相关的精简。去除了OpenGL中比如glBegin/glEnd,四边形(GL_QUADS)、多边形(GL_POLYGONS)等复杂图元等许多非绝对必要的特性。但是OpenGL方面的很多知识,OpenGL ES都是可以借鉴的。
OpenGL ES其实是一个状态机(State machine),它保存一种状态直至其改变。每个状态都有本身默认的缺省值,可以通过相关的查询和设置函数进行相关的查询和设置。
大多数的OpenGL ES的应用都采用的是相同的操作顺序,这一系列的处理阶段被称作OpenGL ES的渲染管线(pipeline)。

OpenGL ES 2.0

看一下OpenGL ES的发展历程,如下图:


从图中我们可见,现在常用的OpenGL ES有两个版本,OpenGL ES1.1和OpenGL ES2.0。其中OpenGL ES1.1是固定渲染管线的,而OpenGL ES2.0是可编程渲染管线的。1.1版本现在多用于低成本的设备中,而2.0的版本的设备通常是兼容1.1的。这里说的渲染,就是根据模型创建图像的一个过程。而模型是根据几何图元创建的,图元包括点、直线、多边形,他们是通过顶点(Vertex)定义的。

OpenGL ES的处理流程

1.        固定渲染管线流程:

上图为固定渲染管线流程图,这个渲染管线是OpenGL ES1.1使用的。所处理的流程如下
1)        Primitive Processing:
这一步是图元运算过程,所谓图元,其实就是一个点集。在OpenGL ES中,所有的物体,几何元素最终都是以顶点的形式表述的。一般来说,这些顶点将会产生三角形、直线或点。它做的工作就是将顶点提供给顶点处理器进行处理。顶点的数据包括顶点的位置(空间坐标)、大小、颜色、顶点的法向量(用于光照计算)、纹理坐标(可能有多个)等等。
2)        Transform and Lighting:
这一步是转换和光照过程。其中Transform是通过模型、视图、投影变换矩阵,将所有的顶点坐标变换成人眼坐标系下的一致坐标。变换矩阵同样会改变物体的顶点法向量。如果激活了纹理,还可以进行纹理坐标转换,以及自动纹理坐标的生产。Lighting处理的就是光照部分,它会利用光源、材质、转换后的顶点位置和法向量计算每个顶点的颜色值。
3)        Primitive Assembly:
图元装配过程。管线中这个流程是对所有的点数据进行点线面等基础图元的组装。这个过程会对所有的图元进行剪切和筛选。对于不在视区空间中的部分进行剪切,对于不可见的面进行筛选。
4)        Resterizar:
光栅化。光栅化的过程就是对所有的经过Primitive Assembly图元转换成屏幕上可以显示的二维Fragment(片元)。片元和将要显示的像素一一对应。
5)        Texture Environment:
纹理处理。利用纹理坐标来进行纹理的相关处理。
6)        Colour Sum:
颜色叠加。根据纹理颜色等相关属性确定最终的顶点颜色。
7)        Fog:
雾。雾化处理。
8)        Alpha Test:
Alpha测试。判断某些片元是否抛弃。比如可以规定Alpha小于0.2的片元就需要抛弃。
9)        Depth Stencil:
深度测试和模板测试。深度测试需要一个深度缓冲区,是在后面的会被在前的遮盖,需要抛弃。模板测试需要一个模板缓冲区,也就是模板缓冲区中为每个像素保存了一个“模板值”,当像素需要进行模板测试时,将设定的模板参考值与该像素的“模板值”进行比较,符合条件的通过测试,不符合条件的则被丢弃,不进行绘制。条件的设置与Alpha测试中的条件设置相似。但注意Alpha测试中是用浮点数来进行比较,而模板测试则是用整数来进行比较。
10)    Color Buffer blend:
跟颜色缓冲区进行混合。最终生成的片元颜色需要跟颜色缓冲区中本来的进行混合(也可以理解成为跟背景混合),以生成最终的颜色。
11)    Dither:
抖动。在可用颜色数量较少的系统中,可能需要对颜色值进行抖动,在适当损失颜色质量的情况下增加可使用的颜色数量。
12)    Frame Buffer:
最终结果就写进了Frame Buffer。一个流程就算结束了。
2.        可编程渲染管线流程:

对比固定渲染管线流程图和可编程渲染管线流程图,可以看出来,大部分的流程都是一样的,只是可编程将固定中的几个功能合并了,新增了两个新的流程,Vertex Shader和Fragment Shader。也就是着色器(shader)
作为OpenGL ES2.0的一部分,着色器允许应用程序显式地指定处理顶点和片断时候所执行的操作。
1)      Shader language简介:
编写OpenGL ES程序使用的着色器类似于使用基于编译器的语言(比如C语言)编写程序。我们需要用编译器来分析程序,检查它所存在的错误,并把它转换成为目标代码。接着,在链接阶段,链接器把一组目标文件组合在一起,形成一个可执行的程序。着色器的创建流程如下:

对于每个着色器对象:
1.      创建一个着色器对象。
2.      把着色器源代码编译为目标代码。
3.      验证这个着色器已经成功通过编译。
然后,为了把多个着色器对象链接到一个着色器程序中,需要:
1.      创建一个着色器程序。
2.      把适当的着色器对象连接到这个着色器程序中。
3.      链接着色器程序。
4.      验证着色器程序链接成功。
5.      使用着色器进行顶点或片段处理。
1)      Vertex Shader:
包含了固定渲染管线中的Transform and lighting的所有操作。
2)      Fragment Shader:
包含了固定渲染管线中的纹理处理、颜色叠加、雾、alpha测试等内容。
                     具体着色器语言和两个着色器的使用,可见后续的sample分析。

EGL简介

OpenGL实现跨平台的功能,在不同的操作系统上需要不同的类似适配层的内容,比如在Windows操作系统上需要WGL。同样的,OpenGL ES是一个平台中立的图形库,在它能够工作前,需要与一个实际的窗口关联起来,但是,与OpenGL不一样的是,OpenGL是每个窗口系统需要一个与之对应的适配层,Windows需要WGL,X-Window需要xgl,Mac OS需要agl。而OpenGL ES的这层,是统一的一个标准。这个标准就是EGL。
(一)      初识EGL
EGL是介于RenderAPI(比如OpenGL ES和OpenVG)和本地基础系统的一套接口。里面涉及了OpenGL ES和OpenVG的一些相关描述,所以需要和OpenGL ES和OpenVG文档一起阅读。EGL使用OpenGLES的命名习惯来命名函数入口和宏定义。具体的接口和相关宏定义可以参见egl.h。
(二)      EGL的使用
1.      获取Display:
Display代表的是显示器,有的系统上有多个显示器,也就会有多个display。获得Display需要调用EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id);,参数一般为EGL_DEFAULT_DISPLAY。该参数的实际意义是平台相关的,比如在windows平台上,一般返回的就是DC。沃Phone上就是TDC。
2.      初始化egl:
获得了Display后,调用EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);该函数会进行一些相关的内部初始化工作。我们可以通过这个函数获得egl的版本号。
3.      选择Config:
Config实际就是FrameBuffer的参数,在Windows下对应于PixelFormat,在X-Window下对应Visual。可以用函数EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);,其中attrib_list 是以EGL_NONE结束的参数数组,通常以id,value依次存放,对于个别标识性的属性可以只有id,没有value。另一个办法是用EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); 来获得所有config。这两个函数都会返回不多于config_size个Config,结果保存在configs[]中,系统的总Config个数保存在num_config中。可以利用eglGetConfig()中间两个参数为0来查询系统支持的Config总个数。Config有众多的Attribute,这些Attribute决定FrameBuffer的格式和能力,通过eglGetConfigAttrib ()来读取,但不能修改。
4.      构造Surface:
有了Config,就可以开始构造Surface了。Surface实际上就是一个FrameBuffer。通过函数EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,EGLNativeWindowType win, const EGLint *attrib_list)可以创建一个Surface。系统通常还支持另外两种Surface:PixmapSurface和PBufferSurface,这两种都不是可显示的Surface,PixmapSurface是保存在系统内存中的位图,PBuffer则是保存在显存中的帧。Surface也有一些attribute,基本上都可以故名思意,EGL_HEIGHT EGL_WIDTH EGL_LARGEST_PBUFFER EGL_TEXTURE_FORMAT EGL_TEXTURE_TARGET EGL_MIPMAP_TEXTURE EGL_MIPMAP_LEVEL,通过eglSurfaceAttrib()设置、eglQuerySurface()读取。
5.      创建Context:
OpenGL ES的pipeline从程序的角度看就是一个状态机,有当前的颜色、纹理坐标、变换矩阵、渲染模式等一大堆状态,这些状态作用于程序提交的顶点坐标等图元从而形成帧缓冲内的像素。在OpenGL ES的编程接口中,Context就代表这个状态机,程序的主要工作就是向Context提供图元、设置状态,偶尔也从Context里获取一些信息。用EGLContext eglCreateContext(EGLDisplay dpy, EGLSurface write, EGLSurface read, EGLContext * share_list)来创建一个Context。
6.      绘制:
应用程序通过OpenGL API进行绘制,一帧完成之后,调用eglSwapBuffers(EGLDisplay dpy, EGLContext ctx)来显示。

 OpenGL ES的HelloWorld---Hello********

  1. #include "TG3.h" 
  2. #include  
  3. #include  
  4. #include "OGLES2Hello********.h" 
  5.   
  6. #define VERTEX_ARRAY   0 
  7.   
  8. EGLDisplay          eglDisplay  = 0; 
  9. EGLConfig           eglConfig   = 0; 
  10. EGLSurface          eglSurface  = 0; 
  11. EGLContext          eglContext  = 0; 
  12. EGLNativeWindowType eglWindow   = 0; 
  13.   
  14. extern TWindow *g_pThis; 
  15.   
  16. bool TestEGLError() 
  17.     
  18.     EGLint iErr = eglGetError(); 
  19.     if (iErr != EGL_SUCCESS) 
  20.     { 
  21.         return false
  22.     } 
  23.   
  24.     return true
  25.   
  26. bool CreateEGLContext() 
  27.     
  28.     eglWindow = (EGLNativeWindowType)g_pThis; 
  29.   
  30.     
  31.     eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY); 
  32.   
  33.     
  34.     EGLint iMajorVersion, iMinorVersion; 
  35.     if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion)) 
  36.     { 
  37.         return false
  38.     } 
  39.   
  40.     
  41.     const EGLint pi32ConfigAttribs[] = 
  42.     { 
  43.         EGL_LEVEL,              0, 
  44.         EGL_SURFACE_TYPE,       EGL_WINDOW_BIT, 
  45.         EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT, 
  46.         EGL_NATIVE_RENDERABLE,  EGL_FALSE, 
  47.         EGL_DEPTH_SIZE,         EGL_DONT_CARE, 
  48.         EGL_NONE 
  49.     }; 
  50.   
  51.     
  52.     int iConfigs; 
  53.     if (!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) 
  54.     { 
  55.         return false
  56.     } 
  57.   
  58.     
  59.     eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, eglWindow, NULL); 
  60.   
  61.     if(eglSurface == EGL_NO_SURFACE) 
  62.     { 
  63.         eglGetError(); 
  64.         eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, NULL, NULL); 
  65.     } 
  66.   
  67.     if (!TestEGLError()) 
  68.     { 
  69.         return false
  70.     } 
  71.   
  72.     
  73.     
  74.     eglBindAPI(EGL_OPENGL_ES_API); 
  75.     EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 
  76.     eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs); 
  77.   
  78.     if (!TestEGLError()) 
  79.     { 
  80.         return false
  81.     } 
  82.   
  83.     
  84.     eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); 
  85.     if (!TestEGLError()) 
  86.     { 
  87.         return false
  88.     } 
  89.     return true
  90.   
  91. bool Render() 
  92.     
  93.     bool bRet = false
  94.   
  95.     
  96.     float pfIdentity[] = 
  97.     { 
  98.         1.0f,0.0f,0.0f,0.0f, 
  99.         0.0f,1.0f,0.0f,0.0f, 
  100.         0.0f,0.0f,1.0f,0.0f, 
  101.         0.0f,0.0f,0.0f,1.0f 
  102.     }; 
  103.   
  104.     
  105.     
  106.     
  107.     char szFragShaderSrc[] = {"\ 
  108.                               void main (void)\ 
  109.                               {\ 
  110.                               gl_FragColor = vec4(1.0, 1.0, 0.66 ,1.0);\  
  111.                               }"}; 
  112.     char szVertShaderSrc[] = {"\ 
  113.                               attribute highp vec4  myVertex;\ 
  114.                               uniform mediump mat4  myPMVMatrix;\ 
  115.                               void main(void)\ 
  116.                               {\ 
  117.                               gl_Position = myPMVMatrix * myVertex;\ 
  118.                               }"}; 
  119.   
  120.     char * pszFragShader = (char *)szFragShaderSrc; 
  121.     char * pszVertShader = (char *)szVertShaderSrc; 
  122.   
  123.     GLuint uiFragShader = 0; 
  124.     GLuint uiVertShader = 0;      
  125.     GLuint uiProgramObject = 0;                   
  126.   
  127.     GLint bShaderCompiled; 
  128.     GLint bLinked; 
  129.   
  130.     
  131.     GLuint  ui32Vbo = 0; 
  132.   
  133.     
  134.     GLfloat afVertices[] = { -0.4f,-0.4f,0.0f, 
  135.         0.4f ,-0.4f,0.0f, 
  136.         0.0f ,0.4f ,0.0f}; 
  137.   
  138.     int i32InfoLogLength, i32CharsWritten; 
  139.     char* pszInfoLog = NULL; 
  140.     int i32Location = 0; 
  141.     unsigned int uiSize = 0; 
  142.   
  143.     
  144.     uiFragShader = glCreateShader(GL_FRAGMENT_SHADER); 
  145.   
  146.     
  147.     glShaderSource(uiFragShader, 1, (const char**)&pszFragShader, NULL); 
  148.   
  149.     
  150.     glCompileShader(uiFragShader); 
  151.   
  152.     
  153.     glGetShaderiv(uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled); 
  154.   
  155.     if (!bShaderCompiled) 
  156.     { 
  157.         
  158.         glGetShaderiv(uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength); 
  159.         
  160.         pszInfoLog = new char[i32InfoLogLength]; 
  161.         glGetShaderInfoLog(uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog); 
  162.         delete[] pszInfoLog; 
  163.         goto cleanup; 
  164.     } 
  165.   
  166.     
  167.     uiVertShader = glCreateShader(GL_VERTEX_SHADER); 
  168.     glShaderSource(uiVertShader, 1, (const char**)&pszVertShader, NULL); 
  169.     glCompileShader(uiVertShader); 
  170.     glGetShaderiv(uiVertShader, GL_COMPILE_STATUS, &bShaderCompiled); 
  171.     if (!bShaderCompiled) 
  172.     { 
  173.         glGetShaderiv(uiVertShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength); 
  174.         pszInfoLog = new char[i32InfoLogLength]; 
  175.         glGetShaderInfoLog(uiVertShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog); 
  176.         delete[] pszInfoLog; 
  177.         goto cleanup; 
  178.     } 
  179.   
  180.     
  181.     uiProgramObject = glCreateProgram(); 
  182.   
  183.     
  184.     glAttachShader(uiProgramObject, uiFragShader); 
  185.     glAttachShader(uiProgramObject, uiVertShader); 
  186.   
  187.     
  188.     glBindAttribLocation(uiProgramObject, VERTEX_ARRAY, "myVertex"); 
  189.   
  190.     
  191.     glLinkProgram(uiProgramObject); 
  192.   
  193.     
  194.     glGetProgramiv(uiProgramObject, GL_LINK_STATUS, &bLinked); 
  195.     if (!bLinked) 
  196.     { 
  197.         glGetProgramiv(uiProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength); 
  198.         pszInfoLog = new char[i32InfoLogLength]; 
  199.         glGetProgramInfoLog(uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog); 
  200.         delete[] pszInfoLog; 
  201.         goto cleanup; 
  202.     } 
  203.   
  204.     
  205.     glUseProgram(uiProgramObject); 
  206.   
  207.     
  208.     glClearColor(0.6f, 0.8f, 1.0f, 1.0f); 
  209.   
  210.     
  211.     glGenBuffers(1, &ui32Vbo); 
  212.   
  213.     
  214.     glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo); 
  215.   
  216.     
  217.     uiSize = 3 * (sizeof(GLfloat) * 3); 
  218.     glBufferData(GL_ARRAY_BUFFER, uiSize, afVertices, GL_STATIC_DRAW); 
  219.   
  220.     
  221.     { 
  222.         
  223.         glClear(GL_COLOR_BUFFER_BIT); 
  224.   
  225.   
  226.         
  227.         i32Location = glGetUniformLocation(uiProgramObject, "myPMVMatrix"); 
  228.   
  229.         
  230.         glUniformMatrix4fv( i32Location, 1, GL_FALSE, pfIdentity); 
  231.   
  232.         
  233.         glEnableVertexAttribArray(VERTEX_ARRAY); 
  234.   
  235.         
  236.         glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0); 
  237.   
  238.         
  239.         glDrawArrays(GL_TRIANGLES, 0, 3); 
  240.   
  241.         
  242.         eglSwapBuffers(eglDisplay, eglSurface); 
  243.     } 
  244.     bRet = true
  245.   
  246. cleanup: 
  247.     
  248.     if (uiProgramObject) 
  249.         glDeleteProgram(uiProgramObject); 
  250.     if (uiFragShader) 
  251.         glDeleteShader(uiFragShader); 
  252.     if (uiVertShader) 
  253.         glDeleteShader(uiVertShader); 
  254.   
  255.     
  256.     if (ui32Vbo) 
  257.         glDeleteBuffers(1, &ui32Vbo); 
  258.   
  259.     return bRet; 
  260.   
  261. bool DestroyEGLContext() 
  262.     
  263.     if (eglDisplay != EGL_NO_DISPLAY) 
  264.     { 
  265.         eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 
  266.         eglDestroyContext(eglDisplay, eglContext ); 
  267.         eglDestroySurface(eglDisplay, eglSurface ); 
  268.         eglTerminate(eglDisplay); 
  269.         eglDisplay = EGL_NO_DISPLAY; 
  270.     } 
  271.   
  272.     
  273.     eglWindow = NULL; 
  274.     return true
  275.   
  276. TWindow *g_pThis = NULL; 
  277.   
  278.     m_bGLESInit = FALSE; 
  279.     g_pThis = this
  280.   
  281.             if (CreateEGLContext()) 
  282.             { 
  283.                 m_bGLESInit = TRUE; 
  284.                 Sys_PostMessage(MESSAGE_PRIOR_LOWEST, 0, &PID_SELF, EVENT_FirstUser, GetWindowHwndId(), 0, NULL, 0); 
  285.             } 
  286.             bHandled = TRUE; 
  287.   
  288.     case EVENT_FirstUser: 
  289.         { 
  290.             if(m_bGLESInit) 
  291.             { 
  292.                 Render(); 
  293.                 Sys_PostMessage(MESSAGE_PRIOR_LOWEST, 0, &PID_SELF, EVENT_FirstUser, GetWindowHwndId(), 0, NULL, 0); 
  294.             } 
  295.             bHandled = TRUE; 
  296.         } 
  297.         break
  298.     case EVENT_GlesUpdateNotify: 
  299.         { 
  300.             if(m_bGLESInit) 
  301.             { 
  302.                 TRectangle  rt; 
  303.                 GetClientBounds(&rt); 
  304.                 MarkUpdateRectangle(&rt); 
  305.             } 
  306.             bHandled = TRUE; 
  307.         } 
  308.         break
  309.   
  310.             if (m_bGLESInit) 
  311.             { 
  312.                 DestroyEGLContext(); 
  313.                 m_bGLESInit = FALSE; 
  314.             } 
  315.             
  316.             pApp->SendStopEvent(); 

这个是在模拟器上跑的时候的代码,如果是在真机下跑,同在模拟器上跑,有以下区别:

1.      模拟器上使用的是自己创建的windows窗口,使用ms window的消息机制。但在真机上传的是沃Phone的窗口句柄。

2.      在调用eglGetDisplay的时候,模拟器上传入的是hdc,真机上传入的是(EGLNativeDisplayType)EGL_DEFAULT_DISPLAY)

3.      调用eglCreateWindowSurface的时候,模拟器上使用的是hWnd,但是真机上传入的是TWindows

4.      模拟器上的消息循环使用ms的机制,需要自己控制。真机上则需要加入EVENT_FirstUserEVENT_GlesUpdateNotify等消息。具体可参见范例。

ps:用3dmax建模,不知道能不能用3dmax与OpenGL ES搭配使用。就是用3dmax建模然后倒入什么的?

----答:3dmax建模后,建模师会把模型导出,保存成文件(比如md2文件)。然后程序员使用程序解析模型文件,把模型数据导入到计算机内存,再使用opengl根据模型数据绘图,就可以得到模型所描述的三维几何形体。(注意:建模师、程序员均为角色,可以是同一个自然人哦)

posted on 2012-12-11 10:06  Orca  阅读(4229)  评论()    收藏  举报