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.