DirectX11 创建和启用纹理

创建和启用纹理

1. 创建纹理步骤

纹理数据通常是存储在磁盘上的图像文件。我们需要将它读取出来,并载入到一个ID3D11Texture2D对象中(参见D3DX11CreateTextureFromFile)。不过,纹理资源是不能被直接绑定到渲染管线上的;我们需要为纹理创建一个着色器资源视图(ID3D11ShaderResourceView),然后将视图绑定到管线上。

这个过程可分为两步:

1.调用D3DX11CreateTextureFromFile,读取存储在磁盘上的图像文件,创建ID3D11Texture2D对象。

2.调用ID3D11Device::CreateShaderResourceView,为纹理创建对应的着色器资源视图。

这两步也可通过如下D3DX函数一次完成:

HRESULT D3DX11CreateShaderResourceViewFromFile(
    ID3D11Device *pDevice,
    LPCTSTR pSrcFile,
    D3DX11_IMAGE_LOAD_INFO *pLoadInfo,
    ID3DX11ThreadPump *pPump,
    ID3D11ShaderResourceView **ppShaderResourceView,
    HRESULT *pHResult
);

1.pDevice:创建纹理时使用的Direct3D设备指针。

2.pSrcFile:所要载入的图像的文件名。

3.pLoadInfo:可选的图像信息;当设为空值时,该函数使用源图像文件信息。例如,我们在这里指定空值,那么源图像的尺寸就是纹理的尺寸;另外,该函数还会生成一个完整的多级渐近纹理链(8.4.2节)。这个默认值很好,因为它所执行的一系列行为通常都是我们想要的。

4.pPump:在一个新的线程中载入资源。如果要在当前的工作线程中载入资源,请将它设为空值。在本书中,这个参数总是设为空值。

5.ppShaderResourceView:返回纹理的着色器资源视图指针。

6.pHResult:当pPump设为空值时,该参数也应设为空值。

注意:有时,我们所说的“纹理”实际上是指“与它关联的着色器资源视图”。例如,我们会说:“将纹理绑定到管线上”,但实际上是指“将它的视图绑定到管线上”。

2. 纹理支持的格式

该函数可以载入以下格式的图像文件:BMP、JPG、PNG、DDS、TIFF、GIF、WMP(参见D3DX11_IMAGE_FILE_FORMAT)。

例如,要从图像文件WoodCrate01.dds创建一个纹理,我们可以编写如下代码:

ID3D11ShaderResourceView* mDiffuseMapSRV;
HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,
L"WoodCrate01.dds", 0, 0, &mDiffuseMapSRV, 0 ));

3. HLSL纹理定义

在纹理载入之后,我们需要把它指定给一个effect变量,使像素着色器中的代码可以访问到这个资源。在.fx文件中,2D纹理对象由Texture2D类型表示;例如,我们可以在effect文件中声明一个纹理变量:

// 非数值对象不能放在常量缓冲区中
Texture2D gDiffuseMap;

如注释所述:“非数值对象不能放在常量缓冲区中”,纹理对象必须放在常量缓冲区之外。

4. 如何在程序中获取与更新HLSL纹理

我们可以在C++应用程序代码中获取这个Texture2D对象的指针(它是一个着色器资源变量):

ID3D11EffectShaderResourceVariable* mfxDiffuseMapVar;
mfxDiffuseMapVar = mFX->GetVariableByName("gDiffuseMap")->AsShaderResource();

在我们获取Texture2D对象的指针之后,可以通过如下C++接口更新纹理对象:

// Set the C++ texture resource view to the effect texture variable.
mfxDiffuseMapVar->SetResource(mDiffuseMapSRV);

与其他的effect效果变量相同,当我们在绘图调用之间更新效果变量时,一定要调用Apply方法:

// set crate texture
mfxDiffuseMapVar->SetResource(mCrateMapSRV);
pass->Apply(0, md3dImmediateContext);
DrawCrate();

// set grass texture
mfxDiffuseMapVar->SetResource(mGrassMapSRV);
pass->Apply(0, md3dImmediateContext);
DrawGrass();

// set brick texture
mfxDiffuseMapVar->SetResource(mBrickMapSRV);
pass->Apply(0, md3dImmediateContext);
DrawBricks();

使用纹理贴图集可以在一次绘制调用中绘制更多的几何体,所以可以提高性能。例如,我们使用了如上一节图所示的包含条板、草地、砖墙纹理的贴图集,通过调整纹理坐标在每个对象上映射不同的子纹理,我们就可以在一次绘制调用中绘制整个几何体(假设每个对象都没有需要改变的其他参数):

//  set texture atlas
mfxDiffuseMap ->SetResource(mAtlasSRV);
pass ->Apply(0, md3dImmediateContext);
DrawCrateGrassAndBricks();

调用绘制需要耗费资源,使用这个技术可以使绘制调用减到最少。

注意:纹理资源实际上可以由任何着色器(顶点、几何或像素)使用。但是目前我们只在像素着色器中使用纹理。如前所述,纹理本质上是一种特殊的数组,所以不难想象,这些数组数据也可以在顶点着色器和几何着色器中使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值