Bài đăng phổ biến

Thứ Sáu, 12 tháng 10, 2012

OpenGLES2.0 - Android (Bài 4 - Basic Texturing)


Trước tiên để tìm hiểu bài này chúng ta cần phải xem qua các bài trước. Bài này chỉ thêm 1 phần nhỏ và được xây dựng dựa trên 3 bài trước. Làm thế nào để chúng ta adding a Texturing. Trước tiên chúng ta hãy tìm hiểu làm thế nào để reading 1 image từ Application Resource. Loading imange vào trong Opengles và hiển thị chúng lên trên màn hình.
  • Texture (vật liệu/vân bề mặt)
Là hình ảnh dùng để "lát" hay "dán" lên một bề mặt. Ví dụ: nền nhà bằng gỗ hay đá đều là các mặt phẳng như nhau, nhưng khác nhau bởi chất liệu "dát" lên.
  • Texel 
Một điểm ảnh (pixel) trên texture. Ta biết rằng texture chỉ là hình ảnh gốc. Còn hình ảnh kết quả trên màn hình được tạo ra từ việc lấy mẫu (sampling) trên texture. Điểm ảnh trên màn hình (hay frame buffer) được gọi là pixel, còn điểm ảnh được lấy mẫu trên texture gọi là texel (gọi tắt của texture pixel).

  •  Texture filtering (lọc vật liệu) 
Ám chỉ việc lấy mẫu (sample) các texel và thực hiện các phép toán trên các mẫu được lấy (thường là các phép tính trung bình có trọng số) để cho ra điểm ảnh kết quả. Texture filtering chỉ dùng để "đặt" hay "dán" (map) texture một cách hiệu quả nhất (về hiệu năng, về chất lượng...) lên bề mặt trong không gian ba chiều. Nó không bao gồm các thao tác làm thay đổi nội dung điểm ảnh như chiếu sáng, tạo bóng tối...

1. Lấy mẫu thô
Phương pháp lấy mẫu đơn giản nhất là ứng với mỗi điểm cần vẽ, ta tìm một điểm phù hợp nhất trên texture. Đây là phương pháp không dùng bộ lọc, được biết đến với cái tên nearest neighbour (láng giềng gần nhất) hay nearest-point sampling (lấy mẫu điểm gần nhất). Phương pháp này thể hiện rất nhiều nhược điểm nhưng cho tốc độ rất cao. Điển hình có thể kể ra đây hai nhược điểm:

• Khi hình ảnh đích lớn hơn hình ảnh nguồn (chẳng hạn khi ta đứng sát một bờ tường): ta có cảm tưởng như các texel được phóng to ra và hình ảnh như là được ghép bởi các khối vuông thô thiển. Lí do là một texel được lấy mẫu cho nhiều pixel.

• Khi hình ảnh đích nhỏ hơn hình ảnh nguồn (chẳng hạn khi ta tiến ra rất xa khỏi bờ tường): chắc chắn thông tin sẽ bị mất mát do số pixel đích ít hơn số texel, dẫn đến có texel không được lấy mẫu.

2. Mipmap
Mipmap là các biến thể theo các kích thước khác nhau của cùng 1 texture.

Tại sao phải dùng đến các mipmap? Giả sử bạn đang đứng trên nền nhà bằng gạch, chắc chắn những viên gạch ở gần bạn trông sẽ "to" hơn theo phối cảnh, và do đó chi tiết hơn. Ở xa, sẽ có ít điểm hơn để hiển thị texture. Do đó mà texture bị co lại. Phép co sẽ làm mất những chi tiết quan trọng như đường viền xi măng của các viên gạch. Lí do là chỉ một số ít điểm trên texture được lấy mẫu (tùy vào loại bộ lọc bạn sử dụng mà độ mất mát khác nhau, tùy vào số texel được lấy mẫu cho một pixel). Tệ hơn nữa, khi bạn di chuyển trên nền gạch, các điểm lấy mẫu trên texture thay đổi theo. Điều này gây ra cảm giác nhiễu trên màn hình vì các điểm ảnh thay đổi liên tục từ texel này sang texel khác. Đặc biệt khi nền gạch có nhiều hoa văn với độ tương phản cao. Nhiễu còn thể hiện ở điểm các hoa văn trông như rời rạc, không liên tục do các texel được lấy mẫu một cách rời rạc.

Các mipmap liên tiếp nhau có kích thước mỗi chiều chênh nhau 2 lần (như vậy ở texture nhỏ hơn, 1 điểm được tạo ra từ 4 điểm ở texture lớn hơn). Các card đồ hoạ ngày nay đều cho phép sinh mipmap tự động. Tức là chỉ cần cung cấp texture ở mức chi tiết nhất.

Để kiểm tra việc sử dụng các mipmap, người ta dùng các Color Mipmap. Người ta tô các texture ở các mức khác nhau với các màu khác nhau. Do đó, khi hiển thị lên màn hình, ta có thể dễ dàng nhận thấy các texture khác nhau được lấy mẫu như thế nào.

3. Linear Filtering (lọc tuyến tính)
Lọc tuyến tính hiểu một cách nôm na là thay vì ta chuyển trực tiếp từ texel này sang texel khác khi lấy mẫu, các texel lại được chuyển qua dần dần một cách tuyến tính. Trong phép lọc tuyến tính, với mỗi chiều lọc, mỗi điểm ảnh được tạo ra từ trung bình có trọng số của hai texel.

Phép lọc tuyến tính đơn giản nhất là Bilinear Filtering. Phép lọc này tạo ra pixel kết quả từ 4 texel gần nhau. Gọi là Bilinear (song tuyến tính) vì nó tuyến tính theo hai trục của texture.

Hình sau đây cho thấy tác dụng của lọc tuyến tính khi thu nhỏ một trang web so với việc dùng phương pháp nearest-point sampling. Do có nhiều texel được lấy mẫu hơn nên nội dung mất mát giảm đi.

Đối với việc phóng to một hình, lọc tuyến tính làm cho việc chuyển tiếp giữa các texel trở nên mượt mà, không bị cảm giác về các khối vuông.

Trong đồ hoạ 3D và game hiện nay, gần như ta không còn gặp nearest neighbour nữa mà thay vào đó là các phương pháp lọc tiên tiến, phổ biến nhất là lọc tuyến tính.

4. Trilinear Filtering (lọc tam tuyến tính)
Như ta thấy, Bilinear filtering không dính dáng tới các mipmap. Nói cách khác, bilinear lọc từng texture trong mipmap một cách riêng rẽ. Do đó, ở chỗ chuyển tiếp giữa các mức mipmap lộ ra mép nối. Kết quả là trông hình ảnh đích như được tạo bởi các "băng" hay "dải" mipmap song song. Điều này đặc biệt khó chịu khi bạn di chuyển trong game. Có cảm giác như có những lớp hình ảnh luôn luôn chạy ở phía trước mặt bạn. Những đường nằm ngang cứ như muốn chấn vào mắt bạn.

Các băng texture bị biến mất với trilinear, hình trở nên "mượt" hơn

Trilinear filtering giải quyết vấn đề này bằng cách thực hiện lọc tuyến tính trên cả các mipmap, làm cho các texture được hoà trộn vào nhau trên hình đích. Trong các card đồ hoạ hiện nay, "chi phí” cho bilinear filtering rất thấp, gần như "miễn phí” (theo nghĩa không ảnh hưởng đến hiệu năng). Nhưng trilinear thì không như vậy, nó là một bộ lọc tốn kém. Vì nó không chỉ tăng gấp đôi số điểm lấy mẫu (từ 4 lên 8) mà còn yêu cầu phải xử lí nhiều texture cùng lúc. Do đó, hiện nay xuất hiện nhiều phép tối ưu để thực hiện trilinear hiệu quả hơn.

5. Anisotropic filtering (lọc bất đẳng hướng)
Trong thực tế đồ hoạ 3D, texture không đơn thuần được vẽ với hình dáng như ban đầu của nó. Do phối cảnh ba chiều, hình vuông hay hình chữ nhật (là dạng gốc của texture) trở thành hình bình hành, hình thang... Trong bộ lọc bất đẳng hướng, khác với Linear Filtering, các texel không được lấy mẫu theo một hình dạng đối xứng (đẳng hướng) mà theo một hình bất quy tắc được điều chỉnh tùy theo phối cảnh. Ta có thể hình dung mỗi pixel đích trên hình ảnh kết quả là một hình vuông. Tương ứng với hình vuông này có thể là hình chữ nhật, hình bình hành hay hình thang... trên texture. Dưới đây là một hình minh hoạ khi ánh xạ cùng một hình tròn nhỏ trên hình ảnh đích sang texture. Tùy vị trí của hình tròn mà các vùng tương ứng trên texture khác nhau.

Anisotropic filtering tiến bộ hơn hẳn so với linear filtering vì nó bám sát hình dạng thực của điểm ảnh, cung cấp khả năng thể hiện thực và đầy đủ hơn nội dung của điểm ảnh, làm giảm thiểu mất mát nội dung trên hình kết quả. Anisotropic filtering có nhiều mức độ khác nhau (như ta thấy trong các thiết lập của driver và game), tùy thuộc vào số texel được lấy mẫu cho mỗi điểm ảnh đích. 1x lấy mẫu 4 texel (ta chưa xem xét đến mipmap), nên kết quả tương tự bilinear; 2x lấy mẫu 8 texel; 4x lấy 16; 8x lấy 32 và 16x (mức cao nhất hiện nay) lấy 64. Ta dễ dàng nhận thấy rằng càng lấy nhiều texel càng đòi hỏi texture chi tiết. Do đó, với các mức cao, mipmap càng bị đẩy sâu vào trong.

Lọc bất đẳng hướng có thể kết hợp với bilinear hoặc trilinear thành bilinear anisotropic hoặc trilinear anisotropic. Với bilinear anisotropic, lọc diễn ra độc lập trên từng mức mipmap; với trilinear anisotropic, lọc được hoà trộn trên hai mức mipmap gần nhất.

Tuy nhiên, cho đến hiện nay, lọc bất đẳng hướng vẫn là một "món" xa xỉ. Nó vừa yêu cầu lấy mẫu một số lượng lớn các điểm, lại vừa sử dụng phép tính có trọng số phức tạp. Do đó, nhiều phép tối ưu đã được thực hiện.

BÍ MẬT CỦA TỐI ƯU
1. Brilinear – Optimized Trilinear
Hiểu một cách đơn giản thì "tối ưu" nghĩa là "làm ít hơn chứ không phải tốt hơn". Nhà thiết kế cố gắng giảm các thao tác được yêu cầu để cho kết quả chính xác nhằm làm cho phần cứng chạy nhanh hơn mà ít ảnh hưởng đến cảm nhận của người sử dụng (nó có thể đem lại kết quả mà hầu hết các điểm ảnh đều bị sai khác, nhưng tác dụng về mặt thị giác giữa hai hình ảnh lại chênh lệch không đáng kể).

Phép tối ưu điển hình nhất và cũng được dùng phổ biến nhất là brilinear, một "phép lai" giữa trilinear với bilinear, thay thế cho trilinear. Mục đích chính của trilinear là làm mất đi các "dải" mipmap trên hình kết quả. Brilinear thu giảm vùng hòa trộn các mức mipmap vào sát các đường ranh giới và thực hiện bilinear hoàn toàn (tức chỉ dùng một mức mipmap) ở vùng chính giữa các "dải" này. Như vậy tức là giảm đáng kể việc sử dụng trilinear và thay thế bằng việc dùng bilinear. Ta có thể thấy rõ điều này qua hình minh hoạ dùng color mipmap dưới đây.

Với Brilinear, khoảng chuyển tiếp mipmap bị thu hẹp và có một khoảng chỉ được lọc Bilinear

Nói chung rất khó để phát hiện ra brilinear bằng mắt thường khi sử dụng các mipmap thực (chẳng hạn khi chơi game). Trong các game thông thường, brilinear có thể thu được đến hơn 30% hiệu năng so với full trilinear.

Hầu hết các chip đồ hoạ mới hiện nay đều dùng phương pháp này. Ta có thể thấy tùy chọn sử dụng "trilinear optimizations" trong driver của các card đồ họa mới dòng GeForce.

2. Tối ưu góc trong Anisotropic Filtering
Thử tưởng tượng bạn đang đứng đối diện với một bức tường. Vì bức tường song song với màn hình nên nó là một hình "đẳng hướng" (các hướng được bảo toàn tỉ lệ). Do đó, việc lọc bất đẳng hướng trên bức tường không khác biệt so với lọc tuyến tính. Cũng giống như vậy với các mặt phẳng khác. Mỗi mặt phẳng có một độ bất đẳng hướng (tỉ lệ chênh lệch giữa các hướng) cực đại nhất định tùy thuộc vào góc nhìn mặt phẳng đó. Do vậy chỉ cần một mức lọc bất đẳng hướng nhất định mà không cần thiết phải dùng mức lọc cao hơn. Ví dụ nếu texture bị biến dạng ở tỉ lệ 1:2, 2xAF là đủ (đương nhiên ngay cả trên một mặt phẳng, tỉ lệ biến dạng của texture cũng liên tục thay đổi, như đã được chỉ ra trong hình vẽ trước). Tối ưu góc trong Anisotropic Filtering tận dụng điều này để nâng cao hiệu năng xử lí. Nó áp dụng các mức độ lọc khác nhau cho các góc khác nhau. Nghĩa là ngay cả khi bạn yêu cầu mức lọc 16x, sẽ có những góc nào đó mà phép lọc chỉ diễn ra ở mức 2x. Thực tế rất ít góc được thực hiện ở mức 16x hoàn toàn. Tối ưu góc được áp dụng trong tất cả các card đồ hoạ của ATI dòng 9xxx và các dòng X, trong các card NVIDIA GeForce FX 5xxx, 6xxx, 7xxx.

3. Tối ưu theo mức mipmap
Tối ưu theo mức mipmap nói một cách ngắn gọn là tùy thuộc vào mức mipmap khác nhau mà áp dụng các mức lọc khác nhau (chẳng hạn các mức lọc bất đẳng hướng). Do ở các mức mipmap thấp, texture đã giảm chi tiết đi rất nhiều. Nên người xem thường không nhận thấy việc thay đổi độ phức tạp trong phép lọc.

4. Độ chính xác của các phép tính
Số bit được sử dụng để lưu trữ các giá trị, các tham số, trọng số trong các phép tính ảnh hướng rất lớn đến độ chính xác của kết quả.

Ví dụ dễ thấy nhất là số bit xác định trọng số trong phép lọc tuyến tính. Số bit này quyết định có bao nhiêu mức chuyển tiếp về màu sắc giữa hai mốc (hai màu của hai texel kề nhau). Vì hiện nay người ta chỉ dùng 8 bit cho mỗi thành phần màu, nên cũng chỉ cần tối đa 8 bit trọng số là có thể miêu tả đầy đủ các mức màu chuyển tiếp (256 mức). Đây là số bit được dùng trong các card GeForce. ATI sử dụng ít bit hơn. Với 6 bit, các card đồ hoạ của ATI chỉ có thể thể hiện được 64 mức chuyển tiếp, nghĩa là không đầy đủ hoàn toàn.Với ít mức chuyển tiếp, đoạn chuyển tiếp sẽ trở nên kém mượt mà.

Tuy nhiên, thực tế rất khó thấy sự khác biệt này. Vì thông thường các texture chỉ được phóng to ở khoảng nhất định. Nghĩa là chỉ có một số ít điểm ảnh chuyển tiếp giữa hai texel, nên cũng chỉ cần một số ít mức chuyển tiếp. Dù vậy, phép lọc tuyến tính còn được dùng trong các thao tác tìm màu khác (chẳng hạn trong bộ đổ bóng điểm – pixel shading) nên với ít bit hơn, độ chính xác trong kết quả cuối cùng sẽ giảm. Đương nhiên, ít bit cũng có nghĩa là ít xử lí hơn và nhanh hơn.

KIỂM NGHIỆM THỰC TẾ
Có rất nhiều công cụ và phương pháp để kiểm nghiệm những vấn đề liên quan đến các phép lọc. Nhưng có lẽ dễ dàng và quen thuộc nhất với những người chơi game hoặc am hiểu về card đồ họa là phần mềm 3DMark của FutureMark. Công cụ này có chức năng "Filtering & AA" rất trực quan. Ở đây tôi xin giới thiệu vài hướng kiểm nghiệm lí thú để thấy vai trò và ảnh hưởng qua lại của các công nghệ kể trên bằng FutureMark 3DMark05.

Chọn chức năng Filtering & AA của 3Dmark05

Trước khi chạy chức năng này, bạn phải đảm bảo driver đồ họa không "ép" bất cứ thao tác nào như AntiAliasing hay Anisotropic Filtering. Nếu không, các thay đổi trong chương trình sẽ không "nghiệm".

Ban đầu, bạn đặt Mag Filter, Min Filter về Point và MipMapping về None để xem Nearest-point sampling. Thử di chuyển, bạn sẽ thấy nhiễu. Sau đó, đưa cả ba thành Point, bạn sẽ thấy rất rõ các lớp Mipmap (nhất là khi di chuyển, đường phân định các lớp mipmap di chuyển "theo sát" bạn) và thấy luôn cả "tác hại" của việc không dùng lọc tuyến tính. Các khối vuông xuất hiện, đặc biệt khi bạn tăng mức chi tiết LOD bias lên (kéo xịch các mipmap lại gần bạn). Dùng chức năng Mipmap Coloring bạn thấy càng rõ. Bây giờ bạn chuyển Mag/Min Filter lên Linear, bạn có Bilinear. Các lớp mipmap vẫn còn rõ, nhưng nhiễu và khối vuông thì biến mất.

Bây giờ bạn đặt cả ba tham số là Linear, bạn có Trilinear. Không còn các lớp mipmap nữa. Bạn có thể thử với Mipmap Coloring. Các lớp màu giờ đã chuyển tiếp hòa trộn vào nhau.

Tiếp theo, bạn chuyển Mag/Min Filter lên Anisotropic (nếu Anisotropy level khác 1, đặt nó về 1 trước). Chẳng có khác biệt gì đáng kể cả. Như tôi đã trình bày, Anisotropic 1x gần giống với Linear Filtering do đều chỉ dùng 4 mẫu (không tính tới các lớp mipmap). Tăng dần Anisotropy Level, bạn dễ dàng phát hiện thật sự chỉ tồn tại các mức 1x, 2x, 4x, 8x, 16x. Các mức khác đều được làm tròn lên hoặc xuống các mức này. Sử dụng Mipmap Coloring để thấy rằng với mức lọc càng cao, mipmap càng bị đẩy vào sâu. Nếu card của bạn là "đời mới", sử dụng tối ưu góc trong Anisotropic Filtering, thì thật ngạc nhiên! Hầu hết các góc trong 16x và 4x được lọc giống hệt nhau!

Hầu hết các góc AF 4x và 16x được lọc giống nhau

Bây giờ thử nghiệm vì sao Anisotropic Filtering lại "hay" hơn Linear Filtering. Bạn đẩy Anisotropy Level lên 16x, và xem Bilinear/Trilinear Anisotropic Filtering (thay đổi Mipmap giữa Point và Linear). Sau đó chuyển về Trilinear (cả ba tham số đều là Linear). Bạn sẽ thấy hình rất mờ. Giảm LOD bias xuống để hình rõ hơn, bạn sẽ thấy hình "có vẻ” rõ hơn nhưng thực ra lại là nhiễu, nhất là khi bạn di chuyển.

Nếu có card GeForce 6xxx, bạn có thể thử chức năng Trilinear Optimizations bằng thiết lập trong card đồ hoạ. Tuy nhiên thay đổi không trực tiếp trong lúc chạy chương trình nên không được rõ.

Trên đây, tôi đã giới thiệu các phương pháp lọc vật liệu và cả các "bí kíp" mà các nhà sản xuất card đồ họa dùng để tăng hiệu năng đồ họa. Hi vọng bài viết có thể phần nào giúp các bạn có được cái nhìn rõ hơn về đồ họa 3D.

  • Cơ bản của Texturing
Nghệ thuật của việc mapping (ánh xạ) texturing là một trong những phần hết sức quan trọng về việc xây dựng thế giới thực 3D. Nếu không có mapping texturing thì mọi thứ trở nên đơn điệu nhân tạo không giống thực và giống như những giao diện cũ năm 90.

Trò chơi đầu tiên sử dụng Texturing khá là nặng nề như Doom và Duke Nukem 3D. Nó tăng cường đáng kể tính hiện thực của trò chơi thông qua việc thêm vào tác động trực quan - đây là những trò chơi mà có thể bắt đầu thực sự sợ hãi nếu chơi vào ban đêm và trong bóng tối.
Dưới đây là 2 hình ảnh, một cái có Texturing và 1 cái không có texturing.

 Trong hình ảnh bên trái, cảnh được thắp sáng với ánh sáng cho mỗi điểm ảnh và màu. Nếu không cảnh xuất hiện rất trơn tru. Không có nhiều nơi trong cuộc sống thực, nơi chúng ta sẽ đi bộ vào một căn phòng đầy đủ trơn bóng mờ các đối tượng như hình bên trái này .Trong hình ảnh bên phải, cùng một cảnh bây giờ cũng được texturing. Ánh sáng môi trường xung quanh cũng đã được tăng lên bởi vì việc sử dụng Textures dark trên cảnh, do đó bạn cũng có thể nhìn thấy những tác động của texturing trên các khối phụ. Các khối có cùng một số đa giác như trước, nhưng chúng xuất hiện rất nhiều chi tiết hơn với các Textures mới.

  • Texture Coordinates (Tọa độ của Texture) 
Trong OpenGLES, Tọa độ textures thỉnh thoảng được xem trong tọa dộ (s, t) thay vì sử dụng tọa độ (x, y). (S,T) nó mô tả 1 Texel trên Texture. Cái này sau đó được ánh xạ tới polygon. Một thứ khác cần phải chú ý là những tọa độ textures này thì giông các tọa độ Opengl khác: The t (or y) axis thì được chỉ lên trên. Do đó giá trị nhân được thì tăng lên (đi lên).

Trong hầu hết các hình ảnh máy tính, trục y là chỉ xuống dưới. Điều này có nghĩa là góc trên bên trái nhất của hình ảnh là (0, 0), và các giá trị y tăng xuống (đi xuống).Nói cách khác, trục y là lộn giữa hệ tọa độ OpenGL và hầu hết các hình ảnh máy tính, và điều này là một cái gì đó bạn cần phải đưa vào tính toán.

 OpenGL's texture coordinate system.

  • Cơ bản của ánh xạ texture

 Trong bài này chúng ta sẽ nghiên cứu Texture 2D thường  (GL_TEXTURE_2D) với màu đỏ, xanh, và blue (GL_RGB). Opengles thì cũng cung cấp (đưa ra - offer) kiểu texture khác mà sẽ đưa bạn cách xử lý khác và có nhiều hiệu ứng đặc biệt. CHúng ta xem xét lấy mẫu điểm sử dụng GL_NEAREST. GL_LINEAR. và mip - mapping sẽ được đề cập trong bài tới. 

Nào chúng ta hãy bắt đầu vào mã và xem làm thế nào để bắt đầu sử dụng cơ bản texturing trong Android!

  • Vertex Shader

 Chúng ta sẽ lấy ánh sáng per-Pixel của chúng ta từ các bài học trước, và thêm vào sự hỗ trợ của texturing. và đây là thay đổi mới:


attribute vec2 a_TexCoordinate; // Per-vertex texture coordinate information we will pass in.
...
varying vec2 v_TexCoordinate;   // This will be passed into the fragment shader.
...
// Pass through the texture coordinate.
v_TexCoordinate = a_TexCoordinate;
Trong Vertex shader. Chúng ta thêm thuộc tính mới kiểu vec2 (một mảng với 2 thành phần). 2 phần tử này có trong tọa độ của textures và như đầu vào. (Việc này thực hiện trên vertex shader) cũng giống như tọa độ màu, vị trí, pháp tuyến...Chúng ta cũng thêm vào 1 biến varying mà làm đầu vào cho fragment shader qua nội suy tuyến tuyến các bề mặt của hình tam giác (Các hình tam giác là kiểu primitive nên 1 cube cũng được build - in từ triangle).
  • Fragment Shader 



uniform sampler2D u_Texture;    // The input texture.
...
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
...
// Add attenuation.
 diffuse = diffuse * (1.0 / (1.0 + (0.10 * distance)));
...
// Add ambient lighting
 diffuse = diffuse + 0.3;
...
// Multiply the color by the diffuse illumination level and texture value to get final output color.
gl_FragColor = (v_Color * diffuse * texture2D(u_Texture, v_TexCoordinate));


 Chúng ta thêm một Uniform mới, có kiểu simpler2D mô tả dữ liệu texture thực (as opposed to texture coordinate). The varying được đưa vào nội suy texture coordinates từ vertex shader. và chúng ta gọi texture2D(texture, textureCoordinate) để đọc giá trị của texture ở tọa độ hiện thời. Chúng ta sau đó sẽ lấy các giá trị này rồi nhân nó với điều kiện khác rồi sẽ nhận được đầu gia là màu cuối cùng.

Thêm một texture theo cách này làm tối toàn bộ cảnh một chút, do đó, chúng ta cũng tăng lên ánh sáng môi trường xung quanh một chút và làm giảm sự suy giảm ánh sáng.
  • Loading trong texture từ 1 file ảnh

public static int loadTexture(final Context context, final int resourceId)
{
    final int[] textureHandle = new int[1];
    GLES20.glGenTextures(1, textureHandle, 0);
    if (textureHandle[0] != 0)
    {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;   // No pre-scaling
        // Read in the resource
        final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
        // Bind to the texture in OpenGL
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
        // Set filtering
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        // Load the bitmap into the bound texture.
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        // Recycle the bitmap, since its data has been loaded into OpenGL.
        bitmap.recycle();
    }
    if (textureHandle[0] == 0)
    {
        throw new RuntimeException("Error loading texture.");
    }
    return textureHandle[0];
}

1. Bước đầu tiền của ứng dụng texture là khởi tạo 1 đối tượng texture. Một đối tượng texture là 1 đối tượng chứa mà nó nắm dữ dữ liệu texture dữ liệu này cần thiết cho việc dựng hình như là ảnh, bộ lọc, chế độ đóng gói...Trong opengles 1 đối tượng texture được mô tả bởi 1 số nguyên không dấu (Tức là được miêu tả bởi kiểu integer >0) mà là 1 cái gì đó kiểu như là đối số để trỏ đến đối tượng texture giúp chúng ta truy cập qua đối số này. 

GLES20.glGenTextures(1, textureHandle, 0);Sinh ra 1 đối tượng texture, và mảng số nguyên không dấu để handle n đối tượng texture (ở bài này là =1), số 0 là offset của mảng.

2. Một khi chúng ta có Texture handle chúng ta sử dụng nó để loaded texture. Đầu tiên chúng ta cần lấy về định dạng Texture mà Opengles hiểu. Nếu chúng ta sử dụng luôn kiểu ảnh PNG, JPG thì Opengl sẽ không hiểu mà ta phải decode chúng thành kiểu Bitmap.
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;   // No pre-scaling

// Read in the resource

Mặc định, Android áp dụng tỷ lệ trước để Bitmap phụ thuộc vào độ phân giải của thiết bị và tài nguyên bạn đặt ảnh trong đó. Chúng ta không muôn android tỷ lệ Bitmap của chúng ta bất kỳ lúc nào, nên ta đặt option.inScaled=false;


Một khi IDs của đối tượng texture được tạo ra ở bước glGenTexture(), ứng dụng phải liên kết các đối tượng texture để chúng hoạt động. Một khi đối tượng texture đã được liên kết thì bước hoạt động tiếp theo sẽ là glTexImage2D và glTexPrameter ảnh hưởng tới đối tượng texture đã được liên kết. 

Chúng ta thiết lập bộ lọc mặc định là GL_NEAREST cái này nhanh tuy nhiên thô, Tất cả nó là chọn Texel gần nhất tại mỗi điểm trong màn hình, việc này đem lại hình ảnh răng cưa.

// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
Android có 1 tiện ích hữu dụng để load trực tiếp ảnh vào Opengl. Một khi chúng ta đã đọc tài nguyên vào trong 1 đối tượng bitmap. GLUtils.texImage2D() sẽ xử lý phần còn lại. 

Một khi Texture được liên kế tới các tham số texture riêng lẻ, đối tượng texture đó sẽ thừa lại liên kết này tới tham số cho đến khi nó được xóa. Sau khi sinh ra đối tượng texture và liên kết nó. bước tiếp theo để sử dụng một Texture là để thực sự tải dữ liệu hình ảnh. Hàm chính được sử dụng cho Texture loading glTexImage2D

public static void texImage2D (int target, int level, Bitmap bitmap, int border)

Chúng ta muốn 1 bitmap bình thường 2D, vì vậy chúng ta đẩy GL_TEXTURE_2D như là tham số đầu tiên, tham số thứ 2 làm mip-mapping. Và bạn phải chỉ rõ hình ảnh sử dụng ở mức nào, Chúng ta không sủ dụng mip - mapping ở đây .vì vậy chúng ta cho =0, cái này là mức mặc định. Chúng ta đẩy bitmap vào, và chúng ta không sử dụng border vì vậy ta đặt là =0;

Khi chúng ta gọi recycle() trên bitmap gốc, điều này rất là quan trọng, chúng làm free thêm bộ nhớ,Texture đã laoded vào Opengl vì vậy chúng ta không cần dữ lại một bản copy xung quanh nó. 



  • public static void texImage2D (int target, int level, Bitmap bitmap, int border)

Chúng ta muốn có một bitmap 2D bình thường, do đó, chúng ta vượt qua tại GL_TEXTURE_2D như tham số đầu tiên. Tham số thứ hai là để lập bản đồ mip, và cho phép bạn chỉ định các hình ảnh để sử dụng ở mỗi cấp. Chúng ta không sử dụng mip-lập bản đồ ở đây vì vậy chúng ta sẽ đặt 0 đó là mức mặc định. Chúng ta vượt qua trong bitmap, và chúng ta không sử dụng biên giới, để chúng ta vượt qua trong 0.

Chúng ta sau đó gọi tái chế () trên Bitmap ban đầu, đó là một bước quan trọng để giải phóng bộ nhớ. Kết cấu đã được nạp vào OpenGL, vì vậy chúng ta không cần phải giữ một bản sao của nó nằm xung quanh. Có, ứng dụng Android chạy theo một máy ảo Dalvik thực hiện thu gom rác thải, nhưng đối tượng Bitmap chứa dữ liệu cư trú trong bộ nhớ bản địa và họ phải mất một vài chu kỳ để được thu gom rác nếu bạn không tái sử dụng chúng một cách rõ ràng. Điều này có nghĩa rằng bạn thực sự có thể sụp đổ với một trong số lỗi bộ nhớ nếu bạn quên làm điều này, ngay cả khi bạn không còn giữ bất kỳ tài liệu tham khảo để bitmap.







Không có nhận xét nào:

Đăng nhận xét