Khóa luận Nghiên cứu và xây dựng thử nghiệm 3D Engine - Phần 4
texture[id]. Texture tương ứng với thứtựtrong id = [ 0.4 ]. Chỉsốid trong
các texture phải liên tục và không được khuyết.
texturefile. Tên tập tin texture. Tên texture file phải bao gồm cả đường dẫn
tính từthưmục chứa tập tin thực thi đến thưmục chứa texture đó.
texture flag(s).0 hay nhiều texture flag cho biết các thông tin vềtexture. Chi
tiết các cờnày sẽ được trình bày chi tiết ởphần sau. Nếu texture flags nhiều hơn 1
thì các flag phải cách nhau khoảng trắng và toàn bộ được đặt trong ngoặc [].
shaderfile. tên tập tin shader cần sửdụng bao gồm cả đường dẫn tính từthư
mục thực thi đến thưmục chứa tập tin đó.
guồn ánh sáng [1] cModel[12] float4x3 c42 .. c77 12 ma trận World (0) -> World (12) (Dùng cho Indexed Skinning). Dùng cho phát triển Engine sau này, hiện nay Engine vẫn chưa hỗ trợ hardware skinning. cView float4x4 c78 .. c81 Ma trận View cProjection float4x4 c82 . .c85 Ma trận Projection cInvModel float4x4 c86 .. c89 Ma trận World (0) nghịch đảo Bảng 3-2 Các hằng mặc định cơ bản Chú thích: [1] : Thông tin về nguồn sáng được bố trí thành cấu trúc. struct LightInfo { float4 color; float4 dir; float4 pos; float4 spotParams; float4 atten; }; LightInfo cLightInfo[2]; Chương 3. Nwfc Engine - 50 - Trong đó: color. Màu của nguồn sáng. dir. Hướng chiếu tới của nguồn sáng (chỉ dùng cho nguồn sáng song song (directional light)). pos. Vị trí đặt nguồn sáng (chỉ dùng cho nguồn sáng điểm (point light) và nguồn sáng hình chóp (spot light)). spotParams. Thông tin về nguồn sáng hình chóp (spot light). atten. Độ suy giảm cường độ ánh sáng theo khoảng cách. Phân loại Vertex Shader trong Engine Vertex Shader trong Engine được phân làm 2 loại tùy vào đặc tính sử dụng Vertex Shader không phụ thuộc (hay không dùng) nguồn sáng. Vertex Shader phụ thuộc vào nguồn sáng ¾ Vertex Shader không phụ thuộc nguồn sáng Vertex Shader thuộc loại này thường khá đơn giản do không phải tính toán đổ sáng từ các nguồn sáng. Số lượng các vi lệnh (intructions) thường rất ít do đó hầu hết chỉ cần dùng Vertex Shader phiên bản vs_1_1 là đủ. Các Vertex Shader được cài đặt sẵn bởi Engine trong số này gồm có (chi tiết các thuật toán và mã nguồn sẽ được trình bày ở chương sau). vertex_screenspace_11.vsh. Dùng để vẽ các đối tượng trực tiếp lên màn hình theo tọa độ điểm trên màn hình. Thường dùng cho việc vẽ các đối tượng giao diện GUI, ngoài ra Shader này còn được dùng trong thuật toán đổ bóng Shadow Volume. vertex_shadowvol_11.vsh. Chỉ dùng cho thuật toán đổ bóng Shadow Volume mà thôi. vertex_skybox_11.vsh. Dùng để vẽ các khung cảnh bầu trời bằng các khối vuông. Chỉ số 11 đằng sau tên của các Vertex Shader chính là phiên bản Vertex Shader đó đang sử dụng. Trong đó 11 là phiên bản vs_1_1, 20 là phiên bản vs_2_0, 30 là phiên bản vs_3_0. Chương 3. Nwfc Engine - 51 - ¾ Vertex Shader phụ thuộc nguồn sáng Các Vertex Shader trong số này gồm có: vertex_bump_11.vsh. Là shader chính dùng để các đối tượng có hỗ trợ ánh sáng và bump bề mặt bằng normal map. Vertex Shader phụ thuộc nguồn sáng có độ phức tạp hơn hẳn do phải tính toán đổ ánh sáng từ các nguồn sáng. Engine hỗ trợ tối đa 2 nguồn sáng cùng với ánh sáng môi trường 6 mặt (ambient light cube) và cung cấp thông tin các ánh sáng này thông qua các biến hằng cAmbientCube[6] và cLightInfo[2], mỗi nguồn sáng có thể là 1 trong 3 loại sau đây, nguồn sáng càng về sau thì tính toán càng phức tạp. Nguồn sáng song song (Directional Light) Nguồn sáng điểm (Point Light) Nguồn sáng hình chóp (Spot Light) Vertex Shader phụ thuộc nguồn sáng khi được viết mới phải đảm bảo sử dụng hết các thông tin về nguồn sáng mà Engine cung cấp để việc dựng hình được chính xác. ¾ Sự phức tạp của Vertex Shader phụ thuộc nguồn sáng Nếu không tính ánh sáng môi trường thì mỗi nguồn sáng có 4 trạng thái (không dùng, song song, điểm và hình chóp) nên tổ hợp trạng thái của 2 nguồn sáng có thể xảy ra trong Engine là 2 * 4 = 8 (trạng thái), muốn kiểm tra 8 trạng thái này Vertex Shader phải sử dụng lệnh rẽ nhánh if. Ta hãy xem qua 1 Vertex Shader đơn giản chỉ tính toán màu sắc vertex theo các nguồn sáng sau đây: VS_OUTPUT main( const VS_INPUT i ) { ... // Calculate lighting for light 1 o.color = 0; if( cLightInfo[0].type == LIGHTTYPE_DIRECTIONAL ) o.color += ( “do directional lighting” ); else if ( cLightInfo[0].type == LIGHTTYPE_POINT ) o.color += ( “do point lighting” ); Chương 3. Nwfc Engine - 52 - else if ( cLightInfo[0].type == LIGHTTYPE_SPOT ) o.color += ( “do spot lighting” ); // Calculate lighting for light 2 if( cLightInfo[1].type == LIGHTTYPE_DIRECTIONAL ) o.color += ( “do directional lighting” ); else if ( cLightInfo[1].type == LIGHTTYPE_POINT ) o.color += ( “do point lighting” ); else if ( cLightInfo[1].type == LIGHTTYPE_SPOT ) o.color += ( “do spot lighting” ); ... return o; } Kết quả là chương trình này quá nặng nề và chỉ biên dịch được trên phiên bản Vertex Shader 3.0 mà thôi (do số vi lệnh phát sinh do các lệnh rẽ nhánh là rất lớn vượt quá giới hạn số vi lệnh tối đa của các phiên bản Vertex Shader thấp hơn, như phiên bản 1.1 chỉ hỗ trợ tối đa 128 vi lệnh còn 2.0 chi hỗ trợ 256 vi lệnh trong 1 chương trình Vertex Shader) điều đó có nghĩa là Shader này chỉ chạy được trên các card màn hình siêu cao cấp mà thôi. ¾ Cách giải quyết của Engine: Engine chia tổ hợp các trạng thái của nguồn sáng thành 11 tổ hợp nguồn sáng (gọi là light combo) ứng với 8 trạng thái ở trên + 3 trạng thái mới do có sự tham gia của ánh sáng môi trường. Mỗi tổ hợp được gán bằng 1 chỉ số nhận dạng (từ 1..11). Chỉ số light combo Nguồn sáng 0 Nguồn sáng 1 Môi trường 1 NONE NONE NONE 2 NONE NONE AMBIENT 3 SPOT NONE AMBIENT 4 POINT NONE AMBIENT 5 DIRECTIONAL NONE AMBIENT 6 SPOT SPOT AMBIENT 7 SPOT POINT AMBIENT 8 SPOT DIRECTIONAL AMBIENT 9 POINT POINT AMBIENT 10 POINT DIRECTIONAL AMBIENT 11 DIRECTIONAL DIRECTIONAL AMBIENT Bảng 3-3 Các tổ hợp nguồn sáng Chương 3. Nwfc Engine - 53 - Tại 1 thời điểm dụng hình (render) chỉ có 1 và chỉ 1 light combo tồn tại mà thôi và thông tin về các nguồn sáng của light combo này là hoàn toàn cố định. Do đó khi thiết kế Vertex Shader thay vì làm 1 Shader lớn như ở trên ta sẽ phân ra làm 11 các Shader nhỏ (mỗi Shader được định dạng bằng chỉ số ứng với light combo mà nó sử dụng, chỉ số này được gán thêm vào tên tập tin để Engine có thể nhận dạng được Vetex Shader đó được dùng cho light combo nào). Ví dụ: tập tin “vertex_bump_11_5.vsh” trong đó “vertex_bump_11” là tên Shader + phiên bản của Shader và “_5” là chỉ số của light combo được sử dụng (ứng với tổ hợp nguồn sáng DIRECTIONAL, NONE, AMBIENT). Với các giải quyết trên chương trình Vertex Shader không phải còn sử dụng các lệnh rẽ nhánh (if) nữa, làm cho số vi lệnh giảm xuống đáng kể khiến cho phiên bản Vertex Shader được biên dịch thành cũng giảm theo, điều này sẽ giúp chương trình có thể chạy trên nhiều thế hệ phần cứng hơn. Đối với loại Vertex Shader phụ thuộc nguồn sáng thì cách sử dụng trong Effect file cũng có 1 số thay đổi nhỏ để Engine có thể nhận biết được loại Vertex Shader này. pass p0 < string vsh = "vertex_bump_11?"; string psh = "pixel_bump_20"; > Dấu “?” phía sau "vertex_bump_11” sẽ giúp Engine nhận diện đây là Vertex Shader có sử dụng nguồn sáng, Engine sẽ tự động tìm kiếm và nạp tất cả các Vertex Shader có tên “vertex_bump_11_x” (x = 1..11) vào bộ nhớ để có thể sử dụng sau này. Chương 3. Nwfc Engine - 54 - 3.5.6.2. Pixel Shader Hầu hết Pixel Shader trong Engine đi liền với 1 Vertex Shader tương ứng do Pixel Shader cần dữ liệu input là các output từ Vertex Shader. Pixel Shader trong Engine không sử dụng các thanh ghi hằng mặc định như Vertex Shader. Danh sách các Pixel Shader được cài đặt trong Engine. pixel_bump_20.psh. Là shader chính dùng để các đối tượng có hỗ trợ ánh sáng và bump bề mặt bằng normal map (dùng chung với vertex_bump_11.vsh). pixel_glowscreen_11.psh. Dùng để vẽ các vật thể phát sáng như bóng đèn, màn hình máy tính… 3.6. Tóm tắt Trong chương này chúng tôi trình bày về một số thành phần chính trong Nwfc Engine. Chi tiết các thuật toán của Vertex Shader và Pixel Shader được cài đặt trong Nwfc Engine sẽ được trình bày ở chương sau. Chương 4. Các thuật toán Vertex và Pixel Shader - 55 - Chương 4 Các thuật toán Vertex và Pixel Shader Lời nói đầu Đổ bóng thời gian thực Shadow Volume Khung cảnh bầu trời (sky box) Chiếu sáng theo điểm ảnh (per-pixel lighting) sử dụng normal map và specular map Tóm tắt Chương 4. Các thuật toán Vertex và Pixel Shader - 56 - 4.1. Lời nói đầu Phần này sẽ trình bày nội dung chi tiết của thuật toán Vertex Shader và Pixel Shader dùng trong Game demo. Các kết quả thử nghiệm đều được chụp lại từ Game demo hay từ Engine. 4.2. Đổ bóng thời gian thực Shadow Volume Trong lĩnh vực đồ họa 3D nói chung cũng như Game 3D nói riêng hiện nay, các mô hình đổ bóng thời gian thực đang được sử dụng rất rộng rãi, ngoài việc giúp người quan sát hình dung được vị trí tương đối của vật thể trong không gian 3 chiều, đổ bóng còn góp phần làm cho bối cảnh trở nên gần gũi với thực tế hơn. Nhận thức được tầm quan trong của việc đổ bóng thời gian thực, hàng loạt các thuật toán về đổ bóng đã đang được phát triển. Hàng loạt các thuật toán ra đời mà đi đôi với nó là chất lượng và tốc độ, trong đó có 2 thuật toán được sử dụng nhiều trong việc dựng hình 3D thời gian thực là Shadow Volume và Shadow Map. Báo cáo trong phần này sẽ đề cập tới cơ sở lý thuyết và áp dụng của thuật toán Shadow Volume trong Nwfc Engine. 4.2.1. Cơ sở lý thuyết ¾ Vùng bóng tối (Shadow Volume) Vùng bóng tối (shadow volume) của một vật thể là 1 khối khu vực trong không gian bị bao phủ bởi bóng tối của vật đó do một nguồn sáng phát ra. Khi dựng hình, tất cả các vật thể khác nằm trong vùng bóng tối đều không được chiếu sáng bởi nguồn sáng tạo ra vùng tối đó. Mỗi shadow volume của vật thể được cấu tạo bởi 3 phần, phần trước (front cap), phần sau (back cap), và phần cạnh (side). Phần trước và phần sau của shadow volume được tạo bởi chính vật thể chắn sáng: phần trước được cấu tạo bởi tất cả các mặt hướng về phía ánh sáng, còn phần sau thì ngược lại bao gồm các mặt hướng ngược lại với hướng ánh sáng nhưng được di chuyển ra xa khỏi nguồn sáng theo phương ánh sáng để cấu thành vùng bóng tối, khoảng di chuyển này phải đủ lớn để
File đính kèm:
- thu_nghiem_3d_engine_4.pdf