光源类型:
directional lighting
point lights, which radiate uniform light from their centers,
spot lights, which are directional but not uniform across all objects.
DX11中实现光照比较简单,不像DX9中有D3DLight9等表示光照的特定类型,在DX11中表现光照效果,就是在Pixel Shader中,根据光源参数计算出特定的颜色值然后输出。
// Pixel Shader,Lambert光照模型例子, vLightDir记录光照方向,vLightColor记录光源颜色
float4 PS( PS_INPUT input) : SV_Target
{
float4 finalColor = 0;
for(int i=0; i<2; i++)
{
//两个光源的光照值叠加
//saturate(HLSL函数)的作用是使值限定在【,1】之间
finalColor += saturate( dot( (float3)vLightDir[i],input.Norm) * vLightColor[i] );
}
return finalColor;
}
计算光照,需要顶点的法线信息,所以顶点的输入结构中至少包含Position和Normal数据,
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
我们可以看到ID3D11DeviceContext对象的一些成员函数的命名是比较有规律的,如前两个大写字母代表了对应函数作用的阶段,eg:IA*表示作用于Input-Assembler Stage的函数。
g_pImmediateContext->IASetInputLayout( g_pVertexLayout );
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
g_pImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );
g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
g_pImmediateContext->VSSetConstantBuffers( 0, 1, &g_pConstantBuffer );
g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
g_pImmediateContext->PSSetConstantBuffers( 0, 1, &g_pConstantBuffer );
g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView );
g_pImmediateContext->RSSetViewports( 1, &vp );
g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
g_pImmediateContext->ClearDepthStencilView( g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0 );
g_pImmediateContext->UpdateSubresource( g_pConstantBuffer, 0, NULL, &cb1, 0, 0 );
g_pImmediateContext->DrawIndexed( 36, 0, 0 );