我目前正在开发一个使用阴影纹理来渲染阴影的项目。
聚光灯很容易,因为只需要聚光灯方向的 1 个纹理,但它有点困难,因为它需要所有方向的 6 个纹理或 1 个以某种方式渲染点光源周围的所有对象的纹理。
这就是我的问题所在。如何生成一个投影矩阵,以某种方式围绕点光源以 360 度角渲染所有对象?
基本上如何创建鱼眼(或任何其他 360 度相机)顶点着色器?
1 回答
如何生成一个投影矩阵,以某种方式围绕点光源以 360 度角渲染所有对象?
你不能。同质空间中的 4x4 投影矩阵不能表示任何会导致多边形边缘弯曲的操作。直线保持直线。
基本上如何创建鱼眼(或任何其他 360 度相机)顶点着色器?
你也不能这样做,至少在一般情况下不能。并且这不是使用中的投影矩阵的限制,而是光栅化器的一般限制。您当然可以将鱼眼失真的公式放入顶点着色器中。但是光栅化器仍然会用直边光栅化每个三角形,你只是扭曲了每个三角形角点的位置。这意味着它只适用于覆盖单个像素的小三角形。对于较大的三角形,您完全搞砸了图像。如果您有 T 形接头之类的东西,这甚至会导致实际上应该完全闭合的对象中出现孔洞或重叠。
聚光灯非常容易,因为只需要聚光灯方向的 1 个纹理,但它有点困难,因为它需要所有方向的 6 个纹理或 1 个以某种方式渲染点光源周围的所有对象的纹理。
正确的解决方案是使用单个立方体贴图纹理,提供 6 个面。在一个完美的立方体中,每个面都可以通过标准的对称透视投影来渲染,水平和垂直方向的视野均为 90 度。
在现代 OpenGL 中,您可以使用分层渲染。在这种情况下,您将立方体贴图的 6 个面中的每一个作为单个层附加到 FBO,您可以使用几何着色器将您的几何体放大 6 倍,并根据 6 个不同的投影矩阵对其进行变换,以便您仍然只需要一个渲染通道即可获得完整的阴影贴图。
还有一些其他特定于供应商的扩展可用于进一步优化立方体贴图渲染,例如 Nvidia 的NV_viewport_swizzle(可在 Maxwell 和更新的 GPU 上使用),但我只是为了完整性而提及这一点。