Trang 1 / 2 12 LastLast
Hiển thị kết quả từ 1 đến 10 / 19
  1. #1
    Tham gia
    17-09-2002
    Location
    SMA
    Bài viết
    749
    Like
    0
    Thanked 3 Times in 3 Posts

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

    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...
    Attached Images
    Quote Quote

  2. #2
    Tham gia
    17-09-2002
    Location
    SMA
    Bài viết
    749
    Like
    0
    Thanked 3 Times in 3 Posts
    còn cái này là tuyết...
    Attached Images

  3. #3
    Tham gia
    02-12-2002
    Bài viết
    155
    Like
    0
    Thanked 0 Times in 0 Posts
    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

  4. #4
    Tham gia
    02-12-2002
    Bài viết
    155
    Like
    0
    Thanked 0 Times in 0 Posts
    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

  5. #5
    Tham gia
    17-09-2002
    Location
    SMA
    Bài viết
    749
    Like
    0
    Thanked 3 Times in 3 Posts
    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.

  6. #6
    Tham gia
    02-12-2002
    Bài viết
    155
    Like
    0
    Thanked 0 Times in 0 Posts
    Í 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

  7. #7
    Tham gia
    17-09-2002
    Location
    SMA
    Bài viết
    749
    Like
    0
    Thanked 3 Times in 3 Posts
    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ử?

  8. #8
    Tham gia
    02-12-2002
    Bài viết
    155
    Like
    0
    Thanked 0 Times in 0 Posts
    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 )....

  9. #9
    Tham gia
    17-09-2002
    Location
    SMA
    Bài viết
    749
    Like
    0
    Thanked 3 Times in 3 Posts
    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?

  10. #10
    Tham gia
    02-12-2002
    Bài viết
    155
    Like
    0
    Thanked 0 Times in 0 Posts
    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

Trang 1 / 2 12 LastLast

Bookmarks

Quy định

  • Bạn không thể tạo chủ đề mới
  • Bạn không thể trả lời bài viết
  • Bạn không thể gửi file đính kèm
  • Bạn không thể sửa bài viết của mình
  •