ПрограммированиеСтатьиГрафика

Программирование шейдеров на HLSL. (5 стр)

Specular Bump Mapping.

Ну конечно, без этого никак :), хотелось бы рассказать про этот эффект…

Вот мы и подошли к более серьезным моделям освещения, нам придется рассчитать вектор освещения, создать неортогональную систему координат, и т.д. Для тех кто не знает что такое bump mapping, то выглядит он так:

Изображение

Для реализации этого эффекта нам понадобиться две текстуры: 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;

// dcl_position 
// dcl_normal
// dcl_texcoord
// dcl_tangent

D3DVERTEXELEMENT9 decl[]=
{
//stream, offset, type, method, semantic type
{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);

// Load mesh from .x
d3d__AddMesh(m_pd3dDevice,m_strTorus,&pMeshSysMem,D3DXMESH_SYSTEMMEM);    
// Clone SysMesh #1 into SesMesh #2.
pMeshSysMem->CloneMesh(D3DXMESH_MANAGED,decl,m_pd3dDevice,&pMeshSysMem2); 

D3DXComputeNormals(pMeshSysMem2,NULL); // compute the normals
D3DXComputeTangent(pMeshSysMem2,0,0,0,TRUE,NULL); // compute tangent(u)
                                                  // and later binormal (v)

// New vertex declaration
// dcl_position 
// dcl_normal
// dcl_texcoord
// dcl_tangent

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()
};

// Clone SysMesh into ResultMesh.
pMeshSysMem2->CloneMesh(D3DXMESH_MANAGED,decl2,m_pd3dDevice,&ResultMesh); 
    
SAFE_RELEASE(pMeshSysMem);
SAFE_RELEASE(pMeshSysMem2);

Шейдеры…

vertex shader

float4x4 m_matMVP;     // World * View * Projection
float4x4 m_matWorld;   // World transposed
float4   m_vLightPos;  // Light position
float4   m_vViewPos;   // View position

struct VS_INPUT_STRUCT
{
    float4 position: POSITION;  // Vertex position
    float3 normal:   NORMAL0;   // Vertex normal
    float2 texcoord: TEXCOORD0; // Vertex texcoord
    float3 tangent:  TANGENT;   // Tangent ( u ) 
    float3 binormal: BINORMAL;  // Binormal( v )
};

struct VS_OUTPUT_STRUCT
{
    float4 position: POSITION;  // Vertex position
    float2 texcoord: TEXCOORD0; // Texture coordinates
    float3 light:    TEXCOORD1; // Light vector
    float3 view:     TEXCOORD2; // View vector
};

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; 
    
    // Calculate binormal
    In_struct.binormal = cross(In_struct.tangent,In_struct.normal);

    matTangentSpace[0] = mul(m_matWorld,In_struct.tangent); // x
    matTangentSpace[1] = mul(m_matWorld,In_struct.binormal);// y
    matTangentSpace[2] = mul(m_matWorld,In_struct.normal);  // z
 
    // Calculate light vector and move into tangent space
    Out_struct.light.xyz = mul(matTangentSpace,m_vLightPos); 
    // Calculate view vector and move into tangent space
    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); // Base map
sampler2D m_Bump: register(s1); // Dot3 map

float4 main(float2 texcoord: TEXCOORD0;
            float3 light:    TEXCOORD1;
            float3 view:     TEXCOORD2): COLOR0;
{
    float4 tx_base = tex2D(m_Base,texcoord); // Load base texture
    float4 tx_bump = tex2D(m_Bump,texcoord); // Load bump texture

    tx_bump = normalize((tx_bump * 2.0)1.0f);//Bias normal to range [-1,1]
    
    float3 nrmd_light = normalize(light); // Normalize light
    float3 nrmd_view  = normalize(view); // Normalize view
     
    // Calculate reflect vector
    float4 reflect_vec = reflect(nrmd_view,nrmd_light);
    // Normal dot light
    float4 n_dot_l     = dot(tx_bump,nrmd_light);
    // Reflect dot view
    float4 r_dot_v     = dot(reflect_vec,nrmd_view);

    // Calculate ambient model
    float4 ambient = tx_base * m_vAmbient * m_vHelper.x; 
    // Calculate diffuse model
    float4 diffuse = tx_base * m_vDiffuse * m_vHelper.y * max(N_dot_L,0.0f);
    // Calculate specular model
    float4 spec    = m_vSpec * m_vHelper.z + pow(r_dot_v, m_vHelper.w);
    
    // Result lighting model
    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]