2010-05-26 23 views
1

Je rencontre des problèmes en transmettant des valeurs à mon shader. Mon application compile bien, mais mon objet cube ne sera pas ombragé. Ci-dessous la majorité de mon code.Problèmes qui transmettent des valeurs au shader

La plupart de mon code pour communiquer avec mon shader est dans la méthode CreateObject

myGame.cpp

#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; 
ID3D10EffectVectorVariable* pLightVarible = NULL; 


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; 

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


    //rotationAngleY += (float)D3DX_PI * 0.002f; 
    //rotationAngleX += (float)D3DX_PI * 0.001f; 

    WorldMatrix = rotationYMatrix * rotationXMatrix; 

    // Set the input layout 
    mpD3DDevice->IASetInputLayout(modelObject.pVertexLayout); 

    // 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} 
    }; 

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

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

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


    //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 ci-dessous est mon shaders

effect.fx

matrix Projection; 
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; 
}; 

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

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

    return psInput; 
} 

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

    return finalColor; 
} 

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

Répondre

1

Que voulez-vous dire exactement par "mon cube objet ne nuance pas"? Quelle est la couleur finale? Blanc? D'après ce que vous publiez, certaines choses ne semblent pas correctes. Tout d'abord, la manière définiriez-vous votre vecteur de lumière:

D3DXVECTOR3 vLight(10.0f, 10.0f, 10.0f); 

Ceci est faux car il n'est pas normalisée et doit être (que ce soit en HLSL ou C++ code) produit autrement dot n'a pas de sens (voir wikipedia page on Dot product, Geometric interpretation). Vous pouvez également utiliser des vecteurs déjà normalisés comme: [-0.577f, 0.577f, -0.577f] ou [0.0f, 0.0f, -1.0f] et ne se soucient pas de la normalisation.

Deuxième chose, dans le VS, vous ne transformez pas le vertex normal selon une matrice World. C'est mauvais surtout si votre direction de la lumière a été définie dans l'espace-monde et que vos normales de cube restent dans l'espace-modèle. Eh bien, ce n'est peut-être pas la cause du mauvais ombrage, mais il est important de mentionner que vous ne pouvez pas faire de maths sur des vecteurs appartenant à des espaces différents.

Le troisième point est le code C++ qui initialise les couleurs de cube (je ne le trouve pas, ainsi que les positions de vertice). Pour moi, votre code semble mal architecturé puisque tous les attributs doivent être au moins initialisés dans la même fonction CreateObject.

A propos de style de codage de shaders, je recommande de déclarer PS_INPUT comme ceci:

struct PS_INPUT 
{ 
    float4 Pos : SV_Position; 
    float4 Col : TEXCOORD0; 
    float3 Norm : TEXCOORD1; 
}; 

donc il n'y a pas de confusion avec entre COLOR et SV_Target. Tous les attributs autres que SV_* doivent utiliser TEXCOORDN.

+0

J'ai effectivement réussi à résoudre le problème il y a quelque temps. Le problème principal était la normalisation. Vous aviez raison à ce sujet. Et ont également raison sur les normales restant dans l'espace modèle. quand j'ai essayé de faire tourner le cube, les côtés sont restés ombrés de tous les côtés ce qui m'a indiqué que les normales restaient dans l'espace modèle. Ma question de suivi si cela ne vous dérange pas. Parce que je suis encore en train d'essayer de comprendre cela est ... 'Puis-je multiplier mes normales par l'espace de projection ou besoin je dois le multiplier par l'espace du monde seulement. Je pense que je dois le multiplier par l'espace du monde. J'allais donner un coup de feu ensuite. – numerical25

+0

Vous ne multipliez pas un vecteur par un "espace" mais une matrice de transformation qui prend un vecteur d'un espace d'entrée et produit un nouveau vecteur qui appartient à un espace de sortie. Habituellement, les sommets sont transformés par une matrice WVP (matrice de concaténation de projection de vue du monde) et finissent ainsi dans l'espace projectif, ou plus précisément dans l'espace de découpage. L'étape de rastérisation exécute la div division de la division w. et transforme vos sommets dans l'espace NDC (-1 Stringer

+0

Vous pouvez simplement utiliser une transformation de matrice du monde (n'oubliez pas d'initialiser w-coord avec 0.0f car c'est un vecteur et non un point). Mais attention, ceci ne sera pas exact pour le cas général. PAR EXEMPLE. vous avez une matrice d'échelle sur votre maillage 3D. Dans ces cas, une matrice WV à transposition inverse est généralement nécessaire, je vous laisse découvrir pourquoi. Mais gardez à l'esprit que pour la transformation des normales, vous n'êtes pas limité à un espace spécifique. C'est au développeur de décider dans quel espace vous voulez faire le calcul de l'éclairage. Vous pourriez travailler par exemple dans l'espace tangent. – Stringer