230 likes | 319 Views
This ELTE-IK 3D Engine is a minimal 3D motor utilizing DirectX 10, offering features like Mesh and Entity classes, .obj file loading, and shader set up. Mesh class allows storing and drawing simple models using position, normal, and 2D texture coordinates. The Entity class represents elements in the scene and combines necessary drawing elements. ObjParser class loads .obj files limiting to one object per file and requiring normal vector and texture coordinates per vertex. Utilize the Engine by managing textures, meshes, and entities using containers. OnCreateDevice loads textures and meshes, while OnFrameRender handles the drawing process, requiring world, view, and projection matrices. Implement camera control for improved visuals and aspect ratio preservation. CFirstPersonCamera object can be integrated for camera functionality. Handle events and drawing with the camera considering view and projection matrices.
E N D
DirectX 10,enGine – minimál 3d motor ELTE-IK, Számítógépes grafika 2./haladó 2. gyakorlat Klár Gergely
enGine3d „motor” • Sokkal kevesebb, mint egy igazi 3d engine • Jóval több, mint a DX10Framework magában • Feature-ök: • Mesh osztály • Entity osztály • .obj file-ok betöltése • Manager konténerek • Shader irányfényforráshoz
Új osztály: Mesh • Egyszerű modellek tárolása/rajzolása • Vertex = pozíció+normál+2D tex. Koord • addVertex/addIndexfv.-k töltik fel • initBuffers hozza létre a DX-esvertex és index buffert • Ne felejtsétek el meghívni! • createInputLayoutForTechnique hozza létre az input layout-ot • Az Entity automatikusan meghívja! • predraw – rajzolás előtti beállítások, amiket nem kell minden pass-ben újra kiadni. • draw – a tényleges rajzolás hívás
Új osztály: Entity • Kb. = Mesh+World mátrix+rajzolás • Az Entity a színtér egy eleme – pl. egy sakkfigura, játékos, láda, stb. • Összefogja, a rajzoláshoz szükséges elemeket, amiket külön-külön töltünk be: • Mesh • Textúra • Effekt • Technika • Pozíció • Méret • Elfogatás
Új osztály: ObjParser • .obj file -> Mesh betöltés • Korlátai: • Az .obj file-ban csak egyetlen objektum lehet • Meg kell legyen adva normálvektor és textúra koordináta is minden csúcshoz • Csak háromszög-lapok szerepelhetnek a file-ban • Használata: #include "Mesh.h" #include "ObjParser.h„ … Mesh *m; m = ObjParser::parse("media\\sphere.obj"); m->initBuffers(_device);
Manager konténerek SimpleApp.h • Textúrák, Mesh-ek és Entity-ktárolására • Név szerinti hivatkozás! • Automatikus felszabadítás! • Gyakorlatilag egy std::map + új cleanupfv. • OnDestroyDevice()-ban pucoljuk ki őket ReleasingManager<ID3D10ShaderResourceView> textures; DeletingManager<Mesh> meshes; DeletingManager<Entity> entities;
Textúrák betöltése SimpleApp::OnCreateDevice D3DX10_IMAGE_LOAD_INFO loadInfo; ZeroMemory( &loadInfo, sizeof(D3DX10_IMAGE_LOAD_INFO) ); loadInfo.BindFlags = D3D10_BIND_SHADER_RESOURCE; loadInfo.Format = DXGI_FORMAT_BC1_UNORM; ID3D10ShaderResourceView *tmp; D3DX10CreateShaderResourceViewFromFile( _device, L"media\\green.png", &loadInfo, NULL, &tmp, NULL ); textures["green"] = tmp;
Mesh-ek betöltése SimpleApp::OnCreateDevice m = ObjParser::parse("media\\cube.obj"); m->initBuffers(_device); meshes["cube"] = m;
Entity-k SimpleApp::OnCreateDevice Entity *e = new Entity(_device, meshes["cube"], textures["green"], effect, dirLightTex); e->setWorld(0,0,0,0,0,0); entities["cube"] = e;
Rajzolás SimpleApp::OnFrameRender • entities["cube"]->draw(view, projection); • Elvégzi a teljes rajzolást, de kéne • view mátrix • projection mátrix • shader-nek átadni a szempozíciót • Megj.: saját worldmátrixát minden Entitytudja
Rajzolás - mátrixok SimpleApp::OnFrameRender • entities["cube"]->draw(view, projection); • Elvégzi a teljes rajzolást, de kéne • view mátrix • projection mátrix • shader-nek átadni a szempozíciót • Megj.: saját worldmátrixát minden Entitytudja
Rajzolás - mátrixok SimpleApp::OnFrameRender D3DXVECTOR3 eye(0, 5, 10), at(0.0f, 0, 0.0f), up(0, 1, 0); D3DXMATRIX view, projection; D3DXMatrixLookAtLH(&view, &eye, &at, &up); D3DXMatrixPerspectiveFovLH(&projection, D3DX_PI / 4, 1.333f, 0.1f, 20); V(effect->GetVariableByName("eyePosition")->AsVector()->SetFloatVector(eye)); entities["cube"]->draw(view, projection);
Nem rossz, de • Még jobb lenne, ha a képarány mindig jó lenne • Be lehetne járni a színteret • Megoldás: DXUTcamera/CFirstPersonCamera
Kamera objektum SimpleApp.h #include "DXUTcamera.h" … classSimpleApp : public DX10Framework { … CFirstPersonCamera camera; … };
Kamera init SimpleApp::OnCreateDevice D3DXVECTOR3 eye(0, 5, 10), at(0.0f, 0, 0.0f); camera.SetViewParams(&eye, &at); camera.SetScalers(0.01f, 5);
Képarány megtartás SimpleApp::OnResizedSwapChain HRESULT SimpleApp::OnResizedSwapChain( const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc) { floataspect = 1.0f * pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height; camera.SetProjParams(D3DX_PI / 4, aspect, 0.1f, 20); return S_OK; }
Eseménykezelők -> kamera SimpleApp::OnFrameMove camera.FrameMove(fElapsedTime); SimpleApp::MsgProc camera.HandleMessages(hWnd, uMsg, wParam, lParam);
Rajzolás „kamerával” SimpleApp::OnFrameRender HRESULT hr; float clearColor[4] = { 0.176f, 0.196f, 0.667f, 0.0f }; const D3DXMATRIX& view = *camera.GetViewMatrix(); const D3DXMATRIX& projection = *camera.GetProjMatrix(); _device->ClearRenderTargetView(_defaultRenderTargetView, clearColor); _device->ClearDepthStencilView(_defaultDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0); V(effect->GetVariableByName("eyePosition")->AsVector()-> SetFloatVector((float*)camera.GetEyePt())); entities["cube"]->draw(view, projection);