[WebGL入门]二十四,补色着色

翻译 2014年10月11日 21:55:59

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正。



本次的demo的运行结果

着色方法

上次介绍了反射光,反射光是实现光泽的不可缺少的概念,到此为止,基本的光照效果都已经封装完毕了。
光照的效果主要就是扩散光,环境光和反射光三种方法,灵活运用这三种光照,应该就能实现非常逼真的照明效果了。
前几篇一直在说光照,这次稍微换个视点,看一下着色,着色是一个比较大的话题,这次讲一下高氏着色和补色着色。

高氏着色(gouraud shading)

高氏着色从名字上看,是比较难明白具体是什么样的着色的,这个高氏(gouraud)其实是以研究该着色的Henri Gouraud来命名的。

lufy:高氏着色又叫高洛德着色或高氏渲染(Gouraud Shading):这是一种光影渲染技术也是目前较为流行的着色方法,它可对3D模型各顶点的颜色进行平滑、融合处理,将每个多边形上的每个点赋以一组色调值,同时将多边形着上较为顺滑的渐变色,使其外观具有更强烈的实时感和立体动感,不过其着色速度比平面着色慢得多但是效果要好得多。

高氏着色可以对多边形的顶点之间的颜色进行补间,高氏着色的计算负荷并不是太高,但是,可以实现很漂亮的渲染,所以经常被使用。

对顶点间的颜色进行补间是什么意思呢?

简单的说,用高氏着色计算得到的最终的颜色情报,适用于所有顶点,并且对顶点和顶点之间的颜色进行补间处理,最后渲染模型。

使用高氏着色,想用少量的顶点渲染漂亮的光照是很难的。比如说,一个最简单的三角形多边形,三维空间中只有这一个三角形,这个面就直接和光碰撞了。




放射性光源的时候(比如说灯泡),应该是三角形的中心就最亮,而顶点的部分要稍微暗一些,但是高氏着色只是在顶点之间进行颜色补间,所以无法凸显三角形中间的亮点。
另外,因为是根据每个顶点进行颜色补间,颜色变化的时候会出现锯齿。这个锯齿随着顶点数的增多而逐渐消失,但是这么做的话,高氏着色计算负荷小的优势就没有了,所以这是个难处理的地方。

细心的朋友可能会发现,这个网站中所有的demo,都是用的高氏着色。顶点着色器的光的强度和颜色的进行计算,然后只是将最终算出的颜色传给了片段着色器,这种根据每个顶点来计算颜色的方法就是高氏着色。
下面是证据,目前为止的demo中的颜色之间会存在锯齿,会有一些不太自然的镜面反射。


扩大之后看的话就比较清楚了吧,顶点数越少,这种现象就越明显。

补色着色(phong shading)


理解了高氏着色之后,接着看补色着色。
像刚才说的那样,相对高氏着色是对顶点之间的颜色进行补间处理,补色着色是对各个像素进行颜色的补间处理。也就是说,计算量会比高氏着色增大很多,但是可以将渲染出颜色的细节。
补色着色的名字跟高氏着色一样,都是以人名(Bui Tuong Phong)来命名的。使用补色着色的话,会克服高氏着色的弱点,即使顶点数少的时候也能得到很自然的效果。

因为补色着色是在像素之间对颜色进行补间,所以不会发生不自然的锯齿。下面是和高氏着色的渲染效果做比较。

完全是相同的顶点数,相同的光源渲染出的补色着色和高氏着色。左边是补色着色,无论阴影还是高亮的部分,都非常的漂亮和自然。

补色着色的封装

知道了高氏着色和补色着色两者之间的不同,那么就来看看补色着色的封装吧。补色着色就是刚才说的那样,在像素之间进行颜色的补间处理,那么目前为止的在顶点着色器中进行的光照处理,全部要交给片段着色器。
具体的说,追加一个处理,顶点着色器中的顶点的法线情报用varying变量传给片段着色器,然后其他的光照处理全部移到片段着色器中。
首先看顶点着色器的代码。


>顶点着色器的代码
attribute vec3 position;
attribute vec3 normal;
attribute vec4 color;
uniform   mat4 mvpMatrix;
varying   vec3 vNormal;
varying   vec4 vColor;


void main(void){
    vNormal     = normal;
    vColor      = color;
    gl_Position = mvpMatrix * vec4(position, 1.0);
}

和目前为止的代码不同,新定义了一个叫做vNormal的varying变量,用来将法线情报传给片段着色器。顶点的颜色情报和坐标变换矩阵等地方不用变。
接着是片段着色器。


>片段着色器代码
precision mediump float;


uniform mat4 invMatrix;
uniform vec3 lightDirection;
uniform vec3 eyeDirection;
uniform vec4 ambientColor;
varying vec3 vNormal;
varying vec4 vColor;


void main(void){
    vec3  invLight  = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz;
    vec3  invEye    = normalize(invMatrix * vec4(eyeDirection, 0.0)).xyz;
    vec3  halfLE    = normalize(invLight + invEye);
    float diffuse   = clamp(dot(vNormal, invLight), 0.0, 1.0);
    float specular  = pow(clamp(dot(vNormal, halfLE), 0.0, 1.0), 50.0);
    vec4  destColor = vColor * vec4(vec3(diffuse), 1.0) + vec4(vec3(specular), 1.0) + ambientColor;
    gl_FragColor    = destColor;
}

逆矩阵,光向量,视线向量等一直以来都在顶点着色器中使用的数据,全都移动到片段着色器中来了。另外,利用刚才在顶点着色器中定义的varying变量vNormal进行了计算。计算的方法和以前一样,没有任何改变。就是说,只是把顶点着色器中的处理,放到了片段着色器中而已。
这次的变化,并没有添加新的uniform变量,也就是说,javascript部分基本上不用变。
简单的来说,高氏着色和补色着色的主要区别就在于,根据顶点处理还是根据像素处理,虽然这么说跟定义相比有些奇怪,但是这么理解的话也没什么错。


总结

这一次分别说了高氏着色和补色着色两种着色,高氏着色的优点是计算量比较低,而和补色着色相比的话,渲染效果不太自然。
补色着色正好相反,计算量很高,但是渲染效果非常完美。
到底选择那种方法,取决于模型的顶点数和需要的渲染效果,以及执行环境能够承受的计算负荷。
实际应用中,根据利用的场景和描画的模型,分别使用不同的方法是非常重要的。
这次也准备了demo,急着看运行效果的人可以点击文章最后的链接来测试。

另外,补充一点,这次的demo中对圆环体的生成函数做了几处修改,返回值是以对象的形势返回的,可以指定圆环体的颜色了。其实,也并没有做什么其他特别的处理。


下次,介绍一下电光源。

用补色着色来渲染的圆环体

http://wgld.org/s/sample_012/


转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

WebGL风向图

前面关于webgl的基本知识点就没翻译,原文地址概述制作风向图通常步骤 1. 在屏幕上生成一系列随机粒子位置并绘制粒子。 2. 对于每一个粒子,查询风数据以获得其当前位置的粒子速度,并相应地移动它...
  • u013929284
  • u013929284
  • 2017-08-06 18:22:29
  • 995

五、WebGL入门,shader剖析

WebGL用的shader语言是glsl(OpenGL Shading Language), shader的主要工作有: 1. 利用视图和投影矩阵对点的位置进行变化 2. 如果需要利用法线的时候...
  • a23366192007
  • a23366192007
  • 2016-01-20 19:41:46
  • 2634

[WebGL入门]二十一,从平行光源发出的光

写的太长了,果然,就算是简单点说,关于光的处理也需要很长的描述。 重点是,3D渲染中没有办法完全模拟现实中的光,只是大致是那么回事而已。 完全模拟自然界的物理学的话,计算量是非常大的,所以代替这些的就...
  • lufy_Legend
  • lufy_Legend
  • 2014-08-28 23:40:53
  • 7993

WebGL入门 颜色与纹理

第五章 颜色与纹理 gl.vertexAttribPointer()的步进和偏移参数 var VSHADER_SOURCE = 'attribute vec4 a_Posit...
  • u012041225
  • u012041225
  • 2016-11-15 23:28:21
  • 307

09 WebGL通过uniform变量修改点的颜色

上一节通过点击绘制点,这一节接着上一节来修改颜色,到这一节关于点的就写完了。案例查看地址:点击这里<!doctype html> <html> ...
  • qq_30100043
  • qq_30100043
  • 2017-05-04 22:43:33
  • 892

[WebGL入门]十五,为多边形涂抹颜色(顶点颜色的指定)

与上一篇的内容相比的变更点。主要就是着色器和VBO周围的处理有了些小变化。如果再给顶点增加其他新的属性的话,就依葫芦画瓢,像本次的内容一样,按照同样的步骤,再重复一遍就可以了,这样就可以给顶点自由的添...
  • lufy_Legend
  • lufy_Legend
  • 2014-08-09 22:56:26
  • 6810

利用Opencv进行图像灰度变换处理

1、利用 OpenCV 读取图像。 具体内容:用打开 OpenCV 打开图像,并在窗口中显示 2、灰度图像二值化处理 具体内容:设置并调整阈值对图像进行二值化处理。 3、灰度图像的对数变换 具体内容:...
  • caiwencongwyj
  • caiwencongwyj
  • 2015-04-14 21:40:33
  • 3521

Android 实现颜色渐变的一个小 tip

价值 | 思考 | 共鸣 简评:TL;DR: 如果要实现某个颜色到透明的渐变时,记得不要改动颜色的 RGB 值。 Tip: 如果你想要创建从某个颜色到透明的渐变(gradient)背景...
  • IaC743nj0b
  • IaC743nj0b
  • 2017-11-06 00:00:00
  • 135

如何实现TWaver 3D颜色渐变

一般而言,需要实现3D物体的渐变,通常的思路就是通过2D绘制一张渐变canvas图片作为3D对象的贴图,这种方式是可以解决这类问题的,不过对于一般用户而言,通过2D生成一张渐变的图片,有一定的难度,另...
  • twaver
  • twaver
  • 2014-10-21 13:35:06
  • 1111

30 WebGL光照的概念

光照原理: 现实世界中的物体呗光纤照射时,会反射一部分光。只有当反射光纤进入你的眼睛时,你才能够看到物体并辨认出它的颜色。比如,白色的盒子会反射白光,当白光进入你的眼睛时,你才能看到盒子是白色的。 在...
  • qq_30100043
  • qq_30100043
  • 2017-06-05 10:42:44
  • 610
收藏助手
不良信息举报
您举报文章:[WebGL入门]二十四,补色着色
举报原因:
原因补充:

(最多只允许输入30个字)