Chào các bác. Tui mới học lập trình DX9, có một thắc mắc. Mong được giúp. Khi dựng một cái hình bằng 1 VertexBuffer & DrawPrimities() thì tốn bộ nhớ quá, lại cực nữa. Nên tui chuyển qua dùng 2 cái VertexBuffer & IndexBuffer. Thế nhưng các Shared - Vertex tui lại ko biết đặt vector normal & u,v bằng bao nhiêu. Vì các vertex này, đối với mặt nào thì có một cái u,v,n khác. Có kỹ thuật nào giải quyết ko các bác? (Vẫn xài cái IndexBuffer nhé )
Thật ra tôi nghĩ là không có cách nào cả. Hai vertex chỉ cần khác dù chỉ là normal hay UV cũng là khác nhau rồi. Bạn cũng có thể áp dụng diffuse lighting để loại bớt vector normal mà vẫn thể hiện độ bóng của hình. Diffuse lighting thực ra có nhiều cách, cách dễ nhất là: + Tắt D3DRS_LIGHTING để có thể loại bỏ vector normal cho các vertices. + Mỗi vertex lại thêm giá trị diffuse. + Sau khi sắp xếp vị trí các vertex, ta loop qua tòan bộ vertex: - Tính ra vector normal cho vertex đó, bằng cách dùng v = D3DXVec3CrossProduct( &v1, &v2 ), v1 và v2 là hai vector tại ra từ vertex đó tới 2 vertex kề, nghĩa là 2 cạnh của hình. - Sau đó dùng s = D3DXVec3DotProduct của v với vector light source (hướng ánh sáng, muốn đặt sao thì đặt). s chính là cos của góc giữa hai vector. Nhờ giá trị s (từ -1.0 đến 1.0), ta tính được cường độ ánh sáng. Đặt giá trị diffuse theo cường độ này. Khi render nhớ đặt Texture Stage State như sau (đây là DirectX 8, bạn có thể sẽ phải thay đổi với DirectX 9): SetTextureStageState( D3DTSS_COLOROP, D3DTOP_MODULATE ); SetTextureStageState( D3DTSS_COLORARG1, D3DTOP_TEXTURE ); SetTextureStageState( D3DTSS_COLORARG2, D3DTOP_DIFFUSE ); Nói như trên vẫn còn chung chung quá. Bạn có thể tham khảo sách Wordware - Introduction to Game Programing with DirectX 9, download bằng eDonkey, phần Rendering Terrain. Trong các game như Warcraft 3, người ta cũng tắt lighting, và giả lập độ bóng bằng texture. Tắt lighting dĩ nhiên còn giúp tăng tốc độ chương trình. Bạn có thể tham khảo help file của DirectX - dùng Search - diffuse lighting để biết kỹ thuật dùng pixel shader hoặc vertex shader. Tuy nhiên card màn hình cũ như cục GeForce 2 của tôi không hỗ trợ pixel shader.
Thanks bác zubachi. Tui đã hiểu cách giả lighting = diffuse+texture. Thaks còn cái vụ uv map - nếu map trên bề mặt terrain thì dễ quá rồi. còn trên model thì sao? Trong quyển sách bác cho ko có đề cập đến modelling. lighting trong model thì ko có vấn đề gì - cũng xài cách trên. Nhưng còn texture map thì ko còn giống terrain nữa - model là 1 khối kín - chứ ko phải 1 mặt như terrain, nếu xài vertexbuffer -> sẽ có 1 số tam giác map sai. chắc bác đã từng tạo model nhiều. cho tui hỏi đối với model thì làm thế nào? Thks again
Với model thì hơi phức tạp hơn một chút: Khi load một model bằng D3DXLoadMeshFromX, nó có tạo ra một Adjacency buffer. Cái buffer đó tạm gọl là buffer "kề". Nghĩa là thể hiện sự kề nhau giữa các vertices. Nó chẳng qua là danh sách 3 vertices một như sau: [Vertex A] [Vertex B] [Vertex C] - [Vertex E] [Vertex F] [Vertex G] - .... Đó là danh sách index, mỗi bộ ba dĩ nhiên tạo ra một face. Dựa vào danh sách này, bạn có thể tạo ra diffuse lighting. Để nắm vững vấn đề trên, bạn cần tham khảo về cách load mesh, IDirect3DBuffer trong help file của DirectX SDK. Bạn cũng có thể làm cho vấn đề dễ dàng hơn nhiều bằng cách: + Đặt ra một FVF có normal vector + Sau khi load mesh, đặt lại FVF cho khối mesh. Rồi dùng D3DXComputeNormals để xác định normal vector cho từng vertex. + Sau đó lại lưu trữ các normal này trong một mảng nào đó, bằng cách Lock vertex buffer của khối mesh. + Đặt lại FVF khác không có normal vector cho khối mesh này. + Nhờ các normal đã tính trên, bạn có thể thực hiện diffuse lighting. Tuy nhiên, đó không phải là cách hay. Trong các game như Warcraft 3, người ta không dùng diffuse lighting như vậy mà người ta thể hiện lighting trong texture luôn. Có thể dùng một layer Clouds rồi soft light trong photoshop.