Bài đăng phổ biến

Thứ Tư, 10 tháng 10, 2012

OpenGL ES2.0 for Android (P1)

-Trước tiên viết về chủ đề này tôi sẽ đi qua 1 chút về kiến thức cơ bản về Opengl


  1. Một số khái niệm cơ bản
  2. Camera
  3. Quy trình dựng hình theo PipeLine
  4. Giới thiệu sơ qua về GLSL (GL Shading language)
  5. Các bài tập ví dụ


  1. Nào bây giờ chúng ta bắt đầu với một số khái niệm cơ bản (Một chút ít để vận dụng - fast-food)

  • Hiện nay chúng ta có 2 nền tảng Opengl cho điện thoại di động là OpenGL ES1.x và OpenGL ES2.x đây là 2 nền tảng được ứng dụng rộng trong các trò game trên điện thoại di động tuy nhiên chúng không tương thích được với nhau (OpenGL ES1.x - Quy trình dựng hình và các hàm chức năng được cố định. OpenGL ES2.x - Sử dụng Programmable Pipeline cho phép chúng ta có thể lập trình được ở một số công đoạn trên Pipeline). Nó đòi hỏi cần nhiều mã nguồn hơn, chương trình phức tạp hơn tuy nhiên nó tạo nên một lợi thế cho chương trình cực kỳ linh động cho người lập trình....
  • Hệ trục tọa độ 3 chiều
          Opengles sử dụng hệ trục tọa độ Decart. Có 3 trục Ox, Oy, Oz vuông góc với nhau (Ox thường hướng sang phải, Oy hướng lên trên và Oz hướng ra ngoài màn hình (Đối với Opengl ES2.0).
(Hệ trục tọa độ 3 chiều trong không gian)

  • Đỉnh
        Là một điểm trong không gian 3D trong OpenGl có thể chỉ là 2 tọa độ (x, y) hoặc nhiều tọa độ như (x, y, z, w) ở đó w là tùy chọn và mặc định nó có giá trị là 1.0, tương tự trục z cũng là tùy chọn và giá trị mặc định của nó là 0. Tất các các đối tượng được vẽ bởi các đỉnh hay chính là các điểm, do đó kho nói tới điểm cũng chính là 1 đỉnh.
       Thông tin tối thiểu của một đỉnh là 3 tọa độ x, y, z của đỉnh đó. Ngoài ra, đỉnh còn có thể mang một số thông tin bổ sung như màu sắc, pháp vector (normal vector), vị trí ánh xạ trên ảnh lợp bề mặt (tex coord)... liên quan đến một mặt cụ thể mà đỉnh đó là thành viên. Bởi thế, cùng một vị trí trong không gian có thể có nhiều đỉnh với các thông tin khác biệt.
  • Cạnh
       Cạnh là một đường thẳng nối 2 đỉnh với nhau. Chúng là đường viền của mặt và đa giác. Trong không gian 3D một cạnh có thể là một đường giao nhau của 2 mặt, do đó khi cạnh này chuyển đổi sẽ dẫn đến sự thay đổi theo của các đỉnh, các mặt kết nối với chúng.
Trong OpenGL ES bạn không định nghĩa các cạnh, thay vào đó bạn định nghĩa các mặt bởi các đỉnh khi đó ta sẽ có các cạnh.
Nếu bạn muốn sửa, thay đổi một cạnh bạn có thể thay đổi 2 đỉnh tạo nên cạnh đó.

  • Mặt
       Một cách tổng quát, mặt trong toán học là đa tạp n-1 chiều trong không gian n chiều. Trong tô pô, một mặt hai chiều được gọi là mặt đơn giản nếu nó đồng phôi với một hình vuông trên mặt phẳng hai chiều.
    
      Trong không gian 3 chiều, mỗi đa giác sẽ có 2 mặt: trái và phải. Mặt phải luôn luôn được hiển thị còn mặt trái thì tùy theo thiết lập. Có thể phân biệt hai mặt này dựa vào thứ tự các đỉnh khi nhìn trực diện. Theo quy ước của OpenGL, nếu các đỉnh xếp ngược chiều kim đồng hồ, đó là mặt phải.


  • Điểm ảnh và điểm hoa văn
      Điểm ảnh (Picture Element) là đơn vị nhỏ nhất cấu thành nên hình ảnh (trên màn hình hoặc trong bộ nhớ). Điểm ảnh trong bộ nhớ và điểm ảnh trên màn hình chỉ đồng nhất với nhau khi ảnh được hiển thị trên màn hình với tỉ lệ 1:1. Tương tự như vậy, điểm ảnh hoa văn (Texture Element) là đơn vị nhỏ nhất cấu thành nên hình ảnh hoa văn (Texture), dùng để tạo màu sắc, họa tiết cho các mặt đa giác. Điểm khác biệt lớn nhất giữa hai khái niệm này với đỉnh (vertex) là chúng có hình dạng và kích thước.


  • Phân mảnh
     Phân mảnh là khái niệm trung gian giữa đỉnh và điểm ảnh. Nó cũng gần như là một điểm ảnh đang trong quá trình xử lý. Điểm khác biệt là phân mảnh là đơn vị xử lý của một mặt đơn lẻ, chứ không phải của hình ảnh cuối cùng. Do đó, mỗi điểm trong hình ảnh cuối cùng được tổng hợp từ rất nhiều phân mảnh khác nhau.

  • Tam giác
     Được tạo nên bởi 3 điểm, trong OpenGL chúng ta có thể dùng 3 đỉnh để tạo nên 1 tam giác.
  • Đa giác
     Được tạo nên bởi nhiều hơn 2 điểm, tam giác cũng là 1 đa giác.

-----------------------Đây là một số  kiến thức chính để vận dụng ----------------------

  • QUY TRÌNH DỰNG HÌNH
Nguồn: http://gameuit.com/gameuit/showthread.php?422-OpenGL-ES-2.0/page2

Quy trình dựng hình có thể khái quát trong sơ đồ như sau:


Trong OpenGL 2.0, hai phần màu cam trong quy trình (Vertex Shader và Fragment Shader) là hai phần đòi hỏi các bạn phải tự lập trình (bằng ngôn ngữ GLSL) chứ hệ thống không cung cấp sẵn. Vì thế quy trình này còn gọi là quy trình dựng hình lập trình được.

Ở góc độ chi tiết hơn, ta có quy trình như trong hình sau:


1. Đầu vào

Đầu vào tối thiểu của quy trình dựng hình là một tập các đỉnh tạo thành các mặt đa giác cùng các thông tin bổ trợ. Ngoài ra, hai thông tin đầu vào khác thường thấy đó là ma trận biến đổi và hình ảnh các hoa văn.

Các tọa độ đỉnh đầu vào phải nằm trong một không gian 3 chiều đặc biệt, gọi là môi trường thiết bị chuẩn (NDC: Normal Device Context). NDC được mô tả như một hình khối vuông, sử dụng hệ tọa độ bàn tay trái và có giới hạn tọa độ từ [-1, -1, -1] đến [1, 1, 1]. Tuy OpenGL vẫn chấp nhận và xử lý đầu vào với các tọa độ nằm ngoài NDC nhưng đến khi dựng hình, các phần mô hình nằm ngoài NDC sẽ bị loại ra và do đó không được hiển thị.

2. Vertex Shader

Trong OpenGL ES 2.0, shader là một tập các chỉ thị phần mềm viết bằng ngôn ngữ GLSL (openGL Shader Language) do người dùng tự viết nhằm mục đích tính toán các hiệu ứng dựng hình trực tiếp trên phần cứng đồ hoạ (GPU) với độ linh động cao.

Vertex Shader là shader chuyên làm nhiệm vụ biến đổi toạ độ (quay, tịnh tiến, co giãn, chiếu,...) và thông tin của các đỉnh đầu vào. Các chỉ thị trong Vertex Shader sẽ được thực thi nhiều lần tương ứng với số lượng đỉnh đầu vào. Do đó, số lượng đỉnh đầu vào càng lớn thì tốc độ xử lý sẽ càng chậm.

Sau đây làm một ví dụ về Vertex Shader

PHP Code:
precision lowp float;
uniform mat4 u_mvpMatrix;  // Ma trận biến đổi tọa độattribute vec4 a_position// Tọa độ đầu vào của Vertexattribute vec2 a_uv;       // Texcoord - tọa độ ánh xạ trên ảnh hoa văn (đầu vào)
varying vec2 v_uv;         // Tọa độ ánh xạ trên ảnh hoa văn (đầu ra)
void main()
{
    
gl_Position u_mvpMatrix *  a_position;  // Tính toán tọa độ đầu ra của Vertex
    
v_uv a_uv;                              // Tính toán tọa độ ánh xạ đầu ra trên ảnh hoa văn}  


3. Primitive Assembly

Bước này bao gồm các thao tác dựng và tối ưu mô hình trong không gian ba chiều như:
  • Tập hợp, gắn kết các đỉnh để tạo nên các mặt đa giác cơ bản (primitive).
  • Cắt xén các phần hoặc toàn bộ mặt đa giác nằm ngoài NDC.
  • Loại bỏ các mặt khuất.
4. Rời rạc hóa (Rasterize)

Tại bước này, tọa độ các đỉnh nằm trong NDC sẽ được chuyển về tọa độ màn hình hai chiều. Tiếp đến, chương trình sẽ rời rạc hóa các mặt thành các phân mảnh rồi nội suy màu sắc cho các phân mảnh đó.


5. Fragment Shader

Fragment Shader là shader chuyên làm nhiệm vụ tính toán các hiệu ứng màu sắc cho các phân mảnh. Các chỉ thị trong Fragment Shader sẽ được thực thi nhiều lần tương ứng với số phân mảnh đầu ra. Do số lượng phân mảnh đầu ra lớn hơn rất nhiều so với số lượng đỉnh, thường tỉ lệ thuận với tổng diện tích các mặt nằm trong NDC, nên chi phí tính toán trên Vertex Shader luôn cực kỳ lớn.

Sau đây là một ví dụ về Fragment Shader:
PHP Code:
precision lowp float;
uniform sampler2D u_texture// Ảnh hoa vănvarying vec2 v_uv;           // Tọa độ ánh xạ của phân mảnh trên hoa văn
void main()
{
    
gl_FragColor =  texture2D(u_texturev_uv); // Tính toán màu sắc của phân mảnh}  
6. Kiểm tra (Test)

Phép kiểm tra thông dụng nhất là kiểm tra độ sâu (Depth Test). Theo đó, trên cùng một tia chiếu, những điểm nằm ở xa sẽ bị che khuất bởi những điểm nằm gần hơn (nếu có). Tùy theo thiết bị, việc kiểm tra độ sâu này có thể được thực hiện trước (Early Depth Test) hoặc sau khi gọi Fragment Shader. Ngoài việc đảm bảo hiệu ứng gần-xa, kiểm tra độ sâu sớm còn có lợi ích giảm số lượng phân mảnh cần xử lý và do đó tăng tốc độ tính toán.

Các phép kiểm tra khác bao gồm:
  • Kiểm tra độ trong suốt (Alpha Test).
  • Kiểm tra mẫu tô (Stencil Test).
  • Kiểm tra vùng hiển thị (Cissor Test).
Tất cả các phép thử ở trên đều không bắt buộc. Việc thực hiện những phép kiểm tra nào là tùy thiết lập của ứng dụng.

7. Pha màu (Color Blending) và hòa sắc (Dithering)

Một phân mảnh nếu có độ trong suốt (alpha) thì thường không thể che khuất hoàn toàn những phân mảnh nằm sau nó. Khi đó, màu của nó sẽ được pha trộn với màu của các phân mảnh nằm phía sau. Thao tác này gọi là pha màu và là thao tác không bắt buộc.

Hòa sắc là một thao tác tùy chọn khác giúp làm mịn hình ảnh, nhất là khi số lượng màu của ảnh đầu ra bị giới hạn đến mức khiến cho các sắc màu chuyển tiếp bị mất đi, ảnh trở nên loang lổ.

8. Đầu ra

Đầu ra của quy trình dựng hình là một hình ảnh hai chiều. Hình ảnh này đơn giản là kết quả của một phép chiếu song song toàn bộ phần mô hình nằm trong NDC lên mặt trước của NDC (z = -1). Mặc dù được ánh xạ từ NDC và có tọa độ hai chiều giới hạn trong khoảng [-1, -1] đến [1, 1], hình ảnh đầu ra không phải phải lúc nào cũng vuông (vì cũng hiếm khi có cửa sổ ứng dụng hay màn hình thiết bị nào có kích thước vuông).




Quy trình dựng hình trên có khác với Fixed Pipeline, bạn chỉ sử dụng những chức năng hệ thống cung cấp sẵn, không chế tác thêm.


-----------------------------------------------------------------------------------------------------------------------------













































































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

Đăng nhận xét