`
yangping_Account
  • 浏览: 191750 次
  • 性别: Icon_minigender_1
  • 来自: 无锡
社区版块
存档分类
最新评论

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

 
阅读更多

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


 

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

 

 

颜色是什么

 

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

 

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

 

电磁波在这个范围之外,因此不是“可见光”,尽管这只是人工的区分方法,它们的唯一不同在频率和波长,在于人眼的感知。尽管有各种方法感知各种电磁波的能力,但从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_FRONTGL_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的值将与落入物体指定区域的任何类型的光相叠加。请注意,甚至上图中的高光部分也成了一点蓝-绿色而不是纯白色。在高光点处其效果是很微小的,但在只有环境光被反射的底部效果更为明显。它实际影响整个物体。

 

分享到:
评论

相关推荐

    从零开始学习OpenGL_ES

    从零开始学习OpenGL_ES 网页文件

    从零开始学习OpenGL ES

    本文将从零开始,详细介绍如何学习OpenGL ES,以及如何利用提供的模板进行快速入门。 首先,我们要理解OpenGL ES的基础概念。OpenGL ES 提供了一个跨平台的编程接口,用于创建2D和3D图形。它包含了一系列函数调用,...

    从零开始学习OpenGL ES中的项目文件

    本教程将从零开始,带你深入理解OpenGL ES项目的构建和运行,帮助你开启图形编程之旅。 在"Empty.OpenGL.ES.Application.zip"这个压缩包中,你可能会找到以下核心文件和目录,它们是构成一个基本OpenGL ES应用的...

    从零开始学习opengl es(iphone)

    iphone上学习opengles的必备资料,完全零基础开始学习

    OpenGL ES 从零开始系列 源码

    泰然论坛翻译的 OpenGL ES 从零开始系列 文章源码,由于是很早之前的,原连接失效了。 找了很久才找到的,是目前最齐全的。总共7个DEMO, 涵盖了总共9章的内容

    OpenglEs从零开始

    OpenGL ES(Open Graphics ...总结而言,学习OpenGL ES从零开始需要掌握其核心概念、数据类型、坐标系统以及对3D图形的处理。在移动和嵌入式平台的应用开发中,这些知识点是构建流畅、高效3D图形应用程序的基础。

    OpenGLES 3.0从零开始,绘制点、线、三角形、立方体,相机实时预览等等实践学习

    OpenGLES 3.0从零开始,绘制点、线、三角形、立方体,相机实时预览等等实践学习 android平台opengles3.0实践学习 android平台下OpenGLES3.0从零开始 android平台下OpenGLES3.0绘制纯色背景 android平台下OpenGLES3.0...

    从零开始学openGL_ES

    学习iphone openGL_ES从这里开始!这是一本关于iphone openGL_ES的入门书,从最基本的开始讲起,只要你看了,那么就能掌握openGL_ES的内容。这真是一本好书,我的openGL_ES就是从这里开始的。(中文版)

    OpenGL ES从入门到精通

    1. "从零开始学习OpenGL+ES"系列:讲解OpenGL ES的基本概念和编程基础。 2. "opengl-es画图步骤":详细介绍OpenGL ES绘制图形的完整流程。 3. "实验6——图形绘制与OpenGL_ES":提供实际的编程练习,加深理论知识的...

    Part5Project Start.zip

    在“从零开始学习OpenGL ES之五 – 材质”这一章节中,我们将深入探讨如何在OpenGL ES中实现球体的绘制以及材质的应用。这个项目文件“Part5ProjectStart.zip”包含了所有必要的源代码和资源,供学习者实践和理解...

    OpenGLES经典教程大全

    教程名称:OpenGL ES经典教程大全课程目录:【】Android应用OpenGLES制作3D图像【技术文档】【】OpenGL ES 2.0 官方手册【】OpenGL ES ...从零开始学习Open 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。

    OpenGLES 2.0 for android 开发教程 从入门到精通和Demo

    本教程旨在帮助开发者从零基础开始掌握OpenGLES 2.0,并通过实例Demo加深理解。 入门篇: 1. **环境配置**:首先,你需要安装Android Studio并创建一个新的Android项目。然后,在项目的build.gradle文件中添加对...

    从零开始android游戏编程 包括源码

    这篇详细的教程将带你从零开始学习Android游戏编程,并提供源码供你参考和实践。我们将会深入探讨以下几个关键知识点: 1. **Android基础知识**:首先,你需要熟悉Android开发环境,包括安装Android Studio、设置...

    西蒙iPhone-OpenGL ES 教程【中文翻译版PDF】

    开发者可以通过这个模板,将重心放在开发应用程序的特定部分,而非从零开始构建基础框架。一旦创建了项目,开发者需要保存它,这是开始任何开发项目的基础步骤。 深度缓冲(Depth Buffer)的概念和启用 教程中提到...

    iphone opengl es开发入门

    为了更好地理解 OpenGL ES 的工作原理,我们将从零开始搭建一个简单的 OpenGL ES 项目。这里以 Xcode 为例: 1. **创建项目**:打开 Xcode,新建一个 Window-based Application 项目,命名为 "HelloOpenGL"。 2. **...

Global site tag (gtag.js) - Google Analytics