Jump to content

  • Log In with Google      Sign In   
  • Create Account


Depth buffer doesn't write in Direct3D9


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 DeadMG   Members   -  Reputation: 100

Like
0Likes
Like

Posted 09 March 2012 - 07:54 AM

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.

Sponsor:

#2 gfxgangsta   Members   -  Reputation: 526

Like
0Likes
Like

Posted 09 March 2012 - 09:48 AM

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).

#3 DeadMG   Members   -  Reputation: 100

Like
0Likes
Like

Posted 09 March 2012 - 09:59 AM

Yes. I only cleared it to 0 to see if the test was being performed correctly.

#4 Tournicoti   Prime Members   -  Reputation: 682

Like
1Likes
Like

Posted 09 March 2012 - 10:08 AM

Hello

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


... 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.

As

gfxgangsta

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



#5 gfxgangsta   Members   -  Reputation: 526

Like
0Likes
Like

Posted 09 March 2012 - 10:17 AM

@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?

#6 DeadMG   Members   -  Reputation: 100

Like
0Likes
Like

Posted 09 March 2012 - 06:35 PM

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


#7 gfxgangsta   Members   -  Reputation: 526

Like
0Likes
Like

Posted 09 March 2012 - 07:16 PM

Are you clearing the color and depth buffers only once?

if (first) {
D3DCALL(device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DColour(ClearColour), 1, 0));
first = false;
}






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS