内容简介:关于图层设置、上下文设置、清空缓冲区、设置renderBuffer、frameBuffer的代码,与由于要实现的是一个金字塔,而且是能够旋转的,所以我们新增了投影矩阵和模型矩阵设置屏幕(清屏颜色、清除屏幕、视口大小),读取着色器程序,加载shader、链接以及使用program这些步骤的代码之前大家都接触过,这里不再展示给大家,因为和
系列推荐文章:
OpenGL/OpenGL ES入门:图形API以及专业名词解析
OpenGL/OpenGL ES入门:渲染流程以及固定存储着色器
OpenGL/OpenGL ES入门:图像渲染实现以及渲染问题
OpenGL/OpenGL ES入门:基础变换 - 初识向量/矩阵
OpenGL/OpenGL ES入门:纹理初探 - 常用API解析
OpenGL/OpenGL ES入门: 纹理应用 - 纹理坐标及案例解析(金字塔)
OpenGL/OpenGL ES入门: 顶点着色器与片元着色器(OpenGL过渡OpenGL ES)
OpenGL/OpenGL ES入门: GLKit以及API简介
OpenGL/OpenGL ES入门: GLKit使用以及案例
OpenGL/OpenGL ES入门: 使用OpenGL ES 渲染图片
OpenGL/OpenGL ES入门:iOS纹理翻转策略解析
OpenGL ES入门: 渲染金字塔 - 颜色、纹理、纹理与颜色混合填充以及GLKit实现案例目标
- 熟悉OpenGL ES渲染图形过程
- 练习使用索引的方式处理顶点坐标
- 使用颜色填充金字塔
- 使用纹理填充金字塔
- 使用纹理与颜色混合填充金字塔
- OpenGL ES GLSL渲染与GLKit对比
金字塔渲染实现流程
颜色填充 相关代码实现
关于图层设置、上下文设置、清空缓冲区、设置renderBuffer、frameBuffer的代码,与 上一篇:OpenGL/OpenGL ES入门: 使用OpenGL ES 渲染图片 的代码无异,这里不过多描述,也会附 demo 一份,供大家参考。
编辑着色器
顶点着色器
由于要实现的是一个金字塔,而且是能够旋转的,所以我们新增了投影矩阵和模型矩阵
attribute vec4 position; attribute vec4 positionColor; uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix; varying lowp vec4 varyColor; void main() { varyColor = positionColor; vec4 vPos; vPos = projectionMatrix * modelViewMatrix * position; gl_Position = vPos; } 复制代码
片元着色器
varying lowp vec4 varyColor; void main() { gl_FragColor = varyColor; } 复制代码
开始绘制
设置屏幕(清屏颜色、清除屏幕、视口大小),读取着色器程序,加载shader、链接以及使用program这些步骤的代码之前大家都接触过,这里不再展示给大家,因为和 上一篇:OpenGL/OpenGL ES入门: 使用OpenGL ES 渲染图片 中的代码也是一摸一样的,具体参考 demo ,下面介绍一下不同的。
索引数组
先看下面这个俯视图的金字塔,共有5个顶点
由6个三角形构成,找出对应三角形的三个顶点,然后放进索引数组里
// 顶点数组 前3顶点值(x,y,z),后3位颜色值(RGB) GLfloat attrArr[] = { -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, //左上0 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, //右上1 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, //右下2 -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, //左下3 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, //顶点4 }; // 索引数组 GLuint indices[] = { 0, 1, 2, 0, 2, 3, 0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0, }; 复制代码
处理顶点数据、顶点颜色值
// 判断顶点缓存区是否为空,如果为空则申请一个缓存区标识符 if (self.myVertices == 0) { glGenBuffers(1, &_myVertices); } //9.-----处理顶点数据------- //(1).将_myVertices绑定到GL_ARRAY_BUFFER标识符上 glBindBuffer(GL_ARRAY_BUFFER, _myVertices); //(2).把顶点数据从CPU内存复制到GPU上 glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW); //(3).将顶点数据通过myPrograme中的传递到顶点着色程序的position //1.glGetAttribLocation,用来获取vertex attribute的入口的. //2.告诉OpenGL ES,通过glEnableVertexAttribArray, //3.最后数据是通过glVertexAttribPointer传递过去的。 //注意:第二参数字符串必须和shaderv.vsh中的输入变量:position保持一致 GLuint position = glGetAttribLocation(self.myProgram, "position"); //(4).打开position glEnableVertexAttribArray(position); //(5).设置读取方式 //参数1:index,顶点数据的索引 //参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4. //参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLOAT //参数4:normalized,固定点数据值是否应该归一化,或者直接转换为固定值。(GL_FALSE) //参数5:stride,连续顶点属性之间的偏移量,默认为0; //参数6:指定一个指针,指向数组中的第一个顶点属性的第一个组件。默认为0 glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 8, NULL); //10.--------处理顶点颜色值------- //(1).glGetAttribLocation,用来获取vertex attribute的入口的. //注意:第二参数字符串必须和shaderv.glsl中的输入变量:positionColor保持一致 GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor"); //(2).打开positionColor glEnableVertexAttribArray(positionColor); glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 8, (float *)NULL + 3); 复制代码
设置投影矩阵、模型矩阵
//11.找到myProgram中的projectionMatrix、modelViewMatrix 2个矩阵的地址。如果找到则返回地址,否则返回-1,表示没有找到2个对象。 GLuint projectionMatrixSlot = glGetUniformLocation(self.myProgram, "projectMatrix"); GLuint modelViewMatrixSlot = glGetUniformLocation(self.myProgram, "modelViewMatrix"); //12.创建4 * 4投影矩阵 KSMatrix4 _projectMat; //(1)获取单元矩阵 ksMatrixLoadIdentity(&_projectMat); //(2)计算纵横比例 float aspect = self.frame.size.width / self.frame.size.height; //(3)获取透视矩阵 /* 参数1:矩阵 参数2:视角,度数为单位 参数3:纵横比 参数4:近平面距离 参数5:远平面距离 */ ksPerspective(&_projectMat, 35, aspect, 5, 20); //(4)将投影矩阵传递到顶点着色器 /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 参数列表: location:指要更改的uniform变量的位置 count:更改矩阵的个数 transpose:是否要转置矩阵,并将它作为uniform变量的值。必须为GL_FALSE value:执行count个元素的指针,用来更新指定uniform变量 */ glUniformMatrix4fv(projectionMatrixSlot, 1, GL_FALSE, (GLfloat *)&_projectMat.m[0][0]); //13.创建一个4 * 4 矩阵,模型视图矩阵 KSMatrix4 _modelViewMat; //(1)获取单元矩阵 ksMatrixLoadIdentity(&_modelViewMat); //(2)平移,z轴平移-10 ksTranslate(&_modelViewMat, 0, 0, -10); //(3)创建一个4 * 4 矩阵,旋转矩阵 KSMatrix4 _rotationMat; //(4)初始化为单元矩阵 ksMatrixLoadIdentity(&_rotationMat); //(5)旋转 分别绕X、Y、Z轴 ksRotate(&_rotationMat, _xDegree, 1, 0, 0); ksRotate(&_rotationMat, _yDegree, 0, 1, 0); ksRotate(&_rotationMat, _zDegree, 0, 0, 1); //(6)把变换矩阵相乘.将_modelViewMatrix矩阵与_rotationMatrix矩阵相乘,结合到模型视图 ksMatrixMultiply(&_modelViewMat, &_rotationMat, &_modelViewMat); //(7)将模型视图矩阵传递到顶点着色器 /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 参数列表: location:指要更改的uniform变量的位置 count:更改矩阵的个数 transpose:是否要转置矩阵,并将它作为uniform变量的值。必须为GL_FALSE value:执行count个元素的指针,用来更新指定uniform变量 */ glUniformMatrix4fv(modelViewMatrixSlot, 1, GL_FALSE, (GLfloat *)&_modelViewMat.m[0][0]); 复制代码
使用索引绘图
//14.开启剔除操作效果 glEnable(GL_CULL_FACE); //15.使用索引绘图 /* void glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices); 参数列表: mode:要呈现的画图的模型 GL_POINTS GL_LINES GL_LINE_LOOP GL_LINE_STRIP GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN count:绘图个数 type:类型 GL_BYTE GL_UNSIGNED_BYTE GL_SHORT GL_UNSIGNED_SHORT GL_INT GL_UNSIGNED_INT indices:绘制索引数组 */ glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices); //16.从渲染缓冲区显示到屏幕上 [self.myContext presentRenderbuffer:GL_RENDERBUFFER]; 复制代码
实现效果:
纹理填充 - 相关代码
纹理填充,顾名思义,就是使用图片去填充,联系 OpenGL/OpenGL ES入门: 使用OpenGL ES 渲染图片 中所说的图片渲染,如果大家练习了,应该可以自己写的出来。下面给出关键代码:
纹理坐标的添加
// 顶点数组 前3顶点值(x,y,z),后3位颜色值(RGB) 后2位纹理坐标 GLfloat attrArr[] = { -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, //左上0 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, //右上1 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, //右下2 -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, //左下3 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, //顶点4 }; 复制代码
在绘制过程中加载纹理,设置纹理采样器 sampler2D,相信下面两句代码,大家并不陌生。
//加载纹理 [self setupTexture:@"test"]; //设置纹理采样器 sampler2D glUniform1f(glGetAttribLocation(self.myProgram, "colorMap"), 0); 复制代码
同时需要修改片元着色器代码
varying lowp vec2 varyTextCoord; uniform sampler2D colorMap; void main () { gl_FragColor = texture2D(colorMap, varyTextCoord); } 复制代码
最终效果:
纹理与颜色混合填充 - 相关代码
这里主要是混合,纹理与颜色的混合,在OpenGL系列文章里说过混合,有相关公式,主要代码在片元着色器中实现,具体代码如下:
precision highp float; varying lowp vec4 varyColor; varying lowp vec2 varyTextCoord; uniform sampler2D colorMap; void main () { vec4 weakMask = texture2D(colorMap, varyTextCoord); vec4 mask = varyColor; float alpha = 0.3; vec4 tempColor = mask * (1.0 - alpha) + weakMask * alpha; gl_FragColor = tempColor; } 复制代码
最终效果:
GLKit实现代码
设置图层
//1.新建图层 - (void)setupContext { //1.新建OpenGL ES上下文 self.mContext = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2]; GLKView *view = (GLKView *)self.view; view.context = self.mContext; view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; view.drawableDepthFormat = GLKViewDrawableDepthFormat24; [EAGLContext setCurrentContext:self.mContext]; glEnable(GL_DEPTH_TEST); } 复制代码
渲染图形
//2.渲染图形 - (void)render { //1.顶点数据 // 顶点数组 前3顶点值(x,y,z),后3位颜色值(RGB) 后2位纹理坐标 GLfloat attrArr[] = { -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, //左上0 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, //右上1 0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, //右下2 -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, //左下3 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, //顶点4 }; //2.绘图索引 GLuint indices[] = { 0, 1, 2, 0, 2, 3, 0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0, }; //顶点个数 self.count = sizeof(indices) /sizeof(GLuint); //将顶点数组放入数组缓冲区中 GL_ARRAY_BUFFER GLuint buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW); //将索引数组存储到索引缓冲区 GL_ELEMENT_ARRAY_BUFFER GLuint index; glGenBuffers(1, &index); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //使用顶点数据 glEnableVertexAttribArray(GLKVertexAttribPosition); glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, NULL); //使用颜色数据 glEnableVertexAttribArray(GLKVertexAttribColor); glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 3); //使用纹理数据 glEnableVertexAttribArray(GLKVertexAttribTexCoord0); glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL + 6); //获取纹理路径 NSString *filePath = [[NSBundle mainBundle]pathForResource:@"timg" ofType:@"jpeg"]; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@"1",GLKTextureLoaderOriginBottomLeft, nil]; GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil]; //着色器 self.mEffect = [[GLKBaseEffect alloc]init]; self.mEffect.texture2d0.enabled = GL_TRUE; self.mEffect.texture2d0.name = textureInfo.name; //投影视图 CGSize size = self.view.bounds.size; float aspect = fabs(size.width / size.height); GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 1000.f); self.mEffect.transform.projectionMatrix = projectionMatrix; //模型视图 GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -3.0f); self.mEffect.transform.modelviewMatrix = modelViewMatrix; //定时器 double seconds = 0.1; timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC, 0.0); dispatch_source_set_event_handler(timer, ^{ self.XDegree += 0.1f * self.XB; self.YDegree += 0.1f * self.YB; self.ZDegree += 0.1f * self.ZB ; }); dispatch_resume(timer); } 复制代码
场景更新
- (void)update { GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -3.0f); modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.XDegree); modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, self.YDegree); modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, self.ZDegree); self.mEffect.transform.modelviewMatrix = modelViewMatrix; } 复制代码
绘制
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { glClearColor(0.3f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); [self.mEffect prepareToDraw]; glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0); } 复制代码
最终实现效果:
该方法实现的代码,后面整理好之后,也会上传一份demo给大家参考。
以上所述就是小编给大家介绍的《OpenGL ES入门: 渲染金字塔 - 颜色、纹理、纹理与颜色混合填充以及GLKit实现》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。