纹理部分:
1.创建纹理。
由于原来的D3DX系列的函数没法用了,许多资料上使用的D3DX11CreateShaderResourceViewFromFile就不行了,我使用了另一种方式。
开源代码:https://github.com/Microsoft/DirectXTex
相关博客:http://blogs.msdn.com/b/chuckw/archive/2012/03/02/directxtk.aspx
一些其它资料:https://github.com/Microsoft/DirectXTK
将DirectXTex中DDSTextureLoader的代码载入到我们的工程中,使用CreateDDSTextureFromFile加载纹理图像。
这里有个麻烦的地方,就是CreateDDSTextureFromFile只能加载DDS文件,不能使用其它格式。。。。。按照博客给的表格,应该是有方法加载其它格式的文件的吧。。。。。。
所以,我还要安装一个PS以及相关的DDS插件去编辑DDS文件。
HRESULT CreateDDSTextureFromFile( _In_ ID3D11Device* d3dDevice, _In_z_ const wchar_t* szFileName, _Outptr_opt_ ID3D11Resource** texture, _Outptr_opt_ ID3D11ShaderResourceView** textureView, _In_ size_t maxsize = 0, _Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr );
使用:
//加载纹理资料 hr = DirectX::CreateDDSTextureFromFile(dev, L"seafloor.dds", nullptr, &pTextureRV);
然后需要为纹理声明一个采样器对象:
D3D11_SAMPLER_DESC sampDesc; ZeroMemory(&sampDesc, sizeof(sampDesc)); sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampDesc.MinLOD = 0; sampDesc.MaxLOD = D3D11_FLOAT32_MAX; hr = dev->CreateSamplerState(&sampDesc, &pSamplerLinear); if (FAILED(hr)) return hr;
具体去看msdn吧,不多解释了。
当然,VS的输入部分与顶点的定义也要改一下,关于顶点对应的纹理坐标看书中的8.2节,请看我上传的代码食用。。。。。。。。。。如果有人看的话。
最后在渲染的循环中,需要设置采样器对象,与纹理资源:
devContext->PSSetShaderResources(0, 1, &pTextureRV); devContext->PSSetSamplers(0, 1, &pSamplerLinear);
这样,C++代码部分暂时结束了。
然后是HLSL部分。
纹理采样:要解释纹理采样,就需要先理解过滤器。当我们的纹理映射到3D的图形上,大小不可能完全匹配的,而且,3D图形会进行放大与缩小。处理这种会使纹理出现变形的情况,我们可以指定过滤方式。具体在书中8.5节第一部分。
好了,现在经过了处理,每个像素对应了一个纹理坐标,就是说纹理坐标与我们的像素坐标一一对应了,使用纹理采样从纹理中提取颜色,并显示:
Texture2D txDiffuse;//定义纹理 SamplerState samLinear;//采样,过滤方式 struct PS_INPUT { float4 Pos : SV_POSITION; float2 Tex : TEXCOORD0; }; float4 PS(PS_INPUT input) : SV_Target { return txDiffuse.Sample(samLinear, input.Tex); }
纹理的寻址方式:
在纹理坐标中为了标准化坐标,所有的纹理坐标都在(0,1)内,那么当在0与1之外应该怎么处理?这个可由SamplerState决定,具体看书中8.8节。
整合纹理作为材质:
也就是把纹理放入光照或者其它的模型中去,书中代码:
// Modulate with late add.
litColor = texColor*(ambient + diffuse) + spec;
///按照书中的流程,接下来应该学习混合与模板
但是看了下面几节的内容,发现都是需要复杂的模型才会有比较好的效果
所以,回头去看了如何从文件中导入模型的代码,很简单。
这里的模型是从书中提供的头骨与汽车,至于如何从3D建模软件导出的模型文件载入模型,需要我们自己去对那些文件的结构进行分析(我看原来有D3DX系列的方法去直接导入已有的模型,但是这里无法直接使用D3DX系列函数,都需要我们自己手动分析)
导入的代码:
//LoadTheModel std::ifstream fin("skull.txt"); if (!fin) { printf("Models not found.\n"); return hr; } UINT vcount = 0; //vertex count UINT tcount = 0; //index count std::string ignore; fin >> ignore >> vcount; fin >> ignore >> tcount; fin >> ignore >> ignore >> ignore >> ignore; // float nx, ny, nz; DirectX::XMFLOAT4 black(0.6f, 0.6f, 0.6f, 0.8f); std::vector<Vertex> vertices(vcount); for (UINT i = 0; i < vcount; ++i) { fin >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z; fin >> vertices[i].Normal.x >> vertices[i].Normal.y >> vertices[i].Normal.z; } fin >> ignore; fin >> ignore; fin >> ignore; mSkullIndexCount = 3 * tcount;//三角形,3*顶点数 std::vector<UINT> indices(mSkullIndexCount); for (UINT i = 0; i < tcount; ++i) { fin >> indices[i * 3 + 0] >> indices[i * 3 + 1] >> indices[i * 3 + 2]; } fin.close();//记得close ///// //
具体输入方式看一下C++的文件操作(文件流)
相关文件下载: