원하는 점은 webgl의 draw 호출에서 정점 셰이더가 몇 번 호출되는지 이해하는 방법입니다. 실제로 인스턴스화하는 것이 무엇인지 알고 싶기 때문에 각 인스턴스에 대해 모든 공유 꼭지점을 호출합니까? 그래서 그것은 너무 많은 시간을 버텍스 쉐이더라고 부를 것입니다.webgl에서 인스턴스링을 수행하는 작업
답변
인스 턴싱은 인스턴스 당 정점 셰이더를 하나씩 호출합니다. 차이점은 하나 이상의 속성을 선택하여 정점 당 한 번이 아닌 인스턴스 당 한 번만 진행할 수 있다는 것입니다.
일반적으로 각 속성은 각 정점에 대해 stride
바이트를 전달합니다. stride
은 gl.vertexAttribPointer
의 마지막 인수에서 두 번째입니다. stride
가 0
경우 다음 size
및 type
(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_VertexID
및 gl_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
참고가 될 것입니다.
Instancing은 같은 메시에 대해 많은 양의 draw call (glDrawArrays
등)을 저장해야합니다.
그러나 버텍스 쉐이더는 여전히 각 버텍스와 각 인스턴스에 대해 개별적으로 실행됩니다. 일반적으로 각 인스턴스마다 다른 값을 반환합니다.
The OpenGL wiki explains this clearly
는 :아이디어는 정점 셰이더는 렌더링 된 메쉬의 각 인스턴스가 하나의 수에 따라 어디로 결정에 대한 몇 가지 내부 메커니즘을 가지고 있다는 것입니다. 아마도 버퍼 텍스쳐 (Buffer Texture) 또는 유니폼 버퍼 객체 (Uniform Buffer Object)에 저장된 테이블을 가지고 있으며, 현재 정점의 인스턴스 번호로 인덱싱하여 필요한 인스턴스 당 데이터를 얻습니다. 아마도 특정 속성에 대한 속성 제수를 사용하며, 이는 각 인스턴스마다 다른 값을 제공합니다. 또는 인스턴스 번호를 기반으로 인스턴스의 위치를 계산하기위한 간단한 알고리즘을 가지고있을 수도 있습니다.
내가 원격으로 전혀 알아 내지 못했지만, 그게 내 것이 야. – gman
실례합니다. 'gl.vertexAttribDivisor'는 webgl2에있는 것이 아닌가? 그것에 대해 읽었습니다.'divisor 일반 속성의 업데이트 사이에 전달되는 인스턴스 수를 지정하는 GLuint입니다 .' 둘 이상일 경우 어떻게됩니까? – MHA15
'gl.vertexAttribDivisor'는 WebGL1의 ['ANGLE_instanced_arrays' 확장 기능 (https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/)의 일부입니다. 1보다 큰 제수를 지정하면 N 인스턴스마다 한 번 해당 속성에 대한 다음 데이터로 진행합니다. 예를 들어, 위의 표에서 2로 설정하면 처음 12 번의 반복 (첫 번째 2 개의 인스턴스)에 대해 색상이 읽히고 마지막 6 번의 반복에 대한 녹색 (마지막 인스턴스) – gman