Come posso inviare più matrici a uno shader di vertice?


9

Sto praticando animazioni usando ossa / skinning. Sto cercando di inviare allo shader una matrice per vertice. Posso pensare a questi due approcci.

Metodo 1

Ho una maniglia uniforme per ogni matrice ossea come questa

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

e nel onDrawmando ciascuno di loro allo shader: GLES20.glUniformMatrix4fv(u_Bone0, 1, false, matrix0, 0);

Questo ovviamente non è un buon approccio se ho un gran numero di matrici. La mia seconda idea che non ho ancora provato poiché c'è molto codice da refactoring

Metodo 2

È usare il glUniformMatrix4fvper inviarli tutti in una volta come (supponiamo che io abbia 20 matrici)

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

dove matricesè float[16 * 20]. Ma poi modificare le matrici per ogni osso diventa un po 'noioso. Ad esempio, se voglio ottenere la terza matrice, ho bisogno di qualcosa sulla falsariga di

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

e salvare i valori può diventare ancora più fastidioso.


Sto usando il metodo 1 ora, ma non sembra molto intelligente ...

Qual è il modo migliore per inviare più matrici a uno shader OpenGL ES 2?

LE: Sto usando Android, quindi sto cercando una soluzione Java.


Solo un sidenote: se hai troppe matrici puoi anche inviarle tramite fp texture.
Kromster,

Risposte:


2

L'invio di più matrici allo shader è semplice:

Shader:

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

Programma:

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

La modifica delle matrici per ciascun osso non è correlata al modo in cui le si passa allo shader. Puoi apportare modifiche più semplici se lavori con strutture anziché con array di numeri.

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

1
Sto usando Android / Java. Pertanto non posso usare "strutture" o altri tipi di dati (mi dispiace per il breve commento, non posso elaborare atm, ma tornerò più tardi)
asincrono il

2

Suggerirei di usare un VBO. Riempi il tuo VBO con le matrici e passale usando un attributo anziché un'uniforme. In questo modo il VBO distribuirà un nuovo mat4 per vertice nello shader.

Quando si collega il VBO prima di disegnare (o si crea un VAO per questi stati):

  • Abilita gli attributi del vertice (glEnableVertexAttribArray)
  • Imposta i divisori degli attributi del vertice su 0 (glVertexAttribDivisor)
  • Imposta il puntatore degli attributi del vertice (glVertexAttribPointer)

Dai un'occhiata a come passare un mat4 come attributo: /programming/17355051/using-a-matrix-as-vertex-attribute-in-opengl3-core-profile

Spero che sia di aiuto


1
Interessante. Tuttavia, le matrici possono cambiare abbastanza frequentemente (ad esempio, posso aggiungere una rotazione aggiuntiva a una di esse ogni fotogramma). Non rimarranno gli stessi. I VBO sono adatti a questo scenario?
asincrono il

sì, hai appena caricato le nuove matrici ogni frame usando glBufferData
Luka

0

il metodo 1 può essere espanso per utilizzare le matrici per sottrarre il numero di matrici nel codice: (supponendo 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+"]");

e poi quando imposti le matrici puoi farlo

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

Ho finito per implementarlo, ma ancora non migliora molto le cose. Ma finora potrebbe essere l'approccio migliore.
asincrono il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.