OpenGL ES 光照计算

2019-07-15  本文已影响0人  紫水依

一、光照计算

1、环境光计算

环境光 = 光源的环境光颜色 * 物体的材质颜色

2、发射光的计算

发射颜色 = 物体的反射材质颜色

3、漫反射光照计算

漫反射颜色 = 光源的漫反射颜色 * 物体的漫反射材质颜色 * DiffuseFactor

DiffuseFactor = max(0, dot(N, L));

4、镜面光计算

镜面反射颜色 = 光源的镜面光颜色 * 物体的镜面材质颜色 * SpecularFactor

SpecularFactor = power(max(0, dot(N, H)), shininess);
H:视线向量E 与光线向量L 的半向量
dot(N, H):H,N的点积几何意义,平方线与法线夹角的cos值
shininess:高光的反光度

5、普通光照计算

光照颜色 = (环境颜色 + 漫反射颜色 + 镜面反射颜色) * 衰减因子

衰减因子计算

衰减因子 = 1.0 / (距离衰减常量 + 线性衰减常量 * 距离 + 二次衰减常量 * 距离的平方)
距离衰减常量、线性衰减常量和二次衰减常量均为常量值

tips:环境光、漫反射光和镜面光的强度都会受距离的增大而衰减,只有发射光和全局环境光的强度不会受影响

6、聚光灯因子

聚光灯夹角cos值 = power(max(0, dot(单位光源位置, 单位光线向量)), 聚光灯指数);

单位光线向量:是从光源指向顶点的单位向量
聚光灯指数:表示聚光灯的亮度程度
公式解读:单位光源位置 * 单位光线向量 点积 的 聚光灯指数次方

7、光照计算终极公式

光照颜色 = 发射颜色 + 全局环境颜色 + (环境颜色 + 漫反射颜色 + 镜面颜色) * 聚光灯效果 * 衰减因子

平面光终极公式

点光源终极公式

二、光照的GLSL实现

1、环境光的GLSL实现

varying vec3 objectColor;
void main() {

    //至少有10%的光照到物体所有面
    float ambientStrength = 0.1;

    //环境光颜色 = 环境光比率 * 环境光颜色
    vec3 ambient = ambientStrength * lightColor;

    //最终颜色 = 环境光颜色 * 物体颜色
    vec3 result = ambient * objectColor;
    //vec3转化成vec4
    gl_FragColor = vec4(result, 1.0);

}

2、漫反射光的GLSL实现

uniform vec3 lightColor;     //光源颜色
uniform vec3 lightPo;         //光源位置
uniform vec3 objectColor; //物体颜色
uniform vec3 viewPo;        //物体位置
varying vec3 outNormal;  //传入当前顶点平面的法向量

//确保法线为单位向量,normalize为内建函数,把法向量转换成单位向量
vec3 norm = normalize(outNormal);
//顶点指向光源的单位向量
vec3 lightDir = normalize(lightPo -   FragPo);
//得到两向量的cos值,小于0则为0
float diff = max(dot(norm, lightDir), 0.0);
//夹角乘以光照颜色得到漫反射的光源向量
vec3 diffuse = diff * lightColor;

vec3 result = diffuse * objectColor;
gl_FragColor = vec4(result, 1.0);

3、镜面光的GLSL实现

//镜面强度
float specularStrength = 0.5;

//顶点指向观察点的单位向量
vec3 viewDir = normalize(viewPo - FragPo);

//光线在顶点的反射线(传入光源指向顶点的向量),镜面光是反方向的光线
vec3 reflectDir = reflect(-lightDir, outNormal);

//夹角cos值,取256次幂,镜面因子
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 256.0);

vec3 specular = specularStrength * spec * lightColor;

4、衰减因子计算

//距离衰减常量
float constantPara = 1.0;
//线性衰减常量
float linearPara = 0.09;
//二次衰减因子
float quadraticPara = 0.032;
//距离
float lightWeakPara = 1.0/(constantPara + linearPara * LFDistance + quadraticPara * (LFDistance * LFDistance));

5、聚光灯过渡计算

//一些复杂的计算操作应该让CPU做以提高效率,不变的量也建议外部传输,避免重复计算
//内锥角cos值
float inCutoff = cos(radians(10.0));
//外锥角cos值
float outCutoff = cos(radians(15.0));
//聚光朝向
vec3 spotDir = vec3(-1.2, -1.0, -2.0);

//光源指向物体的向量和聚光朝向的cos值
float theta = dot(lightDir, normalize(-spotDir));
//内外锥角cos差值
float epsilon = inCutoff - outCutoff;

//clamp(a, b, c);若b<a<c则函数返回a,若不是则返回最小b,最大c
/*(theta - outCutoff)/epsilon 若theta的角度小于内锥角则其值>=1,
若theta的角度大于外锥角则其值<=0,这样光线就在内外锥角之间平滑变化*/
float intensity = clamp((theta - outCutoff) / epsilon, 0.0, 1.0);

上一篇 下一篇

猜你喜欢

热点阅读