LearnOpenGL

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

Mesh.html (23949B)


      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">Mesh</h1>
    320 <h1 id="content-url" style='display:none;'>Model-Loading/Mesh</h1>
    321 <p>
    322   With Assimp we can load many different models into the application, but once loaded they're all stored in Assimp's data structures. What we eventually want is to transform that data to a format that OpenGL understands so that we can render the objects. We learned from the previous chapter that a mesh represents a single drawable entity, so let's start by defining a mesh class of our own.
    323 </p>
    324 
    325 <p>
    326   Let's review a bit of what we've learned so far to think about what a mesh should minimally have as its data. A mesh should at least need a set of vertices, where each vertex contains a position vector, a normal vector, and a texture coordinate vector. A mesh should also contain indices for indexed drawing, and material data in the form of textures (diffuse/specular maps).
    327 </p>
    328 
    329 <p>
    330   Now that we set the minimal requirements for a mesh class we can define a vertex in OpenGL:
    331 </p>
    332 
    333 <pre><code>
    334 struct Vertex {
    335     glm::vec3 Position;
    336     glm::vec3 Normal;
    337     glm::vec2 TexCoords;
    338 };
    339 </code></pre>
    340 
    341 <p>
    342   We store each of the required vertex attributes in a struct called <fun>Vertex</fun>. Next to a <fun>Vertex</fun> struct we also want to organize the texture data in a <fun>Texture</fun> struct:
    343 </p>
    344 
    345 <pre><code>
    346 struct Texture {
    347     unsigned int id;
    348     string type;
    349 };  
    350 </code></pre>
    351 
    352 <p>
    353   We store the id of the texture and its type e.g. a diffuse or specular texture.
    354 </p>
    355 
    356 <p>
    357   Knowing the actual representation of a vertex and a texture we can start defining the structure of the mesh class:
    358 </p>
    359 
    360 <pre><code>
    361 class Mesh {
    362     public:
    363         // mesh data
    364         vector&lt;Vertex&gt;       vertices;
    365         vector&lt;unsigned int&gt; indices;
    366         vector&lt;Texture&gt;      textures;
    367 
    368         Mesh(vector&lt;Vertex&gt; vertices, vector&lt;unsigned int&gt; indices, vector&lt;Texture&gt; textures);
    369         void Draw(Shader &shader);
    370     private:
    371         //  render data
    372         unsigned int VAO, VBO, EBO;
    373 
    374         void setupMesh();
    375 };  
    376 </code></pre>
    377 
    378 <p>
    379   As you can see, the class isn't too complicated. In the constructor we give the mesh all the necessary data, we initialize the buffers in the <fun>setupMesh</fun> function, and finally draw the mesh via the <fun>Draw</fun> function. Note that we give a shader to the <fun>Draw</fun> function; by passing the shader to the mesh we can set several uniforms before drawing (like linking samplers to texture units).
    380 </p>
    381 
    382 <p>
    383   The function content of the constructor is pretty straightforward. We simply set the class's public variables with the constructor's corresponding argument variables. We also call the <fun>setupMesh</fun> function in the constructor:
    384 </p>
    385 
    386 <pre><code>
    387 Mesh(vector&lt;Vertex&gt; vertices, vector&lt;unsigned int&gt; indices, vector&lt;Texture&gt; textures)
    388 {
    389     this-&gt;vertices = vertices;
    390     this-&gt;indices = indices;
    391     this-&gt;textures = textures;
    392 
    393     setupMesh();
    394 }
    395 </code></pre>
    396 
    397 <p>
    398   Nothing special going on here. Let's delve right into the <fun>setupMesh</fun> function now.
    399 </p>
    400 
    401 <h2>Initialization</h2>
    402 <p>
    403   Thanks to the constructor we now have large lists of mesh data that we can use for rendering. We do need to setup the appropriate buffers and specify the vertex shader layout via vertex attribute pointers. By now you should have no trouble with these concepts, but we've spiced it up a bit this time with the introduction of vertex data in structs:
    404 </p>
    405 
    406 <pre><code>
    407 void setupMesh()
    408 {
    409     <function id='33'>glGenVertexArrays</function>(1, &VAO);
    410     <function id='12'>glGenBuffers</function>(1, &VBO);
    411     <function id='12'>glGenBuffers</function>(1, &EBO);
    412   
    413     <function id='27'>glBindVertexArray</function>(VAO);
    414     <function id='32'>glBindBuffer</function>(GL_ARRAY_BUFFER, VBO);
    415 
    416     <function id='31'>glBufferData</function>(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);  
    417 
    418     <function id='32'>glBindBuffer</function>(GL_ELEMENT_ARRAY_BUFFER, EBO);
    419     <function id='31'>glBufferData</function>(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), 
    420                  &indices[0], GL_STATIC_DRAW);
    421 
    422     // vertex positions
    423     <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(0);	
    424     <function id='30'>glVertexAttribPointer</function>(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
    425     // vertex normals
    426     <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(1);	
    427     <function id='30'>glVertexAttribPointer</function>(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
    428     // vertex texture coords
    429     <function id='29'><function id='60'>glEnable</function>VertexAttribArray</function>(2);	
    430     <function id='30'>glVertexAttribPointer</function>(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
    431 
    432     <function id='27'>glBindVertexArray</function>(0);
    433 }  
    434 </code></pre>
    435 
    436 <p>
    437   The code is not much different from what you'd expect, but a few little tricks were used with the help of the <fun>Vertex</fun> struct.
    438 </p>
    439 
    440 <p>
    441   Structs have a great property in C++ that their memory layout is sequential. That is, if we were to represent a struct as an array of data, it would only contain the struct's variables in sequential order which directly translates to a float (actually byte) array that we want for an array buffer. For example, if we have a filled <fun>Vertex</fun> struct, its memory layout would be equal to:
    442 </p>
    443 
    444 <pre><code>
    445 Vertex vertex;
    446 vertex.Position  = glm::vec3(0.2f, 0.4f, 0.6f);
    447 vertex.Normal    = glm::vec3(0.0f, 1.0f, 0.0f);
    448 vertex.TexCoords = glm::vec2(1.0f, 0.0f);
    449 // = [0.2f, 0.4f, 0.6f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f];
    450 </code></pre>
    451 
    452 <p>
    453   Thanks to this useful property we can directly pass a pointer to a large list of <fun>Vertex</fun> structs as the buffer's data and they translate perfectly to what <fun><function id='31'>glBufferData</function></fun> expects as its argument: 
    454 </p>
    455 
    456 <pre><code>
    457 <function id='31'>glBufferData</function>(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices[0], GL_STATIC_DRAW);    
    458 </code></pre>
    459 
    460 <p>
    461   Naturally the <code>sizeof</code> operator can also be used on the struct for the appropriate size in bytes. This should be <code>32</code> bytes (<code>8</code> floats * <code>4</code> bytes each).
    462 </p>
    463 
    464 <p>
    465   Another great use of structs is a preprocessor directive called <code>offsetof(s,m)</code> that takes as its first argument a struct and as its second argument a variable name of the struct. The macro returns the byte offset of that variable from the start of the struct. This is perfect for defining the offset parameter of the <fun><function id='30'>glVertexAttribPointer</function></fun> function:
    466 </p>
    467 
    468 <pre><code>
    469 <function id='30'>glVertexAttribPointer</function>(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));  
    470 </code></pre>
    471 
    472 <p>
    473   The offset is now defined using the <fun>offsetof</fun> macro that, in this case, sets the byte offset of the normal vector equal to the byte offset of the normal attribute in the struct which is <code>3</code> floats and thus <code>12</code> bytes.
    474 </p>
    475 
    476 <p>
    477   Using a struct like this doesn't only get us more readable code, but also allows us to easily extend the structure. If we want another vertex attribute we can simply add it to the struct and due to its flexible nature, the rendering code won't break.
    478 </p>
    479 
    480 <h2>Rendering</h2>
    481 <p>
    482   The last function we need to define for the <fun>Mesh</fun> class to be complete is its <fun>Draw</fun> function. Before rendering the mesh, we first want to bind the appropriate textures before calling <fun><function id='2'>glDrawElements</function></fun>. However, this is somewhat difficult since we don't know from the start how many (if any) textures the mesh has and what type they may have. So how do we set the texture units and samplers in the shaders?
    483 </p>
    484 
    485 <p>
    486   To solve the issue we're going to assume a certain naming convention: each diffuse texture is named <code>texture_diffuseN</code>, and each specular texture should be named <code>texture_specularN</code> where <code>N</code> is any number ranging from <code>1</code> to the maximum number of texture samplers allowed. Let's say we have 3 diffuse textures and 2 specular textures for a particular mesh, their texture samplers should then be called: 
    487 </p>
    488 
    489 <pre><code>
    490 uniform sampler2D texture_diffuse1;
    491 uniform sampler2D texture_diffuse2;
    492 uniform sampler2D texture_diffuse3;
    493 uniform sampler2D texture_specular1;
    494 uniform sampler2D texture_specular2;
    495 </code></pre>
    496 
    497 <p>
    498   By this convention we can define as many texture samplers as we want in the shaders (up to OpenGL's maximum) and if a mesh actually does contain (so many) textures, we know what their names are going to be. By this convention we can process any amount of textures on a single mesh and the shader developer is free to use as many of those as he wants by defining the proper samplers.
    499 </p>
    500 
    501 <note>
    502   There are many solutions to problems like this and if you don't like this particular solution it is up to you to get creative and come up with your own approach.
    503 </note>
    504 
    505 <p>
    506   The resulting drawing code then becomes:
    507 </p>
    508 
    509 <pre><code>
    510 void Draw(Shader &shader) 
    511 {
    512     unsigned int diffuseNr = 1;
    513     unsigned int specularNr = 1;
    514     for(unsigned int i = 0; i &lt; textures.size(); i++)
    515     {
    516         <function id='49'>glActiveTexture</function>(GL_TEXTURE0 + i); // activate proper texture unit before binding
    517         // retrieve texture number (the N in diffuse_textureN)
    518         string number;
    519         string name = textures[i].type;
    520         if(name == "texture_diffuse")
    521             number = std::to_string(diffuseNr++);
    522         else if(name == "texture_specular")
    523             number = std::to_string(specularNr++);
    524 
    525         shader.setFloat(("material." + name + number).c_str(), i);
    526         <function id='48'>glBindTexture</function>(GL_TEXTURE_2D, textures[i].id);
    527     }
    528     <function id='49'>glActiveTexture</function>(GL_TEXTURE0);
    529 
    530     // draw mesh
    531     <function id='27'>glBindVertexArray</function>(VAO);
    532     <function id='2'>glDrawElements</function>(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
    533     <function id='27'>glBindVertexArray</function>(0);
    534 }  
    535 </code></pre>
    536 
    537 <p>
    538   We first calculate the N-component per texture type and concatenate it to the texture's type string to get the appropriate uniform name. We then locate the appropriate sampler, give it the location value to correspond with the currently active texture unit, and bind the texture. This is also the reason we need the shader in the <fun>Draw</fun> function. 
    539 </p>
    540 
    541 <p>
    542  We also added <code>"material."</code> to the resulting uniform name because we usually store the textures in a material struct (this may differ per implementation).
    543 </p>
    544 
    545 <note>
    546   Note that we increment the diffuse and specular counters the moment we convert them to <code>string</code>. In C++ the increment call: <code>variable++</code> returns the variable as is and <strong>then</strong> increments the variable while <code>++variable</code> <strong>first</strong> increments the variable and <strong>then</strong> returns it. In our case the value passed to <code>std::string</code> is the original counter value. After that the value is incremented for the next round.
    547 </note>
    548 
    549 <p>
    550   You can find the full source code of the <fun>Mesh</fun> class <a href="/code_viewer_gh.php?code=includes/learnopengl/mesh.h" target="_blank">here</a>.
    551 </p>
    552 
    553 <p>
    554   The <fun>Mesh</fun> class we just defined is an abstraction for many of the topics we've discussed in the early chapters. In the <a href="https://learnopengl.com/Model-Loading/Model" target="_blank">next</a> chapter we'll create a model that acts as a container for several mesh objects and implements Assimp's loading interface.
    555 </p>
    556        
    557 
    558     </div>
    559     
    560 	</main>
    561 </body>
    562 </html>