8.1 TEXTURE AND RESOURCE RECAP
The 1D, 2D, and 3D texture interfaces all inherit from ID3D11Resource.
Usage: A array of data , mipmap , GPU apply filters , GPU multisampling.
纹理不是任意格式,需要用 DXGI_FORMAT 描述,一般的format
也可以声明为typeless 方便使用多次,但也要在create view 之前声明好
另外,注意texture 本身的 format声明 和 对应 bind的flag声明,以及运行时真正使用的 resource view的声明。
8.2 TEXTURE COORDINATES
坐标系以纹理空间为准,左上角为原点
三角形顶点制定了对应贴图的uv坐标之后,插值方式和顶点坐标的插值一样。
所以任意triangle都有了一个对应的uv坐标。
所以相比之前,vertex的结构体多了一行 float2 tex;表示uv坐标。
多张无关texutre合并为一张texture,表示texture altas 纹理集,多模型只用了同一张纹理,节省内存,另外也可以节省draw call,因为可能shader->SetResource(texture),只用设置一次,之后就不再需要改变,从而渲染多个object,节省draw call。
8.3 CREATING AND ENABLING A TEXTURE
一般使用texture流程,
1. Call D3DX11CreateTextureFromFile to create the ID3D11Texture2D object from an image file stored on disk.
2. Call ID3D11Device::CreateShaderResourceView to create the corresponding shader resource view to the texture.
然后两步可以合成一步调用D3DX11CreateShaderResourceViewFromFile
支持的图片格式:BMP, JPG, PNG, DDS, TIFF, GIF, and WMP (see D3DX11_IMAGE_FILE_FORMAT).
创建了view之后,应用到shader的流程
1.创建view
ID3D11ShaderResourceView* mDiffuseMapSRV;
HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice, L"WoodCrate01.dds", 0, 0, &mDiffuseMapSRV, 0 ));
2.shader中声明texture2D对象,但不能放到cbuffer中
Texture2D gDiffuseMap;
3.c++中先获取shader中对应变量的指针
ID3DX11EffectShaderResourceVariable* DiffuseMap;
fxDiffuseMap = mFX->GetVariableByName("gDiffuseMap")->AsShaderResource();
4.c++中用view去update shader中的变量值,更新之后,调用apply应用,最后调用object的draw call。
fxDiffuseMap->SetResource(mCrateMapSRV);
pass->Apply(0, md3dImmediateContext);
DrawCrate();
8.4 FILTERS
8.4.1 magnifation 放大
用一个texel 覆盖多个 pixel。比如0.126 * 256,会有多个pixel映射到一个 texel 区间。
区间内计算pixel有两种方法:
一种是最近邻居方法,四舍五入直接用最近的texel 常量插值 也叫 point filtering,但这种方法会产生像素块
另一种好一些的是做相邻四个texel的线性插值 linear filtering,这种更加柔和一点,但肯定始终不如高分辨率的贴图
这是两者对比
一些游戏中,远距离贴图还可以,但相机移到很近的位置,贴图就会开始break down。因此要么用更高分辨率,要么有的游戏会阻止相机到很近的距离。
8.4.2 minification
多个texel 覆盖到一个pixel。
初始化,一张大的texture会经过down sampling 构建mipmap chain。
运行时,根据texture设置,可能会做两种事。
1.point filtering for mipmap:根据当前屏幕占比,直接找到最合适的mipmap level,然后这对这层mipmap 应用texture的point/linear filtering。
2.linear filtering for mipmap:根据当前屏幕占比,选择相近的两张mipmap,一张大,一张小,两张mipmap 分别应用texture的point/linear filtering,最终两张的最终值再进行插值。
8.4.2.1 Creating of Mipmaps
可以在外部软件直接创建,也可以使用filter算法创建。
如果使用dx 的格式 .DDS ,这种贱可以直接保存mipml信息,不再需要额外的运行时消耗。
Dirext Texture Tool可以通过导入一张texture,然后创建mipmap,导出.DDS格式文件。
如果image中不含mipmap,需要运行时创建,可以使用 D3DX11CreateShaderResourceViewFromFile or D3DX11CreateTextureFromFile ,通过指定 MipFilter 自动生成mipmap。
有的时候,自动降采样得到的mipmap会花掉,并不能满足需求,这种情况还是需要artist手动制作。
8.4.3 Anisotropic Filtering
各向异性过滤,这种过滤 有利于缓解 当poly的normal 和 相机 向量是 wide 的时候发生的distortion。尤其是使用point /linear 时,会发生扭曲。
这种filter也是最费的。
8.5 SAMPLING TEXTURES
除了Texture2D object关联到 shader上,还有一个对象 SamplerState object关联,用于定义texture用到的filter。
格式类似
SamplerState mySampler2 { Filter = MIN_POINT_MAG_LINEAR_MIP_POINT; };
特殊的如果用到ANISOTROPIC filter,需要指定 ANISOTROPIC等级,1~16,越大越费。
SamplerState mySampler3 { Filter = ANISOTROPIC; MaxAnisotropy = 4; };
HLSL 中,调用Texture2D::Sample 采样,第一个参数为 SamplerState,第二个参数是uv,返回采样到的float4 值。
对应的,c++中有镜像结构体 ID3D11SamplerState,可以使用ID3DX11EffectSamplerVariable::SetSampler.设置。(See D3D11_SAMPLER_DESC and ID3D11Device::CreateSamplerState)
8.6 TEXTURES AND MATERIALS
一般纹理在shader中的应用
// Modulate with late add.
litColor = texColor*(ambient + diffuse) + spec;
8.7 CRATE DEMO
gUseTexture 传入 ps,控制是否使用texture
gLightCount 传入ps,控制光源数量
gTexTransform 定义在constant buffer,用于做texture animation。
vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy;
像这种可以xy 表示 uv scale,zw表示uv offset,或者 把scale rotaion translation做成一个4*4 矩阵,再变成一个float4 vector。
类似调用
XMMATRIX grassTexScale = XMMatrixScaling(5.0f, 5.0f, 0.0f);
XMStoreFloat4x4(&mGrassTexTransform, grassTexScale);
8.8 ADDRESS MODES
wrap, border color, clamp, and mirror.
warp:repeat。
border color:0~1内使用贴图,范围以外的用程序指定的颜色。
clamp:0~1内使用贴图,超过的就最近的0~1的边界处的颜色。
mirror:循环镜像重复。
这些信息同样在SamplerState 指定,注意u v两个方向可以跟开指定不同的寻址模式。
8.10 TEXTURED HILLS AND WAVES DEMO
1.计算landscape 地形网格每个顶点的uv坐标
// Stretch texture over grid.
meshData.Vertices[i*n+j].TexC.x = j*du;
meshData.Vertices[i*n+j].TexC.y = i*dv;
2.对texture应用transform
XMMATRIX grassTexScale = XMMatrixScaling(5.0f, 5.0f, 0.0f);
XMStoreFloat4x4(&mGrassTexTransform, grassTexScale);
8.11 COMPRESSED TEXTURE FORMATS
运行时GPU会在现存中保留所有用到的texture,以用于快速访问,为了减轻显存用量,需要对texture进行压缩。
压缩格式有BC1, BC2, BC3, BC4, BC5, BC6, and BC7:
1. BC1 (DXGI_FORMAT_BC1_UNORM): Use this format if you need to compress a format that supports three color channels, and only a 1-bit (on/off) alpha component. 3color channel,1 bit用于alpha。
2. BC2 (DXGI_FORMAT_BC2_UNORM): Use this format if you need to compress a format that supports three color channels, and only a 4-bit alpha component. 3color channel,4bit用于alpha。
3. BC3 (DXGI_FORMAT_BC3_UNORM): Use this format if you need to compress a format that supports three color channels, and an 8-bit alpha component. 3color channel,8bit用于alpha。
4. BC4 (DXGI_FORMAT_BC4_UNORM): Use this format if you need to compress a format that contains one color channel (e.g., a grayscale image). 灰度图,只有1个color channel。
5. BC5 (DXGI_FORMAT_BC5_UNORM): Use this format if you need to compress a format that supports two color channels. 两个color channel。
6. BC6 (DXGI_FORMAT_BC6_UF16): Use this format for compressed HDR (high dynamic range) image data. 用于HDR image。
7. BC7 (DXGI_FORMAT_BC7_UNORM): Use this format for high quality RGBA compression. In particular, this format significantly reduces the errors caused by compressing normal maps. 用于高质量RGBA 压缩,这种格式可以显著减少由于压缩 normal map带来的问题。
Because the block compression algorithms work with 4 × 4 pixel blocks, the dimensions of the texture must be multiples of 4.由于 BC压缩算法,使用4*4的pixel block,因此 texture的尺寸必须是4的倍数。
如果使用一张未压缩的贴图,在dx中可以在运行时进行压缩,通过在D3DX11CreateShaderResourceViewFromFile 中传入pLoadInfo 参数来实现。
D3DX11_IMAGE_LOAD_INFO loadInfo;
loadInfo.Format = DXGI_FORMAT_BC3_UNORM;
HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice, L"Textures/darkbrick.bmp", &loadInfo, 0, &mDiffuseMapSRV, 0));
debugger中可以查看texture的压缩格式对不对,或者是有没有使用压缩。
DirectX Texture Tool 工具可以直接在导出的DDS文件中存储 压缩后的数据。
在菜单Menu->Format->Change Surface Format 中选择 DXT1, DXT2, DXT3, DXT4, or DXT5. Save the file as a DDS file. These formats are actually Direct3D 9 compressed texture formats, but DXT1 is the same as BC1, DXT2 and DXT3 are the same as BC2, and DXT4 and DXT5 are the same as BC3. 这里只能做到BC3的
如果DDS中包含了压缩格式,loadinfo中就可以传null,program会读取文件中的压缩格式。
NVIDIA Texture Tools 可以做BC4 和BC5 的。
DirectX SDK has a sample called “BC6HBC7EncoderDecoder11.” 可以做 BC6和 BC7 的。