Cook-Torrance Model

来源:互联网 发布:stussy淘宝正品 编辑:程序博客网 时间:2024/05/01 11:43

基本公式描述    

一个由  Robert L. Cook 和 Kenneth E. Torrance开发的光照模型. CT比 Phong或Blinn-Phong模型更加接近真实的物理模拟. 它通常用来描述一个物体的高光部分.这个模型将物体描述为由无数的微面组成的整体.在粗糙的物体上,微面之间的夹角变化大,光滑的物体上则更趋近一致.

在大多数光照模型中,反射由ambient,diffuse和specular组成,lambertian(n·l)通常用来计算diffuse.CT通常用来替代specular的计算,基本公式如下:

    这里的k是一个因子用来平衡diffuse和specular;rs则是高光算子,公式如下:

高光部分由三个因素组成: The fresnel (F), the roughness (= the directional distribution of the microfacets, D) and the geometric attenuation(G).

Fresnel

真实的fresnel过于复杂,基本shader都使用的Schilck近似,计算公式如下:

Fλ是反射因子,I是光源方向向量,h是半向量(光源和视角).

Roughness (microfacet distribution)

表面粗糙度,用来表现表面粗糙物体到平滑物体之间的区别.

通常使用的计算公式使用Beckmanns (1963) distribution function:

m用来控制表面粗糙程度.

Geometrical attenuation

用来描述光束在微面之间造成的影响,这个因子的质在0到1之间.

There are therefore three cases of how light reacts with the surface: (a) the light is reflected without interference, (b) some of the reflected light is blocked after reflection and (c) some of the light is blocked before reaching the next microfacet (TODO: add images).

光和表面的交互有以下结果:

a.光被完全反射

b.一些光在反射后被阻挡

c.一些光在到达其它微面前被阻挡

第一种情况,光源到达观察者数值为1. 

第二种情况为:

第三种情况:

The geometrical attenuation factor is calculated as the minimum of these three values:

The geometric attenuation calculation is described in detail by Blinn (1977).

precision highp float; //set default precision in glsl es 2.0uniform vec3 lightDirection;varying vec3 varNormal;varying vec3 varEyeDir;void main(){    // set important material values    float roughnessValue = 0.3; // 0 : smooth, 1: rough    float F0 = 0.8; // fresnel reflectance at normal incidence    float k = 0.2; // fraction of diffuse reflection (specular reflection = 1 - k)    vec3 lightColor = vec3(0.9, 0.1, 0.1);        // interpolating normals will change the length of the normal, so renormalize the normal.    vec3 normal = normalize(varNormal);        // do the lighting calculation for each fragment.    float NdotL = max(dot(normal, lightDirection), 0.0);        float specular = 0.0;    if(NdotL > 0.0)    {        vec3 eyeDir = normalize(varEyeDir);        // calculate intermediary values        vec3 halfVector = normalize(lightDirection + eyeDir);        float NdotH = max(dot(normal, halfVector), 0.0);         float NdotV = max(dot(normal, eyeDir), 0.0); // note: this could also be NdotL, which is the same value        float VdotH = max(dot(eyeDir, halfVector), 0.0);        float mSquared = roughnessValue * roughnessValue;                // geometric attenuation        float NH2 = 2.0 * NdotH;        float g1 = (NH2 * NdotV) / VdotH;        float g2 = (NH2 * NdotL) / VdotH;        float geoAtt = min(1.0, min(g1, g2));             // roughness (or: microfacet distribution function)        // beckmann distribution function        float r1 = 1.0 / ( 4.0 * mSquared * pow(NdotH, 4.0));        float r2 = (NdotH * NdotH - 1.0) / (mSquared * NdotH * NdotH);        float roughness = r1 * exp(r2);                // fresnel        // Schlick approximation        float fresnel = pow(1.0 - VdotH, 5.0);        fresnel *= (1.0 - F0);        fresnel += F0;                specular = (fresnel * geoAtt * roughness) / (NdotV * NdotL * 3.14);    }        vec3 finalValue = lightColor * NdotL * (k + specular * (1.0 - k);    gl_FragColor = vec4(finalValue, 1.0);}


0 0