开发者

Issues passing values to shader

I am having issues passing values to my shader. My application compiles fine, but my cube object won't shade. Below is majority of my code.

Most of my code for communicating with my shader is in createObject method

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, &ModelObje开发者_JAVA百科ct.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;
}

And below is my shader

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


What do you mean exactly by "my cube object won't shade" ? What's the final color? White?

From what you post, some stuff are looking wrong. First, the manner you define your light vector:

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

This is wrong since it's not normalized and has to be (either in hlsl or c++ code) otherwise dot product is meaningless (see wikipedia page on Dot product, Geometric interpretation). You could also use already normalized vectors like: [-0.577f, 0.577f, -0.577f] or [0.0f, 0.0f, -1.0f] and don't care of normalization.

Second thing, in the VS, you don't transform the vertex normal according to a World matrix. This is bad especially if your light direction has been defined in world-space and your cube normals stay in model-space. Well this is maybe not the cause of the bad shading, but it's important to mention you can't do math on vectors that belong to different spaces.

Third point is the c++ code that initialize cube colors (I can't find it, as well as vertice positions). To me your code looks badly architectured since every attributes should be at least initialized in the same CreateObject function.

About shader coding style, I would recommend declaring PS_INPUT like this:

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

So there is no confusion with between COLOR and SV_Target. All non SV_* attributes should use TEXCOORDN.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜