HLSL和照明的问题

时间:2010-05-09 01:29:09

标签: c++ c visual-studio hlsl

我正在尝试弄清楚我的HLSL代码是怎么回事,但是我无法调试它,因为C ++没有发现任何错误。应用程序在我运行时关闭。我正在尝试将光照添加到我制作的3d平面上。下面是我的HLSL。问题在于我的Pixel着色器方法返回结构“outColor”。如果我将返回值更改回结构“psInput”,一切都会重新开始工作。我的光矢量和颜色位于fx文件的顶部

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

以下是我的一些c ++代码。我展示这个的原因是因为它几乎是为我的着色器创建表面法线以进行评估的原因。用于照明

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

以下是我的c ++代码,完整的。显示图纸并调用通行证

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

2 个答案:

答案 0 :(得分:1)

有一个应用程序,一个随DirectX,fxc.exe一起提供的可执行文件。您可以使用它来消除着色器中的语法错误!

答案 1 :(得分:0)

尝试调高direct3d调试输出。启动directx控制面板,然后转到Direct3D 10选项卡。将应用程序添加到范围列表中,然后在调试层类别中选中“强制打开”。

你会发现D3D为你提供了更多的调试输出。