iOS开发——图形编程OC篇&OpenGL ES2.0编程步骤
OpenGL ES2.0编程步骤
OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。
1. 保存全局变量的数据结构
以下例子程序均基于Linux平台。
typedef struct _escontext
{
void* userData; // Put your user data here...
GLint width; // Window width
GLint height; // Window height
EGLNativeWindowType hWnd; // Window handle
EGLDisplay eglDisplay; // EGL display
EGLContext eglContext; // EGL context
EGLSurface eglSurface; // EGL surface
// Callbacks
void (ESCALLBACK *drawFunc) ( struct _escontext * );
void (ESCALLBACK *keyFunc) ( struct _escontext *, unsigned char, int, int );
void (ESCALLBACK *updateFunc) ( struct _escontext *, float deltaTime );
}ESContext;
typedef struct
{
// Handle to a program object
GLuint programObject;
// Atrribute Location
GLint positionLoc;
GLint textureLoc;
// Uniform location
GLint matrixModeLoc;
GLint matrixViewLoc;
GLint matrixPerspectiveLoc;
// Sampler location
GLint samplerLoc;
// texture
GLuint texture;
} UserData;
2. 初始化EGL渲染环境和相关元素(第一步曲)
int InitEGL(ESContext * esContext)
{
NativeWindowType eglWindow = NULL;
EGLDisplay display;
EGLContext context;
EGLSurface surface;
EGLConfig configs[];
EGLBoolean eRetStatus;
EGLint majorVer, minorVer;
EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, , EGL_NONE};
EGLint numConfigs;
EGLint cfg_attribs[] = {EGL_BUFFER_SIZE, EGL_DONT_CARE,
EGL_DEPTH_SIZE, ,
EGL_RED_SIZE, ,
EGL_GREEN_SIZE, ,
EGL_BLUE_SIZE, ,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE};
// Get default display connection
display = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
if ( display == EGL_NO_DISPLAY )
{
return EGL_FALSE;
}
// Initialize EGL display connection
eRetStatus = eglInitialize(display, &majorVer, &minorVer);
if( eRetStatus != EGL_TRUE )
{
return EGL_FALSE;
}
//Get a list of all EGL frame buffer configurations for a display
eRetStatus = eglGetConfigs (display, configs, , &numConfigs);
if( eRetStatus != EGL_TRUE )
{
return EGL_FALSE;
}
// Get a list of EGL frame buffer configurations that match specified attributes
eRetStatus = eglChooseConfig (display, cfg_attribs, configs, , &numConfigs);
if( eRetStatus != EGL_TRUE || !numConfigs)
{
return EGL_FALSE;
}
// Create a new EGL window surface
surface = eglCreateWindowSurface(display, configs[], eglWindow, NULL);
if (surface == EGL_NO_SURFACE)
{
return EGL_FALSE;
}
// Set the current rendering API (EGL_OPENGL_API, EGL_OPENGL_ES_API,EGL_OPENVG_API)
eRetStatus = eglBindAPI(EGL_OPENGL_ES_API);
if (eRetStatus != EGL_TRUE)
{
return EGL_FALSE;
}
// Create a new EGL rendering context
context = eglCreateContext (display, configs[], EGL_NO_CONTEXT, context_attribs);
if (context == EGL_NO_CONTEXT)
{
return EGL_FALSE;
}
// Attach an EGL rendering context to EGL surfaces
eRetStatus = eglMakeCurrent (display, surface, surface, context);
if( eRetStatus != EGL_TRUE )
{
return EGL_FALSE;
}
//If interval is set to a value of 0, buffer swaps are not synchronized to a video frame, and the swap happens as soon as the render is complete.
eglSwapInterval(display,);
// Return the context elements
esContext->eglDisplay = display;
esContext->eglSurface = surface;
esContext->eglContext = context;
return EGL_TRUE;
}
3. 生成Program (第二步曲)
3.1 LoadShader
LoadShader主要实现以下功能:
1) 创建Shader对象
2) 装载Shader源码
3) 编译Shader
其实现参考代码如下:
/* type specifies the Shader type: GL_VERTEX_SHADER or GL_FRAGMENT_SHADER */
GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
// Create an empty shader object, which maintain the source code strings that define a shader
shader = glCreateShader ( type );
)
;
// Replaces the source code in a shader object
glShaderSource ( shader, , &shaderSrc, NULL );
// Compile the shader object
glCompileShader ( shader );
// Check the shader object compile status
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled )
{
GLint infoLen = ;
glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
)
{
char* infoLog = malloc (sizeof(char) * infoLen );
glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
free ( infoLog );
}
glDeleteShader ( shader );
;
}
return shader;
}
1)glCreateShader
它创建一个空的shader对象,它用于维护用来定义shader的源码字符串。支持以下两种shader:
(1) GL_VERTEX_SHADER: 它运行在可编程的“顶点处理器”上,用于代替固定功能的顶点处理;
( 2) GL_FRAGMENT_SHADER: 它运行在可编程的“片断处理器”上,用于代替固定功能的片段处理;
2)glShaderSource
shader对象中原来的源码全部被新的源码所代替。
3)glCompileShader
编译存储在shader对象中的源码字符串,编译结果被当作shader对象状态的一部分被保存起来,可通过glGetShaderiv函数获取编译状态。
4)glGetShaderiv
获取shader对象参数,参数包括:GL_SHADER_TYPE, GL_DELETE_STATUS, GL_COMPILE_STATUS, GL_INFO_LOG_LENGTH, GL_SHADER_SOURCE_LENGTH.
3.2 LoadProgram
其参考代码如下:
GLuint LoadProgram ( const char *vShaderStr, const char *fShaderStr )
{
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
// Create the program object
programObject = glCreateProgram ( );
)
;
// Attaches a shader object to a program object
glAttachShader ( programObject, vertexShader );
glAttachShader ( programObject, fragmentShader );
// Bind vPosition to attribute 0
glBindAttribLocation ( programObject, , "vPosition" );
// Link the program object
glLinkProgram ( programObject );
// Check the link status
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
if ( !linked )
{
GLint infoLen = ;
glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
)
{
char* infoLog = malloc (sizeof(char) * infoLen );
glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
esLogMessage ( "Error linking program:\n%s\n", infoLog );
free ( infoLog );
}
glDeleteProgram ( programObject );
return GL_FALSE;
}
// Free no longer needed shader resources
glDeleteShader ( vertexShader );
glDeleteShader ( fragmentShader );
return programObject;
}
1)glCreateProgram
建立一个空的program对象,shader对象可以被连接到program对像
2)glAttachShader
program对象提供了把需要做的事连接在一起的机制。在一个program中,在shader对象被连接在一起之前,必须先把shader连接到program上。
3)glBindAttribLocation
把program的顶点属性索引与顶点shader中的变量名进行绑定。
4)glLinkProgram
连接程序对象。如果任何类型为GL_VERTEX_SHADER的shader对象连接到program,它将产生在“可编程顶点处理器”上可执行的程
序;如果任何类型为GL_FRAGMENT_SHADER的shader对象连接到program,它将产生在“可编程片断处理器”上可执行的程序。
5)glGetProgramiv
获取program对象的参数值,参数有:GL_DELETE_STATUS, GL_LINK_STATUS,
GL_VALIDATE_STATUS, GL_INFO_LOG_LENGTH, GL_ATTACHED_SHADERS,
GL_ACTIVE_ATTRIBUTES, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
GL_ACTIVE_UNIFORMS, GL_ACTIVE_UNIFORM_MAX_LENGTH.
3.3 CreateProgram
在3.1中只实现了Shader的编译,在3.2中只实现了Program的链接,现在还缺少真正供进行编译和链接的源码,其参考代码如下:
int CreateProgram(ESContext * esContext)
{
GLuint programObject;
GLbyte vShaderStr[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
GLbyte fShaderStr[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"} \n";
// Create user data
esContext->userData = malloc(sizeof(UserData));
UserData *userData = esContext->userData;
// Load the shaders and get a linked program object
programObject = LoadProgram ( (const char*)vShaderStr, (const char*)fShaderStr );
)
{
return GL_FALSE;
}
// Store the program object
userData->programObject = programObject;
// Get the attribute locations
userData->positionLoc = glGetAttribLocation ( g_programObject, "v_position" );
glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
;
}
4. 安装并执行Program(第三步)
void Render ( ESContext *esContext )
{
UserData *userData = esContext->userData;
GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f };
// Set the viewport
glViewport ( , , esContext->width, esContext->height );
// Clear the color buffer
glClear ( GL_COLOR_BUFFER_BIT );
// Use the program object
glUseProgram ( userData->programObject );
// Load the vertex data
glVertexAttribPointer ( , , GL_FLOAT, GL_FALSE, , vVertices );
glEnableVertexAttribArray ( );
glDrawArrays ( GL_TRIANGLES, , );
eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
4.1 glClear
清除指定的buffer到预设值。可清除以下四类buffer:
1)GL_COLOR_BUFFER_BIT
2)GL_DEPTH_BUFFER_BIT
3)GL_ACCUM_BUFFER_BIT
4)GL_STENCIL_BUFFER_BIT
预设值通过glClearColor, glClearIndex, glClearDepth, glClearStencil, 和glClearAccum来设置。
1)gClearColor
指定color buffer的清除值,当调用glClear(GL_COLOR_BUFFER_BIT)时才真正用设定的颜色值清除color buffer。参数值的范围为:0~1。
void glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
2)glClearIndex
指定color index buffer清除值。void glClearIndex( GLfloat c);
3)glClearDepth
指定depth buffer的清除值,取值范围为:0~1,默认值为1。
void glClearDepth( GLclampd depth);
4)glClearStencil
指定stencil buffer清除值的索引,初始值为0。void glClearStencil( GLint s);
5)glClearAccum
指定accumulation buffer的清除值,初始值为0,取值范围为:-1~1
void glClearAccum( GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha);
4.2 glUseProgram
安装一个program object,并把它作为当前rendering state的一部分。
1) 当一个可执行程序被安装到vertex processor,下列OpenGL固定功能将被disable:
- The modelview matrix is not applied to vertex coordinates.
- The projection matrix is not applied to vertex coordinates.
- The texture matrices are not applied to texture coordinates.
- Normals are not transformed to eye coordinates.
- Normals are not rescaled or normalized.
- Normalization of GL_AUTO_NORMAL evaluated normals is not performed.
- Texture coordinates are not generated automatically.
- Per-vertex lighting is not performed.
- Color material computations are not performed.
- Color index lighting is not performed.
- This list also applies when setting the current raster position.
2) 当一个可执行程序被安装到fragment processor,下列OpenGL固定功能将被disable:
- Texture environment and texture functions are not applied.
- Texture application is not applied.
- Color sum is not applied.
- Fog is not applied.
4.3 glVertexAttribPointer
定义一个通用顶点属性数组。当渲染时,它指定了通用顶点属性数组从索引index处开始的位置和数据格式。其定义如下:
void glVertexAttribPointer(
GLuint index, // 指示将被修改的通用顶点属性的索引
GLint size, // 指点每个顶点元素个数(1~4)
GLenum type, // 数组中每个元素的数据类型
GLboolean normalized, //指示定点数据值是否被归一化(归一化<[-1,1]或[0,1]>:GL_TRUE,直接使用:GL_FALSE)
GLsizei stride, // 连续顶点属性间的偏移量,如果为0,相邻顶点属性间紧紧相邻
const GLvoid * pointer);//顶点数组
//注:其index应该小于#define GL_MAX_VERTEX_ATTRIBS 0x8869
4.4 glEnableVertexAttribArray
Enable由索引index指定的通用顶点属性数组。
void glEnableVertexAttribArray( GLuint index);
void glDisableVertexAttribArray( GLuint index);
默认状态下,所有客户端的能力被disabled,包括所有通用顶点属性数组。如果被Enable,通用顶点属性数组中的值将被访问并被用于rendering,通过调用顶点数组命令:glDrawArrays, glDrawElements, glDrawRangeElements, glArrayElement,
glMultiDrawElements, or glMultiDrawArrays.
4.5 glDrawArrays
void glDrawArrays( GLenum mode,
GLint first,
GLsizei count);
1) mode:指明render原语,如:GL_POINTS,
GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, 和 GL_POLYGON。
2) first: 指明Enable数组中起始索引。
3) count: 指明被render的原语个数。
可以预先使用单独的数据定义vertex、normal和color,然后通过一个简单的glDrawArrays构造一系列原语。当调用
glDrawArrays时,它使用每个enable的数组中的count个连续的元素,来构造一系列几何原语,从第first个元素开始。
4.6 eglSwapBuffers
把EGL surface中的color buffer提交到native window进行显示。
EGLBoolean eglSwapBuffers(EGLDisplay display,EGLSurface surface)
5. 协调组织
在前面的描述中,三步曲已经完成了:
1)初始化EGL环境,为绘图做好准备
2)生成Program
3)安装并执行Program
只有这三个关键人物,还不能运行,还需要一个协调组织者。其参考代码如下:
int main(int argc, char** argv)
{
ESContext esContext;
UserData userData;
int iFrames;
unsigned long iStartTime,iEndTime;
int iDeltaTime;
memset( &esContext, , sizeof( ESContext) );
esContext.userData = &userData;
esContext.width = ;
esContext.height = ;
// Init EGL display, surface and context
if(!InitEGL(&esContext))
{
printf("Init EGL fail\n");
return GL_FALSE;
}
// compile shader, link program
if(!CreateProgram(&esContext))
{
printf("Create Program fail\n");
return GL_FALSE;
}
iStartTime = GetCurTime();
iFrames = ;
)
{ // render a frame
Render(&esContext);
iFrames++;
iEndTime = GetCurTime();
iDeltaTime = iEndTime - iStartTime;
)
{
iStartTime = iEndTime;
float fFrame = iFrames * 1000.0 / iDeltaTime;
iFrames = ;
printf("Frame: %f\n", fFrame);
}
}
glDeleteProgram (esContext.userData->programObject);
return GL_TRUE;
}
iOS开发——图形编程OC篇&OpenGL ES2.0编程步骤的更多相关文章
- iOS开发——新特性OC篇&Swift 2.0新特性
Swift 2.0新特性 转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度 ...
- ios开发——实用技术篇OC篇&iOS的主要框架
iOS的主要框架 阅读目录 Foundation框架为所有的应用程序提供基本系统服务 UIKit框架提供创建基于触摸用户界面的类 Core Data框架管着理应用程序数据模型 Core ...
- iOS开发——网络实用技术OC篇&网络爬虫-使用青花瓷抓取网络数据
网络爬虫-使用青花瓷抓取网络数据 由于最近在研究网络爬虫相关技术,刚好看到一篇的的搬了过来! 望谅解..... 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教 ...
- iOS开发——高级技术OC篇&运行时(Runtime)机制
运行时(Runtime)机制 本文将会以笔者个人的小小研究为例总结一下关于iOS开发中运行时的使用和常用方法的介绍,关于跟多运行时相关技术请查看笔者之前写的运行时高级用法及相关语法或者查看响应官方文档 ...
- iOS开发——UI精选OC篇&UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍
UIApplication,UIWindow,UIViewController,UIView(layer)简单介绍 一:UIApplication:单例(关于单例后面的文章中会详细介绍,你现在只要知道 ...
- iOS开发——运行时OC篇&使用运行时获取系统的属性:使用自己的手势修改系统自带的手势
使用运行时获取系统的属性:使用自己的手势修改系统自带的手势 有的时候我需要实现一个功能,但是没有想到很好的方法或者想到了方法只是那个方法实现起来太麻烦,一或者确实为了装逼,我们就会想到iOS开发中最牛 ...
- iOS开发——网络实用技术OC篇&网络爬虫-使用java语言抓取网络数据
网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一 ...
- iOS开发——高级UI—OC篇&退出键盘
退出键盘 iOS开发中键盘的退出方法用很多中我们应该在合适的地方使用合适的方法才能更好的提高开发的效率和应用的性能 下面给大家介绍几种最常用的键盘退出方法,基本上iOS开发中的键盘退出方法都是这几种中 ...
- iOS开发——技术精华Swift篇&Swift 2.0和Objective-C2.0混编之第三方框架的使用
swift 语言是苹果公司在2014年的WWDC大会上发布的全新的编程语言.Swift语言继承了C语言以及Objective-C的特性,且克服了C语言的兼容性问题.Swift语言采用安全编程模式,且引 ...
随机推荐
- SQL删除数据库里所有表的外键,同时删除所有用户表
SQL删除数据库里所有表的外键,同时删除所有用户表 删除所有的用户表的外键,直接将下面的代码拷贝到数据库里执行即可: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- android测试本地服务调试流程
我今天调试的整个过程 1,安卓发现连不上本地的tomcat 2,使用浏览器直接尝试,发现可以连上 3,怀疑是安卓APP和浏览器访问有差异,后上网搜索不到APP,只有浏览器尝试 再不就是改I ...
- 【原】Storm学习资料推荐
4.Storm学习资料推荐 书籍: 英文: Learning Storm: Ankit Jain, Anand Nalya: 9781783981328: Amazon.com: Books Gett ...
- 利用ASP.NET MVC源代码调试你的应用程序[转]
由于项目需要,最近学起asp.net mvc.昨天遇到ViewData和TempData他们之间的分别这样让我纠结的问题.有园友强烈建议我去看ASP.NET MVC的源代码.所以,我想到如何在调试AS ...
- 怎么用PHP在HTML中生成PDF文件
原文:Generate PDF from html using PHP 译文:使用PHP在html中生成PDF 译者:dwqs 利用PHP编码生成PDF文件是一个非常耗时的工作.在早期,开发者使用PH ...
- matlab图像基础知识
1.MATLAB支持的几种图像文件格式: ⑴JPEG(Joint Photogyaphic Expeyts Group):一种称为联合图像专家组的图像压缩格式. ⑵BMP(Windows Bitmap ...
- Java 编程要点之并发(Concurrency)详解
计算机用户想当然地认为他们的系统在一个时间可以做多件事.他们认为,他们可以工作在一个字处理器,而其他应用程序在下载文件,管理打印队列和音频流.即使是单一的应用程序通常也是被期望在一个时间来做多件事.例 ...
- 获取iOS设备信息(内存/电量/容量/型号/IP地址/当前WIFI名称)
1.获取电池电量(一般用百分数表示,大家自行处理就好) 1 2 3 4 -(CGFloat)getBatteryQuantity { return [[UIDevice current ...
- hud 1166 敌兵布阵
http://acm.hdu.edu.cn/showproblem.php?pid=1166 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory ...
- VPN Gate Client v4.11-免費、無限流量VPN翻牆(跳板)軟體(使用教學)
VPN Gate Client安裝教學 ▼把下載的檔案壓縮後,開啟安裝檔案. ▼接下來就是一般安裝步驟,下一步>下一步 ▼同意>下一步>下一步 ▼安裝目錄可以用預設的也可以自 ...