1 为什么需要Hemisphere Lighting?
我们通过观察现实世界中光的各种呈现形式,在计算机图形学中我们也模拟了各种光源效果,比如方向光、点光源、聚光灯、区域光、环境光等等,这些都是在图形学中比较传统的照明模型。在一些比较基础的照明模型中,环境光常常使用一种简单的偏黄色的颜色代替,但是现实世界中的环境光并不能使用一种简单的颜色来表示。
真实世界中的环境光(模拟太阳光照射到物体)其实更像是从一个穹顶射到物体,射到地面上的光再反射到物体上。正需要这种更加真实的模拟环境光,所以才提出了Hemisphere Lighting(半球光)。
2 Hemisphere Lighting 半球光
半球光照明建模为两个半球,上半球代表天空,下半球代表地面,两个半球分别选择合适的光照颜色,物体表面法向量向上的从上半球获得照明,物体表面法向量向下的从下半球获得照明,如下图所示。
上图中球顶部的点(黑色x)接收来自上半球天空的照明(使用天空的颜色做计算);球底部的点(白色x)接收来自下半球的照明(使用地面的颜色做计算);而球中间的位置则接收一般来自天空的光照,一半接收来自地面的光照(使用50%的天空颜色和50%的地面颜色做计算)。
物体表面任何一点的颜色可通过以下公式计算:
其中,
a = 1.0 - (0.5\cdot \sin (\theta ) ), \theta \le 90^{\circ} \\
a = 0.5 \cdot \cos (\theta ),\theta \ge 90^{\circ} \\
\end{array}
\theta为法线与光源入射方向的夹角,如下图所示。
我们可以使用更简单但是结果差不多的方法计算a
这种简单的方法不需要再判断\theta的大小就可以直接计算a。
上述两种a的函数曲线如下:
两条曲线的形状相似,曲线下方的面积差不多相同,第二种简易方法的着色器更加简单,执行速度更快,但是能获得近似的效果。
根据上述理论,我们可以实现一个Hemisphere Lighting半球光的顶点着色器,
uniform vec3 LightPosition;
uniform vec3 SkyColor;
uniform vec3 GroundColor;
void main()
{
vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);
vec3 lightVec = normalize(LightPosition - ecPosition);
float costheta = dot(tnorm, lightVec);
float a = 0.5 + 0.5 * costheta;
gl_FrontColor = mix(GroundColor, SkyColor, a);
gl_Position = ftransform();
}
或者更加完整的GLSL计算片段
//hemisphere lighting shader with optional diffuse lighting path
//inputs
attribute vec4 vPosition;
attribute vec3 vNormal;
//outputs
varying vec4 color;
//structs
struct global_ambient
{
vec4 direction; // direction of top colour
vec4 top; // top colour
vec4 bottom; // bottom colour
};
struct _material
{
vec4 diffuse;
};
//uniforms
uniform mat4 p; // perspective matrix
uniform mat4 mv; // modelview matrix
uniform _material material; // material properties
uniform global_ambient global; // global ambient uniform
//globals
vec4 mvPosition; // unprojected vertex position
vec3 N; // fixed surface normal
void main()
{
//Transform the point
mvPosition = mv*vPosition; //mvPosition is used often
gl_Position = p*mvPosition;
//Make sure the normal is actually unit length,
//and isolate the important coordinates
N = normalize((mv*vec4(vNormal,0.0)).xyz);
//Make sure global ambient direction is unit length
vec3 L = normalize(global.direction.xyz);
//Calculate cosine of angle between global ambient direction and normal
float cosTheta = dot(L,N);
//Calculate global ambient colour
float a = 0.5+(0.5*cosTheta);
color = a * global.top * material.diffuse
+ (1.0-a)* global.bottom * material.diffuse;
color.a = 1.0; //Override alpha from light calculations - only needs to be done once
}
更加真实的Hemisphere Lighting的Shader还可参考:https://github.com/hughsk/glsl-hemisphere-light
半球光对于模拟更加真实的环境光非常有效,这种照明模型可以用于预览模型,也可以与传统的照明模型相结合,即在半球光的基础上使用点光源,定向光源,聚光灯等。
参考链接
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:计算机图形学 – Hemisphere Lighting 半球光
原文链接:https://www.stubbornhuang.com/2350/
发布于:2022年09月09日 16:12:14
修改于:2023年06月21日 18:06:03
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
52