范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

一看就懂的OpenGLES教程这或许是你遇过最难画的三角形(五)

  通过阅读本文,你将获得以下收获:
  1.客户端程序使用uniform变量指定颜色值
  2.客户端程序使用顶点属性数组指定图形的渲染颜色
  3.OpenGL es光栅化的插值现象
  天青色等烟雨, 而我在等你
  月色被打捞起, 晕开了结局
  OpenGL ES绘制三角形的博文已经到了第五篇了, 今天也正是要揭开结局——绘制完成之前指定的目标三角形。  上篇回顾
  上一篇文章 已经详细展示了OpenGL如何绘制各种的基本图元。之前定的绘制三角形任务已经完成了绘制,不过万事俱备只欠东风,上一篇里三角形用的是单一颜色 ,而我们一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(一)在指定的三角形终极任务是这样的:
  所以我们还差给三角形上这种渐变色效果 ,一旦加上渐变色效果,那么这个绘制三角形的小系列就剧终了,入门OpenGL es我觉得至少算成功一半了吧。 客户端程序指定渲染颜色
  之前的例子片段着色器都是将颜色写固定在代码中的: FragColor = vec4(1.0,0.5,0.5,1.0);
  这样的话客户端就无权控制绘制的颜色了,显然不符合广大人民群众的需要,从客户端传颜色到着色器中就成了必需项。
  这么传呢? 使用uniform变量传单一颜色值
  之前文章对GLSL的叙述中,我们已经接触过了out、in修饰的变量,那么今天要再认识一个变量修饰符了,名曰:uniform
  "uniform"的英文单词有一致的,统一的意思,在这里也算是描述很精准,它表示在一次渲染中不会被改变的变量,类似Java中的final修饰符。所以相对于之前的out、in修饰的变量,它比较牛逼,它是一个渲染管线中的全局常量。 一般用于储存变换矩阵、光参数和颜色等。
  那么怎么理解渲染管线中的全局常量呢?
  C++音视频学习资料免费获取方法:关注音视频开发T哥  ,+「链接」 即可免费获取2023年最新 C++音视频开发进阶独家免费学习大礼包!
  这里的全局是相对一个渲染阶段的一次着色器执行周期而言的。比如在先前文章的例子中,我们传了三个顶点坐标给着色器的vertex 变量,会导致执行三次顶点着色器代码,三次执行中的vertex 变量值都是不一样的,所以vertex 变量就不是一个全局变量。
  但是对于用uniform 修饰的全局常量来说,在一次渲染中,不管执行多少次着色器代码,它都是同一个值,而且是在整个渲染管线内保持同一个值的。
  之所以uniform 全局常量有这种功能,是因为它是保存在着色器程序对象中的,在硬件上体现在全局数据区中 。 uniform全局常量代码实例
  顶点着色器不用改动:         #version 300 es         layout (location = 0)          in vec4 aPosition;//输入的顶点坐标,会在程序指定layout将数据输入到该字段          void main() {            //直接把传入的坐标值作为传入渲染管线。gl_Position是OpenGL内置的表示坐标的变量             gl_Position = aPosition;                        }"
  对于片段着色器来说,新增一个uniform变量 uTextColor,类型为vec4,用来接收客户端程序传入的颜色值:         #version 300 es         precision mediump float;          uniform vec4 uTextColor;//输出的颜色         out vec4 FragColor;          void main() {             FragColor = uTextColor;         };
  对了,因为uniform独特的全局地位,所以客户端程序传值的时候并不用从渲染管线头部开始传 ,而是直接一步到位将数据丢给uniform变量 ,所谓可以直捣黄龙: static float color[] = {         //表示RGBA         0.0f, 1.0f, 0.0f,1.0f };  //获取到uTextColor在着色器程序中的location int colorLocation = glGetUniformLocation(program, "uTextColor"); //通过location去传入一个color向量 glUniform4fv(colorLocation,1, color);
  这里首先还是熟悉的老套路,欲得到一个变量的修改权,必先拿到它的location ,location就是它的引用,这也是OpenGL惯用的套路,拿到引用后,再通过修改方法就可以给其赋值。
  这里通过glGetUniformLocation 方法拿到location ,然后通过glUniform4fv 方法来修改。
  glUniform4fv 是OpenGL中对uniform变量赋值全家桶 的其中一个方法,最后的v表示uniform变量类型为向量vec ,对于全家桶中修改向量的方法系列,其基本格式为: glUniform + n维向量 + 向量元素数据类型 + v
  (glUniform*系列方法详细可见官方文档:registry.khronos.org/OpenGL-Refp…)
  着色器中的vec变量在客户端程序可以通过数组来表示 ,所以这里传入color数组即可,color数组就是一个rgba的颜色值 。
  运行一下,果然是一个绿油油的三角形:
  使用顶点属性传颜色值
  之前强调过,我们传给顶点着色器的叫做顶点属性数组 ,而不是顶点数组 ,因为顶点坐标是一个属性,那么我们是不是可以添加一个颜色属性呢?
  怎么添加颜色属性呢?
  第一种方式 是增加一个颜色的数组,这样就有两个数组: static float triangleVer[] = {         0.0f, 0.8f, 0.0f,//顶点         -0.8f, -0.8f, 0.0f,//顶点         0.8f, -0.8f, 0.0f,//顶点 };  static float colors[] = {         1.0, 0.0, 0.0,//颜色         0.0, 1.0, 0.0,//颜色         0.0, 0.0, 1.0,//颜色 };
  然后调用2次glVertexAttribPointer方法分别解析这2个数组: //解析顶点坐标数据 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, triangleVer); //解析颜色数据 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 12, colors); //分别打开着色器中layout为0,1的变量开关 glEnableVertexAttribArray(0); glEnableVertexAttribArray(1);
  此时顶点着色器相应地增加一个输入变量aColor来接受颜色属性 ,并且增加一个输出给后面阶段着色器的out变量vTextColor :         #version 300 es         layout (location = 0)          in vec4 aPosition;//输入的顶点坐标,会在程序指定layout将数据输入到该字段                  layout (location = 1)           in vec4 aColor;//输入的顶点的颜色                  out vec4 vTextColor;//输出的颜色          void main() {            //直接把传入的坐标值作为传入渲染管线。gl_Position是OpenGL内置的表示坐标的变量             gl_Position = aPosition;                //颜色传给下一个阶段             vTextColor = aColor;          }
  片段着色器代码如下所示,关键是定义一个接受上个阶段输入的颜色的in修饰的上个阶段着色器同名的变量vTextColor :        #version 300 es        precision mediump float;        out vec4 FragColor;                in vec4 vTextColor;//从上个阶段输入的颜色          void main() {            //输入的颜色给当前片段赋颜色值            FragColor = vTextColor;          }
  简单来说,就是在流水线上,前面工序的工人吼一声,后面拥有vTextColor盒子(变量)的工序的人记得接住我这里的vTextColor物料(变量值) 。
  这种方式没问题,但是每次增加一个属性就要增加一个数组 ,显示不符合资深程序员的身份。于是乎第二种方式 更加科学一些,这个方法可以叫做见缝插针法,在每个顶点坐标中间插一个rgb的颜色值 : static float triangleVerWithColor[] = {         0.0f, 0.8f, 0.0f,//顶点         1.0, 0.0, 0.0,//颜色                  -0.8f, -0.8f, 0.0f,//顶点         0.0, 1.0, 0.0,//颜色                  0.8f, -0.8f, 0.0f,//顶点         0.0, 0.0, 1.0,//颜色 };
  这样子依旧是三个顶点,但是每个顶点分别有两个属性:坐标和颜色 ,这样子的好处是无论多少个属性,都可以用一个顶点属性数组解决 。
  解析逻辑要怎么调整呢? //解析顶点坐标数据 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, triangleVerWithColor); //解析颜色数据 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, triangleVerWithColor + 3); //分别打开着色器中layout为0,1的变量开关 glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); 复制代码
  在一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(二) 中的传递数据给着色器 章节曾分析过glVertexAttribPointer方法是如何解析顶点属性数组的,那么现在多了一个颜色属性,解析顶点属性就变成:
  顶点属性数组每3个元素为一个顶点坐标 ,从数组的第0个元素 开始取,每间隔4*6 (一个float4个字节,一个顶点开头到下一个顶点开头距离6个浮点数)取一次。 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, triangleVerWithColor);
  这是原来只有坐标属性的顶点属性数组:
  那么接下来取颜色属性就依葫芦画瓢即可:
  顶点属性数组每3个元素 为一个顶点颜色值,从数组的第4个元素(注意数组地址偏移+3) 开始取,每间隔4*6 (一个float4个字节,一个顶点开头到下一个顶点开头距离6个浮点数)取一次。 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, triangleVerWithColor + 3);
  如今添加了颜色属性,于是数组摇身一变:
  而客户端程序,就是要把这个结构清晰地告诉给OpenGL ,而具体的表达方法,就是通过glVertexAttribPointer 方法。总之,你要玩几个数组随你,但是要明确告诉OpenGL怎么解析即可~
  一切貌似很顺利,不过聪明的你可能已经觉察到了一丝不对劲……
  按照如上做法,也不过每个顶点传了一个颜色属性 ,一个三角形像素那么多,你只给顶点传了颜色,其他点咋整啊?
  管那么多,先运行看看效果~
  这不就是一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(一) 里面提到的绘制三角形的任务的终极目标么。
  但是这种有点酷毙的渐变颜色是怎么形成的呢?光栅化的插值现象
  不知各位记得不,在 一看就懂的OpenGL ES教程——这或许是你遇过最难画的三角形(三) 中,我曾埋过一个小小的彩蛋:
  每个光栅化产生的片段,会携带位置信息 ,以及顶点着色器产生的数据的插值信息 。
  这里的插值信息 如何理解?
  我们在看下这张经典的图形渲染管线图:
  在光栅化中,光栅化器将装配好的图元切成一个个片段,但是我们在外部传入的是顶点属性,但是这些属性往往不是只有顶点才需要的,而是每个片段都需要的,那么光栅化器是如何把这些属性带给每个片段呢?答案便是:线性插值大法 。
  【文章福利】 免费领取 更多 音视频学习资料包 、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hlsrtsp ffplay srs 等等)有需要的可以点击「链接」加君羊领取哦~
  线段的线性插值
  让我们再回到线段的绘制,只是这次改用类似上面的方式给线段2个顶点传入不同的颜色值,比如左边红色(1.0, 0.0, 0.0),右边为蓝色(0.0, 0.0, 1.0),绘制出来的线段如下图所示:
  通过线段,能够比较明显看出颜色渐变的规律了。 左端最红,然后从左往右逐步蓝色化,直到最右最蓝。
  聪明的你可能可以看出是呈现线性变化的,那么用数学语言表示即为:
  假如线段上的某个点距离左端点的距离占线段长度比例为a,距离右端点的距离占线段长度比例为b,且左端点的属性为r,右端点属性为g,则该点上的属性c为: c = r*a + g*b
  在上面的例子中,对于线段中点来说,它的颜色便是: (1.0, 0.0, 0.0)*0.5 + (0.0, 0.0, 1.0)*0.5 = (0.5,0.0,0.5)三角形的线性插值
  对于三角形来说,同理,只是它不再是看距离,而是看面积占比 。
  假如当前点如图所示,Aa,Ab,Ac分别为该点和其他另外2个点连成的三角形面积,则比例系数分别为:
  则对于该点来说,它的某个属性值为三个顶点该属性的线性插值:
  按照这个公式,则我们上面绘制的三角形内部的中心点颜色值为: (1.0, 0.0, 0.0)*0.5 + (0.0, 1.0, 0.0)*0.5 + (0.0, 0.0, 1.0)*0.5 = (0.5,0.5,0.5)
  加餐:如何证明片段着色器每个片段执行一次?
  这个结论其实在之前的博文已经讲过,不过如何去证明呢?
  经过上文描述的线性插值,我们直到了所有顶点属性都会在光栅化阶段被线性插值处理,那么定带你坐标自然也会被处理,处理之后的结果是每个片段上的获取到的坐标就是它的中心点的坐标 。所以将顶点坐标作为一个out类型变量传给片段着色器,那么片段片段着色器拿到的就是当前片段的坐标点 。
  那么如果这里突发奇想,将坐标值作为颜色值赋值给片段颜色,那么如果显示的颜色和对应坐标的一一对应的,就能说明片段着色器是每个片段执行一次 。
  修改顶点着色器代码如下所示:
  顶点着色器:          #version 300 es                 layout (location = 0)                  in vec4 aPosition;//输入的顶点坐标,会在程序指定将数据输入到该字段                         out vec4 vTextColor;//输出的颜色                  out vec4 vPosition;//输出的坐标                          void main() {                    //直接把传入的坐标值作为传入渲染管线。gl_Position是OpenGL内置的                     gl_Position = aPosition;                     //把坐标输出给片段着色器                     vPosition = aPosition;                                  };   #version 300 es   precision  mediump float;    in vec4 vTextColor;//输入的颜色   out vec4 FragColor;//最终的片段颜色    in vec4 vPosition;//输入的坐标,注意这里得到的是顶点的坐标插值的结果,即当前片段的坐标值    void main() {        //确定当前片段颜色,这里设置为传入的坐标值        FragColor = vec4(vPosition.x ,vPosition.y ,vPosition.z,1.0);   };
  因为是作为颜色值,所以就都传入正数的坐标,为了控制变量使得观察方便,所以蓝色分量设置为0: static float triangleVer[] = {        0.8f, 0.0f, 0.0f,        0.0f, 0.0f, 0.0f,        0.0f, 0.8f, 0.0f,  };
  再次敲黑板,这里最需要注意的点,就是顶点着色器传过来的vPosition变量是经过光栅化线性插值过的,所以拿到的是当前片段的坐标,而不是三个顶点的坐标(当然三个顶点所在的片段拿到的就是对应顶点的坐标)。
  运行结果:
  又是一个渐变色的三角形映入眼帘。我们细细观察一下,可以看到越接近(0,0)点的颜色越接近黑色,越接近顶部的点越绿色,因为此时横坐标越接近0,纵坐标越大,所以红色分量越少,绿色分量越大。反之,越靠右的点越红 。
  所以可以证明片段着色器每个片段执行一次!
  总结
  本文主要讲uniform类型变量的特点和使用,以及讲解了OpenGL一个很重要的特性,即光栅化中的线性差值效应,本文终于完成了渐变色三角形的绘制,下一篇文章讲将关注新的内容:一看就懂的OpenGL ES教程——缓冲对象优化程序(一) 代码地址
  opengl-es-study-demo (不断更新中) 参考
  《OpenGL超级宝典》第五版 你好,三角形 Uniform (GLSL)
  作者:半岛铁盒里的猫 链接:https://juejin.cn/post/7145094035521470500 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  在开发的路上你不是一个人,欢迎加入 C++音视频开发交流群大家庭「链接」讨论交流!

俄罗斯导弹打不完?西方发现不对劲,导弹都是最新从流水线拿下来俄乌冲突已经9个月多月了,而在最新一轮的导弹打击当中,俄罗斯发射了超200枚导弹,主要打击了乌克兰境内的基础设施,比如说电力能源等,造成乌克兰的一半能源系统瘫痪,而这也让西方感到震省军区和陆军划清了界限,不承担作战职能,军官不再都是陆军编制在被称为史上最牛军改的本轮军改中,原本由七大军区领导管理的各省军区直辖市警备区基本转隶至中央军委国防动员部,只有新疆军区西藏军区和北京卫戍区是转隶陆军序列,而这也充分说明庞大的省军日常生活中咋消毒?这些坑别踩天气转冷,传染疾病高发。谁家都有老人和孩子,为了家人健康,无论是病愈之后还是防患于未然,消消毒总没坏处。不过市健康管理协会专家高贡提示,日常生活中,一些消毒误区要避免。酒精消毒时注禁欲高冷傅家公子VS美艳撩人富家千金第一章六月底。深夜。一场大雨转到大暴雨,豆子般的雨滴哗啦啦,暴力又有节奏的从天空砸下来,砸落到地面上,废弃的工厂房屋上,还有车顶上。天地间,连接成昏暗的一个颜色。江晚柠被困在车里,产业观察牵头成立全球云网宽带产业协会中国电信携手助力数字化转型全球宽带产业发展再现重磅事件。近日,全球首个云和宽带产业发展的国际组织全球云网宽带产业协会(WBBA)在京召开正式成立发布会。包括中国电信华为诺基亚等11家企业和机构成为全球云网宽国投瑞银基金王彦杰把握长期趋势布局三大方向数十年国际资本市场沉浮,不徐不疾应对市场风云变幻依托股东优势,进可攻退可守,追求长期业绩。这是国投瑞银基金董事兼总经理王彦杰留给中国证券报记者的最初印象。国投瑞银上海总部的办公室窗聚焦强弱项增强发展动力!深入贯彻落实省委十一届三次全会精神系列谈12月18日云南日报头版刊发评论员文章强弱项增强发展动力深入贯彻落实省委十一届三次全会精神系列谈全文如下省委十一届三次全会明确提出分阶段谋划分步骤实施的3815战略发展目标,为推动宋朝人对科举制到底有多狂热,每人都有一个藏在心中的科举梦引言万般皆下品,惟有读书高,这句话是我们常听的劝学之语,它显然已经不再适合现代社会了,三百六十行,行行出状元才是现代社会真实的写照。不过在宋朝,这句话绝对是所有宋朝人最真实的心理写我莫名其妙的阳了!现已转阴!来听听过来人的肺腑之言哈喽,大家好,好几天没有更新了,还是给大家汇报一下啊。事情是这样子的,12月10日晚上直播完回到家,就开始觉得有点感冒,以为是下播换衣服的时候着凉了,加上那天天气特别的冷,每天也是抖音开始全面封杀,这种网红彻底凉了众所周知,网红为了博流量博出位,干过不少让人瞠目结舌的事情。可大家永远都猜不到,下一次离谱网红能有多离谱。瞧这热搜,标准的社会新闻的标题。点进去一瞬间,眉头就皱起来了。只见视频中多梅西拥有哪些世界杯纪录?决赛他还有多项纪录等待创造决赛是不是我世界杯的最后一战?是的,肯定是。距离下一届还有很长的时间,我不认为我能赶得上。以这种方式结束,是最好的。在打进本届世界杯决赛后,梅西在接受媒体采访时表示。北京时间18日
意甲赛程国米意外没拿下比赛,新闻排名比赛一开始,国际米兰的进攻相当强劲,但拉齐奥的射门却更加危险。第40分钟,拉齐奥率先破门,萨维奇长传进入禁区,国米防守不慎,费利佩安德森禁区前稍稍头球破门,10。下半场第51分钟,2022年羽毛球世锦赛决赛赛程中国队员争取勇夺三金2022年8月28日(星期天)下午1420分,争夺金牌决赛开打!中国女双陈清晨贾一凡世界排名第一。韩国这对组合世界排名第四。双方交手记录73。中国选手占优!日本山口茜女子单打世界排坦克世界WCL总决赛迎来捧杯时刻!黄金59限时售卖开启坦克世界作为国产战争策略网游的顶尖之作,已经陪伴玩家们走过了12个春秋,值此周年庆典活动之际,坦克世界推出了一系列福利大派送活动,参与活动即可免费领取奖励,而恰逢WCL夏季赛总决赛中国女排大心脏!252有望逆转晋级决赛匡琦调整见效2022女排亚洲杯半决赛,中国队对阵泰国队,第一局中国队1925输掉,不过第二局中国队2520拿下,拒绝大比分02落后,真是大心脏表现,中国队有望逆转晋级决赛,不得不说第二局匡琦的锁定坦克世界WCL总决赛,黄金59式限时售卖再加码八月即将结束,这个月的坦克世界为玩家推出了很多精彩的活动,如反响热烈的国服820周年庆典WCL夏季赛等,传奇坦克黄金59式的限时回归也给玩家们带来了不小的惊喜。WCL夏季赛总决赛冠被驱逐!字母哥也输了!施罗德那么强,为何还在NBA拿不到合同?八分之一决赛输给意大利出局以后,约老师花了10。1万欧元在拍卖会上买下了2匹意大利马,正式开启休假生活。马能不能受得了他的重量,我们不得而知。但或许输球之后,约老师买马匹是没少说如约基奇被淘汰之后,字母哥也被德国队淘汰,这次不是冷门北京时间9月14日,欧洲杯继续,约基奇带领着的球队本来是夺冠大热门球队,但是在八强战之中,意外的爆冷被淘汰,可以说是本届欧洲杯最大的冷门,当然,也在情理之中了,约基奇一气之下,花了欧冠综合拜仁胜巴萨热刺不敌葡体新华社柏林9月13日电(记者刘旸)20222023欧冠足球联赛13日进行7场较量,拜仁慕尼黑主场20击败巴塞罗那,热刺在客场最后时刻崩盘,连丢两球负于葡萄牙体育。拜仁与巴萨比赛上半请签下安东尼!白曼巴恳求绿军,老詹说得对,他曾是湖人救世主在杜兰特决定留在篮网后,各队终于开始签约自由人。不过令人费解的是,安东尼至今都没有球队签约。在此前曾有消息称,篮网有意安东尼。可最终篮网辟谣,自己对安东尼和霍华德都不感兴趣。之后则王楚钦被打压!因刘国正遭国乒冷遇,刘国梁不出手重演孙颖莎悲剧王楚钦现状不应该被忽视!2022年的成都世乒赛即将开打,国乒的10人大名单也已经确定,通过附加赛晋级的林高远和陈幸同搭上了末班车,获得了最后两个参赛名额,相比较陈幸同的颇费周折,林晚上7点,CBA广东队更新最新18人名单,新赛季目标冲第12冠军头条创作挑战赛CBA广东队新赛季的18名球员大名单已经出炉了。新赛季除了大外援。周鹏威姆斯汤杰还有苏伟离队之后,广东队的新赛季基本没有任何的变动,马尚布鲁克斯归队,正茂周新加入广东