纹理映射:就是指将一张2D的图像投影到3D物体上。
/*
**创建一个着色器纹理资源和纹理采样器
*/
//D3D11中,纹理是一个ShaderResourceView
ID3D11ShaderResourceView* g_pTextureRV = NULL;
ID3D11SamplerState* g_pSamplerLinear = NULL;
//载入纹理
//texture是一个从文件中载入的2D图片,他被用来创建一个shader-resource view,以便能够被shader读取
hr = D3DX11CreateShaderResourceViewFromFile( g_pd3dDevice, L"seafloor.dds", NULL, NULL, &g_pTextureRV, NULL );
if( FAILED( hr ) )
return hr;
//创建纹理采样器
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 = g_pd3dDevice->CreateSamplerState( &sampDesc, &g_pSamplerLinear );
/*
**定义纹理坐标,纹理坐标是二维的(Float2)
*/
//(1)创建顶点缓存时,顶点数据中需要加入纹理坐标
//(2)创建输入结构(D3D11_INPUT_ELEMENT_DESC)时需要加入纹理的信息
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
//(3)shader中VS和PS的传入参数需要加入TEXCOORD信息
/*
**绑定纹理作为着色器资源,他们的绑定方式和Constant buffers一样,在PSSetShader之后调用
*/
g_pImmediateContext->PSSetShaderResources( 0, 1, &g_pTextureRV );
g_pImmediateContext->PSSetSamplers( 0, 1, &g_pSamplerLinear );
shader中需要以下常量,以上代码将绑定到shader中对应的常量:
Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register( s0 );
在PS中可以使用Sample函数进行纹理采样:
return txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor;
**创建一个着色器纹理资源和纹理采样器
*/
//D3D11中,纹理是一个ShaderResourceView
ID3D11ShaderResourceView* g_pTextureRV = NULL;
ID3D11SamplerState* g_pSamplerLinear = NULL;
//载入纹理
//texture是一个从文件中载入的2D图片,他被用来创建一个shader-resource view,以便能够被shader读取
hr = D3DX11CreateShaderResourceViewFromFile( g_pd3dDevice, L"seafloor.dds", NULL, NULL, &g_pTextureRV, NULL );
if( FAILED( hr ) )
return hr;
//创建纹理采样器
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 = g_pd3dDevice->CreateSamplerState( &sampDesc, &g_pSamplerLinear );
/*
**定义纹理坐标,纹理坐标是二维的(Float2)
*/
//(1)创建顶点缓存时,顶点数据中需要加入纹理坐标
//(2)创建输入结构(D3D11_INPUT_ELEMENT_DESC)时需要加入纹理的信息
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
//(3)shader中VS和PS的传入参数需要加入TEXCOORD信息
/*
**绑定纹理作为着色器资源,他们的绑定方式和Constant buffers一样,在PSSetShader之后调用
*/
g_pImmediateContext->PSSetShaderResources( 0, 1, &g_pTextureRV );
g_pImmediateContext->PSSetSamplers( 0, 1, &g_pSamplerLinear );
shader中需要以下常量,以上代码将绑定到shader中对应的常量:
Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register( s0 );
在PS中可以使用Sample函数进行纹理采样:
return txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor;
组织程序中常量表最好的方式是根据其更新频率来组织,最差的组织方式就是将所有着色器变量放在一个常量表中。一个较好的组织方式:
cbuffer VSGlobalPerFrameCB { float AppTime; }; cbuffer VSPerSkinnedCB { matrix Bones[100]; }; cbuffer VSPerStaticCB { matrix World; }; cbuffer VSPerPassCB { matrix ViewProj; uint2 RenderTargetSize; }; cbuffer VSPerMaterialCB { float SpecPower; float4 BDRFCoefficients; };