Three.js 中的光照模型

Three.js 中的光照模型

在这里插入图片描述

Three.js 的一个伟大抽象就是统一了所有材质的光照模型, 无论 PBR 或者 Phong。都只用两个函数给全部囊括了。
就是 RE_Direct(直接反射) 和 RE_IndirectDiffuse(间接反射)。真正做到了大一统。下面以Phong为例,具体看一下如何落地。

省流版本:

// 直接反射
RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );

// 间接反射
vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );

  vec3 outgoingLight =
  // 直接漫反射
  reflectedLight.directDiffuse +
  // 间接漫反射
  reflectedLight.indirectDiffuse +
  // 直接高光
  reflectedLight.directSpecular +
  // 间接高光
  reflectedLight.indirectSpecular;
1、一些概念
  • Incident, 入射光
  • Irradiance, 辐照度, 量化接收光源能量的多少
  • 直接光照, 是指光源直接照射到物体表面产生的光照效果
  • 间接光照, 是指光源经过其他物体反射或散射后照射到物体表面的光照效果。
2、RE_Direct

RE_Direct 计算直接光照的反射效果, 包括直接漫反射和直接高光反射。

3、RE_IndirectDiffuse

RE_IndirectDiffuse_BlinnPhong 函数用于计算间接漫反射的效果。包括间接漫反射和间接高光反射。

4、Phone 实现细节

片元着色器:

varying vec3 vViewPosition;

//
#define RE_Direct				RE_Direct_BlinnPhong
#define RE_IndirectDiffuse		RE_IndirectDiffuse_BlinnPhong

// 直接反射 + 间接反射总结果
struct ReflectedLight {
    // 直接漫反射
    vec3 directDiffuse;
    // 直接高光
    vec3 directSpecular;
    // 间接漫反射
    vec3 indirectDiffuse;
    // 间接高光
    vec3 indirectSpecular;
};

// 入射光参数
struct IncidentLight {
    vec3 color;
    vec3 direction;
    bool visible;
};

struct BlinnPhongMaterial {
    vec3 diffuseColor;
    vec3 specularColor;
    float specularShininess;
    float specularStrength;
};

void RE_Direct_BlinnPhong(
    const in IncidentLight directLight,
    const in vec3 geometryPosition,
    const in vec3 geometryNormal,
    const in vec3 geometryViewDir,
    const in vec3 geometryClearcoatNormal,
    const in BlinnPhongMaterial material,
    inout ReflectedLight reflectedLight
) {
    float dotNL = saturate( dot( geometryNormal, directLight.direction ) );
    vec3 irradiance = dotNL * directLight.color;
    reflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
    reflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;
}

void RE_IndirectDiffuse_BlinnPhong(
    const in vec3 irradiance,
    const in vec3 geometryPosition,
    const in vec3 geometryNormal,
    const in vec3 geometryViewDir,
    const in vec3 geometryClearcoatNormal,
    const in BlinnPhongMaterial material,
    inout ReflectedLight reflectedLight
) {
    reflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );
}



uniform vec3 diffuse;
uniform float opacity;
uniform vec3 specular;
uniform vec3 ambientLightColor;

struct BlinnPhongMaterial {
    vec3 diffuseColor;
    vec3 specularColor;
    float specularShininess;
    float specularStrength;
};

// 方向光信息
struct DirectionalLight {
    vec3 direction;
    vec3 color;
};

uniform DirectionalLight directionalLights[ 1 ];

// 入射的方向光转为通用的入射光信息
void getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {
  light.color = directionalLight.color;
  light.direction = directionalLight.direction;
  light.visible = true;
}

vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
    vec3 irradiance = ambientLightColor;
    return irradiance;
}

void main() {
  vec4 diffuseColor = vec4( diffuse, opacity );

  ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );

  vec4 sampledDiffuseColor = texture2D( map, vMapUv );
  diffuseColor *= sampledDiffuseColor;

  float specularStrength = 1.0;

  BlinnPhongMaterial material;
  material.diffuseColor = diffuseColor.rgb;
  material.specularColor = specular;
  material.specularShininess = shininess;
  material.specularStrength = specularStrength;

  vec3 geometryPosition = - vViewPosition;
  vec3 geometryNormal = normal;
  vec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );
  vec3 geometryClearcoatNormal = vec3( 0.0 );

  // 入射光信息
  IncidentLight directLight;

  // 方向光
  DirectionalLight directionalLight;
  directionalLight = directionalLights[ 0 ];
  getDirectionalLightInfo( directionalLight, directLight );

  // 直接反射
  RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );

  // 间接反射
  vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );
  RE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );

   vec3 outgoingLight =
    // 直接漫反射
    reflectedLight.directDiffuse +
    // 间接漫反射
    reflectedLight.indirectDiffuse +
    // 直接高光
    reflectedLight.directSpecular +
    // 间接高光
    reflectedLight.indirectSpecular;
}

顶点着色器:

vec3 transformed = vec3( position );
vec4 mvPosition = vec4( transformed, 1.0 );
mvPosition = modelViewMatrix * mvPosition;
gl_Position = projectionMatrix * mvPosition;

vViewPosition = - mvPosition.xyz;
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值