Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.



Published on

A brief overview of gpu instancing.

Published in: Technology, Art & Photos
  • Quite interesting presentation, congratulations!
    Are you sure you want to  Yes  No
    Your message goes here


  1. 1. OpenGL Instancing Alessandro Rigazzi Data Analysis and Visualization Group May 27, 2008
  2. 2. Instancing <ul><li>Basically: technique to render multiple instances of the same object with a single draw call </li></ul><ul><li>Works in vertex shader , with vertex buffers only </li></ul><ul><li>Two ways to use it: </li></ul><ul><ul><li>DrawElements InstancedEXT </li></ul></ul><ul><ul><li>DrawArrays InstancedEXT </li></ul></ul><ul><li>Each instance has an ID which can be used by the vertex shader to apply transforms </li></ul>
  3. 3. New Call <ul><li>Instanced Call: </li></ul><ul><ul><li>DrawElements InstancedEXT (enum mode, </li></ul></ul><ul><ul><li> sizei count, </li></ul></ul><ul><ul><li> enum type, </li></ul></ul><ul><ul><li> const void *indices, </li></ul></ul><ul><ul><li> sizei primcount ) </li></ul></ul><ul><li>Normal OpenGL call: </li></ul><ul><ul><ul><li>for (int i = 0; i < primcount; i++) </li></ul></ul></ul><ul><ul><ul><li>{ </li></ul></ul></ul><ul><ul><ul><li>instanceID = i; </li></ul></ul></ul><ul><ul><ul><li>DrawElements(mode, count, type, indices, i); </li></ul></ul></ul><ul><ul><ul><li>} </li></ul></ul></ul>
  4. 4. What is different and what is not <ul><li>Forced to use VBO’s  faster than passing geometry at each call, but obtainable passing all the geometry to the VBO (not feasible for large scenes) or as a texture </li></ul><ul><li>Lower memory usage and faster loading: pass geometry of one object and transforms of its instances, without having copies in memory </li></ul><ul><li>Simpler C++ code, not difficult GLSL shader </li></ul>
  5. 5. Test application
  6. 6. Performances <ul><li>Rendering of an instanced sphere (8200 tri) on a GeForce 8800 Ultra with 768MB RAM </li></ul>spheres triangles fps (full) fps (wireframe) 16 125k 399 120 32 250k 284 63.1 64 500k 167 32.5 128 1M 91.6 16.7 256 2.1M 48.2 8.4 512 4.2M 24.2 4.2 1024 8.4M 12 2.1 2048 16.8M 5.8 1
  7. 7. Extensions <ul><li>Instanced draw is in the EXT_draw_instanced </li></ul><ul><ul><li>Requires GL_EXT_gpu_shader4 extension </li></ul></ul><ul><ul><li>Present on NVidia G8x graphic cards and later </li></ul></ul><ul><li>To pass parameters for the instances: </li></ul><ul><ul><li>Textures </li></ul></ul><ul><ul><li>Uniform buffer arrays  GL_EXT_bindable_uniform </li></ul></ul>
  8. 8. Code snippet: C++ initialization <ul><li>static GLuint vbHandle; </li></ul><ul><li>static GLuint ibHandle; </li></ul><ul><li>// arrays containing geometry information, to fill as needed </li></ul><ul><li>float* vertexAndNormalPtr = new float[vertexCount + normalCount]; </li></ul><ul><li>float* centrePtr = new float[instanceCount]; </li></ul><ul><li>int* indexPtr = new int[indexCount]; </li></ul><ul><li>// vertex buffer initialization, we put 3d vertices and normals </li></ul><ul><li>glGenBuffersARB(1, &vbHandle); </li></ul><ul><li>glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbHandle); </li></ul><ul><li>glBufferDataARB(GL_ARRAY_BUFFER_ARB, 3*(vertexCount+normalCount)*sizeof(float), vertexAndNormalPtr, GL_STATIC_DRAW_ARB); </li></ul><ul><li>// index buffer </li></ul><ul><li>glGenBuffersARB(1, &ibHandle); </li></ul><ul><li>glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ibHandle); </li></ul><ul><li>glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, indexCount*sizeof(int), indexPtr, GL_STATIC_DRAW_ARB); </li></ul><ul><li>// create uniform buffer to store centres, ‘program’ is our compiled shader </li></ul><ul><li>GLint ulocation = glGetUniformLocation(program, &quot;centres&quot;); </li></ul><ul><li>GLint usize = glGetUniformBufferSizeEXT(program, ulocation); </li></ul><ul><li>GLuint ubuffer; </li></ul><ul><li>glGenBuffers(1, &ubuffer); </li></ul><ul><li>glBindBuffer(GL_UNIFORM_BUFFER_EXT, ubuffer); </li></ul><ul><li>glBufferData(GL_UNIFORM_BUFFER_EXT, usize, centrePtr, GL_STATIC_READ); </li></ul><ul><li>glUniformBufferEXT(program, ulocation, ubuffer); </li></ul>
  9. 9. Code snippet: C++ instanced draw call <ul><li>// Attach shaders </li></ul><ul><li>glUseProgram(program); </li></ul><ul><li>// Set GL state to draw indexed elements </li></ul><ul><li>glEnableClientState(GL_VERTEX_ARRAY); </li></ul><ul><li>glEnableClientState(GL_NORMAL_ARRAY); </li></ul><ul><li>glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbHandle); </li></ul><ul><li>glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ibHandle); </li></ul><ul><li>glVertexPointer(3, GL_FLOAT, 0, 0); </li></ul><ul><li>glNormalPointer(GL_FLOAT, 0, (void*)(3 * vertexCount * sizeof(float))); </li></ul><ul><li>glDrawElementsInstancedEXT (GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0, instanceCount ); </li></ul><ul><li>// Reset state </li></ul><ul><li>glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); </li></ul><ul><li>glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0); </li></ul><ul><li>glDisableClientState(GL_VERTEX_ARRAY); </li></ul><ul><li>glDisableClientState(GL_NORMAL_ARRAY); </li></ul><ul><li>// Detach shaders </li></ul><ul><li>glUseProgram(0); </li></ul>
  10. 10. Code snippet: GLSL shaders <ul><li>Vertex shader </li></ul><ul><li>#version 120 </li></ul><ul><li>#extension GL_EXT_bindable_uniform : enable </li></ul><ul><li>#extension GL_EXT_gpu_shader4 : enable </li></ul><ul><li>bindable uniform vec4 centres[1000]; </li></ul><ul><li>varying vec3 v_Normal; </li></ul><ul><li>void main(void) </li></ul><ul><li>{ </li></ul><ul><li>vec3 centre = centres[ gl_InstanceID ].xyz; </li></ul><ul><li>vec3 pos = gl_Vertex + centre; </li></ul><ul><li>v_Normal = gl_NormalMatrix * gl_Normal; </li></ul><ul><li>gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1.0); </li></ul><ul><li>} </li></ul><ul><li>Fragment shader: usual shader with lighting functions </li></ul>