我一直在使用一本书关注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);
}
答案 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);
阅读链接并减少错误。我还没看完你的所有代码。