PDA

View Full Version : To lonelyheart: Giải quyết mưa và tuyết



Mach2
30-05-2003, 23:11
Cái này trả lời lonelyheart trong thread Demo...
Hìhì, lonelyheart làm game gì bí mật á? Bạn dùng DirectX phải ko? Hồi trước mình cũng bị mắc cái khúc mưa tuyết này, mình làm bằng OpenGL nhưng mà cách làm thì cũng ko khác lắm đâu.
Quan trọng của render rain và snow là fps hay bị giảm kinh khủng, đó là do 2 chuyện: tính toán (cập nhật trạng thái các hạt nhiều) và render (dễ bị pixel overdraw). Hai chuyện này ko dễ nhưng mà cũng có thể giải quyết được phần nào.
Mình hay làm mí hiệu ứng này bằng design mí cái particle system đơn giản. Trong trường hợp đơn giản này, mỗi particle của mình chỉ cần 2 toạ độ trước và hiện thời, tốc độ và góc quay (rot) là đủ. Mưa ko cần rot còn tuyết thì ko cần toạ độ sau. Vẽ mưa bằng line nên cần 2 toạ độ, còn tuyết thì bạn đòi nó "quay quay" nên cần rot nữa, đúng ko?
Tối ưu tính toán: Chuyện này phải tối ưu rùi. Bạn tính cho 1000 particle có thể nói là khá ít, mưa kiểu này là mưa phùn rùi ;), nhưng mà nếu ko tối ưu cách cập nhật thì cũng chậm như thường. Chỉ cái gì cần tính thì tính thui, tối ưu phép tính tối đa (cứ mỗi phép tính dư sẽ bị nhân lên 1000 lần, chậm đáng kể). Bạn làm scale, location làm gì, dư nhiều nên chậm đúng tùi. Chỉ cần các bước sau:
- Cập nhật:
prev_loc=current_loc
- Cập nhật trạng thái:
speed=speed+gravity*delta_t
- Tính toạ độ mới của mưa, thêm tốc độ gió để làm khi hiệu ứng chuyển động, mưa sẽ bị rơi xiên xiên...
current_loc.X=prev_loc.X-Windspeed.X*delta_t
current_loc.Y=prev_loc.Y-Windspeed.Y*delta_t
current_loc.Y=prev_loc.Y-(Windspeed.Y-speed)*delta_t
- Kiểm tra xem mưa có rơi khỏi vùng kiểm soát ko, nếu có, tạo lại hạt mưa mới (dùng random cho loc và speed)
Đối với tuyết, bạn cập nhật thêm rot=rot*delta_t với giá trị ban đầu là random, Hiệu ứng này làm bông tuyết xoay tròn khá ngẫu nhiên, giá trị rot ban đầu nên chọn từ 0 cho đến khoảng 30deg/s, nhanh quá nhìn ko ra tuyết gì đâu...
Vẽ mưa dùng blended line (line từ prev_loc đến current_loc), còn tuyết dùng billboard texture, dễ phải ko?
Mình tối ưu cách tính toán như cách trên thì ct của mình có thể cập nhật khoảng thêm >>20000 particle mà fps drop chỉ khoảng cỡ 20 mà thui (ct mình đạt 60 fps ở 1024x768x16bit). Tuy nhiên hiện thời mình có thể tính cho khoảng >>27000 particle mà fps ko drop tí nào, mình dùng một cái mẹo nhỏ, bạn thử xem, kết quả ko ngờ.
Mình dùng một particle system khoảng 3000 hạt, tính khá nhanh, ko giảm fps đoi tí nào, nhưng mà 3000 particle chỉ tạo được mưa phùn thui, cho nên mình dùng một hệ này, vẽ 9 lần xung quanh vị trí hiện thời, như vậy mình chỉ cần update hệ hạt một lần mà được hẳn 27000 hạt, đã quá phải ko? Bạn cứ thử xem trên máy bạn, mình dùng AthlonXP nên tính nhanh, bạn thử dùng hệ 100 hạt rồi vẽ 25 lần thử xem?
Nhìn từ trên xuống:
x x x
x X x
x x x
với: X: vị trí hiện thời. x: các vị trí vẽ hệ.
Tuyết cay hơn nhiều vì dùng texture mờ, nhưng mà với thuật toán trên cũng khá tốt, dùng y chang (chỉ đổi code vẽ mưa thành tuyết, fps mình bị giảm 20, còn khoảng 50fps, có thể chấp nhận được tốt!!!).
Tối ưu render: Dùng Frustum Culling. Mình nghe nói DirectX cho hàm Frustum Culling à? OpenGL thì phải tự viết. Làm theo cách trên thì mình test xem các hệ ở các vị trí (9 vị trí) có nằm trong tầm nhìn ko. Ko test sẽ làm fps giảm còn một nửa nên phải thực hiện bước này, nhất là với tuyết. Billboard của mình tự viết, ko cần tính toán lại cho mỗi quad nên khá nhanh, ko biết billboard của bạn ra sao? Nếu billboard tính nhiều thì nên viết lại, chẳng hạn vẽ vài ngàn quad billboard và ko billboard mà thấy fps giảm nhiều quá thì nên viết lại cho chắc.
Chúc bạn thành công. Mình dùng thuật toán trên trong Flight Simulation của mình, bạn xem thử 2 screen shot sau, 27000 particle được cập nhật và render nếu được ở mỗi bước. Cái này là mưa...

Mach2
30-05-2003, 23:12
còn cái này là tuyết...

lonelyheart
31-05-2003, 00:56
Trời tui có làm game gì đâu tui đang học mà, chỉ implement mấy cái effect chơi nếu bà con không chê tui up nó luôn đây, tui còn yếu cái môn lập trình này lắm . Địa chỉ là :
http://www23.brinkster.com/ngothaian/dx/demo.htm
Người ta demo 64k mà quá trời , tui 300k mà hổng được gì hết :-(
Quên nữa bà con phải có DX mới chạy được

lonelyheart
31-05-2003, 01:25
Billboard của tui làm như sau hổng biết có giống bạn không:
+Khi tạo 4 đỉnh cho tuyết tui tạo trên mặt phẳng xy( z = 0 ) trong World
+Sau đó coi như ( giả tưởng) các toạ độ vừa tạo là toạ độ so với Camera( Camera Origin với z là hướng nhìn, x là rightvector có được do nhân hữu hướng với up vector thường là ( 0, 1, 0 ), y là vec hữu hướng của x, z ) --> thế là nó hướng về camera rồi nhé
+Sau đó mình nhân nó với ma trận View nghịch đảo để chuyển về toạ độ World--> hạt tuyết nằm ngay tại Camera;
+Để di chuyển đến vị trí của nó tui công thêm vec3 = vec3Loc( của nó ) - vecLoc( của Camera ); thế là xong

Note : trong source code của DX8 SDK nó làm rất tuyệt cực nhanh ( tui đã chuyển qua cách này luôn )
Nó xác định BillBoard Matrix bằng cách lấy Inverse View Matrix và cho dòng thứ 4 của matrận này bằng 0 hết ( trừ phàn tử cuối )
_41 = _42 = _43 = 0;
Có ma trận billboard chung rồi bạn xác định matrận BB riêng lẻ cho từng giọt mưa bằng cách cho dong 4 vec3Loc toạ độ World của từng hạt _41 = loc.x; _42 = loc.y; _43 = loc.z;
Chú ý trong OpenGL toạ độ là thẳng đứng , còn DX toạ độ nằm ngang do đó khi đọc bạn nhớ chuyển dòng thành cột nha

Mach2
31-05-2003, 08:16
Billboard có nhiều cách làm, cách của bạn làm là cách chính quy, các DX8 làm là "cheat". Mí cách này tốt nhưng thường để làm cho vật thể ít ít chứ nhiều thì chậm lém (tính ma trận mờ...) Mình làm spherical billboard bằng cách "cheat" như sau, nhanh hơn cả cách "cheat" của DX8:
- Tìm vector Right và vector Up như sau:
Right.X = M[1,1]; Right.Y = M[2,1]; Right.Z = M[3,1]
Up.X = M[1,2]; Up.Y = M[2,2]; Up.Z = M[3,2]
- Sau đó nếu muốn vẽ quad ở toạ độ X, Y, Z và có kích thước size thì vẽ ở các toạ độ như sau:
A-----B
| |
| |
C-----D
Toạ độ A:
X-(Right.X-Up.X)*size/2
Y-(Right.Y-Up.Y)*size/2
Z-(Right.Z-Up.Z)*size/2
Toạ độ B:
X+(Right.X+Up.X)*size/2
Y+(Right.Y+Up.Y)*size/2
Z+(Right.Z+Up.Z)*size/2
Toạ độ C:
X-(Right.X+Up.X)*size/2
Y-(Right.Y+Up.Y)*size/2
Z-(Right.Z+Up.Z)*size/2
Toạ độ D:
X+(Right.X-Up.X)*size/2
Y+(Right.Y-Up.Y)*size/2
Z+(Right.Z-Up.Z)*size/2
Như vậy thay vì biến đổi ma trận thì mình biến đổi toạ độ các vertex liên quan, sẽ nhanh hơn rất nhiều.

lonelyheart
01-06-2003, 00:14
Í mấy cách mình làm trên là Align to View Plane còn cái Align to View nữa tui chưa làm bao giờ nhưng nghe mấy ta nói nhiều lắm

Mach2
01-06-2003, 08:02
Cái mình làm hình như là align to view thì phải... Billboard có nhiều cách lém nhưng mà hiệu quả khác nhau nhiều. Trên gamedev có mí bài về billboard khá hay. Bạn lên xem thử?

lonelyheart
01-06-2003, 15:46
Tui đọc cách bạn làm, hình như là xác định trực tiếp toạ độ của các đỉnh của quad tức là mỗi khi render phải sửa lại toạ độ thích hợp trong vertex buffer chứ không phải dùng ma trận để nhân cho các toạ độ khởi động của Quad( toạ độ lúc khởi tạo ), hổng biết OpenGL làm sao chứ DX nếu muốn sửa lại toạ độ trong VBuffer thì phải lock vertex buffer lại ( tức là D3D cung cấp cho chương trình quyền truy cập exclusive vùng nhớ không cho các chương trình khác sử dụng , vì vùng nhớ đó có thể nằm trên bộ nhớ card màn hình, mà bộ nhớ này là dùng chung cho mọi chương trình , nếu không lock lại có thể lúc ta sửa thì có chương trình khác chen ngang vào tác động lên vùng nhớ này -> thế là tiêu )
Mà lúc lock vùng nhớ DX đòi hỏi rất nhiều tác vụ, do đó không thể làm trong realtime được --> có lẽ vì lí do này mà DX phải sử dụng ma trận hầu hết các trường hợp để khỏi phải lock( chỉ dùng khi khởi tạo và cập nhật mà thôi )....

Mach2
01-06-2003, 16:30
Mình ko rành DX lém, chỉ biết vài cái cơ bản chứ ko sâu, vậy nên ko biết chuyện lock vertex buffer của nó. Cách của mình nhanh là vì ko cần thay đổi ma trận, vì vậy số phép tính được rút đáng kể (ko có một phép nhân ma trận là đỡ được 4x16 phép nhân).
Thôi vậy có lẽ cách của bạn (DX8) là nhanh nhất rồi. Bạn xem lại các cập nhật particle của bạn xem, tối ưu thử xem có tăng thêm tí nào ko?

lonelyheart
02-06-2003, 00:20
Ok khi nào rảnh tui bắt tay vào ngay, nhưng giờ lo thi học kì cái đã :-)
Í mà bạn có biết 1 cái cây 3d dựng bằng code sao hông chì tui với

Mach2
02-06-2003, 19:30
Hi, dựng cây 3D hả?
Bạn ko nói rõ là render hay dựng? Mình nghĩ là render ;)
Nói chung là có hai cách, một cách đúng và một cách né. Cách đúng là tạo mô hình 3D cây thật. Cách này dùng đệ quy sinh cây (giống cây nhị phân á), tuy nhiên hiện nay thì dựng một cây 3D real-time là hơi khó á. Ví dụ như cây có 7 tầng (ít hơn thì ko đẹp) thì cần 2^8 control vertex, muốn vẽ thành cây cho đẹp thì phải tạo thêm vài ống thân (ít nhất phải 16 polys cho một thân mới tròn tròn giống cái thân cây thật), thêm lá, thêm hoa... tính ra khoảng vài chục nghìn polys cho một cây!!! Mình đã thử làm cách này cho cây 4 nhánh (thay vì hai nhánh), làm đến tầng thứ 5 là máy bốc khói rùi. Render vài spf (seconds per frame) là chuyện thường nếu dùng nhiều tầng hơn. Bạn thử Tree Lab trong Bryce thì biết...
Cách né là dùng một texture có kênh alpha, render theo cylindrical billboard (lại billboard!!!). Cách này là cách người ta thường dùng hiện nay, nhanh và đẹp, chỉ có điều nhìn xa thì giống chứ nhìn gần thì ghê ghê, bạn có chơi game FPS thì biết.
Mình đã thử cả hai cách và hiện dùng chủ yếu cách né (mình cần thường khoảng 100 cây cho một scene, nếu dùng cách 1 thì chết). Nếu bạn muốn biết chi tiết thì liên lạc sau nhé.

lonelyheart
03-06-2003, 00:53
Bạn biết nhiều hiệu ứng thiệt, nghe bạn nói thì tui cũng hiểu sơ rồi, vậy cách 1 người ta không bao giờ dùng trong Realtime hả..hí hí vậy mà cứ tưởng..bở. Thôi chắc dùng cách né cho nó lẹ , game chủ yếu tốc độ mà. Cảm ơn bạn đã giúp đỡ..Thank. Đợi mốt mình bí cái gì mình sẽ hỏi tiếp nhé...

chokobo_kupo
06-06-2003, 00:26
Í 2 cao thủ nói chuyện với nhau ... tui ngồi ngó !!! :(

chokobo_kupo
06-06-2003, 00:27
Mach2 nè ông đang học hàng không hả ??? Hàng không Bách Khoa có đúng không ??? đệ tử cô LMNghĩa hả ??? :D

lonelyheart
06-06-2003, 00:55
Tui có phải cao thủ gì đâu , tui chỉ mới biết làm tới đó thôi , chỉ có Mach là biết nhiều thiệt

Mach2
06-06-2003, 07:18
to chokobo: mình học Hàng Không á, đúng là đệ tử cô Nghĩa, mới ra trường đợt rồi. Bạn có rảnh ghé qua bộ môn chơi, mình ngồi trực bộ môn chán wá.
to lonelyheart: Ko phải cao thủ gì đâu lonelyheart ui, mình mê đồ hoạ tí thui mờ... Bạn làm đến đâu rùi? Mình có xem cái demo của bạn rùi, bạn nên làm camera động thì mưa hay tuyết mới thật được. Nhìn ở một góc như vậy thì hơi giống movie, ko hay lém.

lonelyheart
07-06-2003, 00:01
Tui muốn làm lém chứ nhưng, tui viết để test nên code nó tùm lum như cái thùng rác , chán lắm ....dể hè có thời gian , sửa lại code mới làm tiếp được :-(
...Bạn tốt nghiệp rồi á, ngàng HK ! hèn chi bạn gửi toàn hình máy bay thôi :-)

Ghostlake114
07-06-2003, 00:24
Match lên chức giảng viên rùi seo ngồi trực bộ môn...

Shinra
07-06-2003, 01:16
Bài viết được gửi bởi Mach2
Ko phải cao thủ gì đâu lonelyheart ui
Hahah .. Mach ko phải cao thủ thì ai làm cao thủ bi rờ ..