HLSL实现镜面反射光照模型

时间:2021-07-14 04:13:02

镜面反射颜色计算公式:

color = AIntensity * Acolor * Amaterial+ DIntensity * Dcolor * N dot L * Dmaterial+ SIntensity * Scolor * R dot V * Smaterial

N 是漫反射顶点法向量 ,L是漫反射入射光向量的反向量,V是镜面反射的观察点向量(从被观察点指向观察点),R是镜面反射的的反射向量(出射光)

 

1.顶点渲染器代码

//==============================================================
// Desc: 顶点渲染器代码
//==============================================================


//--------------------------------------------------------------
// 全局变量
//--------------------------------------------------------------
float4x4 matWorldViewProj;   //复合变换矩阵
float4x4 matWorld;           //世界矩阵
float4   vecLightDir;         //灯光方向
float4   vecEye;              //观察点位置

float4   materialAmbient;     //材质反射环境光系数
float4   materialDiffuse;     //材质漫反射系数
float4   materialSpecular;    //材质镜面反射系数

//--------------------------------------------------------------
// 输出结构
//--------------------------------------------------------------
struct VS_OUTPUT
{
   float4 Pos: POSITION;
   float4 Color: COLOR;
};


//--------------------------------------------------------------
// 顶点渲染器主函数
//--------------------------------------------------------------
VS_OUTPUT VS( float4 pos: POSITION, float3 normal: NORMAL )
{
    //计算顶点位置
   VS_OUTPUT Out   = (VS_OUTPUT) 0;
   Out.Pos         = mul(pos, matWorldViewProj); // transform Position
  
   //计算灯光方向和观察方向
   float3 lightDir = normalize( vecLightDir );
   float3 posWorld = normalize( mul(pos, matWorld) );
   float3 viewDir = normalize( vecEye - posWorld );
  
   //计算法向量方向和漫反射强度
   float3 normalWorld = normalize( mul(normal, matWorld) );
   float4 diff = saturate( dot(normalWorld, lightDir) );
  
   //计算反射光方向( R = 2 * (N.L) * N - L)和镜面反射强度
   float3 Reflect = normalize( 2 * diff * normalWorld - lightDir );
   float4 specu = pow( saturate(dot(Reflect, viewDir)), 0.5 );

   //计算顶点颜色
   float4 diffuseColor = { 1.0f, 1.0f, 1.0f, 1.0f};  
   float4 ambientColor = { 0.5f, 0.5f, 0.5f, 1.0f};
   float4 specularColor = { 0.0f, 0.0f, 1.0f, 1.0f};
   Out.Color = ambientColor * materialAmbient +
               diffuseColor * diff * materialDiffuse +
               specularColor * specu * materialSpecular;
  
   return Out;
}

 

 

 

 

//构造观察矩阵
D3DXMATRIXA16 matView;
D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5 );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );

//构造投影矩阵
D3DXMATRIXA16 matProj;
float fAspectRatio = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspectRatio, 1.0f, 100.0f );

//构造世界矩阵
D3DXMATRIXA16 matWorld;
D3DXMatrixIdentity( &matWorld );

//设置坐标变换矩阵
D3DXMATRIXA16 matWorldViewProj;
matWorldViewProj = matWorld * matView * matProj;
V_RETURN(g_pConstant->SetMatrix( pd3dDevice, "matWorldViewProj", &matWorldViewProj ));
V_RETURN(g_pConstant->SetMatrix(pd3dDevice, "matWorld", &matWorld ));
V_RETURN(g_pConstant->SetVector( pd3dDevice, "vecEye",
                              &D3DXVECTOR4(vEyePt.x, vEyePt.y, vEyePt.z, 0) ));

//设置剔出模式,为不剔出任何面
    pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

//设置材质
D3DMATERIAL9 mtrl;
    ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
mtrl.Ambient.r = 1.0f;
mtrl.Ambient.g = 1.0f;
mtrl.Ambient.b = 0.0f;
mtrl.Ambient.a = 1.0f;
V_RETURN(g_pConstant->SetVector( pd3dDevice, "materialAmbient",
                              &D3DXVECTOR4(mtrl.Ambient.r, mtrl.Ambient.g,
          mtrl.Ambient.b, mtrl.Ambient.a)));

mtrl.Diffuse.r = 1.0f;
    mtrl.Diffuse.g = 1.0f;
    mtrl.Diffuse.b = 0.0f;
    mtrl.Diffuse.a = 1.0f;
V_RETURN(g_pConstant->SetVector( pd3dDevice, "materialDiffuse",
                                       &D3DXVECTOR4(mtrl.Diffuse.r, mtrl.Diffuse.g,
                  mtrl.Diffuse.b, mtrl.Diffuse.a)));

mtrl.Specular.r = 1.0f;
mtrl.Specular.g = 1.0f;
mtrl.Specular.b = 1.0f;
mtrl.Specular.a = 1.0f;
V_RETURN(g_pConstant->SetVector( pd3dDevice, "materialSpecular",
                                      &D3DXVECTOR4(mtrl.Specular.r, mtrl.Specular.g,
                                    mtrl.Specular.b, mtrl.Specular.a)));