Direct3D 12——灯光——平行光

文章介绍了平行光源在3D图形渲染中的概念,这种光源发出的光线视为平行,常以太阳作为实际例子。文中还涉及了菲涅尔方程的近似计算方法——Schlick近似,以及Blinn-Phong着色模型在计算反射光量时的角色,包括漫反射和镜面反射的结合。此外,提到了光照强度与法线、视角向量的关系在计算中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

平行光源(parallel light)也称方向光源(directional light,也译作定向光源),是一种距离目标物体 极远的光源。因此,我们就可以将这种光源发出的所有入射光看作是彼此平行的光线。再者, 由于光源距物体十分遥远,我们就能忽略距离所带来的影响,而仅指定照射到场景中光线的光强(light intensity )。
在这里插入图片描述
我们用向量来定义平行光源,借此即可指定光线传播的方向。因为这些光线是相互平行的,所以采 用相同的方向向量代之。而光向量与光线传播的方向正相反。可以准确模拟出方向光的常见光源实例是 太阳
在这里插入图片描述
实现

//代替菲涅尔方程的石里克近似。此函数基于光向量L于表面法线n之间的夹角,并根据菲涅尔效应近似地计算出以n为法线的表面所反射光的百分比
// Schlick gives an approximation to Fresnel reflectance (see pg. 233 "Real-Time Rendering 3rd Ed.").
// R0 = ( (n-1)/(n+1) )^2, where n is the index of refraction.
float3 SchlickFresnel(float3 R0, float3 normal, float3 lightVec)
{
    float cosIncidentAngle = saturate(dot(normal, lightVec));

    float f0 = 1.0f - cosIncidentAngle;
    float3 reflectPercent = R0 + (1.0f - R0)*(f0*f0*f0*f0*f0);

    return reflectPercent;
}

//计算反射到观察者眼中的光量,该值为漫反射光量于镜面反射光量的总和
float3 BlinnPhong(float3 lightStrength, float3 lightVec, float3 normal, float3 toEye, Material mat)
{
    //m由光泽度推导而来,而光泽度则根据粗糙度求得
    const float m = mat.Shininess * 256.0f;
    float3 halfVec = normalize(toEye + lightVec);

    float roughnessFactor = (m + 8.0f)*pow(max(dot(halfVec, normal), 0.0f), m) / 8.0f;
    float3 fresnelFactor = SchlickFresnel(mat.FresnelR0, halfVec, lightVec);

    float3 specAlbedo = fresnelFactor*roughnessFactor;

    //尽管我们进行的是LDR(low dynamic range .低动态范围)渲染,但spec(镜面反射)公式得到
    // 的结果仍会超出范围[0,1],因此现将其按比例缩小一些
    // Our spec formula goes outside [0,1] range, but we are 
    // doing LDR rendering.  So scale it down a bit.
    specAlbedo = specAlbedo / (specAlbedo + 1.0f);

    return (mat.DiffuseAlbedo.rgb + specAlbedo) * lightStrength;
}

//平行光(方向光)
float3 ComputeDirectionalLight(Light L, Material mat, float3 normal, float3 toEye)
{
    //光向量与光线传播的方向刚好相反
    float3 lightVec = -L.Direction;

    //通过朗伯余弦定律按比例降低光强
    float ndotl = max(dot(lightVec, normal), 0.0f);
    float3 lightStrength = L.Strength * ndotl;

    return BlinnPhong(lightStrength, lightVec, normal, toEye, mat);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值