2012-03-28 2 views
5

나는 인간과 조랑말과 같은 2 종을 가지고 있다고 말한다. 그들은 서로 다른 골격을 가지고있어서 균일 한 뼈의 배열은 각 종마다 달라야합니다. 각 본 배열을 제대로 렌더링 할 수있는 두 개의 셰이더 프로그램을 구현해야합니까? 아니면 동적 배열을 동적으로 선언하고 동적 배열을 반복하는 방법이 있습니까?(OpenGL 3.1 - 4.2) 동적 균일 배열?

성능을 염두에 두어야합니다 (의사 결정 분기가 진행되는 동안 모든 쉐이더가 빨려 들었습니다).

답변

12

OpenGL 4.3까지, GLSL의 배열은 고정 된 컴파일 시간 크기 여야했습니다. 4.3에서는 쉐이더 저장 버퍼 객체를 사용할 수있게되어 궁극적 인 길이가 "제한되지 않음"을 허용합니다. 기본적으로, 당신은이 작업을 수행 할 수 있습니다

buffer BlockName 
{ 
    mat4 manyManyMatrices[]; 
}; 

OpenGL은 당신이 glBindBufferRange를 사용하는 방법에 따라 런타임에이 배열에 얼마나 많은 행렬 알아낼 것입니다. 따라서 길이를 얻으려면 여전히 manyManyMatrices.length()을 사용할 수 있지만 컴파일 타임 상수는 아닙니다.

그러나이 기능은 (이 편집 시점에) 매우 새롭고 베타에서만 구현됩니다. 또한 GL 4.x 급 하드웨어 (일명 : Direct3D 11 급 하드웨어)가 필요합니다. 마지막으로 셰이더 저장 블록을 사용하기 때문에 데이터에 액세스하는 것이 원하는 것보다 느릴 수 있습니다.

이와 같이, 내가 사용하는 행렬 수가 가장 많은 균일 블록을 사용하는 것이 좋습니다. 그것이 메모리 문제 (가능성은 희박한 경우)가되면 어레이 크기를 기반으로 셰이더를 분할하거나 셰이더 저장 블록 또는 기타를 사용할 수 있습니다.

10

배열 대신 nx1 텍스처를 사용할 수 있습니다. 텍스처 크기는 런타임에 지정할 수 있습니다. 셰이더에 임의의 수의 조명을 전달할 때이 방법을 사용합니다. 나는 많은 루프와 가지에도 불구하고 그것이 얼마나 빨리 실행되는지 놀랍습니다. 예제는 jReality 소스의 jogl3.glsl.nontransp에있는 polygon.f 셰이더 파일을 참조하십시오.

uniform sampler2D sys_globalLights; 
uniform int sys_numGlobalDirLights; 
uniform int sys_numGlobalPointLights; 
uniform int sys_numGlobalSpotLights; 

...

int lightTexSize = sys_numGlobalDirLights*3+sys_numGlobalPointLights*3+sys_numGlobalSpotLights*5; 

    for(int i = 0; i < numDir; i++){ 
     vec4 dir = texture(sys_globalLights, vec2((3*i+1+0.5)/lightTexSize, 0)); 

...