Introduction à DirectX 10 – Texturing – partie 3

directx9c

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é.

partie3

Voici l’archive du code complet pour cette partie :  DirectX 10 Tutoriel – Partie 3.zip

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *