LearnOpenGL

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

Geometry-Shader.html (40051B)


      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">Geometry Shader</h1>
    320 <h1 id="content-url" style='display:none;'>Advanced-OpenGL/Geometry-Shader</h1>
    321 <p>
    322   Between the vertex and the fragment shader there is an optional shader stage called the <def>geometry shader</def>. A geometry shader takes as input a set of vertices that form a single primitive e.g. a point or a triangle. The geometry shader can then transform these vertices as it sees fit before sending them to the next shader stage. What makes the geometry shader interesting is that it is able to convert the original primitive (set of vertices) to completely different primitives, possibly generating more vertices than were initially given. 
    323 </p>
    324 
    325 <p>
    326   We're going to throw you right into the deep by showing you an example of a geometry shader:
    327 </p>
    328 
    329 <pre><code>
    330 #version 330 core
    331 layout (points) in;
    332 layout (line_strip, max_vertices = 2) out;
    333 
    334 void main() {    
    335     gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0); 
    336     EmitVertex();
    337 
    338     gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0);
    339     EmitVertex();
    340     
    341     EndPrimitive();
    342 }  
    343 </code></pre>
    344 
    345 <p>
    346   At the start of a geometry shader we need to declare the type of primitive input we're receiving from the vertex shader. We do this by declaring a layout specifier in front of the <fun>in</fun> keyword. This input layout qualifier can take any of the following primitive values:
    347 </p>
    348 
    349 <ul>
    350   <li><code>points</code>: when drawing <var>GL_POINTS</var> primitives (<code>1</code>).</li>
    351   <li><code>lines</code>: when drawing <var>GL_LINES</var> or <var>GL_LINE_STRIP</var> (<code>2</code>).</li>
    352   <li><code>lines_adjacency</code>: <var>GL_LINES_ADJACENCY</var> or <var>GL_LINE_STRIP_ADJACENCY</var> (<code>4</code>).</li>
    353   <li><code>triangles</code>: <var>GL_TRIANGLES</var>, <var>GL_TRIANGLE_STRIP</var> or <var>GL_TRIANGLE_FAN</var> (<code>3</code>).</li>
    354    <li><code>triangles_adjacency </code>: <var>GL_TRIANGLES_ADJACENCY</var> or <var>GL_TRIANGLE_STRIP_ADJACENCY </var> (<code>6</code>).</li>
    355 </ul>
    356 
    357 <p>
    358   These are almost all the rendering primitives we're able to give to rendering calls like <fun><function id='1'>glDrawArrays</function></fun>. If we'd chosen to draw vertices as <var>GL_TRIANGLES</var> we should set the input qualifier to <code>triangles</code>. The number within the parenthesis represents the minimal number of vertices a single primitive contains.
    359 </p>
    360 
    361 <p>
    362   We also need to specify a primitive type that the geometry shader will output and we do this via a layout specifier in front of the <fun>out</fun> keyword. Like the input layout qualifier, the output layout qualifier can take several primitive values:
    363 </p>
    364 
    365 <ul>
    366   <li><code>points</code></li>
    367   <li><code>line_strip</code></li>
    368   <li><code>triangle_strip</code></li>
    369 </ul>
    370 
    371 <p>
    372 	With just these 3 output specifiers we can create almost any shape we want from the input primitives. To generate a single triangle for example we'd specify <code>triangle_strip</code> as the output and output 3 vertices.
    373 </p>
    374 
    375 <p>
    376   The geometry shader also expects us to set a maximum number of vertices it outputs (if you exceed this number, OpenGL won't draw the <em>extra</em> vertices) which we can also do within the layout qualifier of the <fun>out</fun> keyword. In this particular case we're going to output a <code>line_strip</code> with a maximum number of 2 vertices. 
    377 </p>
    378 
    379 <note>
    380   In case you're wondering what a line strip is: a line strip binds together a set of points to form one continuous line between them with a minimum of 2 points. Each extra point results in a new line between the new point and the previous point as you can see in the following image with 5 point vertices:
    381 
    382 <img src="/img/advanced/geometry_shader_line_strip.png" class="clean" alt="Image of line_strip primitive in geometry shader"/>
    383 </note>
    384 
    385 <p>
    386   To generate meaningful results we need some way to retrieve the output from the previous shader stage. GLSL gives us a <def>built-in</def> variable called <fun>gl_in</fun> that internally (probably) looks something like this:
    387 </p>
    388 
    389 <pre><code>
    390 in gl_Vertex
    391 {
    392     vec4  gl_Position;
    393     float gl_PointSize;
    394     float gl_ClipDistance[];
    395 } gl_in[];  
    396 </code></pre>
    397 
    398 <p>
    399   Here it is declared as an <def>interface block</def> (as discussed in the <a href="https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL" target="_blank">previous</a> chapter) that contains a few interesting variables of which the most interesting one is <var>gl_Position</var> that contains the vector we set as the vertex shader's output.
    400 </p>
    401 
    402 <p>
    403   Note that it is declared as an array, because most render primitives contain more than 1 vertex. The geometry shader receives <strong>all</strong> vertices of a primitive as its input.
    404 </p>
    405 
    406 <p>
    407   Using the vertex data from the vertex shader stage we can generate new data with 2 geometry shader functions called <fun>EmitVertex</fun> and <fun>EndPrimitive</fun>. The geometry shader expects you to generate/output at least one of the primitives you specified as output. In our case we want to at least generate one line strip primitive.
    408 </p>
    409 
    410 <pre><code>
    411 #version 330 core
    412 layout (points) in;
    413 layout (line_strip, max_vertices = 2) out;
    414   
    415 void main() {    
    416     gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0); 
    417     EmitVertex();
    418 
    419     gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0);
    420     EmitVertex();
    421     
    422     EndPrimitive();
    423 }    
    424 </code></pre>
    425 
    426 <p>
    427   Each time we call <fun>EmitVertex</fun>, the vector currently set to <var>gl_Position</var> is added to the output primitive. Whenever <fun>EndPrimitive</fun> is called, all emitted vertices for this primitive are combined into the specified output render primitive. By repeatedly calling <fun>EndPrimitive</fun>, after one or more <fun>EmitVertex</fun> calls, multiple primitives can be generated. This particular case emits two vertices that were translated by a small offset from the original vertex position and then calls <fun>EndPrimitive</fun>, combining the two vertices into a single line strip of 2 vertices.
    428 </p>
    429 
    430 <p>
    431   Now that you (sort of) know how geometry shaders work you can probably guess what this geometry shader does. This geometry shader takes a point primitive as its input and creates a horizontal line primitive with the input point at its center. If we were to render this it looks something like this:
    432 </p>
    433 
    434 <img src="/img/advanced/geometry_shader_lines.png" class="clean" alt="Geometry shader drawing lines out of points in OpenGL"/>
    435 
    436 <p>
    437   Not very impressive yet, but it's interesting to consider that this output was generated using just the following render call:
    438 </p>
    439 
    440 <pre class="cpp"><code>
    441 <function id='1'>glDrawArrays</function>(GL_POINTS, 0, 4);  
    442 </code></pre>
    443 
    444 <p>
    445   While this is a relatively simple example, it does show you how we can use geometry shaders to (dynamically) generate new shapes on the fly. Later in this chapter we'll discuss a few interesting effects that we can create using geometry shaders, but for now we're going to start with a simple example.
    446 </p>
    447 
    448 <h2>Using geometry shaders</h2>
    449 <p>
    450   To demonstrate the use of a geometry shader we're going to render a really simple scene where we draw 4 points on the z-plane in normalized device coordinates. The coordinates of the points are:
    451 </p>
    452 
    453 <pre><code>
    454 float points[] = {
    455 	-0.5f,  0.5f, // top-left
    456 	 0.5f,  0.5f, // top-right
    457 	 0.5f, -0.5f, // bottom-right
    458 	-0.5f, -0.5f  // bottom-left
    459 };  
    460 </code></pre>
    461 
    462 <p>
    463   The vertex shader needs to draw the points on the z-plane so we'll create a basic vertex shader:
    464 </p>
    465 
    466 <pre><code>
    467 #version 330 core
    468 layout (location = 0) in vec2 aPos;
    469 
    470 void main()
    471 {
    472     gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); 
    473 }
    474 </code></pre>
    475 
    476 <p>
    477   And we'll output the color green for all points which we code directly in the fragment shader:
    478 </p>
    479 
    480 <pre><code>
    481 #version 330 core
    482 out vec4 FragColor;
    483 
    484 void main()
    485 {
    486     FragColor = vec4(0.0, 1.0, 0.0, 1.0);   
    487 }  
    488 </code></pre>
    489 
    490 <p>
    491   Generate a VAO and a VBO for the points' vertex data and then draw them via <fun><function id='1'>glDrawArrays</function></fun>:
    492 </p>
    493 
    494 <pre class="cpp"><code>
    495 shader.use();
    496 <function id='27'>glBindVertexArray</function>(VAO);
    497 <function id='1'>glDrawArrays</function>(GL_POINTS, 0, 4); 
    498 </code></pre>
    499 
    500 <p>
    501   The result is a dark scene with 4 (difficult to see) green points:
    502 </p>
    503 
    504 <img src="/img/advanced/geometry_shader_points.png" class="clean" alt="4 Points drawn using OpenGL"/>
    505 
    506 <p>
    507   But didn't we already learn to do all this? Yes, and now we're going to spice this little scene up by adding geometry shader magic to the scene.
    508 </p>
    509 
    510 <p>
    511   For learning purposes we're first going to create what is called a <def>pass-through</def> geometry shader that takes a point primitive as its input and <em>passes</em> it to the next shader unmodified:
    512 </p>
    513 
    514 <pre><code>
    515 #version 330 core
    516 layout (points) in;
    517 layout (points, max_vertices = 1) out;
    518 
    519 void main() {    
    520     gl_Position = gl_in[0].gl_Position; 
    521     EmitVertex();
    522     EndPrimitive();
    523 }  
    524 </code></pre>
    525 
    526 <p>
    527   By now this geometry shader should be fairly easy to understand. It simply emits the unmodified vertex position it received as input and generates a point primitive.
    528 </p>
    529 
    530 <p>
    531   A geometry shader needs to be compiled and linked to a program just like the vertex and fragment shader, but this time we'll create the shader using <var>GL_GEOMETRY_SHADER</var> as the shader type:
    532 </p>
    533 
    534 <pre class="cpp"><code>
    535 geometryShader = <function id='37'>glCreateShader</function>(GL_GEOMETRY_SHADER);
    536 <function id='42'>glShaderSource</function>(geometryShader, 1, &gShaderCode, NULL);
    537 <function id='38'>glCompileShader</function>(geometryShader);  
    538 [...]
    539 <function id='34'>glAttachShader</function>(program, geometryShader);
    540 <function id='35'>glLinkProgram</function>(program);  
    541 </code></pre>
    542 
    543 <p>
    544   The shader compilation code is the same as the vertex and fragment shaders. Be sure to check for compile or linking errors!
    545 </p>
    546 
    547 <p>
    548   If you'd now compile and run you should be looking at a result that looks a bit like this:
    549 </p>
    550 
    551 <img src="/img/advanced/geometry_shader_points.png" class="clean" alt="4 Points drawn using OpenGL (with geometry shader this time!)"/>
    552 
    553 <p>
    554   It's exactly the same as without the geometry shader! It's a bit dull, I'll admit that, but the fact that we were still able to draw the points means that the geometry shader works, so now it's time for the more funky stuff!
    555 </p>
    556 
    557 <h2>Let's build houses</h2>
    558 <p>
    559   Drawing points and lines isn't <strong>that</strong> interesting so we're going to get a little creative by using the geometry shader to draw a house for us at the location of each point. We can accomplish this by setting the output of the geometry shader to <def>triangle_strip</def> and draw a total of three triangles: two for the square house and one for the roof.
    560 </p>
    561 
    562 <p>
    563   A triangle strip in OpenGL is a more efficient way to draw triangles with fewer vertices. After the first triangle is drawn, each subsequent vertex generates another triangle next to the first triangle: every 3 adjacent vertices will form a triangle. If we have a total of 6 vertices that form a triangle strip we'd get the following triangles: (1,2,3), (2,3,4), (3,4,5) and (4,5,6); forming a total of 4 triangles. A triangle strip needs at least 3 vertices and will generate N-2 triangles; with 6 vertices we created 6-2 = 4 triangles. The following image illustrates this:
    564 </p>
    565 
    566 <img src="/img/advanced/geometry_shader_triangle_strip.png" class="clean" alt="Image of a triangle strip with their index order in OpenGL"/>
    567 
    568 <p>
    569   Using a triangle strip as the output of the geometry shader we can easily create the house shape we're after by generating 3 adjacent triangles in the correct order. The following image shows in what order we need to draw what vertices to get the triangles we need with the blue dot being the input point:
    570 </p>
    571 
    572 <img src="/img/advanced/geometry_shader_house.png" class="clean" alt="How a house figure should be drawn from a single point using geometry shaders"/>
    573 
    574 <p>
    575   This translates to the following geometry shader:
    576 </p>
    577 
    578 <pre><code>
    579 #version 330 core
    580 layout (points) in;
    581 layout (triangle_strip, max_vertices = 5) out;
    582 
    583 void build_house(vec4 position)
    584 {    
    585     gl_Position = position + vec4(-0.2, -0.2, 0.0, 0.0);    // 1:bottom-left
    586     EmitVertex();   
    587     gl_Position = position + vec4( 0.2, -0.2, 0.0, 0.0);    // 2:bottom-right
    588     EmitVertex();
    589     gl_Position = position + vec4(-0.2,  0.2, 0.0, 0.0);    // 3:top-left
    590     EmitVertex();
    591     gl_Position = position + vec4( 0.2,  0.2, 0.0, 0.0);    // 4:top-right
    592     EmitVertex();
    593     gl_Position = position + vec4( 0.0,  0.4, 0.0, 0.0);    // 5:top
    594     EmitVertex();
    595     EndPrimitive();
    596 }
    597 
    598 void main() {    
    599     build_house(gl_in[0].gl_Position);
    600 }  
    601 </code></pre>
    602 
    603 <p>
    604   This geometry shader generates 5 vertices, with each vertex being the point's position plus an offset to form one large triangle strip. The resulting primitive is then rasterized and the fragment shader runs on the entire triangle strip, resulting in a green house for each point we've rendered:
    605 </p>
    606 
    607 <img src="/img/advanced/geometry_shader_houses.png" class="clean" alt="Houses drawn with points using geometry shader in OpenGL"/>
    608 
    609 <p>
    610   You can see that each house indeed consists of 3 triangles - all drawn using a single point in space. The green houses do look a bit boring though, so let's liven it up a bit by giving each house a unique color. To do this we're going to add an extra vertex attribute in the vertex shader with color information per vertex and direct it to the geometry shader that further forwards it to the fragment shader. 
    611 </p>
    612 
    613 <p>
    614   The updated vertex data is given below:
    615 </p>
    616 
    617 <pre><code>
    618 float points[] = {
    619     -0.5f,  0.5f, 1.0f, 0.0f, 0.0f, // top-left
    620      0.5f,  0.5f, 0.0f, 1.0f, 0.0f, // top-right
    621      0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // bottom-right
    622     -0.5f, -0.5f, 1.0f, 1.0f, 0.0f  // bottom-left
    623 };  
    624 </code></pre>
    625 
    626 <p>
    627   Then we update the vertex shader to forward the color attribute to the geometry shader using an interface block:
    628 </p>
    629 
    630 <pre><code>
    631 #version 330 core
    632 layout (location = 0) in vec2 aPos;
    633 layout (location = 1) in vec3 aColor;
    634 
    635 out VS_OUT {
    636     vec3 color;
    637 } vs_out;
    638 
    639 void main()
    640 {
    641     gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); 
    642     vs_out.color = aColor;
    643 }  
    644 </code></pre>
    645 
    646 <p>
    647   Then we also need to declare the same interface block (with a different interface name) in the geometry shader:
    648 </p>
    649 
    650 <pre><code>
    651 in VS_OUT {
    652     vec3 color;
    653 } gs_in[];  
    654 </code></pre>
    655 
    656 <p>
    657   Because the geometry shader acts on a set of vertices as its input, its input data from the vertex shader is always represented as arrays of vertex data even though we only have a single vertex right now.
    658 </p>
    659 
    660 <note>
    661   We don't necessarily have to use interface blocks to transfer data to the geometry shader. We could have also written it as:
    662 <pre><code>
    663 in vec3 outColor[];
    664 </code></pre>
    665   This works if the vertex shader forwarded the color vector as <code>out</code> <code>vec3</code> <code>outColor</code>. However, interface blocks are easier to work with in shaders like the geometry shader. In practice, geometry shader inputs can get quite large and grouping them in one large interface block array makes a lot more sense.  
    666 </note>
    667 
    668 <p>
    669   We should also declare an output color vector for the next fragment shader stage:
    670 </p>
    671 
    672 <pre><code>
    673 out vec3 fColor;  
    674 </code></pre>
    675 
    676 <p>
    677   Because the fragment shader expects only a single (interpolated) color it doesn't make sense to forward multiple colors. The <var>fColor</var> vector is thus not an array, but a single vector. When emitting a vertex, that vertex will store the last stored value in <var>fColor</var> as that vertex's output value. For the houses, we can fill <var>fColor</var> once with the color from the vertex shader before the first vertex is emitted to color the entire house:
    678 </p>
    679 
    680 <pre><code>
    681 fColor = gs_in[0].color; // gs_in[0] since there's only one input vertex
    682 gl_Position = position + vec4(-0.2, -0.2, 0.0, 0.0);    // 1:bottom-left   
    683 EmitVertex();   
    684 gl_Position = position + vec4( 0.2, -0.2, 0.0, 0.0);    // 2:bottom-right
    685 EmitVertex();
    686 gl_Position = position + vec4(-0.2,  0.2, 0.0, 0.0);    // 3:top-left
    687 EmitVertex();
    688 gl_Position = position + vec4( 0.2,  0.2, 0.0, 0.0);    // 4:top-right
    689 EmitVertex();
    690 gl_Position = position + vec4( 0.0,  0.4, 0.0, 0.0);    // 5:top
    691 EmitVertex();
    692 EndPrimitive();  
    693 </code></pre>
    694 
    695 <p>
    696   All the emitted vertices will have the last stored value in <var>fColor</var> embedded into their data, which is equal to the input vertex's color as we defined in its attributes. All the houses will now have a color of their own:
    697 </p>
    698 
    699 <img src="/img/advanced/geometry_shader_houses_colored.png" class="clean" alt="Colored houses, generating using points with geometry shaders in OpenGL"/>
    700 
    701 <p>
    702   Just for fun we could also pretend it's winter and give their roofs a little snow by giving the last vertex a color of its own: 
    703 </p>
    704 
    705 <pre><code>
    706 fColor = gs_in[0].color; 
    707 gl_Position = position + vec4(-0.2, -0.2, 0.0, 0.0);    // 1:bottom-left   
    708 EmitVertex();   
    709 gl_Position = position + vec4( 0.2, -0.2, 0.0, 0.0);    // 2:bottom-right
    710 EmitVertex();
    711 gl_Position = position + vec4(-0.2,  0.2, 0.0, 0.0);    // 3:top-left
    712 EmitVertex();
    713 gl_Position = position + vec4( 0.2,  0.2, 0.0, 0.0);    // 4:top-right
    714 EmitVertex();
    715 gl_Position = position + vec4( 0.0,  0.4, 0.0, 0.0);    // 5:top
    716 fColor = vec3(1.0, 1.0, 1.0);
    717 EmitVertex();
    718 EndPrimitive();  
    719 </code></pre>
    720 
    721 <p>
    722   The result now looks something like this:
    723 </p>
    724 
    725 <img src="/img/advanced/geometry_shader_houses_snow.png" class="clean" alt="Snow-colored houses, generating using points with geometry shaders in OpenGL"/>
    726 
    727 <p>
    728   You can compare your source code with the OpenGL code <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/9.1.geometry_shader_houses/geometry_shader_houses.cpp" target="_blank">here</a>.
    729 </p>
    730 
    731 <p>
    732   You can see that with geometry shaders you can get pretty creative, even with the simplest primitives. Because the shapes are generated dynamically on the ultra-fast hardware of your GPU this can be a lot more powerful than defining these shapes yourself within vertex buffers. Geometry shaders are a great tool for simple (often-repeating) shapes, like cubes in a voxel world or grass leaves on a large outdoor field.
    733 </p>
    734 
    735 <h1>Exploding objects</h1>
    736 <p>
    737   While drawing houses is fun and all, it's not something we're going to use that much. That's why we're now going to take it up one notch and explode objects! That is something we're also probably not going to use that much either, but it's definitely fun to do!
    738 </p>
    739 
    740 <p>
    741   When we say <em>exploding</em> an object we're not actually going to blow up our precious bundled sets of vertices, but we're going to move each triangle along the direction of their normal vector over a small period of time. The effect is that the entire object's triangles seem to <em>explode</em>. The effect of exploding triangles on the backpack model looks a bit like this:
    742 </p>
    743 
    744 <img src="/img/advanced/geometry_shader_explosion.png" class="clean" alt="Explosion effect with geometry shaders in OpenGL"/>
    745 
    746 <p>
    747   The great thing about such a geometry shader effect is that it works on all objects, regardless of their complexity.
    748 </p>
    749 
    750 <p>
    751   Because we're going to translate each vertex into the direction of the triangle's normal vector we first need to calculate this normal vector. What we need to do is calculate a vector that is perpendicular to the surface of a triangle, using just the 3 vertices we have access to. You may remember from the <a href="https://learnopengl.com/Getting-started/Transformations" target="_blank">transformations</a> chapter that we can retrieve a vector perpendicular to two other vectors using the <def>cross product</def>. If we were to retrieve two vectors <var>a</var> and <var>b</var> that are parallel to the surface of a triangle we can retrieve its normal vector by doing a cross product on those vectors. The following geometry shader function does exactly this to retrieve the normal vector using 3 input vertex coordinates:
    752 </p>
    753 
    754 <pre><code>
    755 vec3 GetNormal()
    756 {
    757    vec3 a = vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position);
    758    vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position);
    759    return normalize(cross(a, b));
    760 }  
    761 </code></pre>
    762 
    763 <p>
    764   Here we retrieve two vectors <var>a</var> and <var>b</var> that are parallel to the surface of the triangle using vector subtraction. Subtracting two vectors from each other results in a vector that is the difference of the two vectors. Since all 3 points lie on the triangle plane, subtracting any of its vectors from each other results in a vector parallel to the plane. Do note that if we switched <var>a</var> and <var>b</var> in the <fun>cross</fun> function we'd get a normal vector that points in the opposite direction - order is important here!
    765 </p>
    766 
    767 <p>
    768   Now that we know how to calculate a normal vector we can create an <fun>explode</fun> function that takes this normal vector along with a vertex position vector. The function returns a new vector that translates the position vector along the direction of the normal vector:
    769 </p>
    770 
    771 <pre><code>
    772 vec4 explode(vec4 position, vec3 normal)
    773 {
    774     float magnitude = 2.0;
    775     vec3 direction = normal * ((sin(time) + 1.0) / 2.0) * magnitude; 
    776     return position + vec4(direction, 0.0);
    777 } 
    778 </code></pre>
    779 
    780 <p>
    781   The function itself shouldn't be too complicated. The <fun>sin</fun> function receives a <var>time</var> uniform variable as its argument that, based on the time, returns a value between <code>-1.0</code> and <code>1.0</code>. Because we don't want to <em>implode</em> the object we transform the sin value to the <code>[0,1]</code> range. The resulting value is then used to scale the <var>normal</var> vector and the resulting <var>direction</var> vector is added to the position vector.
    782 </p>
    783 
    784 <p>
    785   The complete geometry shader for the <def>explode</def> effect, while drawing a model loaded using our <a href="https://learnopengl.com/Model-Loading/Assimp" target="_blank">model loader</a>, looks a bit like this:
    786 </p>
    787 
    788 <pre><code>
    789 #version 330 core
    790 layout (triangles) in;
    791 layout (triangle_strip, max_vertices = 3) out;
    792 
    793 in VS_OUT {
    794     vec2 texCoords;
    795 } gs_in[];
    796 
    797 out vec2 TexCoords; 
    798 
    799 uniform float time;
    800 
    801 vec4 explode(vec4 position, vec3 normal) { ... }
    802 
    803 vec3 GetNormal() { ... }
    804 
    805 void main() {    
    806     vec3 normal = GetNormal();
    807 
    808     gl_Position = explode(gl_in[0].gl_Position, normal);
    809     TexCoords = gs_in[0].texCoords;
    810     EmitVertex();
    811     gl_Position = explode(gl_in[1].gl_Position, normal);
    812     TexCoords = gs_in[1].texCoords;
    813     EmitVertex();
    814     gl_Position = explode(gl_in[2].gl_Position, normal);
    815     TexCoords = gs_in[2].texCoords;
    816     EmitVertex();
    817     EndPrimitive();
    818 }  
    819 </code></pre>
    820 
    821 <p>
    822   Note that we're also outputting the appropriate texture coordinates before emitting a vertex. 
    823 </p>
    824 
    825 <p>
    826   Also don't forget to actually set the <var>time</var> uniform in your OpenGL code:
    827 </p>
    828 
    829 <pre><code>
    830 shader.setFloat("time", <function id='47'>glfwGetTime</function>());  
    831 </code></pre>
    832 
    833 <p>
    834   The result is a 3D model that seems to continually explode its vertices over time after which it returns to normal again. Although not exactly super useful, it does show you a more advanced use of the geometry shader. You can compare your source code with the complete source code <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/9.2.geometry_shader_exploding/geometry_shader_exploding.cpp" target="_blank">here</a>.
    835 </p>
    836 
    837 <h1>Visualizing normal vectors</h1>
    838 <p>
    839   To shake things up we're going to now discuss an example of using the geometry shader that is actually useful: visualizing the normal vectors of any object. When programming lighting shaders you will eventually run into weird visual outputs of which the cause is hard to determine. A common cause of lighting errors is incorrect normal vectors. Either caused by incorrectly loading vertex data, improperly specifying them as vertex attributes, or by incorrectly managing them in the shaders. What we want is some way to detect if the normal vectors we supplied are correct. A great way to determine if your normal vectors are correct is by visualizing them, and it just so happens that the geometry shader is an extremely useful tool for this purpose.
    840 </p>
    841 
    842 <p>
    843   The idea is as follows: we first draw the scene as normal without a geometry shader and then we draw the scene a second time, but this time only displaying normal vectors that we generate via a geometry shader. The geometry shader takes as input a triangle primitive and generates 3 lines from them in the directions of their normal - one normal vector for each vertex. In code it'll look something like this:
    844 </p>
    845 
    846 <pre><code>
    847 shader.use();
    848 DrawScene();
    849 normalDisplayShader.use();
    850 DrawScene();
    851 </code></pre>
    852 
    853 <p>
    854   This time we're creating a geometry shader that uses the vertex normals supplied by the model instead of generating it ourself. To accommodate for scaling and rotations (due to the view and model matrix) we'll transform the normals with a normal matrix. The geometry shader receives its position vectors as view-space coordinates so we should also transform the normal vectors to the same space. This can all be done in the vertex shader:
    855 </p>
    856 
    857 <pre><code>
    858 #version 330 core
    859 layout (location = 0) in vec3 aPos;
    860 layout (location = 1) in vec3 aNormal;
    861 
    862 out VS_OUT {
    863     vec3 normal;
    864 } vs_out;
    865 
    866 uniform mat4 view;
    867 uniform mat4 model;
    868 
    869 void main()
    870 {
    871     gl_Position = view * model * vec4(aPos, 1.0); 
    872     mat3 normalMatrix = mat3(transpose(inverse(view * model)));
    873     vs_out.normal = normalize(vec3(vec4(normalMatrix * aNormal, 0.0)));
    874 }
    875 </code></pre>
    876 
    877 <p>
    878   The transformed view-space normal vector is then passed to the next shader stage via an interface block. The geometry shader then takes each vertex (with a position and a normal vector) and draws a normal vector from each position vector:
    879 </p>
    880 
    881 <pre><code>
    882 #version 330 core
    883 layout (triangles) in;
    884 layout (line_strip, max_vertices = 6) out;
    885 
    886 in VS_OUT {
    887     vec3 normal;
    888 } gs_in[];
    889 
    890 const float MAGNITUDE = 0.4;
    891   
    892 uniform mat4 projection;
    893 
    894 void GenerateLine(int index)
    895 {
    896     gl_Position = projection * gl_in[index].gl_Position;
    897     EmitVertex();
    898     gl_Position = projection * (gl_in[index].gl_Position + 
    899                                 vec4(gs_in[index].normal, 0.0) * MAGNITUDE);
    900     EmitVertex();
    901     EndPrimitive();
    902 }
    903 
    904 void main()
    905 {
    906     GenerateLine(0); // first vertex normal
    907     GenerateLine(1); // second vertex normal
    908     GenerateLine(2); // third vertex normal
    909 }  
    910 </code></pre>
    911 
    912 <p>
    913   The contents of geometry shaders like these should be self-explanatory by now. Note that we're multiplying the normal vector by a <var>MAGNITUDE</var> vector to restrain the size of the displayed normal vectors (otherwise they'd be a bit too large). 
    914 </p>
    915 
    916 <p>
    917   Since visualizing normals are mostly used for debugging purposes we can just display them as mono-colored lines (or super-fancy lines if you feel like it) with the help of the fragment shader:
    918 </p>
    919 
    920 <pre><code>
    921 #version 330 core
    922 out vec4 FragColor;
    923 
    924 void main()
    925 {
    926     FragColor = vec4(1.0, 1.0, 0.0, 1.0);
    927 }  
    928 </code></pre>
    929 
    930 <p>
    931   Now rendering your model with normal shaders first and then with the special <em>normal-visualizing</em> shader you'll see something like this:
    932 </p>
    933 
    934 <img src="/img/advanced/geometry_shader_normals.png" class="clean" alt="Image of geometry shader displaying normal vectors in OpenGL"/>
    935 
    936 <p>
    937   Apart from the fact that our backpack now looks a bit hairy, it gives us a really useful method for determining if the normal vectors of a model are indeed correct. You can imagine that geometry shaders like this could also be used for adding <def>fur</def> to objects.
    938 </p>
    939 
    940 <p>
    941   You can find the OpenGL's source code <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/9.3.geometry_shader_normals/normal_visualization.cpp" target="_blank">here</a>.
    942 </p>       
    943 
    944     </div>
    945     
    946 	</main>
    947 </body>
    948 </html>