<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 open"><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-swapchain/"class="active sidebar-link">The Swapchain</a><ulclass="sidebar-sub-headers"><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#first-some-house-keeping-state"class="sidebar-link">First, some house keeping: State</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#state-new"class="sidebar-link">State::new()</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#resize"class="sidebar-link">resize()</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#input"class="sidebar-link">input()</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#update"class="sidebar-link">update()</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#render"class="sidebar-link">render()</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#wait-what-s-going-on-with-renderpassdescriptor"class="sidebar-link">Wait, what's going on with RenderPassDescriptor?</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial2-swapchain/#challenge"class="sidebar-link">Challenge</a></li></ul></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"><span>Showcase</span><spanclass="arrow right"></span></p><!----></section></li><li><ahref="/learn-wgpu/news/"class="sidebar-link">News</a></li></ul></aside><mainclass="page"><divclass="theme-default-content content__default"><h1id="the-swapchain"><ahref="#the-swapchain"class="header-anchor">#</a> The Swapchain</h1><h2id="first-some-house-keeping-state"><ahref="#first-some-house-keeping-state"class="header-anchor">#</a> First, some house keeping: State</h2><p>For convenience we're going to pack all the fields into a struct, and create some methods on that.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// main.rs</span>
</code></pre></div><p>The <code>features</code> field on <code>DeviceDescriptor</code>, allows us to specify what extra features we want. For this simple example, I've deviced to not use any extra features.</p><divclass="note"><p>The device you have limits the features you can use. If you want to use certain features you may need to limit what devices you support, or provide work arounds.</p><p>You can get a list of features supported by your device using <code>adapter.features()</code>, or <code>device.features()</code>.</p><p>You can view a full list of features <ahref="https://docs.rs/wgpu/0.7.0/wgpu/struct.Features.html"target="_blank"rel="noopener noreferrer">here<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></div><p>The <code>limits</code> field describes the limit of certain types of resource we can create. We'll use the defaults for this tutorial, so we can support most devices. You can view a list of limits <ahref="https://docs.rs/wgpu/0.7.0/wgpu/struct.Limits.html"target="_blank"rel="noopener noreferrer">here<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><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">let</span> sc_desc <spanclass="token operator">=</span><spanclass="token namespace">wgpu<spanclass="token punctuation">::</span></span><spanclass="token class-name">SwapChainDescriptor</span><spanclass="token punctuation">{</span>
</code></pre></div><p>The <code>RenderPassColorAttachmentDescriptor</code> has the <code>attachment</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>swap_chain.get_current_frame()</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>attachment</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.</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="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-swapchain/"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">3/21/2021, 11:19:24 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
</code></pre></div><p>The <code>RenderPassColorAttachmentDescriptor</code> has the <code>attachment</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>swap_chain.get_current_frame()</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>attachment</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.</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="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-swapchain/"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">5/1/2021, 9:55:26 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 open"><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-swapchain/"class="sidebar-link">The Swapchain</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="active sidebar-link">Model Loading</a><ulclass="sidebar-sub-headers"><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial9-models/#accessing-files-in-the-res-folder"class="sidebar-link">Accessing files in the res folder</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial9-models/#loading-models-with-tobj"class="sidebar-link">Loading models with TOBJ</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial9-models/#rendering-a-mesh"class="sidebar-link">Rendering a mesh</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial9-models/#using-the-correct-textures"class="sidebar-link">Using the correct textures</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/beginner/tutorial9-models/#rendering-the-entire-model"class="sidebar-link">Rendering the entire model</a></li></ul></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"><span>Showcase</span><spanclass="arrow right"></span></p><!----></section></li><li><ahref="/learn-wgpu/news/"class="sidebar-link">News</a></li></ul></aside><mainclass="page"><divclass="theme-default-content content__default"><h1id="model-loading"><ahref="#model-loading"class="header-anchor">#</a> Model Loading</h1><p>Up to this point we've been creating our models manually. While this is an acceptable way to do this, but it's really slow if we want to include complex models with lots of polygons. Because of this, we're going modify our code to leverage the obj model format so that we can create a model in a software such as blender and display it in our code.</p><p>Our <code>main.rs</code> file is getting pretty cluttered, let's create a <code>model.rs</code> file that we can put our model loading code into.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// model.rs</span>
</code></pre></div><p>With all that in place we need a model to render. If you have one already that's great, but I've supplied a <ahref="https://github.com/sotrh/learn-wgpu/blob/master/code/beginner/tutorial9-models/res/cube.zip"target="_blank"rel="noopener noreferrer">zip file<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> with the model and all of it's textures. We're going to put this model in a new <code>res</code> folder next to the existing <code>src</code> folder.</p><h2id="accessing-files-in-the-res-folder"><ahref="#accessing-files-in-the-res-folder"class="header-anchor">#</a> Accessing files in the res folder</h2><p>When cargo builds and runs our program it sets what's known as the current working directory. This directory is usually the folder containing your projects root <code>Cargo.toml</code>. The path to our res folder may differ depending on the structure of the project. In the <code>res</code> folder for the example code for this section tutorial is at <code>code/beginner/tutorial9-models/res/</code>. When loading our model we could use this path, and just append <code>cube.obj</code>. This is fine, but if we change our projects structure, our code will break.</p><p>We're going to fix that by modifying our build script to copy our <code>res</code> folder to where cargo creates our executable, and we'll reference it from there. Add the following lines to <code>build.rs</code> after you compile the shaders.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// This tells cargo to rerun this script if something in /res/ changes.</span>
</code></pre></div><p>With all that in place we need a model to render. If you have one already that's great, but I've supplied a <ahref="https://github.com/sotrh/learn-wgpu/blob/master/code/beginner/tutorial9-models/res/cube.zip"target="_blank"rel="noopener noreferrer">zip file<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> with the model and all of it's textures. We're going to put this model in a new <code>res</code> folder next to the existing <code>src</code> folder.</p><h2id="accessing-files-in-the-res-folder"><ahref="#accessing-files-in-the-res-folder"class="header-anchor">#</a> Accessing files in the res folder</h2><p>When cargo builds and runs our program it sets what's known as the current working directory. This directory is usually the folder containing your projects root <code>Cargo.toml</code>. The path to our res folder may differ depending on the structure of the project. In the <code>res</code> folder for the example code for this section tutorial is at <code>code/beginner/tutorial9-models/res/</code>. When loading our model we could use this path, and just append <code>cube.obj</code>. This is fine, but if we change our projects structure, our code will break.</p><p>We're going to fix that by modifying our build script to copy our <code>res</code> folder to where cargo creates our executable, and we'll reference it from there. Create a file called <code>build.rs</code> and add the following:</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">use</span><spanclass="token namespace">anyhow<spanclass="token punctuation">::</span></span><spanclass="token operator">*</span><spanclass="token punctuation">;</span>
</code></pre></div><divclass="note"><p>The <code>OUT_DIR</code> is an environment variable that cargo uses to specify where our application will be built.</p></div><h2id="loading-models-with-tobj"><ahref="#loading-models-with-tobj"class="header-anchor">#</a> Loading models with TOBJ</h2><p>We're going to use the <ahref="https://docs.rs/tobj/0.1.12/tobj/"target="_blank"rel="noopener noreferrer">tobj<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> library to load our model. Before we can load our model though, we need somewhere to put it.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// model.rs</span>
</code></pre></div><divclass="note"><p>Make sure to put <code>build.rs</code> in the same folder as the <code>Cargo.toml</code>. If you don't, cargo won't run it when your crate builds.</p></div><divclass="note"><p>The <code>OUT_DIR</code> is an environment variable that cargo uses to specify where our application will be built.</p></div><p>You'll need to modify your <code>Cargo.toml</code> for this to work properly. Add the following below your <code>[dependencies]</code> block.</p><divclass="language-toml extra-class"><preclass="language-toml"><code><spanclass="token punctuation">[</span><spanclass="token table class-name">build-dependencies</span><spanclass="token punctuation">]</span>
</code></pre></div><h2id="loading-models-with-tobj"><ahref="#loading-models-with-tobj"class="header-anchor">#</a> Loading models with TOBJ</h2><p>We're going to use the <ahref="https://docs.rs/tobj/0.1.12/tobj/"target="_blank"rel="noopener noreferrer">tobj<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> library to load our model. Before we can load our model though, we need somewhere to put it.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// model.rs</span>
<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-swapchain/"class="sidebar-link">The Swapchain</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 open"><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="active sidebar-link">A Better Camera</a><ulclass="sidebar-sub-headers"><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial12-camera/#the-camera"class="sidebar-link">The Camera</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial12-camera/#the-projection"class="sidebar-link">The Projection</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial12-camera/#cleaning-up-main-rs"class="sidebar-link">Cleaning up main.rs</a></li></ul></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"><span>Showcase</span><spanclass="arrow right"></span></p><!----></section></li><li><ahref="/learn-wgpu/news/"class="sidebar-link">News</a></li></ul></aside><mainclass="page"><divclass="theme-default-content content__default"><h1id="a-better-camera"><ahref="#a-better-camera"class="header-anchor">#</a> A Better Camera</h1><p>I've been putting this off for a while. Implementing a camera isn't specifically related to using WGPU properly, but it's been bugging me so let's do it.</p><p><code>main.rs</code> is getting a little crowded, so let's create a <code>camera.rs</code> file to put our camera code. The first thing we're going to put in it in is some imports and our <code>OPENGL_TO_WGPU_MATRIX</code>.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">use</span><spanclass="token namespace">cgmath<spanclass="token punctuation">::</span></span><spanclass="token operator">*</span><spanclass="token punctuation">;</span>
<metaproperty="article:modified_time"content="2021-03-26T16:46:37.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 R Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2021-05-24T17:44:10.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 R Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<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-swapchain/"class="sidebar-link">The Swapchain</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 open"><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="active sidebar-link">Multi-threading with Wgpu and Rayon</a><ulclass="sidebar-sub-headers"><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial13-threading/#threading-build-rs"class="sidebar-link">Threading build.rs</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial13-threading/#parallelizing-loading-models-and-textures"class="sidebar-link">Parallelizing loading models and textures</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial13-threading/#it-s-that-easy"class="sidebar-link">It's that easy!</a></li></ul></li></ul></section></li><li><sectionclass="sidebar-group collapsable depth-0"><pclass="sidebar-heading"><span>Showcase</span><spanclass="arrow right"></span></p><!----></section></li><li><ahref="/learn-wgpu/news/"class="sidebar-link">News</a></li></ul></aside><mainclass="page"><divclass="theme-default-content content__default"><h1id="multi-threading-with-wgpu-and-rayon"><ahref="#multi-threading-with-wgpu-and-rayon"class="header-anchor">#</a> Multi-threading with Wgpu and Rayon</h1><p>The main selling point of Vulkan, DirectX 12, Metal, and by extension Wgpu is that these APIs is that they designed from the ground up to be thread safe. Up to this point we have been doing everything on a single thread. That's about to change.</p><divclass="note"><p>I won't go into what threads are in this tutorial. That is a course in and of itself. All we'll be covering is using threading to make loading resources faster.</p><p>We won't go over multithreading rendering as we don't have enough different types of objects to justify that yet. This will change in a coming tutorial</p></div><h2id="threading-build-rs"><ahref="#threading-build-rs"class="header-anchor">#</a> Threading build.rs</h2><p>If you remember <ahref="../../beginner/tutorial3-pipeline">the pipeline tutorial</a>, we created a build script to compile our GLSL shaders to spirv. That had a section in the <code>main</code> function that looked like this.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// This could be parallelized</span>
</code></pre></div><p>That <code>This could be parallelized</code> comment will soon become <code>This is parallelized</code>. We're going to add a build dependecy to <ahref="https://docs.rs/rayon"target="_blank"rel="noopener noreferrer">rayon<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> to our <code>Cargo.toml</code>.</p><divclass="language-toml extra-class"><preclass="language-toml"><code><spanclass="token punctuation">[</span><spanclass="token table class-name">build-dependencies</span><spanclass="token punctuation">]</span>
</code></pre></div><p>First some housekeeping. Our <code>build.rs</code> code currently uses an array to store the globs to find our projects shaders. We're going to switch to using a <code>Vec</code> to make things play nicer with <code>rayon</code>.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// Collect all shaders recursively within /src/</span>
</code></pre></div><p>We'll also need to import <code>rayon</code> as well.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token keyword">use</span><spanclass="token namespace">rayon<spanclass="token punctuation">::</span>prelude<spanclass="token punctuation">::</span></span><spanclass="token operator">*</span><spanclass="token punctuation">;</span>
</code></pre></div><p>Now we can change our shader source collection code to the following.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// UPDATED!</span>
<spanclass="token comment">// This is parallelized</span>
</code></pre></div><p>Super simple isn't it? By using <code>into_par_iter</code>, <code>rayon</code> will try to spread our shader loading across multiple threads if it can. This means that our build script will load the shader text source for multiple shaders at the same time. This has the potential to drastically reduce our build times.</p><p>We can compare the speeds of our compilation by running <code>cargo build</code> on both this tutorial and the previous one.</p><divclass="language-bash extra-class"><preclass="language-bash"><code>$ cargo build --bin tutorial12-camera
</code></pre></div><p>Our build speed is a little more than twice as fast!</p><divclass="note"><p>I got these build speeds after building the project one time to get <code>rayon</code> installed, and then deleting the .spv files from the previous two projects.</p></div><h2id="parallelizing-loading-models-and-textures"><ahref="#parallelizing-loading-models-and-textures"class="header-anchor">#</a> Parallelizing loading models and textures</h2><p>Currently we load the materials and meshes of our model one at a time. This is a perfect opportunity for multithreading! All our changes will be in <code>model.rs</code>. Let's first start with the materials. We'll convert the regular for loop into a <code>par_iter().map()</code>.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// model.rs</span>
<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-swapchain/"class="sidebar-link">The Swapchain</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 open"><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="active sidebar-link">Multi-threading with Wgpu and Rayon</a><ulclass="sidebar-sub-headers"><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial13-threading/#parallelizing-loading-models-and-textures"class="sidebar-link">Parallelizing loading models and textures</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/intermediate/tutorial13-threading/#it-s-that-easy"class="sidebar-link">It's that easy!</a></li></ul></li></ul></section></li><li><sectionclass="sidebar-group collapsable depth-0"><pclass="sidebar-heading"><span>Showcase</span><spanclass="arrow right"></span></p><!----></section></li><li><ahref="/learn-wgpu/news/"class="sidebar-link">News</a></li></ul></aside><mainclass="page"><divclass="theme-default-content content__default"><h1id="multi-threading-with-wgpu-and-rayon"><ahref="#multi-threading-with-wgpu-and-rayon"class="header-anchor">#</a> Multi-threading with Wgpu and Rayon</h1><p>The main selling point of Vulkan, DirectX 12, Metal, and by extension Wgpu is that these APIs is that they designed from the ground up to be thread safe. Up to this point we have been doing everything on a single thread. That's about to change.</p><divclass="note"><p>I won't go into what threads are in this tutorial. That is a course in and of itself. All we'll be covering is using threading to make loading resources faster.</p><p>We won't go over multithreading rendering as we don't have enough different types of objects to justify that yet. This will change in a coming tutorial</p></div><h2id="parallelizing-loading-models-and-textures"><ahref="#parallelizing-loading-models-and-textures"class="header-anchor">#</a> Parallelizing loading models and textures</h2><p>Currently we load the materials and meshes of our model one at a time. This is a perfect opportunity for multithreading! All our changes will be in <code>model.rs</code>. Let's first start with the materials. We'll convert the regular for loop into a <code>par_iter().map()</code>.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token comment">// model.rs</span>
</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
</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">3/26/2021, 4:46:37 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">5/24/2021, 5:44:10 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">
<metaproperty="article:modified_time"content="2021-02-12T06:29:40.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Compute Example: Tangents and Bitangents"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/showcase/compute/"><metaname="twitter:title"content="Compute Example: Tangents and Bitangents"><metaname="twitter:url"content="/showcase/compute/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin R Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<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-swapchain/"class="sidebar-link">The Swapchain</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="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="active sidebar-link">Compute Example: Tangents and Bitangents</a><ulclass="sidebar-sub-headers"><liclass="sidebar-sub-header"><ahref="/learn-wgpu/showcase/compute/#possible-improvements"class="sidebar-link">Possible Improvements</a></li><liclass="sidebar-sub-header"><ahref="/learn-wgpu/showcase/compute/#results"class="sidebar-link">Results</a></li></ul></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="compute-example-tangents-and-bitangents"><ahref="#compute-example-tangents-and-bitangents"class="header-anchor">#</a> Compute Example: Tangents and Bitangents</h1><p>This proved more difficult than I anticipated. The first problem I encountered was some vertex data corruption due to the shader reading my vertex data incorrectly. I was using my <code>ModelVertex</code> struct I used in the <ahref="/learn-wgpu/intermediate/tutorial11-normals/">normal mapping tutorial</a>.</p><divclass="language-rust extra-class"><preclass="language-rust"><code><spanclass="token attribute attr-name">#[repr(C)]</span>
<metaproperty="article:modified_time"content="2020-09-23T21:56:34.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Foreward"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/showcase/"><metaname="twitter:title"content="Foreward"><metaname="twitter:url"content="/showcase/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin R Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<metaproperty="article:modified_time"content="2020-09-25T21:57:57.000Z"><metaproperty="og:site_name"content="Learn Wgpu"><metaproperty="og:title"content="Foreward"><metaproperty="og:type"content="website"><metaproperty="og:url"content="/showcase/"><metaname="twitter:title"content="Foreward"><metaname="twitter:url"content="/showcase/"><metaname="twitter:card"content="summary_large_image"><metaname="twitter:label1"content="Written by"><metaname="twitter:data2"content="Benjamin R Hansen"><metaname="twitter:creator"content="https://twitter.com/sotrh760">
<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-swapchain/"class="sidebar-link">The Swapchain</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">9/23/2020, 9:56:34 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-swapchain/"class="sidebar-link">The Swapchain</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">9/25/2020, 9:57:57 PM</span></div></footer><divclass="page-nav"><pclass="inner"><spanclass="prev">