Для реализации этого эффекта нам понадобиться две текстуры: base map и normal map, base map — это diffuse текстура, а normal map текстуру нам придется делать самим (почти самим). Для этого нужно скачать plug-in к Photoshop (На сайте nVidia есть этот plug-in), или любую другую программу которая конвертирует из height map в dot3. Или же воспользоваться программой normal mapper, которая находиться в Radeon DX SDK. Суть bump mapping’a состоит в том, чтобы сделать иллюзию выпуклости какой либо поверхности. Для bump mapping’а понадобиться tangent space. Вместо normal’и полигона мы будем брать normal map (dot3 текстуру), а tangent и binormal нам понадобятся для расчета освещения. Еще одна трудность правильного bump mapping’a (specular bump mapping’a) состоит в том, что нужно рассчитывать tangent space (в математической литературе привычно называть tangent space касательное пространство). В этой системе координат normal будет осью z, binormal — y, и tangent — x.
Так выглядит tangent space для вершины полигона:
Для расчета нормалей и tangent в D3DX есть следующие функции:
D3DXComputeNormals(…)
D3DXComputeTangent(…)
Так что давайте сначала сосчитаем normal и tangent:
LPD3DXMESH ResultMesh,pMeshSysMem2,pMeshSysMem = NULL;
D3DVERTEXELEMENT9 decl[]=
{
{0,0, D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0},
{0,12,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_NORMAL, 0},
{0,24,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD,0},
{0,36,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TANGENT, 0},
D3DDECL_END()
};
m_pd3dDevice->CreateVertexDeclaration(decl,&m_pDecl);
d3d__AddMesh(m_pd3dDevice,m_strTorus,&pMeshSysMem,D3DXMESH_SYSTEMMEM);
pMeshSysMem->CloneMesh(D3DXMESH_MANAGED,decl,m_pd3dDevice,&pMeshSysMem2);
D3DXComputeNormals(pMeshSysMem2,NULL);
D3DXComputeTangent(pMeshSysMem2,0,0,0,TRUE,NULL);
D3DVERTEXELEMENT9 decl2[]=
{
{0,0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0},
{0,12,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_NORMAL, 0},
{0,24,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, 0},
{0,36,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TANGENT, 0},
D3DDECL_END()
};
pMeshSysMem2->CloneMesh(D3DXMESH_MANAGED,decl2,m_pd3dDevice,&ResultMesh);
SAFE_RELEASE(pMeshSysMem);
SAFE_RELEASE(pMeshSysMem2);
Шейдеры…
vertex shader
float4x4 m_matMVP;
float4x4 m_matWorld;
float4 m_vLightPos;
float4 m_vViewPos;
struct VS_INPUT_STRUCT
{
float4 position: POSITION;
float3 normal: NORMAL0;
float2 texcoord: TEXCOORD0;
float3 tangent: TANGENT;
float3 binormal: BINORMAL;
};
struct VS_OUTPUT_STRUCT
{
float4 position: POSITION;
float2 texcoord: TEXCOORD0;
float3 light: TEXCOORD1;
float3 view: TEXCOORD2;
};
VS_OUTPUT_STRUCT main(VS_INPUT_STRUCT In_struct)
{
VS_OUTPUT_STRUCT Out_struct;
Out_struct.position = mul(m_matMVP,In_struct.position);
Out_struct.texcoord = In_struct.texcoord;
float3x3 matTangentSpace;
In_struct.binormal = cross(In_struct.tangent,In_struct.normal);
matTangentSpace[0] = mul(m_matWorld,In_struct.tangent);
matTangentSpace[1] = mul(m_matWorld,In_struct.binormal);
matTangentSpace[2] = mul(m_matWorld,In_struct.normal);
Out_struct.light.xyz = mul(matTangentSpace,m_vLightPos);
Out_struct.view = mul(matTangentSpace,m_vViewPos);
return Out_struct;
}
fragment shader
float4 m_vAmbient;
float4 m_vDiffuse;
float4 m_vSpec;
float4 m_vHelper;
sampler2D m_Base: register(s0);
sampler2D m_Bump: register(s1);
float4 main(float2 texcoord: TEXCOORD0;
float3 light: TEXCOORD1;
float3 view: TEXCOORD2): COLOR0;
{
float4 tx_base = tex2D(m_Base,texcoord);
float4 tx_bump = tex2D(m_Bump,texcoord);
tx_bump = normalize((tx_bump * 2.0) – 1.0f);
float3 nrmd_light = normalize(light);
float3 nrmd_view = normalize(view);
float4 reflect_vec = reflect(nrmd_view,nrmd_light);
float4 n_dot_l = dot(tx_bump,nrmd_light);
float4 r_dot_v = dot(reflect_vec,nrmd_view);
float4 ambient = tx_base * m_vAmbient * m_vHelper.x;
float4 diffuse = tx_base * m_vDiffuse * m_vHelper.y * max(N_dot_L,0.0f);
float4 spec = m_vSpec * m_vHelper.z + pow(r_dot_v, m_vHelper.w);
float4 light_m = ambient + diffuse + spec;
return light_m;
}
Теперь о переменных в шейдерах…
m_matMVP – ModelViewProjection matrix
m_matWorld – World matrix
m_vLightPos – Light position
m_vViewPos – View position
m_vAmbient – Ambient color
m_vDiffuse – Diffuse color
m_vSpec - Specular color
m_vHelper.x - Ambient intensity
m_vHelper.y – Diffuse intensity
m_vHelper.z – Specular intensity
m_vHelper.w – Specular exponent
Для работы примера достаточно установить все константы, например, так:
If(m_hLocation = m_pVertShader->GetConstantByName(NULL,”Нужная константа”))
{
}
Страницы:
1 2 3 4 5 6 7 Следующая »
#3D, #Direct3D, #DirectX, #HLSL, #шейдеры
1 июня 2004
(Обновление: 19 июня 2024)
Комментарии [151]