我正在使用Java编写一个非常原始的3D图形引擎,该引擎基于1995年的3D游戏编程的黑色艺术。我已经到了可以在屏幕上绘制单色多边形并在"场景"周围移动相机的地步。我甚至有一个Z缓冲区,只要我不同时显示太多半透明像素,它就可以通过按Z对像素进行排序来正确处理半透明对象。我正处于需要添加照明的位置。我想保持简单,环境光似乎足够简单,定向光也应该相当简单。但我真的希望点光源能够移动光源并投射出非常原始的阴影(主要是我不希望光线穿过墙壁)。
我的问题是,我不知道解决这个问题的最佳方法。我想象一个点光源以规则的角度投射光线,如果这些光线与多边形相交,它会照亮该多边形并停止向前移动。然而,当我想到一个有多个光源和多个多边形以及所有这些光线的场景时,我想它会变得非常慢。我也不知道如何处理这样一种情况,即多边形离光源足够远,如果落在两条光线之间。我会给每个光源一个最大距离,如果我给它足够的光线,那么在这个距离内不应该有任何两条光线相距太远而错过一个多边形的点,但这只会增加我要执行的计算数量的问题。
我想问你的是:有没有一些技巧可以指向光源来加快速度,或者只是为了更好地组织它?恐怕我会做一个嵌套循环的噩梦。我不能使用openGL或Direct3D或任何其他作弊,因为我想写自己的。
如果你想看看我到目前为止的结果,这里有一个youtube视频。我已经修复了坏的相机旋转。http://www.youtube.com/watch?v=_XYj113Le58&feature=plcp
实时三维应用程序的照明是(或者更确切地说,过去通常是)通过非常简单的近似来完成的-请参阅http://en.wikipedia.org/wiki/Shading.阴影是昂贵的,并且通常在光栅化3d引擎中是通过阴影贴图&阴影体积。点光源会使阴影更加昂贵。
动态实时光源最近才成为游戏中的一个常见功能,只是因为它们给渲染系统带来了沉重的负担。这些游戏利用了专用的图形卡。所以我认为,如果你决定包括动态阴影投射点光源,你可能很难从你的引擎中获得良好的性能。
如今,照明以两种方式应用是很常见的:
- 传统上这是"正向渲染"。在这种方法中,对于每个顶点(如果按顶点进行照明)或片段(如果按像素进行照明),将计算每个光源的贡献
- 最近,"延迟"照明变得流行起来,其中几何体和额外的数据(如法线&颜色信息都被渲染到中间缓冲区,然后用于计算照明贡献。这样,照明计算就不依赖于几何图形计数。然而,它确实有很多其他开销
有很多选择。然而,实现任何比过去几年专用显卡使用的一些基本模型更复杂的东西都将是一项挑战!
我的建议是从一些简单的东西开始——没有阴影的基本照明。从那里你可以扩展和优化。
你做射线三角形相交测试是为了什么?你是想只照亮光线能到达的三角形吗?射线三角形我认为,每一盏灯与每一个多边形的交点都会非常昂贵。对于没有阴影的照明,通常只需在每个面上迭代(或者如果你在每个顶点上迭代,则在每个顶点),然后计算&添加每个灯光的照明贡献-你应该在开始光栅化之前这样做,因为无论如何你都必须穿过所有多边形。
您可以通过使用任何照明模型来计算照明,这种模型非常简单,比如朗伯反射率,它基于曲面法线和从曲面到灯光的方向向量的点积来对曲面进行着色。确保你的矢量在相同的空间!这可能就是为什么你会得到奇怪的结果。如果曲面法线在世界空间中,请确保计算世界空间光向量。计算某些空间的照明有很多优点,你可以稍后再看,现在我建议你只需掌握基本知识。还可以看看Blinn phong-这是多年来使用的着色模型图形卡。
对于带有阴影的照明,请查看我发布的链接。它们的开发是因为逼真的照明计算成本太高。
顺便说一句,拉莫特有一本名为《3D游戏编程大师的技巧高级3D图形和光栅化》的后续书籍
这将带您完成编程3d引擎的每一步。我不知道这本黑色艺术书的封面是什么。