如何将生成的法线应用于位图?

时间:2013-05-21 15:24:08

标签: bitmap terrain normals

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

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

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

2 个答案:

答案 0 :(得分:2)

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

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

假设Normal始终指向特定方向(通常垂直于面),然后根据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得到两个字节。因此X = RG和Y = BA的RGBA值。然后你可以做一些魔法来拉出Z值以获得完全正常。当标准化法线时,其长度变为1.因此1 = sqrt(x * x + y * y + z * z)。从位图读取它们时你知道X和Y,所以你可以求解Z.大大提高了精度,也可以根据你的需要用来提高凹凸贴图精度。

答案 1 :(得分:0)

Dot产品是关键! :)

对于那些感兴趣的人,我想出的解决方案如下。 感谢上面的评论。 此外,这里有2个网站非常有助于我:

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);