《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》——6.5节光照的每顶点计算与每片元计算...

本节书摘来自异步社区《OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例》一书中的第6章,第6.5节光照的每顶点计算与每片元计算,作者 吴亚峰,更多章节内容可以访问云栖社区“异步社区”公众号查看

6.5 光照的每顶点计算与每片元计算
OpenGL ES 2.0游戏开发(上卷):基础技术和典型案例
细心的读者会发现,本章前面的案例都是在顶点着色器中进行光照计算的。这是由于在顶点着色器中对每个顶点进行光照计算后得到顶点的最终光照强度,再由管线插值后传入片元着色器以计算片元的颜色,这样一方面效率比较高;另一方面产生的光照效果也不错。

但由于这种计算方式插值的是基于顶点计算后的光照强度,因此在要求很高,希望有非常细腻光照效果的场合下就略显粗糙了。本节将介绍另一种光照计算方式,其首先将插值后的法向量数据传入片元着色器,然后在片元着色器中进行光照计算。这种新的方式也称为每片元光照,可以取得为更细腻的光照效果。

进行案例开发之前需要首先了解一下本节两个案例(Sample6_9和Sample6_10)的运行效果,具体情况如图6-21所示。


72fbbe8bc699882a123fe863e061b58255a2a81a

图6-21中左侧是每片元计算一次光照的案例Sample6_9的运行效果,右侧是每顶点计算一次光照的案例Sample6_10的运行效果。从两幅图的对比中可以看出,每片元执行一次光照使过渡更平滑,没有明显的边缘。另外,仅从图上观察可能区别还不是很明显,笔者建议读者用真机运行一下两个案例,将光源设置在不同的位置观察比较,区别会更明显。
了解了两个案例的运行效果后,就可以进行开发了。实际上这两个案例主要是将前面6.2.5小节中的案例Sample6_5复制并修改了部分代码而成的。其中Sample6_10仅修改了Java代码中切割球面的角度以及绘制球体的次数,没有本质变化,这里不再赘述,需要的读者请参考随书光盘中的源代码。

而案例Sample6_9除了也进行了Sample6_10的Java代码改动外,还大面积修改了顶点着色器与片元着色器,具体情况如下所列。

(1)首先介绍Sample6_9中修改后的顶点着色器,其具体代码如下。

1  uniform mat4 uMVPMatrix;            //总变换矩阵
2  attribute vec3 aPosition;           //顶点位置
3  attribute vec3 aNormal;            //法向量
4  varying vec3 vPosition;            //用于传递给片元着色器的顶点位置
5  varying vec3 vNormal;              //用于传递给片元着色器的法向量
6  void main(){ 
7    gl_Position = uMVPMatrix * vec4(aPosition,1);//根据总变换矩阵计算此次绘制此顶点位置 
8    vPosition = aPosition;             //将顶点的位置传给片元着色器
9    vNormal = aNormal;               //将法向量传给片元着色器
10  }

从上述代码中可以看出,顶点着色器比改动前简单多了,没有了计算光照的大量代码,同时增加了将法向量通过易变变量传入片元着色器的代码。
(2)介绍完顶点着色器后,接着就应该介绍改动后的片元着色器了,其具体代码如下。

1  precision mediump float;              //给出默认浮点精度
2  uniform float uR;                      //球的半径
3  uniform vec3 uLightLocation;       //光源位置
4  uniform mat4 uMMatrix;           //变换矩阵
5  uniform vec3 uCamera;           //摄像机位置
6  varying vec3 vPosition;          //接收从顶点着色器传递过来的顶点位置
7  varying vec3 vNormal;            //接收从顶点着色器传递过来的法向量
8  void pointLight(              //定位光光照计算的方法
9   in vec3 normal,             //法向量
10   inout vec4 ambient,          //环境光最终强度
11   inout vec4 diffuse,           //散射光最终强度
12   inout vec4 specular,          //镜面光最终强度
13   in vec3 lightLocation,         //光源位置
14   in vec4 lightAmbient,          //环境光强度
15   in vec4 lightDiffuse,          //散射光强度
16   in vec4 lightSpecular          //镜面光强度
17  ){
18   ambient=lightAmbient;          //直接得出环境光的最终强度 
19   vec3 normalTarget=vPosition+normal; //计算变换后的法向量
20   vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(vPosition,1)).xyz;
21   newNormal=normalize(newNormal);    //对法向量规格化
22   //计算从表面点到摄像机的向量
23   vec3 eye= normalize(uCamera-(uMMatrix*vec4(vPosition,1)).xyz); 
24   //计算从表面点到光源位置的向量vp
25   vec3 vp= normalize(lightLocation-(uMMatrix*vec4(vPosition,1)).xyz); 
26   vp=normalize(vp);//格式化vp
27   vec3 halfVector=normalize(vp+eye);  //求视线与光线的半向量  
28   float shininess=50.0;          //粗糙度,越小越光滑
29   float nDotViewPosition=max(0.0,dot(newNormal,vp));//求法向量与vp的点积与0的最大值
30   diffuse=lightDiffuse*nDotViewPosition;        //计算散射光的最终强度
31   float nDotViewHalfVector=dot(newNormal,halfVector);  //法线与半向量的点积 
32   float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess));//镜面反射光强度因子
33   specular=lightSpecular*powerFactor;        //计算镜面光的最终强度
34  }
35  void main() {
36    ……//此处省略了计算片元颜色值的代码,请读者自行查看随书光盘中的源代码  
37    vec4 ambient,diffuse,specular;  //用来接收3个通道最终强度的变量  
38    pointLight(normalize(vNormal),ambient,diffuse,specular,uLightLocation,                          //计算定位光各通道强度 
39    vec4(0.15,0.15,0.15,1.0),vec4(0.8,0.8,0.8,1.0),vec4(0.7,0.7,0.7,1.0));   
40    //综合3个通道光的最终强度及片元的颜色计算出最终片元的颜色并传递给管线
41    gl_FragColor=finalColor*ambient + finalColor*diffuse + finalColor*specular;
42  }

读者应该发现,上述片元着色器中的很多代码都是本章前面案例中多次出现过的,只不过前面的案例中都是在顶点着色器中出现,而这里挪到了片元着色器中。因此,每片元计算光照与每顶点计算光照算法并没有本质区别,只是代码执行的位置不同、效果与效率不同而已。实际开发中读者应该权衡速度、效果的要求,选用合适的计算策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/258987.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Debian上安装配置ownCloud

如何在Debian上安装配置ownCloud 据其官方网站,ownCloud可以让你通过一个Web界面或者WebDAV访问你的文件。它还提供了一个平台,可以轻松地查看、编辑和同步您所有设备的通讯录、日历和书签。尽管ownCloud与广泛使用Dropbox非常相似,但主要区别…

[转]js判断url是否有效

本文转自:http://www.cnblogs.com/fumj/p/3490121.html 方法一:(仅适用于ie) function CheckStatus(url){XMLHTTP new ActiveXObject("Microsoft.XMLHTTP")XMLHTTP.open("HEAD",url,false)XMLHTTP.send()return XMLHTTP.status200}function Ne…

32位md5解密_冰蝎特征检测及报文解密

点击“蓝字”关注我们,不迷路~‍‍前言19年驻场于某金融单位。参加19年9月、11月两次攻防演练,负责攻防演练组织、技术支持和复盘。期间,多个攻击队伍使用冰蝎 webshell ,防守方监测时确实各 IDS 确实报出 webshell 连接&#xff…

《移动App测试的22条军规》—App测试综合案例分析23.13节测试微信App的流量和电量消耗...

本节书摘来自异步社区《移动App测试的22条军规》一书中的App测试综合案例分析,第23.13节测试微信App的流量和电量消耗,作者黄勇,更多章节内容可以访问云栖社区“异步社区”公众号查看。 23.13 测试微信App的流量和电量消耗关于微信App消耗流…

python做数据可视化的代码_Python数据可视化正态分布简单分析及实现代码

Python说来简单也简单,但是也不简单,尤其是再跟高数结合起来的时候。。。 正态分布(Normaldistribution),也称“常态分布”,又名高斯分布(Gaussiandistribution),最早由A…

wpf window 不执行show 就不能load执行_Numpy反序列化命令执行漏洞分析(CVE-2019-6446)附0day...

1、介绍 NumPy 是 Python 机器学习库中之一,主要对于多为数组执行计算。NumPy 提供大量的 函数和操作,能够帮助程序员便利进行数值计算。在 NumPy 1.16.0 版本之前存在反序列化 命令执行漏洞,用户加载恶意的数据源造成命令执行。2、环境 软件…

使用Def文件导出dll

前面我们介绍了dll的生成,大多数是使用extern "C"__declspec(dllexport)函数名的方法导出dll。其实我们还有另一种方法来导出dll。 先介绍参考文献: 1.dll导出声明相关 2.VS2012中 C创建DLL图解 3.DLL中导出函数的两种方式(dllexport与.…

XML语法学习

本文章集合两篇博文而写&#xff0c;两篇博文地址&#xff1a; XML学习总结(二)——XML入门&#xff1a; XML基础<第一篇> XML简介 XML是一种标记语言&#xff0c;用于描述数据&#xff0c;它提供一种标准化的方式来来表示文本数据。XML文档以.xml为后缀。需要彻底注…

FM实现F4帮助系列三:弹出框多筛选…

FM实现F4帮助系列三&#xff1a;弹出框多筛选条件的搜索帮助&#xff08;根据搜索帮助筛选字段&#xff09;函数&#xff1a;F4IF_GET_SHLP_DESCRF4IF_START_VALUE_REQUEST效果图&#xff1a;本例子代码&#xff1a;找到需要的帮助:*&------------------------------------…

《计算复杂性:现代方法》——0.2 判定问题/语言

本节书摘来自华章计算机《计算复杂性&#xff1a;现代方法》一书中的第0章&#xff0c;第0.2节&#xff0c;作者 &#xff3b;美&#xff3d;桑杰夫阿罗拉&#xff08;Sanjeev Arora&#xff09;&#xff0c;博阿兹巴拉克&#xff08;Boaz Barak&#xff09;&#xff0c;译 骆吉…

python从date目录导入数据集_使用python划分数据集

无论是训练机器学习或是深度学习&#xff0c;第一步当然是先划分数据集啦&#xff0c;今天小白整理了一些划分数据集的方法&#xff0c;希望大佬们多多指教啊&#xff0c;嘻嘻~ 首先看一下数据集的样子&#xff0c;flower_data文件夹下有四个文件夹&#xff0c;每个文件夹表示一…

开源牛人 zcbenz

事情是这样的&#xff0c;微软推出了Visual Studio Code&#xff0c;我很好奇他怎么做跨平台的&#xff0c;所以就找找资料&#xff0c;在他的网站中是这么描述的&#xff1a; Architecturally, Visual Studio Code combines the best of web, native, and language-specific t…

eclipse 与 tomcat 的那些路径

我们用mvn创建了一个web工程&#xff0c;同时希望在eclipse里调试开发。mvn有mvn的路径要求&#xff0c;eclispe有eclipse的默认路径&#xff0c;怎么整合二者&#xff1f; 首先介绍一下eclipse的默认路径。 重点在Server Locations里面。 下面我们把[workspace]/.metadata\.pl…

python数据处理常用函数_pandas数据分析常用函数总结大全:上篇

基础知识在数据分析中就像是九阳神功&#xff0c;熟练的掌握&#xff0c;加以运用&#xff0c;就可以练就深厚的内力&#xff0c;成为绝顶高手自然不在话下&#xff01; 为了更好地学习数据分析&#xff0c;我对于数据分析中pandas这一模块里面常用的函数进行了总结。整篇总结&…

从运维角度浅谈MySQL数据库优化

一个成熟的数据库架构并不是一开始设计就具备高可用、高伸缩等特性的&#xff0c;它是随着用户量的增加&#xff0c;基础架构才逐渐完善。这篇博文主要谈MySQL数据库发展周期中所面临的问题及优化方案&#xff0c;暂且抛开前端应用不说&#xff0c;大致分为以下五个阶段&#x…

c语言c99标准_自学C语言之一

上次自学C语言还是在刚开学到国庆期间&#xff0c;听学姐的建议买了本C语言的书&#xff0c;在军训期间的晚上翻翻看看。后来选课、开始正式上课、面试社团、开各种会等等&#xff0c;好像每天都有许多事要忙&#xff0c;但又没忙出来什么结果&#xff0c;慢慢地好像就把C语言放…

Font Rending 的 Hint 机制对排版的影响

Font Rending 的 Hint 机制对排版的影响【转】 在设计一种 Font 时&#xff0c;设计者使用的是一个抽象的单位&#xff0c;叫做 EM&#xff0c;来源于大写 M 的宽度&#xff08;通常英文字体中大写 M 的宽度最大&#xff09;。EM 即不同于在屏幕显示时用的像素&#xff08;Pixe…

《SQL初学者指南(第2版)》——2.4 指定列

本节书摘来自异步社区出版社《SQL初学者指南&#xff08;第2版&#xff09;》一书中的第2章&#xff0c;第2.4节&#xff0c;作者&#xff1a;【美】Larry Rockoff&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 2.4 指定列 到目前为止&#xff0c;我们只…

《PowerShell V3——SQL Server 2012数据库自动化运维权威指南》——2.13 创建视图...

本节书摘来自异步社区出版社《PowerShell V3—SQL Server 2012数据库自动化运维权威指南》一书中的第2章&#xff0c;第2.13节&#xff0c;作者&#xff1a;【加拿大】Donabel Santos&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 2.13 创建视图 本方案展…

python刷抖音_用Python生成抖音字符视频!

抖音字符视频在去年火过一段时间。 反正我是始终忘不了那段极乐净土的音乐... 这一次自己也来实现一波&#xff0c;做一个字符视频出来。 主要用到的库有cv2&#xff0c;pillow库。 原视频如下&#xff0c;直接抖音下载的&#xff0c;妥妥的水印。 不过并不影响本次的操作。 / …