LearnOpenGL

Translation in progress of learnopengl.com.
git clone https://git.mtkn.jp/LearnOpenGL
Log | Files | Refs

Instancing.html (37655B)


      1 <!DOCTYPE html>
      2 <html lang="ja"> 
      3 <head>
      4     <meta charset="utf-8"/>
      5     <title>LearnOpenGL</title>
      6     <link rel="shortcut icon" type="image/ico" href="/favicon.ico"  />
      7 	<link rel="stylesheet" href="../static/style.css" />
      8 	<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"> </script>
      9 	<script src="/static/functions.js"></script>
     10 </head>
     11 <body>
     12 	<nav>
     13 <ol>
     14 	<li id="Introduction">
     15 		<a href="https://learnopengl.com/Introduction">はじめに</a>
     16 	</li>
     17 	<li id="Getting-started">
     18 		<span class="closed">入門</span>
     19 		<ol>
     20 			<li id="Getting-started/OpenGL">
     21 				<a href="https://learnopengl.com/Getting-started/OpenGL">OpenGL </a>
     22 			</li>
     23 			<li id="Getting-started/Creating-a-window">
     24 				<a href="https://learnopengl.com/Getting-started/Creating-a-window">ウィンドウの作成</a>
     25 			</li>
     26 			<li id="Getting-started/Hello-Window">
     27 				<a href="https://learnopengl.com/Getting-started/Hello-Window">最初のウィンドウ</a>
     28 			</li>
     29 			<li id="Getting-started/Hello-Triangle">
     30 				<a href="https://learnopengl.com/Getting-started/Hello-Triangle">最初の三角形</a>
     31 			</li>
     32 			<li id="Getting-started/Shaders">
     33 				<a href="https://learnopengl.com/Getting-started/Shaders">シェーダー</a>
     34 			</li>
     35 			<li id="Getting-started/Textures">
     36 				<a href="https://learnopengl.com/Getting-started/Textures">テクスチャ</a>
     37 			</li>
     38 			<li id="Getting-started/Transformations">
     39 				<a href="https://learnopengl.com/Getting-started/Transformations">座標変換</a>
     40 			</li>
     41 			<li id="Getting-started/Coordinate-Systems">
     42 				<a href="https://learnopengl.com/Getting-started/Coordinate-Systems">座標系</a>
     43 			</li>
     44 			<li id="Getting-started/Camera">
     45 				<a href="https://learnopengl.com/Getting-started/Camera">カメラ</a>
     46 			</li>
     47 			<li id="Getting-started/Review">
     48 				<a href="https://learnopengl.com/Getting-started/Review">まとめ</a>
     49 			</li>
     50 		</ol>
     51 	</li>
     52 	<li id="Lighting">
     53 		<span class="closed">Lighting </span>
     54 		<ol>
     55 			<li id="Lighting/Colors">
     56 				<a href="https://learnopengl.com/Lighting/Colors">Colors </a>
     57 			</li>
     58 			<li id="Lighting/Basic-Lighting">
     59 				<a href="https://learnopengl.com/Lighting/Basic-Lighting">Basic Lighting </a>
     60 			</li>
     61 			<li id="Lighting/Materials">
     62 				<a href="https://learnopengl.com/Lighting/Materials">Materials </a>
     63 			</li>
     64 			<li id="Lighting/Lighting-maps">
     65 				<a href="https://learnopengl.com/Lighting/Lighting-maps">Lighting maps </a>
     66 			</li>
     67 			<li id="Lighting/Light-casters">
     68 				<a href="https://learnopengl.com/Lighting/Light-casters">Light casters </a>
     69 			</li>
     70 			<li id="Lighting/Multiple-lights">
     71 				<a href="https://learnopengl.com/Lighting/Multiple-lights">Multiple lights </a>
     72 			</li>
     73 			<li id="Lighting/Review">
     74 				<a href="https://learnopengl.com/Lighting/Review">Review </a>
     75 			</li>
     76 		</ol>
     77 	</li>
     78 	<li id="Model-Loading">
     79 		<span class="closed">Model Loading </span>
     80 		<ol>
     81 			<li id="Model-Loading/Assimp">
     82 				<a href="https://learnopengl.com/Model-Loading/Assimp">Assimp </a>
     83 			</li>
     84 			<li id="Model-Loading/Mesh">
     85 				<a href="https://learnopengl.com/Model-Loading/Mesh">Mesh </a>
     86 			</li>
     87 			<li id="Model-Loading/Model">
     88 				<a href="https://learnopengl.com/Model-Loading/Model">Model </a>
     89 			</li>
     90 		</ol>
     91 	</li>
     92 	<li id="Advanced-OpenGL">
     93 		<span class="closed">Advanced OpenGL </span>
     94 		<ol>
     95 			<li id="Advanced-OpenGL/Depth-testing">
     96 				<a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing">Depth testing </a>
     97 			</li>
     98 			<li id="Advanced-OpenGL/Stencil-testing">
     99 				<a href="https://learnopengl.com/Advanced-OpenGL/Stencil-testing">Stencil testing </a>
    100 			</li>
    101 			<li id="Advanced-OpenGL/Blending">
    102 				<a href="https://learnopengl.com/Advanced-OpenGL/Blending">Blending </a>
    103 			</li>
    104 			<li id="Advanced-OpenGL/Face-culling">
    105 				<a href="https://learnopengl.cm/Advanced-OpenGL/Face-culling">Face culling </a>
    106 			</li>
    107 			<li id="Advanced-OpenGL/Framebuffers">
    108 				<a href="https://learnopengl.com/Advanced-OpenGL/Framebuffers">Framebuffers </a>
    109 			</li>
    110 			<li id="Advanced-OpenGL/Cubemaps">
    111 				<a href="https://learnopengl.com/Advanced-OpenGL/Cubemaps">Cubemaps </a>
    112 			</li>
    113 			<li id="Advanced-OpenGL/Advanced-Data">
    114 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-Data">Advanced Data </a>
    115 			</li>
    116 			<li id="Advanced-OpenGL/Advanced-GLSL">
    117 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL">Advanced GLSL </a>
    118 			</li>
    119 			<li id="Advanced-OpenGL/Geometry-Shader">
    120 				<a href="https://learnopengl.com/Advanced-OpenGL/Geometry-Shader">Geometry Shader </a>
    121 			</li>
    122 			<li id="Advanced-OpenGL/Instancing">
    123 				<a href="https://learnopengl.com/Advanced-OpenGL/Instancing">Instancing </a>
    124 			</li>
    125 			<li id="Advanced-OpenGL/Anti-Aliasing">
    126 				<a href="https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing">Anti Aliasing </a>
    127 			</li>
    128 		</ol>
    129 	</li>
    130 	<li id="Advanced-Lighting">
    131 		<span class="closed">Advanced Lighting </span>
    132 		<ol>
    133 			<li id="Advanced-Lighting/Advanced-Lighting">
    134 				<a href="https://learnopengl.com/Advanced-Lighting/Advanced-Lighting">Advanced Lighting </a>
    135 			</li>
    136 			<li id="Advanced-Lighting/Gamma-Correction">
    137 				<a href="https://learnopengl.com/Advanced-Lighting/Gamma-Correction">Gamma Correction </a>
    138 			</li>
    139 			<li id="Advanced-Lighting/Shadows">
    140 				<span class="closed">Shadows </span>
    141 				<ol>
    142 					<li id="Advanced-Lighting/Shadows/Shadow-Mapping">
    143 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping">Shadow Mapping </a>
    144 					</li>
    145 					<li id="Advanced-Lighting/Shadows/Point-Shadows">
    146 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows">Point Shadows </a>
    147 					</li>
    148 				</ol>
    149 			</li>
    150 			<li id="Advanced-Lighting/Normal-Mapping">
    151 				<a href="https://learnopengl.com/Advanced-Lighting/Normal-Mapping">Normal Mapping </a>
    152 			</li>
    153 			<li id="Advanced-Lighting/Parallax-Mapping">
    154 				<a href="https://learnopengl.com/Advanced-Lighting/Parallax-Mapping">Parallax Mapping </a>
    155 			</li>
    156 			<li id="Advanced-Lighting/HDR">
    157 				<a href="https://learnopengl.com/Advanced-Lighting/HDR">HDR </a>
    158 			</li>
    159 			<li id="Advanced-Lighting/Bloom">
    160 				<a href="https://learnopengl.com/Advanced-Lighting/Bloom">Bloom </a>
    161 			</li>
    162 			<li id="Advanced-Lighting/Deferred-Shading">
    163 				<a href="https://learnopengl.com/Advanced-Lighting/Deferred-Shading">Deferred Shading </a>
    164 			</li>
    165 			<li id="Advanced-Lighting/SSAO">
    166 				<a href="https://learnopengl.com/Advanced-Lighting/SSAO">SSAO </a>
    167 			</li>
    168 		</ol>
    169 	</li>
    170 	<li id="PBR">
    171 		<span class="closed">PBR </span>
    172 		<ol>
    173 			<li id="PBR/Theory">
    174 				<a href="https://learnopengl.com/PBR/Theory">Theory </a>
    175 			</li>
    176 			<li id="PBR/Lighting">
    177 				<a href="https://learnopengl.com/PBR/Lighting">Lighting </a>
    178 			</li>
    179 			<li id="PBR/IBL">
    180 				<span class="closed">IBL </span>
    181 				<ol>
    182 					<li id="PBR/IBL/Diffuse-irradiance">
    183 						<a href="https://learnopengl.com/PBR/IBL/Diffuse-irradiance">Diffuse irradiance </a>
    184 					</li>
    185 					<li id="PBR/IBL/Specular-IBL">
    186 						<a href="https://learnopengl.com/PBR/IBL/Specular-IBL">Specular IBL </a>
    187 					</li>
    188 				</ol>
    189 			</li>
    190 		</ol>
    191 	</li>
    192 	<li id="In-Practice">
    193 		<span class="closed">In Practice </span>
    194 		<ol>
    195 			<li id="In-Practice/Debugging">
    196 				<a href="https://learnopengl.com/In-Practice/Debugging">Debugging </a>
    197 			</li>
    198 			<li id="In-Practice/Text-Rendering">
    199 				<a href="https://learnopengl.com/In-Practice/Text-Rendering">Text Rendering </a>
    200 			</li>
    201 			<li id="In-Practice/2D-Game">
    202 				<span class="closed">2D Game </span>
    203 				<ol>
    204 					<li id="In-Practice/2D-Game/Breakout">
    205 						<a href="https://learnopengl.com/In-Practice/2D-Game/Breakout">Breakout </a>
    206 					</li>
    207 					<li id="In-Practice/2D-Game/Setting-up">
    208 						<a href="https://learnopengl.com/In-Practice/2D-Game/Setting-up">Setting up </a>
    209 					</li>
    210 					<li id="In-Practice/2D-Game/Rendering-Sprites">
    211 						<a href="https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites">Rendering Sprites </a>
    212 					</li>
    213 					<li id="In-Practice/2D-Game/Levels">
    214 						<a href="https://learnopengl.com/In-Practice/2D-Game/Levels">Levels </a>
    215 					</li>
    216 					<li id="In-Practice/2D-Game/Collisions">
    217 						<span class="closed">Collisions </span>
    218 						<ol>
    219 							<li id="In-Practice/2D-Game/Collisions/Ball">
    220 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Ball">Ball </a>
    221 							</li>
    222 							<li id="In-Practice/2D-Game/Collisions/Collision-detection">
    223 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-detection">Collision detection </a>
    224 							</li>
    225 							<li id="In-Practice/2D-Game/Collisions/Collision-resolution">
    226 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-resolution">Collision resolution </a>
    227 							</li>
    228 						</ol>
    229 					</li>
    230 					<li id="In-Practice/2D-Game/Particles">
    231 						<a href="https://learnopengl.com/In-Practice/2D-Game/Particles">Particles </a>
    232 					</li>
    233 					<li id="In-Practice/2D-Game/Postprocessing">
    234 						<a href="https://learnopengl.com/In-Practice/2D-Game/Postprocessing">Postprocessing </a>
    235 					</li>
    236 					<li id="In-Practice/2D-Game/Powerups">
    237 						<a href="https://learnopengl.com/In-Practice/2D-Game/Powerups">Powerups </a>
    238 					</li>
    239 					<li id="In-Practice/2D-Game/Audio">
    240 						<a href="https://learnopengl.com/In-Practice/2D-Game/Audio">Audio </a>
    241 					</li>
    242 					<li id="In-Practice/2D-Game/Render-text">
    243 						<a href="https://learnopengl.com/In-Practice/2D-Game/Render-text">Render text </a>
    244 					</li>
    245 					<li id="In-Practice/2D-Game/Final-thoughts">
    246 						<a href="https://learnopengl.com/In-Practice/2D-Game/Final-thoughts">Final thoughts </a>
    247 					</li>
    248 				</ol>
    249 			</li>
    250 		</ol>
    251 	</li>
    252 	<li id="Guest-Articles">
    253 		<span class="closed">Guest Articles </span>
    254 		<ol>
    255 			<li id="Guest-Articles/How-to-publish">
    256 				<a href="https://learnopengl.com/Guest-Articles/How-to-publish">How to publish </a>
    257 			</li>
    258 			<li id="Guest-Articles/2020">
    259 				<span class="closed">2020 </span>
    260 				<ol>
    261 					<li id="Guest-Articles/2020/OIT">
    262 						<span class="closed">OIT </span>
    263 						<ol>
    264 							<li id="Guest-Articles/2020/OIT/Introduction">
    265 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Introduction">Introduction </a>
    266 							</li>
    267 							<li id="Guest-Articles/2020/OIT/Weighted-Blended">
    268 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Weighted-Blended">Weighted Blended </a>
    269 							</li>
    270 						</ol>
    271 					</li>
    272 					<li id="Guest-Articles/2020/Skeletal-Animation">
    273 						<a href="https://learnopengl.com/Guest-Articles/2020/Skeletal-Animation">Skeletal Animation </a>
    274 					</li>
    275 				</ol>
    276 			</li>
    277 			<li id="Guest-Articles/2021">
    278 				<span class="closed">2021 </span>
    279 				<ol>
    280 					<li id="Guest-Articles/2021/CSM">
    281 						<a href="https://learnopengl.com/Guest-Articles/2021/CSM">CSM </a>
    282 					</li>
    283 					<li id="Guest-Articles/2021/Scene">
    284 						<span class="closed">Scene </span>
    285 						<ol>
    286 							<li id="Guest-Articles/2021/Scene/Scene-Graph">
    287 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Scene-Graph">Scene Graph </a>
    288 							</li>
    289 							<li id="Guest-Articles/2021/Scene/Frustum-Culling">
    290 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling">Frustum Culling </a>
    291 							</li>
    292 						</ol>
    293 					</li>
    294 					<li id="Guest-Articles/2021/Tessellation">
    295 						<span class="closed">Tessellation </span>
    296 						<ol>
    297 							<li id="Guest-Articles/2021/Tessellation/Height-map">
    298 								<a href="https://learnopengl.com/Guest-Articles/2021/Tessellation/Height-map">Height map </a>
    299 							</li>
    300 						</ol>
    301 					</li>
    302 				</ol>
    303 			</li>
    304 		</ol>
    305 	</li>
    306 	<li id="Code-repository">
    307 		<a href="https://learnopengl.com/Code-repository">Code repository </a>
    308 	</li>
    309 	<li id="Translations">
    310 		<a href="https://learnopengl.com/Translations">Translations </a>
    311 	</li>
    312 	<li id="About">
    313 		<a href="https://learnopengl.com/About">About </a>
    314 	</li>
    315 </ol>
    316 	</nav>
    317 	<main>
    318     <div id="content">
    319     <h1 id="content-title">Instancing</h1>
    320 <h1 id="content-url" style='display:none;'>Advanced-OpenGL/Instancing</h1>
    321 <p>
    322   Say you have a scene where you're drawing a lot of models where most of these models contain the same set of vertex data, but with different world transformations. Think of a scene filled with grass leaves: each grass leave is a small model that consists of only a few triangles. You'll probably want to draw quite a few of them and your scene may end up with thousands or maybe tens of thousands of grass leaves that you need to render each frame. Because each leaf is only a few triangles, the leaf is rendered almost instantly. However, the thousands of render calls you'll have to make will drastically reduce performance.
    323 </p>
    324 
    325 <p>
    326   If we were to actually render such a large amount of objects it will look a bit like this in code:
    327 </p>
    328 
    329 <pre><code>
    330 for(unsigned int i = 0; i &lt; amount_of_models_to_draw; i++)
    331 {
    332     DoSomePreparations(); // bind VAO, bind textures, set uniforms etc.
    333     <function id='1'>glDrawArrays</function>(GL_TRIANGLES, 0, amount_of_vertices);
    334 }
    335 </code></pre>
    336 
    337 <p>
    338   When drawing many <def>instances</def> of your model like this you'll quickly reach a performance bottleneck because of the many draw calls. Compared to rendering the actual vertices, telling the GPU to render your vertex data with functions like <fun><function id='1'>glDrawArrays</function></fun> or <fun><function id='2'>glDrawElements</function></fun> eats up quite some performance since OpenGL must make necessary preparations before it can draw your vertex data (like telling the GPU which buffer to read data from, where to find vertex attributes and all this over the relatively slow CPU to GPU bus). So even though rendering your vertices is super fast, giving your GPU the commands to render them isn't.
    339 </p>
    340 
    341 <p>
    342   It would be much more convenient if we could send data over to the GPU once, and then tell OpenGL to draw multiple objects using this data with a single drawing call. Enter <def>instancing</def>.
    343 </p>
    344 
    345 <p>
    346   Instancing is a technique where we draw many (equal mesh data) objects at once with a single render call, saving us all the CPU -> GPU communications each time we need to render an object. To render using instancing all we need to do is change the render calls <fun><function id='1'>glDrawArrays</function></fun> and <fun><function id='2'>glDrawElements</function></fun> to <fun><function id='98'><function id='1'>glDrawArrays</function>Instanced</function></fun> and <fun><function id='99'><function id='2'>glDrawElements</function>Instanced</function></fun> respectively. These <em>instanced</em> versions of the classic rendering functions take an extra parameter called the <def>instance count</def> that sets the number of instances we want to render. We sent all the required data to the GPU once, and then tell the GPU how it should draw all these instances with a single call. The GPU then renders all these instances without having to continually communicate with the CPU.
    347 </p>
    348 
    349 <p>
    350   By itself this function is a bit useless. Rendering the same object a thousand times is of no use to us since each of the rendered objects is rendered exactly the same and thus also at the same location; we would only see one object! For this reason GLSL added another built-in variable in the vertex shader called <var>gl_InstanceID</var>. 
    351 </p>
    352 
    353 <p>
    354   When drawing with one of the instanced rendering calls, <var>gl_InstanceID</var> is incremented for each instance being rendered starting from <code>0</code>. If we were to render the 43th instance for example, <var>gl_InstanceID</var> would have the value <code>42</code> in the vertex shader. Having a unique value per instance means we could now for example index into a large array of position values to position each instance at a different location in the world.
    355 </p>
    356 
    357 <p>
    358   To get a feel for instanced drawing we're going to demonstrate a simple example that renders a hundred 2D quads in normalized device coordinates with just one render call. We accomplish this by uniquely positioning each instanced quad by indexing a uniform array of <code>100</code> offset vectors. The result is a neatly organized grid of quads that fill the entire window:
    359 </p>
    360 
    361 <img src="/img/advanced/instancing_quads.png" class="clean" alt="100 Quads drawn via OpenGL instancing."/>
    362 
    363 <p>
    364   Each quad consists of 2 triangles with a total of 6 vertices. Each vertex contains a 2D NDC position vector and a color vector. Below is the vertex data used for this example - the triangles are small enough to properly fit the screen when there's a 100 of them:
    365 </p>
    366 
    367 <pre><code>
    368 float quadVertices[] = {
    369     // positions     // colors
    370     -0.05f,  0.05f,  1.0f, 0.0f, 0.0f,
    371      0.05f, -0.05f,  0.0f, 1.0f, 0.0f,
    372     -0.05f, -0.05f,  0.0f, 0.0f, 1.0f,
    373 
    374     -0.05f,  0.05f,  1.0f, 0.0f, 0.0f,
    375      0.05f, -0.05f,  0.0f, 1.0f, 0.0f,   
    376      0.05f,  0.05f,  0.0f, 1.0f, 1.0f		    		
    377 };  
    378 </code></pre>
    379 
    380 <p>
    381   The quads are colored in the fragment shader that receives a color vector from the vertex shader and sets it as its output:
    382 </p>
    383 
    384 <pre><code>
    385 #version 330 core
    386 out vec4 FragColor;
    387   
    388 in vec3 fColor;
    389 
    390 void main()
    391 {
    392     FragColor = vec4(fColor, 1.0);
    393 }
    394 </code></pre>
    395 
    396 <p>
    397   Nothing new so far, but at the vertex shader it's starting to get interesting:
    398 </p>
    399 
    400 <pre><code>
    401 #version 330 core
    402 layout (location = 0) in vec2 aPos;
    403 layout (location = 1) in vec3 aColor;
    404 
    405 out vec3 fColor;
    406 
    407 uniform vec2 offsets[100];
    408 
    409 void main()
    410 {
    411     vec2 offset = offsets[gl_InstanceID];
    412     gl_Position = vec4(aPos + offset, 0.0, 1.0);
    413     fColor = aColor;
    414 }  
    415 </code></pre>
    416 
    417 <p>
    418   Here we defined a uniform array called <var>offsets</var> that contain a total of <code>100</code> offset vectors. Within the vertex shader we retrieve an offset vector for each instance by indexing the <var>offsets</var> array using <var>gl_InstanceID</var>. If we now were to draw <code>100</code> quads with instanced drawing we'd get <code>100</code> quads located at different positions.
    419 </p>
    420 
    421 <p>
    422   We do need to actually set the offset positions that we calculate in a nested for-loop before we enter the render loop:
    423 </p>
    424 
    425 <pre><code>
    426 glm::vec2 translations[100];
    427 int index = 0;
    428 float offset = 0.1f;
    429 for(int y = -10; y &lt; 10; y += 2)
    430 {
    431     for(int x = -10; x &lt; 10; x += 2)
    432     {
    433         glm::vec2 translation;
    434         translation.x = (float)x / 10.0f + offset;
    435         translation.y = (float)y / 10.0f + offset;
    436         translations[index++] = translation;
    437     }
    438 }  
    439 </code></pre>
    440 
    441 <p>
    442   Here we create a set of <code>100</code> translation vectors that contains an offset vector for all positions in a 10x10 grid. In addition to generating the <var>translations</var> array, we'd also need to transfer the data to the vertex shader's uniform array:
    443 </p>
    444 
    445 <pre><code>
    446 shader.use();
    447 for(unsigned int i = 0; i &lt; 100; i++)
    448 {
    449     shader.setVec2(("offsets[" + std::to_string(i) + "]")), translations[i]);
    450 }  
    451 </code></pre>
    452 
    453 <p>
    454   Within this snippet of code we transform the for-loop counter <var>i</var> to a <fun>string</fun> to dynamically create a location string for querying the uniform location. For each item in the <var>offsets</var> uniform array we then set the corresponding translation vector.
    455 </p>
    456 
    457 <p>
    458   Now that all the preparations are finished we can start rendering the quads. To draw via instanced rendering we call <fun><function id='98'><function id='1'>glDrawArrays</function>Instanced</function></fun> or <fun><function id='99'><function id='2'>glDrawElements</function>Instanced</function></fun>. Since we're not using an element index buffer we're going to call the <fun><function id='1'>glDrawArrays</function></fun> version:
    459 </p>
    460 
    461 <pre class="cpp"><code>
    462 <function id='27'>glBindVertexArray</function>(quadVAO);
    463 <function id='98'><function id='1'>glDrawArrays</function>Instanced</function>(GL_TRIANGLES, 0, 6, 100);  
    464 </code></pre>
    465 
    466 <p>
    467   The parameters of <fun><function id='98'><function id='1'>glDrawArrays</function>Instanced</function></fun> are exactly the same as <fun><function id='1'>glDrawArrays</function></fun> except the last parameter that sets the number of instances we want to draw. Since we want to display <code>100</code> quads in a 10x10 grid we set it equal to <code>100</code>. Running the code should now give you the familiar image of <code>100</code> colorful quads.
    468 </p>
    469 
    470 <h2>Instanced arrays</h2>
    471 <p>
    472   While the previous implementation works fine for this specific use case, whenever we are rendering a lot more than <code>100</code> instances (which is quite common) we will eventually hit a <a href="https://www.khronos.org/opengl/wiki/GLSL_Uniform#Implementation_limits" target="_blank">limit</a> on the amount of uniform data we can send to the shaders. One alternative option is known as <def>instanced arrays</def>. Instanced arrays are defined as a vertex attribute (allowing us to store much more data) that are updated per instance instead of per vertex.
    473 </p>
    474 
    475 <p>
    476   With vertex attributes, at the start of each run of the vertex shader, the GPU will retrieve the next set of vertex attributes that belong to the current vertex. When defining a vertex attribute as an instanced array however, the vertex shader only updates the content of the vertex attribute per instance. This allows us to use the standard vertex attributes for data per vertex and use the instanced array for storing data that is unique per instance.
    477 </p>
    478 
    479 <p>
    480   To give you an example of an instanced array we're going to take the previous example and convert the offset uniform array to an instanced array. We'll have to update the vertex shader by adding another vertex attribute:
    481 </p>
    482 
    483 <pre><code>
    484 #version 330 core
    485 layout (location = 0) in vec2 aPos;
    486 layout (location = 1) in vec3 aColor;
    487 layout (location = 2) in vec2 aOffset;
    488 
    489 out vec3 fColor;
    490 
    491 void main()
    492 {
    493     gl_Position = vec4(aPos + aOffset, 0.0, 1.0);
    494     fColor = aColor;
    495 }  
    496 </code></pre>
    497 
    498 <p>
    499   We no longer use <var>gl_InstanceID</var> and can directly use the <var>offset</var> attribute  without first indexing into a large uniform array.
    500 </p>
    501 
    502 <p>
    503   Because an instanced array is a vertex attribute, just like the <var>position</var> and <var>color</var> variables, we need to store its content in a vertex buffer object and configure its attribute pointer. We're first going to store the <var>translations</var> array (from the previous section) in a new buffer object:
    504 </p>
    505 
    506 <pre><code>
    507 unsigned int instanceVBO;
    508 <function id='12'>glGenBuffers</function>(1, &instanceVBO);
    509 <function id='32'>glBindBuffer</function>(GL_ARRAY_BUFFER, instanceVBO);
    510 <function id='31'>glBufferData</function>(GL_ARRAY_BUFFER, sizeof(glm::vec2) * 100, &translations[0], GL_STATIC_DRAW);
    511 <function id='32'>glBindBuffer</function>(GL_ARRAY_BUFFER, 0); 
    512 </code></pre>
    513 
    514 <p>
    515   Then we also need to set its vertex attribute pointer and enable the vertex attribute:
    516 </p>
    517 
    518 <pre><code>
    519 <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(2);
    520 <function id='32'>glBindBuffer</function>(GL_ARRAY_BUFFER, instanceVBO);
    521 <function id='30'>glVertexAttribPointer</function>(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    522 <function id='32'>glBindBuffer</function>(GL_ARRAY_BUFFER, 0);	
    523 <function id='100'>glVertexAttribDivisor</function>(2, 1);  
    524 </code></pre>
    525 
    526 <p>
    527   What makes this code interesting is the last line where we call <fun><function id='100'>glVertexAttribDivisor</function></fun>. This function tells OpenGL <strong>when</strong> to update the content of a vertex attribute to the next element. Its first parameter is the vertex attribute in question and the second parameter the <def>attribute divisor</def>. By default, the attribute divisor is <code>0</code> which tells OpenGL to update the content of the vertex attribute each iteration of the vertex shader. By setting this attribute to <code>1</code> we're telling OpenGL that we want to update the content of the vertex attribute when we start to render a new instance. By setting it to <code>2</code> we'd update the content every 2 instances and so on. By setting the attribute divisor to <code>1</code> we're effectively telling OpenGL that the vertex attribute at attribute location <code>2</code> is an instanced array.
    528 </p>
    529 
    530 <p>
    531   If we now were to render the quads again with <fun><function id='98'><function id='1'>glDrawArrays</function>Instanced</function></fun> we'd get the following output:
    532 </p>
    533 
    534 <img src="/img/advanced/instancing_quads.png" class="clean" alt="Same image of OpenGL instanced quads, but this time using instanced arrays."/>
    535 
    536 <p>
    537   This is exactly the same as the previous example, but now with instanced arrays, which allows us to pass a lot more data (as much as memory allows us) to the vertex shader for instanced drawing.
    538 </p>
    539 
    540 <p>
    541   For fun we could slowly downscale each quad from top-right to bottom-left using <var>gl_InstanceID</var> again, because why not?
    542 </p>
    543 
    544 <pre><code>
    545 void main()
    546 {
    547     vec2 pos = aPos * (gl_InstanceID / 100.0);
    548     gl_Position = vec4(pos + aOffset, 0.0, 1.0);
    549     fColor = aColor;
    550 } 
    551 </code></pre>
    552 
    553 <p>
    554   The result is that the first instances of the quads are drawn extremely small and the further we're in the process of drawing the instances, the closer <var>gl_InstanceID</var> gets to <code>100</code> and thus the more the quads regain their original size. It's perfectly legal to use instanced arrays together with <var>gl_InstanceID</var> like this.
    555 </p>
    556 
    557 <img src="/img/advanced/instancing_quads_arrays.png" class="clean" alt="Image of instanced quads drawn in OpenGL using instanced arrays"/>
    558 
    559 <p>
    560   If you're still a bit unsure about how instanced rendering works or want to see how everything fits together you can find the full source code of the application <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/10.1.instancing_quads/instancing_quads.cpp" target="_blank">here</a>.
    561 </p>
    562 
    563 <p>
    564   While fun and all, these examples aren't really good examples of instancing. Yes, they do give you an easy overview of how instancing works, but instancing gets most of its power when drawing an enormous amount of similar objects. For that reason we're going to venture into space.
    565 </p>
    566 
    567 <h1>An asteroid field</h1>
    568 <p>
    569   Imagine a scene where we have one large planet that's at the center of a large asteroid ring. Such an asteroid ring could contain thousands or tens of thousands of rock formations and quickly becomes un-renderable on any decent graphics card. This scenario proves itself particularly useful for instanced rendering, since all the asteroids can be represented with a single model. Each single asteroid then gets its variation from a transformation matrix unique to each asteroid.
    570 </p>
    571 
    572 <p>
    573   To demonstrate the impact of instanced rendering we're first going to render a scene of asteroids hovering around a planet <em>without</em> instanced rendering. The scene will contain a large planet model that can be downloaded from <a href="/data/models/planet.zip" target="_blank">here</a> and a large set of asteroid rocks that we properly position around the planet. The asteroid rock model can be downloaded <a href="/data/models/rock.zip" target="_blank">here</a>.
    574 </p>
    575 
    576 <p>
    577   Within the code samples we load the models using the model loader we've previously defined in the <a href="https://learnopengl.com/Model-Loading/Assimp" target="_blank">model loading</a> chapters. 
    578 </p>
    579 
    580 <p>
    581   To achieve the effect we're looking for we'll be generating a model transformation matrix for each asteroid. The transformation matrix first translates the rock somewhere in the asteroid ring - then we'll add a small random displacement value to the offset to make the ring look more natural. From there we also apply a random scale and a random rotation. The result is a transformation matrix that translates each asteroid somewhere around the planet while also giving it a more natural and unique look compared to the other asteroids. 
    582 </p>
    583 
    584 <pre><code>
    585 unsigned int amount = 1000;
    586 glm::mat4 *modelMatrices;
    587 modelMatrices = new glm::mat4[amount];
    588 srand(<function id='47'>glfwGetTime</function>()); // initialize random seed	
    589 float radius = 50.0;
    590 float offset = 2.5f;
    591 for(unsigned int i = 0; i &lt; amount; i++)
    592 {
    593     glm::mat4 model = glm::mat4(1.0f);
    594     // 1. translation: displace along circle with 'radius' in range [-offset, offset]
    595     float angle = (float)i / (float)amount * 360.0f;
    596     float displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;
    597     float x = sin(angle) * radius + displacement;
    598     displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;
    599     float y = displacement * 0.4f; // keep height of field smaller compared to width of x and z
    600     displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset;
    601     float z = cos(angle) * radius + displacement;
    602     model = <function id='55'>glm::translate</function>(model, glm::vec3(x, y, z));
    603 
    604     // 2. scale: scale between 0.05 and 0.25f
    605     float scale = (rand() % 20) / 100.0f + 0.05;
    606     model = <function id='56'>glm::scale</function>(model, glm::vec3(scale));
    607 
    608     // 3. rotation: add random rotation around a (semi)randomly picked rotation axis vector
    609     float rotAngle = (rand() % 360);
    610     model = <function id='57'>glm::rotate</function>(model, rotAngle, glm::vec3(0.4f, 0.6f, 0.8f));
    611 
    612     // 4. now add to list of matrices
    613     modelMatrices[i] = model;
    614 }  
    615 </code></pre>
    616 
    617 <p>
    618   This piece of code may look a little daunting, but we basically transform the x and z position of the asteroid along a circle with a radius defined by <var>radius</var> and randomly displace each asteroid a little around the circle by <var>-offset</var> and <var>offset</var>. We give the <code>y</code> displacement less of an impact to create a more flat asteroid ring. Then we apply scale and rotation transformations and store the resulting transformation matrix in <var>modelMatrices</var> that is of size <var>amount</var>. Here we generate <code>1000</code> model matrices, one per asteroid.
    619 </p>
    620 
    621 <p>
    622   After loading the planet and rock models and compiling a set of shaders, the rendering code then looks a bit like this:
    623 </p>
    624 
    625 <pre><code>
    626 // draw planet
    627 shader.use();
    628 glm::mat4 model = glm::mat4(1.0f);
    629 model = <function id='55'>glm::translate</function>(model, glm::vec3(0.0f, -3.0f, 0.0f));
    630 model = <function id='56'>glm::scale</function>(model, glm::vec3(4.0f, 4.0f, 4.0f));
    631 shader.setMat4("model", model);
    632 planet.Draw(shader);
    633   
    634 // draw meteorites
    635 for(unsigned int i = 0; i &lt; amount; i++)
    636 {
    637     shader.setMat4("model", modelMatrices[i]);
    638     rock.Draw(shader);
    639 }  
    640 </code></pre>
    641 
    642 <p>
    643   First we draw the planet model, that we translate and scale a bit to accommodate the scene, and then we draw a number of rock models equal to the <var>amount</var> of transformations we generated previously.  Before we draw each rock however, we first set the corresponding model transformation matrix within the shader.
    644 </p>
    645 
    646 <p>
    647   The result is then a space-like scene where we can see a natural-looking asteroid ring around a planet:
    648 </p>
    649 
    650 <img src="/img/advanced/instancing_asteroids.png" class="clean" alt="Image of asteroid field drawn in OpenGL"/>
    651 
    652 <p>
    653   This scene contains a total of <code>1001</code> rendering calls per frame of which <code>1000</code> are of the rock model. You can find the source code for this scene <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/10.2.asteroids/asteroids.cpp" target="_blank">here</a>.
    654 </p>
    655 
    656 <p>
    657   As soon as we start to increase this number we will quickly notice that the scene stops running smoothly and the number of frames we're able to render per second reduces drastically. As soon as we set <var>amount</var> to something close to <code>2000</code> the scene already becomes so slow on our GPU that it becomes difficult to move around. 
    658 </p>
    659 
    660 <p>
    661   Let's now try to render the same scene, but this time with instanced rendering. We first need to adjust the vertex shader a little:
    662 </p>
    663 
    664 <pre><code>
    665 #version 330 core
    666 layout (location = 0) in vec3 aPos;
    667 layout (location = 2) in vec2 aTexCoords;
    668 layout (location = 3) in mat4 instanceMatrix;
    669 
    670 out vec2 TexCoords;
    671 
    672 uniform mat4 projection;
    673 uniform mat4 view;
    674 
    675 void main()
    676 {
    677     gl_Position = projection * view * instanceMatrix * vec4(aPos, 1.0); 
    678     TexCoords = aTexCoords;
    679 }
    680 </code></pre>
    681 
    682 <p>
    683   We're no longer using a model uniform variable, but instead declare a <fun>mat4</fun> as a vertex attribute so we can store an instanced array of transformation matrices. However, when we declare a datatype as a vertex attribute that is greater than a <fun>vec4</fun> things work a bit differently. The maximum amount of data allowed for a vertex attribute is equal to a <fun>vec4</fun>. Because a <fun>mat4</fun> is basically 4 <fun>vec4</fun>s, we have to reserve 4 vertex attributes for this specific matrix. Because we assigned it a location of <code>3</code>, the columns of the matrix will have vertex attribute locations of <code>3</code>, <code>4</code>, <code>5</code>, and <code>6</code>.
    684 </p>
    685 
    686 <p>
    687   We then have to set each of the attribute pointers of those <code>4</code> vertex attributes and configure them as instanced arrays:
    688 </p>
    689 
    690 <pre><code>
    691 // vertex buffer object
    692 unsigned int buffer;
    693 <function id='12'>glGenBuffers</function>(1, &buffer);
    694 <function id='32'>glBindBuffer</function>(GL_ARRAY_BUFFER, buffer);
    695 <function id='31'>glBufferData</function>(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);
    696   
    697 for(unsigned int i = 0; i &lt; rock.meshes.size(); i++)
    698 {
    699     unsigned int VAO = rock.meshes[i].VAO;
    700     <function id='27'>glBindVertexArray</function>(VAO);
    701     // vertex attributes
    702     std::size_t vec4Size = sizeof(glm::vec4);
    703     <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(3); 
    704     <function id='30'>glVertexAttribPointer</function>(3, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)0);
    705     <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(4); 
    706     <function id='30'>glVertexAttribPointer</function>(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)(1 * vec4Size));
    707     <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(5); 
    708     <function id='30'>glVertexAttribPointer</function>(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)(2 * vec4Size));
    709     <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(6); 
    710     <function id='30'>glVertexAttribPointer</function>(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (void*)(3 * vec4Size));
    711 
    712     <function id='100'>glVertexAttribDivisor</function>(3, 1);
    713     <function id='100'>glVertexAttribDivisor</function>(4, 1);
    714     <function id='100'>glVertexAttribDivisor</function>(5, 1);
    715     <function id='100'>glVertexAttribDivisor</function>(6, 1);
    716 
    717     <function id='27'>glBindVertexArray</function>(0);
    718 }  
    719 </code></pre>
    720 
    721 <p>
    722   Note that we cheated a little by declaring the <var>VAO</var> variable of the <fun>Mesh</fun> as a public variable instead of a private variable so we could access its vertex array object. This is not the cleanest solution, but just a simple modification to suit this example. Aside from the little hack, this code should be clear. We're basically declaring how OpenGL should interpret the buffer for each of the matrix's vertex attributes and that each of those vertex attributes is an instanced array.
    723 </p>
    724 
    725 <p>
    726   Next we take the <var>VAO</var> of the mesh(es) again and this time draw using <fun><function id='99'><function id='2'>glDrawElements</function>Instanced</function></fun>:
    727 </p>
    728 
    729 <pre><code>
    730 // draw meteorites
    731 instanceShader.use();
    732 for(unsigned int i = 0; i &lt; rock.meshes.size(); i++)
    733 {
    734     <function id='27'>glBindVertexArray</function>(rock.meshes[i].VAO);
    735     <function id='99'><function id='2'>glDrawElements</function>Instanced</function>(
    736         GL_TRIANGLES, rock.meshes[i].indices.size(), GL_UNSIGNED_INT, 0, amount
    737     );
    738 }  
    739 </code></pre>
    740 
    741 <p>
    742   Here we draw the same <var>amount</var> of asteroids as the previous example, but this time with instanced rendering. The results should be exactly the same, but once we increase the <var>amount</var> you'll really start to see the power of instanced rendering. Without instanced rendering we were able to smoothly render around <code>1000</code> to <code>1500</code> asteroids. With instanced rendering we can now set this value to <code>100000</code>. This, with the rock model having <code>576</code> vertices, would equal around <code>57</code> million vertices drawn each frame without significant performance drops; and only 2 draw calls!
    743 </p>
    744 
    745 <img src="/img/advanced/instancing_asteroids_quantity.png" class="clean" alt="Image of asteroid field in OpenGL drawn using instanced rendering"/>
    746 
    747 <p>
    748   This image was rendered with <code>100000</code> asteroids with a radius of <code>150.0f</code> and an offset equal to <code>25.0f</code>. You can find the source code of the instanced rendering demo <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/10.3.asteroids_instanced/asteroids_instanced.cpp" target="_blank">here</a>.
    749 </p>
    750 
    751 <note>
    752   On different machines an asteroid count of <code>100000</code> may be a bit too high, so try tweaking the values till you reach an acceptable framerate.
    753 </note>
    754 
    755 <p>
    756   As you can see, with the right type of environments, instanced rendering can make an enormous difference to the rendering capabilities of your application. For this reason, instanced rendering is commonly used for grass, flora, particles, and scenes like this - basically any scene with many repeating shapes can benefit from instanced rendering.
    757 </p>       
    758 
    759     </div>
    760     
    761 	</main>
    762 </body>
    763 </html>