Intro :
Dans cette troisième partie, nous allons apprendre comment ajouter une texture à un petit cube auto généré.
Prérequis :
Avoir suivi la deuxième partie de ce tutoriel.
Troisième partie :
Afficher un petit cube avec une texture appliquée dessus.
Explications :
Dans ce tutoriel nous allons utiliser cette structure de vertex :
struct SimpleVertex
{
D3DXVECTOR3 Pos;
D3DXVECTOR2 Tex;
};
La deuxième variable indique que l’on va utiliser les coordonnées de la texture appliqués au cube.
Rajoutez dans votre fichier D3D10Renderer.h :
/* Variables HLSL des matrix. Ces variables seront utilisées et envoyées au vertex shader HLSL. */ ID3D10EffectMatrixVariable* m_pWorldVariable; ID3D10EffectMatrixVariable* m_pViewVariable; ID3D10EffectMatrixVariable* m_pProjectionVariable; // Variable de la texture ID3D10EffectShaderResourceVariable* m_pDiffuseVariable; // Les matrix pour afficher le rendu D3DXMATRIX m_worldMatrix; D3DXMATRIX m_viewMatrix; D3DXMATRIX m_projectionMatrix; ID3D10ShaderResourceView* m_pTextureRV;
Voici le fichier effet HLSL utilisé – partie3.fx :
//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
Texture2D txDiffuse;
SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
cbuffer cbNeverChanges
{
matrix View;
};
cbuffer cbChangeOnResize
{
matrix Projection;
};
cbuffer cbChangesEveryFrame
{
matrix World;
};
struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output = (PS_INPUT)0;
output.Pos = mul( input.Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.Tex = input.Tex;
return output;
}
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( PS_INPUT input) : SV_Target
{
return txDiffuse.Sample( samLinear, input.Tex );
}
//--------------------------------------------------------------------------------------
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}
Dans le fichier D3D10Renderer.cpp à la fonction Initialize(bool bFullScreen) :
/******************** Partie 2 & 3 ********************/
DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
// Permet d'afficher les éventuelles erreurs de la compilation d'un shader
dwShaderFlags |= D3D10_SHADER_DEBUG;
#endif
// Pour la création du shader, on le compile
hr = D3DX10CreateEffectFromFile(L"Partie3.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, m_pd3dDevice, NULL,
NULL, &m_pEffect, NULL, NULL);
if (FAILED(hr))
return false;
// On acquiert la technique du shader HLSL
m_pTechnique = m_pEffect->GetTechniqueByName("Render");
/* Voici les variables matrix utilisées par le shader HLSL */
m_pWorldVariable = m_pEffect->GetVariableByName("World")->AsMatrix();
m_pViewVariable = m_pEffect->GetVariableByName("View")->AsMatrix();
m_pProjectionVariable = m_pEffect->GetVariableByName("Projection")->AsMatrix();
m_pMeshColorVariable = m_pEffect->GetVariableByName("vMeshColor")->AsVector();
m_pDiffuseVariable = m_pEffect->GetVariableByName("txDiffuse")->AsShaderResource();
/******************************************************/
Voir cet article si vous ne comprenez pas à quoi sert les matrices World, View et Projection.
On définit la nouvelle structure d’un vertex :
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = sizeof( layout ) / sizeof( layout[0] );
D3D10_PASS_DESC PassDesc;
m_pTechnique->GetPassByIndex(0)->GetDesc(&PassDesc);
hr = m_pd3dDevice->CreateInputLayout(layout, numElements, PassDesc.pIAInputSignature,
PassDesc.IAInputSignatureSize, &m_pVertexLayout);
if(FAILED(hr))
return false;
m_pd3dDevice->IASetInputLayout(m_pVertexLayout);
/******************************************************/
On définit les informations de vertex et index buffers d’un cube :
// On créé le vertex buffer d'un cube
SimpleVertex vertices[] =
{
{ D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
{ D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) },
{ D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) },
{ D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) },
};
// On créé l'index buffer de ce cube
DWORD indices[] =
{
3,1,0,
2,1,3,
6,4,5,
7,4,6,
11,9,8,
10,9,11,
14,12,13,
15,12,14,
19,17,16,
18,17,19,
22,20,21,
23,20,22
};
Voir cet article si vous ne comprenez pas à quoi sert les vertex buffer et index buffer.
On implémente les vertex et index buffers :
/********** Vertex buffer **********/ D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; // Taille d'une entrée vertex bd.ByteWidth = sizeof(SimpleVertex) * 24; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = m_pd3dDevice->CreateBuffer(&bd, &InitData, &m_pVertexBuffer); if(FAILED(hr)) return false; UINT stride = sizeof(SimpleVertex); UINT offset = 0; m_pd3dDevice->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset); /********** Index buffer **********/ bd.Usage = D3D10_USAGE_DEFAULT; // Taille d'une entrée index bd.ByteWidth = sizeof( DWORD ) * 36; bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; InitData.pSysMem = indices; hr = m_pd3dDevice->CreateBuffer(&bd, &InitData, &m_pIndexBuffer); if(FAILED(hr)) return false; // Set index buffer m_pd3dDevice->IASetIndexBuffer( m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); /* On définit le type de primitive */ m_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); /******************************************************/
On charge la texture qui sera utilisée :
// On charge la texture hr = D3DX10CreateShaderResourceViewFromFile(m_pd3dDevice, L"seafloor.dds", NULL, NULL, &m_pTextureRV, NULL); if(FAILED(hr)) return false;
On initialise les matrices et la texture :
D3DXMatrixIdentity(&m_worldMatrix); D3DXVECTOR3 Eye(0.0f, 3.0f, -6.0f); D3DXVECTOR3 At(0.0f, 0.0f, 0.0f); D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f); D3DXMatrixLookAtLH(&m_viewMatrix, &Eye, &At, &Up); // Initialize the projection matrix D3DXMatrixPerspectiveFovLH( &m_projectionMatrix, ( float )D3DX_PI * 0.25f, width / ( FLOAT )height, 0.1f, 100.0f ); // Update Variables that never change m_pViewVariable->SetMatrix( ( float* )&m_viewMatrix ); m_pProjectionVariable->SetMatrix( ( float* )&m_projectionMatrix ); m_pDiffuseVariable->SetResource( m_pTextureRV );
Résumé :
Au final nous avons affiché un petit cube texturé.
Voici l’archive du code complet pour cette partie : DirectX 10 Tutoriel – Partie 3.zip


