DirectX12 3D 中的Light

1.Light结构体

struct Light
{
    float3 Strength;    // 光源的颜色
    float FalloffStart; // 仅供点光源/聚光灯
    float3 Direction;   // 仅供方向光源/聚光灯
    float FalloffEnd;   // 仅供点光源/聚光灯
    float3 Position;    // 仅供点光源/聚光灯
    float SpotPower;    // 仅供聚光灯 
};

2.辅助函数

2.1 衰减因子

    点光源和聚光灯的线性衰减。

float CalcAttenuation(float d, float falloffStart, float falloffEnd)
{
    return saturate((falloffEnd-d) / (falloffEnd - falloffStart));
}

2.2 反射率

    根据光向量L和表面法线n之间的夹角,根据菲涅尔效应近似计算出以n为法线的表面反射光的百分比。

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;
}

2.3 光量

    计算反射到观察者眼中的光量,该值为漫反射光亮和镜面反射光量的总和。

float3 BlinnPhong(float3 lightStrength, float3 lightVec, float3 normal, float3 toEye, Material mat)
{
    const float m = mat.Shininess * 256.0f;           //Shininess表示光泽度
    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;

    //由镜面反射公式得到的结果超出[0,1]时,按比例缩小
    specAlbedo = specAlbedo / (specAlbedo + 1.0f);
    return (mat.DiffuseAlbedo.rgb + specAlbedo) * lightStrength;
}

2.4  方向光源光量

      输出来自某方向光源发出,经表面反射入观察者眼中的光量。

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);
}

2.5 点光源光量

    输出从点光源放出,经表面反射入观察者眼中的光量。

float3 ComputePointLight(Light L, Material mat, float3 pos, float3 normal, float3 toEye)
{
    //自表面指向光源的向量
    float3 lightVec = L.Position - pos;
    //表面到光源的距离
    float d = length(lightVec);
    //范围检测
    if(d > L.FalloffEnd)
        return 0.0f;
    //对光向量进行规范化处理
    lightVec /= d;
    //通过朗伯余弦定理按比例降低光强
    float ndotl = max(dot(lightVec, normal), 0.0f);
    float3 lightStrength = L.Strength * ndotl;
    //根据距离计算光的衰减
    float att = CalcAttenuation(d, L.FalloffStart, L.FalloffEnd);
    lightStrength *= att;

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

2.6 聚光灯光量

float3 ComputeSpotLight(Light L, Material mat, float3 pos, float3 normal, float3 toEye)
{
    // 自表面指向光源的向量
    float3 lightVec = L.Position - pos;
    // 表面到光源的距离
    float d = length(lightVec);
    // 范围检测
    if(d > L.FalloffEnd)
        return 0.0f;
    // 对光向量进行规范化处理
    lightVec /= d;
    // 通过朗伯余弦定理按比例降低光强
    float ndotl = max(dot(lightVec, normal), 0.0f);
    float3 lightStrength = L.Strength * ndotl;
    // 根据距离计算光的衰减
    float att = CalcAttenuation(d, L.FalloffStart, L.FalloffEnd);
    lightStrength *= att;
    // 根据聚光灯照明模型对光强进行缩放处理
    float spotFactor = pow(max(dot(-lightVec, L.Direction), 0.0f), L.SpotPower);
    lightStrength *= spotFactor;

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值