2010-05-26 66 views
1

我遇到了将值传递给着色器的问题。我的应用程序编译得很好,但我的立方体对象不会遮挡。以下是我的大部分代码。将值传递给着色器的问题

我的大部分代码与我沟通着色器在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; 
} 

而下面是我的着色器

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())); 
    } 
} 

回答

1

你什么意思是由“我的立方体对象不会阴影”?最终的颜色是什么?白色?

从你发布的信息看,有些东西看起来不对。首先,你的方式定义你的光矢量:

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

这是错误的,因为它不是标准化的,且必须(在HLSL或C++代码),否则点积是没有意义的(见wikipedia page on Dot product, Geometric interpretation)。您也可以使用已标准化的矢量,如: [-0.577f, 0.577f, -0.577f][0.0f, 0.0f, -1.0f],并且不关心标准化。

第二件事,在VS,你不根据世界矩阵转换顶点法线。如果您的光线方向已在世界空间中定义并且您的立方体法线保持在模型空间中,这种情况尤其糟糕。 嗯,这可能不是坏阴影的原因,但重要的是要提到你不能对属于不同空间的向量进行数学运算。

第三点是初始化立方体颜色(我无法找到它,以及顶点位置)的C++代码。对我来说,你的代码看起来很糟糕,因为每个属性至少应该在同一个CreateObject函数中初始化。

关于着色器的编码风格,我会建议宣布PS_INPUT这样的:

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

所以有与COLORSV_Target之间不存在混淆。所有非SV_*属性应该使用TEXCOORDN

+0

我实际上设法解决了这个问题。主要问题是正常化。你说得对。对于留在模型空间中的法线也是正确的。当我试图旋转立方体时,两侧都保持阴影,这表明我的模型空间仍然存在法线。如果你不介意,我的后续问题。因为我仍然试图弄清楚这是......“我可以乘以投影空间还是需要我的法线,或者只能将它乘以世界空间。我想我必须在世界空间中繁衍它。接下来我会准备好。 – numerical25 2010-05-29 18:44:00

+0

您不会将矢量乘以“空间”,而是乘以一个输入空间中的矢量并生成属于输出空间的新矢量的变换矩阵。通常顶点通过WVP矩阵(世界观投影连接矩阵)进行变换,最后在投影空间中结束,或者更精确地剪切空间。栅格化步骤执行w-division aka透视图div。并将您的顶点转换为NDC空间(-1 Stringer 2010-05-30 18:08:00

+0

你可以使用世界矩阵变换(不要忘记用0.0f初始化w-coord,因为它是一个矢量而不是一个点)。但要小心这对于一般情况并不准确。例如。你的3D网格上有一个缩放矩阵。在这些情况下,通常需要逆转换WV矩阵,我让你找出原因。 但请记住,对于法线转换,您并不局限于特定的空间。这完全取决于开发人员在哪个空间中进行照明计算。你可以在切线空间工作。 – Stringer 2010-05-30 18:37:16