<metaproperty="article:modified_time"content="2021-11-24T22:56:19.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Dependencies and the window"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/beginner/tutorial1-window/"><metaname="twitter:title"content="Dependencies and the window"><metaname="twitter:url"content="/beginner/tutorial1-window/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2021-11-24T22:58:49.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Dependencies and the window"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/beginner/tutorial1-window/"><metaname="twitter:title"content="Dependencies and the window"><metaname="twitter:url"content="/beginner/tutorial1-window/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
</code></pre></div><p>All this does is create a window, and keep it open until user closes it, or presses escape. Next tutorial we'll actually start using wgpu!</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial1-window/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>All this does is create a window, and keep it open until user closes it, or presses escape. Next tutorial we'll actually start using wgpu!</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial1-window/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>The <code>RenderPassColorAttachment</code> has the <code>view</code> field which informs <code>wgpu</code> what texture to save the colors to. In this case we specify <code>frame.view</code> that we created using <code>surface.get_current_texture()</code>. This means that any colors we draw to this attachment will get drawn to the screen.</p><p>The <code>resolve_target</code> is the texture that will receive the resolved output. This will be the same as <code>view</code> unless multisampling is enabled. We don't need to specify this, so we leave it as <code>None</code>.</p><p>The <code>ops</code> field takes a <code>wpgu::Operations</code> object. This tells wgpu what to do with the colors on the screen (specified by <code>frame.view</code>). The <code>load</code> field tells wgpu how to handle colors stored from the previous frame. Currently we are clearing the screen with a bluish color. The <code>store</code> field tells wgpu with we want to store the rendered results to the <code>Texture</code> behind our <code>TextureView</code> (in this case it's the <code>SurfaceTexture</code>). We use <code>true</code> as we do want to store our render results. There are cases when you wouldn't want to but those</p><divclass="note"><p>It's not uncommon to not clear the screen if the screen is going to be completely covered up with objects. If your scene doesn't cover the entire screen however you can end up with something like this.</p><p><imgsrc="/learn-wgpu/assets/img/no-clear.753f913f.png"alt="./no-clear.png"></p></div><h2id="validation-errors"><ahref="#validation-errors"class="header-anchor">#</a> Validation Errors?</h2><p>If wgpu is using Vulkan on your machine, you may run into validation errors if you are running an older version of the Vulkan SDK. You should be using at least version <code>1.2.182</code> as older versions can give out some false positives. If errors persist, you may have encountered a bug in wgpu. You can post an issue at <ahref="https://github.com/gfx-rs/wgpu"target="_blank"rel="noopener noreferrer">https://github.com/gfx-rs/wgpu<svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Modify the <code>input()</code> method to capture mouse events, and update the clear color using that. <em>Hint: you'll probably need to use <code>WindowEvent::CursorMoved</code></em>.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial2-surface/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>The <code>RenderPassColorAttachment</code> has the <code>view</code> field which informs <code>wgpu</code> what texture to save the colors to. In this case we specify <code>frame.view</code> that we created using <code>surface.get_current_texture()</code>. This means that any colors we draw to this attachment will get drawn to the screen.</p><p>The <code>resolve_target</code> is the texture that will receive the resolved output. This will be the same as <code>view</code> unless multisampling is enabled. We don't need to specify this, so we leave it as <code>None</code>.</p><p>The <code>ops</code> field takes a <code>wpgu::Operations</code> object. This tells wgpu what to do with the colors on the screen (specified by <code>frame.view</code>). The <code>load</code> field tells wgpu how to handle colors stored from the previous frame. Currently we are clearing the screen with a bluish color. The <code>store</code> field tells wgpu with we want to store the rendered results to the <code>Texture</code> behind our <code>TextureView</code> (in this case it's the <code>SurfaceTexture</code>). We use <code>true</code> as we do want to store our render results. There are cases when you wouldn't want to but those</p><divclass="note"><p>It's not uncommon to not clear the screen if the screen is going to be completely covered up with objects. If your scene doesn't cover the entire screen however you can end up with something like this.</p><p><imgsrc="/learn-wgpu/assets/img/no-clear.753f913f.png"alt="./no-clear.png"></p></div><h2id="validation-errors"><ahref="#validation-errors"class="header-anchor">#</a> Validation Errors?</h2><p>If wgpu is using Vulkan on your machine, you may run into validation errors if you are running an older version of the Vulkan SDK. You should be using at least version <code>1.2.182</code> as older versions can give out some false positives. If errors persist, you may have encountered a bug in wgpu. You can post an issue at <ahref="https://github.com/gfx-rs/wgpu"target="_blank"rel="noopener noreferrer">https://github.com/gfx-rs/wgpu<svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Modify the <code>input()</code> method to capture mouse events, and update the clear color using that. <em>Hint: you'll probably need to use <code>WindowEvent::CursorMoved</code></em>.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial2-surface/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
<metaproperty="article:modified_time"content="2021-11-24T22:56:19.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Textures and bind groups"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/beginner/tutorial5-textures/"><metaname="twitter:title"content="Textures and bind groups"><metaname="twitter:url"content="/beginner/tutorial5-textures/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2021-11-24T22:58:49.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Textures and bind groups"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/beginner/tutorial5-textures/"><metaname="twitter:title"content="Textures and bind groups"><metaname="twitter:url"content="/beginner/tutorial5-textures/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
</code></pre></div><p>Phew!</p><p>With these changes in place, the code should be working the same as it was before, but we now have a much easier way to create textures.</p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Create another texture and swap it out when you press the space key.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial5-textures/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>Phew!</p><p>With these changes in place, the code should be working the same as it was before, but we now have a much easier way to create textures.</p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Create another texture and swap it out when you press the space key.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial5-textures/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
<metaproperty="article:modified_time"content="2021-11-24T22:56:19.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Uniform buffers and a 3d camera"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/beginner/tutorial6-uniforms/"><metaname="twitter:title"content="Uniform buffers and a 3d camera"><metaname="twitter:url"content="/beginner/tutorial6-uniforms/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2021-11-24T22:58:49.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Uniform buffers and a 3d camera"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/beginner/tutorial6-uniforms/"><metaname="twitter:title"content="Uniform buffers and a 3d camera"><metaname="twitter:url"content="/beginner/tutorial6-uniforms/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
</code></pre></div><p>That's all we need to do. If you run the code now you should see a pentagon with our tree texture that you can rotate around and zoom into with the wasd/arrow keys.</p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Have our model rotate on it's own independently of the the camera. <em>Hint: you'll need another matrix for this.</em></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial6-uniforms/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>That's all we need to do. If you run the code now you should see a pentagon with our tree texture that you can rotate around and zoom into with the wasd/arrow keys.</p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Have our model rotate on it's own independently of the the camera. <em>Hint: you'll need another matrix for this.</em></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial6-uniforms/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>With all that done, we should have a forest of trees!</p><p><imgsrc="/learn-wgpu/assets/img/forest.5c5cf3ad.png"alt="./forest.png"></p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Modify the position and/or rotation of the instances every frame.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial7-instancing/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>With all that done, we should have a forest of trees!</p><p><imgsrc="/learn-wgpu/assets/img/forest.5c5cf3ad.png"alt="./forest.png"></p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Modify the position and/or rotation of the instances every frame.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial7-instancing/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>And that's all we have to do! No shader code needed! If you run the application, the depth issues will be fixed.</p><p><imgsrc="/learn-wgpu/assets/img/forest_fixed.a77f70f6.png"alt="forest_fixed.png"></p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Since the depth buffer is a texture, we can sample it in the shader. Because it's a depth texture, we'll have to use the <code>samplerShadow</code> uniform type and the <code>sampler2DShadow</code> function instead of <code>sampler</code>, and <code>sampler2D</code> respectively. Create a bind group for the depth texture (or reuse an existing one), and render it to the screen.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial8-depth/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>And that's all we have to do! No shader code needed! If you run the application, the depth issues will be fixed.</p><p><imgsrc="/learn-wgpu/assets/img/forest_fixed.a77f70f6.png"alt="forest_fixed.png"></p><h2id="challenge"><ahref="#challenge"class="header-anchor">#</a> Challenge</h2><p>Since the depth buffer is a texture, we can sample it in the shader. Because it's a depth texture, we'll have to use the <code>samplerShadow</code> uniform type and the <code>sampler2DShadow</code> function instead of <code>sampler</code>, and <code>sampler2D</code> respectively. Create a bind group for the depth texture (or reuse an existing one), and render it to the screen.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial8-depth/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>The <code>load</code> method will be useful when we load the textures for our models, as <code>include_bytes!</code> requires that we know the name of the file at compile time which we can't really guarantee with model textures.</p><p>While we're at it let's import <code>texture.rs</code> in <code>model.rs</code>.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">use</span><spanclass="token keyword">crate</span><spanclass="token module-declaration namespace"><spanclass="token punctuation">::</span>texture</span><spanclass="token punctuation">;</span>
</code></pre></div><p>The <code>load</code> method will be useful when we load the textures for our models, as <code>include_bytes!</code> requires that we know the name of the file at compile time which we can't really guarantee with model textures.</p><p>While we're at it let's import <code>texture.rs</code> in <code>model.rs</code>.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">use</span><spanclass="token keyword">crate</span><spanclass="token module-declaration namespace"><spanclass="token punctuation">::</span>texture</span><spanclass="token punctuation">;</span>
</code></pre></div><p>We also need to make a subtle change on <code>from_image()</code> method in <code>texture.rs</code>. PNGs work fine with <code>as_rgba8()</code>, as they have an alpha channel. But, JPEGs don't have an alpha channel, and the code would panic if we try to call <code>as_rgba8()</code> on the JPEG texture image we are going to use. Instead, we can use <code>to_rgba8()</code> to handle such an image.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">let</span> rgba <spanclass="token operator">=</span> img<spanclass="token punctuation">.</span><spanclass="token function">to_rgba8</span><spanclass="token punctuation">(</span><spanclass="token punctuation">)</span><spanclass="token punctuation">;</span>
</code></pre></div><p>We also need to make a subtle change on <code>from_image()</code> method in <code>texture.rs</code>. PNGs work fine with <code>as_rgba8()</code>, as they have an alpha channel. But, JPEGs don't have an alpha channel, and the code would panic if we try to call <code>as_rgba8()</code> on the JPEG texture image we are going to use. Instead, we can use <code>to_rgba8()</code> to handle such an image, which will generate a new image buffer with alpha channel even if the original image does not have one.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">let</span> rgba <spanclass="token operator">=</span> img<spanclass="token punctuation">.</span><spanclass="token function">to_rgba8</span><spanclass="token punctuation">(</span><spanclass="token punctuation">)</span><spanclass="token punctuation">;</span>
</code></pre></div><p>Since <code>rgba</code> is now a new image buffer, and not a reference to the original image's buffer, when it is used in the call to <code>write_texture</code> later, it needs to be passed as a reference instead.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">//...</span>
</code></pre></div><p><code>Mesh</code> holds a vertex buffer, an index buffer, and the number of indices in the mesh. We're using an <code>usize</code> for the material. This <code>usize</code> will be used to index the <code>materials</code> list when it comes time to draw.</p><p>With all that out of the way, we can get to loading our model.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">impl</span><spanclass="token class-name">Model</span><spanclass="token punctuation">{</span>
</code></pre></div><p><code>Mesh</code> holds a vertex buffer, an index buffer, and the number of indices in the mesh. We're using an <code>usize</code> for the material. This <code>usize</code> will be used to index the <code>materials</code> list when it comes time to draw.</p><p>With all that out of the way, we can get to loading our model.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">impl</span><spanclass="token class-name">Model</span><spanclass="token punctuation">{</span>
<metaproperty="article:modified_time"content="2021-11-24T22:56:19.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Working with Lights"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/intermediate/tutorial10-lighting/"><metaname="twitter:title"content="Working with Lights"><metaname="twitter:url"content="/intermediate/tutorial10-lighting/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2021-11-24T22:58:49.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Working with Lights"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/intermediate/tutorial10-lighting/"><metaname="twitter:title"content="Working with Lights"><metaname="twitter:url"content="/intermediate/tutorial10-lighting/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
@ -623,7 +623,7 @@ let specular_color = specular_strength * light.color;
let half_dir = normalize(view_dir + light_dir);
let half_dir = normalize(view_dir + light_dir);
let specular_strength = pow(max(dot(in.world_normal, half_dir), 0.0), 32.0);
let specular_strength = pow(max(dot(in.world_normal, half_dir), 0.0), 32.0);
</code></pre></div><p>It's hard to tell the difference, but here's the results.</p><p><imgsrc="/learn-wgpu/assets/img/half_dir.bbcc23b8.png"alt="./half_dir.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial10-lighting/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>It's hard to tell the difference, but here's the results.</p><p><imgsrc="/learn-wgpu/assets/img/half_dir.bbcc23b8.png"alt="./half_dir.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial10-lighting/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>That gives us something like this.</p><p><imgsrc="/learn-wgpu/assets/img/debug_material.b374492b.png"alt=""></p><p>You can find the textures I use in the Github Repository.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial11-normals/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>That gives us something like this.</p><p><imgsrc="/learn-wgpu/assets/img/debug_material.b374492b.png"alt=""></p><p>You can find the textures I use in the Github Repository.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial11-normals/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>With that we should be able to move our camera wherever we want.</p><p><imgsrc="/learn-wgpu/assets/img/screenshot.4f5740bc.png"alt="./screenshot.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial12-camera/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>With that we should be able to move our camera wherever we want.</p><p><imgsrc="/learn-wgpu/assets/img/screenshot.4f5740bc.png"alt="./screenshot.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial12-camera/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
<metaproperty="article:modified_time"content="2021-11-24T22:56:19.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Multi-threading with Wgpu and Rayon"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/intermediate/tutorial13-threading/"><metaname="twitter:title"content="Multi-threading with Wgpu and Rayon"><metaname="twitter:url"content="/intermediate/tutorial13-threading/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2021-11-24T22:58:49.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Multi-threading with Wgpu and Rayon"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/intermediate/tutorial13-threading/"><metaname="twitter:title"content="Multi-threading with Wgpu and Rayon"><metaname="twitter:url"content="/intermediate/tutorial13-threading/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
</code></pre></div><p>We've parallelized loading the meshes, and making the vertex array for them. Propably a bit overkill, but <code>rayon</code> should prevent us from using too many threads.</p><divclass="note"><p>You'll notice that we didn't use <code>rayon</code> for calculating the tangent, and bitangent. I tried to get it to work, but I was having trouble finding a way to do it without multiple mutable references to <code>vertices</code>. I don't feel like introducing a <code>std::sync::Mutex</code>, so I'll leave it for now.</p><p>This is honestly a better job for a compute shader, as the model data is going to get loaded into a buffer anyway.</p></div><h2id="it-s-that-easy"><ahref="#it-s-that-easy"class="header-anchor">#</a> It's that easy!</h2><p>Most of the <code>wgpu</code> types are <code>Send + Sync</code>, so we can use them in threads without much trouble. It was so easy, that I feel like this tutorial is too short! I'll just leave off with a speed comparison between the previous model loading code and the current code.</p><divclass="language- extra-class"><preclass="language-text"><code>Elapsed (Original): 309.596382ms
</code></pre></div><p>We've parallelized loading the meshes, and making the vertex array for them. Propably a bit overkill, but <code>rayon</code> should prevent us from using too many threads.</p><divclass="note"><p>You'll notice that we didn't use <code>rayon</code> for calculating the tangent, and bitangent. I tried to get it to work, but I was having trouble finding a way to do it without multiple mutable references to <code>vertices</code>. I don't feel like introducing a <code>std::sync::Mutex</code>, so I'll leave it for now.</p><p>This is honestly a better job for a compute shader, as the model data is going to get loaded into a buffer anyway.</p></div><h2id="it-s-that-easy"><ahref="#it-s-that-easy"class="header-anchor">#</a> It's that easy!</h2><p>Most of the <code>wgpu</code> types are <code>Send + Sync</code>, so we can use them in threads without much trouble. It was so easy, that I feel like this tutorial is too short! I'll just leave off with a speed comparison between the previous model loading code and the current code.</p><divclass="language- extra-class"><preclass="language-text"><code>Elapsed (Original): 309.596382ms
Elapsed (Threaded): 199.645027ms
Elapsed (Threaded): 199.645027ms
</code></pre></div><p>We're not loading that many resources, so the speed up is minimal. We'll be doing more stuff with threading, but this is a good introduction.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial13-threading/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>We're not loading that many resources, so the speed up is minimal. We'll be doing more stuff with threading, but this is a good introduction.</p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial13-threading/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><olstart="2"><li>The <code>request_device</code> method now returns a <code>(Device, Queue)</code> tuple. This means that you can borrow the <code>Queue</code> mutably while using the <code>Device</code> immutably. Because of this change, submitting <code>CommandBuffer</code>s to the queue uses the <code>submit</code> method on the <code>Queue</code> directly.</li></ol><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">self</span><spanclass="token punctuation">.</span>queue<spanclass="token punctuation">.</span><spanclass="token function">submit</span><spanclass="token punctuation">(</span><spanclass="token operator">&</span><spanclass="token punctuation">[</span>
</code></pre></div><olstart="2"><li>The <code>request_device</code> method now returns a <code>(Device, Queue)</code> tuple. This means that you can borrow the <code>Queue</code> mutably while using the <code>Device</code> immutably. Because of this change, submitting <code>CommandBuffer</code>s to the queue uses the <code>submit</code> method on the <code>Queue</code> directly.</li></ol><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">self</span><spanclass="token punctuation">.</span>queue<spanclass="token punctuation">.</span><spanclass="token function">submit</span><spanclass="token punctuation">(</span><spanclass="token operator">&</span><spanclass="token punctuation">[</span>
</code></pre></div><olstart="3"><li>The <code>create</code> method on <code>Surface</code> takes in any struct that implements the <code>HasRawWindow</code> trait, instead of a <code>RawWindowHandle</code>. This means that the <code>raw-window-handle = "0.3"</code> line in <code>Cargo.toml</code> is no longer needed.</li></ol><p>I don't know if this is a change from 0.4, but you use <code>wgpu = "0.4"</code> line in dependencies instead of the <code>[dependencies.wgpu]</code> as wgpu will determine the best back end for you.</p><h2id="new-recent-articles"><ahref="#new-recent-articles"class="header-anchor">#</a> New/Recent Articles</h2><div><ul><li><ahref="/beginner/tutorial1-window/">Dependencies and the window</a></li><li><ahref="/beginner/tutorial2-surface/">The Surface</a></li><li><ahref="/beginner/tutorial3-pipeline/">The Pipeline</a></li><li><ahref="/beginner/tutorial4-buffer/">Buffers and Indices</a></li><li><ahref="/beginner/tutorial5-textures/">Textures and bind groups</a></li></ul></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><olstart="3"><li>The <code>create</code> method on <code>Surface</code> takes in any struct that implements the <code>HasRawWindow</code> trait, instead of a <code>RawWindowHandle</code>. This means that the <code>raw-window-handle = "0.3"</code> line in <code>Cargo.toml</code> is no longer needed.</li></ol><p>I don't know if this is a change from 0.4, but you use <code>wgpu = "0.4"</code> line in dependencies instead of the <code>[dependencies.wgpu]</code> as wgpu will determine the best back end for you.</p><h2id="new-recent-articles"><ahref="#new-recent-articles"class="header-anchor">#</a> New/Recent Articles</h2><div><ul><li><ahref="/beginner/tutorial1-window/">Dependencies and the window</a></li><li><ahref="/beginner/tutorial2-surface/">The Surface</a></li><li><ahref="/beginner/tutorial3-pipeline/">The Pipeline</a></li><li><ahref="/beginner/tutorial4-buffer/">Buffers and Indices</a></li><li><ahref="/beginner/tutorial5-textures/">Textures and bind groups</a></li></ul></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>I ultimately decided against this method as it was more complicated, and I haven't had time to benchmark it to see if it's faster that the simple method.</p><h2id="results"><ahref="#results"class="header-anchor">#</a> Results</h2><p>The tangents and bitangents are now getting calculated correctly and on the GPU!</p><p><imgsrc="/learn-wgpu/assets/img/results.7918efc1.png"alt="./results.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/compute/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>I ultimately decided against this method as it was more complicated, and I haven't had time to benchmark it to see if it's faster that the simple method.</p><h2id="results"><ahref="#results"class="header-anchor">#</a> Results</h2><p>The tangents and bitangents are now getting calculated correctly and on the GPU!</p><p><imgsrc="/learn-wgpu/assets/img/results.7918efc1.png"alt="./results.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/compute/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>That's the gist of it. We can improve things using a texture array, and sending the draw commands all at once, but this gets the idea across. With the shader I wrote we get the following GIF.</p><p><imgsrc="/learn-wgpu/assets/img/output.5ed23d6e.gif"alt="./output.gif"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/gifs/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>That's the gist of it. We can improve things using a texture array, and sending the draw commands all at once, but this gets the idea across. With the shader I wrote we get the following GIF.</p><p><imgsrc="/learn-wgpu/assets/img/output.5ed23d6e.gif"alt="./output.gif"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/gifs/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>That's all there is to it. Here's a picture of the results!</p><p><imgsrc="/learn-wgpu/assets/img/screenshot.1f9dab62.png"alt="./screenshot.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/imgui-demo/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>That's all there is to it. Here's a picture of the results!</p><p><imgsrc="/learn-wgpu/assets/img/screenshot.1f9dab62.png"alt="./screenshot.png"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/imgui-demo/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
<divid="app"data-server-rendered="true"><divclass="theme-container"><headerclass="navbar"><divclass="inner"><divclass="sidebar-button"><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"role="img"viewBox="0 0 448 512"class="icon"><pathfill="currentColor"d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div><ahref="/learn-wgpu/"class="home-link router-link-active"><!----><spanclass="site-name">Learn Wgpu</span></a><divclass="links"><!----><divclass="search-box"><inputaria-label="Search"autocomplete="off"spellcheck="false"value=""><!----></div></div></div></header><divclass="sidebar-mask"></div><divclass="docs-layout"><asideclass="sidebar"><!----><ulclass="sidebar-links"><li><ahref="/learn-wgpu/"class="sidebar-link">Introduction</a></li><li><sectionclass="sidebar-group depth-0"><pclass="sidebar-heading"><span>Beginner</span><!----></p><ulclass="sidebar-links sidebar-group-items"><li><ahref="/learn-wgpu/beginner/tutorial1-window/"class="sidebar-link">Dependencies and the window</a></li><li><ahref="/learn-wgpu/beginner/tutorial2-surface/"class="sidebar-link">The Surface</a></li><li><ahref="/learn-wgpu/beginner/tutorial3-pipeline/"class="sidebar-link">The Pipeline</a></li><li><ahref="/learn-wgpu/beginner/tutorial4-buffer/"class="sidebar-link">Buffers and Indices</a></li><li><ahref="/learn-wgpu/beginner/tutorial5-textures/"class="sidebar-link">Textures and bind groups</a></li><li><ahref="/learn-wgpu/beginner/tutorial6-uniforms/"class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><ahref="/learn-wgpu/beginner/tutorial7-instancing/"class="sidebar-link">Instancing</a></li><li><ahref="/learn-wgpu/beginner/tutorial8-depth/"class="sidebar-link">The Depth Buffer</a></li><li><ahref="/learn-wgpu/beginner/tutorial9-models/"class="sidebar-link">Model Loading</a></li></ul></section></li><li><sectionclass="sidebar-group depth-0"><pclass="sidebar-heading"><span>Intermediate</span><!----></p><ulclass="sidebar-links sidebar-group-items"><li><ahref="/learn-wgpu/intermediate/tutorial10-lighting/"class="sidebar-link">Working with Lights</a></li><li><ahref="/learn-wgpu/intermediate/tutorial11-normals/"class="sidebar-link">Normal Mapping</a></li><li><ahref="/learn-wgpu/intermediate/tutorial12-camera/"class="sidebar-link">A Better Camera</a></li><li><ahref="/learn-wgpu/intermediate/tutorial13-threading/"class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><sectionclass="sidebar-group collapsable depth-0"><pclass="sidebar-heading open"><span>Showcase</span><spanclass="arrow down"></span></p><ulclass="sidebar-links sidebar-group-items"><li><ahref="/learn-wgpu/showcase/"class="active sidebar-link">Foreward</a></li><li><ahref="/learn-wgpu/showcase/windowless/"class="sidebar-link">Wgpu without a window</a></li><li><ahref="/learn-wgpu/showcase/gifs/"class="sidebar-link">Creating gifs</a></li><li><ahref="/learn-wgpu/showcase/pong/"class="sidebar-link">Pong</a></li><li><ahref="/learn-wgpu/showcase/compute/"class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><ahref="/learn-wgpu/showcase/alignment/"class="sidebar-link">Memory Layout in GLSL</a></li><li><ahref="/learn-wgpu/showcase/imgui-demo/"class="sidebar-link">Basic Imgui Demo</a></li></ul></section></li><li><ahref="/learn-wgpu/news/"class="sidebar-link">News</a></li></ul></aside><mainclass="page"><divclass="theme-default-content content__default"><h1id="foreward"><ahref="#foreward"class="header-anchor">#</a> Foreward</h1><p>The articles in this section are not meant to be tutorials. They are showcases of the various things you can do with <code>wgpu</code>. I won't go over specifics of creating <code>wgpu</code> resources, as those will be covered elsewhere. The code for these examples is still available however, and will be accessible on Github.</p></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
<divid="app"data-server-rendered="true"><divclass="theme-container"><headerclass="navbar"><divclass="inner"><divclass="sidebar-button"><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"role="img"viewBox="0 0 448 512"class="icon"><pathfill="currentColor"d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div><ahref="/learn-wgpu/"class="home-link router-link-active"><!----><spanclass="site-name">Learn Wgpu</span></a><divclass="links"><!----><divclass="search-box"><inputaria-label="Search"autocomplete="off"spellcheck="false"value=""><!----></div></div></div></header><divclass="sidebar-mask"></div><divclass="docs-layout"><asideclass="sidebar"><!----><ulclass="sidebar-links"><li><ahref="/learn-wgpu/"class="sidebar-link">Introduction</a></li><li><sectionclass="sidebar-group depth-0"><pclass="sidebar-heading"><span>Beginner</span><!----></p><ulclass="sidebar-links sidebar-group-items"><li><ahref="/learn-wgpu/beginner/tutorial1-window/"class="sidebar-link">Dependencies and the window</a></li><li><ahref="/learn-wgpu/beginner/tutorial2-surface/"class="sidebar-link">The Surface</a></li><li><ahref="/learn-wgpu/beginner/tutorial3-pipeline/"class="sidebar-link">The Pipeline</a></li><li><ahref="/learn-wgpu/beginner/tutorial4-buffer/"class="sidebar-link">Buffers and Indices</a></li><li><ahref="/learn-wgpu/beginner/tutorial5-textures/"class="sidebar-link">Textures and bind groups</a></li><li><ahref="/learn-wgpu/beginner/tutorial6-uniforms/"class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><ahref="/learn-wgpu/beginner/tutorial7-instancing/"class="sidebar-link">Instancing</a></li><li><ahref="/learn-wgpu/beginner/tutorial8-depth/"class="sidebar-link">The Depth Buffer</a></li><li><ahref="/learn-wgpu/beginner/tutorial9-models/"class="sidebar-link">Model Loading</a></li></ul></section></li><li><sectionclass="sidebar-group depth-0"><pclass="sidebar-heading"><span>Intermediate</span><!----></p><ulclass="sidebar-links sidebar-group-items"><li><ahref="/learn-wgpu/intermediate/tutorial10-lighting/"class="sidebar-link">Working with Lights</a></li><li><ahref="/learn-wgpu/intermediate/tutorial11-normals/"class="sidebar-link">Normal Mapping</a></li><li><ahref="/learn-wgpu/intermediate/tutorial12-camera/"class="sidebar-link">A Better Camera</a></li><li><ahref="/learn-wgpu/intermediate/tutorial13-threading/"class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><sectionclass="sidebar-group collapsable depth-0"><pclass="sidebar-heading open"><span>Showcase</span><spanclass="arrow down"></span></p><ulclass="sidebar-links sidebar-group-items"><li><ahref="/learn-wgpu/showcase/"class="active sidebar-link">Foreward</a></li><li><ahref="/learn-wgpu/showcase/windowless/"class="sidebar-link">Wgpu without a window</a></li><li><ahref="/learn-wgpu/showcase/gifs/"class="sidebar-link">Creating gifs</a></li><li><ahref="/learn-wgpu/showcase/pong/"class="sidebar-link">Pong</a></li><li><ahref="/learn-wgpu/showcase/compute/"class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><ahref="/learn-wgpu/showcase/alignment/"class="sidebar-link">Memory Layout in GLSL</a></li><li><ahref="/learn-wgpu/showcase/imgui-demo/"class="sidebar-link">Basic Imgui Demo</a></li></ul></section></li><li><ahref="/learn-wgpu/news/"class="sidebar-link">News</a></li></ul></aside><mainclass="page"><divclass="theme-default-content content__default"><h1id="foreward"><ahref="#foreward"class="header-anchor">#</a> Foreward</h1><p>The articles in this section are not meant to be tutorials. They are showcases of the various things you can do with <code>wgpu</code>. I won't go over specifics of creating <code>wgpu</code> resources, as those will be covered elsewhere. The code for these examples is still available however, and will be accessible on Github.</p></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>I was going to have <code>BallBounce</code> play a positioned sound using a <code>SpatialSink</code>, but I was getting clipping issues, and I wanted to be done with the project. Aside from that, the events system worked nicely.</p><h2id="summary"><ahref="#summary"class="header-anchor">#</a> Summary</h2><p>A fun project to work on. It was overly architected, and kinda hard to make changes, but a good experience none the less.</p></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>I was going to have <code>BallBounce</code> play a positioned sound using a <code>SpatialSink</code>, but I was getting clipping issues, and I wanted to be done with the project. Aside from that, the events system worked nicely.</p><h2id="summary"><ahref="#summary"class="header-anchor">#</a> Summary</h2><p>A fun project to work on. It was overly architected, and kinda hard to make changes, but a good experience none the less.</p></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
<metaproperty="article:modified_time"content="2021-11-24T22:56:19.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Wgpu without a window"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/showcase/windowless/"><metaname="twitter:title"content="Wgpu without a window"><metaname="twitter:url"content="/showcase/windowless/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2021-11-24T22:58:49.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Wgpu without a window"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/showcase/windowless/"><metaname="twitter:title"content="Wgpu without a window"><metaname="twitter:url"content="/showcase/windowless/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
</code></pre></div><p>With all that you should have an image like this.</p><p><imgsrc="data:image/png;base64,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"alt="a brown triangle"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/windowless/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:56:19 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>With all that you should have an image like this.</p><p><imgsrc="data:image/png;base64,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"alt="a brown triangle"></p><divclass="auto-github-link"><ahref="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/windowless/"target="_blank"rel="noopener noreferrer">Check out the code!</a><svgxmlns="http://www.w3.org/2000/svg"aria-hidden="true"x="0px"y="0px"viewBox="0 0 100 100"width="15"height="15"class="icon outbound"><pathfill="currentColor"d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygonfill="currentColor"points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div></div><footerclass="page-edit"><!----><divclass="last-updated"><spanclass="prefix">Last Updated: </span><spanclass="time">11/24/2021, 10:58:49 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">