Bagaimana cara mengirim beberapa matriks ke vertex shader?

9

Saya berlatih animasi menggunakan tulang / menguliti. Saya mencoba mengirim shader satu matriks per simpul. Saya bisa memikirkan dua pendekatan ini.

Metode 1

Saya punya satu pegangan seragam untuk setiap matriks tulang seperti ini

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

dan di onDrawsaya kirim masing-masing ke shader: GLES20.glUniformMatrix4fv(u_Bone0, 1, false, matrix0, 0);

Ini jelas bukan pendekatan yang baik jika saya memiliki banyak matriks. Gagasan kedua saya yang belum saya coba karena ada banyak kode untuk refactor

Metode 2

Apakah menggunakan glUniformMatrix4fvuntuk mengirim semuanya sekaligus seperti (anggap saya memiliki 20 matriks)

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

di mana matricesadalah float[16 * 20]. Tetapi kemudian memodifikasi matriks untuk setiap tulang menjadi sedikit membosankan. Sebagai contoh, jika saya ingin mendapatkan matriks ke-3, saya perlu sesuatu di sepanjang baris

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

dan menyimpan kembali nilainya dapat menjadi lebih menyebalkan.


Saya menggunakan Metode 1 sekarang, tetapi tidak terlihat sangat pintar ...

Apa cara terbaik untuk mengirim banyak matriks ke shader OpenGL ES 2?

LE: Saya menggunakan Android, jadi saya mencari solusi Java.

async
sumber
Hanya sidenote: jika Anda memiliki terlalu banyak matriks, Anda juga dapat mengirimnya melalui tekstur fp.
Kromster

Jawaban:

2

Mengirim beberapa matriks ke shader sangat mudah:

Shader:

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

Program:

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

Memodifikasi matriks untuk setiap tulang tidak terkait dengan bagaimana Anda meneruskannya ke shader. Anda dapat membuat modifikasi lebih sederhana jika Anda bekerja dengan struktur bukan array angka.

bones20: array of TMatrix; // Declare array of matrices
bones20[2] := TMatrix.Identity; //Reset 3rd matrix
Kromster
sumber
1
Saya menggunakan Android / Java. Oleh karena itu saya tidak dapat menggunakan "struktur" atau tipe data lainnya (Maaf untuk komentar singkat, saya tidak bisa menguraikan atm, tetapi akan kembali lagi nanti)
async
2

Saya akan menyarankan menggunakan VBO. Isi VBO Anda dengan matriks, dan berikan mereka menggunakan atribut bukan seragam. Dengan begitu VBO akan mendistribusikan mat4 baru per vertex pass di shader.

Saat Anda mengikat VBO sebelum menggambar (atau membuat VAO untuk status ini):

  • Aktifkan atribut titik (glEnableVertexAttribArray)
  • Atur pembagi atribut vertex ke 0 (glVertexAttribDivisor)
  • Atur pointer atribut vertex (glVertexAttribPointer)

Lihat bagaimana cara melewatkan mat4 sebagai atribut: /programming/17355051/using-a-matrix-as-vertex-attribute-in-opengl3-core-profile

Semoga ini membantu

Luka
sumber
1
Menarik. Namun, matriks dapat berubah cukup sering (misalnya saya dapat menambahkan rotasi tambahan ke salah satu dari mereka setiap bingkai). Mereka tidak akan tetap sama. Apakah VBO cocok untuk skenario ini?
async
ya Anda cukup mengunggah matriks baru setiap frame menggunakan glBufferData
Luka
0

metode 1 dapat diperluas untuk menggunakan array untuk abstrak jumlah matriks dalam kode: (dengan asumsi 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+"]");

dan kemudian ketika Anda mengatur matriks yang dapat Anda lakukan

for(int i=0;i<matrix.length;i++)
    GLES20.glUniformMatrix4fv(u_Bone[i], 1, false, matrix[i], 0);
aneh ratchet
sumber
Saya akhirnya menerapkan ini, tetapi masih tidak meningkatkan banyak hal. Namun sejauh ini bisa menjadi pendekatan terbaik.
async