开发者

Issues with HLSL and lighting

I am trying figure out whats going on with my HLSL code but I have no way of debugging it cause C++ gives off no errors. The application just closes when I run it. I am trying to add lighting to a 3d plane I made. below is my HLSL. The problem consist when my Pixel shader method returns the struct "outColor" . If I change the return value back to the struct "psInput" , everything goes back to working again. My light vectors and colors are at the top of the fx file

// PS_INPUT - input variables to the pixel shader
// This struct is created and fill in by the 
// vertex shader
cbuffer Variables
{
    matrix Projection;
    matrix World;
    float TimeStep;
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
        float4 Color : COLOR0;
    float3 Normal : TEXCOORD0;
    float3 ViewVector : TEXCOORD1;
};

float specpower = 80.0f;
float3 camPos = float3(0.0f, 9.0, -256.0f);
float3 DirectLightColor  = float3(1.0f, 1.0f, 1.0f);
float3 DirectLightVector = float3(0.0f, 0.602f, 0.70f);
float3 AmbientLightColor = float3(1.0f, 1.0f, 1.0f);

/***************************************
* Lighting functions
***************************************/

/*********************************
* CalculateAmbient - 
* inputs - 
*   vKa material's reflective color
*   lightColor - the ambient color of the lightsource
* output - ambient color
*********************************/
float3 CalculateAmbient(float3 vKa, float3 lightColor)
{
    float3 vAmbient = vKa * lightColor;

    return vAmbient;
}

/*********************************
* CalculateDiffuse - 
* inputs - 
*   material color
*   The color of the direct light
*   the local normal
*   the vector of the direct light
* output - difuse color
*********************************/
float3 CalculateDiffuse(float3 baseColor, float3 lightColor, float3 normal, float3 lightVector)
{
    float3 vDiffuse = baseColor * lightColor * saturate(dot(normal, lightVector));

    return vDiffuse;
}


/*********************************
* CalculateSpecular - 
* inputs - 
*   viewVector
*   the direct light vector
*   the normal
* output - specular highlight
*********************************/
float CalculateSpecular(float3 viewVector, float3 lightVector, float3 normal)
{
    float3 vReflect = reflect(lightVector, normal);

    float fSpecular = saturate(dot(vReflect, viewVector));
    fSpecular = pow(fSpecular, specpower);

    return fSpecular;
}

/*********************************
* LightingCombine - 
* inputs - 
*   ambient component
*   diffuse component
*   specualr component
* output - phong color color
*********************************/
float3 LightingCombine(float3 vAmbient, float3 vDiffuse, float fSpecular)
{
    float3 vCombined = vAmbient + vDiffuse + fSpecular.xxx;

    return vCombined;
}

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

    newPosition.y = sin((newPosition.x * TimeStep) + (newPosition.z / 3.0f)) * 5.0f;

    // Pass through both the position and the color
        psInput.Pos = mul(newPosition , Projection );
    psInput.Color = Color;
    psInput.ViewVector = normalize(camPos - psInput.Pos);

    return psInput;
}


///////////////////////////////////////////////
// Pixel Shader
///////////////////////////////////////////////
//Anthony!!!!!!!!!!! Find out how color works when multiplying them

float4 PS(PS_INPUT psInput) : SV_Target
{
    float3 normal = -normalize(psInput.Normal);
    float3 vAmbient = CalculateAmbient(psInput.Color, AmbientLightColor);
    float3 vDiffuse = CalculateDiffuse(psInput.Color, DirectLightColor, normal, DirectLightVector);

    float fSpecular = CalculateSpecular(psInput.ViewVector, DirectLightVector, normal);

    float4 outColor;
    outColor.rgb = LightingCombine(vAmbient, vDiffuse, fSpecular);
    outColor.a = 1.0f;
    //Below is where the error begins
        return outColor;
}



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

Below is some of my c++ code. Reason I am showing this is because it is pretty much what creates the surface normals for my shaders to evaluate. for the lighting

modelObject.numIndices = sizeof(indices) / sizeof(DWORD);
    // compute normals for each face in the model
    for (unsigned int i = 0; i < modelObject.numIndices; i+=3)
    {
        D3DXVECTOR3 v0 = vertices[indices[i]].pos;
        D3DXVECTOR3 v1 = vertices[indices[i + 1]].pos;
        D3DXVECTOR3 v2 = vertices[indices[i + 2]].pos;

        D3DXVECTOR3 normal;
        D3DXVECTOR3 cross;
        D3DXVec3Cross(&am开发者_如何学Gop;cross, &D3DXVECTOR3(v2 - v0), &D3DXVECTOR3(v1 - v0));
        D3DXVec3Normalize(&normal, &cross);

        // assign the computed normal to each vertex in this face
        vertices[indices[i]].normal     = normal;
        vertices[indices[i + 1]].normal = normal;
        vertices[indices[i + 2]].normal = normal;
}

and below is my c++ code, in it's entirety. showing the drawing and also calling on the passes

 #include "MyGame.h"

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;

//grid information
#define NUM_COLS 16
#define NUM_ROWS 16

#define CELL_WIDTH 32
#define CELL_HEIGHT 32

#define NUM_VERTSX (NUM_COLS + 1)
#define NUM_VERTSY (NUM_ROWS + 1)

// timer variables
LARGE_INTEGER timeStart;
LARGE_INTEGER timeEnd;
LARGE_INTEGER timerFreq;
double currentTime;
float  anim_rate;


// Variable to hold how long since last frame change
float         lastElaspedFrame = 0;
// How long should the frames last
float         frameDuration = 0.5;


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

    // Get the timer frequency
    QueryPerformanceFrequency(&timerFreq);
    float freqSeconds = 1.0f / timerFreq.QuadPart;
    lastElaspedFrame = 0;

    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(200.0f, 60.0f, -20.0f), new D3DXVECTOR3(200.0f, 50.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);
    pTimeVariable = NULL;
    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 rotationAngle = 0.0f;

    // create the rotation matrix using the rotation angle
    D3DXMatrixRotationY(&WorldMatrix, rotationAngle);
    rotationAngle += (float)D3DX_PI * 0.0f;

    // 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);
    mpD3DDevice->IASetIndexBuffer(modelObject.pIndicesBuffer, DXGI_FORMAT_R32_UINT, 0);
    pTimeVariable->SetFloat((float)currentTime);

    // Set primitive topology
    mpD3DDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // 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->DrawIndexed(modelObject.numIndices,0,0);
    }
}

//Render actually incapsulates Gamedraw, so you can call data before you actually clear the buffer or after you 
//present data
void MyGame::Render()
{
    // Get the start timer count
    QueryPerformanceCounter(&timeStart);
    currentTime += anim_rate;

    DX3dApp::Render();

    QueryPerformanceCounter(&timeEnd);
    anim_rate = ( (float)timeEnd.QuadPart - (float)timeStart.QuadPart ) / timerFreq.QuadPart;
}

bool MyGame::CreateObject()
{
    VertexPos vertices[NUM_VERTSX * NUM_VERTSY];
    for(int z=0; z < NUM_VERTSY; ++z)
    {
        for(int x = 0; x < NUM_VERTSX; ++x)
        {
            vertices[x + z * NUM_VERTSX].pos.x = (float)x * CELL_WIDTH;
            vertices[x + z * NUM_VERTSX].pos.z = (float)z * CELL_HEIGHT;

            vertices[x + z * NUM_VERTSX].pos.y = (float)(rand() % CELL_HEIGHT);

            vertices[x + z * NUM_VERTSX].color = D3DXVECTOR4(1.0, 0.0f, 0.0f, 0.0f);
        }
    }

    DWORD indices[NUM_COLS * NUM_ROWS * 6];
    int curIndex = 0;

    for(int z=0; z < NUM_ROWS; ++z)
    {
        for(int x = 0; x < NUM_COLS; ++x)
        {
            int curVertex = x + (z * NUM_VERTSX);
            indices[curIndex] = curVertex;
            indices[curIndex + 1] = curVertex + NUM_VERTSX;
            indices[curIndex + 2] = curVertex + 1;


            indices[curIndex + 3] = curVertex + 1;
            indices[curIndex + 4] = curVertex + NUM_VERTSX;
            indices[curIndex + 5] = curVertex + NUM_VERTSX + 1;

            curIndex += 6;
        }
    }
    modelObject.numIndices = sizeof(indices) / sizeof(DWORD);
    // compute normals for each face in the model
    for (unsigned int i = 0; i < modelObject.numIndices; i+=3)
    {
        D3DXVECTOR3 v0 = vertices[indices[i]].pos;
        D3DXVECTOR3 v1 = vertices[indices[i + 1]].pos;
        D3DXVECTOR3 v2 = vertices[indices[i + 2]].pos;

        D3DXVECTOR3 normal;
        D3DXVECTOR3 cross;
        D3DXVec3Cross(&cross, &D3DXVECTOR3(v2 - v0), &D3DXVECTOR3(v1 - v0));
        D3DXVec3Normalize(&normal, &cross);

        // assign the computed normal to each vertex in this face
        vertices[indices[i]].normal     = normal;
        vertices[indices[i + 1]].normal = normal;
        vertices[indices[i + 2]].normal = normal;

    }


    //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 , 28, D3D10_INPUT_PER_VERTEX_DATA, 0}
    };

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

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

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

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


There is an application, an executable file that ships with DirectX, fxc.exe. You can use that to get rid of syntax errors in your shaders!


Try turning up the direct3d debug output. Start the directx control panel then go to the Direct3D 10 tab. Add you application to the scope list then check "Force On" in the debug layer category.

You should find that D3D gives you more debug output.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜