[OpenGL] 点光源PCF柔和阴影

 

本章节源码点击此处

PCF技术

  • 在上一篇文章[OpenGL] 点光源阴影(万向阴影贴图) 中,我们放大后还是会发现很生硬的锯齿边的情况
  • PCF允许通过采样片段位置周围的多个样本并平均结果来平滑(软化)这些锯齿状边缘。

  • PCF的平均采样技术也可以参考这篇文章 PCF柔和阴影 着二者之间的计算原理是相同的,但是此时我们是立方体贴图,所以我们需要加入第三个维度来计算。
  • 其实我们只需要将每个采样点的x,y,z都稍微进行偏移,就做到了平均采样的效果,也就能够柔和阴影边缘的锯齿边了。
float shadow = 0.0;
float bias = 0.05; 
float samples = 4.0;  // 每次循环的采样数
float offset = 0.1;   // 每次循环的偏移距离
for(float x = -offset; x < offset; x += offset / (samples * 0.5))
{
    for(float y = -offset; y < offset; y += offset / (samples * 0.5))
    {
        for(float z = -offset; z < offset; z += offset / (samples * 0.5))
        {
            float closestDepth = texture(depthMap, fragToLight + vec3(x, y, z)).r; 
            closestDepth *= far_plane;   // Undo mapping [0;1]
            if(currentDepth - bias > closestDepth)
                shadow += 1.0;
        }
    }
}
shadow /= (samples * samples * samples);
  • 这样我们就能看到比较柔和的纹理了,也比较否和视角上的纹理。

  • 但是我们会发现,每次遍历一个顶点会有64次计算采样的样本,这太多了,因为我们是在向量的附近做偏移量采样,但是大多数的采样都是多余的,因为大部分深度是相同的。
  • 由于我们是想获取的是深度值的大小,我们不如在采样的基础上只采样垂直方向的垂直方向进行采样
  • 我们可以定义20个完全不同方向的数组,这样就能剔除那些离的很近的方向。
vec3 sampleOffsetDirections[20] = vec3[]
(
   vec3( 1,  1,  1), vec3( 1, -1,  1), vec3(-1, -1,  1), vec3(-1,  1,  1), 
   vec3( 1,  1, -1), vec3( 1, -1, -1), vec3(-1, -1, -1), vec3(-1,  1, -1),
   vec3( 1,  1,  0), vec3( 1, -1,  0), vec3(-1, -1,  0), vec3(-1,  1,  0),
   vec3( 1,  0,  1), vec3(-1,  0,  1), vec3( 1,  0, -1), vec3(-1,  0, -1),
   vec3( 0,  1,  1), vec3( 0, -1,  1), vec3( 0, -1, -1), vec3( 0,  1, -1)
);
  • 然后我们把利用这20个数组来平均采样深度值,这样就比之前的采样的样本少了很多。
  • 这里还有一个技巧就是,可以基于观察者里一个fragment的距离来改变diskRadius;这样我们就能根据观察者的距离来增加偏移半径了,当距离更远的时候阴影更柔和,更近了就更锐利。
float shadow = 0.0;
float bias = 0.15;
int samples = 20;
float viewDistance = length(viewPos - fragPos);
float diskRadius = (1.0 + (viewDistance / far_plane)) / 25.0;
for(int i = 0; i < samples; ++i)
{
    float closestDepth = texture(depthMap, fragToLight + sampleOffsetDirections[i] * diskRadius).r;
    closestDepth *= far_plane;   // Undo mapping [0;1]
    if(currentDepth - bias > closestDepth)
        shadow += 1.0;
}
shadow /= float(samples);
  • 这样我们就能看到的阴影效果就会更加柔和,并且会随着视角距离的变化柔和效果也会变化

阴影总结

  • 我们在阴影中使用的偏移量bias需要根据场景和业务进行不断地调整和优化,这并不是一个固定的值
  • 使用几何着色器来生成深度贴图不会一定比每个面渲染场景6次更快。使用几何着色器有它自己的性能局限,在第一个阶段使用它可能获得更好的性能表现。这取决于环境的类型,以及特定的显卡驱动等等,所以如果你很关心性能,就要确保对两种方法有大致了解,然后选择对你场景来说更高效的那个。
  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值