LearnOpenGL

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

Shadow-Mapping.html (53632B)


      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     <h1 id="content-title">Shadow Mapping</h1>
    319 <h1 id="content-url" style='display:none;'>Advanced-Lighting/Shadows/Shadow-Mapping</h1>
    320 <p>
    321   Shadows are a result of the absence of light due to occlusion. When a light source's light rays do not hit an object because it gets occluded by some other object, the object is in shadow. Shadows add a great deal of realism to a lit scene and make it easier for a viewer to observe spatial relationships between objects. They give a greater sense of depth to our scene and objects. For example, take a look at the following image of a scene with and without shadows:
    322   
    323 </p>
    324 
    325 <img src="/img/advanced-lighting/shadow_mapping_with_without.png" alt="comparrison of shadows in a scene with and without in OpenGL"/>
    326   
    327 <p>
    328   You can see that with shadows it becomes much more obvious how the objects relate to each other. For instance, the fact that one of the cubes is floating above the others is only really noticeable when we have shadows.
    329 </p>
    330   
    331 <p>
    332   Shadows are a bit tricky to implement though, specifically because in current real-time (rasterized graphics) research a perfect shadow algorithm hasn't been developed yet. There are several good shadow approximation techniques, but they all have their little quirks and annoyances which we have to take into account.
    333 </p>
    334   
    335 <p>
    336   One technique used by most videogames that gives decent results and is relatively easy to implement is <def>shadow mapping</def>. Shadow mapping is not too difficult to understand, doesn't cost too much in performance and quite easily extends into more advanced algorithms (like <a href="https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows" target="_blank">Omnidirectional Shadow Maps</a> and Cascaded Shadow Maps). 
    337 </p>
    338   
    339 <h2>Shadow mapping</h2>
    340 <p>
    341    The idea behind shadow mapping is quite simple: we render the scene from the light's point of view and everything we see from the light's perspective is lit and everything we can't see must be in shadow. Imagine a floor section with a large box between itself and a light source. Since the light source will see this box and not the floor section when looking in its direction that specific floor section should be in shadow. 
    342 </p>
    343   
    344   <img src="/img/advanced-lighting/shadow_mapping_theory.png" class="clean" alt="Shadow mapping illustrated."/>
    345     
    346 <p>
    347    Here all the blue lines represent the fragments that the light source can see. The occluded fragments are shown as black lines: these are rendered as being shadowed. If we were to draw a line or <def>ray</def> from the light source to a fragment on the right-most box we can see the ray first hits the floating container before hitting the right-most container. As a result, the floating container's fragment is lit and the right-most container's fragment is not lit and thus in shadow.
    348 </p>
    349     
    350 <p>
    351   We want to get the point on the ray where it first hit an object and compare this <em>closest point</em> to other points on this ray. We then do a basic test to see if a test point's ray position is further down the ray than the closest point and if so, the test point must be in shadow. Iterating through possibly thousands of light rays from such a light source is an extremely inefficient approach and doesn't lend itself too well for real-time rendering. We can do something similar, but without casting light rays. Instead, we use something we're quite familiar with: the depth buffer.
    352 </p>
    353     
    354 <p>
    355   You may remember from the <a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing" target="_blank">depth testing</a> chapter that a value in the depth buffer corresponds to the depth of a fragment clamped to [0,1] from the camera's point of view. What if we were to render the scene from the light's perspective and store the resulting depth values in a texture? This way, we can sample the closest depth values as seen from the light's perspective. After all, the depth values show the first fragment visible from the light's perspective. We store all these depth values in a texture that we call a <def>depth map</def> or <def>shadow map</def>.
    356 </p>
    357     
    358     <img src="/img/advanced-lighting/shadow_mapping_theory_spaces.png" class="clean" alt="Different coordinate transforms / spaces for shadow mapping."/>
    359       
    360 <p>
    361   The left image shows a directional light source (all light rays are parallel) casting a shadow on the surface below the cube. Using the depth values stored in the depth map we find the closest point and use that to determine whether fragments are in shadow. We create the depth map by rendering the scene (from the light's perspective) using a view and projection matrix specific to that light source. This projection and view matrix together form a transformation \(T\) that transforms any 3D position to the light's (visible) coordinate space.
    362 </p>
    363             
    364 <note>
    365   A directional light doesn't have a position as it's modelled to be infinitely far away. However, for the sake of shadow mapping we need to render the scene from a light's perspective and thus render the scene from a position somewhere along the lines of the light direction.
    366 </note>
    367       
    368  <p>
    369   In the right image we see the same directional light and the viewer. We render a fragment at point \(\bar{\color{red}{P}}\) for which we have to determine whether it is in shadow. To do this, we first transform point \(\bar{\color{red}{P}}\) to the light's coordinate space using \(T\). Since point \(\bar{\color{red}{P}}\) is now as seen from the light's perspective, its <code>z</code> coordinate corresponds to its depth which in this example is <code>0.9</code>. Using point \(\bar{\color{red}{P}}\) we can also index the depth/shadow map to obtain the closest visible depth from the light's perspective, which is at point \(\bar{\color{green}{C}}\) with a sampled depth of <code>0.4</code>. Since indexing the depth map returns a depth smaller than the depth at point \(\bar{\color{red}{P}}\) we can conclude point \(\bar{\color{red}{P}}\) is occluded and thus in shadow. 
    370 </p>
    371 
    372     
    373 <p>
    374   Shadow mapping therefore consists of two passes: first we render the depth map, and in the second pass we render the scene as normal and use the generated depth map to calculate whether fragments are in shadow. It may sound a bit complicated, but as soon as we walk through the technique step-by-step it'll likely start to make sense. 
    375 </p>
    376     
    377 <h2>The depth map</h2>
    378 <p>
    379   The first pass requires us to generate a depth map. The depth map is the depth texture as rendered from the light's perspective that we'll be using for testing for shadows. Because we need to store the rendered result of a scene into a texture we're going to need <a href="https://learnopengl.com/Advanced-OpenGL/Framebuffers" target="_blank">framebuffers</a> again.
    380 </p>
    381       
    382 <p>
    383   First we'll create a framebuffer object for rendering the depth map:
    384 </p>
    385       
    386 <pre><code>
    387 unsigned int depthMapFBO;
    388 <function id='76'>glGenFramebuffers</function>(1, &depthMapFBO);  
    389 </code></pre>
    390       
    391 <p>
    392   Next we create a 2D texture that we'll use as the framebuffer's depth buffer:
    393 </p>
    394       
    395 <pre><code>
    396 const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
    397 
    398 unsigned int depthMap;
    399 <function id='50'>glGenTextures</function>(1, &depthMap);
    400 <function id='48'>glBindTexture</function>(GL_TEXTURE_2D, depthMap);
    401 <function id='52'>glTexImage2D</function>(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 
    402              SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    403 <function id='15'>glTexParameter</function>i(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    404 <function id='15'>glTexParameter</function>i(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    405 <function id='15'>glTexParameter</function>i(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    406 <function id='15'>glTexParameter</function>i(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);  
    407 </code></pre>
    408       
    409 <p>
    410   Generating the depth map shouldn't look too complicated. Because we only care about depth values we specify the texture's formats as <var>GL_DEPTH_COMPONENT</var>. We also give the texture a width and height of <code>1024</code>: this is the resolution of the depth map. 
    411 </p>
    412       
    413 <p>
    414   With the generated depth texture we can attach it as the framebuffer's depth buffer:
    415 </p>
    416 
    417 <pre class="cpp"><code>
    418 <function id='77'>glBindFramebuffer</function>(GL_FRAMEBUFFER, depthMapFBO);
    419 <function id='81'>glFramebufferTexture2D</function>(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
    420 glDrawBuffer(GL_NONE);
    421 glReadBuffer(GL_NONE);
    422 <function id='77'>glBindFramebuffer</function>(GL_FRAMEBUFFER, 0);  
    423 </code></pre>
    424 
    425 <p>
    426   We only need the depth information when rendering the scene from the light's perspective so there is no need for a color buffer. A framebuffer object however is not complete without a color buffer so we need to explicitly tell OpenGL we're not going to render any color data. We do this by setting both the read and draw buffer to <var>GL_NONE</var> with <fun>glDrawBuffer</fun> and <fun>glReadbuffer</fun>. 
    427 </p>
    428       
    429 <p>
    430   With a properly configured framebuffer that renders depth values to a texture we can start the first pass: generate the depth map. When combined with the second pass, the complete rendering stage will look a bit like this:
    431 </p>
    432       
    433 <pre><code>
    434 // 1. first render to depth map
    435 <function id='22'>glViewport</function>(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
    436 <function id='77'>glBindFramebuffer</function>(GL_FRAMEBUFFER, depthMapFBO);
    437     <function id='10'>glClear</function>(GL_DEPTH_BUFFER_BIT);
    438     ConfigureShaderAndMatrices();
    439     RenderScene();
    440 <function id='77'>glBindFramebuffer</function>(GL_FRAMEBUFFER, 0);
    441 // 2. then render scene as normal with shadow mapping (using depth map)
    442 <function id='22'>glViewport</function>(0, 0, SCR_WIDTH, SCR_HEIGHT);
    443 <function id='10'>glClear</function>(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    444 ConfigureShaderAndMatrices();
    445 <function id='48'>glBindTexture</function>(GL_TEXTURE_2D, depthMap);
    446 RenderScene();
    447 </code></pre>
    448       
    449 <p>
    450   This code left out some details, but it'll give you the general idea of shadow mapping. What is important to note here are the calls to <fun><function id='22'>glViewport</function></fun>. Because shadow maps often have a different resolution compared to what we originally render the scene in (usually the window resolution), we need to change the viewport parameters to accommodate for the size of the shadow map. If we forget to update the viewport parameters, the resulting depth map will be either incomplete or too small.
    451 </p>
    452     
    453 <h3>Light space transform</h3>
    454 <p>
    455   An unknown in the previous snippet of code is the <fun>ConfigureShaderAndMatrices</fun> function. In the second pass this is business as usual: make sure proper projection and view matrices are set, and set the relevant model matrices per object. However, in the first pass we need to use a different projection and view matrix to render the scene from the light's point of view.
    456 </p>
    457       
    458 <p>
    459   Because we're modelling a directional light source, all its light rays are parallel. For this reason, we're going to use an orthographic projection matrix for the light source where there is no perspective deform:
    460 </p>
    461 
    462 <pre><code>
    463 float near_plane = 1.0f, far_plane = 7.5f;
    464 glm::mat4 lightProjection = <function id='59'>glm::ortho</function>(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);  
    465 </code></pre>
    466       
    467 <p>
    468   Here is an example orthographic projection matrix as used in this chapter's demo scene. Because a projection matrix indirectly determines the range of what is visible (e.g. what is not clipped) you want to make sure the size of the projection frustum correctly contains the objects you want to be in the depth map. When objects or fragments are not in the depth map they will not produce shadows.
    469 </p>
    470       
    471 <p>
    472   To create a view matrix to transform each object so they're visible from the light's point of view, we're going to use the infamous <fun><function id='62'>glm::lookAt</function></fun> function; this time with the light source's position looking at the scene's center. 
    473 </p>
    474       
    475 <pre><code>
    476 glm::mat4 lightView = <function id='62'>glm::lookAt</function>(glm::vec3(-2.0f, 4.0f, -1.0f), 
    477                                   glm::vec3( 0.0f, 0.0f,  0.0f), 
    478                                   glm::vec3( 0.0f, 1.0f,  0.0f));  
    479 </code></pre>
    480       
    481 <p>
    482   Combining these two gives us a light space transformation matrix that transforms each world-space vector into the space as visible from the light source; exactly what we need to render the depth map.
    483 </p>
    484       
    485 <pre><code>
    486 glm::mat4 lightSpaceMatrix = lightProjection * lightView; 
    487 </code></pre>
    488       
    489 <p>
    490   This <var>lightSpaceMatrix</var> is the transformation matrix that we earlier denoted as \(T\). With this <var>lightSpaceMatrix</var>, we can render the scene as usual as long as we give each shader the light-space equivalents of the projection and view matrices. However, we only care about depth values and not all the expensive fragment (lighting) calculations. To save performance we're going to use a different, but much simpler shader for rendering to the depth map.
    491 </p>
    492       
    493 <h3>Render to depth map</h3>
    494 <p>
    495   When we render the scene from the light's perspective we'd much rather use a simple shader that only transforms the vertices to light space and not much more. For such a simple shader called <var>simpleDepthShader</var> we'll use the following vertex shader:
    496 </p>
    497       
    498 <pre><code>
    499 #version 330 core
    500 layout (location = 0) in vec3 aPos;
    501 
    502 uniform mat4 lightSpaceMatrix;
    503 uniform mat4 model;
    504 
    505 void main()
    506 {
    507     gl_Position = lightSpaceMatrix * model * vec4(aPos, 1.0);
    508 }  
    509 </code></pre>
    510       
    511 <p>
    512   This vertex shader takes a per-object model, a vertex, and transforms all vertices to light space using <var>lightSpaceMatrix</var>.
    513 </p>      
    514       
    515 <p>
    516   Since we have no color buffer and disabled the draw and read buffers, the resulting fragments do not require any processing so we can simply use an empty fragment shader:
    517 </p>
    518 
    519 <pre><code>
    520 #version 330 core
    521 
    522 void main()
    523 {             
    524     // gl_FragDepth = gl_FragCoord.z;
    525 }  
    526 </code></pre>
    527       
    528 <p>
    529   This empty fragment shader does no processing whatsoever, and at the end of its run the depth buffer is updated. We could explicitly set the depth by uncommenting its one line, but this is effectively what happens behind the scene anyways.
    530 </p>
    531       
    532 <p>
    533   Rendering the depth/shadow map now effectively becomes:
    534 </p>
    535       
    536 <pre><code>
    537 simpleDepthShader.use();
    538 <function id='44'>glUniform</function>Matrix4fv(lightSpaceMatrixLocation, 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
    539 
    540 <function id='22'>glViewport</function>(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
    541 <function id='77'>glBindFramebuffer</function>(GL_FRAMEBUFFER, depthMapFBO);
    542     <function id='10'>glClear</function>(GL_DEPTH_BUFFER_BIT);
    543     RenderScene(simpleDepthShader);
    544 <function id='77'>glBindFramebuffer</function>(GL_FRAMEBUFFER, 0);  
    545 </code></pre>
    546       
    547 <p>
    548   Here the <fun>RenderScene</fun> function takes a shader program, calls all relevant drawing functions and sets the corresponding model matrices where necessary. 
    549 </p>
    550 
    551 <p>
    552   The result is a nicely filled depth buffer holding the closest depth of each visible fragment from the light's perspective. By rendering this texture onto a 2D quad that fills the screen (similar to what we did in the post-processing section at the end of the <a href="https://learnopengl.com/Advanced-OpenGL/Framebuffers" target="_blank">framebuffers</a> chapter) we get something like this:
    553 </p>
    554       
    555 <img src="/img/advanced-lighting/shadow_mapping_depth_map.png" class="clean" alt="Depth (or shadow) map of shadow mapping technique"/>
    556       
    557 <p>
    558   For rendering the depth map onto a quad we used the following fragment shader:
    559 </p>
    560   
    561 <pre><code>
    562 #version 330 core
    563 out vec4 FragColor;
    564   
    565 in vec2 TexCoords;
    566 
    567 uniform sampler2D depthMap;
    568 
    569 void main()
    570 {             
    571     float depthValue = texture(depthMap, TexCoords).r;
    572     FragColor = vec4(vec3(depthValue), 1.0);
    573 }  
    574 </code></pre>
    575   
    576 <p>
    577   Note that there are some subtle changes when displaying depth using a perspective projection matrix instead of an orthographic projection matrix as depth is non-linear when using perspective projection. At the end of this chapter we'll discuss some of these subtle differences.
    578 </p>
    579   
    580 <p>
    581   You can find the source code for rendering a scene to a depth map <a href="/code_viewer_gh.php?code=src/5.advanced_lighting/3.1.1.shadow_mapping_depth/shadow_mapping_depth.cpp" target="_blank">here</a>.
    582 </p>
    583       
    584 <h2>Rendering shadows</h2>  
    585 <p>
    586   With a properly generated depth map we can start rendering the actual shadows. The code to check if a fragment is in shadow is (quite obviously) executed in the fragment shader, but we do the light-space transformation in the vertex shader:
    587 </p>
    588   
    589 <pre><code>
    590 #version 330 core
    591 layout (location = 0) in vec3 aPos;
    592 layout (location = 1) in vec3 aNormal;
    593 layout (location = 2) in vec2 aTexCoords;
    594 
    595 out VS_OUT {
    596     vec3 FragPos;
    597     vec3 Normal;
    598     vec2 TexCoords;
    599     vec4 FragPosLightSpace;
    600 } vs_out;
    601 
    602 uniform mat4 projection;
    603 uniform mat4 view;
    604 uniform mat4 model;
    605 uniform mat4 lightSpaceMatrix;
    606 
    607 void main()
    608 {    
    609     vs_out.FragPos = vec3(model * vec4(aPos, 1.0));
    610     vs_out.Normal = transpose(inverse(mat3(model))) * aNormal;
    611     vs_out.TexCoords = aTexCoords;
    612     vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
    613     gl_Position = projection * view * vec4(vs_out.FragPos, 1.0);
    614 }
    615 </code></pre>
    616   
    617 <p>
    618   What is new here is the extra output vector <var>FragPosLightSpace</var>. We take the same <var>lightSpaceMatrix</var> (used to transform vertices to light space in the depth map stage) and transform the world-space vertex position to light space for use in the fragment shader. 
    619 </p>
    620   
    621 <p>
    622   The main fragment shader we'll use to render the scene uses the Blinn-Phong lighting model. Within the fragment shader we then calculate a <var>shadow</var> value that is either <code>1.0</code> when the fragment is in shadow or <code>0.0</code> when not in shadow. The resulting <var>diffuse</var> and <var>specular</var> components are then multiplied by this shadow component. Because shadows are rarely completely dark (due to light scattering) we leave the <var>ambient</var> component out of the shadow multiplications. 
    623 </p>
    624   
    625 <pre><code>
    626 #version 330 core
    627 out vec4 FragColor;
    628 
    629 in VS_OUT {
    630     vec3 FragPos;
    631     vec3 Normal;
    632     vec2 TexCoords;
    633     vec4 FragPosLightSpace;
    634 } fs_in;
    635 
    636 uniform sampler2D diffuseTexture;
    637 uniform sampler2D shadowMap;
    638 
    639 uniform vec3 lightPos;
    640 uniform vec3 viewPos;
    641 
    642 float ShadowCalculation(vec4 fragPosLightSpace)
    643 {
    644     [...]
    645 }
    646 
    647 void main()
    648 {           
    649     vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;
    650     vec3 normal = normalize(fs_in.Normal);
    651     vec3 lightColor = vec3(1.0);
    652     // ambient
    653     vec3 ambient = 0.15 * color;
    654     // diffuse
    655     vec3 lightDir = normalize(lightPos - fs_in.FragPos);
    656     float diff = max(dot(lightDir, normal), 0.0);
    657     vec3 diffuse = diff * lightColor;
    658     // specular
    659     vec3 viewDir = normalize(viewPos - fs_in.FragPos);
    660     float spec = 0.0;
    661     vec3 halfwayDir = normalize(lightDir + viewDir);  
    662     spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
    663     vec3 specular = spec * lightColor;    
    664     // calculate shadow
    665     float shadow = ShadowCalculation(fs_in.FragPosLightSpace);       
    666     vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;    
    667     
    668     FragColor = vec4(lighting, 1.0);
    669 }
    670 </code></pre>
    671   
    672 <p>
    673   The fragment shader is largely a copy from what we used in the <a href="https://learnopengl.com/Advanced-Lighting/Advanced-Lighting" target="_blank">advanced lighting</a> chapter, but with an added shadow calculation. We declared a function <fun>ShadowCalculation</fun> that does most of the shadow work. At the end of the fragment shader, we multiply the diffuse and specular contributions by the inverse of the <var>shadow</var> component e.g. how much the fragment is <em>not</em> in shadow. This fragment shader takes as extra input the light-space fragment position and the depth map generated from the first render pass.
    674 </p>
    675 
    676 <p>
    677   The first thing to do to check whether a fragment is in shadow, is transform the light-space fragment position in clip-space to normalized device coordinates. When we output a clip-space vertex position to <var>gl_Position</var> in the vertex shader, OpenGL automatically does a perspective divide e.g. transform clip-space coordinates in the range [<code>-w</code>,<code>w</code>] to [<code>-1</code>,<code>1</code>] by dividing the <code>x</code>, <code>y</code> and <code>z</code> component by the vector's <code>w</code> component. As the clip-space <var>FragPosLightSpace</var> is not passed to the fragment shader through <var>gl_Position</var>, we have to do this perspective divide ourselves:
    678 </p>
    679   
    680 <pre><code>
    681 float ShadowCalculation(vec4 fragPosLightSpace)
    682 {
    683     // perform perspective divide
    684     vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    685     [...]
    686 }
    687 </code></pre>
    688   
    689 <p>
    690   This returns the fragment's light-space position in the range [<code>-1</code>,<code>1</code>].
    691 </p>
    692 
    693   <note>
    694     When using an orthographic projection matrix the <code>w</code> component of a vertex remains untouched so this step is actually quite meaningless. However, it is necessary when using perspective projection so keeping this line ensures it works with both projection matrices.
    695   </note>
    696   
    697 <p>
    698     Because the depth from the depth map is in the range [<code>0</code>,<code>1</code>] and we also want to use <var>projCoords</var> to sample from the depth map, we transform the NDC coordinates to the range [<code>0</code>,<code>1</code>]:
    699 </p>
    700   
    701 <pre class="cpp"><code>
    702 projCoords = projCoords * 0.5 + 0.5; 
    703 </code></pre>
    704   
    705 <p>
    706   With these projected coordinates we can sample the depth map as the resulting [<code>0</code>,<code>1</code>] coordinates from <var>projCoords</var> directly correspond to the transformed NDC coordinates from the first render pass. This gives us the closest depth from the light's point of view:
    707 </p>
    708   
    709 <pre><code>
    710 float closestDepth = texture(shadowMap, projCoords.xy).r;   
    711 </code></pre>
    712   
    713 <p>
    714   To get the current depth at this fragment we simply retrieve the projected vector's <code>z</code> coordinate which equals the depth of this fragment from the light's perspective.
    715 </p>
    716   
    717 <pre><code>
    718 float currentDepth = projCoords.z;  
    719 </code></pre>
    720   
    721 <p>
    722   The actual comparison is then simply a check whether <var>currentDepth</var> is higher than <var>closestDepth</var> and if so, the fragment is in shadow:
    723 </p>
    724   
    725 <pre><code>
    726 float shadow = currentDepth > closestDepth  ? 1.0 : 0.0;  
    727 </code></pre>
    728   
    729 <p>
    730   The complete <fun>ShadowCalculation</fun> function then becomes:
    731 </p>
    732   
    733 <pre><code>
    734 float ShadowCalculation(vec4 fragPosLightSpace)
    735 {
    736     // perform perspective divide
    737     vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    738     // transform to [0,1] range
    739     projCoords = projCoords * 0.5 + 0.5;
    740     // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
    741     float closestDepth = texture(shadowMap, projCoords.xy).r; 
    742     // get depth of current fragment from light's perspective
    743     float currentDepth = projCoords.z;
    744     // check whether current frag pos is in shadow
    745     float shadow = currentDepth > closestDepth  ? 1.0 : 0.0;
    746 
    747     return shadow;
    748 }  
    749 </code></pre>
    750   
    751 <p>
    752   Activating this shader, binding the proper textures, and activating the default projection and view matrices in the second render pass should give you a result similar to the image below:
    753 </p>
    754   
    755   <img src="/img/advanced-lighting/shadow_mapping_shadows.png" class="clean" alt="Shadow mapped images, without improvements."/>
    756     
    757 <p>
    758   If you did things right you should indeed see (albeit with quite a few artifacts) shadows on the floor and the cubes. You can find the source code of the demo application <a href="/code_viewer_gh.php?code=src/5.advanced_lighting/3.1.2.shadow_mapping_base/shadow_mapping_base.cpp" target="_blank">here</a>.
    759 </p>    
    760   
    761 <h2>Improving shadow maps</h2>
    762 <p>
    763   We managed to get the basics of shadow mapping working, but as you can we're not there yet due to several (clearly visible) artifacts related to shadow mapping we need to fix. We'll focus on fixing these artifacts in the next sections.
    764 </p> 
    765     
    766 <h3>Shadow acne</h3>
    767 <p>
    768     It is obvious something is wrong from the previous image. A closer zoom shows us a very obvious Moiré-like pattern:
    769 </p>
    770     
    771     <img src="/img/advanced-lighting/shadow_mapping_acne.png" alt="Image of shadow acne as Moiré pattern with shadow mapping"/>
    772       
    773 <p>
    774   We can see a large part of the floor quad rendered with obvious black lines in an alternating fashion. This shadow mapping artifact is called <def>shadow acne</def> and can be explained by the following image:
    775 </p>
    776       
    777 <img src="/img/advanced-lighting/shadow_mapping_acne_diagram.png" class="clean" alt="Shadow acne explained"/>
    778         
    779 <p>
    780   Because the shadow map is limited by resolution, multiple fragments can sample the same value from the depth map when they're relatively far away from the light source. The image shows the floor where each yellow tilted panel represents a single texel of the depth map. As you can see, several fragments sample the same depth sample. 
    781   </p>
    782   
    783 <p>
    784   While this is generally okay, it becomes an issue when the light source looks at an angle towards the surface as in that case the depth map is also rendered from an angle. Several fragments then access the same tilted depth texel while some are above and some below the floor; we get a shadow discrepancy. Because of this, some fragments are considered to be in shadow and some are not, giving the striped pattern from the image.
    785 </p>
    786   
    787 <p>
    788   We can solve this issue with a small little hack called a <def>shadow bias</def> where we simply offset the depth of the surface (or the shadow map) by a small bias amount such that the fragments are not incorrectly considered above the surface. 
    789 </p>
    790   
    791  <img src="/img/advanced-lighting/shadow_mapping_acne_bias.png" class="clean" alt="Shadow mapping, with shadow acne fixed using shadow bias."/>
    792    
    793 <p>
    794   With the bias applied, all the samples get a depth smaller than the surface's depth and thus the entire surface is correctly lit without any shadows. We can implement such a bias as follows:
    795 </p>
    796   
    797 <pre><code>
    798 float bias = 0.005;
    799 float shadow = currentDepth - bias > closestDepth  ? 1.0 : 0.0;  
    800 </code></pre>
    801   
    802 <p>
    803   A shadow bias of <code>0.005</code> solves the issues of our scene by a large extent, but you can imagine the bias value is highly dependent on the angle between the light source and the surface. If the surface would have a steep angle to the light source, the shadows may still display shadow acne. A more solid approach would be to change the amount of bias based on the surface angle towards the light: something we can solve with the dot product:
    804 </p>
    805   
    806 <pre><code>
    807 float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);  
    808 </code></pre>
    809   
    810 <p>
    811   Here we have a maximum bias of <code>0.05</code> and a minimum of <code>0.005</code> based on the surface's normal and light direction. This way, surfaces like the floor that are almost perpendicular to the light source get a small bias, while surfaces like the cube's side-faces get a much larger bias. The following image shows the same scene but now with a shadow bias:
    812 </p>
    813   
    814    
    815   <img src="/img/advanced-lighting/shadow_mapping_with_bias.png" class="clean" alt="Shadow mapped images, with (sloped) shadow bias applied."/>
    816   
    817 <p>
    818   Choosing the correct bias value(s) requires some tweaking as this will be different for each scene, but most of the time it's simply a matter of slowly incrementing the bias until all acne is removed.
    819 </p>
    820   
    821 <h3>Peter panning</h3>
    822 <p>
    823   A disadvantage of using a shadow bias is that you're applying an offset to the actual depth of objects. As a result, the bias may become large enough to see a visible offset of shadows compared to the actual object locations as you can see below (with an exaggerated bias value):
    824 </p>
    825   
    826   <img src="/img/advanced-lighting/shadow_mapping_peter_panning.png" class="clean" alt="Peter panning with shadow mapping implementation"/>
    827     
    828 <p>
    829   This shadow artifact is called <def>peter panning</def> since objects seem slightly <em>detached</em> from their shadows. We can use a little trick to solve most of the peter panning issue by using front face culling when rendering the depth map. You may remember from the <a href="https://learnopengl.com/Advanced-OpenGL/Face-Culling" target="_blank">face culling</a> chapter that OpenGL by default culls back-faces. By telling OpenGL we want to cull front faces during the shadow map stage we're switching that order around. 
    830 </p>
    831     
    832 <p>
    833   Because we only need depth values for the depth map it shouldn't matter for solid objects whether we take the depth of their front faces or their back faces. Using their back face depths doesn't give wrong results as it doesn't matter if we have shadows inside objects; we can't see there anyways.
    834 </p>
    835     
    836     <img src="/img/advanced-lighting/shadow_mapping_culling.png" class="clean" alt="Shadow mapping showing how front face culling helps solve peter panning."/>
    837     
    838 <p>
    839   To fix peter panning we cull all front faces during the shadow map generation. Note that you need to enable <var>GL_CULL_FACE</var> first.
    840 </p>
    841     
    842 <pre><code>
    843 <function id='74'>glCullFace</function>(GL_FRONT);
    844 RenderSceneToDepthMap();
    845 <function id='74'>glCullFace</function>(GL_BACK); // don't forget to reset original culling face
    846 </code></pre>
    847     
    848 <p>
    849   This effectively solves the peter panning issues, but <strong>only for solid</strong> objects that actually have an inside without openings. In our scene for example, this works perfectly fine on the cubes. However, on the floor it won't work as well as culling the front face completely removes the floor from the equation. The floor is a single plane and would thus be completely culled. If one wants to solve peter panning with this trick, care has to be taken to only cull the front faces of objects where it makes sense. 
    850 </p>    
    851     
    852 <p>
    853   Another consideration is that objects that are close to the shadow receiver (like the distant cube) may still give incorrect results. However, with normal bias values you can generally avoid peter panning. 
    854 </p>
    855       
    856 <h3>Over sampling</h3>
    857 <p>
    858   Another visual discrepancy which you may like or dislike is that regions outside the light's visible frustum are considered to be in shadow while they're (usually) not. This happens because projected coordinates outside the light's frustum are higher than <code>1.0</code> and will thus sample the depth texture outside its default range of [<code>0</code>,<code>1</code>]. Based on the texture's wrapping method, we will get incorrect depth results not based on the real depth values from the light source.
    859 </p>
    860       
    861        <img src="/img/advanced-lighting/shadow_mapping_outside_frustum.png" class="clean" alt="Shadow mapping with edges of depth map visible, texture wrapping"/>
    862 <p>
    863   You can see in the image that there is some sort of imaginary region of light, and a large part outside this area is in shadow; this area represents the size of the depth map projected onto the floor. The reason this happens is that we earlier set the depth map's wrapping options to <var>GL_REPEAT</var>.
    864 </p>
    865          
    866 <p>
    867   What we'd rather have is that all coordinates outside the depth map's range have a depth of <code>1.0</code> which as a result means these coordinates will never be in shadow (as no object will have a depth larger than <code>1.0</code>). We can do this by configuring a texture border color and set the depth map's texture wrap options to <var>GL_CLAMP_TO_BORDER</var>:
    868 </p>
    869       
    870 <pre><code>
    871 <function id='15'>glTexParameter</function>i(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    872 <function id='15'>glTexParameter</function>i(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    873 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    874 <function id='15'>glTexParameter</function>fv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);  
    875 </code></pre>
    876       
    877 <p>
    878   Now whenever we sample outside the depth map's [<code>0</code>,<code>1</code>] coordinate range, the <fun>texture</fun> function will always return a depth of <code>1.0</code>, producing a <var>shadow</var> value of <code>0.0</code>. The result now looks more plausible:
    879 </p>
    880       
    881       <img src="/img/advanced-lighting/shadow_mapping_clamp_edge.png" class="clean" alt="Shadow mapping with texture wrapping set to clamp to border color"/>
    882         
    883 <p>
    884   There seems to still be one part showing a dark region. Those are the coordinates outside the far plane of the light's orthographic frustum. You can see that this dark region always occurs at the far end of the light source's frustum by looking at the shadow directions.
    885 </p>
    886         
    887 <p>
    888    A light-space projected fragment coordinate is further than the light's far plane when its <code>z</code> coordinate is larger than <code>1.0</code>. In that case the <var>GL_CLAMP_TO_BORDER</var> wrapping method doesn't work anymore as we compare the coordinate's <code>z</code> component with the depth map values; this always returns true for <code>z</code> larger than <code>1.0</code>.
    889 </p>
    890         
    891 <p>
    892   The fix for this is also relatively easy as we simply force the <var>shadow</var> value to <code>0.0</code> whenever the projected vector's <code>z</code> coordinate is larger than <code>1.0</code>:
    893 </p>
    894  
    895 <pre><code>
    896 float ShadowCalculation(vec4 fragPosLightSpace)
    897 {
    898     [...]
    899     if(projCoords.z > 1.0)
    900         shadow = 0.0;
    901     
    902     return shadow;
    903 }  
    904 </code></pre>
    905        
    906 <p>
    907   Checking the far plane and clamping the depth map to a manually specified border color solves the over-sampling of the depth map. This finally gives us the result we are looking for:
    908 </p>
    909         
    910 <img src="/img/advanced-lighting/shadow_mapping_over_sampling_fixed.png" class="clean" alt="Shadow mapping with over sampling fixed with border clamp to color and far plane fix."/>               
    911         
    912 <p>
    913   The result of all this does mean that we only have shadows where the projected fragment coordinates sit inside the depth map range so anything outside the light frustum will have no visible shadows. As games usually make sure this only occurs in the distance it is a much more plausible effect than the obvious black regions we had before.
    914 </p>      
    915   
    916 <h2>PCF</h2>
    917 <p>
    918   The shadows right now are a nice addition to the scenery, but it's still not exactly what we want. If you were to zoom in on the shadows the resolution dependency of shadow mapping quickly becomes apparent.
    919 </p>
    920   
    921   <img src="/img/advanced-lighting/shadow_mapping_zoom.png" alt="Zoomed in of shadows with shadow mappign technique shows jagged edges."/>
    922     
    923 <p>
    924   Because the depth map has a fixed resolution, the depth frequently usually spans more than one fragment per texel. As a result, multiple fragments sample the same depth value from the depth map and come to the same shadow conclusions, which produces these jagged blocky edges.
    925 </p>      
    926     
    927 <p>
    928   You can reduce these blocky shadows by increasing the depth map resolution, or by trying to fit the light frustum as closely to the scene as possible.
    929 </p>
    930     
    931 <p>
    932   Another (partial) solution to these jagged edges is called PCF, or <def>percentage-closer filtering</def>, which is a term that hosts many different filtering functions that produce <em>softer</em> shadows, making them appear less blocky or hard. The idea is to sample more than once from the depth map, each time with slightly different texture coordinates. For each individual sample we check whether it is in shadow or not. All the sub-results are then combined and averaged and we get a nice soft looking shadow.
    933 </p>
    934     
    935 <p>
    936   One simple implementation of PCF is to simply sample the surrounding texels of the depth map and average the results:
    937 </p>
    938     
    939 <pre><code>
    940 float shadow = 0.0;
    941 vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
    942 for(int x = -1; x &lt;= 1; ++x)
    943 {
    944     for(int y = -1; y &lt;= 1; ++y)
    945     {
    946         float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; 
    947         shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;        
    948     }    
    949 }
    950 shadow /= 9.0;
    951 </code></pre>
    952     
    953 <p>
    954   Here <fun>textureSize</fun> returns a <code>vec2</code> of the width and height of the given sampler texture at mipmap level <code>0</code>. 1 divided over this returns the size of a single texel that we use to offset the texture coordinates, making sure each new sample samples a different depth value. Here we sample 9 values around the projected coordinate's <code>x</code> and <code>y</code> value, test for shadow occlusion, and finally average the results by the total number of samples taken.
    955 </p>
    956     
    957 <p>
    958   By using more samples and/or varying the <var>texelSize</var> variable you can increase the quality of the soft shadows. Below you can see the shadows with simple PCF applied:
    959 </p>
    960     
    961     <img src="/img/advanced-lighting/shadow_mapping_soft_shadows.png" alt="Soft shadows with PCF using shadow mapping"/>
    962       
    963 <p>
    964   From a distance the shadows look a lot better and less hard. If you zoom in you can still see the resolution artifacts of shadow mapping, but in general this gives good results for most applications. 
    965 </p>
    966       
    967 <p>
    968   You can find the complete source code of the example <a href="/code_viewer_gh.php?code=src/5.advanced_lighting/3.1.3.shadow_mapping/shadow_mapping.cpp" target="_blank">here</a>.
    969 </p>
    970       
    971 <p>
    972   There is actually much more to PCF and quite a few techniques to considerably improve the quality of soft shadows, but for the sake of this chapter's length we'll leave that for a later discussion.
    973 </p>
    974     
    975 <h2>Orthographic vs perspective</h2>
    976 <p>
    977   There is a difference between rendering the depth map with an orthographic or a perspective projection matrix. An orthographic projection matrix does not deform the scene with perspective so all view/light rays are parallel. This makes it a great projection matrix for directional lights. A perspective projection matrix however does deform all vertices based on perspective which gives different results. The following image shows the different shadow regions of both projection methods:
    978 </p>
    979       
    980 <img src="/img/advanced-lighting/shadow_mapping_projection.png" class="clean" alt="Shadow mapping difference between orthographic and perspective projection."/>
    981   
    982 <p>
    983   Perspective projections make most sense for light sources that have actual locations, unlike directional lights. Perspective projections are most often used with spotlights and point lights, while orthographic projections are used for directional lights.
    984 </p>
    985   
    986 <p>
    987   Another subtle difference with using a perspective projection matrix is that visualizing the depth buffer will often give an almost completely white result. This happens because with perspective projection the depth is transformed to non-linear depth values with most of its noticeable range close to the near plane. To be able to properly view the depth values as we did with the orthographic projection you first want to transform the non-linear depth values to linear as we discussed in the <a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing" target="_blank">depth testing</a> chapter:
    988 </p>
    989   
    990 <pre><code>
    991 #version 330 core
    992 out vec4 FragColor;
    993   
    994 in vec2 TexCoords;
    995 
    996 uniform sampler2D depthMap;
    997 uniform float near_plane;
    998 uniform float far_plane;
    999 
   1000 float LinearizeDepth(float depth)
   1001 {
   1002     float z = depth * 2.0 - 1.0; // Back to NDC 
   1003     return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane));
   1004 }
   1005 
   1006 void main()
   1007 {             
   1008     float depthValue = texture(depthMap, TexCoords).r;
   1009     FragColor = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective
   1010     // FragColor = vec4(vec3(depthValue), 1.0); // orthographic
   1011 }  
   1012 </code></pre>
   1013   
   1014 <p>
   1015   This shows depth values similar to what we've seen with orthographic projection. Note that this is only useful for debugging; the depth checks remain the same with orthographic or projection matrices as the relative depths do not change.
   1016 </p>
   1017 
   1018 <h2>Additional resources</h2>
   1019   <ul>
   1020   <li><a href="http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/" target="_blank">Tutorial 16 : Shadow mapping</a>: similar shadow mapping tutorial by opengl-tutorial.org with a few extra notes.</li>
   1021     <li><a href="http://ogldev.atspace.co.uk/www/tutorial23/tutorial23.html" target="_blank">Shadow Mapping - Part 1</a>: another shadow mapping tutorial by ogldev.</li>
   1022     <li><a href="https://www.youtube.com/watch?v=EsccgeUpdsM" target="_blank">How Shadow Mapping Works</a>: a 3-part YouTube tutorial by TheBennyBox on shadow mapping and its implementation.</li>
   1023     <li><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ee416324%28v=vs.85%29.aspx" target="_blank">Common Techniques to Improve Shadow Depth Maps</a>: a great article by Microsoft listing a large number of techniques to improve the quality of shadow maps.
   1024 </ul>       
   1025 
   1026     </div>
   1027     
   1028     <div id="hover">
   1029         HI
   1030     </div>
   1031    <!-- 728x90/320x50 sticky footer -->
   1032 <div id="waldo-tag-6196"></div>
   1033 
   1034    <div id="disqus_thread"></div>
   1035 
   1036     
   1037 
   1038 
   1039 </div> <!-- container div -->
   1040 
   1041 
   1042 </div> <!-- super container div -->
   1043 </body>
   1044 </html>
   1045 	</main>
   1046 </body>
   1047 </html>