Deploying to gh-pages from @ sotrh/learn-wgpu@66096d6f81 🚀

gh-pages
sotrh 2 years ago
parent b79577876a
commit 8f66086d83

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/27.702b4de8.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.d40f290b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.fa667d51.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.77b9a0f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><div class="theme-default-content"><h1>404</h1> <blockquote>Looks like we've got some broken links.</blockquote> <a href="/learn-wgpu/" class="router-link-active">Take me home.</a></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/27.702b4de8.js" defer></script>
</body>
</html>

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{176:function(e,r,n){},260:function(e,r,n){var t={"./pong/pong.js":[263,1,2,35],"./pong/pong_bg.js":[156,1,2]};function a(e){if(!n.o(t,e))return Promise.resolve().then((function(){var r=new Error("Cannot find module '"+e+"'");throw r.code="MODULE_NOT_FOUND",r}));var r=t[e],a=r[0];return Promise.all(r.slice(1).map(n.e)).then((function(){return n(a)}))}a.keys=function(){return Object.keys(t)},a.id=260,e.exports=a},261:function(e,r,n){"use strict";var t=n(176);n.n(t).a},313:function(e,r,n){"use strict";n.r(r);n(109),n(17),n(23),n(49),n(78);var t=n(40);var a={props:{example:"",autoLoad:!1},data:function(){return{error:"",loading:!1,exampleStarted:!1}},computed:{exampleName:function(){return this.example.replace(/\w\S*/g,(function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()}))}},methods:{loadExample:function(){var e=this;return Object(t.a)(regeneratorRuntime.mark((function r(){return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return e.loading=!0,r.prev=1,r.next=4,n(260)("./".concat(e.example,"/").concat(e.example,".js"));case 4:(0,r.sent)().then((function(){console.log("WASM Loaded")})),r.next=11;break;case 8:r.prev=8,r.t0=r.catch(1),"Error: Using exceptions for control flow, don't mind me. This isn't actually an error!"!="".concat(r.t0)?(e.error='An error occurred loading "'.concat(e.example,'": ').concat(r.t0),console.error(r.t0),e.exampleStarted=!1):e.exampleStarted=!0;case 11:e.loading=!1;case 12:case"end":return r.stop()}}),r,null,[[1,8]])})))()}},mounted:function(){var e=this;return Object(t.a)(regeneratorRuntime.mark((function r(){return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:return r.next=2,e.$nextTick();case 2:if(!e.autoLoad){r.next=5;break}return r.next=5,e.loadExample();case 5:case"end":return r.stop()}}),r)})))()}},o=(n(261),n(10)),c=Object(o.a)(a,(function(){var e=this,r=e.$createElement,n=e._self._c||r;return n("div",{attrs:{id:"wasm-example"}},[e.error?n("div",{staticClass:"error"},[e._v("\n "+e._s(e.error)+"\n ")]):e._e(),e._v(" "),e.exampleStarted||e.autoLoad?e._e():n("button",{attrs:{disabled:e.loading},on:{click:function(r){return e.loadExample()}}},[e._v("Try "+e._s(e.exampleName)+"!")])])}),[],!1,null,null,null);r.default=c.exports}}]);

@ -0,0 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{395:function(e,t,r){},517:function(e,t,r){"use strict";var n=r(1),a=r(2),o=r(30),u=r(61),c=r(14),i=a("".slice),s=Math.max,l=Math.min;n({target:"String",proto:!0,forced:!"".substr||"b"!=="ab".substr(-1)},{substr:function(e,t){var r,n,a=c(o(this)),d=a.length,p=u(e);return p===1/0&&(p=0),p<0&&(p=s(d+p,0)),(r=void 0===t?d:u(t))<=0||r===1/0||p>=(n=l(p+r,d))?"":i(a,p,n)}})},518:function(e,t,r){var n={"./tutorial13_threading/tutorial13_threading.js":[521,1,2,36],"./tutorial13_threading/tutorial13_threading_bg.js":[363,1,2],"./tutorial2_surface/tutorial2_surface.js":[533,1,3,37],"./tutorial2_surface/tutorial2_surface_bg.js":[364,1,3]};function a(e){if(!r.o(n,e))return Promise.resolve().then((function(){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}));var t=n[e],a=t[0];return Promise.all(t.slice(1).map(r.e)).then((function(){return r(a)}))}a.keys=function(){return Object.keys(n)},a.id=518,e.exports=a},519:function(e,t,r){"use strict";r(395)},538:function(e,t,r){"use strict";r.r(t);var n=r(87);r(135),r(29),r(92),r(517),r(8),r(19),r(27),r(125);var a={name:"WasmExample",props:{example:"",autoLoad:!1},data:function(){return{error:"",loading:!1,exampleStarted:!1}},computed:{exampleName:function(){return this.example.replace(/\w\S*/g,(function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()}))}},methods:{loadExample:function(){var e=this;return Object(n.a)(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return e.loading=!0,t.prev=1,t.next=4,r(518)("./".concat(e.example,"/").concat(e.example,".js"));case 4:t.next=9;break;case 6:t.prev=6,t.t0=t.catch(1),"Error: Using exceptions for control flow, don't mind me. This isn't actually an error!"!="".concat(t.t0)?(e.error='An error occurred loading "'.concat(e.example,'": ').concat(t.t0),console.error(t.t0),e.exampleStarted=!1):e.exampleStarted=!0;case 9:e.loading=!1;case 10:case"end":return t.stop()}}),t,null,[[1,6]])})))()}},mounted:function(){var e=this;return Object(n.a)(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.$nextTick();case 2:if(!e.autoLoad){t.next=5;break}return t.next=5,e.loadExample();case 5:case"end":return t.stop()}}),t)})))()}},o=(r(519),r(23)),u=Object(o.a)(a,(function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{attrs:{id:"wasm-example"}},[e.error?r("div",{staticClass:"error"},[e._v("\n "+e._s(e.error)+"\n ")]):e._e(),e._v(" "),e.exampleStarted||e.autoLoad?e._e():r("button",{attrs:{disabled:e.loading},on:{click:function(t){return e.loadExample()}}},[e._v("Try "+e._s(e.exampleName)+"!")])])}),[],!1,null,null,null);t.default=u.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{258:function(t,e,n){"use strict";var r=n(0),i=n(71),a=n(12),o=n(2),u=n(33),l=[],s=l.sort,c=o((function(){l.sort(void 0)})),f=o((function(){l.sort(null)})),d=u("sort");r({target:"Array",proto:!0,forced:c||!f||!d},{sort:function(t){return void 0===t?s.call(a(this)):s.call(a(this),i(t))}})},259:function(t,e,n){var r=n(13),i=Date.prototype,a=i.toString,o=i.getTime;new Date(NaN)+""!="Invalid Date"&&r(i,"toString",(function(){var t=o.call(this);return t==t?a.call(this):"Invalid Date"}))},312:function(t,e,n){"use strict";n.r(e);n(18),n(112),n(35),n(258),n(259),n(114);var r={data:function(){return{}},computed:{recentFiles:function(){return this.$site.pages.filter((function(t){return t.path.includes("beginner")||t.path.includes("intermediate")})).sort((function(t,e){var n=new Date(t.frontmatter.published).getTime()-new Date(e.frontmatter.published).getTime();return n<0?-1:n>0?1:0})).slice(0,5)}}},i=n(10),a=Object(i.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",[n("ul",t._l(t.recentFiles,(function(e,r){return n("li",{key:e},[n("a",{attrs:{href:r.path}},[t._v(t._s(r.title))])])})),0)])}),[],!1,null,null,null);e.default=a.exports}}]);

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{177:function(t,e,n){},262:function(t,e,n){"use strict";var a=n(177);n.n(a).a},339:function(t,e,n){"use strict";n.r(e);var a={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,a=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||a().default)}},i=(n(262),n(10)),r=Object(i.a)(a,void 0,void 0,!1,null,"86b323a0",null);e.default=r.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{394:function(t,e,n){},514:function(t,e,n){"use strict";n(394)},536:function(t,e,n){"use strict";n.r(e);var i={name:"AutoGithubLink",computed:{link:function(){return"https://github.com/sotrh/learn-wgpu/tree/master/code"+this.$page.path}}},r=(n(514),n(23)),u=Object(r.a)(i,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"auto-github-link"},[e("a",{attrs:{href:this.link,target:"_blank",rel:"noopener noreferrer"}},[this._v("Check out the code!")]),this._v(" "),e("OutboundLink")],1)}),[],!1,null,null,null);e.default=u.exports}}]);

@ -0,0 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{396:function(t,e,n){},520:function(t,e,n){"use strict";n(396)},564:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(520),n(23)),a=Object(r.a)(i,void 0,void 0,!1,null,"86b323a0",null);e.default=a.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{311:function(t,e,n){"use strict";n.r(e);var r={computed:{link:function(){return"https://github.com/sotrh/learn-wgpu/tree/master/code"+this.$page.path}}},i=n(10),s=Object(i.a)(r,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"auto-github-link"},[e("a",{attrs:{href:this.link,target:"_blank",rel:"noopener noreferrer"}},[this._v("Check out the code!")]),this._v(" "),e("OutboundLink")],1)}),[],!1,null,null,null);e.default=s.exports}}]);

File diff suppressed because one or more lines are too long

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{310:function(t,e,s){"use strict";s.r(e);var o=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],n={methods:{getMsg:function(){return o[Math.floor(Math.random()*o.length)]}}},i=s(10),h=Object(i.a)(n,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("router-link",{attrs:{to:"/"}},[this._v("Take me home.")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{535:function(t,e,s){"use strict";s.r(e);var o=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],n={methods:{getMsg:function(){return o[Math.floor(Math.random()*o.length)]}}},i=s(23),h=Object(i.a)(n,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("router-link",{attrs:{to:"/"}},[this._v("Take me home.")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]);

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{314:function(t,e,a){"use strict";a.r(e);var n=a(10),r=Object(n.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("h2",{attrs:{id:"what-is-wgpu"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#what-is-wgpu"}},[t._v("#")]),t._v(" What is wgpu?")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://github.com/gfx-rs/wgpu",target:"_blank",rel:"noopener noreferrer"}},[t._v("Wgpu"),a("OutboundLink")],1),t._v(" is a Rust implementation of the "),a("a",{attrs:{href:"https://gpuweb.github.io/gpuweb/",target:"_blank",rel:"noopener noreferrer"}},[t._v("WebGPU API spec"),a("OutboundLink")],1),t._v(". WebGPU is a specification published by the GPU for the Web Community Group. It aims to allow web code access to GPU functions in a safe and reliable manner. It does this by mimicking the Vulkan API, and translating that down to whatever API the host hardware is using (ie. DirectX, Metal, Vulkan).")]),t._v(" "),a("p",[t._v("Wgpu is still in development, so some of this doc is subject to change.")]),t._v(" "),a("h2",{attrs:{id:"why-rust"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#why-rust"}},[t._v("#")]),t._v(" Why Rust?")]),t._v(" "),a("p",[t._v("Wgpu actually has C bindings to allow you to write C/C++ code with it, as well as use other languages that interface with C. That being said, wgpu is written in Rust, and it has some convenient Rust bindings that don't have to jump through any hoops. On top of that, I've been enjoying writing in Rust.")]),t._v(" "),a("p",[t._v("You should be fairly familiar with Rust before using this tutorial as I won't go into much detail on Rust syntax. If you're not super comfortable with Rust you can review the "),a("a",{attrs:{href:"https://www.rust-lang.org/learn",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust tutorial"),a("OutboundLink")],1),t._v(". You should also be familiar with "),a("a",{attrs:{href:"https://doc.rust-lang.org/cargo/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cargo"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("I'm using this project to learn wgpu myself, so I might miss some important details, or explain things badly. I'm always open to constructive feedback.")]),t._v(" "),a("h2",{attrs:{id:"contribution-and-support"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#contribution-and-support"}},[t._v("#")]),t._v(" Contribution and Support")]),t._v(" "),a("ul",[a("li",[t._v("I accept pull requests ("),a("a",{attrs:{href:"https://github.com/sotrh/learn-wgpu",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitHub repo"),a("OutboundLink")],1),t._v(") for fixing issues with this tutorial such as typos, incorrect information, and other inconsistencies.")]),t._v(" "),a("li",[t._v("Due to wgpu's rapidly changing api, I'm not accepting any new pull requests for showcase demos.")]),t._v(" "),a("li",[t._v("If you want to support me directly, check out my "),a("a",{attrs:{href:"https://www.patreon.com/sotrh",target:"_blank",rel:"noopener noreferrer"}},[t._v("patreon"),a("OutboundLink")],1),t._v("!")])]),t._v(" "),a("h2",{attrs:{id:"special-thanks-to-these-patrons"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#special-thanks-to-these-patrons"}},[t._v("#")]),t._v(" Special thanks to these patrons!")]),t._v(" "),a("p",[a("em",[t._v("In no particular order")])]),t._v(" "),a("ul",[a("li",[t._v("Zeh Fernando")]),t._v(" "),a("li",[t._v("The toddling chaos")]),t._v(" "),a("li",[t._v("Jan Šipr")]),t._v(" "),a("li",[t._v("Bernard Llanos")]),t._v(" "),a("li",[t._v("Aron Granberg")]),t._v(" "),a("li",[t._v("Ian Gowen")]),t._v(" "),a("li",[t._v("Paul E Hansen")]),t._v(" "),a("li",[t._v("Lennart")]),t._v(" "),a("li",[t._v("Gunstein Vatnar")]),t._v(" "),a("li",[t._v("David Laban")])])])}),[],!1,null,null,null);e.default=r.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{539:function(t,e,a){"use strict";a.r(e);var n=a(23),r=Object(n.a)({},(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("h2",{attrs:{id:"what-is-wgpu"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#what-is-wgpu"}},[t._v("#")]),t._v(" What is wgpu?")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://github.com/gfx-rs/wgpu",target:"_blank",rel:"noopener noreferrer"}},[t._v("Wgpu"),a("OutboundLink")],1),t._v(" is a Rust implementation of the "),a("a",{attrs:{href:"https://gpuweb.github.io/gpuweb/",target:"_blank",rel:"noopener noreferrer"}},[t._v("WebGPU API spec"),a("OutboundLink")],1),t._v(". WebGPU is a specification published by the GPU for the Web Community Group. It aims to allow web code access to GPU functions in a safe and reliable manner. It does this by mimicking the Vulkan API, and translating that down to whatever API the host hardware is using (ie. DirectX, Metal, Vulkan).")]),t._v(" "),a("p",[t._v("Wgpu is still in development, so some of this doc is subject to change.")]),t._v(" "),a("h2",{attrs:{id:"why-rust"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#why-rust"}},[t._v("#")]),t._v(" Why Rust?")]),t._v(" "),a("p",[t._v("Wgpu actually has C bindings to allow you to write C/C++ code with it, as well as use other languages that interface with C. That being said, wgpu is written in Rust, and it has some convenient Rust bindings that don't have to jump through any hoops. On top of that, I've been enjoying writing in Rust.")]),t._v(" "),a("p",[t._v("You should be fairly familiar with Rust before using this tutorial as I won't go into much detail on Rust syntax. If you're not super comfortable with Rust you can review the "),a("a",{attrs:{href:"https://www.rust-lang.org/learn",target:"_blank",rel:"noopener noreferrer"}},[t._v("Rust tutorial"),a("OutboundLink")],1),t._v(". You should also be familiar with "),a("a",{attrs:{href:"https://doc.rust-lang.org/cargo/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Cargo"),a("OutboundLink")],1),t._v(".")]),t._v(" "),a("p",[t._v("I'm using this project to learn wgpu myself, so I might miss some important details, or explain things badly. I'm always open to constructive feedback.")]),t._v(" "),a("h2",{attrs:{id:"contribution-and-support"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#contribution-and-support"}},[t._v("#")]),t._v(" Contribution and Support")]),t._v(" "),a("ul",[a("li",[t._v("I accept pull requests ("),a("a",{attrs:{href:"https://github.com/sotrh/learn-wgpu",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitHub repo"),a("OutboundLink")],1),t._v(") for fixing issues with this tutorial such as typos, incorrect information, and other inconsistencies.")]),t._v(" "),a("li",[t._v("Due to wgpu's rapidly changing api, I'm not accepting any new pull requests for showcase demos.")]),t._v(" "),a("li",[t._v("If you want to support me directly, check out my "),a("a",{attrs:{href:"https://www.patreon.com/sotrh",target:"_blank",rel:"noopener noreferrer"}},[t._v("patreon"),a("OutboundLink")],1),t._v("!")])]),t._v(" "),a("h2",{attrs:{id:"special-thanks-to-these-patrons"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#special-thanks-to-these-patrons"}},[t._v("#")]),t._v(" Special thanks to these patrons!")]),t._v(" "),a("p",[a("em",[t._v("In no particular order")])]),t._v(" "),a("ul",[a("li",[t._v("Zeh Fernando")]),t._v(" "),a("li",[t._v("The toddling chaos")]),t._v(" "),a("li",[t._v("Jan Šipr")]),t._v(" "),a("li",[t._v("Bernard Llanos")]),t._v(" "),a("li",[t._v("Aron Granberg")]),t._v(" "),a("li",[t._v("Ian Gowen")]),t._v(" "),a("li",[t._v("Paul E Hansen")]),t._v(" "),a("li",[t._v("Lennart")]),t._v(" "),a("li",[t._v("Gunstein Vatnar")]),t._v(" "),a("li",[t._v("David Laban")])])])}),[],!1,null,null,null);e.default=r.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{324:function(t,s,e){"use strict";e.r(s);var i=e(10),n=Object(i.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"sources"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#sources"}},[this._v("#")]),this._v(" Sources")]),this._v(" "),s("ul",[s("li",[this._v("https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading")]),this._v(" "),s("li",[this._v("http://jimmiejohnsson84.me/pages/rendering_pbr.html")])])])}),[],!1,null,null,null);s.default=n.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{549:function(t,s,e){"use strict";e.r(s);var i=e(23),n=Object(i.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"sources"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#sources"}},[this._v("#")]),this._v(" Sources")]),this._v(" "),s("ul",[s("li",[this._v("https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading")]),this._v(" "),s("li",[this._v("http://jimmiejohnsson84.me/pages/rendering_pbr.html")])])])}),[],!1,null,null,null);s.default=n.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{331:function(e,t,o){"use strict";o.r(t);var s=o(10),r=Object(s.a)({},(function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[o("h1",{attrs:{id:"foreword"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#foreword"}},[e._v("#")]),e._v(" Foreword")]),e._v(" "),o("p",[e._v("The articles in this section are not meant to be tutorials. They are showcases of the various things you can do with "),o("code",[e._v("wgpu")]),e._v(". I won't go over specifics of creating "),o("code",[e._v("wgpu")]),e._v(" resources, as those will be covered elsewhere. The code for these examples is still available however, and will be accessible on Github.")])])}),[],!1,null,null,null);t.default=r.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{556:function(e,t,o){"use strict";o.r(t);var s=o(23),r=Object(s.a)({},(function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[o("h1",{attrs:{id:"foreword"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#foreword"}},[e._v("#")]),e._v(" Foreword")]),e._v(" "),o("p",[e._v("The articles in this section are not meant to be tutorials. They are showcases of the various things you can do with "),o("code",[e._v("wgpu")]),e._v(". I won't go over specifics of creating "),o("code",[e._v("wgpu")]),e._v(" resources, as those will be covered elsewhere. The code for these examples is still available however, and will be accessible on Github.")])])}),[],!1,null,null,null);t.default=r.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{338:function(t,s,n){"use strict";n.r(s);var e=n(10),o=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"coming-soon"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#coming-soon"}},[this._v("#")]),this._v(" Coming Soon!")]),this._v(" "),s("p",[this._v("This section has not yet been completed.")])])}),[],!1,null,null,null);s.default=o.exports}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{563:function(t,s,n){"use strict";n.r(s);var e=n(23),o=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"coming-soon"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#coming-soon"}},[this._v("#")]),this._v(" Coming Soon!")]),this._v(" "),s("p",[this._v("This section has not yet been completed.")])])}),[],!1,null,null,null);s.default=o.exports}}]);

@ -1 +0,0 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{155:function(n,w,o){}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{370:function(t,r,e){var n=e(201),i=Math.floor,o=function(t,r){var e=t.length,c=i(e/2);return e<8?u(t,r):a(t,o(n(t,0,c),r),o(n(t,c),r),r)},u=function(t,r){for(var e,n,i=t.length,o=1;o<i;){for(n=o,e=t[o];n&&r(t[n-1],e)>0;)t[n]=t[--n];n!==o++&&(t[n]=e)}return t},a=function(t,r,e,n){for(var i=r.length,o=e.length,u=0,a=0;u<i||a<o;)t[u+a]=u<i&&a<o?n(r[u],e[a])<=0?r[u++]:e[a++]:u<i?r[u++]:e[a++];return t};t.exports=o},371:function(t,r,e){var n=e(42).match(/firefox\/(\d+)/i);t.exports=!!n&&+n[1]},372:function(t,r,e){var n=e(42);t.exports=/MSIE|Trident/.test(n)},373:function(t,r,e){var n=e(42).match(/AppleWebKit\/(\d+)\./);t.exports=!!n&&+n[1]},515:function(t,r,e){"use strict";var n=e(1),i=e(2),o=e(33),u=e(15),a=e(24),c=e(14),f=e(3),s=e(370),l=e(47),v=e(371),h=e(372),d=e(45),p=e(373),g=[],m=i(g.sort),w=i(g.push),b=f((function(){g.sort(void 0)})),k=f((function(){g.sort(null)})),D=l("sort"),x=!f((function(){if(d)return d<70;if(!(v&&v>3)){if(h)return!0;if(p)return p<603;var t,r,e,n,i="";for(t=65;t<76;t++){switch(r=String.fromCharCode(t),t){case 66:case 69:case 70:case 72:e=3;break;case 68:case 71:e=4;break;default:e=2}for(n=0;n<47;n++)g.push({k:r+n,v:e})}for(g.sort((function(t,r){return r.v-t.v})),n=0;n<g.length;n++)r=g[n].k.charAt(0),i.charAt(i.length-1)!==r&&(i+=r);return"DGBEFHACIJK"!==i}}));n({target:"Array",proto:!0,forced:b||!k||!D||!x},{sort:function(t){void 0!==t&&o(t);var r=u(this);if(x)return void 0===t?m(r):m(r,t);var e,n,i=[],f=a(r);for(n=0;n<f;n++)n in r&&w(i,r[n]);for(s(i,function(t){return function(r,e){return void 0===e?-1:void 0===r?1:void 0!==t?+t(r,e)||0:c(r)>c(e)?1:-1}}(t)),e=i.length,n=0;n<e;)r[n]=i[n++];for(;n<f;)delete r[n++];return r}})},516:function(t,r,e){var n=e(2),i=e(16),o=Date.prototype,u=n(o.toString),a=n(o.getTime);"Invalid Date"!=String(new Date(NaN))&&i(o,"toString",(function(){var t=a(this);return t==t?u(this):"Invalid Date"}))},537:function(t,r,e){"use strict";e.r(r);e(62),e(515),e(38),e(8),e(213),e(214),e(516);var n={name:"RecentArticles",data:function(){return{}},computed:{recentFiles:function(){return this.$site.pages.filter((function(t){return t.regularPath.includes("beginner")||t.regularPath.includes("intermediate")})).sort((function(t,r){var e=new Date(t.frontmatter.published).getTime()-new Date(r.frontmatter.published).getTime();return e<0?-1:e>0?1:0})).slice(0,5)}}},i=e(23),o=Object(i.a)(n,(function(){var t=this,r=t.$createElement,e=t._self._c||r;return e("div",[e("ul",t._l(t.recentFiles,(function(r,n){return e("li",{key:r},[e("a",{attrs:{href:n.path}},[t._v(t._s(n.title))])])})),0)])}),[],!1,null,null,null);r.default=o.exports}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,16 +4,27 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Model Loading | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Model Loading">
<meta property="og:type" content="website">
<meta property="og:url" content="/beginner/tutorial9-models/">
<meta name="twitter:title" content="Model Loading">
<meta name="twitter:url" content="/beginner/tutorial9-models/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Model Loading"><meta property="og:type" content="website"><meta property="og:url" content="/beginner/tutorial9-models/"><meta name="twitter:title" content="Model Loading"><meta name="twitter:url" content="/beginner/tutorial9-models/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/11.918ac8f8.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/25.5a7a1f31.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/13.c9d2040b.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/10.d40f290b.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/14.fa667d51.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="active sidebar-link">Model Loading</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#accessing-files-in-the-res-folder" class="sidebar-link">Accessing files in the res folder</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#loading-models-with-tobj" class="sidebar-link">Loading models with TOBJ</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#rendering-a-mesh" class="sidebar-link">Rendering a mesh</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#using-the-correct-textures" class="sidebar-link">Using the correct textures</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#rendering-the-entire-model" class="sidebar-link">Rendering the entire model</a></li></ul></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="model-loading"><a href="#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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// model.rs</span>
<span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">Vertex</span> <span class="token punctuation">{</span>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" aria-current="page" class="active sidebar-link">Model Loading</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#accessing-files-in-the-res-folder" class="sidebar-link">Accessing files in the res folder</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#accessing-files-from-wasm" class="sidebar-link">Accessing files from WASM</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#loading-models-with-tobj" class="sidebar-link">Loading models with TOBJ</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#rendering-a-mesh" class="sidebar-link">Rendering a mesh</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#using-the-correct-textures" class="sidebar-link">Using the correct textures</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/beginner/tutorial9-models/#rendering-the-entire-model" class="sidebar-link">Rendering the entire model</a></li></ul></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="model-loading"><a href="#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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// model.rs</span>
<span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">Vertex</span> <span class="token punctuation">{</span>
<span class="token keyword">fn</span> <span class="token function-definition function">desc</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">VertexBufferLayout</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
@ -64,8 +75,8 @@
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Since the <code>desc</code> method is implemented on the <code>Vertex</code> trait, the trait needs to be imported before the method will be accessible. Put the import towards the top of the file with the others.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">Vertex</span><span class="token punctuation">;</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 <a href="https://github.com/sotrh/learn-wgpu/blob/master/code/beginner/tutorial9-models/res/cube.zip" target="_blank" rel="noopener noreferrer">zip file<svg xmlns="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"><path fill="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> <polygon fill="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> <h2 id="accessing-files-in-the-res-folder"><a href="#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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">anyhow<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
</code></pre></div><p>Since the <code>desc</code> method is implemented on the <code>Vertex</code> trait, the trait needs to be imported before the method will be accessible. Put the import towards the top of the file with the others.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">Vertex</span><span class="token punctuation">;</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 <a href="https://github.com/sotrh/learn-wgpu/blob/master/code/beginner/tutorial9-models/res/cube.zip" target="_blank" rel="noopener noreferrer">zip file<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></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> <h2 id="accessing-files-in-the-res-folder"><a href="#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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">anyhow<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">fs_extra<span class="token punctuation">::</span></span>copy_items<span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">fs_extra<span class="token punctuation">::</span>dir<span class="token punctuation">::</span></span><span class="token class-name">CopyOptions</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span></span>env<span class="token punctuation">;</span>
@ -87,7 +98,74 @@
<span class="token key property">anyhow</span> <span class="token punctuation">=</span> <span class="token string">&quot;1.0&quot;</span>
<span class="token key property">fs_extra</span> <span class="token punctuation">=</span> <span class="token string">&quot;1.2&quot;</span>
<span class="token key property">glob</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.3&quot;</span>
</code></pre></div><h2 id="loading-models-with-tobj"><a href="#loading-models-with-tobj" class="header-anchor">#</a> Loading models with TOBJ</h2> <p>We're going to use the <a href="https://docs.rs/tobj/3.0/tobj/" target="_blank" rel="noopener noreferrer">tobj<svg xmlns="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"><path fill="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> <polygon fill="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. Let's add it to our <code>Cargo.toml</code>.</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token punctuation">[</span><span class="token table class-name">dependencies</span><span class="token punctuation">]</span>
</code></pre></div><h2 id="accessing-files-from-wasm"><a href="#accessing-files-from-wasm" class="header-anchor">#</a> Accessing files from WASM</h2> <p>By design, you can't access files on a users filesystem in Web Assembly. Instead we'll serve those files up using a web serve, and then load those files into our code using an http request. In order to simplify this, let's create a file called <code>resources.rs</code> to handle this for us. We'll create two functions that will load text files and binary files respectively.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>io<span class="token punctuation">::</span></span><span class="token punctuation">{</span><span class="token class-name">BufReader</span><span class="token punctuation">,</span> <span class="token class-name">Cursor</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">cfg_if<span class="token punctuation">::</span></span>cfg_if<span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">wgpu<span class="token punctuation">::</span>util<span class="token punctuation">::</span></span><span class="token class-name">DeviceExt</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token keyword">crate</span><span class="token punctuation">::</span><span class="token punctuation">{</span>model<span class="token punctuation">,</span> texture<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token attribute attr-name">#[cfg(target_arch = <span class="token string">&quot;wasm32&quot;</span>)]</span>
<span class="token keyword">fn</span> <span class="token function-definition function">format_url</span><span class="token punctuation">(</span>file_name<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">str</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token namespace">reqwest<span class="token punctuation">::</span></span><span class="token class-name">Url</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> window <span class="token operator">=</span> <span class="token namespace">web_sys<span class="token punctuation">::</span></span><span class="token function">window</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> location <span class="token operator">=</span> window<span class="token punctuation">.</span><span class="token function">location</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> base <span class="token operator">=</span> <span class="token namespace">reqwest<span class="token punctuation">::</span></span><span class="token class-name">Url</span><span class="token punctuation">::</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token macro property">format!</span><span class="token punctuation">(</span>
<span class="token string">&quot;{}/{}/&quot;</span><span class="token punctuation">,</span>
location<span class="token punctuation">.</span><span class="token function">origin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token macro property">option_env!</span><span class="token punctuation">(</span><span class="token string">&quot;RES_PATH&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap_or</span><span class="token punctuation">(</span><span class="token string">&quot;res&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
base<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">async</span> <span class="token keyword">fn</span> <span class="token function-definition function">load_string</span><span class="token punctuation">(</span>file_name<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">str</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token namespace">anyhow<span class="token punctuation">::</span></span><span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token class-name">String</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token macro property">cfg_if!</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token attribute attr-name">#[cfg(target_arch = <span class="token string">&quot;wasm32&quot;</span>)]</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> url <span class="token operator">=</span> <span class="token function">format_url</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> txt <span class="token operator">=</span> <span class="token namespace">reqwest<span class="token punctuation">::</span></span><span class="token function">get</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span>
<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> path <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>path<span class="token punctuation">::</span></span><span class="token class-name">Path</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token macro property">env!</span><span class="token punctuation">(</span><span class="token string">&quot;OUT_DIR&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">&quot;res&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> txt <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>fs<span class="token punctuation">::</span></span><span class="token function">read_to_string</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token class-name">Ok</span><span class="token punctuation">(</span>txt<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">pub</span> <span class="token keyword">async</span> <span class="token keyword">fn</span> <span class="token function-definition function">load_binary</span><span class="token punctuation">(</span>file_name<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">str</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token namespace">anyhow<span class="token punctuation">::</span></span><span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token class-name">Vec</span><span class="token operator">&lt;</span><span class="token keyword">u8</span><span class="token operator">&gt;&gt;</span> <span class="token punctuation">{</span>
<span class="token macro property">cfg_if!</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token attribute attr-name">#[cfg(target_arch = <span class="token string">&quot;wasm32&quot;</span>)]</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> url <span class="token operator">=</span> <span class="token function">format_url</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> data <span class="token operator">=</span> <span class="token namespace">reqwest<span class="token punctuation">::</span></span><span class="token function">get</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span>
<span class="token punctuation">.</span><span class="token function">bytes</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span>
<span class="token punctuation">.</span><span class="token function">to_vec</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> path <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>path<span class="token punctuation">::</span></span><span class="token class-name">Path</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token macro property">env!</span><span class="token punctuation">(</span><span class="token string">&quot;OUT_DIR&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">&quot;res&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> data <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>fs<span class="token punctuation">::</span></span><span class="token function">read</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token class-name">Ok</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><div class="note"><p>We're using <code>OUT_DIR</code> on desktop to get at our <code>res</code> folder.</p></div> <p>I'm using <a href="https://docs.rs/reqwest" target="_blank" rel="noopener noreferrer">reqwest<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></a> to handle loading the requests when using WASM. Add the following to the Cargo.toml:</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token punctuation">[</span><span class="token table class-name">target.'cfg(target_arch = &quot;wasm32&quot;)'.dependencies</span><span class="token punctuation">]</span>
<span class="token comment"># Other dependencies</span>
<span class="token key property">reqwest</span> <span class="token punctuation">=</span> <span class="token punctuation">{</span> <span class="token key property">version</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.11&quot;</span> <span class="token punctuation">}</span>
</code></pre></div><p>We'll also need to add the <code>Location</code> feature to <code>web-sys</code>:</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token key property">web-sys</span> <span class="token punctuation">=</span> <span class="token punctuation">{</span> <span class="token key property">version</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.3&quot;</span><span class="token punctuation">,</span> <span class="token key property">features</span> <span class="token punctuation">=</span> <span class="token punctuation">[</span>
<span class="token string">&quot;Document&quot;</span><span class="token punctuation">,</span>
<span class="token string">&quot;Window&quot;</span><span class="token punctuation">,</span>
<span class="token string">&quot;Element&quot;</span><span class="token punctuation">,</span>
<span class="token string">&quot;Location&quot;</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">}</span>
</code></pre></div><p>Make sure to add <code>resources</code> as a module in <code>lib.rs</code>:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">mod</span> <span class="token module-declaration namespace">resources</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="loading-models-with-tobj"><a href="#loading-models-with-tobj" class="header-anchor">#</a> Loading models with TOBJ</h2> <p>We're going to use the <a href="https://docs.rs/tobj/3.0/tobj/" target="_blank" rel="noopener noreferrer">tobj<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></a> library to load our model. Let's add it to our <code>Cargo.toml</code>.</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token punctuation">[</span><span class="token table class-name">dependencies</span><span class="token punctuation">]</span>
<span class="token comment"># other dependencies...</span>
<span class="token key property">tobj</span> <span class="token punctuation">=</span> <span class="token string">&quot;3.0&quot;</span>
</code></pre></div><p>Before we can load our model though, we need somewhere to put it.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// model.rs</span>
@ -108,77 +186,69 @@
<span class="token keyword">pub</span> num_elements<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
<span class="token keyword">pub</span> material<span class="token punctuation">:</span> <span class="token keyword">usize</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p>The <code>Material</code> is pretty simple, it's just the name and one texture. Our cube obj actually has 2 textures, but one is a normal map, and we'll get to those <a href="../../intermediate/tutorial11-normals">later</a>. The name is more for debugging purposes.</p> <p>Speaking of textures, we'll need to add a <code>load()</code> method to <code>Texture</code> in <code>texture.rs</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>path<span class="token punctuation">::</span></span><span class="token class-name">Path</span><span class="token punctuation">;</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">load</span><span class="token operator">&lt;</span><span class="token class-name">P</span><span class="token punctuation">:</span> <span class="token class-name">AsRef</span><span class="token operator">&lt;</span><span class="token class-name">Path</span><span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>
</code></pre></div><p>The <code>Material</code> is pretty simple, it's just the name and one texture. Our cube obj actually has 2 textures, but one is a normal map, and we'll get to those <a href="../../intermediate/tutorial11-normals">later</a>. The name is more for debugging purposes.</p> <p>Speaking of textures, we'll need to add a function to load a <code>Texture</code> in <code>resources.rs</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code>
<span class="token keyword">pub</span> <span class="token keyword">async</span> <span class="token keyword">fn</span> <span class="token function-definition function">load_texture</span><span class="token punctuation">(</span>
file_name<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">str</span><span class="token punctuation">,</span>
device<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Device</span><span class="token punctuation">,</span>
queue<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Queue</span><span class="token punctuation">,</span>
path<span class="token punctuation">:</span> <span class="token class-name">P</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token keyword">Self</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token comment">// Needed to appease the borrow checker</span>
<span class="token keyword">let</span> path_copy <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">as_ref</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">to_path_buf</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> label <span class="token operator">=</span> path_copy<span class="token punctuation">.</span><span class="token function">to_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> img <span class="token operator">=</span> <span class="token namespace">image<span class="token punctuation">::</span></span><span class="token function">open</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token keyword">Self</span><span class="token punctuation">::</span><span class="token function">from_image</span><span class="token punctuation">(</span>device<span class="token punctuation">,</span> queue<span class="token punctuation">,</span> <span class="token operator">&amp;</span>img<span class="token punctuation">,</span> label<span class="token punctuation">)</span>
<span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token namespace">anyhow<span class="token punctuation">::</span></span><span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token namespace">texture<span class="token punctuation">::</span></span><span class="token class-name">Texture</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> data <span class="token operator">=</span> <span class="token function">load_binary</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token namespace">texture<span class="token punctuation">::</span></span><span class="token class-name">Texture</span><span class="token punctuation">::</span><span class="token function">from_bytes</span><span class="token punctuation">(</span>device<span class="token punctuation">,</span> queue<span class="token punctuation">,</span> <span class="token operator">&amp;</span>data<span class="token punctuation">,</span> file_name<span class="token punctuation">)</span>
<span class="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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token keyword">crate</span><span class="token module-declaration namespace"><span class="token punctuation">::</span>texture</span><span class="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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> rgba <span class="token operator">=</span> img<span class="token punctuation">.</span><span class="token function">to_rgba8</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="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> <div class="language-rust extra-class"><pre class="language-rust"><code> <span class="token comment">//...</span>
<span class="token operator">&amp;</span>rgba<span class="token punctuation">,</span> <span class="token comment">// UPDATED!</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">ImageDataLayout</span> <span class="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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">impl</span> <span class="token class-name">Model</span> <span class="token punctuation">{</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">load</span><span class="token operator">&lt;</span><span class="token class-name">P</span><span class="token punctuation">:</span> <span class="token class-name">AsRef</span><span class="token operator">&lt;</span><span class="token class-name">Path</span><span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>
device<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Device</span><span class="token punctuation">,</span>
queue<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Queue</span><span class="token punctuation">,</span>
layout<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupLayout</span><span class="token punctuation">,</span>
path<span class="token punctuation">:</span> <span class="token class-name">P</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token keyword">Self</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> <span class="token punctuation">(</span>obj_models<span class="token punctuation">,</span> obj_materials<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token namespace">tobj<span class="token punctuation">::</span></span><span class="token function">load_obj</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">as_ref</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token class-name">LoadOptions</span> <span class="token punctuation">{</span>
triangulate<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
single_index<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">..</span><span class="token class-name">Default</span><span class="token punctuation">::</span><span class="token function">default</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> obj_materials <span class="token operator">=</span> obj_materials<span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token comment">// We're assuming that the texture files are stored with the obj file</span>
<span class="token keyword">let</span> containing_folder <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">as_ref</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">parent</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">context</span><span class="token punctuation">(</span><span class="token string">&quot;Directory has no parent&quot;</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> materials <span class="token operator">=</span> <span class="token class-name">Vec</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> mat <span class="token keyword">in</span> obj_materials <span class="token punctuation">{</span>
<span class="token keyword">let</span> diffuse_path <span class="token operator">=</span> mat<span class="token punctuation">.</span>diffuse_texture<span class="token punctuation">;</span>
<span class="token keyword">let</span> diffuse_texture <span class="token operator">=</span> <span class="token namespace">texture<span class="token punctuation">::</span></span><span class="token class-name">Texture</span><span class="token punctuation">::</span><span class="token function">load</span><span class="token punctuation">(</span>device<span class="token punctuation">,</span> queue<span class="token punctuation">,</span> containing_folder<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>diffuse_path<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> bind_group <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_bind_group</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupDescriptor</span> <span class="token punctuation">{</span>
layout<span class="token punctuation">,</span>
entries<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token punctuation">[</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupEntry</span> <span class="token punctuation">{</span>
binding<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
resource<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindingResource</span><span class="token punctuation">::</span><span class="token class-name">TextureView</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>diffuse_texture<span class="token punctuation">.</span>view<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupEntry</span> <span class="token punctuation">{</span>
binding<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
resource<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindingResource</span><span class="token punctuation">::</span><span class="token class-name">Sampler</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>diffuse_texture<span class="token punctuation">.</span>sampler<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
label<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>The <code>load_texture</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><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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">async</span> <span class="token keyword">fn</span> <span class="token function-definition function">load_model</span><span class="token punctuation">(</span>
file_name<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token keyword">str</span><span class="token punctuation">,</span>
device<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Device</span><span class="token punctuation">,</span>
queue<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">Queue</span><span class="token punctuation">,</span>
layout<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupLayout</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token namespace">anyhow<span class="token punctuation">::</span></span><span class="token class-name">Result</span><span class="token operator">&lt;</span><span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">Model</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> obj_text <span class="token operator">=</span> <span class="token function">load_string</span><span class="token punctuation">(</span>file_name<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> obj_cursor <span class="token operator">=</span> <span class="token class-name">Cursor</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>obj_text<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> obj_reader <span class="token operator">=</span> <span class="token class-name">BufReader</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>obj_cursor<span class="token punctuation">)</span><span class="token punctuation">;</span>
materials<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token class-name">Material</span> <span class="token punctuation">{</span>
name<span class="token punctuation">:</span> mat<span class="token punctuation">.</span>name<span class="token punctuation">,</span>
diffuse_texture<span class="token punctuation">,</span>
bind_group<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> <span class="token punctuation">(</span>models<span class="token punctuation">,</span> obj_materials<span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token namespace">tobj<span class="token punctuation">::</span></span><span class="token function">load_obj_buf_async</span><span class="token punctuation">(</span>
<span class="token operator">&amp;</span><span class="token keyword">mut</span> obj_reader<span class="token punctuation">,</span>
<span class="token operator">&amp;</span><span class="token namespace">tobj<span class="token punctuation">::</span></span><span class="token class-name">LoadOptions</span> <span class="token punctuation">{</span>
triangulate<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
single_index<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token punctuation">..</span><span class="token class-name">Default</span><span class="token punctuation">::</span><span class="token function">default</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>p<span class="token closure-punctuation punctuation">|</span></span> <span class="token keyword">async</span> <span class="token keyword">move</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> mat_text <span class="token operator">=</span> <span class="token function">load_string</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>p<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token namespace">tobj<span class="token punctuation">::</span></span><span class="token function">load_mtl_buf</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token class-name">BufReader</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token class-name">Cursor</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span>mat_text<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> materials <span class="token operator">=</span> <span class="token class-name">Vec</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> m <span class="token keyword">in</span> obj_materials<span class="token operator">?</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> diffuse_texture <span class="token operator">=</span> <span class="token function">load_texture</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>m<span class="token punctuation">.</span>diffuse_texture<span class="token punctuation">,</span> device<span class="token punctuation">,</span> queue<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token operator">?</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> bind_group <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_bind_group</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupDescriptor</span> <span class="token punctuation">{</span>
layout<span class="token punctuation">,</span>
entries<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token punctuation">[</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupEntry</span> <span class="token punctuation">{</span>
binding<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
resource<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindingResource</span><span class="token punctuation">::</span><span class="token class-name">TextureView</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>diffuse_texture<span class="token punctuation">.</span>view<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroupEntry</span> <span class="token punctuation">{</span>
binding<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
resource<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindingResource</span><span class="token punctuation">::</span><span class="token class-name">Sampler</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>diffuse_texture<span class="token punctuation">.</span>sampler<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
label<span class="token punctuation">:</span> <span class="token class-name">None</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
materials<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">Material</span> <span class="token punctuation">{</span>
name<span class="token punctuation">:</span> m<span class="token punctuation">.</span>name<span class="token punctuation">,</span>
diffuse_texture<span class="token punctuation">,</span>
bind_group<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> meshes <span class="token operator">=</span> <span class="token class-name">Vec</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> m <span class="token keyword">in</span> obj_models <span class="token punctuation">{</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> vertices <span class="token operator">=</span> <span class="token class-name">Vec</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token number">0</span><span class="token punctuation">..</span>m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>positions<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">3</span> <span class="token punctuation">{</span>
vertices<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token class-name">ModelVertex</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> meshes <span class="token operator">=</span> models
<span class="token punctuation">.</span><span class="token function">into_iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>m<span class="token closure-punctuation punctuation">|</span></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> vertices <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">..</span>m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>positions<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>i<span class="token closure-punctuation punctuation">|</span></span> <span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">ModelVertex</span> <span class="token punctuation">{</span>
position<span class="token punctuation">:</span> <span class="token punctuation">[</span>
m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>positions<span class="token punctuation">[</span>i <span class="token operator">*</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>positions<span class="token punctuation">[</span>i <span class="token operator">*</span> <span class="token number">3</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
@ -190,37 +260,35 @@
m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>normals<span class="token punctuation">[</span>i <span class="token operator">*</span> <span class="token number">3</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>normals<span class="token punctuation">[</span>i <span class="token operator">*</span> <span class="token number">3</span> <span class="token operator">+</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">::</span><span class="token operator">&lt;</span><span class="token class-name">Vec</span><span class="token operator">&lt;</span>_<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> vertex_buffer <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_buffer_init</span><span class="token punctuation">(</span>
<span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span>util<span class="token punctuation">::</span></span><span class="token class-name">BufferInitDescriptor</span> <span class="token punctuation">{</span>
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">&quot;{:?} Vertex Buffer&quot;</span><span class="token punctuation">,</span> path<span class="token punctuation">.</span><span class="token function">as_ref</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
contents<span class="token punctuation">:</span> <span class="token namespace">bytemuck<span class="token punctuation">::</span></span><span class="token function">cast_slice</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>vertices<span class="token punctuation">)</span><span class="token punctuation">,</span>
usage<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferUsages</span><span class="token punctuation">::</span><span class="token constant">VERTEX</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> index_buffer <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_buffer_init</span><span class="token punctuation">(</span>
<span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span>util<span class="token punctuation">::</span></span><span class="token class-name">BufferInitDescriptor</span> <span class="token punctuation">{</span>
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">&quot;{:?} Index Buffer&quot;</span><span class="token punctuation">,</span> path<span class="token punctuation">.</span><span class="token function">as_ref</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
contents<span class="token punctuation">:</span> <span class="token namespace">bytemuck<span class="token punctuation">::</span></span><span class="token function">cast_slice</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>indices<span class="token punctuation">)</span><span class="token punctuation">,</span>
usage<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferUsages</span><span class="token punctuation">::</span><span class="token constant">INDEX</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
meshes<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token class-name">Mesh</span> <span class="token punctuation">{</span>
name<span class="token punctuation">:</span> m<span class="token punctuation">.</span>name<span class="token punctuation">,</span>
<span class="token keyword">let</span> vertex_buffer <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_buffer_init</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span>util<span class="token punctuation">::</span></span><span class="token class-name">BufferInitDescriptor</span> <span class="token punctuation">{</span>
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">&quot;{:?} Vertex Buffer&quot;</span><span class="token punctuation">,</span> file_name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
contents<span class="token punctuation">:</span> <span class="token namespace">bytemuck<span class="token punctuation">::</span></span><span class="token function">cast_slice</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>vertices<span class="token punctuation">)</span><span class="token punctuation">,</span>
usage<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferUsages</span><span class="token punctuation">::</span><span class="token constant">VERTEX</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> index_buffer <span class="token operator">=</span> device<span class="token punctuation">.</span><span class="token function">create_buffer_init</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token namespace">wgpu<span class="token punctuation">::</span>util<span class="token punctuation">::</span></span><span class="token class-name">BufferInitDescriptor</span> <span class="token punctuation">{</span>
label<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">&quot;{:?} Index Buffer&quot;</span><span class="token punctuation">,</span> file_name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
contents<span class="token punctuation">:</span> <span class="token namespace">bytemuck<span class="token punctuation">::</span></span><span class="token function">cast_slice</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>indices<span class="token punctuation">)</span><span class="token punctuation">,</span>
usage<span class="token punctuation">:</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BufferUsages</span><span class="token punctuation">::</span><span class="token constant">INDEX</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">Mesh</span> <span class="token punctuation">{</span>
name<span class="token punctuation">:</span> file_name<span class="token punctuation">.</span><span class="token function">to_string</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
vertex_buffer<span class="token punctuation">,</span>
index_buffer<span class="token punctuation">,</span>
num_elements<span class="token punctuation">:</span> m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>indices<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
material<span class="token punctuation">:</span> m<span class="token punctuation">.</span>mesh<span class="token punctuation">.</span>material_id<span class="token punctuation">.</span><span class="token function">unwrap_or</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">::</span><span class="token operator">&lt;</span><span class="token class-name">Vec</span><span class="token operator">&lt;</span>_<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token keyword">Self</span> <span class="token punctuation">{</span> meshes<span class="token punctuation">,</span> materials <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">Model</span> <span class="token punctuation">{</span> meshes<span class="token punctuation">,</span> materials <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="rendering-a-mesh"><a href="#rendering-a-mesh" class="header-anchor">#</a> Rendering a mesh</h2> <p>Before we can draw the model, we need to be able to draw an individual mesh. Let's create a trait called <code>DrawModel</code>, and implement it for <code>RenderPass</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">DrawModel</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
</code></pre></div><h2 id="rendering-a-mesh"><a href="#rendering-a-mesh" class="header-anchor">#</a> Rendering a mesh</h2> <p>Before we can draw the model, we need to be able to draw an individual mesh. Let's create a trait called <code>DrawModel</code>, and implement it for <code>RenderPass</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// model.rs</span>
<span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">DrawModel</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">fn</span> <span class="token function-definition function">draw_mesh</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> mesh<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token lifetime-annotation symbol">'a</span> <span class="token class-name">Mesh</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">fn</span> <span class="token function-definition function">draw_mesh_instanced</span><span class="token punctuation">(</span>
<span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span>
@ -246,7 +314,7 @@
<span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">draw_indexed</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">..</span>mesh<span class="token punctuation">.</span>num_elements<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> instances<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>We could have put this methods in <code>impl Model</code>, but I felt it made more sense to have the <code>RenderPass</code> do all the rendering, as that's kind of it's job. This does mean we have to import <code>DrawModel</code> when we go to render though.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// main.rs</span>
</code></pre></div><p>We could have put this methods in an <code>impl Model</code>, but I felt it made more sense to have the <code>RenderPass</code> do all the rendering, as that's kind of it's job. This does mean we have to import <code>DrawModel</code> when we go to render though.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// lib.rs</span>
render_pass<span class="token punctuation">.</span><span class="token function">set_vertex_buffer</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>instance_buffer<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token punctuation">..</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">set_pipeline</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>render_pipeline<span class="token punctuation">)</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">set_bind_group</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>diffuse_bind_group<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
@ -254,14 +322,13 @@ render_pass<span class="token punctuation">.</span><span class="token function">
<span class="token keyword">use</span> <span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">DrawModel</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">draw_mesh_instanced</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>obj_model<span class="token punctuation">.</span>meshes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">..</span><span class="token keyword">self</span><span class="token punctuation">.</span>instances<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token keyword">u32</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Before that though we need to actually load the model and save it to <code>State</code>. Put the following in <code>State::new()</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> res_dir <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>path<span class="token punctuation">::</span></span><span class="token class-name">Path</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token macro property">env!</span><span class="token punctuation">(</span><span class="token string">&quot;OUT_DIR&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">&quot;res&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> obj_model <span class="token operator">=</span> <span class="token namespace">model<span class="token punctuation">::</span></span><span class="token class-name">Model</span><span class="token punctuation">::</span><span class="token function">load</span><span class="token punctuation">(</span>
</code></pre></div><p>Before that though we need to actually load the model and save it to <code>State</code>. Put the following in <code>State::new()</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> obj_model <span class="token operator">=</span> <span class="token namespace">resources<span class="token punctuation">::</span></span><span class="token function">load_model</span><span class="token punctuation">(</span>
<span class="token string">&quot;cube.obj&quot;</span><span class="token punctuation">,</span>
<span class="token operator">&amp;</span>device<span class="token punctuation">,</span>
<span class="token operator">&amp;</span>queue<span class="token punctuation">,</span>
<span class="token operator">&amp;</span>texture_bind_group_layout<span class="token punctuation">,</span>
res_dir<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">&quot;cube.obj&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><div class="note"><p>We're using <code>OUT_DIR</code> here to get at our <code>res</code> folder.</p></div> <p>Our new model is a bit bigger than our previous one so we're gonna need to adjust the spacing on our instances a bit.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">const</span> <span class="token constant">SPACE_BETWEEN</span><span class="token punctuation">:</span> <span class="token keyword">f32</span> <span class="token operator">=</span> <span class="token number">3.0</span><span class="token punctuation">;</span>
<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">.</span><span class="token function">unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Our new model is a bit bigger than our previous one so we're gonna need to adjust the spacing on our instances a bit.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">const</span> <span class="token constant">SPACE_BETWEEN</span><span class="token punctuation">:</span> <span class="token keyword">f32</span> <span class="token operator">=</span> <span class="token number">3.0</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> instances <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">..</span><span class="token constant">NUM_INSTANCES_PER_ROW</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">flat_map</span><span class="token punctuation">(</span><span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>z<span class="token closure-punctuation punctuation">|</span></span> <span class="token punctuation">{</span>
<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">..</span><span class="token constant">NUM_INSTANCES_PER_ROW</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token keyword">move</span> <span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>x<span class="token closure-punctuation punctuation">|</span></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> x <span class="token operator">=</span> <span class="token constant">SPACE_BETWEEN</span> <span class="token operator">*</span> <span class="token punctuation">(</span>x <span class="token keyword">as</span> <span class="token keyword">f32</span> <span class="token operator">-</span> <span class="token constant">NUM_INSTANCES_PER_ROW</span> <span class="token keyword">as</span> <span class="token keyword">f32</span> <span class="token operator">/</span> <span class="token number">2.0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
@ -280,7 +347,7 @@ render_pass<span class="token punctuation">.</span><span class="token function">
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">::</span><span class="token operator">&lt;</span><span class="token class-name">Vec</span><span class="token operator">&lt;</span>_<span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>With all that done, you should get something like this.</p> <p><img src="/learn-wgpu/assets/img/cubes.988d14be.png" alt="cubes.png"></p> <h2 id="using-the-correct-textures"><a href="#using-the-correct-textures" class="header-anchor">#</a> Using the correct textures</h2> <p>If you look at the texture files for our obj, you'll see that they don't match up to our obj. The texture we want to see is this one,</p> <p><img src="/learn-wgpu/assets/img/cube-diffuse.03fc55af.jpg" alt="cube-diffuse.jpg"></p> <p>but we're still getting our happy tree texture.</p> <p>The reason for this is quite simple. Though we've created our textures we haven't created a bind group to give to the <code>RenderPass</code>. We're still using our old <code>diffuse_bind_group</code>. If we want to change that we need to use the bind group from our materials - the <code>bind_group</code> member of the <code>Material</code> struct.</p> <p>We're going to add a material parameter to <code>DrawModel</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">DrawModel</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
</code></pre></div><p>With all that done, you should get something like this.</p> <p><img src="/learn-wgpu/assets/img/cubes.988d14be.png" alt="cubes.png"></p> <h2 id="using-the-correct-textures"><a href="#using-the-correct-textures" class="header-anchor">#</a> Using the correct textures</h2> <p>If you look at the texture files for our obj, you'll see that they don't match up to our obj. The texture we want to see is this one,</p> <p><img src="/learn-wgpu/assets/img/cube-diffuse.03fc55af.jpg" alt="cube-diffuse.jpg"></p> <p>but we're still getting our happy tree texture.</p> <p>The reason for this is quite simple. Though we've created our textures we haven't created a bind group to give to the <code>RenderPass</code>. We're still using our old <code>diffuse_bind_group</code>. If we want to change that we need to use the bind group from our materials - the <code>bind_group</code> member of the <code>Material</code> struct.</p> <p>We're going to add a material parameter to <code>DrawModel</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">DrawModel</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">fn</span> <span class="token function-definition function">draw_mesh</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> mesh<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token lifetime-annotation symbol">'a</span> <span class="token class-name">Mesh</span><span class="token punctuation">,</span> material<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token lifetime-annotation symbol">'a</span> <span class="token class-name">Material</span><span class="token punctuation">,</span> camera_bind_group<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token lifetime-annotation symbol">'a</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroup</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">fn</span> <span class="token function-definition function">draw_mesh_instanced</span><span class="token punctuation">(</span>
<span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span>
@ -321,7 +388,7 @@ render_pass<span class="token punctuation">.</span><span class="token function">
<span class="token keyword">let</span> mesh <span class="token operator">=</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>obj_model<span class="token punctuation">.</span>meshes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> material <span class="token operator">=</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>obj_model<span class="token punctuation">.</span>materials<span class="token punctuation">[</span>mesh<span class="token punctuation">.</span>material<span class="token punctuation">]</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">draw_mesh_instanced</span><span class="token punctuation">(</span>mesh<span class="token punctuation">,</span> material<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">..</span><span class="token keyword">self</span><span class="token punctuation">.</span>instances<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token keyword">u32</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>camera_bind_group<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>With all that in place we should get the following.</p> <p><img src="/learn-wgpu/assets/img/cubes-correct.2db711eb.png" alt="cubes-correct.png"></p> <h2 id="rendering-the-entire-model"><a href="#rendering-the-entire-model" class="header-anchor">#</a> Rendering the entire model</h2> <p>Right now we are specifying the mesh and the material directly. This is useful if we want to draw a mesh with a different material. We're also not rendering other parts of the model (if we had some). Let's create a method for <code>DrawModel</code> that will draw all the parts of the model with their respective materials.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token class-name">DrawModel</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
</code></pre></div><p>With all that in place we should get the following.</p> <p><img src="/learn-wgpu/assets/img/cubes-correct.2db711eb.png" alt="cubes-correct.png"></p> <h2 id="rendering-the-entire-model"><a href="#rendering-the-entire-model" class="header-anchor">#</a> Rendering the entire model</h2> <p>Right now we are specifying the mesh and the material directly. This is useful if we want to draw a mesh with a different material. We're also not rendering other parts of the model (if we had some). Let's create a method for <code>DrawModel</code> that will draw all the parts of the model with their respective materials.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">DrawModel</span><span class="token operator">&lt;</span><span class="token lifetime-annotation symbol">'a</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token comment">// ...</span>
<span class="token keyword">fn</span> <span class="token function-definition function">draw_model</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> model<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token lifetime-annotation symbol">'a</span> <span class="token class-name">Model</span><span class="token punctuation">,</span> camera_bind_group<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token lifetime-annotation symbol">'a</span> <span class="token namespace">wgpu<span class="token punctuation">::</span></span><span class="token class-name">BindGroup</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">fn</span> <span class="token function-definition function">draw_model_instanced</span><span class="token punctuation">(</span>
@ -355,7 +422,7 @@ render_pass<span class="token punctuation">.</span><span class="token function">
</code></pre></div><p>The code in <code>main.rs</code> will change accordingly.</p> <div class="language-rust extra-class"><pre class="language-rust"><code>render_pass<span class="token punctuation">.</span><span class="token function">set_vertex_buffer</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>instance_buffer<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token punctuation">..</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">set_pipeline</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>render_pipeline<span class="token punctuation">)</span><span class="token punctuation">;</span>
render_pass<span class="token punctuation">.</span><span class="token function">draw_model_instanced</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>obj_model<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">..</span><span class="token keyword">self</span><span class="token punctuation">.</span>instances<span class="token punctuation">.</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token keyword">u32</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>camera_bind_group<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial9-models/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <svg xmlns="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"><path fill="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> <polygon fill="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> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
</code></pre></div><div id="wasm-example"><!----> <button>Try Tutorial9_models!</button></div> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/beginner/tutorial9-models/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/beginner/tutorial8-depth/" class="prev">
The Depth Buffer
@ -364,6 +431,6 @@ render_pass<span class="token punctuation">.</span><span class="token function">
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/11.918ac8f8.js" defer></script><script src="/learn-wgpu/assets/js/25.5a7a1f31.js" defer></script>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/13.c9d2040b.js" defer></script><script src="/learn-wgpu/assets/js/10.d40f290b.js" defer></script><script src="/learn-wgpu/assets/js/14.fa667d51.js" defer></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

@ -0,0 +1,14 @@
# Blender MTL File: 'cube.blend'
# Material Count: 1
newmtl Material.001
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Bump cube-normal.png
map_Kd cube-diffuse.jpg

1143
cube.obj

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -4,15 +4,26 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Sources | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Sources">
<meta property="og:type" content="website">
<meta property="og:url" content="/intermediate/pbr-notes.html">
<meta name="twitter:title" content="Sources">
<meta name="twitter:url" content="/intermediate/pbr-notes.html">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Sources"><meta property="og:type" content="website"><meta property="og:url" content="/intermediate/pbr-notes.html"><meta name="twitter:title" content="Sources"><meta name="twitter:url" content="/intermediate/pbr-notes.html"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/29.c45319b3.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.5a7a1f31.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/30.edbea28d.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.d40f290b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.fa667d51.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="sources"><a href="#sources" class="header-anchor">#</a> Sources</h1> <ul><li>https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading</li> <li>http://jimmiejohnsson84.me/pages/rendering_pbr.html</li></ul></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <!----> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/29.c45319b3.js" defer></script>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="sources"><a href="#sources" class="header-anchor">#</a> Sources</h1> <ul><li>https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/diffuse-lambertian-shading</li> <li>http://jimmiejohnsson84.me/pages/rendering_pbr.html</li></ul></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <!----> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/30.edbea28d.js" defer></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,18 +4,34 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>A Better Camera | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="A Better Camera">
<meta property="og:type" content="website">
<meta property="og:url" content="/intermediate/tutorial12-camera/">
<meta name="twitter:title" content="A Better Camera">
<meta name="twitter:url" content="/intermediate/tutorial12-camera/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="A Better Camera"><meta property="og:type" content="website"><meta property="og:url" content="/intermediate/tutorial12-camera/"><meta name="twitter:title" content="A Better Camera"><meta name="twitter:url" content="/intermediate/tutorial12-camera/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/17.57f53ce3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/25.5a7a1f31.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/19.04b3176c.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/10.d40f290b.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/14.fa667d51.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="active sidebar-link">A Better Camera</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial12-camera/#the-camera" class="sidebar-link">The Camera</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial12-camera/#the-projection" class="sidebar-link">The Projection</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial12-camera/#cleaning-up-main-rs" class="sidebar-link">Cleaning up main.rs</a></li></ul></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="a-better-camera"><a href="#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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">cgmath<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" aria-current="page" class="active sidebar-link">A Better Camera</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial12-camera/#the-camera" class="sidebar-link">The Camera</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial12-camera/#the-projection" class="sidebar-link">The Projection</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial12-camera/#cleaning-up-main-rs" class="sidebar-link">Cleaning up main.rs</a></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="a-better-camera"><a href="#a-better-camera" class="header-anchor">#</a> A Better Camera</h1> <div class="warn"><p>The shaders used in this example don't compile on WASM using version 0.12.0 of wgpu. They are working on the &quot;gecko&quot; branch, so to get the code working for WASM, change the wgpu entries in Cargo.toml to be the following.</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token punctuation">[</span><span class="token table class-name">dependencies</span><span class="token punctuation">]</span>
<span class="token key property">wgpu</span> <span class="token punctuation">=</span> <span class="token punctuation">{</span> <span class="token key property">version</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.12&quot;</span><span class="token punctuation">,</span> <span class="token key property">git</span><span class="token punctuation">=</span><span class="token string">&quot;https://github.com/gfx-rs/wgpu&quot;</span><span class="token punctuation">,</span> <span class="token key property">branch</span><span class="token punctuation">=</span><span class="token string">&quot;gecko&quot;</span><span class="token punctuation">}</span>
<span class="token punctuation">[</span><span class="token table class-name">target.'cfg(target_arch = &quot;wasm32&quot;)'.dependencies</span><span class="token punctuation">]</span>
<span class="token key property">wgpu</span> <span class="token punctuation">=</span> <span class="token punctuation">{</span> <span class="token key property">version</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.12&quot;</span><span class="token punctuation">,</span> <span class="token key property">git</span><span class="token punctuation">=</span><span class="token string">&quot;https://github.com/gfx-rs/wgpu&quot;</span><span class="token punctuation">,</span> <span class="token key property">branch</span><span class="token punctuation">=</span><span class="token string">&quot;gecko&quot;</span><span class="token punctuation">,</span> <span class="token key property">features</span> <span class="token punctuation">=</span> <span class="token punctuation">[</span><span class="token string">&quot;webgl&quot;</span><span class="token punctuation">]</span><span class="token punctuation">}</span>
</code></pre></div><p>Once 0.13 comes out I'll revert to using the version published on crates.io.</p></div> <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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">cgmath<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">winit<span class="token punctuation">::</span>event<span class="token punctuation">::</span></span><span class="token operator">*</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">winit<span class="token punctuation">::</span>dpi<span class="token punctuation">::</span></span><span class="token class-name">PhysicalPosition</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">instant<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token namespace">std<span class="token punctuation">::</span></span><span class="token keyword">f32</span><span class="token punctuation">::</span><span class="token namespace">consts<span class="token punctuation">::</span></span><span class="token constant">FRAC_PI_2</span><span class="token punctuation">;</span>
<span class="token attribute attr-name">#[rustfmt::skip]</span>
@ -27,7 +43,8 @@
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token constant">SAFE_FRAC_PI_2</span><span class="token punctuation">:</span> <span class="token keyword">f32</span> <span class="token operator">=</span> <span class="token constant">FRAC_PI_2</span> <span class="token operator">-</span> <span class="token number">0.0001</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="the-camera"><a href="#the-camera" class="header-anchor">#</a> The Camera</h2> <p>Next we need create a new <code>Camera</code> struct. We're going to be using a FPS style camera, so we'll store the position and the yaw (horizontal rotation), and pitch (vertical rotation). We'll have a <code>calc_matrix</code> method to create our view matrix.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[derive(Debug)]</span>
</code></pre></div><div class="note"><p><code>std::time::Instant</code> panics on WASM, so we'll use the <a href="https://docs.rs/instant" target="_blank" rel="noopener noreferrer">instant crate<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></a>. You'll want to include it in your <code>Cargo.toml</code>:</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token key property">instant</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.1&quot;</span>
</code></pre></div></div> <h2 id="the-camera"><a href="#the-camera" class="header-anchor">#</a> The Camera</h2> <p>Next we need create a new <code>Camera</code> struct. We're going to be using a FPS style camera, so we'll store the position and the yaw (horizontal rotation), and pitch (vertical rotation). We'll have a <code>calc_matrix</code> method to create our view matrix.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[derive(Debug)]</span>
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Camera</span> <span class="token punctuation">{</span>
<span class="token keyword">pub</span> position<span class="token punctuation">:</span> <span class="token class-name">Point3</span><span class="token operator">&lt;</span><span class="token keyword">f32</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
yaw<span class="token punctuation">:</span> <span class="token class-name">Rad</span><span class="token operator">&lt;</span><span class="token keyword">f32</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
@ -266,37 +283,34 @@
<span class="token keyword">self</span><span class="token punctuation">.</span>projection<span class="token punctuation">.</span><span class="token function">resize</span><span class="token punctuation">(</span>new_size<span class="token punctuation">.</span>width<span class="token punctuation">,</span> new_size<span class="token punctuation">.</span>height<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
</code></pre></div><p><code>input()</code> will need to be updated as well. Up to this point we have been using <code>WindowEvent</code>s for our camera controls. While this works, it's not the best solution. The <a href="https://docs.rs/winit/0.24.0/winit/event/enum.WindowEvent.html?search=#variant.CursorMoved" target="_blank" rel="noopener noreferrer">winit docs<svg xmlns="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"><path fill="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> <polygon fill="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> inform us that OS will often transform the data for the <code>CursorMoved</code> event to allow effects such as cursor acceleration. Because of this, we're going to change our <code>input()</code> function to use <code>DeviceEvent</code> instead of <code>WindowEvent</code>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// UPDATED!</span>
<span class="token keyword">fn</span> <span class="token function-definition function">input</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> event<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token class-name">DeviceEvent</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">bool</span> <span class="token punctuation">{</span>
</code></pre></div><p><code>input()</code> will need to be updated as well. Up to this point we have been using <code>WindowEvent</code>s for our camera controls. While this works, it's not the best solution. The <a href="https://docs.rs/winit/0.24.0/winit/event/enum.WindowEvent.html?search=#variant.CursorMoved" target="_blank" rel="noopener noreferrer">winit docs<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></a> inform us that OS will often transform the data for the <code>CursorMoved</code> event to allow effects such as cursor acceleration.</p> <p>Now to fix this we could change the <code>input()</code> function to process <code>DeviceEvent</code> instead of <code>WindowEvent</code>, but keyboard and button presses don't get emitted as <code>DeviceEvent</code>s on MacOS and WASM. Instead, we'll just remove the <code>CursorMoved</code> check in <code>input()</code>, and a manual call to <code>camera_controller.process_mouse()</code> in the <code>run()</code> function.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// UPDATED!</span>
<span class="token keyword">fn</span> <span class="token function-definition function">input</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> event<span class="token punctuation">:</span> <span class="token operator">&amp;</span><span class="token class-name">WindowEvent</span><span class="token punctuation">)</span> <span class="token punctuation">-&gt;</span> <span class="token keyword">bool</span> <span class="token punctuation">{</span>
<span class="token keyword">match</span> event <span class="token punctuation">{</span>
<span class="token class-name">DeviceEvent</span><span class="token punctuation">::</span><span class="token class-name">Key</span><span class="token punctuation">(</span>
<span class="token class-name">KeyboardInput</span> <span class="token punctuation">{</span>
virtual_keycode<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">,</span>
state<span class="token punctuation">,</span>
<span class="token punctuation">..</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">self</span><span class="token punctuation">.</span>camera_controller<span class="token punctuation">.</span><span class="token function">process_keyboard</span><span class="token punctuation">(</span><span class="token operator">*</span>key<span class="token punctuation">,</span> <span class="token operator">*</span>state<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token class-name">DeviceEvent</span><span class="token punctuation">::</span><span class="token class-name">MouseWheel</span> <span class="token punctuation">{</span> delta<span class="token punctuation">,</span> <span class="token punctuation">..</span> <span class="token punctuation">}</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token class-name">WindowEvent</span><span class="token punctuation">::</span><span class="token class-name">KeyboardInput</span> <span class="token punctuation">{</span>
input<span class="token punctuation">:</span>
<span class="token class-name">KeyboardInput</span> <span class="token punctuation">{</span>
virtual_keycode<span class="token punctuation">:</span> <span class="token class-name">Some</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">,</span>
state<span class="token punctuation">,</span>
<span class="token punctuation">..</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">..</span>
<span class="token punctuation">}</span> <span class="token operator">=&gt;</span> <span class="token keyword">self</span><span class="token punctuation">.</span>camera_controller<span class="token punctuation">.</span><span class="token function">process_keyboard</span><span class="token punctuation">(</span><span class="token operator">*</span>key<span class="token punctuation">,</span> <span class="token operator">*</span>state<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token class-name">WindowEvent</span><span class="token punctuation">::</span><span class="token class-name">MouseWheel</span> <span class="token punctuation">{</span> delta<span class="token punctuation">,</span> <span class="token punctuation">..</span> <span class="token punctuation">}</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>camera_controller<span class="token punctuation">.</span><span class="token function">process_scroll</span><span class="token punctuation">(</span>delta<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token class-name">DeviceEvent</span><span class="token punctuation">::</span><span class="token class-name">Button</span> <span class="token punctuation">{</span>
button<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token comment">// Left Mouse Button</span>
<span class="token class-name">WindowEvent</span><span class="token punctuation">::</span><span class="token class-name">MouseInput</span> <span class="token punctuation">{</span>
button<span class="token punctuation">:</span> <span class="token class-name">MouseButton</span><span class="token punctuation">::</span><span class="token class-name">Left</span><span class="token punctuation">,</span>
state<span class="token punctuation">,</span>
<span class="token punctuation">..</span>
<span class="token punctuation">}</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>mouse_pressed <span class="token operator">=</span> <span class="token operator">*</span>state <span class="token operator">==</span> <span class="token class-name">ElementState</span><span class="token punctuation">::</span><span class="token class-name">Pressed</span><span class="token punctuation">;</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token class-name">DeviceEvent</span><span class="token punctuation">::</span><span class="token class-name">MouseMotion</span> <span class="token punctuation">{</span> delta <span class="token punctuation">}</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token keyword">self</span><span class="token punctuation">.</span>mouse_pressed <span class="token punctuation">{</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>camera_controller<span class="token punctuation">.</span><span class="token function">process_mouse</span><span class="token punctuation">(</span>delta<span class="token number">.0</span><span class="token punctuation">,</span> delta<span class="token number">.1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token boolean">true</span>
<span class="token punctuation">}</span>
_ <span class="token operator">=&gt;</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>This change means will have to modify the event loop in <code>main()</code> as well.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</code></pre></div><p>Here are the changes to <code>run()</code>:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ...</span>
event_loop<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">move</span> <span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>event<span class="token punctuation">,</span> _<span class="token punctuation">,</span> control_flow<span class="token closure-punctuation punctuation">|</span></span> <span class="token punctuation">{</span>
<span class="token operator">*</span>control_flow <span class="token operator">=</span> <span class="token class-name">ControlFlow</span><span class="token punctuation">::</span><span class="token class-name">Poll</span><span class="token punctuation">;</span>
@ -304,17 +318,18 @@
<span class="token comment">// ...</span>
<span class="token comment">// NEW!</span>
<span class="token class-name">Event</span><span class="token punctuation">::</span><span class="token class-name">DeviceEvent</span> <span class="token punctuation">{</span>
<span class="token keyword">ref</span> event<span class="token punctuation">,</span>
event<span class="token punctuation">:</span> <span class="token class-name">DeviceEvent</span><span class="token punctuation">::</span><span class="token class-name">MouseMotion</span><span class="token punctuation">{</span> delta<span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">..</span> <span class="token comment">// We're not using device_id currently</span>
<span class="token punctuation">}</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
state<span class="token punctuation">.</span><span class="token function">input</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token operator">=&gt;</span> <span class="token keyword">if</span> state<span class="token punctuation">.</span>mouse_pressed <span class="token punctuation">{</span>
state<span class="token punctuation">.</span>camera_controller<span class="token punctuation">.</span><span class="token function">process_mouse</span><span class="token punctuation">(</span>delta<span class="token number">.0</span><span class="token punctuation">,</span> delta<span class="token number">.1</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// UPDATED!</span>
<span class="token class-name">Event</span><span class="token punctuation">::</span><span class="token class-name">WindowEvent</span> <span class="token punctuation">{</span>
<span class="token keyword">ref</span> event<span class="token punctuation">,</span>
window_id<span class="token punctuation">,</span>
<span class="token punctuation">}</span> <span class="token keyword">if</span> window_id <span class="token operator">==</span> window<span class="token punctuation">.</span><span class="token function">id</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span> <span class="token keyword">if</span> window_id <span class="token operator">==</span> window<span class="token punctuation">.</span><span class="token function">id</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>state<span class="token punctuation">.</span><span class="token function">input</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">match</span> event <span class="token punctuation">{</span>
<span class="token attribute attr-name">#[cfg(not(target_arch=<span class="token string">&quot;wasm32&quot;</span>))]</span>
<span class="token class-name">WindowEvent</span><span class="token punctuation">::</span><span class="token class-name">CloseRequested</span>
<span class="token operator">|</span> <span class="token class-name">WindowEvent</span><span class="token punctuation">::</span><span class="token class-name">KeyboardInput</span> <span class="token punctuation">{</span>
input<span class="token punctuation">:</span>
@ -338,7 +353,7 @@
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>The <code>update</code> function requires a bit more explanation. The <code>update_camera</code> function on the <code>CameraController</code> has a parameter <code>dt: Duration</code> which is the delta time or time between frames. This is to help smooth out the camera movement so that it's not locked be the framerate. Currently we aren't calculating <code>dt</code>, so I decided to pass it into <code>update</code> as a parameter.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">update</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> dt<span class="token punctuation">:</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
</code></pre></div><p>The <code>update</code> function requires a bit more explanation. The <code>update_camera</code> function on the <code>CameraController</code> has a parameter <code>dt: Duration</code> which is the delta time or time between frames. This is to help smooth out the camera movement so that it's not locked be the framerate. Currently we aren't calculating <code>dt</code>, so I decided to pass it into <code>update</code> as a parameter.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">update</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">,</span> dt<span class="token punctuation">:</span> <span class="token namespace">instant<span class="token punctuation">::</span></span><span class="token class-name">Duration</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// UPDATED!</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>camera_controller<span class="token punctuation">.</span><span class="token function">update_camera</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">mut</span> <span class="token keyword">self</span><span class="token punctuation">.</span>camera<span class="token punctuation">,</span> dt<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>camera_uniform<span class="token punctuation">.</span><span class="token function">update_view_proj</span><span class="token punctuation">(</span><span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>camera<span class="token punctuation">,</span> <span class="token operator">&amp;</span><span class="token keyword">self</span><span class="token punctuation">.</span>projection<span class="token punctuation">)</span><span class="token punctuation">;</span>
@ -350,15 +365,15 @@
<span class="token operator">*</span> old_position<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">into</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// UPDATED!</span>
</code></pre></div><p>We still need to calculate <code>dt</code>. Let's do that in the <code>main</code> function.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ...</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> state <span class="token operator">=</span> <span class="token namespace">pollster<span class="token punctuation">::</span></span><span class="token function">block_on</span><span class="token punctuation">(</span><span class="token class-name">State</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>window<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> last_render_time <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Instant</span><span class="token punctuation">::</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// NEW!</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> state <span class="token operator">=</span> <span class="token class-name">State</span><span class="token punctuation">::</span><span class="token function">new</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>window<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">await</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> <span class="token keyword">mut</span> last_render_time <span class="token operator">=</span> <span class="token namespace">instant<span class="token punctuation">::</span></span><span class="token class-name">Instant</span><span class="token punctuation">::</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// NEW!</span>
event_loop<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token keyword">move</span> <span class="token closure-params"><span class="token closure-punctuation punctuation">|</span>event<span class="token punctuation">,</span> _<span class="token punctuation">,</span> control_flow<span class="token closure-punctuation punctuation">|</span></span> <span class="token punctuation">{</span>
<span class="token operator">*</span>control_flow <span class="token operator">=</span> <span class="token class-name">ControlFlow</span><span class="token punctuation">::</span><span class="token class-name">Poll</span><span class="token punctuation">;</span>
<span class="token keyword">match</span> event <span class="token punctuation">{</span>
<span class="token comment">// ...</span>
<span class="token comment">// UPDATED!</span>
<span class="token class-name">Event</span><span class="token punctuation">::</span><span class="token class-name">RedrawRequested</span><span class="token punctuation">(</span>window_id<span class="token punctuation">)</span> <span class="token keyword">if</span> window_id <span class="token operator">==</span> window<span class="token punctuation">.</span><span class="token function">id</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> now <span class="token operator">=</span> <span class="token namespace">std<span class="token punctuation">::</span>time<span class="token punctuation">::</span></span><span class="token class-name">Instant</span><span class="token punctuation">::</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> now <span class="token operator">=</span> <span class="token namespace">instant<span class="token punctuation">::</span></span><span class="token class-name">Instant</span><span class="token punctuation">::</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> dt <span class="token operator">=</span> now <span class="token operator">-</span> last_render_time<span class="token punctuation">;</span>
last_render_time <span class="token operator">=</span> now<span class="token punctuation">;</span>
state<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>dt<span class="token punctuation">)</span><span class="token punctuation">;</span>
@ -368,15 +383,15 @@
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>With that we should be able to move our camera wherever we want.</p> <p><img src="/learn-wgpu/assets/img/screenshot.4f5740bc.png" alt="./screenshot.png"></p> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial12-camera/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <svg xmlns="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"><path fill="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> <polygon fill="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> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
</code></pre></div><p>With that we should be able to move our camera wherever we want.</p> <p><img src="/learn-wgpu/assets/img/screenshot.4f5740bc.png" alt="./screenshot.png"></p> <div id="wasm-example"><!----> <button>Try Tutorial12_camera!</button></div> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial12-camera/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/intermediate/tutorial11-normals/" class="prev">
Normal Mapping
</a></span> <span class="next"><a href="/learn-wgpu/intermediate/tutorial13-threading/">
Multi-threading with Wgpu and Rayon
</a></span> <span class="next"><a href="/learn-wgpu/showcase/">
Foreword
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/17.57f53ce3.js" defer></script><script src="/learn-wgpu/assets/js/25.5a7a1f31.js" defer></script>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/19.04b3176c.js" defer></script><script src="/learn-wgpu/assets/js/10.d40f290b.js" defer></script><script src="/learn-wgpu/assets/js/14.fa667d51.js" defer></script>
</body>
</html>

@ -4,15 +4,34 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Multi-threading with Wgpu and Rayon | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Multi-threading with Wgpu and Rayon">
<meta property="og:type" content="website">
<meta property="og:url" content="/intermediate/tutorial13-threading/">
<meta name="twitter:title" content="Multi-threading with Wgpu and Rayon">
<meta name="twitter:url" content="/intermediate/tutorial13-threading/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Multi-threading with Wgpu and Rayon"><meta property="og:type" content="website"><meta property="og:url" content="/intermediate/tutorial13-threading/"><meta name="twitter:title" content="Multi-threading with Wgpu and Rayon"><meta name="twitter:url" content="/intermediate/tutorial13-threading/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/30.e1eaf249.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/25.5a7a1f31.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/31.bc1e9142.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/10.d40f290b.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/14.fa667d51.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="active sidebar-link">Multi-threading with Wgpu and Rayon</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial13-threading/#parallelizing-loading-models-and-textures" class="sidebar-link">Parallelizing loading models and textures</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/intermediate/tutorial13-threading/#it-s-that-easy" class="sidebar-link">It's that easy!</a></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="multi-threading-with-wgpu-and-rayon"><a href="#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> <div class="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> <h2 id="parallelizing-loading-models-and-textures"><a href="#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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// model.rs</span>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="multi-threading-with-wgpu-and-rayon"><a href="#multi-threading-with-wgpu-and-rayon" class="header-anchor">#</a> Multi-threading with Wgpu and Rayon</h1> <div class="warn"><p>The shaders used in this example don't compile on WASM using version 0.12.0 of wgpu. They are working on the &quot;gecko&quot; branch, so to get the code working for WASM, change the wgpu entries in Cargo.toml to be the following.</p> <div class="language-toml extra-class"><pre class="language-toml"><code><span class="token punctuation">[</span><span class="token table class-name">dependencies</span><span class="token punctuation">]</span>
<span class="token key property">wgpu</span> <span class="token punctuation">=</span> <span class="token punctuation">{</span> <span class="token key property">version</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.12&quot;</span><span class="token punctuation">,</span> <span class="token key property">git</span><span class="token punctuation">=</span><span class="token string">&quot;https://github.com/gfx-rs/wgpu&quot;</span><span class="token punctuation">,</span> <span class="token key property">branch</span><span class="token punctuation">=</span><span class="token string">&quot;gecko&quot;</span><span class="token punctuation">}</span>
<span class="token punctuation">[</span><span class="token table class-name">target.'cfg(target_arch = &quot;wasm32&quot;)'.dependencies</span><span class="token punctuation">]</span>
<span class="token key property">wgpu</span> <span class="token punctuation">=</span> <span class="token punctuation">{</span> <span class="token key property">version</span> <span class="token punctuation">=</span> <span class="token string">&quot;0.12&quot;</span><span class="token punctuation">,</span> <span class="token key property">git</span><span class="token punctuation">=</span><span class="token string">&quot;https://github.com/gfx-rs/wgpu&quot;</span><span class="token punctuation">,</span> <span class="token key property">branch</span><span class="token punctuation">=</span><span class="token string">&quot;gecko&quot;</span><span class="token punctuation">,</span> <span class="token key property">features</span> <span class="token punctuation">=</span> <span class="token punctuation">[</span><span class="token string">&quot;webgl&quot;</span><span class="token punctuation">]</span><span class="token punctuation">}</span>
</code></pre></div><p>Once 0.13 comes out I'll revert to using the version published on crates.io.</p></div> <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> <div class="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> <h2 id="parallelizing-loading-models-and-textures"><a href="#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> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token comment">// resources.rs</span>
<span class="token attribute attr-name">#[cfg(not(target_arch=<span class="token string">&quot;wasm32&quot;</span>))]</span>
<span class="token keyword">use</span> <span class="token namespace">rayon<span class="token punctuation">::</span>iter<span class="token punctuation">::</span></span><span class="token class-name">IntoParallelIterator</span><span class="token punctuation">;</span>
<span class="token keyword">impl</span> <span class="token class-name">Model</span> <span class="token punctuation">{</span>
<span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">load</span><span class="token operator">&lt;</span><span class="token class-name">P</span><span class="token punctuation">:</span> <span class="token class-name">AsRef</span><span class="token operator">&lt;</span><span class="token class-name">Path</span><span class="token operator">&gt;&gt;</span><span class="token punctuation">(</span>
@ -99,15 +118,7 @@
<span class="token punctuation">}</span>
</code></pre></div><p>We've parallelized loading the meshes, and making the vertex array for them. Probably a bit overkill, but <code>rayon</code> should prevent us from using too many threads.</p> <div class="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> <h2 id="it-s-that-easy"><a href="#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> <div class="language- extra-class"><pre class="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> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial13-threading/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <svg xmlns="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"><path fill="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> <polygon fill="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> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/intermediate/tutorial12-camera/" class="prev">
A Better Camera
</a></span> <span class="next"><a href="/learn-wgpu/showcase/">
Foreword
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/30.e1eaf249.js" defer></script><script src="/learn-wgpu/assets/js/25.5a7a1f31.js" defer></script>
</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> <div id="wasm-example"><!----> <button>Try Tutorial12_camera!</button></div> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial13-threading/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <!----> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/31.bc1e9142.js" defer></script><script src="/learn-wgpu/assets/js/10.d40f290b.js" defer></script><script src="/learn-wgpu/assets/js/14.fa667d51.js" defer></script>
</body>
</html>

@ -4,15 +4,26 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Update to 0.12! | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Update to 0.12!">
<meta property="og:type" content="website">
<meta property="og:url" content="/news/0.12/">
<meta name="twitter:title" content="Update to 0.12!">
<meta name="twitter:url" content="/news/0.12/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Update to 0.12!"><meta property="og:type" content="website"><meta property="og:url" content="/news/0.12/"><meta name="twitter:title" content="Update to 0.12!"><meta name="twitter:url" content="/news/0.12/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/31.ab88ef7b.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.5a7a1f31.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/32.782ad442.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.d40f290b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.fa667d51.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>News</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/news/0.12/" class="active sidebar-link">Update to 0.12!</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#multi-view-added" class="sidebar-link">Multi view added</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#no-more-block-attribute" class="sidebar-link">No more block attribute</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#more-validation" class="sidebar-link">More validation</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#misc" class="sidebar-link">Misc</a></li></ul></li><li><a href="/learn-wgpu/news/pre-0.12/" class="sidebar-link">News (Pre 0.12)</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="update-to-0-12"><a href="#update-to-0-12" class="header-anchor">#</a> Update to 0.12!</h1> <p>There's not a ton of changes in this release, so the migration
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>News</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/news/0.12/" aria-current="page" class="active sidebar-link">Update to 0.12!</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#multi-view-added" class="sidebar-link">Multi view added</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#no-more-block-attribute" class="sidebar-link">No more block attribute</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#more-validation" class="sidebar-link">More validation</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/news/0.12/#misc" class="sidebar-link">Misc</a></li></ul></li><li><a href="/learn-wgpu/news/pre-0.12/" class="sidebar-link">News (Pre 0.12)</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="update-to-0-12"><a href="#update-to-0-12" class="header-anchor">#</a> Update to 0.12!</h1> <p>There's not a ton of changes in this release, so the migration
wasn't too painful.</p> <h2 id="multi-view-added"><a href="#multi-view-added" class="header-anchor">#</a> Multi view added</h2> <p>The <code>RenderPipelineDescriptor</code> now includes a <code>multiview</code> field that
indicates the number of array textures if array textures are used
as render attachments.</p> <h2 id="no-more-block-attribute"><a href="#no-more-block-attribute" class="header-anchor">#</a> No more block attribute</h2> <p>The WGSL spec has changed and the <code>block</code> attribute is no longer a thing.
@ -46,11 +57,11 @@ I needed to do was add a padding field:</p> <div class="language-rust extra-clas
<span class="token comment">// Due to uniforms requiring 16 byte (4 float) spacing, we need to use a padding field here</span>
_padding2<span class="token punctuation">:</span> <span class="token keyword">u32</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p>I updated the <a href="../../intermediate/tutorial10-lighting">lighting tutorial</a> to reflect this change.</p> <h2 id="misc"><a href="#misc" class="header-anchor">#</a> Misc</h2> <p>Due to the recent deploy to <a href="https://docs.rs/anyhow/latest/" target="_blank" rel="noopener noreferrer">anyhow<svg xmlns="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"><path fill="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> <polygon fill="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> that
</code></pre></div><p>I updated the <a href="../../intermediate/tutorial10-lighting">lighting tutorial</a> to reflect this change.</p> <h2 id="misc"><a href="#misc" class="header-anchor">#</a> Misc</h2> <p>Due to the recent deploy to <a href="https://docs.rs/anyhow/latest/" target="_blank" rel="noopener noreferrer">anyhow<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></a> that
breaks glob imports (aka. <code>use anyhow::*</code>), I had to switch qualified
imports and uses (ie. <code>anyhow::Result</code>). This was mostly an issue on my
build scripts for some of the showcase examples.</p> <p>The main tutorial examples weren't affected, and the changes are minor, so
if your curious feel free to look at the repo.</p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
if your curious feel free to look at the repo.</p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/showcase/alignment/" class="prev">
Memory Layout in WGSL
@ -59,6 +70,6 @@ if your curious feel free to look at the repo.</p></div> <footer class="page-edi
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/31.ab88ef7b.js" defer></script>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/32.782ad442.js" defer></script>
</body>
</html>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

@ -0,0 +1,14 @@
# Blender MTL File: 'cube.blend'
# Material Count: 1
newmtl Material.001
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Bump cube-normal.png
map_Kd cube-diffuse.jpg

File diff suppressed because it is too large Load Diff

Binary file not shown.

@ -4,15 +4,26 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Memory Layout in WGSL | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Memory Layout in WGSL">
<meta property="og:type" content="website">
<meta property="og:url" content="/showcase/alignment/">
<meta name="twitter:title" content="Memory Layout in WGSL">
<meta name="twitter:url" content="/showcase/alignment/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Memory Layout in WGSL"><meta property="og:type" content="website"><meta property="og:url" content="/showcase/alignment/"><meta name="twitter:title" content="Memory Layout in WGSL"><meta name="twitter:url" content="/showcase/alignment/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/33.4daba1cc.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.5a7a1f31.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/34.e516cba8.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.d40f290b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.fa667d51.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" class="sidebar-link">Foreword</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="sidebar-link">Wgpu without a window</a></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="sidebar-link">Pong</a></li><li><a href="/learn-wgpu/showcase/compute/" class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><a href="/learn-wgpu/showcase/alignment/" class="active sidebar-link">Memory Layout in WGSL</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/alignment/#alignment-of-vertex-and-index-buffers" class="sidebar-link">Alignment of vertex and index buffers</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/alignment/#alignment-of-uniform-and-storage-buffers" class="sidebar-link">Alignment of Uniform and Storage buffers</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/alignment/#how-to-deal-with-alignment-issues" class="sidebar-link">How to deal with alignment issues</a></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="memory-layout-in-wgsl"><a href="#memory-layout-in-wgsl" class="header-anchor">#</a> Memory Layout in WGSL</h1> <div class="warn"><p>This page is currently being reworked. I want to understand the topics a bit better, but
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" aria-current="page" class="sidebar-link">Foreword</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="sidebar-link">Wgpu without a window</a></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="sidebar-link">Pong</a></li><li><a href="/learn-wgpu/showcase/compute/" class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><a href="/learn-wgpu/showcase/alignment/" aria-current="page" class="active sidebar-link">Memory Layout in WGSL</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/alignment/#alignment-of-vertex-and-index-buffers" class="sidebar-link">Alignment of vertex and index buffers</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/alignment/#alignment-of-uniform-and-storage-buffers" class="sidebar-link">Alignment of Uniform and Storage buffers</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/alignment/#how-to-deal-with-alignment-issues" class="sidebar-link">How to deal with alignment issues</a></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="memory-layout-in-wgsl"><a href="#memory-layout-in-wgsl" class="header-anchor">#</a> Memory Layout in WGSL</h1> <div class="warn"><p>This page is currently being reworked. I want to understand the topics a bit better, but
as 0.12 is out I want to release what I have for now.</p></div> <h2 id="alignment-of-vertex-and-index-buffers"><a href="#alignment-of-vertex-and-index-buffers" class="header-anchor">#</a> Alignment of vertex and index buffers</h2> <p>Vertex buffers require defining a <code>VertexBufferLayout</code>, so the memory alignment is whatever
you tell WebGPU it should be. This can be really convenient for keeping down memory usage
on the GPU.</p> <p>The Index Buffer use the alignment of whatever primitive type you specify via the <code>IndexFormat</code>
@ -22,7 +33,7 @@ on processing aligned by powers of 2. The exact specifics of why this is are bey
my level of knowledge, but it's important to know so that you can trouble shoot why your
shaders aren't working.</p> <p>Let's take a look at the following table:</p> <hr> <table><thead><tr><th>Type</th> <th>Alignment in Bytes</th> <th>Size in Bytes</th></tr></thead> <tbody><tr><td>scalar (i32, u32, f32)</td> <td>4</td> <td>4</td></tr> <tr><td>vec2&lt;T&gt;</td> <td>8</td> <td>8</td></tr> <tr><td>vec3&lt;T&gt;</td> <td><strong>16</strong></td> <td>12</td></tr> <tr><td>vec4&lt;T&gt;</td> <td>16</td> <td>16</td></tr></tbody></table> <p>You can see for <code>vec3</code> the alignment is the next power of 2 from the size, 16. This can
catch beginners (and even veterans) off guard as it's not the most intuitive. This becomes especially
important when we start laying out structs. Take the light struct from the <a href="/learn-wgpu/intermediate/tutorial10-lighting/#seeing-the-light">lighting tutorial</a>:</p> <p>You can see the full table of the alignments in section <a href="https://www.w3.org/TR/WGSL/#alignment-and-size" target="_blank" rel="noopener noreferrer">4.3.7.1 of the WGSL spec<svg xmlns="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"><path fill="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> <polygon fill="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 class="language-wgsl extra-class"><pre class="language-text"><code>struct Light {
important when we start laying out structs. Take the light struct from the <a href="/learn-wgpu/intermediate/tutorial10-lighting/#seeing-the-light">lighting tutorial</a>:</p> <p>You can see the full table of the alignments in section <a href="https://www.w3.org/TR/WGSL/#alignment-and-size" target="_blank" rel="noopener noreferrer">4.3.7.1 of the WGSL spec<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></a></p> <div class="language-wgsl extra-class"><pre class="language-text"><code>struct Light {
position: vec3&lt;f32&gt;;
color: vec3&lt;f32&gt;;
};
@ -45,7 +56,7 @@ be able to do something like the following:</p> <div class="language-rust extra-
position<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token keyword">f32</span><span class="token punctuation">;</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
color<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token keyword">f32</span><span class="token punctuation">;</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
</code></pre></div><p>But this won't compile. The <a href="https://docs.rs/bytemuck/" target="_blank" rel="noopener noreferrer">bytemuck crate<svg xmlns="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"><path fill="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> <polygon fill="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> doesn't work with
</code></pre></div><p>But this won't compile. The <a href="https://docs.rs/bytemuck/" target="_blank" rel="noopener noreferrer">bytemuck crate<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></a> doesn't work with
structs with implicit padding bytes. Rust can't guarantee that the memory between the fields
has been initialized properly. This gave be an error when I tried it:</p> <div class="language- extra-class"><pre class="language-text"><code>error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--&gt; code/intermediate/tutorial10-lighting/src/main.rs:246:8
@ -55,7 +66,7 @@ has been initialized properly. This gave be an error when I tried it:</p> <div c
|
= note: source type: `LightUniform` (256 bits)
= note: target type: `_::{closure#0}::TypeWithoutPadding` (192 bits)
</code></pre></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
</code></pre></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/showcase/compute/" class="prev">
Compute Example: Tangents and Bitangents
@ -64,6 +75,6 @@ has been initialized properly. This gave be an error when I tried it:</p> <div c
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/33.4daba1cc.js" defer></script>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/34.e516cba8.js" defer></script>
</body>
</html>

@ -4,15 +4,26 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Compute Example: Tangents and Bitangents | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Compute Example: Tangents and Bitangents">
<meta property="og:type" content="website">
<meta property="og:url" content="/showcase/compute/">
<meta name="twitter:title" content="Compute Example: Tangents and Bitangents">
<meta name="twitter:url" content="/showcase/compute/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Compute Example: Tangents and Bitangents"><meta property="og:type" content="website"><meta property="og:url" content="/showcase/compute/"><meta name="twitter:title" content="Compute Example: Tangents and Bitangents"><meta name="twitter:url" content="/showcase/compute/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/9.62cbd082.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/25.5a7a1f31.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/12.fd778d47.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/14.fa667d51.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.d40f290b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" class="sidebar-link">Foreword</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="sidebar-link">Wgpu without a window</a></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="sidebar-link">Pong</a></li><li><a href="/learn-wgpu/showcase/compute/" class="active sidebar-link">Compute Example: Tangents and Bitangents</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/compute/#possible-improvements" class="sidebar-link">Possible Improvements</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/compute/#results" class="sidebar-link">Results</a></li></ul></li><li><a href="/learn-wgpu/showcase/alignment/" class="sidebar-link">Memory Layout in WGSL</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="compute-example-tangents-and-bitangents"><a href="#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 <a href="/learn-wgpu/intermediate/tutorial11-normals/">normal mapping tutorial</a>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[repr(C)]</span>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" aria-current="page" class="sidebar-link">Foreword</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="sidebar-link">Wgpu without a window</a></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="sidebar-link">Pong</a></li><li><a href="/learn-wgpu/showcase/compute/" aria-current="page" class="active sidebar-link">Compute Example: Tangents and Bitangents</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/compute/#possible-improvements" class="sidebar-link">Possible Improvements</a></li><li class="sidebar-sub-header"><a href="/learn-wgpu/showcase/compute/#results" class="sidebar-link">Results</a></li></ul></li><li><a href="/learn-wgpu/showcase/alignment/" class="sidebar-link">Memory Layout in WGSL</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="compute-example-tangents-and-bitangents"><a href="#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 <a href="/learn-wgpu/intermediate/tutorial11-normals/">normal mapping tutorial</a>.</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token attribute attr-name">#[repr(C)]</span>
<span class="token attribute attr-name">#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]</span>
<span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">ModelVertex</span> <span class="token punctuation">{</span>
position<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token keyword">f32</span><span class="token punctuation">;</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
@ -113,7 +124,7 @@
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
flat_triangle_map<span class="token punctuation">.</span><span class="token function">extend</span><span class="token punctuation">(</span>t_list<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</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> <h2 id="results"><a href="#results" class="header-anchor">#</a> Results</h2> <p>The tangents and bitangents are now getting calculated correctly and on the GPU!</p> <p><img src="/learn-wgpu/assets/img/results.7918efc1.png" alt="./results.png"></p> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/compute/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <svg xmlns="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"><path fill="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> <polygon fill="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> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="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> <h2 id="results"><a href="#results" class="header-anchor">#</a> Results</h2> <p>The tangents and bitangents are now getting calculated correctly and on the GPU!</p> <p><img src="/learn-wgpu/assets/img/results.7918efc1.png" alt="./results.png"></p> <div class="auto-github-link"><a href="https://github.com/sotrh/learn-wgpu/tree/master/code/showcase/compute/" target="_blank" rel="noopener noreferrer">Check out the code!</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="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> <polygon fill="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> <span class="sr-only">(opens new window)</span></span></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/showcase/pong/" class="prev">
Pong
@ -122,6 +133,6 @@
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/9.62cbd082.js" defer></script><script src="/learn-wgpu/assets/js/25.5a7a1f31.js" defer></script>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/12.fd778d47.js" defer></script><script src="/learn-wgpu/assets/js/14.fa667d51.js" defer></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,23 +4,34 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Foreword | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Foreword">
<meta property="og:type" content="website">
<meta property="og:url" content="/showcase/">
<meta name="twitter:title" content="Foreword">
<meta name="twitter:url" content="/showcase/">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Foreword"><meta property="og:type" content="website"><meta property="og:url" content="/showcase/"><meta name="twitter:title" content="Foreword"><meta name="twitter:url" content="/showcase/"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/32.21765d0f.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.5a7a1f31.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.d664ca20.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/33.3ff9e37f.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.d40f290b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.fa667d51.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.a8b2dd1c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" class="active sidebar-link">Foreword</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="sidebar-link">Wgpu without a window</a></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="sidebar-link">Pong</a></li><li><a href="/learn-wgpu/showcase/compute/" class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><a href="/learn-wgpu/showcase/alignment/" class="sidebar-link">Memory Layout in WGSL</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="foreword"><a href="#foreword" class="header-anchor">#</a> Foreword</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> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>Showcase</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/showcase/" aria-current="page" class="active sidebar-link">Foreword</a></li><li><a href="/learn-wgpu/showcase/windowless/" class="sidebar-link">Wgpu without a window</a></li><li><a href="/learn-wgpu/showcase/gifs/" class="sidebar-link">Creating gifs</a></li><li><a href="/learn-wgpu/showcase/pong/" class="sidebar-link">Pong</a></li><li><a href="/learn-wgpu/showcase/compute/" class="sidebar-link">Compute Example: Tangents and Bitangents</a></li><li><a href="/learn-wgpu/showcase/alignment/" class="sidebar-link">Memory Layout in WGSL</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="foreword"><a href="#foreword" class="header-anchor">#</a> Foreword</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> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
<a href="/learn-wgpu/intermediate/tutorial13-threading/" class="prev">
Multi-threading with Wgpu and Rayon
<a href="/learn-wgpu/intermediate/tutorial12-camera/" class="prev">
A Better Camera
</a></span> <span class="next"><a href="/learn-wgpu/showcase/windowless/">
Wgpu without a window
</a>
</span></p></div> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/32.21765d0f.js" defer></script>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/33.3ff9e37f.js" defer></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,15 +4,26 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Coming Soon! | Learn Wgpu</title>
<meta name="generator" content="VuePress 1.9.7">
<meta name="description" content="">
<meta name="generator" content="VuePress 1.4.0">
<meta property="article:modified_time" content="2022-03-26T00:15:11.000Z">
<meta property="og:site_name" content="Learn Wgpu">
<meta property="og:title" content="Coming Soon!">
<meta property="og:type" content="website">
<meta property="og:url" content="/todo.html">
<meta name="twitter:title" content="Coming Soon!">
<meta name="twitter:url" content="/todo.html">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Written by">
<meta name="twitter:data1" content="Benjamin Hansen">
<meta name="twitter:creator" content="https://twitter.com/sotrh760">
<meta property="article:modified_time" content="2022-03-18T19:17:14.000Z"><meta property="og:site_name" content="Learn Wgpu"><meta property="og:title" content="Coming Soon!"><meta property="og:type" content="website"><meta property="og:url" content="/todo.html"><meta name="twitter:title" content="Coming Soon!"><meta name="twitter:url" content="/todo.html"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:label1" content="Written by"><meta name="twitter:data2" content="Benjamin Hansen"><meta name="twitter:creator" content="https://twitter.com/sotrh760">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.754f9a2f.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/4.c4741047.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/34.d664ca20.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.e1054b07.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.9b2446b9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.918ac8f8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.7e1fa0ed.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c591e8de.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.87ade59d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.c68f983c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.8b83d0ae.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.57f53ce3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.2398c480.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.623df875.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.b98e18a6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.140d2648.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.a801933f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.d1c5beb9.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.ffb83767.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.6a0d1e12.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.5a7a1f31.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.a5048f3d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.16add643.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.f4a55ac6.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.c45319b3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.e1eaf249.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.ab88ef7b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.21765d0f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.4daba1cc.js"><link rel="prefetch" href="/learn-wgpu/assets/js/35.368358c3.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.c0c5124a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/5.a5d0b8f5.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.43d3e796.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.88628e61.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.87be279f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.62cbd082.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.4fb695a1.css">
<link rel="preload" href="/learn-wgpu/assets/css/0.styles.b003e29f.css" as="style"><link rel="preload" href="/learn-wgpu/assets/js/app.9755eea3.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/5.77b9a0f5.js" as="script"><link rel="preload" href="/learn-wgpu/assets/js/35.a8b2dd1c.js" as="script"><link rel="prefetch" href="/learn-wgpu/assets/js/1.0a5baa1d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/10.d40f290b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/11.bbe770a2.js"><link rel="prefetch" href="/learn-wgpu/assets/js/12.fd778d47.js"><link rel="prefetch" href="/learn-wgpu/assets/js/13.c9d2040b.js"><link rel="prefetch" href="/learn-wgpu/assets/js/14.fa667d51.js"><link rel="prefetch" href="/learn-wgpu/assets/js/15.ab847d83.js"><link rel="prefetch" href="/learn-wgpu/assets/js/16.2c92615d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/17.0c774b06.js"><link rel="prefetch" href="/learn-wgpu/assets/js/18.61b15753.js"><link rel="prefetch" href="/learn-wgpu/assets/js/19.04b3176c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/2.4bef8391.js"><link rel="prefetch" href="/learn-wgpu/assets/js/20.0cd325c7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/21.93d20474.js"><link rel="prefetch" href="/learn-wgpu/assets/js/22.77a3a552.js"><link rel="prefetch" href="/learn-wgpu/assets/js/23.47917ab4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/24.f3e54fe7.js"><link rel="prefetch" href="/learn-wgpu/assets/js/25.064681a4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/26.33de4e71.js"><link rel="prefetch" href="/learn-wgpu/assets/js/27.702b4de8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/28.d70c699a.js"><link rel="prefetch" href="/learn-wgpu/assets/js/29.49d319db.js"><link rel="prefetch" href="/learn-wgpu/assets/js/3.dea3d18c.js"><link rel="prefetch" href="/learn-wgpu/assets/js/30.edbea28d.js"><link rel="prefetch" href="/learn-wgpu/assets/js/31.bc1e9142.js"><link rel="prefetch" href="/learn-wgpu/assets/js/32.782ad442.js"><link rel="prefetch" href="/learn-wgpu/assets/js/33.3ff9e37f.js"><link rel="prefetch" href="/learn-wgpu/assets/js/34.e516cba8.js"><link rel="prefetch" href="/learn-wgpu/assets/js/36.e6611f74.js"><link rel="prefetch" href="/learn-wgpu/assets/js/37.c4afb320.js"><link rel="prefetch" href="/learn-wgpu/assets/js/6.4ed9d1d4.js"><link rel="prefetch" href="/learn-wgpu/assets/js/7.90dd9685.js"><link rel="prefetch" href="/learn-wgpu/assets/js/8.99c50be0.js"><link rel="prefetch" href="/learn-wgpu/assets/js/9.55967133.js">
<link rel="stylesheet" href="/learn-wgpu/assets/css/0.styles.b003e29f.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li><li><a href="/learn-wgpu/intermediate/tutorial13-threading/" class="sidebar-link">Multi-threading with Wgpu and Rayon</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="coming-soon"><a href="#coming-soon" class="header-anchor">#</a> Coming Soon!</h1> <p>This section has not yet been completed.</p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/18/2022, 7:17:14 PM</span></div></footer> <!----> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.754f9a2f.js" defer></script><script src="/learn-wgpu/assets/js/4.c4741047.js" defer></script><script src="/learn-wgpu/assets/js/34.d664ca20.js" defer></script>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="inner"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="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> <a href="/learn-wgpu/" class="home-link router-link-active"><!----> <span class="site-name">Learn Wgpu</span></a> <div class="links"><!----> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div></div></header> <div class="sidebar-mask"></div> <div class="docs-layout"><aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/learn-wgpu/" aria-current="page" class="sidebar-link">Introduction</a></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Beginner</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/beginner/tutorial1-window/" class="sidebar-link">Dependencies and the window</a></li><li><a href="/learn-wgpu/beginner/tutorial2-surface/" class="sidebar-link">The Surface</a></li><li><a href="/learn-wgpu/beginner/tutorial3-pipeline/" class="sidebar-link">The Pipeline</a></li><li><a href="/learn-wgpu/beginner/tutorial4-buffer/" class="sidebar-link">Buffers and Indices</a></li><li><a href="/learn-wgpu/beginner/tutorial5-textures/" class="sidebar-link">Textures and bind groups</a></li><li><a href="/learn-wgpu/beginner/tutorial6-uniforms/" class="sidebar-link">Uniform buffers and a 3d camera</a></li><li><a href="/learn-wgpu/beginner/tutorial7-instancing/" class="sidebar-link">Instancing</a></li><li><a href="/learn-wgpu/beginner/tutorial8-depth/" class="sidebar-link">The Depth Buffer</a></li><li><a href="/learn-wgpu/beginner/tutorial9-models/" class="sidebar-link">Model Loading</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Intermediate</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/learn-wgpu/intermediate/tutorial10-lighting/" class="sidebar-link">Working with Lights</a></li><li><a href="/learn-wgpu/intermediate/tutorial11-normals/" class="sidebar-link">Normal Mapping</a></li><li><a href="/learn-wgpu/intermediate/tutorial12-camera/" class="sidebar-link">A Better Camera</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Showcase</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>News</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="coming-soon"><a href="#coming-soon" class="header-anchor">#</a> Coming Soon!</h1> <p>This section has not yet been completed.</p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">3/26/2022, 12:15:11 AM</span></div></footer> <!----> </main></div></div><div class="global-ui"><!----></div></div>
<script src="/learn-wgpu/assets/js/app.9755eea3.js" defer></script><script src="/learn-wgpu/assets/js/5.77b9a0f5.js" defer></script><script src="/learn-wgpu/assets/js/35.a8b2dd1c.js" defer></script>
</body>
</html>

Loading…
Cancel
Save