17.2 环境贴图
立方体贴图的主要用途是实现环境贴图映射(environment mapping)。它的实现思路是:在场景中的某个物体O的中心位置放置一架摄像机,将(水平和垂直)视域角设为90º。然后沿着±X轴、±Y轴和±X轴方向,从6种不同的角度各拍摄一张照片(在照片中不包含物体O)。因为视域角为90º,所以这6张照片完全可以从物体O的角度捕捉到各个方向上的环境信息(参见图17.2)。我们把这6张照片存入到一个立方体贴图中,就得到了所谓的环境贴图。换句话说,环境贴图就是在立方体平面上存入一个环境的全景照片。
上述内容表明,在场景中有多少个使用环境贴图映射的物体,我们就必须创建多少个环境贴图。不过,环境贴图通常只用于表现远处的“背景”信息,而近景物体可以共享相同的环境贴图。例如,在图17.3中,所有的球体都共享图17.2所示的环境贴图。注意,这个环境贴图并没有拍摄场景中的石柱和地板;它只拍摄了远处的山峰和天空(即,场景背景)。虽然在某些场景中,背景环境贴图不能表现场景的所有细节,但是在实践中它的渲染结果还是比较令人满意的。
当创建环境贴图时,摄像机的拍摄方向必须与世界空间的主轴方向对齐,只有这样,环境贴图才能直接在世界空间中使用。当然,你也可以采用其他的方向进行拍摄(比方说某个物体的局部空间)。但是此时,查找向量必须被转换到立方体贴图空间之后,才能进行纹理映射。
注意,环境贴图使用的这6幅图像一般不是在Direct3D程序中生成的,虽然有时也可以这么做(参见17.5节)。因为立方体贴图只存储纹理数据,它们的内容通常是由美术师提前画好的(就像我们之前使用的2D纹理一样)。所以,我们不需要使用实时渲染计算一个立方体贴图的图像。也就是,我们可以在一个3D世界编辑器中创建场景,然后在编辑器中预渲染立方体贴图平面上的这6幅图像。对于室外环境贴图来说,我们通常使用Terragen软件(http://www.planetside.co.uk/terragen/,该软件有免费的个人使用版本),它可以创建照片级的室外场景。本书使用的环境贴图都是使用Terragen软件生成的,比如图17.2所示的环境贴图。
注意:当你初次使用Terragen软件时,一定要在Camera Settings对话框中将缩放系数(zoom factor)设为1.0,以得到一个90º的视域角。另外,输出图像的宽度和高度也必须设为相同的值,只有这样摄像机在水平和垂直方向上的视域角才会相同,也就是90º。
注意:网上(https://developer.valvesoftware.com/wiki/Skybox_(2D)_with_Terragen)还有一个很好的Terragen脚本,它可以使用当前相机的位置并以90º的视域角渲染出周围的六张图像。
当我们使用某种软件创建了立方体贴图的6幅图像之后,我们必须创建一幅立方体贴图纹理来存储这6幅图像。我们之前使用的DDS纹理图像格式就支持立方体贴图,我们可以很容易地使用DirectX纹理工具将这6幅图像合并为一个立方体贴图。运行DirectX纹理工具(它位于DirectX SDK的DXSDXJune10\Utilities\Bin\x86目录下)。在File菜单中选择 New Texture命令,弹出如图17.4所示的对话框。在Texture Type中选择Cubemap Texture选项,输入源图像的尺寸大小,并选择一种表面格式。(最好使用像DXT1这样的压缩格式;因为这里要存储6幅纹理,高分辨率的立方体贴图会占用很多内存。)
现在我们有了一幅空的立方体贴图。将鼠标定位在View菜单上,选择Cube Map Face子菜单,挑选一个你希望在窗口中显示的立方体贴图平面(图17.5)。(起初,这些平面都是空的。)现在随便选择一个平面,然后单击File菜单,选择Open Onto This Cubemap Face命令,在弹出的对话框中选择对应于个立方体平面的图像文件,将它导入到当前的立方体贴图平面中。重复这一操作,向其余的5个立方体贴图平面导入相应的图像文件。当全部操作完成之后,将立方体贴图保存为DDS文件。
注意:NVIDIA提供了一个Photoshop插件用来保存.DDS和立方体贴图,可见http://developer.nvidia.com/nvidia-texture-tools-adobe-photoshop。
11.2.1 在Direct3D中载入和使用立方体贴图
使用D3DX11CreateShaderResourceViewFromFile函数可以很方便地将一个存储了立方体贴图的DDS文件载入到ID3D11Texture2D对象中并生成对应的shader视图:
ID3D11ShaderResourceView * mCubeMapSRV; HR(D3DX11CreateShaderResourceViewFromFile(device,cubemapFilename. c_str(),0,0,&mCubeMapSRV,0));
ID3D11Texture2D对象会将立方体贴图的6个纹理存储为一个纹理数组。
在我们获得了一个指向立方体纹理的ID3D11ShaderResourceView*指针之后,我们可以使用ID3D11EffectShaderResourceVariable::SetResource方法将它指定给effet文件中的TextureCube变量:
// .fx变量 TextureCube gCubeMap; // .cpp代码 ID3D11EffectShaderResourceVariable* CubeMap; CubeMap = mfx -> GetVariableByName("gCubeMap")->AsShaderResource(); ... CubeMap->SetResource(cubemap);文件下载(已下载 1399 次)
发布时间:2014/8/19 下午8:41:10 阅读次数:4870