在 上一篇文章,我们讨论了光效的设定以及光效的各种属性。我们还讨论了光的三要素:散射光环境光 和高光。如果你还不是完全清楚,那么我们来复习一下,在定义材质时大量的用到这些要素。

 

作为本文的起点,我们使用了原文中球体绘制 的项目文件。我们不再使用二十面体而是转向球体是因为球体是展示光和材质不同要素之间相互作用的最佳形状。

颜色是什么

这可能是对小学美术课的复习。为什么现实世界会有颜色?是什么造成的?

我们看得见的光被称为 光的可见频谱 。根据不同的波长我们可以感知到不同的颜色。在可见光谱的一端是低波长高频率的紫色和蓝色,而在另一端是低频高波长的橘色和红色:

电磁波在这个范围之外,因此不是“可见光”,尽管这只是人工的区分方法,它们的唯一不同在频率和波长,在于人眼的感知。尽管有各种方法感知各种电磁波的能力,但从OpenGL的角度出发,我们只关心可见光谱。

“白色光”包括等量的所有波长。换言之,白光之所以是白色的是因为它包括了所有(或至少大部分)可见光的频率。如果你曾经做过棱镜试验,那么你可能看过如下效果:

棱镜反射白光,各种波长被分离出来。这就是彩虹产生的原理。

如果你看到一个物体呈蓝色,那么实际上是该物体吸收了大部分可见光谱低频部分。它吸收了红,橘,黄和绿光。根据蓝色的不同色度,它还可能吸收一些紫色和蓝色。

但大部分蓝色的波长都被反射到你的眼睛。因为一些可见光被吸收了,由于它不再包括可见光谱中的所有波长所以反射到你眼中的光不再是白色。

简单吧?让我们看看这些是怎样运用在OpenGL的。

OpenGL 材质

我们通过定义材质的反射光来定义OpenGL ES中的材质,正如现实世界中一样。如果一个材质定义为反射红光,那么在正常的白光下,它将显示红色。

在OpenGL中 (至少在使用光滑着色处理和光效时),材质是没有颜色的。OpenGL具有分别定义材质是怎样反射OpenGL光效三要素(环境,散射和高光)的能力。另外,它还具有指定材质 自发光(emissive) 属性的能力,关于这点我们稍后再讨论。

指定材质

要在OpenGL创建一个材质,我们需要一次或多次调用 glMaterialf() 或者 glMaterialfv()。类似于上一篇文章中光效的定义,由于各属性或元素需要分别通过这些调用了指定,所以我们通常必须多次调用这些函数以完全定义材质。所有未定义的元素或属性默认值为0,或者以颜色来说为黑色。

传递给 glMaterialf() 或者 glMaterialfv() 的第一个参数总是用于指定是否材质影响多边形的前,后或两者的GL_ENUM。实际上除了为了与OpenGL兼容,第一个参数在OpenGL ES中没有什么意义,因为只有一个有效的选项: GL_FRONT_AND_BACK,它简单地表示材质适用于任何绘制的多边形。如果你还记得第一部分,那么你应该知道三角形的正面和背面是由winding(顶点的绘制次序)决定的。默认情况下,只有三角形的正面被绘制出来,但是有可能让OpenGL也绘制背面,或甚至只绘制背面,常规 OpenGL 允许你通过传递GL_FRONT,GL_BACK, 或者 GL_FRONT_AND_BACK来为正面和背面指定不同的材质。但是OpenGL ES仅支持GL_FRONT_AND_BACK。

glMaterialf() 或 glMaterialfv()的第二个参数是指示正在设定材质的哪个元素或属性的 GL_ENUM。它们像传递给glLightfv()的值一样,比如 GL_AMBIENT ,另外还有些新的值我们稍后再谈。

最终值是 GL_FLOAT或包括了实际属性或元素的GL_FLOAT数组的指针。

材 质的最重要元素是环境光和散射光,因为它们决定了材质是怎样反射大量光线的。我们今天使用的项目代码定义了正如太阳光或白炽灯产生的白色,它具有平均分布 的各种波长和颜色的光。如果光不是白色,球体看上去会有不同的外观。例如,反射至红色材质的蓝光将产生紫色阴影。简单起见,我们只使用白色光。当然,你可 以随意改变光的颜色进行试验看看光和材质是怎样交互作用的。大部分时候,它们在OpenGL ES中的表示与现实生活中完全一样。

下面是项目在添加材质前运行时的样子:

如你所见,它具有一些环境光和更为显著的散射光。

环境光和散射光

当 讨论OpenGL的材质时,我们需要同时讨论环境光和散射光,这是因为这两个元素是一起工作从而决定物体被感知的颜色的。记住,散射光处于本文第一个图片 中球体的顶部(亮黄色),环境光则是下方的暗黄色。材质怎样反射这两个元素决定了物体被感知的颜色。上图的效果可以通过不止一种方法获得。同样地,黄色球 以同样比例反射环境光和散射光,但是场景中具有较少的环境光。

大约 90% 或更多的情况下,将材质的环境光和散射光参数设定成一样。这样做,使它们成为决定物体阴影和外观的因素。实际上,有一种方法通过一个调用glMaterialfv()同时设定材质环境光和散射光。下面是定义材质为蓝色的示例:

    GLfloat ambientAndDiffuse[] = {0.0, 0.1, 0.9, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, ambientAndDiffuse);

正如 glColor4f(), 设置材质指示随后所有物体绘制的方式直到另一个材质被指定。如果将上叙代码放置于我们的绘制代码之前,那么运行时你将看到球体变为蓝色。由于环境光没有散射光强,其下方只是稍暗。

有时你希望更多地控制并希望分别设定材质对环境光和散射光的反射方式。例如,下例中,材质从环境光反射蓝色,从散射光反射红色:

    GLfloat ambient[] = {0.0, 0.1, 0.9, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);GLfloat diffuse[] = {0.9, 0.0, 0.1, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);

运行结果:

在此情况下,它看上去像我们投射了有色光到球体上,实际上却不是这样。原因是我们反射了与环境光不一样的定向光线。

大部分情况下,如果你希望产生彩色光的效果,你只需创建彩色光线然后使用GL_AMBIENT_AND_DIFFUSE来指定材质颜色。但是有时却希望分别设置它们产生特殊效果或在不引起创建额外光线开销的情况下假造一个分离的彩色点光源。记住:你每增加一个光源,也就增加了每秒钟的运算量,所以有时候欺骗并不完全是一件坏事。

高光和光泽

你还可以单独设置场景中高光元素的反射方式,从而控制高光“热点”的亮度。一个叫 GL_SHININESS的参数与材质的高光元素一起定义了高光热点的大小。如果你设定了材质的 GL_SPECULAR 值,你还应该定义其反光度。反光度越高,高光反射越小,所以默认值 0.0 几乎完全淹没了散射光,因此看上去很糟糕。

让我们回到蓝色球体,增加高光热点:

    GLfloat ambientAndDiffuse[] = {0.0, 0.1, 0.9, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, ambientAndDiffuse);GLfloat specular[] = {0.3, 0.3, 0.3, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 25.0);

我们使用了一个较暗的白色作为球体的高光值。这个值看上去有些小,但就是这么小的值也能产生显著的效果。光线高光元素的值与材质的高光元素相乘所产生的光集中在材质反光度指定的区域。下面是上叙代码产生的结果:

现在,球体上有一个小的区域具有更强的反射光。我们可以通过增强光或光的高光元素,或者通过增加材质的反光度使这个点更亮。我们还可以通过调整反光度改变高光的大小。材质反光度越高,高光越集中。例如,如果我们将反光度从25.0 改为 50.0,我们将得到一个更小的热点,它使得球体显得更具有光泽。

但是,有一点要小心。本文之所以改为使用球体的部分原因以及为什么球体使用较高的顶点数目的原因是高光在一个低面数的物体上看上去实在糟糕。注意一下,如果我减少球体的顶点数会发生什么:

低面片

高光使三角形边缘突出,高光通常在我们的游戏中经常使用的低面片的物体上表现不佳。在常规OpenGL中,有一个称为 着色器(shader) 的 机制可以用来为低面片物体产生较为理想的结果,但目前iPhone上的OpenGL ES并不支持此功能(译者注:iPhone 3GS支持OpenGL ES 2.0,有shader功能。但有一个问题就是OpenGL ES 1.1与OpenGL ES 2.0并不完全兼容)在游戏中如果你想使低面片物体漂亮的唯一方法就是完全摒弃高光元素而使用纹理映射,这将在下一篇文章中谈到。

自发光

还 剩最后一个材质的重要属性,它称为自发光元素。通过设定自发光元素,使得材质看上去会发射我们指定的颜色。它并不是真正在发光。例如,其周边物体并不会被 发射的光线影响。如果你希望一个物体像灯泡一样发光照亮其他物体,由于在OpenGL ES中只有光源会发光(听上去像废话),你需要将自发光元素和与物体同一位置处的实际光源结合起来。但是自发光元素可以使物体漂亮地发光。

例如,我们可以为蓝色球体添加绿色的光泽:

    GLfloat emission[] = {0.0, 0.4, 0.0, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission);

结果如下:

自发光元素影响整个材质,因此 GL_EMISSION的值将与落入物体指定区域的任何类型的光相叠加。请注意,甚至上图中的高光部分也成了一点蓝-绿色而不是纯白色。在高光点处其效果是很微小的,但在只有环境光被反射的底部效果更为明显。它实际影响整个物体。

转载于:https://www.cnblogs.com/zhoujq/archive/2013/03/15/2961819.html

[转载]从零开始学习OpenGL ES之五 – 材质相关推荐

  1. 从零开始学习OpenGL ES之五 – 材质

    从零开始学习OpenGL ES之五 – 材质 作者: iPhoneGeek 爱疯极客 09-Jan-10 iPhone Development 浏览次数: 411 |  评论 ↓ Tweet Shar ...

  2. [转载]从零开始学习OpenGL ES之八 – 交叉存取顶点数据

    Technote 2230提出了很多用OpenGL ES来提升iphone程序性能的建议.我们现在远远不能深刻理解OpenGL ES所以你需要学习以下内容.不信?是真的,试试看,我等着你的读后感. 好 ...

  3. [转载]从零开始学习OpenGL ES之三 – 透视

    现在你已经知道OpenGL是怎样绘图的了,让我们回头谈谈一个很重要的概念:OpenGL视口(viewport). 许多人对3D编程还很陌生,那些使用过像Maya, Blender, 或 Lightwa ...

  4. 从显示一张图片开始学习OpenGL ES

    前言 网上很多介绍OpenGL ES的文章,但由于OpenGL ES内容太多,所以这些文章难免过于臃肿杂乱,很难抓住重点,对于初学者来说最后还是云里雾里.很多人(包括笔者本人)开始深入了解OpenGL ...

  5. [转载]从零开始学习jQuery (一) 开天辟地入门篇

    一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案,  即使你会使用jQuery也能在阅读中发现些许秘籍. 本篇文章是入门第一篇, 主要是简单介绍jQuer ...

  6. [乐意黎转载]从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件

    从零开始学习jQuery (一) 开天辟地入门篇 从零开始学习jQuery (二) 万能的选择器 从零开始学习jQuery (三) 管理jQuery包装集 从零开始学习jQuery (四) 使用jQu ...

  7. 学习OpenGL ES之透明和混合

    获取示例代码 本文主要讲解OpenGL ES对于透明颜色的处理,在例子中我绘制了三个平面,分别赋予绿色半透明纹理,红色半透明纹理,和不透明纹理. 首先为这三张图生成纹理. - (void)genTex ...

  8. [乐意黎转载]从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式

    一.摘要 本篇文章讲解如何使用jQuery获取和操作元素的属性和CSS样式. 其中DOM属性和元素属性的区分值得大家学习. 二.前言 通过前面几章我们已经能够完全控制jQuery包装集了,  无论是通 ...

  9. [乐意黎转载]从零开始学习jQuery (二) 万能的选择器

    一.摘要 本章讲解jQuery最重要的选择器部分的知识. 有了jQuery的选择器我们几乎可以获取页面上任意的一个或一组对象, 可以明显减轻开发人员的工作量. 二.前言 编写任何javascript程 ...

  10. [乐意黎转载]从零开始学习jQuery (八) 插播:jQuery实施方案

    一.摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案,  即使你会使用jQuery也能在阅读中发现些许秘籍. 本篇文章属于临时插播,  用于介绍我在本公司的j ...

最新文章

  1. android5多窗口,教程 开启 Nexus5 Android M 的多窗口模式。
  2. ASP.NET Ajax替代品AjaxWidgets
  3. 【控制】《多智能体系统的动力学分析与设计》徐光辉老师-第10章-带有分层领航者的多智能体系统的混杂协调
  4. 阿里云容器服务新增支持Kubernetes编排系统,性能重大提升
  5. 权限柜作用_超市条码寄存柜使用要点
  6. android自定义push通知_20个海外Web和App推送通知服务工具
  7. 帮助学生改善学习方法_学生应该如何花费时间改善自己的幸福
  8. LeetCode(40):组合总和 II
  9. linux jzmq编译,Linux下ps aux解释
  10. 55)PHP,在html嵌套PHP写法
  11. 加州理工学院公开课:机器学习与数据挖掘_神经网络
  12. Ubuntu安装RabbitMQ及RabbitMQ基于使用
  13. boost python实现_Boost Python官方样例(一)
  14. unity3d在菜单栏,一键设置Player setting及自动打包并设置apk的存储位置
  15. sfm点云代码_PCL点云显示sfm数据
  16. 三星30pin引脚_USB3.0针脚定义、引脚定义(精校版本)
  17. 2020中国互联网十大人物
  18. 最强大脑记忆曲线(10)—— 信息统计
  19. ChatGPT专业应用:纯英文视频-中英文快速字幕添加
  20. 瑞晟蓝牙来电语音软件下载_语音来电秀app下载-语音来电秀 安卓版v12.6-PC6安卓网...

热门文章

  1. Adobe系列错误代码解决方案汇总
  2. Mac怎么连接多个蓝牙音箱?
  3. 面向对象学习(1):认识软件系统的复杂性
  4. Ubuntu source insight3稳定性
  5. scala 资源 copy 自知乎
  6. 简繁体在线切换JS插件
  7. SQL Server 2008数据库快照技术(八)
  8. 安装win7的小插曲
  9. [VBA]工作需求,写了段VBA。EXCEL的效率很差
  10. [style] visibility