6-2光照

72 阅读1分钟

假设无论光源在哪,入射光线的辐射率一样,点光源具有相同的辐射强度,所以辐射强度可以设为一个常量向量

辐射强度根据点的位置和光源的位置和距离进行缩放,所以根据表面法向量和入射角度来缩放辐射强度,用光源的数目计算总辐照度

vec3 lightColor = vec3(23.47, 21.31, 20.79); 
vec3 wi = normalize(lightPos - fragPos); 
float cosTheta = max(dot(N, Wi), 0.0); 
float attenuation = calculateAttenuation(fragPos, lightPos); 
float radiance = lightColor * attenuation * cosTheta;

首先计算镜面反射和漫反射的比值,和表面折射的光线相比,反射了多少光线,使用菲涅尔方程

DFG4(ωo⋅n)(ωi⋅n)

vec3 fresnelSchlick(float cosTheta, vec3 F0)
{ 
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); 
}

然后计算法线分布函数和几何遮蔽函数

float DistributionGGX(vec3 N, vec3 H, float roughness)
{ 
float a = roughness*roughness; 
float a2 = a*a; 
float NdotH = max(dot(N, H), 0.0); 
float NdotH2 = NdotH*NdotH; 
float num = a2; 
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom; return num / denom; 
} 
float GeometrySchlickGGX(float NdotV, float roughness) 
{
float r = (roughness + 1.0); 
float k = (r*r) / 8.0;
float num = NdotV; 
float denom = NdotV * (1.0 - k) + k; 
return num / denom;
} 
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) 
{ 
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness); 
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2; 
}

在几何遮蔽函数和法线分布函数中用粗糙度的平方,使光线看起来更自然

使用菲涅尔方程计算出ks后计算折射比值kd

vec3 kS = F; 
vec3 kD = vec3(1.0) - kS; 
kD *= 1.0 - metallic;

金属不会折射光线,所以没有漫反射,将系数设置为0

在着色器的最后进行伽马矫正,在伽马矫正前从LDR转为HDR