2010-05-29 6 views
1

J'essaie d'appliquer une texture sur mon cube 3D mais il ne s'affiche pas correctement. Je crois que cela pourrait fonctionner parce que le cube est tout brun qui a presque le même teint que la texture. Et à l'origine, je n'ai pas rendu le cube brun. Ce sont les étapes que j'ai fait ajouter la textureLa texture ne s'applique pas à mon cube 3d directX

j'ai 2 Déclaré nouvelles varibles

ID3D10EffectShaderResourceVariable* pTextureSR; 
ID3D10ShaderResourceView* textureSRV; 

J'ai aussi ajouté une variable et un struct à mon shaders .fx fichier

Texture2D tex2D; 

SamplerState linearSampler 
{ 
    Filter = MIN_MAG_MIP_LINEAR; 
    AddressU = Wrap; 
    AddressV = Wrap; 
}; 

J'ai ensuite saisi l'image de mon disque dur local à partir du fichier .cpp. Je crois que cela a été un succès, j'ai vérifié toutes les variables pour les erreurs, tout a une adresse mémoire. De plus, j'ai tiré des ressources avant et n'a jamais eu de problème.

D3DX10CreateShaderResourceViewFromFile(mpD3DDevice,L"crate.jpg",NULL,NULL,&textureSRV,NULL); 

J'ai attrapé le varible de tex2D de mon fichier fx et placé dans ma ressource varible

pTextureSR = modelObject.pEffect->GetVariableByName("tex2D")->AsShaderResource(); 

Et a ajouté la ressource à la varible

pTextureSR->SetResource(textureSRV); 

J'ai aussi ajouté la propriété supplémentaire pour ma disposition des sommets

D3D10_INPUT_ELEMENT_DESC layout[] = { 
    {"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT, 0 , 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, 
    {"COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT, 0 , 12, D3D10_INPUT_PER_VERTEX_DATA, 0}, 
    {"NORMAL",0,DXGI_FORMAT_R32G32B32A32_FLOAT, 0 , 24, D3D10_INPUT_PER_VERTEX_DATA, 0}, 
    {"TEXCOORD",0, DXGI_FORMAT_R32G32_FLOAT, 0 , 36, D3D10_INPUT_PER_VERTEX_DATA, 0} 
}; 

ainsi que mon struct

struct VertexPos 
{ 
    D3DXVECTOR3 pos; 
    D3DXVECTOR4 color; 
    D3DXVECTOR3 normal; 
    D3DXVECTOR2 texCoord; 
}; 

Puis je crée un nouveau pixel shader qui ajoute la texture. Ci-dessous le code dans son intégralité

matrix Projection; 
matrix WorldMatrix; 
Texture2D tex2D; 

float3 lightSource; 
float4 lightColor = {0.5, 0.5, 0.5, 0.5}; 

// PS_INPUT - input variables to the pixel shader 
// This struct is created and fill in by the 
// vertex shader 
struct PS_INPUT 
{ 
    float4 Pos : SV_POSITION; 
    float4 Color : COLOR0; 
    float4 Normal : NORMAL; 
    float2 Tex : TEXCOORD; 
}; 

SamplerState linearSampler 
{ 
    Filter = MIN_MAG_MIP_LINEAR; 
    AddressU = Wrap; 
    AddressV = Wrap; 
}; 


//////////////////////////////////////////////// 
// Vertex Shader - Main Function 
/////////////////////////////////////////////// 
PS_INPUT VS(float4 Pos : POSITION, float4 Color : COLOR, float4 Normal : NORMAL, float2 Tex : TEXCOORD) 
{ 
    PS_INPUT psInput; 

    // Pass through both the position and the color 
    psInput.Pos = mul(Pos, Projection); 
    psInput.Normal = Normal; 
    psInput.Tex = Tex; 

    return psInput; 
} 

/////////////////////////////////////////////// 
// Pixel Shader 
/////////////////////////////////////////////// 
float4 PS(PS_INPUT psInput) : SV_Target 
{ 
    float4 finalColor = 0; 
    finalColor = saturate(dot(lightSource, psInput.Normal) * lightColor); 

    return finalColor; 
} 

float4 textured(PS_INPUT psInput) : SV_Target 
{ 
    return tex2D.Sample(linearSampler, psInput.Tex); 
} 



// Define the technique 
technique10 Render 
{ 
    pass P0 
    { 
     SetVertexShader(CompileShader(vs_4_0, VS())); 
     SetGeometryShader(NULL); 
     SetPixelShader(CompileShader(ps_4_0, textured())); 
    } 
} 

Ci-dessous le code de votre CPU. C'est peut-être un peu négligé. Mais je ne fais qu'ajouter du code n'importe où parce que je suis en train d'expérimenter et de jouer. Vous devriez trouver la plupart du code de texture au fond createObject

#include "MyGame.h" 
#include "OneColorCube.h" 
/* This code sets a projection and shows a turning cube. What has been added is the project, rotation and 
a rasterizer to change the rasterization of the cube. The issue that was going on was something with the effect file 
which was causing the vertices not to be rendered correctly.*/ 
typedef struct 
{ 
    ID3D10Effect* pEffect; 
    ID3D10EffectTechnique* pTechnique; 

    //vertex information 
    ID3D10Buffer* pVertexBuffer; 
    ID3D10Buffer* pIndicesBuffer; 
    ID3D10InputLayout* pVertexLayout; 

    UINT numVertices; 
    UINT numIndices; 
}ModelObject; 

ModelObject modelObject; 
// World Matrix 
D3DXMATRIX     WorldMatrix; 
// View Matrix 
D3DXMATRIX     ViewMatrix; 
// Projection Matrix 
D3DXMATRIX     ProjectionMatrix; 
ID3D10EffectMatrixVariable* pProjectionMatrixVariable = NULL; 
ID3D10EffectMatrixVariable* pWorldMatrixVarible = NULL; 
ID3D10EffectVectorVariable* pLightVarible = NULL; 
ID3D10EffectShaderResourceVariable* pTextureSR; 


bool MyGame::InitDirect3D() 
{ 
    if(!DX3dApp::InitDirect3D()) 
    { 
     return false; 
    } 

    D3D10_RASTERIZER_DESC rastDesc; 
    rastDesc.FillMode = D3D10_FILL_WIREFRAME; 
    rastDesc.CullMode = D3D10_CULL_FRONT; 
    rastDesc.FrontCounterClockwise = true; 
    rastDesc.DepthBias = false; 
    rastDesc.DepthBiasClamp = 0; 
    rastDesc.SlopeScaledDepthBias = 0; 
    rastDesc.DepthClipEnable = false; 
    rastDesc.ScissorEnable = false; 
    rastDesc.MultisampleEnable = false; 
    rastDesc.AntialiasedLineEnable = false; 

    ID3D10RasterizerState *g_pRasterizerState; 
    mpD3DDevice->CreateRasterizerState(&rastDesc, &g_pRasterizerState); 
    //mpD3DDevice->RSSetState(g_pRasterizerState); 

    // Set up the World Matrix 
    D3DXMatrixIdentity(&WorldMatrix); 
    D3DXMatrixLookAtLH(&ViewMatrix, new D3DXVECTOR3(0.0f, 10.0f, -20.0f), new D3DXVECTOR3(0.0f, 0.0f, 0.0f), new D3DXVECTOR3(0.0f, 1.0f, 0.0f)); 
    // Set up the projection matrix 
    D3DXMatrixPerspectiveFovLH(&ProjectionMatrix, (float)D3DX_PI * 0.5f, (float)mWidth/(float)mHeight, 0.1f, 100.0f); 


    if(!CreateObject()) 
    { 
     return false; 
    } 

    return true; 
} 

//These are actions that take place after the clearing of the buffer and before the present 
void MyGame::GameDraw() 
{ 

    static float rotationAngleY = 15.0f; 
    static float rotationAngleX = 0.0f; 

    static D3DXMATRIX rotationXMatrix; 
    static D3DXMATRIX rotationYMatrix; 

    D3DXMatrixIdentity(&rotationXMatrix); 
    D3DXMatrixIdentity(&rotationYMatrix); 

    // create the rotation matrix using the rotation angle 
    D3DXMatrixRotationY(&rotationYMatrix, rotationAngleY); 
    D3DXMatrixRotationX(&rotationXMatrix, rotationAngleX); 


    rotationAngleY += (float)D3DX_PI * 0.0008f; 
    rotationAngleX += (float)D3DX_PI * 0.0005f; 

    WorldMatrix = rotationYMatrix * rotationXMatrix; 

    // Set the input layout 
    mpD3DDevice->IASetInputLayout(modelObject.pVertexLayout); 
    pWorldMatrixVarible->SetMatrix((float*)&WorldMatrix); 

    // Set vertex buffer 
    UINT stride = sizeof(VertexPos); 
    UINT offset = 0; 
    mpD3DDevice->IASetVertexBuffers(0, 1, &modelObject.pVertexBuffer, &stride, &offset); 

    // Set primitive topology 
    mpD3DDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 
    //ViewMatrix._43 += 0.005f; 

    // Combine and send the final matrix to the shader 
    D3DXMATRIX finalMatrix = (WorldMatrix * ViewMatrix * ProjectionMatrix); 
    pProjectionMatrixVariable->SetMatrix((float*)&finalMatrix); 


    // make sure modelObject is valid 


    // Render a model object 
    D3D10_TECHNIQUE_DESC techniqueDescription; 
    modelObject.pTechnique->GetDesc(&techniqueDescription); 

    // Loop through the technique passes 
    for(UINT p=0; p < techniqueDescription.Passes; ++p) 
    { 
     modelObject.pTechnique->GetPassByIndex(p)->Apply(0); 

     // draw the cube using all 36 vertices and 12 triangles 
     mpD3DDevice->Draw(36,0); 
    } 
} 

//Render actually incapsulates Gamedraw, so you can call data before you actually clear the buffer or after you 
//present data 
void MyGame::Render() 
{ 
    DX3dApp::Render(); 
} 

bool MyGame::CreateObject() 
{ 

    //Create Layout 
    D3D10_INPUT_ELEMENT_DESC layout[] = { 
     {"POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT, 0 , 0, D3D10_INPUT_PER_VERTEX_DATA, 0}, 
     {"COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT, 0 , 12, D3D10_INPUT_PER_VERTEX_DATA, 0}, 
     {"NORMAL",0,DXGI_FORMAT_R32G32B32A32_FLOAT, 0 , 24, D3D10_INPUT_PER_VERTEX_DATA, 0}, 
     {"TEXCOORD",0, DXGI_FORMAT_R32G32_FLOAT, 0 , 36, D3D10_INPUT_PER_VERTEX_DATA, 0} 
    }; 

    UINT numElements = (sizeof(layout)/sizeof(layout[0])); 
    modelObject.numVertices = sizeof(vertices)/sizeof(VertexPos); 

    for(int i = 0; i < modelObject.numVertices; i += 3) 
    { 
     D3DXVECTOR3 out; 

     D3DXVECTOR3 v1 = vertices[0 + i].pos; 
     D3DXVECTOR3 v2 = vertices[1 + i].pos; 
     D3DXVECTOR3 v3 = vertices[2 + i].pos; 

     D3DXVECTOR3 u = v2 - v1; 
     D3DXVECTOR3 v = v3 - v1; 

     D3DXVec3Cross(&out, &u, &v); 
     D3DXVec3Normalize(&out, &out); 

     vertices[0 + i].normal = out; 
     vertices[1 + i].normal = out; 
     vertices[2 + i].normal = out; 
    } 

    //Create buffer desc 
    D3D10_BUFFER_DESC bufferDesc; 
    bufferDesc.Usage = D3D10_USAGE_DEFAULT; 
    bufferDesc.ByteWidth = sizeof(VertexPos) * modelObject.numVertices; 
    bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER; 
    bufferDesc.CPUAccessFlags = 0; 
    bufferDesc.MiscFlags = 0; 

    D3D10_SUBRESOURCE_DATA initData; 
    initData.pSysMem = vertices; 
    //Create the buffer 

    HRESULT hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &modelObject.pVertexBuffer); 
    if(FAILED(hr)) 
     return false; 

    /* 
    //Create indices 
    DWORD indices[] = 
    { 
     0,1,3, 
     1,2,3 
    }; 

    ModelObject.numIndices = sizeof(indices)/sizeof(DWORD); 

    bufferDesc.ByteWidth = sizeof(DWORD) * ModelObject.numIndices; 
    bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; 

    initData.pSysMem = indices; 

    hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &ModelObject.pIndicesBuffer); 
    if(FAILED(hr)) 
     return false;*/ 


    ///////////////////////////////////////////////////////////////////////////// 
    //Set up fx files 
    LPCWSTR effectFilename = L"effect.fx"; 
    modelObject.pEffect = NULL; 

    hr = D3DX10CreateEffectFromFile(effectFilename, 
     NULL, 
     NULL, 
     "fx_4_0", 
     D3D10_SHADER_ENABLE_STRICTNESS, 
     0, 
     mpD3DDevice, 
     NULL, 
     NULL, 
     &modelObject.pEffect, 
     NULL, 
     NULL); 

    if(FAILED(hr)) 
     return false; 

    pProjectionMatrixVariable = modelObject.pEffect->GetVariableByName("Projection")->AsMatrix(); 
    pWorldMatrixVarible = modelObject.pEffect->GetVariableByName("WorldMatrix")->AsMatrix(); 
    pTextureSR = modelObject.pEffect->GetVariableByName("tex2D")->AsShaderResource(); 

    ID3D10ShaderResourceView* textureSRV; 
    D3DX10CreateShaderResourceViewFromFile(mpD3DDevice,L"crate.jpg",NULL,NULL,&textureSRV,NULL); 

    pLightVarible = modelObject.pEffect->GetVariableByName("lightSource")->AsVector(); 
    //Dont sweat the technique. Get it! 
    LPCSTR effectTechniqueName = "Render"; 

    D3DXVECTOR3 vLight(1.0f, 1.0f, 1.0f); 
    pLightVarible->SetFloatVector(vLight); 

    modelObject.pTechnique = modelObject.pEffect->GetTechniqueByName(effectTechniqueName); 
    if(modelObject.pTechnique == NULL) 
     return false; 

    pTextureSR->SetResource(textureSRV); 


    //Create Vertex layout 
    D3D10_PASS_DESC passDesc; 
    modelObject.pTechnique->GetPassByIndex(0)->GetDesc(&passDesc); 

    hr = mpD3DDevice->CreateInputLayout(layout, numElements, 
     passDesc.pIAInputSignature, 
     passDesc.IAInputSignatureSize, 
     &modelObject.pVertexLayout); 
    if(FAILED(hr)) 
     return false; 

    return true; 
} 

Et voici mes coordonnées de cube. En fait, j'ai seulement ajouté des coordonnées d'un côté. Et c'est le recto. Pour vérifier que je feuilletais le cube dans toutes les directions juste pour vous assurer que je ne ai pas accidentellement placer le texte du mauvais côté

//Create vectors and put in vertices 

    // Create vertex buffer 
    VertexPos vertices[] = 
    { 
     // BACK SIDES 
     { D3DXVECTOR3(-5.0f, 5.0f, 5.0f), D3DXVECTOR4(1.0f,0.0f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(-5.0f, -5.0f, 5.0f), D3DXVECTOR4(1.0f,0.0f,0.0f,0.0f), D3DXVECTOR2(1.0,0.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, 5.0f), D3DXVECTOR4(1.0f,0.0f,0.0f,0.0f), D3DXVECTOR2(0.0,1.0)}, 

     { D3DXVECTOR3(5.0f, 5.0f, 5.0f), D3DXVECTOR4(1.0f,0.0f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(-5.0f, -5.0f, 5.0f), D3DXVECTOR4(1.0f,0.0f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, -5.0f, 5.0f), D3DXVECTOR4(1.0f,0.0f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     // 2 FRONT SIDE 
     { D3DXVECTOR3(-5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f), D3DXVECTOR2(2.0,0.0)}, 
     { D3DXVECTOR3(-5.0f, -5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f), D3DXVECTOR2(0.0,2.0)}, 

     { D3DXVECTOR3(-5.0f, -5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f), D3DXVECTOR2(0.0,2.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f) , D3DXVECTOR2(2.0,0.0)}, 
     { D3DXVECTOR3(5.0f, -5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f), D3DXVECTOR2(2.0,2.0)}, 

     // 3 
     { D3DXVECTOR3(-5.0f, 5.0f, 5.0f), D3DXVECTOR4(0.0f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, 5.0f), D3DXVECTOR4(0.0f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(-5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.0f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     { D3DXVECTOR3(-5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.0f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, 5.0f), D3DXVECTOR4(0.0f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.0f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     // 4 
     { D3DXVECTOR3(-5.0f, -5.0f, 5.0f), D3DXVECTOR4(1.0f,0.5f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(-5.0f, -5.0f, -5.0f), D3DXVECTOR4(1.0f,0.5f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, -5.0f, 5.0f), D3DXVECTOR4(1.0f,0.5f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     { D3DXVECTOR3(5.0f, -5.0f, 5.0f), D3DXVECTOR4(1.0f,0.5f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(-5.0f, -5.0f, -5.0f), D3DXVECTOR4(1.0f,0.5f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, -5.0f, -5.0f), D3DXVECTOR4(1.0f,0.5f,0.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     // 5 
     { D3DXVECTOR3(5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.5f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, 5.0f), D3DXVECTOR4(0.0f,1.0f,0.5f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, -5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.5f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     { D3DXVECTOR3(5.0f, -5.0f, -5.0f), D3DXVECTOR4(0.0f,1.0f,0.5f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, 5.0f, 5.0f), D3DXVECTOR4(0.0f,1.0f,0.5f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     { D3DXVECTOR3(5.0f, -5.0f, 5.0f), D3DXVECTOR4(0.0f,1.0f,0.5f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     // 6 
     {D3DXVECTOR3(-5.0f, 5.0f, -5.0f), D3DXVECTOR4(0.5f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     {D3DXVECTOR3(-5.0f, -5.0f, -5.0f), D3DXVECTOR4(0.5f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     {D3DXVECTOR3(-5.0f, 5.0f, 5.0f), D3DXVECTOR4(0.5f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 

     {D3DXVECTOR3(-5.0f, 5.0f, 5.0f), D3DXVECTOR4(0.5f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     {D3DXVECTOR3(-5.0f, -5.0f, -5.0f), D3DXVECTOR4(0.5f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
     {D3DXVECTOR3(-5.0f, -5.0f, 5.0f), D3DXVECTOR4(0.5f,0.0f,1.0f,0.0f), D3DXVECTOR2(0.0,0.0)}, 
    }; 

Ok, donc j'ajouté un HRESULT dans le code suivant

HRESULT *pHResult = NULL; 

D3DX10CreateShaderResourceViewFromFile(mpD3DDevice,L"crate.jpg",NULL,NULL,&textureSRV,pHResult); 

I vérifié le résultat et il n'a rien retourné. l'adresse pour l'échec de pHResult 0x00000 pour évaluer l'expression. Je ne sais pas si c'est parce que ce n'est pas charger crate.jpg correctement ou quoi. L'emplacement est correct. J'ai crate.jpg dans le même emplacement que mon fichier effect.fx. et j'ai chargé mon fichier d'effets de la même manière. "effect.fx"

Si quelqu'un pouvait regarder mes sommets et s'assurer que mes coordonnées UV sont correctes. ce serait génial. Je suis un peu sceptique à ce sujet.

+0

Ok, rien, je lis dans MSDN, que la valeur de pHResult retourne habituellement NULL. Donc je l'ai ajouté comme ça ... pHResult = D3DX10CreateShaderResourceViewFromFile (mpD3DDevice, L "crate.bmp", NULL, NULL, & textureSRV, NULL); Il est retourné comme S_OK. Je n'ai aucune idée de ce problème. – numerical25

+1

C'est une question assez longue ... eh bien ... plus probablement un train de pensée se terminant sur une ligne abandonnée. Réduisez-le la prochaine fois pour vous intéresser. – Jamie

Répondre

1

bien je l'ai compris. Dans ma description de disposition de sommet, mon décalage est éteint. J'ai incrémenté ma couleur de 12 quand il devrait être 16 parce que rgba. Quoi qu'il en soit, je l'ai corrigé et maintenant la texture apparaît mais incorrectement. Je vais poster un autre pour ce problème.

Questions connexes