Cook-Torrance光照模型附 shader代码

来源:互联网 发布:淘宝小说 编辑:程序博客网 时间:2024/05/21 21:47

这种光照模型是由罗伯特·L·库克和Kenneth E.托兰斯的发展。库克-托兰斯模型更接近比的Phong或的Blinn-的Phong模型的物理现实。它是用来模拟不同材料的镜面反射。该模型将每个表面由许多微小面:非常小的方面,反映了入射光。在粗糙表面上,这些微小面的斜坡变化很大,并且在光滑表面的微小面以类似的方向上取向(如在1967年由托兰斯-麻雀描述)。

因为在大多数的光照模型,反射由环境,漫反射和镜面反射和朗伯(的ñ · 用于漫反射)。该模型,而不是集中在镜面反射。下面的公式示出了基本的反射模型(以简化的形式库克&托兰斯(1982)的原配方见。):

其中,ķ ]是漫反射的光的分数(0之间的值和1)和- [R 小号是镜面反射分量,这样计算:

这种镜面反射取决于三个因素:该菲涅耳˚F),所述粗糙度(=微小面的方向分布,ð)和几何衰减ģ)。

菲涅尔

菲涅尔因子定义了入射光的分数被反射,哪一部分被发送。在我所见过的石里克近似的例子着色器代替原有的配方,因为原来的菲涅耳公式太耗费计算。见库克 - 托兰斯(1982年)为全面菲涅耳公式。

石里克(1994)做了菲涅耳公式的近似值来获得类似的结果具有更快的计算。他的公式是这样的:

˚F λ是在法向入射的反射率,是光矢量和ħ是光矢量和朝向观看者指向的向量之间的半向量。

粗糙度(微面分布)

这个因素定义了以相同的方式(=作为法线矢量指向相同的方向),为的中途矢量定向微小面的分数v。上光滑的表面,所有微小面具有相似的方向,因此,所有的反射光接近反射载体。在粗糙的表面,光线分布更加广泛。

计算所述分布的一个方法是使用Beckmanns(1963)分布函数:

其中是控制表面的粗糙度的变量。

几何衰减

在到达表面之前或反射后一些微小面遮挡入射光。的几何衰减因子是从0到1的值,表示保持此遮蔽或掩蔽已经发生后的光的比例量。该计算假定所有微小面具有V形槽的形式。

因此有三种情况的光与表面的反应:(a)该光被反射而不干扰,(二)部分的反射光被反射和(c)一些光到达下一个微面之前被阻塞后阻止(TODO:添加图片)。

在第一种情况下,到达观看者的光1.第二种情况的公式为:

对于第三种情况的公式是一样的第二种情况,但与v交换:

的几何衰减因子计算为最小下列三个值:

几何衰减计算在详细的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);}


1 0
原创粉丝点击