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 :
|
1 2 3 4 5 |
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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* 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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
//-------------------------------------------------------------------------------------- // 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) :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/******************** 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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// 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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/********** 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 :
|
1 2 3 4 |
// 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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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



