0

我将“倒退”进行地形生成:我正在程序上生成地形及其法线。然后我生成一个地形位图,用作 2D 地图。这一切都正常工作并产生了我想要的结果。但是现在,2D 贴图有“平面”阴影——如何将地形生成的法线应用于 2D 生成的位图?

理想情况下,我想像“太阳”直接在头顶(在“正午”)一样应用照明。我搜索了这个和其他开发网站,以及一般的互联网,但没有找到任何特定于我需求的东西,只有理论和概念信息。

谁能告诉我如何做到这一点或指出我正确的方向?您不必提供代码(尽管伪代码会很好),但我只需要知道从哪里开始。我在我的游戏中使用 C#/XNA,但欢迎来自任何语言的想法。

4

2 回答 2

2

您尝试做的是创建凹凸贴图。

http://www.gutgames.com/post/Normal-Map-Creation-Using-C.aspx

它假定法线始终指向特定方向(通常垂直于面部),然后根据 rgb 值对其进行偏移。有很多资源涵盖凹凸贴图,包括上面的链接。

如果您想简化事情,您可以将实际的正常值存储在新位图的 RGB 中(请注意,使用此方法会丢失精度)。

如果您的范围是 [-1...1],则:将 1 添加到您的结果并除以 2,然后乘以 255。

所以如果你有正常的 (0, 1, 0)

0 + 1 = 1 / 2 = 0.5 * 255 = 128 = 你的新 X 值

1 + 1 = 2 / 2 = 1 * 255 = 255 = 你的新 Y 值

0 + 1 = 1 / 2 = 0.5 * 255 = 128 = 你的新 Z 值

然后将 (128,255,128) 存储在位图中。

要将其返回到正确的值,您将反转该过程:

128 / 255 = 0.5 * 2 = 1 - 1 = 0 = 你的旧 X 值

255 / 255 = 1 * 2 = 2 - 1 = 1 = 你的旧 Y 值

128 / 255 = 0.5 * 2 = 1 - 1 = 0 = 你的旧 Z 值

精度很差,但效果很好。您还可以打包这些值,以便每个 X 和 Y 获得两个字节。因此,RGBA 值的 X = RG 和 Y = BA。然后你可以做一些魔术来拉出 Z 值以获得完整的法线。当您对法线进行归一化时,它的长度变为 1。所以 1 = sqrt(x*x + y*y + z*z)。从位图中读取 X 和 Y 时您知道它们,因此您可以求解 Z。大大提高了精度,也可以根据您的需要用于提高凹凸贴图的精度。

于 2013-05-21T18:36:45.867 回答
0

点积是关键!:)

对于那些感兴趣的人,我想出的解决方案如下。感谢上面的评论。另外,这里有两个对我有很大帮助的网站:

https://stackoverflow.com/questions/3121815/what-are-the-dot-and-cross-product-of-vectors

http://www.tjhsst.edu/~dhyatt/supercomp/n310.html

//==========================================

// change location of lightPosition as desired
// lightPosition Y may have to be positive for different implementations
Vector3 lightPosition = new Vector3(0, -1, 0); 
lightPosition.Normalize(); // not needed for above but this assumes normalized
float dotProduct = (Vector3.Dot(
    terrainPositionVector3Normalized, lightPosition) + 1) * 0.5f;
terrainColor.R = (byte)((float)terrainColor.R * dotProduct);
terrainColor.G = (byte)((float)terrainColor.G * dotProduct);
terrainColor.B = (byte)((float)terrainColor.B * dotProduct);
于 2014-01-20T02:38:54.140 回答