使用着色器问题照亮多维数据集

时间:2014-11-09 15:54:22

标签: c++ visual-c++ directx directx-11

我一直在使用一本书关注directx 11上的教程,现在正尝试使用着色器为我的代码提供一些照明效果。但问题是它只显示后台缓冲区,并且似乎根本没有使用灯光着色器文件。我想点亮一个立方体。谢谢你的帮助。 HLSL:

struct DirectionalLight
{
   float4 Ambient;
   float4 Diffuse;
   float4 Specular;
   float3 Direction;
   float pad;
};

struct PointLight
{
   float4 Ambient;
   float4 Diffuse;
   float4 Specular;

   float3 Position;
   float Range;

   float3 Att;
   float pad;
};

struct SpotLight
{
   float4 Ambient;
   float4 Diffuse;
   float4 Specular;

   float3 Position;
   float Range;

   float3 Direction;
   float Spot;

   float3 Att;
   float pad;
};

struct Material
{
   float4 Ambient;
   float4 Diffuse;
   float4 Specular;
   float4 Reflect;
};

void ComputeDirectionalLight( Material mat, DirectionalLight L, float3 normal, float3 toEye, out float4 ambient, out float4 diffuse, out float4 spec)
{
   ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
   diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
   spec =    float4(0.0f, 0.0f, 0.0f, 0.0f);

   float3 lightVec = -L.Direction;
   ambient = mat.Ambient * L.Ambient;
   float diffuseFactor = dot(lightVec, normal);

   [flatten]
   if( diffuseFactor > 0.0f )
   {
      float3 v = reflect(-lightVec, normal);
      float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);
      diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
      spec = specFactor * mat.Specular * L.Specular;
   }
}

void ComputePointLight(Material mat, PointLight L, float3 pos, float3 normal, float3 toEye, out float4 ambient, out float4 diffuse, out float4 spec)
{
   ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
   diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
   spec    = float4(0.0f, 0.0f, 0.0f, 0.0f);

   float3 LightVec = L.Position - pos;
   float d = length(LightVec);

   if( d > L.Range )
   return;

   LightVec /= d;

   ambient = mat.Ambient * L.Ambient;

   float diffuseFactor = dot(LightVec, normal);

   [flatten]
   if(diffuseFactor > 0.0f)
   {
       float3 v = reflect(-LightVec, normal);
       float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);
       diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
       spec = specFactor * mat.Specular * L.Specular;
   }

   float att = 1.0f / dot(L.Att, float3(1.0f, d, d*d));
   diffuse *= att;
   spec *= att;
}

void ComputeSpotLight(Material mat, SpotLight L, float3 pos, float3 normal, float3 toEye, out float4 ambient, out float4 diffuse, out float4 spec)
{
   ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
   diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
   spec = float4(0.0f, 0.0f, 0.0f, 0.f);

   float3 LightVec = L.Position - pos;
   float d = length(LightVec);

   if( d > L.Range )
   return;

   LightVec /= d;

   ambient = mat.Ambient * L.Ambient;
   float diffuseFactor = dot(LightVec, normal);

   [flatten]
   if( diffuseFactor > 0.0f )
   {
    float3 v = reflect(-LightVec, normal);
    float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);
    diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
    spec = specFactor * mat.Specular * L.Specular;
   }

   float spot = pow(max(dot(-LightVec, L.Direction), 0.0f), L.Spot);
   float att = spot / dot(L.Att, float3(1.0f, d, d*d));

   ambient *= spot;
   diffuse *= att;
   spec *= att;
}

cbuffer cbPerFrame
{
    DirectionalLight gDirLight;
    PointLight gPointLight;
    SpotLight gSpotLight;
    float3 gEyePosW;
};

cbuffer cbPerObject
{
    float4x4 gWorld;
    float4x4 gWorldInvTranspose;
    float4x4 gWorldViewProj;
    Material gMaterial;
};

struct VertexIn
{
    float3 PosL : POSITION;
    float3 NormalL : NORMAL;
};

struct VertexOut
{
    float4 PosH : SV_POSITION;
    float3 PosW : POSITION;
    float3 NormalW: NORMAL;
};

VertexOut VS(VertexIn vin)
{
   VertexOut vout;
   vout.PosW = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
   vout.NormalW = mul(vin.NormalL, (float3x3)gWorldInvTranspose);
   vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
   return vout;
}

float4 PS(VertexOut pin) : SV_Target
{
    pin.NormalW = normalize(pin.NormalW);
    float3 toEyeW = normalize(gEyePosW - pin.PosW);
    float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
    float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
    float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f);
    float4 A, D, S;

    ComputeDirectionalLight(gMaterial, gDirLight, pin.NormalW, toEyeW, A, D, S);
    ambient += A;
    diffuse += D;
    spec += S;

    ComputePointLight(gMaterial, gPointLight, pin.PosW, pin.NormalW, toEyeW, A, D, S);
    ambient += A;
    diffuse += D;
    spec += S;

    ComputeSpotLight(gMaterial, gSpotLight, pin.PosW, pin.NormalW, toEyeW, A, D, S);
    ambient += A;
    diffuse += D;
    spec += S;

    float4 litColor = ambient + diffuse + spec;
    litColor.a = gMaterial.Diffuse.a;
    return litColor;
}

我的cpp文件中的代码:

struct Vertex
{
    XMFLOAT3 Pos;
    XMFLOAT3 Normal;
};

struct CBUFFER{ XMMATRIX gWorldViewProj; };

class BoxApp : public Framework_App
{
public:
    BoxApp(HINSTANCE hInstance);
    ~BoxApp();

    bool Init();
    void OnResize();
    void UpdateScene(float dt);
    void DrawScene();

    void OnMouseDown(WPARAM BtnState, int x, int y);
    void OnMouseUp(WPARAM BtnState, int x, int y);
    void OnMouseMove(WPARAM BtnState, int x, int y);

private:
    void BuildGeometryBuffers();
    void BuildFX();
private:
    ID3D11Buffer* mBoxVB;
    ID3D11Buffer* mBoxIB;
    ID3D11Buffer* mBoxCB = nullptr;
    ID3D11VertexShader* pVS;
    ID3D11PixelShader* pPS;
ID3D11InputLayout* mInputLayout;

    XMFLOAT4X4 mWorld;
    XMFLOAT4X4 mView;
    XMFLOAT4X4 mProj;
    XMFLOAT3 mEyePosW;
    XMFLOAT3 GetNormal(float x, float z)const;

    //licht variablen
    DirectionalLight mDirLight;
    PointLight mPointLight;
    SpotLight mSpotLight;
    Material mLandmat;
    Material mWavesmat;

    float mTheta;
    float mPhi;
    float mRadius;
    float GetHeight(float x, float z)const;

    POINT mLastMousePos;
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
    PSTR cmdLine, int showCmd)
{
    BoxApp theApp(hInstance);

    if (!theApp.Init())
        return 0;

    return theApp.App_Run();
}


BoxApp::BoxApp(HINSTANCE hInstance)
: Framework_App(hInstance), mBoxVB(0), mBoxIB(0), mBoxCB(0) ,pVS(0), pPS(0), mInputLayout(0), mEyePosW(0.0f, 0.0f, 0.0f),
mTheta(1.5f*MathTools::HalfTau), mPhi(0.25f*MathTools::HalfTau), mRadius(5.0f)
{
mLastMousePos.x = 0;
    mLastMousePos.y = 0;

    XMMATRIX I = XMMatrixIdentity();
    XMStoreFloat4x4(&mWorld, I);
    XMStoreFloat4x4(&mView, I);
    XMStoreFloat4x4(&mProj, I);

    //directional light
    mDirLight.Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
    mDirLight.Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
    mDirLight.Specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
    mDirLight.Direction = XMFLOAT3(0.57735f, -0.57735f, 0.57735f);

    //point light
    mPointLight.Ambient = XMFLOAT4(0.3f, 0.3, 0.3f, 1.0f);
    mPointLight.Diffuse = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f);
    mPointLight.Specular = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f);
    mPointLight.Att = XMFLOAT3(0.0f, 0.1f, 0.0f);
    mPointLight.Range = 25.0f;

    //spot light
    mSpotLight.Ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
    mSpotLight.Diffuse = XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f);
    mSpotLight.Specular = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
    mSpotLight.Att = XMFLOAT3(1.0f, 0.0f, 0.0f);
    mSpotLight.Spot = 96.0f;
    mSpotLight.Range = 1000.0f;

    //materials
    mLandmat.Ambient = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
    mLandmat.Diffuse = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
    mLandmat.Specular = XMFLOAT4(0.2f, 0.2f, 0.2f, 16.0f);
}
BoxApp::~BoxApp()
{
    ReleaseCOM(mBoxVB);
    ReleaseCOM(mBoxIB);
    ReleaseCOM(mBoxCB);
    ReleaseCOM(pVS);
    ReleaseCOM(pPS);
    ReleaseCOM(mInputLayout);
}

bool BoxApp::Init()
{
    if (!Framework_App::App_Init())
        return false;

    BuildGeometryBuffers();
    BuildFX();
return true;
}
void BoxApp::OnResize()
{
    Framework_App::OnResize();

    // The window resized, so update the aspect ratio and recompute the projection matrix.
    XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathTools::HalfTau, AspectRatio(), 1.0f, 1000.0f);
    XMStoreFloat4x4(&mProj, P);
}
void BoxApp::UpdateScene(float dt)
{
    // Convert Spherical to Cartesian coordinates.
    float x = mRadius*sinf(mPhi)*cosf(mTheta);
    float z = mRadius*sinf(mPhi)*sinf(mTheta);
    float y = mRadius*cosf(mPhi);

    mEyePosW = XMFLOAT3(x, y ,z);

    // Build the view matrix.
    XMVECTOR pos = XMVectorSet(x, y, z, 1.0f);
    XMVECTOR target = XMVectorZero();
    XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

    XMMATRIX V = XMMatrixLookAtLH(pos, target, up);
    XMStoreFloat4x4(&mView, V);

    //update lights
    mPointLight.Position.x = 70.0f*cosf(0.2f*mTimer.Totaltime());
    mPointLight.Position.z = 70.0f*sinf(0.2f*mTimer.Totaltime());
    mPointLight.Position.y = MathTools::Max(GetHeight(mPointLight.Position.x, mPointLight.Position.z), -3.0f) + 10.0f;

    mSpotLight.Position = mEyePosW;
    XMStoreFloat3(&mSpotLight.Direction, XMVector3Normalize(target - pos));
}

void BoxApp::DrawScene()
{
    MainDevContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::LightSteelBlue));
    MainDevContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

    MainDevContext->IASetInputLayout(mInputLayout);
    MainDevContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    UINT stride = sizeof(Vertex);
    UINT offset = 0;
    MainDevContext->IASetVertexBuffers(0, 1, &mBoxVB, &stride, &offset);
    MainDevContext->IASetIndexBuffer(mBoxIB, DXGI_FORMAT_R32_UINT, 0);

    // Set constants
    XMMATRIX world = XMLoadFloat4x4(&mWorld);
    XMMATRIX view = XMLoadFloat4x4(&mView);
    XMMATRIX proj = XMLoadFloat4x4(&mProj);
    XMMATRIX worldViewProj = world*view*proj;
    XMMATRIX worldViewProjTRNS = XMMatrixTranspose(worldViewProj);

    CBUFFER cBuffer;
    cBuffer.gWorldViewProj = worldViewProjTRNS;

    MainDevContext->UpdateSubresource(mBoxCB, 0, 0, &cBuffer, 0, 0);
MainDevContext->DrawIndexed(36, 0, 0);
mSwapChain->Present(0, 0);
}
void BoxApp::OnMouseDown(WPARAM BtnState, int x, int y)
{
    mLastMousePos.x = x;
    mLastMousePos.y = y;

    SetCapture(FrmeWrkMainWnd);
}

void BoxApp::OnMouseUp(WPARAM BtnState, int x, int y)
{
    ReleaseCapture();
}

void BoxApp::OnMouseMove(WPARAM BtnState, int x, int y)
{
    if ((BtnState & MK_LBUTTON) != 0)
    {
        // Make each pixel correspond to a quarter of a degree.
        float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
        float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));

        // Update angles based on input to orbit camera around box.
        mTheta += dx;
        mPhi += dy;

        // Restrict the angle mPhi.
        mPhi = MathTools::Clamp(mPhi, 0.1f, MathTools::HalfTau - 0.1f);
    }
    else if ((BtnState & MK_RBUTTON) != 0)
    {
        // Make each pixel correspond to 0.005 unit in the scene.
        float dx = 0.005f*static_cast<float>(x - mLastMousePos.x);
        float dy = 0.005f*static_cast<float>(y - mLastMousePos.y);

        // Update the camera radius based on input.
        mRadius += dx - dy;

        // Restrict the radius.
        mRadius = MathTools::Clamp(mRadius, 3.0f, 15.0f);
    }

    mLastMousePos.x = x;
    mLastMousePos.y = y;
}

void BoxApp::BuildGeometryBuffers()
{
    // Create vertex buffer
    Vertex vertices[] =
    {
        { XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::White },
        { XMFLOAT3(-1.0f, +1.0f, -1.0f), (const float*)&Colors::Black },
        { XMFLOAT3(+1.0f, +1.0f, -1.0f), (const float*)&Colors::Red },
        { XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Green },
        { XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Blue },
        { XMFLOAT3(-1.0f, +1.0f, +1.0f), (const float*)&Colors::Yellow },
        { XMFLOAT3(+1.0f, +1.0f, +1.0f), (const float*)&Colors::Cyan },
        { XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Magneta }
    };

    D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(Vertex)* 8;
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
    vbd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = vertices;
    MainD3DDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB);


    // Create the index buffer

    UINT indices[] = {
        // front face
        0, 1, 2,
        0, 2, 3,

        // back face
        4, 6, 5,
        4, 7, 6,

        // left face
        4, 5, 1,
        4, 1, 0,

        // right face
        3, 2, 6,
        3, 6, 7,

        // top face
        1, 5, 6,
        1, 6, 2,

        // bottom face
        4, 0, 3,
        4, 3, 7
    };

    D3D11_BUFFER_DESC ibd;
    ibd.Usage = D3D11_USAGE_IMMUTABLE;
    ibd.ByteWidth = sizeof(UINT)* 36;
    ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;
    ibd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA iinitData;
    iinitData.pSysMem = indices;
    MainD3DDevice->CreateBuffer(&ibd, &iinitData, &mBoxIB);
}

float BoxApp::GetHeight(float x, float z)const
{
    return 0.3f*(z*sinf(0.1f*x) + x*cosf(0.1*z));
}

XMFLOAT3 BoxApp::GetNormal(float x, float z)const
{
    XMFLOAT3 n(-0.03f*z*cosf(0.1f*x) - 0.3f*cosf(0.1f*z), 1.0f, -0.3f*sinf(0.1f*x) - 0.03f*x*sinf(0.1f*z));
    XMVECTOR unitNormal = XMVector3Normalize(XMLoadFloat3(&n));
    XMStoreFloat3(&n, unitNormal);

    return n;
}

void BoxApp::BuildFX()
{
ID3D10Blob* VS;
    ID3D10Blob* PS;
    D3DX11CompileFromFile((LPSTR)"mColor.shader",0,0, "VS", "vs_4_0", 0, 0, 0, &VS, 0, 0);
    D3DX11CompileFromFile((LPSTR)"mColor.shader", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS, 0, 0);
    MainD3DDevice->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
    MainD3DDevice->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
    MainDevContext->VSSetShader(pVS, 0, 0);
    MainDevContext->PSSetShader(pPS, 0, 0);

    D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
    };
    MainD3DDevice->CreateInputLayout(vertexDesc, 2, VS->GetBufferPointer(), VS->GetBufferSize() ,&mInputLayout);
    MainDevContext->IASetInputLayout(mInputLayout);
    D3D11_BUFFER_DESC bd;
    ZeroMemory(&bd, sizeof(bd));

    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof(CBUFFER);
    bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;

    MainD3DDevice->CreateBuffer(&bd, nullptr, &mBoxCB);
    MainDevContext->VSSetConstantBuffers(0, 1, &mBoxCB);
}

1 个答案:

答案 0 :(得分:0)

我认为您在此代码中有很多错误。

请参阅这些教程,然后可能更容易获得整个视图: http://web.archive.org/web/20140213145557/http://rastertek.com/tutdx11.html

一个例子,你在开始时运行BuildFX(),我很确定你应该每帧都设置这两个函数

MainDevContext->VSSetShader(pVS, 0, 0);
MainDevContext->PSSetShader(pPS, 0, 0);

您是否成功渲染了纯色的立方体?如果是这样,你应该从那里建立。 有很多代码要提,但我每帧运行的最后5个函数是:

deviceContext->IASetInputLayout(m_layout);

deviceContext->VSSetShader(m_vertexShader, NULL, 0);
deviceContext->PSSetShader(m_pixelShader, NULL, 0);

deviceContext->PSSetSamplers(0, 1, &m_sampleState);

deviceContext->DrawIndexed(indexCount, 0, 0);

阅读链接并减少错误。我还没看完你的所有代码。