Làm thế nào để tôi gửi nhiều ma trận cho một shader đỉnh?


9

Tôi đang thực hành hoạt hình bằng cách sử dụng xương / lột da. Tôi đang cố gắng gửi shader một ma trận trên mỗi đỉnh. Tôi có thể nghĩ về hai cách tiếp cận này.

Phương pháp 1

Tôi có một tay cầm thống nhất cho mỗi ma trận xương như thế này

u_Bone0 = GLES20.glGetUniformLocation(mProgram, "u_Bone[0]");
u_Bone1 = GLES20.glGetUniformLocation(mProgram, "u_Bone[1]");

và trong onDrawtôi gửi từng cái cho shader: GLES20.glUniformMatrix4fv(u_Bone0, 1, false, matrix0, 0);

Đây rõ ràng không phải là một cách tiếp cận tốt nếu tôi có một số lượng lớn ma trận. Ý tưởng thứ hai của tôi mà tôi chưa thử vì có rất nhiều mã để cấu trúc lại

Cách 2

Là sử dụng glUniformMatrix4fvđể gửi tất cả chúng cùng một lúc (giả sử tôi có 20 ma trận)

GLES20.glUniformMatrix4fv(u_Bones, 20, false, matrices, 0);

nơi matricesfloat[16 * 20]. Nhưng sau đó sửa đổi ma trận cho mỗi xương trở nên hơi tẻ nhạt. Ví dụ: nếu tôi muốn lấy ma trận thứ 3, tôi cần một cái gì đó dọc theo dòng

float[] _3rd = Arrays.copy(matrices, 3*16, 4*16);

và lưu lại các giá trị có thể trở nên khó chịu hơn.


Hiện tôi đang sử dụng Phương pháp 1, nhưng có vẻ không thông minh lắm ...

Cách tốt nhất để gửi nhiều ma trận đến trình tạo bóng OpenGL ES 2 là gì?

LE: Tôi đang sử dụng Android, vì vậy tôi đang tìm kiếm một giải pháp Java.


Chỉ là một sidenote: nếu bạn có quá nhiều ma trận, bạn cũng có thể gửi chúng qua kết cấu fp.
Kromster

Câu trả lời:


2

Gửi nhiều ma trận cho shader rất đơn giản:

Shader:

uniform mat4 mBones[20]; //20 matrices
.. skipped code ..
vec4 vert = vec4(vPosition, 1.0) * mBones[int(vaBoneId)];

Chương trình:

glUniformMatrix4fv(fShaderUnitSkeletal.uBones, 20, False, @bones20[0]); // Passing 20 matrices

Sửa đổi ma trận cho mỗi xương không liên quan đến cách bạn chuyển chúng cho shader. Bạn có thể thực hiện sửa đổi đơn giản hơn nếu bạn làm việc với các cấu trúc thay vì mảng số.

bones20: array of TMatrix; // Declare array of matrices
bones20[2] := TMatrix.Identity; //Reset 3rd matrix

1
Tôi đang sử dụng Android / Java. Do đó, tôi không thể sử dụng "cấu trúc" hoặc các loại dữ liệu khác (Xin lỗi vì nhận xét ngắn gọn, tôi không thể xây dựng atm, nhưng sẽ quay lại sau)
async

2

Tôi sẽ đề nghị sử dụng VBO. Điền vào VBO của bạn với ma trận và chuyển chúng bằng cách sử dụng một thuộc tính thay vì đồng phục. Bằng cách đó, VBO sẽ phân phối một mat4 mới cho mỗi lần vượt qua đỉnh trong shader.

Khi bạn liên kết VBO trước khi vẽ (hoặc tạo VAO cho các trạng thái này):

  • Kích hoạt các thuộc tính đỉnh (glEnableVertexAttribArray)
  • Đặt các ước tính thuộc tính đỉnh là 0 (glVertexAttribDivisor)
  • Đặt con trỏ thuộc tính đỉnh (glVertexAttribPulum)

Hãy xem cách vượt qua mat4 như một thuộc tính: /programming/17355051/USE-a-matrix-as-vertex-attribution-in-opengl3-core-profile

Hi vọng điêu nay co ich


1
Hấp dẫn. Tuy nhiên, ma trận có thể thay đổi khá thường xuyên (ví dụ tôi có thể thêm một vòng quay bổ sung cho một trong số chúng mỗi khung hình). Họ sẽ không giữ nguyên. VBO có phù hợp với kịch bản này không?
async

có, bạn chỉ cần tải lên các ma trận mới mỗi khung hình bằng glBufferData
Luka

0

phương thức 1 có thể được mở rộng để sử dụng các mảng để trừu tượng hóa số lượng ma trận trong mã: (giả sử java)

int[] u_Bone=new int[NUM_MATRICES];

for(int i=0;i<u_Bone.length;i++)
   u_Bone[i]=GLES20.glGetUniformLocation(mProgram, "u_Bone["+i+"]");

và sau đó khi bạn đặt ma trận bạn có thể làm

for(int i=0;i<matrix.length;i++)
    GLES20.glUniformMatrix4fv(u_Bone[i], 1, false, matrix[i], 0);

Tôi đã kết thúc việc thực hiện điều này, nhưng vẫn không cải thiện nhiều thứ. Nhưng cho đến nay nó có thể là cách tiếp cận tốt nhất.
async
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.