版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xyh930929/article/details/83278025
一个模型受光照后最终呈现的颜色,由三种因素决定:光的种类、物体表面的材质。
对以上三种影响因素进行分类:常见的光被分为4种、物体表面的材质通常受3种因素影响(漫反射、镜面反射、表面纹理)。
光的定义有很多参数可以调整,而且一个三维场景中还可以放入很多种类的光、影响材质的漫反射和镜面反射也有很多参数可以调整。所以,最终呈现出的效果是可以有很多种情况的。
4种常见光分别为:
- 环境光:影响因素为强度、颜色。这种类型的光源来自空间中的任何地方,并以相同的方式照亮所有物体。
- 点光源:影响因素为强度、颜色、位置、衰减因素。
- 聚光灯:影响因素为强度、颜色、位置、衰减因素、方向、夹角。(聚光灯就是在点光源的基础之上加上了方向和夹角的概念)
- 方向光:影响因素为颜色、方向、强度。
下面基于joml(Java OpenGL Math Library)对上面的光进行抽象:
在对各种光进行抽象时,有一些属性被定义为向量,有一些属性被定义为float类型的常数,是由于光的数学定义。
-
光的数学定义可以参考这篇文章
WebGL笔记(二)_光 -
关于这些光是如何结合模型顶点和法向量在着色器中进行计算的,参考这篇文章OpenGL中环境光、漫反射、镜面反射对光线的影响
环境光
环境光就是一个三维的向量Vector3f类型的变量,可以直接传给着色器程序。
点光源
public class PointLight {
//点光源的颜色
private Vector3f color;
//点光源的位置
private Vector3f position;
//点光源的强度
private float intensity;
//点光源的衰减
private Attenuation attenuation;
}
//点光源的定义里面提到的光衰减定义:这个对象的三个系数,只是为了着色器中在计算衰减时更加方便和灵活。
//这三个参数完全可以抽象为一个系数,只要着色器算出的最终颜色上乘以该系数即可。
//这只是大多数情况下的光衰减定义。
public static class Attenuation {
//连续系数
private float constant;
//线性系数
private float linear;
//衰减系数
private float exponent;
}
聚光灯
由于聚光灯是基于点光源的基础上,所以聚光灯的定义可以将点光源作为自身的一个属性。
//聚光灯
public class SpotLight {
//点光源
private PointLight pointLight;
//方向
private Vector3f coneDirection;
//锥形体的夹角
private float cutOff;
}
方向光
//方向光的定义
public class DirectionalLight {
//颜色
private Vector3f color;
//方向
private Vector3f direction;
//强度
private float intensity;
}
光源汇总:
在一个三维场景中,前面提到的光源可以同时放在一个场景中、点光源和激光灯也可以被放入场景中很多次,所以可以对三维场景中的全部光源进行整体抽象。可以如下:
//场景内全部的光
public class SceneLight {
//环境光
private Vector3f ambientLight;
//点光源数组
private PointLight[] pointLightList;
//聚光灯数组
private SpotLight[] spotLightList;
//方向光
private DirectionalLight directionalLight;
}
材质(漫反射和镜面反射)
public class Material {
//如果被环境光照射呈现的颜色
private Vector4f ambientColour;
//漫反射系数(4维向量)
private Vector4f diffuseColour;
//镜面反射系数(4维向量)
private Vector4f specularColour;
//反射率
private float reflectance;
//模型表面的纹理
private Texture texture;
}
//材质对象中的纹理抽象Texture
public class Texture {
//调用glGenTextures()函数返回的值
private final int id;
//纹理图片的宽度
private final int width;
//纹理图片的高度
private final int height;
}