Jump to content
  • Advertisement
Sign in to follow this  
DeadMG

Depth buffer doesn't write in Direct3D9

This topic is 2291 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
@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?

Share this post


Link to post
Share on other sites
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()));
}

Share this post


Link to post
Share on other sites
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]}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!