Depth buffer doesn't write in Direct3D9

Started by
5 comments, last by gfxgangsta 12 years, 1 month ago
As the title says, my application will not write new depths to the depth buffer in D3D9. I've used PIX to confirm that the depth buffer is cleared and set to the device as it should be, and the depth test is even used- if I clear it to 0, then all the pixels are rejected against buffer. I've checked the return code of all D3D9 functions and got nothing. I even explicitly set the render states in the shader to the appropriate values to no avail. Any suggestions?

In an unfortunately unrelated issue, the Direct3D debug runtime is not functioning correctly and I don't have it's output. I am trying to solve this issue as quickly as possible.
Advertisement
I'm not sure if I understood your problem... but you should be clearing your depth buffer to 1.0 (farthest value) instead of 0 (closest value).
Yes. I only cleared it to 0 to see if the test was being performed correctly.
Hello

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif]

if I clear it to 0, then all the pixels are rejected against buffer

[/font]
[/quote]
... that's what it is supposed to do if the depth test is less, or less or equal : Whatever is the incoming pixel, it will be rejected because its depth is greater than zéro.
[color=#5A5A5A][font=helvetica, arial, verdana, tahoma, sans-serif]

As

[/font]gfxgangsta[color=#5A5A5A][font=helvetica, arial, verdana, tahoma, sans-serif]

suggested, maybe can you try to clear your z-buffer with 1.0f instead?

[/font]

@NicoLaCrevette:

Good point about the depth test! I assumed a test of "<" or "<=" in my comment. Thanks for pointing that out.

@DeadMG:

So, when you clear to 1, are the pixels being rejected? Or are they supposedly being written but you don't get the expected results? Can you post some code?
No. None of the pixels are being rejected- so you can see through parts of the model to parts which are supposed to be obscured. When I look at the depth buffer in PIX, it's all still got the original 1 value. I fixed the D3D Debug Runtime, found a few bugs but fixing them had no effect.

Here's my code for rendering:


void Scene3D::Render(
float dt,
IDirect3DDevice9* device,
IDirect3DVertexDeclaration9* VertexDecl,
ID3DXEffect* RenderOnlyAmbientLightEffect
) const {
bool first = true;
auto SetRenderTargetToDevice = [&] {
std::unique_ptr<IDirect3DSurface9, COMDeleter> RenderTargetSurface;
D3DCALL(RenderTarget->GetSurfaceLevel(0, PointerToPointer(RenderTargetSurface)));
D3DCALL(device->SetRenderTarget(0, RenderTargetSurface.get()));
D3DCALL(device->SetDepthStencilSurface(DepthBuffer.get()));
if (first) {
D3DCALL(device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DColour(ClearColour), 1, 0));
first = false;
}
};

auto SetMeshSpecificDataToEffect = [&](ID3DXEffect* effect, const Direct3D9::Mesh* mesh) {
auto RenData = mesh->GetRenderData();
/*if (auto handle = effect->GetParameterByName(0, "ColourMap")) {
effect->SetTexture(handle, RenData.Texture);
}*/
if (auto handle = effect->GetParameterByName(0, "AmbientMaterial")) {
effect->SetVector(handle, reinterpret_cast<D3DXVECTOR4*>(&RenData.AmbientMaterial));
}
if (auto handle = effect->GetParameterByName(0, "DiffuseMaterial")) {
effect->SetVector(handle, reinterpret_cast<D3DXVECTOR4*>(&RenData.DiffuseMaterial));
}
if (auto handle = effect->GetParameterByName(0, "SpecularMaterial")) {
effect->SetVector(handle, reinterpret_cast<D3DXVECTOR4*>(&RenData.SpecularMaterial));
}
};

auto SetCameraSpecificDataToEffect = [&](ID3DXEffect* effect) {
if (auto handle = effect->GetParameterByName(0, "CameraVP")) {
D3DXMATRIX Projection;
D3DXMATRIX View;
auto lookingat = D3DVector(camera.Position + camera.LookingAt);
D3DXMatrixLookAtLH(
&View,
&D3DVector(camera.Position),
&lookingat,
&D3DVector(camera.Up)
);
#pragma warning(disable : 4244)
D3DXMatrixPerspectiveFovLH(
&Projection,
D3DXToRadian(90),
GetDimensions().x / GetDimensions().y,
camera.NearPlane,
camera.FarPlane
);
#pragma warning(default : 4244)
effect->SetMatrix(handle, &(View * Projection));
}
};

// Define a couple variables the helpers can use
auto SendAllVerticesToPipeline = [&, this](ID3DXEffect* effect, const std::unordered_map<const Direct3D9::Mesh*, std::unordered_set<Object*>>& ObjectsByMesh) {
std::for_each(ObjectsByMesh.begin(), ObjectsByMesh.end(), [&](const decltype(*ObjectsByMesh.begin())& group) {
// Set all per-mesh data - first to the pipeline
auto RenData = group.first->GetRenderData();
D3DCALL(device->SetStreamSource(
0,
RenData.VertexBuffer,
0,
sizeof(Render::InputMesh::Vertex)
));
D3DCALL(device->SetStreamSource(
1,
InstanceBuffer.get(),
0,
sizeof(D3DXMATRIX)
));
D3DCALL(device->SetIndices(
RenData.IndexBuffer
));

// then to the effect
SetMeshSpecificDataToEffect(effect, group.first);
auto handle = effect->GetTechniqueByName("PrimaryTechnique");
D3DCALL(effect->SetTechnique(handle));
D3DCALL(device->SetStreamSourceFreq(0, D3DSTREAMSOURCE_INDEXEDDATA | group.second.size()));

auto bones = group.first->GetBones();
std::for_each(bones.begin(), bones.end(), [&](const decltype(*bones.begin())& bone) {
std::vector<Direct3D9::Bone*> bones;
std::for_each(group.second.begin(), group.second.end(), [&](const Wide::Direct3D9::Object* obj) {
bones.push_back(obj->GetBoneByName(bone->Name));
});
D3DXMATRIXA16* matrices;
D3DCALL(InstanceBuffer->Lock(0, bones.size() * sizeof(D3DXMATRIXA16), reinterpret_cast<void**>(&matrices), D3DLOCK_DISCARD));
std::for_each(bones.begin(), bones.end(), [&](Direct3D9::Bone* bone) {
*matrices = bone->World;
matrices++; // Guaranteed not to overflow because we already made the size as large as we needed it
});
D3DCALL(InstanceBuffer->Unlock());
unsigned int passes;
D3DCALL(effect->Begin(&passes, 0));
for(unsigned int i = 0; i < passes; i++) {
D3DCALL(effect->BeginPass(i));
D3DCALL(device->DrawIndexedPrimitive(
D3DPRIMITIVETYPE::D3DPT_TRIANGLELIST,
0,
0,
bone->NumVerts,
bone->IndexBegin,
bone->NumIndices / 3
));
D3DCALL(effect->EndPass());
}
D3DCALL(effect->End());
});
});
};

// Save the original back buffer and depth stencil
std::unique_ptr<IDirect3DSurface9, COMDeleter> BackBuffer;
std::unique_ptr<IDirect3DSurface9, COMDeleter> DepthStencil;
D3DCALL(device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, PointerToPointer(BackBuffer)));
D3DCALL(device->GetDepthStencilSurface(PointerToPointer(DepthStencil)));

// Sort the objects by mesh, and compute the world matrices whilst you're at it.
std::unordered_map<const Direct3D9::Mesh*, std::unordered_set<Object*>> ObjectsByMesh;
std::for_each(Objects.begin(), Objects.end(), [&](Wide::Render::Object* ptr) {
auto d3dptr = static_cast<Wide::Direct3D9::Object*>(ptr);
d3dptr->ComputeWorldMatrices();
ObjectsByMesh[d3dptr->GetMesh().get()].insert(d3dptr);
});

// Resize the buffer, if it's not big enough to hold what we're doin here.
unsigned int maxsize = 0;
std::for_each(ObjectsByMesh.begin(), ObjectsByMesh.end(), [&](const decltype(*ObjectsByMesh.begin())& group) {
maxsize = std::max(maxsize, group.second.size());
});
if (InstanceBufferSize < maxsize) {
InstanceBufferSize = maxsize;
ResetInstanceBuffer(device);
}

// Set the mesh-independent stuff to the device
D3DVIEWPORT9 vp = { 0, 0, GetDimensions().x, GetDimensions().y, 0, 1 };
D3DCALL(device->SetViewport(&vp));
D3DCALL(device->SetVertexDeclaration(VertexDecl));
D3DCALL(device->SetStreamSource(1, InstanceBuffer.get(), 0, sizeof(D3DXMATRIXA16)));
D3DCALL(device->SetStreamSourceFreq(1, D3DSTREAMSOURCE_INSTANCEDATA | 1));

// If there is only ambient light, then just render directly to BB with no shadow mapping
//if (Lights.empty()) {
// Render ambient only- no shadowmapping needed
SetRenderTargetToDevice();
SetCameraSpecificDataToEffect(RenderOnlyAmbientLightEffect);
SendAllVerticesToPipeline(RenderOnlyAmbientLightEffect, ObjectsByMesh);
//}

// Restore the previous backbuffer and depth stencil
D3DCALL(device->SetRenderTarget(0, BackBuffer.get()));
D3DCALL(device->SetDepthStencilSurface(DepthStencil.get()));
}
Are you clearing the color and depth buffers only once?


[color=#000000] [color=#000088]if[color=#000000] [color=#666600]([color=#000000]first[color=#666600])[color=#000000] [color=#666600]{
[color=#000000] D3DCALL[color=#666600]([color=#000000]device[color=#666600]->[color=#660066]Clear[color=#666600]([color=#006666]0[color=#666600],[color=#000000] [color=#000088]nullptr[color=#666600],[color=#000000] D3DCLEAR_TARGET [color=#666600]|[color=#000000] D3DCLEAR_ZBUFFER[color=#666600],[color=#000000] D3DColour[color=#666600]([color=#660066]ClearColour[color=#666600]),[color=#000000] [color=#006666]1[color=#666600],[color=#000000] [color=#006666]0[color=#666600]));
[color=#000000] first [color=#666600]=[color=#000000] [color=#000088]false[color=#666600];
[color=#000000] [color=#666600]}

This topic is closed to new replies.

Advertisement