ThreeJS LambertMaterial

359 阅读1分钟

原文

  • ThreeJS材质对比
    • MeshBasicMaterial 不受光照的影响。
    • MeshLambertMaterial 只在顶点计算光照。
    • MeshPhongMaterial 则在每个像素计算光照,还支持镜面高光。
  • 定义diffuseColor和反射光reflectedLight
vec4 diffuseColor = vec4( diffuse, opacity );
ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
  • diffuse
#ifdef USE_MAP
    vec4 texelColor = texture2D( map, vUv );
    texelColor = mapTexelToLinear( texelColor ); 
    diffuseColor *= texelColor; //就线性转换
#endif
#ifdef USE_COLOR
    diffuseColor.rgb *= vColor; //如果有color的话  还是会乘的
#endif
  • 计算前后的反射光
// vertex shader中计算的 vIndirectFront
IncidentLight directLight;
float dotNL;
vec3 directLightColor_Diffuse;
vIndirectFront += getAmbientLightIrradiance( ambientLightColor );
vIndirectFront += getLightProbeIrradiance( lightProbe, geometry ); //lightProbe还是比较少用的
#ifdef DOUBLE_SIDED //有两面的话 还是会设置两面的
    vIndirectBack += getAmbientLightIrradiance( ambientLightColor );
    vIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );
#endif
  • 根据参数设置反射光
 #ifdef DOUBLE_SIDED
    reflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;//判断是哪个面
#else
    reflectedLight.indirectDiffuse += vIndirectFront;
#endif
#ifdef USE_LIGHTMAP  //lightmap
    vec4 lightMapTexel = texture2D( lightMap, vUv2 );
    reflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;
#endif
reflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );
#ifdef DOUBLE_SIDED
    reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;
#else
    reflectedLight.directDiffuse = vLightFront;
#endif
  • BRDF计算,这块后续探讨
reflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();
  • 最终输出的灯光
vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance; //diffuse 
  • 最后的FragColor
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
#if defined( TONE_MAPPING )
    gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );
#endif
gl_FragColor = linearToOutputTexel( gl_FragColor );
#ifdef USE_FOG
    #ifdef FOG_EXP2
        float fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );
    #else
        float fogFactor = smoothstep( fogNear, fogFar, fogDepth );
    #endif
    gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );
#endif
#ifdef PREMULTIPLIED_ALPHA
    gl_FragColor.rgb *= gl_FragColor.a;
#endif
#ifdef DITHERING
    gl_FragColor.rgb = dithering( gl_FragColor.rgb );
#endif