2017-09-05 23 views
2

원하는 점은 webgl의 draw 호출에서 정점 셰이더가 몇 번 호출되는지 이해하는 방법입니다. 실제로 인스턴스화하는 것이 무엇인지 알고 싶기 때문에 각 인스턴스에 대해 모든 공유 꼭지점을 호출합니까? 그래서 그것은 너무 많은 시간을 버텍스 쉐이더라고 부를 것입니다.webgl에서 인스턴스링을 수행하는 작업

답변

3

인스 턴싱은 인스턴스 당 정점 셰이더를 하나씩 호출합니다. 차이점은 하나 이상의 속성을 선택하여 정점 당 한 번이 아닌 인스턴스 당 한 번만 진행할 수 있다는 것입니다.

일반적으로 각 속성은 각 정점에 대해 stride 바이트를 전달합니다. stridegl.vertexAttribPointer의 마지막 인수에서 두 번째입니다. stride0 경우 다음 sizetype (gl.vertexAttribPointer에 2 층과 3 인수에 기반을위한 보폭을 계산 WebGL을.

를 특정 속성에 대한 gl.vertexAttribDivisor 전화를 인스턴스화으로. 0은 기본 정상적인 상황과 특성을 발전 '의미 정점 당 한 번 버퍼를 통해. 1 개 수단 인스턴스에 한 번 버퍼를 통해 속성을 진행합니다.

여기

아마 가장 간단한 예입니다. 당신이이 개 삼각형 6 개 정점

-1, -1, 
    1, -1, 
    -1, 1, 

    -1, 1, 
    1, -1, 
    -1, -1, 
로 만든 쿼드 있다고 가정

또한 3 색

1, 0, 0, 
    0, 1, 0, 
    0, 0, 1, 

당신은 인스턴스에 한 색상을 사용하는 당신이 그것을 말해 색상은이

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 
const size = 2; // 2 floats per iteration 
const type = gl.FLOAT; 
const normalize = false; 
const stride = 0; // let WebGL compute the stride based on size and type 
const offset = 0; 
gl.vertexAttribPointer(posLocation, size, type, normalize, stride, offset); 

같은 쿼드 위치를 읽을 WebGL이 말의 버퍼를 가지고

gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 
const size = 3; // 2 floats per iteration 
const type = gl.FLOAT; 
const normalize = false; 
const stride = 0; // let WebGL compute the stride based on size and type 
const offset = 0; 
gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset); 
gl.vertexAttribDivisor(colorLocation, 1); 

gl.drawArraysInstanced와 같이 전화하면

버텍스 쉐이더를 3 * 6 번 호출 할 것입니다.당신이

attribute vec2 position; 
attribute vec3 color; 

했다 가정하면 각각의 반복에 대한 위치 및 색상의 값은 gl_VertexIDgl_InstanceID는 WebGL2에서만 사용할 수 있다는

iteration | position | color | gl_InstanceID | gl_VertexID 
----------+----------+--------+---------------+------------ 
    0  | -1, -1, | 1,0,0 |  0  | 0 
    1  | 1, -1, | 1,0,0 |  0  | 1 
    2  | -1, 1, | 1,0,0 |  0  | 2 
    3  | -1, 1, | 1,0,0 |  0  | 3 
    4  | 1, -1, | 1,0,0 |  0  | 4 
    5  | -1, -1, | 1,0,0 |  0  | 5 
    6  | -1, -1, | 0,1,0 |  1  | 0 
    7  | 1, -1, | 0,1,0 |  1  | 1 
    8  | -1, 1, | 0,1,0 |  1  | 2 
    9  | -1, 1, | 0,1,0 |  1  | 3 
    10  | 1, -1, | 0,1,0 |  1  | 4 
    11  | -1, -1, | 0,1,0 |  1  | 5 
    12  | -1, -1, | 0,0,1 |  2  | 0 
    13  | 1, -1, | 0,0,1 |  2  | 1 
    14  | -1, 1, | 0,0,1 |  2  | 2 
    15  | -1, 1, | 0,0,1 |  2  | 3 
    16  | 1, -1, | 0,0,1 |  2  | 4 
    17  | -1, -1, | 0,0,1 |  2  | 5 

참고가 될 것입니다.

+0

실례합니다. 'gl.vertexAttribDivisor'는 webgl2에있는 것이 아닌가? 그것에 대해 읽었습니다.'divisor 일반 속성의 업데이트 사이에 전달되는 인스턴스 수를 지정하는 GLuint입니다 .' 둘 이상일 경우 어떻게됩니까? – MHA15

+1

'gl.vertexAttribDivisor'는 WebGL1의 ['ANGLE_instanced_arrays' 확장 기능 (https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/)의 일부입니다. 1보다 큰 제수를 지정하면 N 인스턴스마다 한 번 해당 속성에 대한 다음 데이터로 진행합니다. 예를 들어, 위의 표에서 2로 설정하면 처음 12 번의 반복 (첫 번째 2 개의 인스턴스)에 대해 색상이 읽히고 마지막 6 번의 반복에 대한 녹색 (마지막 인스턴스) – gman

1

Instancing은 같은 메시에 대해 많은 양의 draw call (glDrawArrays 등)을 저장해야합니다.

그러나 버텍스 쉐이더는 여전히 각 버텍스와 각 인스턴스에 대해 개별적으로 실행됩니다. 일반적으로 각 인스턴스마다 다른 값을 반환합니다.

The OpenGL wiki explains this clearly

는 :

아이디어는 정점 셰이더는 렌더링 된 메쉬의 각 인스턴스가 하나의 수에 따라 어디로 결정에 대한 몇 가지 내부 메커니즘을 가지고 있다는 것입니다. 아마도 버퍼 텍스쳐 (Buffer Texture) 또는 유니폼 버퍼 객체 (Uniform Buffer Object)에 저장된 테이블을 가지고 있으며, 현재 정점의 인스턴스 번호로 인덱싱하여 필요한 인스턴스 당 데이터를 얻습니다. 아마도 특정 속성에 대한 속성 제수를 사용하며, 이는 각 인스턴스마다 다른 값을 제공합니다. 또는 인스턴스 번호를 기반으로 인스턴스의 위치를 ​​계산하기위한 간단한 알고리즘을 가지고있을 수도 있습니다.

+1

내가 원격으로 전혀 알아 내지 못했지만, 그게 내 것이 야. – gman