버텍스 쉐이더에 여러 행렬을 보내려면 어떻게해야합니까?


9

뼈 / 스킨을 사용하여 애니메이션을 연습하고 있습니다. 버텍스 당 하나의 행렬을 셰이더를 보내려고합니다. 이 두 가지 접근법을 생각할 수 있습니다.

방법 1

이 뼈대마다 하나의 균일 한 핸들이 있습니다

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

그리고 onDraw나는 그들 각각을 쉐이더에 보냅니다. GLES20.glUniformMatrix4fv(u_Bone0, 1, false, matrix0, 0);

행렬 수가 많은 경우 분명히 좋은 방법이 아닙니다. 리팩토링 할 코드가 많기 때문에 아직 시도하지 않은 두 번째 아이디어

방법 2

를 사용하여 glUniformMatrix4fv한 번에 모두 보내기 (20 개의 행렬이 있다고 가정)

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

어디 matrices있어 float[16 * 20]. 그러나 각 뼈의 행렬을 수정하는 것은 약간 지루합니다. 예를 들어, 3 번째 행렬을 얻으려면

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

값을 저장하면 더욱 성 가실 수 있습니다.


지금 방법 1을 사용하고 있지만 그리 똑똑하지는 않습니다 ...

여러 행렬을 OpenGL ES 2 셰이더에 보내는 가장 좋은 방법은 무엇입니까?

LE : Android를 사용하고 있으므로 Java 솔루션을 찾고 있습니다.


참고 사항 : 매트릭스가 너무 많으면 fp 텍스처를 통해 보낼 수도 있습니다.
Kromster

답변:


2

여러 매트릭스를 셰이더에 보내는 것은 간단합니다.

쉐이더 :

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

프로그램:

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

각 본에 대한 매트릭스 수정은 쉐이더에 전달하는 방법과 관련이 없습니다. 숫자 배열 대신 구조로 작업하면 수정이 더 간단해질 수 있습니다.

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

1
Android / Java를 사용하고 있습니다. 따라서 "구조"또는 다른 데이터 형식을 사용할 수 없습니다 (간단히 말해 죄송합니다. atm을 설명 할 수는 없지만 나중에 다시 올 것입니다)
async

2

VBO를 사용하는 것이 좋습니다. VBO를 행렬로 채우고 유니폼 대신 속성을 사용하여 전달하십시오. 그렇게하면 VBO는 쉐이더에서 버텍스 패스 당 새로운 mat4를 배포합니다.

그리기 전에 VBO를 바인딩하거나 다음 상태에 대한 VAO를 만들 때 :

  • 꼭짓점 속성 사용 (glEnableVertexAttribArray)
  • 꼭짓점 속성 제수를 0으로 설정 (glVertexAttribDivisor)
  • 꼭짓점 속성 포인터 설정 (glVertexAttribPointer)

mat4를 속성으로 전달하는 방법을 살펴보십시오. /programming/17355051/using-a-matrix-as-vertex-attribute-in-opengl3-core-profile

도움이 되었기를 바랍니다


1
흥미 롭군 그러나 행렬은 자주 변경 될 수 있습니다 (예 : 프레임마다 추가 회전을 추가 할 수 있음). 그들은 동일하게 유지되지 않습니다. 이 시나리오에 VBO가 적합합니까?
async

예, glBufferData
Luka

0

메소드 1은 배열을 사용하여 코드의 행렬 수를 추출하도록 확장 할 수 있습니다. (자바 가정)

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+"]");

행렬을 설정하면

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

나는 이것을 구현하게되었지만 여전히 많은 것을 향상 시키지는 않습니다. 그러나 지금까지는 최선의 방법이 될 수 있습니다.
async
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.