DirectX 9 Z-Buffer funktioniert nicht.



  • Ich habe ein großes Problem! Der Z-Buffer bei DirectX 9 funktioniert bei mir nicht.

    Da der Code zu lang ist (651 Zeilen) erkläre ich die Situation:

    Ich habe zwei um den Mittelpunkt rotierende Würfel. Auf Tastendruck entferne ich einen und ersetzte ihn durch zwei andere an anderen Positionen.

    Aber weder vor noch nach der Änderung funktioniert der Z-Buffer. Denn manchmal ist der weiter entfernte Würfel vor dem näheren.

    Die beiden Würfel am Start sind in zwei verschiedenen V-Buffern, aber selbst intern (nach dem Austausch) stimmt die Anzeige nicht. Denn auch hier ist der weiter entfernte Würfel vor dem nähren und das obwohl beide im selben V-Buffer sind.

    Ich verwende außerdem einen I-Buffer.

    Ich hoffe ihr könnt mir helfen!

    P.S.: Wenn ihr troztdem Code brauchen solltet, sagt mir bitte was ihr haben wollt.



  • Hast du überhaupt einen Z-Buffer erzeugt, clearest du ihn auch und ist Depth Buffering eingeschaltet?



  • Eigentlich schon.

    Codeausschnitte:

    d3ddev->SetRenderState(D3DRS_ZENABLE, true);    // turn on the z-buffer
    
    //in meiner render_frame-Funktion (selbsterkärend oder?) bevor ich irgentetwas rendere
    
    d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    

    Das hat bisher immer funktioniert!

    Frage: Was ist Depth Buffering? Müsste doch das mit dem Z-Buffer sein, oder?



  • aus erfahrung kann ich dir sagen das das zwei unterschiedliche dinge sind.
    ich kann es dir nicht erklären, weil mir das wissen fehlt.
    aber ich weiß das es bei mir einige unterschiede gab.

    mach am besten beide auf TRUE dann sollte es klappen.
    ich hab da ein bisschen rumgespielt um mit Alphatexturen was zu fixen. ich glaub ich hatte beide vorher immer auf True.



  • Was soll ich einschalten?



  • d3dpp.EnableAutoDepthStencil = TRUE; 
    d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
    

    die beiden. ich kann dir aber wie gesagt nicht sagen, ob nur der Z-Buffer wichtig ist.



  • Es sind beide wichtig, nur D3DRS_ZENABLE sollte eigentlich per default auf true sein.



  • Auch das geht nicht. Soll ich euch einen Screenshot zeigen?



  • Interessanter als ein Screenshot wär in dem konkreten Fall wohl der relevante Code...



  • Das Problem ist, dass ich nicht genau weiß, was der Relevante Code in diesem Fall ist.
    Ich könnte natürlich den gesamten Code posten, da ich eigentlich nicht mehr mache als Würfel rotieren zu lassen, aber das sind schon 675 Zeilen Code und die möchte ich euch nicht unbedingt zumuten.
    Wenn ihr den Code wollt, dann ist das kein Problem.



  • Interessant ist der Code wo du das Device erzeugst und der Code mit dem du den Würfel renderst.



  • ok. Ich versuche es. Schade, dass das Forum keine Spoiler hat, sonst könnte ich den gesamten Code hier einfügen. Naja, aber hier der "relevante" Teil:

    //============================================Auslassung============================================
    
    struct CAMERA { D3DXVECTOR3 cam_pos, look_at, up_dir;
    CAMERA(float cam_pos_x, float cam_pos_y, float cam_pos_z, float look_at_x, float look_at_y, float look_at_z,
    	float up_dir_x, float up_dir_y, float up_dir_z)
    {
    	cam_pos.x = cam_pos_x;
    	cam_pos.y = cam_pos_y;
    	cam_pos.z = cam_pos_z;
    	look_at.x = look_at_x;
    	look_at.y = look_at_y;
    	look_at.z = look_at_z;
    	up_dir.x = up_dir_x;
    	up_dir.y = up_dir_y;
    	up_dir.z = up_dir_z;
    }
    
    CAMERA()
    {
    	cam_pos.x = 0.0f;
    	cam_pos.y = 0.0f;
    	cam_pos.z = 0.0f;
    	look_at.x = 0.0f;
    	look_at.y = 0.0f;
    	look_at.z = 0.0f;
    	up_dir.x = 0.0f;
    	up_dir.y = 0.0f;
    	up_dir.z = 0.0f;
    }
    };
    
    LPDIRECT3D9 d3d;    // the pointer to our Direct3D interface
    LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
    LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;    // the pointer to the vertex buffer
    LPDIRECT3DINDEXBUFFER9 i_buffer = NULL;
    LPDIRECT3DTEXTURE9 texture = NULL;    // our first texture
    
    LPDIRECT3DVERTEXBUFFER9 v_buffer2 = NULL;    // the pointer to the vertex buffer
    LPDIRECT3DINDEXBUFFER9 i_buffer2 = NULL;
    
    //============================================Auslassung============================================
    
    //Fenster
    
    // the entry point for any Windows program
    int WINAPI WinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPSTR lpCmdLine,
                       int nCmdShow)
    {
        //HWND hWnd;
        WNDCLASSEX wc;
    
        ZeroMemory(&wc, sizeof(WNDCLASSEX));
    
        wc.cbSize = sizeof(WNDCLASSEX);
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WindowProc;
        wc.hInstance = hInstance;
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        // wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wc.lpszClassName = L"WindowClass";
    
        RegisterClassEx(&wc);
    
        hWnd = CreateWindowEx(NULL,
                              L"WindowClass",
                              L"Our First Direct3D Program",
                              WS_EX_TOPMOST | WS_POPUP,    // fullscreen values
                              0, 0,    // the starting x and y positions should be 0
                              SCREEN_WIDTH, SCREEN_HEIGHT,    // set window to new resolution
                              NULL,
                              NULL,
                              hInstance,
                              NULL);
    
        ShowWindow(hWnd, nCmdShow);
    
        // set up and initialize Direct3D
        initD3D(hWnd);
    
        // enter the main loop:
        MSG msg;
    
    	clock_t next = clock() + fps;
    
        while(true)
        {
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
    			//render_frame();
            }
    
            if(msg.message == WM_QUIT)
                break;
    
    		if(clock() >= next)
    		{
    			render_frame();
    
    			next = clock() + fps;
    		}
    		else
    		{
    			Sleep(1);
    		}
        }
    
        // clean up DirectX and COM
        cleanD3D();
    
        return msg.wParam;
    }
    
    //============================================Auslassung============================================
    
    // this function initializes and prepares Direct3D for use
    void initD3D(HWND hWnd)
    {
        d3d = Direct3DCreate9(D3D_SDK_VERSION);    // create the Direct3D interface
    
        D3DPRESENT_PARAMETERS d3dpp;    // create a struct to hold various device information
    
        ZeroMemory(&d3dpp, sizeof(d3dpp));    // clear out the struct for use
        d3dpp.Windowed = false;    // program windowed, not fullscreen
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // discard old frames
        d3dpp.hDeviceWindow = hWnd;    // set the window to be used by Direct3D
    	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;    // set the back buffer format to 32-bit
        d3dpp.BackBufferWidth = SCREEN_WIDTH;    // set the width of the buffer
        d3dpp.BackBufferHeight = SCREEN_HEIGHT;    // set the height of the buffer
    	d3dpp.EnableAutoDepthStencil = true;
    	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    
        // create a device class using this information and the info from the d3dpp stuct
        d3d->CreateDevice(D3DADAPTER_DEFAULT,
                          D3DDEVTYPE_HAL,
                          hWnd,
                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                          &d3dpp,
                          &d3ddev);
    
    	D3DXCreateTextureFromFile(d3ddev,    // the Direct3D device
                                  L"E:\\Eigene Dateien\\Visual Studio 2010\\Projects\\Block Forge\\Textures.bmp",    // the filename of the texture
                                  &texture);    // the address of the texture storage
    
            //Hier werden die Würfel erzeugt.
    
    	init_graphics();    // call the function to initialize the triangle
    	init_graphics2();
    	init_light();    // call the function to initialize the light and material
    
    	d3ddev->SetRenderState(D3DRS_LIGHTING, true);    // turn off the 3D lighting
    	//d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);	// render both sides
    	d3ddev->SetRenderState(D3DRS_ZENABLE, true);    // turn on the z-buffer
    	d3dpp.EnableAutoDepthStencil = true;
    	d3ddev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255, 255, 255));    // ambient light
    	d3ddev->SetRenderState(D3DRS_NORMALIZENORMALS, true);   // handle normals in scaling
    
    	d3ddev->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 8);	// anisotrpic level
    	d3ddev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);		// minfication
    	d3ddev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);		// magnification
    	d3ddev->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);		// mipmap
    
    	camera = CAMERA(0.0f, 5.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
    }
    
    //============================================Auslassung============================================
    
    // this is the function used to render a single frame
    void render_frame(void)
    {
        // clear the window to a deep blue
        d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    	d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    
        d3ddev->BeginScene();    // begins the 3D scene
    
    		// select which vertex format we are using
            d3ddev->SetFVF(CUSTOMFVF);
    
            // select the vertex buffer to display
            d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
    		d3ddev->SetIndices(i_buffer);
    
    		// set the texture
    		d3ddev->SetTexture(0, texture);
    
    			// SET UP THE PIPELINE
    
    			D3DXMATRIX matRotateY;    // a matrix to store the rotation information
    
    			float index = ((float)clock()) / (159.154943f * 10.0f);    // an ever-increasing float value
    
    			// build a matrix to rotate the model based on the increasing float value
    			D3DXMatrixRotationY(&matRotateY, index);
    
    			// tell Direct3D about our matrix
    			d3ddev->SetTransform(D3DTS_WORLD, &matRotateY);
    
    			D3DXMATRIX matView;    // the view transform matrix
    
    			D3DXMatrixLookAtLH(&matView,
    							   &camera.cam_pos,	// the camera position
    							   &camera.look_at,	// the look-at position
    							   &camera.up_dir);	// the up direction
    
    			d3ddev->SetTransform(D3DTS_VIEW, &matView);    // set the view transform to matView
    
    			D3DXMATRIX matProjection;     // the projection transform matrix
    
    			D3DXMatrixPerspectiveFovLH(&matProjection,
    									   D3DXToRadian(45),    // the horizontal field of view
    									   (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
    									   0.0f,    // the near view-plane
    									   100.0f);    // the far view-plane
    
    			d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection);    // set the projection
    
            // copy the vertex buffer to the back buffer
            d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, anz_vertices, 0, anz_triangles);
    
    		//========================================================================================
    
    		// select the vertex buffer to display
            d3ddev->SetStreamSource(0, v_buffer2, 0, sizeof(CUSTOMVERTEX));
    		d3ddev->SetIndices(i_buffer2);
    
    		// set the texture
    		d3ddev->SetTexture(0, texture);
    
    			// SET UP THE PIPELINE
    
    			D3DXMATRIX matRotateY2;    // a matrix to store the rotation information
    
    			// build a matrix to rotate the model based on the increasing float value
    			D3DXMatrixRotationY(&matRotateY2, index);
    
    			// tell Direct3D about our matrix
    			d3ddev->SetTransform(D3DTS_WORLD, &matRotateY2);
    
    			D3DXMATRIX matView2;    // the view transform matrix
    
    			D3DXMatrixLookAtLH(&matView2,
    							   &camera.cam_pos,	// the camera position
    							   &camera.look_at,	// the look-at position
    							   &camera.up_dir);	// the up direction
    
    			d3ddev->SetTransform(D3DTS_VIEW, &matView2);    // set the view transform to matView
    
    			D3DXMATRIX matProjection2;     // the projection transform matrix
    
    			D3DXMatrixPerspectiveFovLH(&matProjection2,
    									   D3DXToRadian(45),    // the horizontal field of view
    									   (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
    									   0.0f,    // the near view-plane
    									   100.0f);    // the far view-plane
    
    			d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection2);    // set the projection
    
            // copy the vertex buffer to the back buffer
            d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, anz_vertices2, 0, anz_triangles2);
    
        d3ddev->EndScene();    // ends the 3D scene
    
        d3ddev->Present(NULL, NULL, NULL, NULL);   // displays the created frame on the screen
    }
    

    Das müsste soweit der relevante Code sein. Viel Spaß 🤡



  • Pack deine near plane mal an 0.1f oder so. 0.0f ist eine ganz schlechte Idee 😉



  • DAAAAAAAAAAAAAANNNNKKKKKKKKKKKKKEEEEEEEEEEEEEEEEEEEEEEEE!

    Es funktioniert! ich hätte nie gedacht, dass das so schlimm ist. Dann schau ich mal, wie weit ich da runter gehen kann. Danke nochmal!



  • Die erinnerung schrieb:

    Dann schau ich mal, wie weit ich da runter gehen kann. Danke nochmal!

    Du solltest nicht schauen wie weit du da runter gehen kannst, sondern wie weit du raufgehen kannst. Um die Präzision des Depth Buffer gut zu nutzen, sollte die near plane so weit weg wie möglich und die far plane so nahe dran wie möglich sein...



  • Das Problem ist aber, wenn ich mit der Spielfigur direkt vor einer Wand stehe und die dann verschwindet, ist das scheiße. Und die Far-Plane muss auch relativ weit weg (740), damit man die komplette Welt sehen kann. Aber ich habe jettzt gute Werte gefunden.



  • Kleiner Tip, weils mir grad aufgefallen ist

    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); 
        d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    

    Das kannst du mit einem einzigen Aufruf machen, was auf manchen Karten effizienter sein könnte:

    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    


  • Um es effizient zu machen, sollte man afaik immer auch den Stencil Buffer mit clearen...

    EDIT: Ok sein Format hat keinen Stencil Buffer, aber naja.



  • @hustbear:

    Danke für den Tipp, hab ich gleich umgesetzt.


Anmelden zum Antworten