Opengles API

转自 http://blog.csdn.net/wangyuchun_799/article/details/7736928

入门常见代码解析

3.1创建渲染缓冲区

GLuint m_renderbuffer;//创建一个渲染缓冲区对象

glGenRenderbuffers(1, &m_renderbuffer);//创建一个渲染缓冲区对象

glBindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);//将该渲染缓冲区对象绑定到管线上

3.2创建帧缓冲区

GLuint m_framebuffer;//创建一个帧缓冲区对象

glGenFramebuffers(1, &m_framebuffer);//创建一个帧染缓冲区对象

glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);//将该帧染缓冲区对象绑定到管线上

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);//将创建的渲染缓冲区绑定到帧缓冲区上,并使用颜色填充

3.3设置视口

glViewport(0, 0, width, height);//定义视口大小,说白了就是OpenGL ES窗口大小

3.4创建着色器

3.4.1创建一个空着色器

GLuint shaderHandle = glCreateShader(shaderType);//shaderType代表着色器的类型,可以是GL_VERTEX_SHADER(顶点着色器)或GL_FRAGMENT_SHADER(片元着色器)

3.4.2指定着色器源代码

glShaderSource(shaderHandle, 1, &source, 0);// source代表要执行的源代码字符串数组,1表示源代码字符串数组的字符串个数是一个,0表示源代码字符串长度数组的个数为0个

3.4.3编译着色器

glCompileShader(shaderHandle);//编译着色器

3.4.4检查编译是否成功

GLint compileSuccess;

glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);//查看编译着色器是否成功,可选的查询状态有L_DELETE_STATUS,GL_COMPILE_STATUS, GL_INFO_LOG_LENGTH, GL_SHADER_SOURCE_LENGTH

//如果编译出错,则记录出错信息

if (compileSuccess == GL_FALSE) {

GLchar messages[256];

glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);

std::cout << messages;

exit(1);

}

3.5创建渲染源程序

3.5.1创建一个空源程序

GLuint programHandle = glCreateProgram();//创建一个渲染程序

3.5.2向源程序中添加着色器

glAttachShader(programHandle, shaderHandle);//将着色器添加到程序中

3.5.3链接源程序

glLinkProgram(programHandle);//你可能添加了多个着色器,链接程序

3.5.4检查链接程序是否成功

GLint linkSuccess;

glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);//查看连接是否成功

//链接失败记录失败信息

if (linkSuccess == GL_FALSE) {

GLchar message[256];

glGetProgramInfoLog(programHandle, sizeof(message), 0, &message[0]);

std::cout << message;

exit(1);

}

3.6顶点结构体

//此处定义了一个代表顶点的结构体,内部包含一个有两个点(x,y)组成的顶点的位置信息,和一个四个值(r, g, b, a)表示的颜色信息

struct Vertex{

float Position[2];

float Color[4];

};

//创建顶点数组,里面有6个顶点信息

const Vertex vertices[] = {

{{-0.5, -0.866}, {0.5, 1, 0.5, 1}},

{{0.5, -0.866}, {0.2, 0.6, 0.5, 1}},

{{0, 1}, {0.6, 0.1, 0.8, 1}},

{{0.5, -0.866}, {0.5, 0.5, 0.5, 1}},

{{1.5, -0.866}, {0.5, 0.5, 0.5, 1}},

{{1, 0.4}, {0.5, 0.5, 0.5, 1}}

};

3.7着色器

3.7.1顶点着色器

#define STRINGIFY(A) #A

const char *SimpleVertexShader = STRINGIFY(

attribute vec4 Position;//位置,vec4说明有4个点组成,attribute表示属性,由程序提供输入值

attribute vec4 SourceColor;//源颜色,RGBA

varying vec4 DestinationColor;//目标颜色,输出值,用来传递到片元着色器,vary表示可变传出变量

uniform mat4 Projection;//投影矩阵,mat4表示一个4*4的矩阵,uniform表示统一的,不变的,每个顶点都是固定的这个值

uniform mat4 Modelview;//模型矩阵

void main(void){

DestinationColor = SourceColor;//简单的将源颜色赋给目标颜色

gl_Position = Projection * Modelview * Position;//通过矩阵乘法获得目标位置,gl_Position是OpenGL ES内定的值,必须指定

}

);

3.7.2片元着色器

const char *SimpleFragmentShader = STRINGIFY(

varying lowp vec4 DestinationColor;//由顶点着色器传入,lowp表示低精度

void main(void){

gl_FragColor = DestinationColor;//片元颜色,gl_FragColor也是OpenGL ES内定的,必须指定

}

);

3.8开始渲染

3.8.1填充(清理)屏幕

glClearColor(0.1f, 0.9f, 0.5f, 1);//指定填充屏幕的RGBA值

glClear(GL_COLOR_BUFFER_BIT);//指定要清除哪些缓冲区,GL_COLOR_BUFFER_BIT表示颜色缓冲区,GL_DEPTH_BUFFER_BIT表示深度缓冲区,GL_STENCIL_BUFFER_BIT表示模板缓冲区

3.8.2从着色器代码中获取属性信息

GLuint m_simpleProgram = programHandle;

GLuint positionSlot = glGetAttribLocation(m_simpleProgram, "Position");//从着色器源程序中的顶点着色器中获取Position属性

GLuint colorSlot = glGetAttribLocation(m_simpleProgram, "SourceColor");//从着色器源程序中的顶点着色器中获取SourceColor属性

3.8.3开启顶点属性数组

glEnableVertexAttribArray(positionSlot);

glEnableVertexAttribArray(colorSlot);

3.8.4为着色器属性赋值

GLsizei stride = sizeof(Vertex);//单个顶点的数据长度

const GLvoid *pCoords = &vertices[0].Position[0];//顶点数组中的位置数组首地址

const GLvoid *pColors = &vertices[0].Color[0];/顶点数组中的颜色数组首地址

glVertexAttribPointer(positionSlot, 2, GL_FLOAT, GL_FALSE, stride, pCoords);//为顶点着色器位置信息赋值,positionSlot表示顶点着色器位置属性(即,Position);2表示每一个顶点信息由几个值组成,这个值必须位1,2,3或4;GL_FLOAT表示顶点信息的数据类型;GL_FALSE表示不要将数据类型标准化(即fixed-point);stride表示数组中每个元素的长度;pCoords表示数组的首地址

glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors);//同上

3.8.5渲染顶点

GLsizei vertexCount = sizeof(vertices)/sizeof(Vertex);//顶点个数

glDrawArrays(GL_TRIANGLES, 0, vertexCount);//将顶点数组使用三角形渲染,GL_TRIANGLES表示三角形, 0表示数组第一个值的位置,vertexCount表示数组长度

3.8.6渲染完毕,关闭顶点属性数组

glDisableVertexAttribArray(positionSlot);

glDisableVertexAttribArray(colorSlot);

4.OpenGL 1.1和2.0在编程上的区别

4.1函数命名上的区别

1.1版API函数和宏末尾通常都为加上OES(即OpenglES的缩写),2.0版本基本上都把这个后缀名给去掉了,如:

1.1API函数和宏:glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_renderbuffer);

2.0API函数和宏:glBindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);

4.2渲染方式不同

1.1版是基于不可编程管线,2.0版是基于可编程管线的,明显的差别是1.1不支持着色器而2.0支持着色器,如下:

在1.1版将顶点渲染到屏幕上一般这样写:

glMatrixMode(GL_PROJECTION);

const float maxX = 2;

const float maxY = 3;

glOrthof(-maxX, maxX, -maxY, maxY, -1, 1);

glMatrixMode(GL_MODELVIEW);

2.0版支持着色器,就不再这么渲染顶点了。将顶点属性和变换方式全部放在顶点着色器和片元着色器中,然后程序中通过着色器来渲染

4.3编写同样的程序API不同

如,同样是激活和关闭顶点数组,在1.1中是glEnableClientState(GL_VERTEX_ARRAY);和glDisableClientState(GL_VERTEX_ARRAY);

但在2.0中,就变成了:glEnableVertexAttribArray(*);和glDisableVertexAttribArray(*);

差别的来源就在于1.1不使用着色器,而2.0使用着色器。

4.4编程难易程度不同。

1.1是基于不可编程管线的,因此,管线的各个组件都是写好的,我们仅需要调用即可。而2.0是基于可编程管线的,灵活性大大增加了,但是编写的难度和复杂度也增加了,因为什么功能都得自己写了。

5.着色器的使用流程

刚开始学习OpenGL ES2.0,对其着色器十分不感冒,什么是着色器,着色器该怎么使用,着色器包含哪些内容呢?

着色器就是一段包含着色信息的源代码字符串。通常着色器分为顶点着色器(Vertex Shader)和片元着色器(Fragment Shader),两个着色器分别写在不同的文件中,文件没有固定的后缀名,可以根据你自己的爱好写,但是最好能区别文件中写的是顶点着色器还是片元着色器,不然时间长了自己都不知道哪个文件中写的是什么信息了。如你可以给你的顶点着色器后缀名命名为:vert, ver, v, vsh等,给你的片元着色器后缀名命名为:frag, fra, f, fsh等。

着色器源代码和OpenGL源代码不是一起编译的,所以要特别强调我刚才说的“着色器是一段包含着色信息的源代码字符串”。所以,OpenGL源代码肯定是和工程一起编译的,但是着色器源代码是在运行期编译的。你可能会问,着色器的源代码是一个字符串怎么编译呢?所以OpenGL ES提供了一套运行期动态编译的流程:

(1)创建着色器:glCreateShader

(2)指定着色器源代码字符串:glShaderSource

(3)编译着色器:glCompileShader

(4)创建着色器可执行程序:glCompileShader

(5)向可执行程序中添加着色器:glAttachShader

(6)链接可执行程序:glLinkProgram

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容