当我们设计 奥斯丁 ,我们花了相当长的时间思考不同的页面视图和布局,以及如何在它们之间转换。 我们想创造一个沉浸式的体验,用户可以操纵和浏览奥斯汀的网页在一个直观的方式;页面通过捏手势在3D中进行放大和缩小,相机在页面上滑动,甚至当手指在屏幕上拖动时会有一点倾斜。 这使得 页面只是在三维空间中“浮动”,并根据需要移动和重新排列。 为了增加视觉效果,我花了一些时间让页面投射阴影。 这种微妙的添加使得场景在视觉上更加丰富和有趣。
我在图形编程方面没有太多的经验,所以这对我来说是个挑战。 我花了一些时间研究非常著名的算法,比如阴影映射和体积阴影。 我用阴影贴图制作了一个原型版本,但不能让它看起来像我想要的那样。 最后,我想我可能会伪造它的大部分,因为我有一个优势,那就是在我的场景中投射阴影的几何体非常简单(只是一张平的,正方形的纸!),所以我最终采用了我在这里描述的技术。 我相信有更好的方法来做到这一点,但我很高兴的结果看起来。 速度也是我的目标 因为我最初的实现对我的帧速率有很大的拖累,但是这个实现非常快。
可以下载Austin的源代码,包括这里描述的特定于阴影渲染的位 在这里 .
那你怎么办 它 工作?
我们的页面总是平放在XY平面上这一事实是解决这个问题的关键。 这意味着我们知道投射在平面上的阴影也是一个矩形。 有一个小的例外,那就是当用户拖动一个手指进入下一页时,我们会卷曲一个页面,在这种情况下,我们只会根据页面的卷曲程度渲染一个更薄但仍然是矩形的阴影。 这不是一个完美的投影变形页,但它足够好,做的把戏。
记住这一点,我们可以通过渲染一个简单的四边形来绘制阴影,该四边形与页面位于同一位置,但在Z轴上向后移动,使其平放在XY平面上,并缩放和偏移一点,以“伪造”投射在XY平面上的阴影体积的投影。 此四边形的渲染颜色比背景颜色深,背景颜色始终为纯色。
画一个实心四边形会产生一个非常“硬”的阴影,所以我们想把它软化一点。 为了做到这一点,我们应用了高斯模糊过滤器,这是实现一个像素着色的GPU。 这是一个很好的文件过滤器和网上有大量的文章如何做到这一点。要查看效果,请查看 高斯模糊效应 以MSDN为例。
我们所做的第二件有助于模糊和软化阴影的事情是将这个场景渲染到一个比屏幕小得多的渲染目标,在我们的例子中是256像素×256纹理。 然后,当我们将最终的纹理复制到后缓冲区时,我们将其放大到屏幕尺寸,由于对纹理应用了从256像素到实际分辨率的过滤,此操作进一步软化了阴影。 作为额外的副作用×256纹理更小,渲染速度更快。
最后,为了增加一点深度,我们做了最后一个后处理效果,并做了一个“径向变暗”,这样你离背景中心越远,图片就越暗。
你可以 获取所有这些的代码 在奥斯汀项目中,看看 笔记本::renderFrame 对于执行不同步骤的主要代码块,以及在quad_pixel_shader_u*.hlsl文件中对于不同效果的像素着色器。 页面::渲染阴影 包含显示如何缩放和转换阴影节点以创建假投影的代码。
在图片中
一张图片胜过千言万语,让我们来看看应用程序中的所有内容。
首先,这是在平面背景上渲染的较暗的四边形的外观×256纹理:
这是应用高斯模糊后的效果:
然后,使用径向深色滤光片:
最后,它会放大到屏幕大小,然后在屏幕上呈现纸页:
下一张图片展示了同一场景在没有阴影和平坦背景的情况下的样子,以及这一切带来的不同:
下图显示了直接渲染到屏幕大小的渲染目标和渲染到更小的目标(256)之间的区别×256)渲染目标,然后放大到屏幕大小:
最后,这个技巧看起来非常好,更重要的是,给了我想要的表现。 我在做这项工作的时候很开心,我希望这些想法能帮助其他人解决同样的问题。
不够吗? 退房 层叠阴影贴图 和 改进阴影深度贴图的常用技术 有关的更多详细信息 实现高性能三维阴影。