Đối với các thiết bị xử lí đồ họa tương ứng trước thế hệ NVIDIA GerForce
8000 series, thì việc sử dụng tính năng vertex texturing không thực sự hiệu
quả. Tuy nhiên với các thể hệ sau đó, đã cung cấp khả nằng fast vertex
texturing thì đây là một kĩ thuật hiệu quả.
55 trang |
Chia sẻ: lylyngoc | Lượt xem: 2677 | Lượt tải: 2
Bạn đang xem trước 20 trang tài liệu Luận văn Xây dựng game engine đa nền tảng mô phỏng tự nhiên, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ử dụng các cờ tiền biên
dịch, hạn chế tối đa việc sử dụng các lớp abstract – vì việc này sẽ làm giảm hiệu suất
chương trình đáng kể Error! Reference source not found.. Cũng vì lí đo chạy đa nền
nên hiện tại chúng tôi sử dụng openGL làm giao diện lập trình đồ họa 3D cấp thấp cho
GEM, do chuẩn openGL là chuẩn mở và không bị phụ thuộc vào hệ điều hành.
GEM được thiết kế hướng đối tượng và yêu cầu về hiệu năng chạy cao nên chúng
tôi sử dụng ngôn ngữ C++ - ngôn ngữ đáp ứng hoàn hảo các điều kiện trên. Đa số các
Game Engine trên thế giới hiện nay đều được phát triển bằng ngôn ngữ C++.
Chúng tôi thiết kế GEM nhắm đến phân khúc phát triển MMORPG, nên khả năng
tương thích với một phạm vi rộng cấu hình phần cứng là một điều kiện quan trọng.
Mục tiêu thiết kế GEM là hoạt động được trên các GPU hỗ trợ openGL 1.4 và shader
1.0 trở lên.
Bảng 1: Bảng GPU tối thiểu được hỗ trợ
Hãng sãn xuất GPU hỗ trợ
nVidia Từ GeForce4 Ti trở lên
Hình 1:
Kiến trúc phân tầng của GEM
4
ATI Từ Radeon 9500 trở lên
Intel ( card tích hợp ) Từ Intel® GMA 3100 ( chipset G31,Q33) trở lên
Chương 3. Kiến trúc tổng thể
GEM là được chia thành nhiều thành phần để tiện cho việc phát triển và bảo trì.
Cụ thể GEM gồm các thành phần như sau:
Ghi chú : Do thời gian làm luận văn có hạn, chúng tôi mới chỉ hoàn thành những
thành phần sau: Giao tiếp với hệ điều hành, Các kiểu dữ liệu cơ bản, Render Engine.
Những thành phần này đủ để hỗ trợ người sử dụng tạo ra các khung cảnh 3D và tương
Hình 2: Kiến trúc tổng thể
5
tác với chúng.
3.1. Thành phần Các kiểu dữ liệu cơ bản
Các kiểu dữ liệu cơ bản là thành phần bao gồm các cấu trúc dữ liệu cơ bản như
mảng động, vector, ma trận…, các phép toán trên các kiểu dữ liệu đó cung cấp cho
thành phần khác sử dụng.
Các kiểu dữ liệu này có thể chia thành 2 nhóm chính:
1. Các yếu tố không gian 3D
‒ Vector2, Vector, Vector4 : các loại vector biểu diễn tọa độ 2 chiều, 3
chiều và tọa độ đồng nhất.
Hình 3: Sơ đồ lớp của thành phần Các kiểu dữ liệu cơ bản
6
‒ Aabb (Axis aligned bounding box) : hình hộp chữ nhật có các cạnh dọc
theo 3 trục xyz, được mô tả bằng 2 điểm (xmin, ymin, zmin ), ( xmax, ymax,
zmax )
‒ Sphere : hình cầu, được mô tả bởi tọa độ tâm và bán kính.
‒ LineSequent, Line, Ray : đoạn thẳng, đường thẳng, tia.
‒ Matrix : ma trận sử dụng để thực hiện các phép biến đổi trong không
gian 3 chiều.
‒ Plane : mặt phẳng được mô tả bằng các hệ số của phương trình: ax +
by + cz + d = 0.
‒ Frustum : là hình chóp cụt biểu diễn khung nhìn của camera, được mô
tả bằng 6 mặt phẳng tạo nên nó.
2. Các kiểu đối tượng lưu trữ
‒ String : lớp lưu trữ dữ liệu kiểu xâu kí tự.
‒ Array : mảng động với hệ số mở rộng có thể tùy biến.
‒ GemAllocator : sử dụng bởi các lớp khác để thực thi việc cấp phát và
giải phóng bộ nhớ.
‒ List : danh sách liên kết 2 chiều.
‒ Stack : ngăn xếp.
3.2. Thành phần Giao tiếp với hệ điều hành
Giao tiếp với hệ điều hành là thành phần thực thi các công việc cần giao tiếp với
hệ điều hành như điều phối event, đọc ghi file, lấy thời gian hệ thống… Trong đó quan
trọng nhất là quá trình điều phối event:
GEM lấy event từ Message System của hệ điều hành, từ đó lấy các thông tin cần
thiết tạo ra GemEvent - lý do cần tạo ra GemEvent là để tránh bị phụ thuộc vào hệ
điều hành. Sau đó, GemEvent sẽ được gửi lần lượt đến các thành phần có khả năng
nhận và xử lý event (Hình 4).
7
3.3. Thành phần Render Engine
3.3.1. Khái quát về Render Engine
Render Engine là thành phần cốt lõi của một Game Engine. Nó hỗ trợ người lập
trình game các công việc thiết yếu để tạo ra một khung cảnh 3D. Người dùng sẽ không
cần biết nhiều đến những công việc tầng thấp như quá trình đọc file tài nguyên, sử
dụng 3D Graphic API, triển khai các hiệu ứng trên GPU… mà chỉ cần dùng giao diện
do Render Engine cung cấp.
Render Engine là thành phần duy nhất trong Game Engine giao tiếp với các thư
viện đồ họa cấp thấp (cụ thể ở đây là openGL và Cg - Hình 5).
Hình 4: Quá trình điều phối event.
8
3.3.2. Kiến trúc của Render Engine
Render engine được chia thành các mô đun sau (Hình 6):
‒ Graphic Driver là mô đun duy nhất trực tiếp sử dụng 3D Graphic API
(openGL), cung cấp cho các mô đun khác một giao diện đơn giản hơn để
tương tác với thiết bị xử lí đồ họa.
‒ Quản lý tài nguyên là mô đun quản lý các tài nguyên cần thiết để xây dựng
Hình 6: Biểu đồ gói của Render Engine.
Hình 5:
Kiến trúc phân tầng của Render Engine.
9
một khung cảnh 3D như mesh, animated mesh, texture 2D, cubemap… Mô
đun này được bạn Hoàng Tuấn Hưng trình bày trong khóa luận “Xây dựng
Game Engine đa nền tảng – Quản lý tài Nguyên và Chuyển động đối tượng”.
‒ Quản lý khung cảnh là mô đun thực hiện việc tổ chức và kiểm soát các đối
tượng tồn tại trong một khung cảnh 3D, từ đó thực hiện quá trình render toàn
bộ khung cảnh đó tạo nên hình ảnh 2D tại vị trí nhìn. Mô đun này được bạn
Trương Đức Phương trình bày chi tiết trong khóa luận “Xây dựng Game
Engine đa nền tảng – Quản lí khung cảnh”.
‒ Hiệu ứng ánh sáng và vật liệu là mô đun mở rộng các thành phần của
Quản lý khung cảnh để tạo các hiệu ứng về ánh sáng, vật liệu, và đổ bóng.
Mô đun này được bạn Bùi Hoàng Khánh trình bày chi tiết trong khóa luận
“Xây dựng Game Engine đa nền tảng – Hiệu ứng ánh sáng và vật liệu”.
‒ Mô phỏng tự nhiên là mô đun mở rộng các thành phần của Quản lý khung
cảnh để mô phỏng các yếu tố tự nhiên cần có trong game như nước, địa hình,
lửa, khói… Mô đun này sẽ được trình bày chi tiết trong chương 3 của khóa
luận này.
‒ Chuyển động của đối tượng là mô đun mở rộng các thành phần của Quản
lý khung cảnh, thực hiện quá trình nội suy trong các mô hình chuyển động
(thường là các nhân vật trong game) thông qua hai kĩ thuật thông dụng là
keyframe và skinning. Mô đun này được trình bày chi tiết trong khóa luận
“Xây dựng Game Engine đa nền tảng – Quản lý tài nguyên và chuyển động
đối tượng” của Hoàng Tuấn Hưng.
3.4. Các thành phần còn lại
Các thành phần Mạng, Trí tuệ nhân tạo, Tính toán vật lí, Âm thanh chưa được
triển khai nên chúng tôi không đề cập đến trong tài liệu này.
10
Chương 4. Mô phỏng Tự nhiên
4.1. Khái Quát
Mô phỏng tự nhiên là một nhiệm vụ hết sức cơ bản và cũng đóng vai trò rất quan
trọng trong các trò chơi 3D hiện nay. Nhiệm vụ của mô đun này là hỗ trợ việc tạo ra
các đối tượng đặc biệt trong khung cảnh 3D – các đối tượng tự nhiên như là nước, lửa,
khói, bụi, mưa, địa hình, cây cỏ … Các đối tượng này thường xuất hiện trong các
khung cảnh ngoài trời. Vì vậy đây là phần không thể thiếu được trong bất kì một game
3D nào có khung cảnh ngoài trời. Vì thời gian không cho phép nên mục tiêu ban đầu
của chúng tôi là triển khai kĩ thuật mô phỏng mặt nước, địa hình và hệ thống hạt – hệ
thống cơ bản được sử dụng để mô phỏng mưa, bụi, khói, lửa,.... Với những hiệu ứng
cơ bản này ta đã có thể tạo ra được một khung cảnh 3D ngoài trời đơn giản.
Hiệu ứng cho các đối tượng ở đây được triển khai chủ yếu sẽ thực thi bằng GPU
để giảm gánh nặng cho CPU, nơi mà các công việc của những phần sau này của hệ
thống vốn sẽ tốn rất nhiều tài nguyên CPU ( đặc biệt quá trình tính toán và xử lí vật lí
). Vì vậy, để triển khai nó chúng ta cần phải lựa chọn một ngôn ngữ lập trình thích hợp
cho GPU. Các tiêu chí được đưa ra để lựa chọn là:
‒ ngôn ngữ lập trình bậc cao, dễ hiểu và triển khai hiệu quả
‒ hỗ trợ lập trình đa nền
‒ hỗ trợ các tính năng của các card đồ họa thế hệ thứ tư ( từ 2002 đến nay )
Dựa trên các tiêu chí trên, chúng tôi đã lựa chọn Cg Shading Language. Chi tiết
về ngôn ngữ là hướng dẫn lập trình có thể tham khảo ở sách “The Cg Tutorial” Error!
Reference source not found..
Như đã nói ở trên mô đun này hiện tại có 3 mô đun con độc lập:
‒ Mô phỏng mặt nước: triển khai kĩ thuật mô phỏng mặt nước từ mô hình vật
lí Error! Reference source not found..
‒ Hệ thống hạt: mô phỏng các hiện tượng như mưa, lửa, vụ nổ, pháo hoa,
khói, tuyết,... hay các hiệu ứng thị giác như phép thuật.
‒ Địa hình: render địa hình có ứng dụng kĩ thuật LOD.
11
4.2. Mô phỏng mặt nước
Mô phỏng mặt nước là một trong các công việc phức tạp và khó khăn nhất hiện
nay trong lĩnh vực đồ họa 3D bởi tính phức tạp và khối lượng phép toán cần thực hiện.
Do đó việc thực hiện mô phỏng mặt nước động thời gian thực trên máy tính cá nhân
trước đây là rất khó khăn. Với sự phát triển của các phương pháp xử lí số tín hiệu, đặc
biệt là biến đổi Fourier nhanh (FFT) khả năng mô phỏng mặt nước thời gian thực bằng
máy tính cá nhân, với điều kiện kích thước vùng nước không quá lớn Error!
Reference source not found.. Tuy nhiên để triển khai việc mô phỏng mặt nước trong
Game Engine, ta cần có kĩ thuật đơn giản để có thể triển khai trên GPU. Vì với ứng
dụng mô phỏng lớn như các trò chơi 3D, thì ngoài việc mô phỏng được hình ảnh 3D
bạn còn phải cần thực hiện rất nhiều tính toán khác như xử lí vật lí, trí tuệ nhân tạo...
Các thành phần này đã chiếm một lượng lớn tài nguyên của CPU và bộ nhớ máy tính.
Vì vậy mô đun này sẽ thực hiện việc triển khai kĩ thuật mô phỏng mặt nước từ
mô hình vật lí được giới thiệu chi tiết trong tài liệu Error! Reference source not
found.. Tư tưởng chính của kĩ thuật này là sử dụng mô hình vật lí là:
‒ Tính toán các sóng lan truyền trên bề mặt theo điều kiện thời tiết (gió)
‒ Tổng hợp các sóng để tính độ cao của bề mặt và normal map.
‒ Tính độ trong suốt nước phụ thuộc vào độ sâu nước và ánh sáng phản xạ từ
environment map.
Như vậy, sau khi render ta có được hình ảnh sóng nước trên bề mặt chuyển động
phụ thuộc vào điều kiện thời tiết và tính chất của vùng nước (nông, sâu) và môi trường
xung quanh.
4.2.1. Thiết kế cơ bản
Mô đun sẽ được triển khai thành 3 class ( xem Hình 7 ):
‒ WaterEffect: lớp trực tiếp quản lí và có nhiệm vụ là tầng giao tiếp với các
chương trình Cg của hiệu ứng mặt nước. Thừa kế từ lớp Effect, các đối
tượng của lớp sẽ được lưu trữ và quản lí bởi EffectBank thuộc package
Quản Lí Tài Nguyên( Chi tiết về cách thức lưu trữ và quản lí xem trong tài
liệu Quản Lí Tài Nguyên – Hoàng Tuấn Hưng).
‒ WaterParameters: lớp này lưu trữ các tham số sẽ được truyền cho các
12
chương trình Cg. Các tham số này quyết định tính chất mặt nước sẽ được
render bởi chương trình Cg. Ví dụ như khoảng bước sóng, tỉ lệ của bước
sóng và biên độ, độ dốc của sóng, tính phản xạ ánh sáng...
‒ WaterSceneNode: lớp mở rộng của lớp SceneNode để được gắn vào
scenegraph của hệ thống RenderEngine. Lớp này sẽ chứa một đối tượng
WaterParameters để lưu trữ các tham số đầu vào cho chương trình Cg.
(Thông tin chi tiết về SceneNode và SceneGraphManager có thể xem trong
tài liệu Quản Lí Khung Cảnh – Trương Đức Phương).
Thêm nữa, chúng ta phải triển khai 2 chương trình Cg:
‒ NormProg: chương trình render normalmap của mặt nước. Các hàm sóng
truyền cho chương trình là các hàm sóng riêng và độc lập so với các hàm
sóng tạo nên chuyển động sóng trong chương trình WaterSim.
‒ WaterSim: chương trình render mặt nước dựa trên bốn hàm sóng và
normalmap đã được tính trước của bề mặt. Các hàm sóng truyền cho chương
trình đã được tạo ngẫu nhiên trước bởi CPU trong lớp WaterEffect dựa trên
Hình 7: Sơ đồ lớp cơ bản của package Mô phỏng Mặt Nước
13
những ràng buộc về tính chất của mặt nước như khoảng bước sóng, độ dốc,
mức độ phản xạ ánh sáng,... Các ràng buộc này được thiết lập cho đối tượng
WaterSceneNode và lưu trữ trong đối tượng WaterParameters.
Với mô hình như trên, mô đun sẽ hoạt động cơ bản như sau:
‒ Bước 1: tạo ra RenderContext cho
renderList của WaterSceneNode và
WaterEffect. Mọi đối tượng
WaterSceneNode đều được gắn vào
renderList này và sử dụng
WaterEffect để render với tham số
của mình.
‒ Bước 2: khởi tạo đối tượng
WaterSceneNode. Trong đó nhiệm
vụ chủ yếu là gắn đối tượng vào
renderList và khởi tạo tham số cho
ràng buộc cho WaterEffect.
‒ Bước 3: Tạo ngẫu nhiên các hàm
sóng dựa trên các tham số ràng
buộc. Song song với việc tạo sóng,
ta cũng phải triệt tiêu dần các hàm
sóng theo thời gian. Rồi tái tạo lại
sóng mới khi một sóng bị triệt tiêu hoàn toàn.
‒ Bước 4: render normal map ra texture với các hàm sóng đã tạo bởi chương
trình Cg NormProg.
‒ Bước 5: render mặt nước với các hàm sóng và normalmap texture đã tạo.
Quá trình render được thực hiện bởi chương trình WaterSim viết bằng Cg.
Quay lại bước 3.
Như vậy sau khi kết thúc bước 5, ta có một hình ảnh mặt nước tại một thời điểm.
Quá trình lặp từ bước 3 đến bước 5 sẽ cho ta một hình ảnh mặt nước động với các tính
chất đã được xác định ban đầu.
Hình 8: Quá trình hoạt động của
package Mô Phỏng Mặt Nước.
14
4.2.2. Thiết kế chức năng
Dựa trên mô hình cơ bản ở trên, ta cần thiết kế các chức năng sau:
‒ Tiền khởi tạo: tạo RenderContext và WaterEffect.
‒ Khởi tạo: khởi tạo đối tượng WaterSceneNode và đặt các tham số cho
WaterEffect.
‒ Tạo sóng: tạo các ngẫu nhiên sóng từ các tham số ràng buộc.
‒ Render normalmap: render normalmap ra texture.
‒ Render mặt nước: render mặt nước với thông số về sóng, và normal map đã
tính trước.
Tiền khởi tạo
Chức năng này được thiết kế thực thi theo sơ đồ luồng như sau:
Theo sơ đồ trong Hình 9, bước đầu tiên ta phải tạo ra rendercontext và đặt các cờ
trạng thái thích hợp cho quá trình render đối tượng WaterSceneNode. Việc tiếp theo là
tạo ra WaterEffect để render WaterSceneNode. Sau đó gắn effect này vào effectBank
trong scenegraphmanager. Việc lưu trữ và quản lí effect hoàn toàn được kiểm soát bởi
effectBank (mô đun Quản lí Tài Nguyên). Do đó ta chỉ cần lưu lại ID của effect để có
Hình 9: Sơ đồ luồng thực hiện chức năng Tiền khởi tạo
15
thể truy cập khi cần. Sau cùng, ta phải gắn RenderContext đã tạo vào render list trong
scenegraphmanager. Việc render list nào được gán sẽ được quyết định bởi người lập
trình khi viết chương trình 3D. Đồng thời chỉ số của render list đó.
Chú ý, vì tất cả các đối tượng WaterSceneNode đều sử dụng chung một đối tượng
RenderContext và WaterEffect nên việc lưu trữ chỉ số của render list hay WaterEffect ở
trong mỗi đối tượng WaterSceneNode là không cần thiết. Ta có thể đưa các thuộc tính
này trở thành thành phần thuộc lớp thay vì thuộc tính riêng của từng đối tượng. Do đó
hàm thực hiện chức năng này cũng thuộc lớp và cần được gọi trước khi tạo ra các đối
tượng WaterSceneNode thực sự.
Khởi tạo
Các bước chính để khởi tạo một đối tượng WaterSceneNode là:
‒ Bước 1: gắn node vào water render list được xác định trong quá trình tiền
khởi tạo.
‒ Bước 2: khởi tạo đối tượng WaterParameters với các tham số mặc định.
‒ Bước 3: khởi tạo các sóng từ các tham số mặc định. Và bắt đầu quá trình cập
nhật các tham số của sóng theo thời gian.
Ngoài các bước chính như phân tích trên, trong sơ đồ (Hình 10) ta có thêm một
số bước sau:
‒ Gán node vào danh sách node con của node cha của nó trong scenegraph.
Đây một chức năng của mọi SceneNode.
‒ Tạo ra texture lưu trữ giá trị cosine và noise để truyền cho chương trình
NormProg nhằm giảm các phép tính phức tạp cho chương trình Cg thực hiện
bởi GPU. BiasNoise là các số ngẫu nhiên được tạo trong khoảng [0..1] để
tăng mức chi tiết cho các gợn sóng. CosineLUT là một texture lưu trữ các giá
trị tương ứng của hàm (sin(2u)*0.5 + 0.5)*cos(2u). Trong đó, u là tọa độ
của các pixel trong hệ tọa độ của texture.
‒ Khởi tạo các texture để thực hiện offscreen render – dùng trong render
normal map.
16
Như vậy, sau khi tạo xong một đối tượng WaterSceneNode. Thì đối tượng đó đã
sẵn sàng để được render trong khung cảnh 3D.
Tạo sóng
Đây là chức năng tạo ra các hàm sóng ngẫu nhiên theo các ràng buộc là các tham
số trong WaterParameters. Ngoài ra nó còn đảm nhận việc triệt tiêu dần các sóng theo
thời gian và tạo lại sóng mới khi một sóng đã hết thời gian sống và bị triệt tiêu hoàn
toàn. Sóng mới được tạo ra vẫn phải được tuân theo ràng buộc như các tham số ban
đầu.
Trạng thái một sóng có thể được đặc tả bởi các thông số sau:
‒ Pha (
‒ Biên độ (A)
‒ Bước sóng (L)
‒ Tần số (f)
‒ Phương truyền (D)
‒ Cường độ sóng (F)
Hình 10: Sơ đồ luồng thực hiện việc khởi tạo đối tượng WaterSceneNode
17
Để tạo ra các sóng ngẫu nhiên, trong các tham số cho hiệu ứng thay vì lưu trữ các
giá trị chính xác của sóng, ta lưu trữ các tham số ràng buộc miền giá trị như bước sóng
lớn nhất (Lmax) và bước sóng nhỏ nhất (Lmin).
Để tạo ra các sóng khác nhau nhưng có cùng dáng điệu ta sẽ thể hiện biên độ của
sóng theo một hệ số tỉ lệ cố định giữa biên độ và bước sóng.
Ngoài ra để tạo ra sự khác biệt về phương truyền sóng, ta còn lưu trữ thêm một
tham số lưu trữ góc lệch tối đa so với hướng gió.
V
ới các
tham
số như
trên ta
có thể
tính ra
tất cả
các
thông
số
trạng
thái
của
sóng
với hệ
số ngẫu
nhiên
được
sinh
trong
khoảng
từ [0..1] với mỗi lần tạo sóng. Thêm nữa để tạo hiệu ứng sóng tăng dần khi mới được
sinh ra rồi bị triệt tiêu dần khi đạt đến mức cao nhất. Ta có thông số về cường độ sóng
F được khởi tạo với giá trị 0, sóng đạt cực đại khi F = 1. Và một tham số đặc trưng cho
tốc độ thay đổi cường độ sóng sau mỗi khung hình, kí hiệu là T. Ngoài ra, ta còn thêm
Hình 11: Sơ đồ tạo hiệu ứng tăng giảm cường độ sóng theo thời gian
18
một tham số là Idx xác định chỉ số sóng đang thay đổi. Vì ta sẽ thay đổi lần lượt cường
độ từng sóng. Quá trình thực hiện xem Hình 11.
Render normalmap
Được thực hiện bởi chương trình viết bằng ngôn ngữ Cg và xử lí qua GPU.
Nhiệm vụ của nó là render normal map từ các tham số đầu vào và hai texture là
BiasNoise và CosineLUT.
CosineLUT là texture lưu trữ giá trị tính trước của
hàm số sin 2 u k− 1 cos 2 u . Việc tính trước giá trị hàm
số này sẽ tiết kiệm rất nhiều phép tính trong các chương
trình Cg. Nơi mà mỗi một phép tính thừa sẽ khiến chương
trình chạy chậm đi rất nhiều do, mỗi chương trình xử lí
pixel được gọi n lần với n là số pixel cần được render. Hơn
nữa đây chỉ là chương trình render normalmap, mục đích
chính là tính ra vector normal với mỗi khung hình. Cho nên
cần phải giảm thời gian xử lí để tính ra vector normal nhanh
nhất có thể. Để cung cấp vector normal cho chương trình
render chính sử dụng.
BiasNoise là texture lưu trữ các giá trị ngẫu nhiên
trong khoảng [0..1]. Các giá trị này được cộng thêm vào
vector normal để tạo ra bức ảnh không quá láng mịn. Nó có
thể tăng thêm độ chi tiết và đem lại cảm giác thật hơn.
Theo kĩ thuật được giới thiệu trong sách GPU
GemsError! Reference source not found. ta sẽ sử dụng 16 sóng cho
texture vì để tối ưu cho tính toán ta sẽ quá trình xử lí của
chương trình Cg làm 5 giai đoạn. Bốn giai đoạn đầu, mỗi
giai đoạn xử lí 4 sóng. Để cộng gộp giá trị tính toán ta xử
dụng phương pháp trộn màu giữa các giai đoạn. Giai đoạn cuối là cộng giá trị noise.
(xem Hình 12).
Lưu ý là, chương trình render normal sẽ không render hình ảnh vector normal mà
nó render ra một texture. Texture này được sử dụng như là tham số đầu vào và được
truy cập bởi chương trình vẽ mặt nước.
Hình 12: Quá trình
render normal map
19
Render mặt nước
Đây là chức năng chính có nhiệm vụ render ra màn hình hình ảnh 3D của mặt
nước. Chức năng này cũng được thực hiện bởi chương trình Cg chạy trong GPU. So
với chương trình render normalmap thì chương trình này sẽ chỉ chạy một lần vì số
sóng được sử dụng để tổng hợp là ít hơn chỉ có 4 sóng. Các dữ liệu có thể được gói
chung vào trong các vector-4 chiều, để lợi dụng các phép toán vector được hỗ trợ bởi
GPU.
Chương trình xử lí vertex phải thực hiện những việc sau (xem Hình 13):
‒ Chuyển tọa độ vertex từ local space sang world space. Vì các tính toán trong
chương trình đều tính trong world space.
‒ Tính tọa độ texture uv của normal texture.
‒ Tính hệ số lọc theo độ sâu. Hệ số này được dùng để lọc hay giảm bớt biên
độ sóng ở vùng nước nông.
‒ Tính lại tọa độ vertex bằng cách lấy tổng của các hàm sóng.
‒ Tính vector nhìn – vector từ mắt đến vertex. Vector này được truyền cho
fragment program để tính tia sáng đến.
‒ Tính ma trận chuyển vector normal sang không gian world. Vì vector
normal đã tính ở bước trên là tọa độ trong không gian uv của texture.
‒ Tính tọa độ cuối cùng của vertex ( trong không gian Clip ).
‒ Tính lại màu nước theo độ sâu và truyền cho fragment program.
20
Phần việc còn lại của chương trình xử lí pixel là lấy vector normal từ texture.
Chuyển normal sang không gian World bằng ma trận chuyển đổi. Tính tia sáng tới
vertex bằng vector nhìn và vector pháp tuyến. Lấy màu phản xạ của môi trường từ tia
tới và environment map. Trộn màu nước và màu phản xạ ta được màu cuối cùng.
Vertex Program
Fragment Program
Hình 13: Sơ đồ hoạt động của chương trình Render mặt nước
21
4.2.3. Triển khai lớp đề xuất:
WaterParameters
Lớp WaterParameters lưu trữ đối 2 đối tượng của 2 lớp con là GeoWaveParams
và TexWaveParams. Trong đó:
‒ World2Clip, Local2World là các ma trận biến đổi giữa các hệ tọa độ.
‒ NormalMap, EnvMap, CosineLUT, BiasNoise là các ID của các texture
tương ứng.
‒ Chop : là hệ số xác định độ dốc của sóng.
‒ MinLength, MaxLength là các tham số ràng buộc miền giá trị của bước
sóng.
‒ AmpOverLen xác định tỉ lệ giữa bước sóng và biên độ.
‒ WindDir và AngleDeviation: xác định hướng gió và góc lệch tối đa của
phương truyền sóng so với hướng gió.
‒ WaterLevel xác định độ cao của mặt nước trong không gian World.
Hình 14: Sơ đồ lớp WaterParameters
22
‒ TransIdx và TransDel xác định sóng đang bị biến đổi và tốc đổ biến đổi
cường độ sóng.
‒ RippleScale xác định hệ số tỉ lệ của gợn sóng. Được dùng để tạo ra texture
có thể xếp liên tiếp.
WaterEffect
L
ớp
Water
Effect
được
triển
khai
theo
sơ đồ
trên
(Hình
15).
Lớp
được
thừa
kế từ
lớp
Effect, và triển khai các phương thức thực hiện các chức năng sau:
‒ updateParameters() thực hiện update các tham số cho chương trình Cg với
các tham số ràng buộc được truyền vào lưu trữ trong đối tượng của lớp
WaterParameters.
‒ initWaves() : khởi tạo các sóng trong danh sách sóng theo các ràng buộc
được truyền vào.
‒ updateWaves() : cập nhật các sóng theo thời gian.
Ngoài ra lớp có khai báo các lớp con để tiện sử dụng:
Hình 15: Sơ đồ triển khai lớp WaterEffect
23
‒ WaterParams, NormParams lưu trữ các con trỏ đến thanh ghi dữ liệu vào của
các chương trình Cg tương ứng.
‒ TexWaveDesc, GeoWaveDesc lưu trữ các tham số đặc tả trạng thái của sóng
trong không gian texture và không gian vertex. Hiện tại cả hai lớp đều có
cùng các thông số đặc tả chung là pha (Phase), biên độ (Amp), bước sóng
(Len), tần số (Freq), phương truyền (Dir), cường độ sóng (Fade).
WaterSceneNode
Lớp WaterSceneNode là lớp chính thể hiện giao diện lập trình cho người viết
chương trình. Do vậy lớp sẽ có các phương thức thực hiện các chức năng như sau:
‒ createWaterList() : thực hiện chức năng tiền khởi tạo. Phương thức được cài
đặt là phương thức tĩnh. Người lập trình phải gọi phương thức này trước khi
tạo đối tượng của lớp.
‒ updateEffectParameters() : cập nhật lại các tham số thay đổi sau mỗi khung
hình như ma trận biến đổi, vị trí camera. Phương thức này là phương thức
nạp chồng của phương thức thuộc lớp SceneNode và được gọi trước render
node.
‒ render() : triển khai phương thức render riêng của lớp WaterSceneNode.
Phương thức này sẽ gọi lần lượt 2 phương thức render là renderNormalMap()
và renderWater().
Hình 16: Sơ đồ triển khai lớp WaterSceneNode
24
Như đã phân tích trong phần thiết kế chức năng. Hai thuộc tính lưu trữ chỉ số
render list và WaterEffect là m_WaterList và m_EffectID đều được triển khai là thuộc
tính tĩnh không thuộc đối tượng WaterSceneNode.
4.3. Hệ thống hạt
Hệ thống hạt là một hệ thống cơ sở để thực hiện các hiệu ứng tự nhiên được tạo
nên từ các thành phần cơ sở (hạt): mưa, khói, pháo hoa... hay các hiệu ứng có thể được
lượng tử hóa: phép thuật, lửa, vụ nổ...
Một hệ thống hạt sẽ bao gồm các nguồn phát hạt, mỗi một nguồn phát hạt được
đặc trưng bởi tốc độ phát hạt, năng lượng hạt được sinh ra, tốc độ mất năng lượng của
hạt sau khi được sinh ra, và hình dạng hạt được sinh ra.
Hệ thống hạt được phát triển dựa theo hệ thống hạt của phần mềm dựng cảnh 3D
Maya. Hệ thống hạt được phát triển hỗ trợ các mô hình hạt sau:
‒ Point : hạt có dạng điểm. Đây là dạng đơn giản nhất của hệ thống hạt.
‒ Multi-Point : đây là dạng chùm hạt (điểm). Mỗi phần tử hệ thống phát ra
gồm 1 điểm ở trung tâm và 6 điểm xung quanh. Nếu hệ thống tạo ra nhiều
hạt trong một phạm vi nhỏ (mật độ hạt cao) thì nếu sử dụng dạng chùm hạt sẽ
nâng cao hiệu suất chương trình do số lần phát hạt ít hơn.
‒ Streak : hạt sẽ có dạng vệt. Phần tử hạt sẽ được render dạng đường thẳng.
Điểm đầu tiên sẽ được render với độ trong suốt bằng 1.0 và mờ dần cho đến
điểm cuối. Thường được ứng dụng trong việc tạo ra sao chổi, pháo hoa,...
‒ Multi-Streak: tương tự mô hình multi-point nhưng thay vì tạo ra chùm 7
điểm tạo ra một chùm vệt.
‒ Sprite_2D: phương thức thực hiện của mô hình này là render một texture
cho mỗi hạt. Thường được dùng để tạo các hiệu ứng lửa, khói... rất hiệu quả
có tính chân thực cao hơn so với việc dùng các mô hình trên.
Ngoài ra còn có các mô hình hạt chưa được triển khai:
‒ Sprite_3D: tương tự sprite_2D nhưng hỗ trợ sử dụng texture 3D.
‒ Point-sprite : đây là phương thức render hạt dạng sprite (2D và 3D) mới
được hỗ trợ bởi OpenGL 2.0 trở lên, để nâng cao hiệu quả render hệ thống
25
hạt. Tuy nhiên do giới hạn bởi phần cứng nên chỉ có các thiết bị xử lí đồ họa
hỗ trợ OpenGL 2.0 hoặc có hỗ trợ OpenGL extensions
GL_ARB_point_sprite.
Hiện tại mô đun sẽ triển khai hai loại hệ thống hạt. Một là hệ thống hạt tĩnh
(StaticParticleSystemSceneNode) số lượng hạt được cố định và được tạo trước, thường
được ứng dụng mô phỏng các hiện tượng dạng vụ nổ. Hai là hệ thống hạt động
(ParticleSystemSceneNode), các hạt được sinh ra theo thời gian với một tỉ lệ xác định.
Sự kết hợp của hai loại hệ thống hạt trên có thể mô phỏng rất nhiều hiện tượng
phức tạp như pháo hoa, va chạm giữa hai hành tinh...
4.3.1. Thiết kế cơ bản
Thiết lớp cơ bản của mô đun sẽ bao gồm:
‒ ParticleParameters : lớp mở rộng của EffectParameters lưu các tham số cho
chương trình Cg render hạt.
‒ ParticleEffect : lớp giao tiếp với chương trình Cg render hệ thống hạt.
Hình 17: Thiết kế lớp cơ bản của hệ thống hạt
26
‒ ParticleSystemSceneNode : lớp triển khai hệ thống hạt động.
‒ StaticParticleSystemSceneNode : lớp triển khai hệ thống hạt tĩnh.
4.3.2. Thiết kế chức năng
Tiền khởi tạo
Chức năng này được triển khai tương tự như chức năng tiền khởi tạo của mô đun
Mô phỏng mặt nước (xem 3.2.2) .
Khởi tạo
Chức năng khởi tạo đối tượng
ParticleSystemSceneNode được thực hiện cơ
bản như sau (xem Hình 18):
‒ Gán node vào render list được xác
định bởi người viết ứng dụng.
‒ Khởi tạo dữ liệu nguồn ban đầu của
nguồn hạt. Đối với hệ thống hạt tĩnh
(StaticParticleSystemSceneNode) các
hạt được sinh ra ngay trong quá trình
khởi tạo nhưng có kích thước và màu
bằng được gán bằng không.
‒ Tạo đối tượng ParticleParameters.
Cập nhật Hệ thống hạt
Hình 18: Sơ đồ thực hiện chức
năng Khởi tạo đối tượng
ParticleSystemSceneNode
27
Chức năng được thực hiện qua các bước sau:
‒ Bước 1: cập nhật vị trí các hạt tồn tại trong hệ thống (xem Hình 19).
‒ Bước 2: tính số hạt được sinh ra từ khung hình trước cho mỗi nguồn hạt
trong hệ thống.
‒ Bước 3: tạo mới hạt và thêm vào danh sách hạt của nguồn phát hạt.
Hai bước sau chỉ được triển khai trong lớp ParticleSystemSceneNode. Lớp
StaticParticleSystemSceneNode có số lượng hạt cố định do đó không cần sinh thêm
hạt cho các nguồn hạt sau mỗi khung hình.
Phương thức triển khai chức năng này được gọi trước mỗi lần render.
Chú ý: trong Hình 19, vị trí hạt được tính toán dựa trên thời gian trải qua sau mỗi
khung hình, trạng thái hạt hiện tại và các trường lực trong hệ thống.
Render Hệ thống hạt
Hình 19: Sơ đồ cập nhật vị trí hạt
28
Theo sơ đồ hoạt động (Hình 20), với mỗi hạt tồn tại trong hệ thống, ta phải tính
thông tin cần thiết cho các vertex theo hình dạng hạt. Sau đó mới thực hiện render hạt
đó bằng chương trình Cg tương ứng với dạng hạt.
4.3.3. Triển khai lớp đề xuất
ParticleParameters
ParticleParameters là lớp lưu trữ các tham số của chương trình Cg được dùng để
render hạt. Triển khai cụ thể của lớp này sẽ gồm các tham số sau:
‒ m_ModelViewProjMatrix và m_ModelMatrix là các ma trận chuyển đổi từ
local space sang clip space và world space.
‒ m_CameraPos lưu tọa độ của camera trong world space.
‒ m_ColorSampler lưu id của texture 2D được dùng trong hạt có dạng
Hình 20: Sơ đồ hoạt động của chức
năng Render Hệ thống hạt
Hình 21: Sơ đồ triển khai Lớp ParticleParameters
29
sprite_2D.
ParticleEffect
ParticleEffect là lớp trung gian giao tiếp với các chương trình Cg thực hiện việc
render các hạt trong Hệ thống hạt. Phương thức chính cần được triển khai của lớp này
là updateParameters(). Phương thức này có nhiệm vụ truyền giá trị các tham số lưu
trong lớp ParticleParameters cho chương trình Cg render hạt. Giá trị các tham số được
truyền thông qua các con trỏ điều khiển (handle) tham số tương ứng (xem Hình 22).
ParticleSystemSceneNode và StaticParticleSystemSceneNode
Để triển khai các lớp mở rộng của SceneNode cho mô đun Địa hình, ta phải triển
khai các lớp thành phần theo sơ đồ quan hệ trong Hình 23. Trong đó:
‒ Lớp Particle, lớp lưu trữ các thuộc tính thể hiện trạng thái của hạt:
‒ Life là thuộc tính quyết định sinh mạng của hạt hay có thể coi là mức
năng lượng của hạt. Giá trị life = 0 thì hạt chết, life = 1.0 là trạng thái
năng lượng cao nhất.
‒ Fade là thuộc tính quyết định tốc độ chết của hạt tính theo giây. Cũng có
thể hiểu là tốc độ mất năng lượng của hạt.
‒ Speed là thuộc tính quyết định tốc độ di chuyển của hạt.
‒ Acceleration là thuộc tính quyết định gia tốc của hạt.
‒ Color lưu giá trị màu của hạt.
Hình 22: Sơ đồ triển khai lớp
ParticleEffect
30
‒ Pos lưu vị trí (tọa độ) của hạt.
‒ MaxDistance là khoảng cách xa nhất hạt có thể di chuyển. Nếu giá trị
thuộc tính bằng 0 thì có nghĩa là không giới hạn.
‒ Size lưu trữ thông tin về kích thước hạt. Ý nghĩa của kích thước phụ
thuộc vào hình dạng của hạt.
‒ BirthTime lưu trữ thời điểm hạt được sinh ra.
Chú ý: Các thuộc tính năng lượng, tốc độ mất năng lượng, tốc độ, gia tốc,
kích thước, màu sắc và vị trí được lưu trữ thành hai tham số. Một là giá
trị hiện tại của tham số, và giá trị ban đầu khi hạt được sinh ra.
‒ Lớp EmitterData và StaticEmitterData, là lớp lưu trữ thông tin về nguồn
phát hạt. Các thông tin cần được lưu là vị trí nguồn phát và danh sách hạt đã
được sinh ra bởi nguồn phát.
‒ Lớp Field, là lớp trừu tượng mô tả trường lực tác dụng trong hệ thống hạt.
Do đó phương thức chính được triển khai ở các lớp mở rộng của lớp này là
phương thức effect(Particle* p). Phương thức này tính toán ảnh hưởng của
trường lực tác dụng lên chuyển động các hạt trong đó. Cụ thể là gia tốc của
hạt. Hiện tại có hai lớp mở rộng được triển khai cho hai trường lực cơ bản là
trường lực hấp dẫn, và trường lực dạng cầu. Trường lực này thay đổi gia tốc
phụ thuộc vào khoảng cách so với tâm.
Lớp ParticleSceneNode lưu các miền giá trị [min...max] cho các thuộc tính của
hạt và nguồn hạt như: vị trí, màu sắc, tốc độ, gia tốc, khoảng cách, sinh mạng, tốc độ
mất sinh mạng. Ngoài ra, lớp còn phải lưu trữ danh sách nguồn phát hạt, tốc độ phát
hạt, hình dạng hạt, danh sách trường lực và các tham số cơ sở của scene node có sử
dụng Effect là render list và effect id. Lớp StaticParticleSceneNode được triển khai
tương tự nhưng không cần tốc độ phát hạt vì số lượng hạt của các nguồn phát là cố
định.
31
Các phương thức chính được triển khai là:
‒ createParticleList() là phương thức thực hiện chức năng tiền khởi tạo.
Phương thức này sẽ khởi tạo Render Context cho render list mà node sẽ được
gắn vào và đối tượng Particle Effect.
‒ Step() là phương thức thực hiện chức năng cập nhật vị trí hạt theo thời gian
hiện tại.
‒ Render() là phương thức thực hiện chức năng render Hệ thống hạt thông qua
Particle Effect.
‒ Chức năng khởi tạo sẽ được triển khai trong phương thức khởi tạo.
4.4. Địa hình
Địa hình gọi đơn giản thì đó là mặt đất, là thành phần không thể thiếu của khung
cảnh 3D ngoài trời. Việc render địa hình đòi hỏi cần một khối lượng phép toán rất lớn
vì khung cảnh ngoài trời vốn có phạm vi rất lớn. Do đó các đối tượng lưu trữ thông tin
địa hình cũng thường rất tốn kém bộ nhớ máy tính. Đặc biệt là nếu ta lưu trữ thông tin
về địa hình dưới dạng một mesh như một đối tượng thông thường thì để tạo ra cảnh
quan có mức chi tiết chấp nhận thường thì dữ liệu của mesh thương phải rất lớn. Nó
thường bao gồm thông tin về vị trí vertex, vector normal, và chất liệu đất... Do đó để
đơn giản người ta thường lưu trữ thông tin về địa hình dưới dạng heightmap.
Heightmap thường là một bức ảnh đơn sắc trong đó, lưu trữ giá trị thể hiện cao độ của
Hình 23: Sơ đồ quan hệ Lớp mô đun Hệ thống hạt
32
bề mặt. Từ heightmap người ta sẽ chuyển được thành một 3D mesh. Quá trình chuyển
đổi này được thực hiện động khi chương trình render ra khung cảnh 3D.
Ngoài ra, vì các đối tượng địa hình với kích thước lớn, nhưng trong quá trình
render chúng ta nhận ra rằng chỉ có các vertex ở trong một phạm vi nhất định quanh vị
trí camera là cần được render ở mức chi tiết nhất. Với các vertex ở xa, ta có thể giảm
mức độ chi tiết xuống vì thực tế với các đối tượng ở xa thì số pixel được render ra là
giảm đi rất nhiều. Điều đó cho phép ta cắt giảm thông tin, với sai số nhất định thì
khung cảnh được render ra vẫn đảm bảo tính chân thực cần thiết nhưng lại giúp ta tiết
kiệm được không gian bộ nhớ của máy tính, giảm số lượng phép tính cần thực hiện.
Các kĩ thuật thực hiện việc giảm bớt thông tin không cần thiết này được gọi là Level of
Detail ( viết tắt là LOD ).
Các kĩ thuật thực hiện render địa hình có sử dụng LOD đã được phát triển mà tôi
tham khảo được là:
‒ ROAM (tham khảo Error! Reference source not found.).
‒ Geometry clipmaps – F. Losasso, H. Hoppe. 2004 (tham khảo Error!
Reference source not found.).
‒ GPU-based Geometry clipmaps – A. Asirvatham, H. Hoppe. March 2005
(tham khảo Error! Reference source not found.)
Tôi đã chọn kĩ thuật sử dụng Geometry clipmaps để triển khai cho mô đun này
trước tiên vì đây là một kĩ thuật tương đối mới và dễ dàng triển khai đồng thời nó được
tối ưu cho để hỗ trợ các địa hình lớn. Hai phiên bản khác nhau của Geometry clipmaps
như liệt kê ở trên có sự khác nhau lớn nhất là với phiên bản đầu tiên, tác giả giới thiệu
kĩ thuật chủ yếu được triển khai trên CPU. Còn ở phiên bản sau, là phiên bản áp dụng
tính năng mới của card đồ họa hỗ trợ mô hình shader 3.0 (Nvidia Gerforce 6 series).
Đó là vertex textures, tính năng này cho phép bạn truy cập texture ngay trong vertex
program ( Error! Reference source not found.).
Trong khóa luận này, tôi sẽ trình bày phương pháp triển khai thuật toán
GeoClipmaps trên GPU. Vì đây là thuật toán mới, khả năng triển khai dễ dàng và có
nhiều cải tiến về tổ chức dữ liệu so với phương pháp cũ. Trong đó, tôi sẽ cố gắng để
thiết kế của mô đun được đơn giản và hỗ trở khả năng chuyển đổi nhanh sang phiên
bản được triển khai trên CPU.
33
4.4.1. Thiết kế cơ bản
Thiết kế cơ bản của mô đun render Địa hình là tương tự như các thiết kế cơ bản
của mô đun Mô phỏng mặt nước. Do đây là thiết kế chung cho các mô đun mở rộng
các thành phần SceneNode trong mô đun Quản lí Khung cảnh có triển khai riêng của
các hiệu ứng đồ họa.
Các thành phần (lớp) cơ bản bao gồm ( xem Hình 24):
‒ TerrainParameters: là một mở rộng của lớp EffectParameters (mô đun Quản
lí Tài nguyên – Hoàng Tuấn Hưng). Có nhiệm vụ lưu trữ các tham số cho
hiệu ứng dùng để render bề mặt địa hình.
‒ TerrainEffect: mở rộng của lớp Effect. Đây là lớp giao tiếp với chương trình
Cg render bề mặt địa hình.
‒ TerrainSceneNode: mở rộng của lớp SceneNode (mô đun Quản lí Khung
Cảnh). Đây là lớp giao tiếp với người lập trình ứng dụng, có nhiệm vụ quản
lí và điều khiển quá trình render ra bề mặt địa hình từ heightmap.
Quá trình hoạt động của mô đun thực hiện như sau:
Hình 24: Kiến trúc cơ bản của mô đun Địa hình
34
‒ Bước 1: khởi tạo các thành thuộc
lớp được sử dụng chung cho mọi
đối tượng TerrainSceneNode.
‒ Bước 2: khởi tạo đối tượng
TerrainSceneNode.
‒ Bước 3: cập nhật các clip map theo
vị trí camera.
‒ Bước 4: render các tầng clipmap
được kích hoạt. Sau đó quay lại
bước 3 thực hiện render khung hình
tiếp theo.
4.4.2. Thiết kế chức năng
Với thiết kế cơ bản ở trên, mô đun cần
cung cấp các chức năng sau đây:
‒ Tiền khởi tạo: khởi tạo render context cho render list được dùng để render
TerrainSceneNode và TerrainEffect. Phương thức thực hiện chức năng phải
được gọi trước khi tạo và render đối tượng TerrainSceneNode.
‒ Khởi tạo: khởi tạo đối tượng TerrainSceneNode. Trong đó, phải khởi tạo đối
tượng TerrainParameters với giá trị mặc định được sử dụng bởi TerrainEffect.
Đồng thời truy cập height map và khởi tạo các giá trị ban đầu cho các tầng
của của clipmap.
‒ Cập nhật clipmap theo camera: cập nhật thông tin về vị trí, dữ liệu về độ cao
của clipmap.
‒ Render các tầng được kích hoạt: render các tầng được kích hoạt bằng
chương trình Cg với dữ liệu về vertex lưu trong vertex buffer và mảng giá trị
độ cao của vertex.
Tiền khởi tạo
Chức năng này được triển khai tương tự như chức năng tiền khởi tạo của mô đun
Mô phỏng mặt nước (xem 3.2.2).
Hì
nh 25: Sơ đồ hoạt động của mô đun
35
Khởi tạo
Ngoài các bước cơ bản là gán vào node cha, và terrain render list, khởi tạo đối
tượng TerrainParameters, chức năng khởi tạo đối tượng TerrainSceneNode còn phải
thực hiện những công việc sau:
‒ Tạo các Vertex Buffer để lưu trữ thông tin về tọa độ vertex cho các khối con
của clipmap trong mặt phẳng. Các khối này sau khi được tạo ra sẽ được dùng
lại nhiều lần trong quá trình render. Nó chỉ bị huỷ khi đối tượng bị huỷ. Chi
tiết về kĩ thuật triển khai vertex buffer
‒ Tạo các tầng clipmap với các giá trị mặc định.
Cập nhật Clipmap
Đây là chức năng quan trọng, nó đảm nhận vai trò cập nhật dữ liệu của clipmap
khi vị trí camera thay đổi sau mỗi khung hình.
Bước đầu tiên là phải tính các active region theo vị trí camera. Cụ thể là, tạo ra
một vùng diện tích hình vuông xung quanh vị trí camera tương ứng với mỗi tầng
clipmap. Để đơn giản hóa, tôi áp dụng phương pháp lọc bỏ đi các tầng có phạm vi của
nhỏ hơn 2,5 lần độ cao của camera so với mặt đất (xem chi tiết tại tài liệu Error!
Reference source not found.).
Hình 26: Luồng thực hiện chức năng khởi tạo
36
Cập nhật mảng lưu trữ giá trị độ cao
của các vertex trong clip map (height field)
và tính normalmap từ heightfield. Trước khi
cập nhật heightfield cho một tầng clipmap,
ta kiểm tra vùng cần update nếu phải update
toàn bộ thì loại bỏ kích hoạt từ tầng này trở
lên.
Bước cuối cùng là tính normalmap cho
các tầng clipmap được kích hoạt từ
heightfield mới.
Render Địa hình
Để render ra bề mặt địa hình, ta phải
render toàn bộ các tầng được kích hoạt còn
lại. Với mỗi tầng ta phải thực hiện các bước
sau:
Chương trình Cg render một khối con được triển khai như sau:
if (không phải tầng cao nhất)
{
foreach (khối con)
if ( nằm trong view frustum)
render khối
}
else
render khối
Hình 27: Sơ đồ hoạt động của chức
năng Cập nhật Clipmap
37
Trong Hình 28, vertex program tính tọa độ x, y trong world space từ tọa độ
vertex trong khối, khoảng cách lưới và tọa độ khối trong world space. Tương tự,
chương trình tính tọa độ u, v được dùng để lấy normal từ normal map. Hệ số trộn
alpha là hệ số dùng để tính tọa độ z khi trộn các cao độ ở phần mép ngoài của lưới
clipmap với tầng thấp hơn. Phương trình tính là: z '= z 1− zc (Phương trình tính
giá trị alpha có thể xem trong tr.4 tài liệu Error! Reference source not found.). Bước
cuối cùng là chuyển tọa độ vertex sang clip space. Các giá trị được truyền cho
fragment program là tọa độ uv, giá trị z để lấy màu theo độ cao và hệ số alpha để trộn
vector normal.
Trong fragment program, vì hạn chế về thời gian cũng như tạo demo đơn giản,
tôi chỉ sử dụng normal để tính ánh sáng khuếch tán.
Vertex Program
Fragment Program
Hình 28: Sơ đồ hoạt động chương trình Render Block
38
4.4.3. Triển khai lớp đề xuất
TerrainParameters
Đây là triển khai ban đầu của lớp TerrainParameters, trong đó các tham số:
‒ m_World2Clip : ma trận chuyển đổi từ world space sang clip space
‒ m_GridScaleFactor : lưu trữ khoảng cách lưới và tọa độ trong mặt phẳng
của khối được render trong world space.
‒ m_TexBlock: lưu trữ thông tin về khối trong texture. Tọa độ của khối trong
texture coordinate cùng hệ số 1/w, 1/h ( w, h tương ứng là độ rộng và chiều
cao texture). Tuy hiện tại không dùng height map nhưng ta có thể tính w = h
= n + 1 (với n là kích thước của lưới clip tầng hiện tại).
‒ m_CameraPos : vị trí camera trong world space.
‒ m_AlphaOffset và m_OneOverWidth tham số được dùng để tính giá trị hệ
số alpha.
‒ m_LightDirection : hướng ánh sáng. Tham số được dùng để tính ánh sáng
khuếch tán trong fragment program.
‒ m_Normalmap : normal map của tầng được render.
‒ m_ZBasedColorSampler : texture lưu trữ mẫu màu theo giá trị độ cao.
TerrainEffect
Hình 29: Triển khai Lớp TerrainParameters
39
Đây là lớp mở rộng của lớp Effect thực hiện việc giao tiếp với chương trình Cg
render một khối con của lưới clipmap ở mỗi tầng. Nó có nhiệm vụ truyền các tham số
trong TerrainParameters cho chương trình Cg. Vì vậy phương thức chính cần được
triển khai là updateParameters(). Phương thức này nhận vào đối tượng
TerrainParameters, và truyền các tham số cho chương trình Cg bằng các con trỏ điều
khiển tham số của chương trình Cg được lưu trong lớp con RenderBlockParams.
Ta đưa các con trỏ điều khiển tham số của chương trình render khối vào một lớp
con riêng để tiện cho việc mở rộng sau này, khi TerrainEffect cần giao tiếp với nhiều
chương trình Cg khác. Việc này tất yếu sẽ phải thực hiện khi ta thực hiện triển khai các
chức năng như cập nhật clipmap bằng chương trình Cg.
TerrainSceneNode
Lớp TerrainSceneNode là lớp quan trọng nhất, hầu hết chức năng của mô đun
chủ yếu được triển khai trong lớp này (Hình 31). Để triển khai lớp TerrainSceneNode
ta triển khai các lớp thành phần sau:
‒ Các lớp FootPrint, RingFixUp, InteriorRing là các lớp quản lí các vertex
buffer object của khối con được lưu trữ trong video memory, và quá trình
render các khối con. Vì vậy nó có hai phương thức chính là
viewFrustumCulling() ‒ kiểm tra khối con có nằm trong trường quan sát của
camera hay không và render() điều khiển việc render khối con. Chi tiết về
cách tổ chức dữ liệu của các khối con xem mục 2.3.2. “Vertex and Index
Bufers” trong tài liệu Error! Reference source not found..
‒ Lớp DegenerateTriangleRing điều khiển việc render vòng tam giác có kích
thước bằng không để tạo ra bề mặt địa hình liên tục, kín nước.
Hình 30: Lớp TerrainEffect
40
‒ Lớp GeoClipmap lưu trữ các thông tin về tầng clipmap. Đó là kích thước,
tầng, khoảng cách lưới, normalmap, mảng dữ liệu độ cao và vị trí của
clipmap trong mặt phẳng z = 0 ở trong worldspace.
Lớp TerrainSceneNode được triển khai các phương thức sau:
‒ createTerrainList() là phương thức thực hiện chức năng tiền khởi tạo. Nó
khởi tạo RenderContext và Terrain Effect cho đối tượng TerrainSceneNode
sử dụng. Phương thức này được triển khai là phương thức tĩnh, và được gọi
trong chương trình ứng dụng trước khi tạo đối tượng TerrainSceneNode.
Hình 31: Sơ đồ lớp TerrainSceneNode và các lớp thành phần.
41
‒ updateEffectParameters() và render() là các phương thức cơ sở của một
SceneNode bất kì sử dụng Effect.
‒ initPyramidClipmap() thực hiện khởi tạo các tầng clipmap với các dữ liệu
ban đầu. Phương thức được gọi ngay trong phương thức khởi tạo
TerrainSceneNode.
‒ updatePyramidClipmap() thực hiện chức năng cập nhật các tầng clipmap
được bật.
42
Chương 5. Kết luận
5.1. Kết quả
Các chương trình demo được chạy trên hai máy thử nghiệm:
1. Dell XPS M1330
▪ CPU: T7100 (1.8GHz x 2)
▪ RAM: 2GB
▪ Card đồ họa : Nvidia GeForce 8400M GS
▪ OS: Windows Vista Home Premium
2. Toshiba Satellite A200-10W
▪ CPU: T7200 (2.0GHz x 2)
▪ RAM: 2GB
▪ Card đồ họa: Nvidia GeForce Go 7300
5.1.1. Mô phỏng mặt nước
Tôi đã hoàn thành xong mô đun và thử nghiệm chương trình demo có một
WaterSceneNode:
‒ Kích thước 65x65 (vertex) tương ứng với khoảng cách 32mx32m.
‒ Kích thước normalmap texture là 256x256 pixel
‒ Số sóng được sử dụng: 4 sóng hình học và 16 sóng texture.
Bảng 2: Bảng đánh giá thời gian thực thi
Chỉ số đo được Satellite A200 XPS M1330
Tốc độ đáp ứng (FPS) ~80 ~120
Thời gian render normalmap(ms) ~7 ~4
Thời gian render mặt nước (ms) ~5 ~5
Như vậy, hệ thống đã vượt qua được yêu cầu đề nghị dành cho game là 60 khung
hình/giây.
43
5.1.2. Hệ thống hạt
Mô đun đã được xây dựng và hoàn thiện. Chương trình demo thực hiện một số
phép đo thực nghiệm cho kết quả như sau:
Bảng 3: Kết quả thực nghiệm tốc độ khung hình đáp ứng Hệ thống hạt
Loại hạt Số lượng hạt XPS M1330 Ghi chú
Point 10000 ~180 fps Hệ thống tĩnh
Multi Point 2000 (tương đương 14000 Point) ~300 fps Hệ thống tĩnh
Streak 2000 ~400 fps Hệ thống tĩnh
Multi Streak ~2000 ~220 fps Hệ thống động
Point sprite ~400 ~190 fps Hệ thống
Trên đây là hình ảnh demo hệ thống hạt được sử dụng để mô phỏng khói, mưa,...
Với kết quả này, ta đã có thể tạo ra những hiệu ứng tự nhiên đơn giản và nhanh chóng.
Để có được các hiệu ứng phức tạp hơn, ta hoàn toàn có thể kết hợp các loại hệ thống
hạt khác nhau để thu được kết quả mong muốn.
Hình 32: Hình ảnh demo hệ thống hạt
44
5.1.3. Địa hình
Đến thời điểm thực viết khóa luận này, tôi đã xây dựng được bộ khung cơ bản
cho mô đun. Các chức năng đã được triển khai xong là:
‒ Chức năng tạo ra TerainSceneNode từ heightmap loại ảnh 8-bit grayscale
bitmap.
‒ Chức năng render các khối con của clip map và cập nhật vị trí clipmap theo
camera.
Hiện tại việc cập nhật các normal map cho các clipmap chưa được triển khai do
còn thiếu sự hỗ trợ offscreen render ra nhiều texture của GEM. Tuy nhiên, các kết quả
đo ban đầu với việc bỏ qua tính toán normal map. Ta thu được kết luận như sau:
‒ Đối với các thiết bị xử lí đồ họa tương ứng trước thế hệ NVIDIA GerForce
8000 series, thì việc sử dụng tính năng vertex texturing không thực sự hiệu
quả. Tuy nhiên với các thể hệ sau đó, đã cung cấp khả nằng fast vertex
texturing thì đây là một kĩ thuật hiệu quả.
‒ Để hỗ trợ cho các thiết bị xử lí đồ họa thấp hơn, ta cần triển khai kĩ thuật
tương tự phù hợp hơn với các thiết bị đó.
Bảng 4: Kết quả đo số khung hình đạt được trên hai hệ thống
Độ lớn của clipmap Kích thước heightmap Satellite A200-10W XPS M1330
63 512x512 pixel ~10 fps >600 fps
127 512x512 pixel ~2 fps >600 fps
5.2. Hướng phát triển
Mô phỏng mặt nước
Tiếp tục triển khai mở rộng cho loại sóng nước lan truyền theo dạng hình tròn,
các loại môi trường nước có thể tương tác. Tìm hiểu các kĩ thuật mô phỏng mặt nước
khác và đánh giá so sánh với kĩ thuật hiện tại để có thể ứng dụng các kĩ thuật mới và
hiệu quả hơn.
Hệ thống hạt
Triển khai thêm một số lớp mở rộng kết hợp các loại hạt cơ bản đã được triển
45
khai để tạo sẵn một số hiệu ứng thường dùng như lửa, pháo hoa, vụ nổ...
Địa hình
Mục tiêu trước mắt là tiếp tục hoàn thiện triển khai của mô đun Địa hình và triển
khai phiên bản kĩ thuật geoclipmap trên CPU dành cho các card đồ họa cấp thấp. Nếu
cần thiết thì phải triển khai một kĩ thuật khác dành riêng cho các hệ thống phần cứng
cấu hình thấp.
Ngoài ra, chúng tôi sẽ tiếp tục triển khai một số mô đun mở rộng khác dành cho
việc mô phỏng tự nhiên như cây cỏ...
Hình 33: Hình ảnh chương trình demo Mô phỏng mặt nước
PHỤ LỤC
Bảng kí hiệu UML sử dụng
Kí hiệu Tên Ý nghĩa
Activity Thể hiện một hành động
Aggregation Thể hiện quan hệ kết tập
Choice Điểm rẽ nhánh có điều kiện
Class Thể hiện một lớp
Composition Thể hiện quan hệ hợp thành
Containment Thể hiện quan hệ bao hàm
Control Flow Thể hiện luồng điều khiển
Dependency Thể hiện quan hệ phụ thuộc
Final state Điểm kết thúc.
Genaralization Thể hiện quan hệ tổng quát hóa.
Initial state Điểm bắt đầu.
Lifeline Vòng đời của đối tượng
Package Thể hiện một gói
Tài liệu tham khảo
Tiếng Anh
[1] Karel Driesen and Urs Hölzle, The Direct Cost of Virtual Function Calls in
C++, 1995 ACM.
[2] Mark Finch of Cyan Worlds. Chapter 1. “Effective Water Simulation from
Physical Models” – GPU Gems, Addison-Wesley, 2004.
[3] Tessendorf, Jerry. 2001. "Simulating Ocean Water." In Proceedings of
SIGGRAPH 2001.
[4] A. Asirvatham, H. Hoppe. Chapter 2. “Terrain rendering using GPU-based
geometry clipmaps” – GPU Gems 2, R. Fernando, eds., Addison-Wesley,
March 2005.
[5] Losasso, Frank, and Hugues Hoppe. 2004. "Geometry Clipmaps: Terrain
Rendering Using Nested Regular Grids." ACM Transactions on Graphics
(Proceedings of SIGGRAPH 2004) 23(3), pp. 769–776.
[6] Mark Duchaineau, Murray Wolinsky, David E. Sigeti, Mark C. Miller,
Charles Aldrich, Mark B. Mineev-Weinstein. “ROAMing Terrain: Real-time
Optimally Adapting Meshes”. 1997
[7] The Cg Tutorial: The Definitive Guide to Programmable Real-Time Graphics
[8] Gerasimov, Philip, Randima Fernando, and Simon Green. 2004. "Shader
Model 3.0: Using Vertex Textures." NVIDIA white paper DA-01373-001_v00,
June 2004.
Các file đính kèm theo tài liệu này:
- LUẬN VĂN- XÂY DỰNG GAME ENGINE ĐA NỀN TẢNG MÔ PHỎNG TỰ NHIÊN.pdf