<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-6950833531562942289</id><updated>2021-09-12T00:51:52.631-07:00</updated><category term="Stupid rendering tricks" /><category term="The industry" /><category term="Rendering tutorials" /><category term="Graphic rants" /><category term="Off-topic" /><category term="Tools" /><category term="Programming rants" /><category term="Rendering ideas" /><category term="Programming tutorials" /><category term="Announcements" /><category term="Rants" /><category term="Stupid programming tricks" /><category term="Photography" /><title type="text">C0DE517E</title><subtitle type="html">Computer Science &amp;amp;&amp;amp; Computer Graphics &amp;amp;&amp;amp; Altera</subtitle><link rel="alternate" type="text/html" href="http://c0de517e.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default?start-index=26&amp;max-results=25&amp;redirect=false" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>332</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/C0de517e" /><feedburner:info uri="c0de517e" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-8015923071414610343</id><published>2020-12-27T14:03:00.010-08:00</published><updated>2021-01-06T13:00:29.066-08:00</updated><title type="text">Why Raytracing won't simplify AAA real-time rendering.</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;div&gt;&lt;i style="font-family: arial;"&gt;"The big trick we are getting now is the final unification of lighting and shadowing across all surfaces in a game - games had to do these hacks and tricks for years now where we do different things for characters and different things for environments and different things for lights that move versus static lights, and now we are able to do all of that the same way for everything..."&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Who said this?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Jensen Huang, presenting NVidia's RTX?&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Not quite... John Carmack. In 2001, at Tokyo's MacWorld, showing Doom 3 for the first time. It was though on an NVidia hardware, just a bit less powerful than today's 20xx/30xx series. A GeForce 3.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-GOFDMhJBbAg/X-a5eH4ONJI/AAAAAAAACPs/3ZddtRZfyqsNEEoPhWdFhjflykb0N1E_QCLcBGAsYHQ/s1328/Capture3.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;span style="font-family: arial;"&gt;&lt;img border="0" data-original-height="458" data-original-width="1328" height="221" src="https://1.bp.blogspot.com/-GOFDMhJBbAg/X-a5eH4ONJI/AAAAAAAACPs/3ZddtRZfyqsNEEoPhWdFhjflykb0N1E_QCLcBGAsYHQ/w640-h221/Capture3.PNG" width="640" /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;Can watch the recording on &lt;a href="https://www.youtube.com/watch?v=80guchXqz14"&gt;YouTube&lt;/a&gt;&amp;nbsp;for a bit of nostalgia.&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;And of course, the unifying technology at that time was stencil shadows - yes, we were at a time before shadowmaps were viable.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Now. I am not a fan of making long-term predictions, in fact, I believe there is a given time horizon after which things are mostly dominated by chaos, and it's just silly to talk about what's going to happen then.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;But if we wanted to make predictions, a good starting point is to look at the history, as history tends to repeat. What happened last time that we had significant innovation in rendering hardware?&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Did compute shaders lead to simpler rendering engines, or more complex? What happened when we introduced programmable fragment shaders? Simpler, or more complex? What about hardware vertex shaders - a.k.a. hardware transform and lighting...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;And so on and so forth, we can go all the way back to the first popular accelerated&amp;nbsp;video card for the consumer market, the 3dfx.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-ZmdnEndnf_4/X-j6lHMFC0I/AAAAAAAACP8/rtTbfKiLm6oOMe_aHWozrzHvVKETwMgxACLcBGAsYHQ/3570-front.jpg" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="796" data-original-width="1200" height="213" src="https://lh3.googleusercontent.com/-ZmdnEndnf_4/X-j6lHMFC0I/AAAAAAAACP8/rtTbfKiLm6oOMe_aHWozrzHvVKETwMgxACLcBGAsYHQ/w320-h213/3570-front.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Memories... A 3dfx Voodoo. PCem has some emulation for these, if one wants to play...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Surely it must have made things simpler, not having to program software rasterizers specifically for each game, for each kind of object, for each CPU even! No more assembly. No more self-modifying code, s-buffers, software clipping, BSPs...&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;No more crazy tricks to get textures on screen, we suddenly got it all done for us, for free! Z-buffer, anisotropic filtering, perspective correction... Crazy stuff we never could even dream of is now in hardware.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Imagine that - overnight you could have taken the bulk of your 3d engine and deleted it. Did it make engines simpler, or more complex?&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Our shaders today, powered by incredible hardware, are much more code, and much more complexity, than the software rasterizers of decades ago!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Are there reasons to believe this time it will be any different?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;Spoiler alert: no.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;At least not in AAA real-time rendering. Complexity has nothing to do with technologies.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Technologies can enable new products,&amp;nbsp; true, but even the existence of new products is always about people first and foremost.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;The truth is that our real-time rendering engines could have been dirt-simple ten years ago, there's nothing inherently complex in what we got right now.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Getting from zero to a reasonable, real-time PBR renderer is not hard. The equations are there, just render one light at a time, brute force shadowmaps, loop over all objects and shadows and you can get there. Use MSAA for antialiasing...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Of course, you would need to trade-off performance for such relatively "brute-force" approaches, and some quality... But it's doable, and will look reasonably good.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Even better? Just download Unreal, and hire -zero- rendering engineers.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;Would you not be able to ship any game your mind can imagine?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;The only reason we do not... is in people and products. It's organizational, structural, not technical.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We like our graphics to be cutting edge as graphics and performance still sell games, sell consoles, are talked about.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;And it's relatively inexpensive, in the grand scheme of things - rendering engineers are a small fraction of the engineering effort which in turn is not the most expensive part of making AAA games...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-8tNXD7O7CTA/X-j76hgWpFI/AAAAAAAACQI/-bDpYCBChCU6osrv7fiSuCVcIxXQkt9wgCLcBGAsYHQ/red-dead-redemption-photo-mode.jpg" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="1080" data-original-width="1920" height="360" src="https://lh3.googleusercontent.com/-8tNXD7O7CTA/X-j76hgWpFI/AAAAAAAACQI/-bDpYCBChCU6osrv7fiSuCVcIxXQkt9wgCLcBGAsYHQ/w640-h360/red-dead-redemption-photo-mode.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;So pretty... Look at that sky. Worth its &lt;a href="https://advances.realtimerendering.com/s2019/index.htm"&gt;complexity&lt;/a&gt;, right?&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;In AAA is perfectly ok to have someone work for say, a month, producing new, complicated code paths to save say, one millisecond in our frame time. It's perfectly ok often to spend a month to save a tenth of a millisecond!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Until this equation will be true, we will always sacrifice engineering, and thus, accept bigger and bigger engines, more complex rendering techniques, in order to have larger, more beautiful worlds, rendered faster!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;It has nothing to do with hardware nor it has anything to do with the inherent complexity of photorealistic graphics.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We write code because we're not in the business of making disruptive new games, AAA is not where risks are taken, it's where blockbuster productions are made.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;It's the nature of what we do, we don't run scrappy experimental teams, but machines with dozens of engineers and hundreds of artists.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;We're not trying to make the next Fortnite - that would require entirely different attitudes and methodologies.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;And so, engineers gonna engineer, if you have a dozen rendering people on a game, its rendering will never be trivial - and once that's a thing that people do in the industry, it's hard not to do it, you have to keep competing on every dimension if you want to be at the top of the game.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;The cyclic nature of innovation.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-zEAlCJ1ncjM/X-j8cHx0HXI/AAAAAAAACQQ/umTlSFR5Pnw4T_Ff2GLkfWcBwi0s6yzxQCLcBGAsYHQ/2618._SY475_.jpg" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="475" data-original-width="301" height="240" src="https://lh3.googleusercontent.com/-zEAlCJ1ncjM/X-j8cHx0HXI/AAAAAAAACQQ/umTlSFR5Pnw4T_Ff2GLkfWcBwi0s6yzxQCLcBGAsYHQ/2618._SY475_.jpg" width="152" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Another point of view, useful to make some prediction, comes from the classic works of Clayton Christensen on innovation. These are also mandatory reads if you want to understand the natural flow of innovation, from disruptive inventions to established markets.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;One of the phenomena that Christensen observes is that technologies evolve in cycles of commoditization, bringing costs down and scaling, and de-commoditization, leveraging integrated, proprietary stacks to deliver innovation.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;In AAA games, rendering has not been commoditized, and the trend does not seem going towards commoditization yet.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Innovation is still the driving force behind real-time graphics, not scale of production, even if we have been saying for years, perhaps decades that we were at the tipping point, in practice we never seemed to reach it.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We are not even, at least in the big titles, close to the point where production efficiency for artists and assets are really the focus.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;It's crazy to say, but still today our rendering teams typically dwarf the efforts put into tooling and asset production efficiency.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We live in a world where it's imperative for most AAA titles to produce content at a steady pace. Yet, we don't see this percolating in the technology stack, look at the actual engines (if you have experience of them), look at the talks and presentations at conferences. We are still focusing on features, quality and performance more than anything else.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We do not like to accept tradeoffs on our stacks, we run on tightly integrated technologies because we like the idea of customizing them to the game specifics - i.e. we have not embraced open standards that would allow for components in our production stacks to be shared and exchanged.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-9QwOsTejLXc/X-j_0qZVVoI/AAAAAAAACQc/H7j9U0LsnbMCR7T-b6GmBGZGgH8GJrW8wCLcBGAsYHQ/teaser.jpg" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="634" data-original-width="1200" height="211" src="https://lh3.googleusercontent.com/-9QwOsTejLXc/X-j_0qZVVoI/AAAAAAAACQc/H7j9U0LsnbMCR7T-b6GmBGZGgH8GJrW8wCLcBGAsYHQ/w400-h211/teaser.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Alita - rendered with Weta's proprietary (and RenderMan-compatible) &lt;a href="https://jo.dreggn.org/path-tracing-in-production/"&gt;Manuka&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;I do not think this trend will change, at the top end, for the next decade or so at least, the only time horizon I would even care to make predictions.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;I think we will see a focus on efficiency of the artist tooling, this shift in attention is already underway - but engines themselves will only keep growing in complexity - same for rendering overall.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We see just recently, in the movie industry (which is another decent way of "predicting" the future of real-time) that production pipelines are becoming somewhat standardized around common interchange formats.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;For the top studios, rendering itself is not, with most big ones running on their own proprietary path-tracing solutions...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;So, is it all pain? And it will always be?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;No, not at all!&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We live in a fantastic world full of opportunities for everyone. There is definitely a lot of real-time rendering that has been completely commoditized and abstracted.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;People can create incredible graphics without knowing anything at all of how things work underneath, and this is definitely something incredibly new and exciting.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Once upon a time, you had to be John friggin' Carmack (and we went full circle...) to make a 3d engine, create Doom, and be legendary because of it. Your hardcore ability of pushing pixels made entire game genres that were impossible to create without the very best of technical skills.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-CwEguqwJM1E/X-kCGFIwEXI/AAAAAAAACQo/dxfqCcgyU28kb17Ea-Ue8sZ6KTiesyPBACLcBGAsYHQ/Screen%2BShot%2B2020-12-27%2Bat%2B1.51.47%2BPM.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="1246" data-original-width="1992" height="250" src="https://lh3.googleusercontent.com/-CwEguqwJM1E/X-kCGFIwEXI/AAAAAAAACQo/dxfqCcgyU28kb17Ea-Ue8sZ6KTiesyPBACLcBGAsYHQ/w400-h250/Screen%2BShot%2B2020-12-27%2Bat%2B1.51.47%2BPM.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="https://threejs.org/"&gt;https://threejs.org/&lt;/a&gt; frontpage.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Today? I believe a FPS templates ships for free with Unity, you can download Unreal with its source code for free, you have Godot... All products that invest in art efficiency and ease of use first and foremost.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Everyone can create any game genre with little complexity, without caring about technology - the complicated stuff is only there for cutting-edge "blockbuster" titles where bespoke engines matter, and only to some better features (e.g. fidelity, performance etc), not to fundamentally enable the game to exist...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;And that's already professional stuff - we can do much better!&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Three.js is the most popular 3d engine on github - you don't need to know anything about 3d graphics to start creating. We have Roblox, Dreams, Minecraft and Fortnite Creative. We have Notch, for real-time motion graphics...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Computer graphics has never been simpler, and at the same time, at the top end, never been more complex.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-IeCq9VIlRQ4/X-kHTz-RJfI/AAAAAAAACQ0/NXpss994o_4duTMJmmHR19sEO2Tu9ZqPwCLcBGAsYHQ/joseph-mcgrae-robloxscreenshot20201225-154707203.jpg" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="839" data-original-width="1650" height="326" src="https://lh3.googleusercontent.com/-IeCq9VIlRQ4/X-kHTz-RJfI/AAAAAAAACQ0/NXpss994o_4duTMJmmHR19sEO2Tu9ZqPwCLcBGAsYHQ/w640-h326/joseph-mcgrae-robloxscreenshot20201225-154707203.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Roblox &lt;a href="https://www.artstation.com/artwork/xJoW0X"&gt;creations&lt;/a&gt; are completely tech-agnostic.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;AAA will stay AAA - and for the foreseeable future it will keep being wonderfully complicated.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Slowly we will invest more in productivity for artists and asset production - as it really matters for games - but it's not a fast process.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;It's probably easier for AAA to become relatively irrelevant (compared to the overall market size - that expands faster in other directions than in the established AAA one) - than for it to radically embrace change.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Other products and other markets is where real-time rendering is commoditized and radically different.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;It -is- already, a&lt;/span&gt;&lt;span style="font-family: arial;"&gt;ll these products already exist, and we already have huge market segments that do not need to bother at all with technical details.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;And the quality and scope of these games grows year after year.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;This market was facilitated by the fact that we have 3d hardware acceleration pretty much in any device now - but at the same time&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;n&lt;/span&gt;&lt;span style="font-family: arial;"&gt;ew h&lt;/span&gt;&lt;span style="font-family: arial;"&gt;ardware is not going to change any of that.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Raytracing will only -add- complexity at the top end.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;It might make certain problems simpler, perhaps &lt;span style="font-size: xx-small;"&gt;(note - right now people seem to underestimate how hard is to make good RT-shadows or even worse, RT-reflections, which are truly hard...)&lt;/span&gt;, but it will also make the overall effort to produce a AAA frame bigger, not smaller - like all technologies before it.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;We'll see incredible hybrid techniques, and if we have today dozens of ways of doing shadows and combining signals to solve the rendering equation in real-time, we'll only grow these more complex - and wonderful, in the future.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Raytracing&lt;/span&gt;&lt;span style="font-family: arial;"&gt;&amp;nbsp;will eventually percolate to the non-AAA eventually too, as all technologies do.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;But that won't change complexity or open new products there either because people who are making real-time graphics with higher-level tools already don't have to care about the technology that drives them - technology there will always evolve under the hood, never to be seen by the users...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/Itz9cZjvVT0" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/8015923071414610343/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=8015923071414610343" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/8015923071414610343" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/8015923071414610343" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/Itz9cZjvVT0/why-raytracing-wont-simplify-aaa-real.html" title="Why Raytracing won't simplify AAA real-time rendering." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-GOFDMhJBbAg/X-a5eH4ONJI/AAAAAAAACPs/3ZddtRZfyqsNEEoPhWdFhjflykb0N1E_QCLcBGAsYHQ/s72-w640-h221-c/Capture3.PNG" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/12/why-raytracing-wont-simplify-aaa-real.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-136009820948484982</id><published>2020-12-17T00:10:00.011-08:00</published><updated>2020-12-18T15:27:33.823-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Rendering tutorials" /><title type="text"> Hallucinations re: the rendering of Cyberpunk 2077</title><content type="html">&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Two curses befall rendering engineers. First, we lose the ability to look at reality without being constantly reminded of how fascinatingly hard it is to solve light transport and model materials.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Second, when you start playing any game, you cannot refrain from trying to reverse its rendering technology (which is particularly infuriating for multiplayer titles - stop shooting at me, I'm just here to look how rocks cast shadows!).&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;So when I bought Cyberpunk 2077 I had to look at how it renders a frame. It's very simple to take RenderDoc captures of it, so I had really no excuse.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The following are speculations on its rendering techniques, observations made while skimming captures, and playing a few hours.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;It's by no means a serious attempt at reverse engineering.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;For that, I lack both the time and the talent. I also rationalize doing a bad job at this by the following excuse: it's actually better this way.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;I think it's better to dream about how rendering (or anything really) could be, just with some degree of inspiration from external sources (in this case, RenderDoc captures), rather than exactly knowing what is going on.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;If we know, we know, there's no mystery anymore. It's what we do not know that makes us think, and sometimes we exactly guess what's going on, but other times we do one better, we hallucinate something new... Isn't that wonderful?&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The following is mostly a read-through of a single capture. I did open a second one to try to fill some blanks, but so far, that's all.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-Accm4KmCjcQ/X90IqbPkniI/AAAAAAAACO4/Y30F2-QUQuEN3oa44WvOhq4zrALKMpAHwCLcBGAsYHQ/s957/Capture.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="536" data-original-width="957" height="224" src="https://1.bp.blogspot.com/-Accm4KmCjcQ/X90IqbPkniI/AAAAAAAACO4/Y30F2-QUQuEN3oa44WvOhq4zrALKMpAHwCLcBGAsYHQ/w400-h224/Capture.PNG" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;This is the frame we are going to look at.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;I made the captures at high settings, without RTX or DLSS as RenderDoc does not allow these (yet?). I disabled motionblur and other uninteresting post-fx and made sure I was moving in all captures to be able to tell a bit better when passes access previous frame(s) data.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;I am also not relying on insider information for this. Makes everything easier and more fun.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;The basics&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;At a glance, it doesn't take long to describe the core of Cyberpunk 2077 rendering.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;It's a classic deferred renderer, with a fairly vanilla g-buffer layout. We don't see the crazy amount of buffers of say, Suckerpunch's PS4 launch Infamous:Second Son, nor complex bit-packing and re-interpretation of channels.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-Hfi1VZdBR7k/X9ukF1t2liI/AAAAAAAACMI/YfEXc8ELO8knX4zW4L0pfzHyckezaFVfACLcBGAsYHQ/s1690/001.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="948" data-original-width="1690" height="360" src="https://1.bp.blogspot.com/-Hfi1VZdBR7k/X9ukF1t2liI/AAAAAAAACMI/YfEXc8ELO8knX4zW4L0pfzHyckezaFVfACLcBGAsYHQ/w640-h360/001.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Immediately recognizable g-buffer layout&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;10.10.10.2 Normals, with the 2-bit alpha reserved to mark hair&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;10.10.10.2 Albedo. Not clear what the alpha is doing here, it seems to just be set to one for everything drawn, but it might be only the captures I got&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;8.8.8.8 Metalness, Roughness, Translucency and Emissive, in this order (RGBA)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;Z-buffer and Stencil. The latter seems to isolate object/material types. Moving objects are tagged. Skin. Cars. Vegetation. Hair. Roads. Hard to tell / would take time to identify the meaning of each bit, but you get the gist...&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;If we look at the frame chronologically, it starts with a bunch of UI draws (that I didn't investigate further), a bunch of copies from a CPU buffer into VS constants, then a shadowmap update (more on this later), and finally a depth pre-pass.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-Ysj98gZ695I/X9ukNnRwAiI/AAAAAAAACMU/71spZTnarM0XbAk1lEuI9Bis-ptl50CMgCLcBGAsYHQ/s1056/002.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="592" data-original-width="1056" height="358" src="https://1.bp.blogspot.com/-Ysj98gZ695I/X9ukNnRwAiI/AAAAAAAACMU/71spZTnarM0XbAk1lEuI9Bis-ptl50CMgCLcBGAsYHQ/w640-h358/002.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Some stages of the depth pre-pass.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;This depth pre-pass is partial (not drawing the entire scene) and is only used to reduce the overdraw in the subsequent g-buffer pass.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Basically, all the geometry draws are using instancing and some form of bindless textures. I'd imagine this was a big part of updating the engine from The Witcher 3 to contemporary hardware.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Bindless also makes it quite annoying to look at the capture in renderDoc unfortunately - by spot-checking I could not see too many different shaders in the g-buffer pass - perhaps a sign of not having allowed artists to make shaders via visual graphs?&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Other wild guesses: I don't see any front-to-back sorting in the g-buffer, and the depth prepass renders all kinds of geometries, not just walls, so it would seem that there is no special authoring for these (brushes, forming a BSP) - nor artists have hand-tagged objects for the prepass, as some relatively "bad" occluders make the cut. I imagine that after culling a list of objects is sorted by shader and from there instanced draws are dynamically formed on the CPU.&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family: arial;"&gt;The opening credits do not mention Umbra (which was used in The Witcher 3) - so I guess CDPr rolled out their own visibility solution. Its effectiveness is really hard to gauge, as visibility is a GPU/CPU balance problem, but there seem to be quite a few draws that do not contribute to the image, for what's worth. It also looks like that at times the rendering can display "hidden" rooms, so it looks like it's not a cell and portal system - I am guessing that for such large worlds it's impractical to ask artists to do lots of manual work for visibility.&lt;/span&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-KRaRIyMFtME/X9ukTego-UI/AAAAAAAACMY/4U1NZpnI0ukFGI5v2xdt1QfIRWi8x7cnwCLcBGAsYHQ/s1300/003.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="486" data-original-width="1300" height="240" src="https://1.bp.blogspot.com/-KRaRIyMFtME/X9ukTego-UI/AAAAAAAACMY/4U1NZpnI0ukFGI5v2xdt1QfIRWi8x7cnwCLcBGAsYHQ/w640-h240/003.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A different frame, with some of the pre-pass. &lt;br /&gt;Looks like some non-visible rooms are drawn then covered by the floor - which might hint at culling done without old-school brushes/BSP/cell&amp;amp;portals?&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Lastly, I didn't see any culling done GPU side, with depth pyramids and so on, no per-triangle or cluster culling or predicated draws, so I guess all frustum and occlusion culling is CPU-side.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;i&gt;Note: people are asking if "bad" culling is the reason for the current performance issues, I guess meaning on ps4/xb1. This inference cannot be done, nor the visibility system can be called "bad" - as I wrote already. FWIW - it seems mostly that consoles struggle with memory and streaming more than anything else. Who knows...&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Let's keep going... After the main g-buffer pass (which seems to be always split in two - not sure if there's a rendering reason or perhaps these are two command buffers done on different threads), there are other passes for moving objects (which write motion vectors - the motion vector buffer is first initialized with camera motion).&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;This pass includes avatars, and the shaders for these objects do not use bindless (perhaps that's used only for world geometry) - so it's much easier to see what's going on there if one wants to.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Finally, we're done with the main g-buffer passes, depth-writes are turned off and there is a final pass for decals. Surprisingly these are pretty "vanilla" as well, most of them being mesh decals.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Mesh decals bind as inputs (a copy of) the normal buffer, which is interesting as one might imagine the 10.10.10 format was chosen to allow for easy hardware blending, but it seems that some custom blend math is used as well - something important enough to pay for the price of making a copy (on PC at least).&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-IOHdlY5caH0/X9ukf5owjLI/AAAAAAAACMk/0SBXr0kOnlg7a4BUqAwdOxZdoixcZRfNACLcBGAsYHQ/s1086/004.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="606" data-original-width="1086" height="358" src="https://1.bp.blogspot.com/-IOHdlY5caH0/X9ukf5owjLI/AAAAAAAACMk/0SBXr0kOnlg7a4BUqAwdOxZdoixcZRfNACLcBGAsYHQ/w640-h358/004.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A mesh decal - note how it looks like the original mesh with the triangles that do not map to decal textures removed.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;It looks like only triangles carrying decals are rendered, using special decal meshes, but other than that everything is remarkably simple. It's not bindless either&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;(only the main static geometry g-buffer pass seems to be)&lt;/span&gt;&lt;span style="font-family: arial;"&gt;, so it's easier to see what's going on here.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;At the end of the decal pass we see sometimes projected decals as well, I haven't investigated dynamic ones created by weapons, but the static ones on the levels are just applied with tight boxes around geometry, I guess hand-made, without any stencil-marking technique (which would probably not help in this case) to try to minimize the shaded pixels.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Projected decals do bind depth-stencil as input as well, obviously as they need the scene depth, to reconstruct world-space surface position and do the texture projection, but probably also to read stencil and avoid applying these decals on objects tagged as moving.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-lAQrsXP7oD0/X9ukuT7u_JI/AAAAAAAACMs/YvxJzcvupaokmi3Y_WqNd6bxqcw8Rz1fACLcBGAsYHQ/s1520/005.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="438" data-original-width="1520" height="184" src="https://1.bp.blogspot.com/-lAQrsXP7oD0/X9ukuT7u_JI/AAAAAAAACMs/YvxJzcvupaokmi3Y_WqNd6bxqcw8Rz1fACLcBGAsYHQ/w640-h184/005.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A projected decal, on the leftmost wall (note the decal box in yellow)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;As for the main g-buffer draws, many of the decals might end up not contributing at all to the image, and I don't see much evidence of decal culling (as some tiny ones are draws) - but it also might depend on my chosen settings.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The g-buffer pass is quite heavy, but it has lots of detail and it's of course the only pass that depends on scene geometry, a fraction of the overall frame time. E.g. look at the normals on the ground, pushed beyond the point of aliasing. At least on this PC capture, textures seem even biased towards aliasing, perhaps knowing that temporal will resolve them later (which absolutely does in practice, rotating the camera often reveals texture aliasing that immediately gets resolved when stopped - not a bad idea, especially as noise during view rotation can be masked by motion blur).&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-FMoGzCIfuWA/X90LGa88O6I/AAAAAAAACPE/bKQroTcaEcQ1H-fhxouSXGkEy4RTZ0qAgCLcBGAsYHQ/s1010/Capture.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="772" data-original-width="1010" height="245" src="https://1.bp.blogspot.com/-FMoGzCIfuWA/X90LGa88O6I/AAAAAAAACPE/bKQroTcaEcQ1H-fhxouSXGkEy4RTZ0qAgCLcBGAsYHQ/w320-h245/Capture.PNG" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;1:1 crop of the final normal buffer&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;A note re:Deferred vs Forward+&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Most state-of-the-art engines are deferred nowadays. Frostbite, Guerrilla's Decima, Call of Duty BO3/4/CW, Red Dead Redemption 2, Naughty Dog's Uncharted/TLOU and so on.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;On the other hand, the amount of advanced trickery that Forward+ allows you is unparalleled, and it has been adopted by a few to do truly incredible rendering, see for example the latest Doom games or have a look at the mind-blowing tricks behind Call of Duty: Modern Warfare / Warzone (and the previous Infinity Warfare which was the first time that COD line moved from being a crazy complex forward renderer to a crazy complex forward+).&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;I think the jury is still out on all this, and as most thing rendering (or well, coding!) we don't know anything about what's optimal, we just make/inherit choices and optimize around them.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;That said, I'd wager this was a great idea for CP2077 - and I'm not surprised at all to see this setup. As we'll see in the following, CP2077 does not seem to have baked lighting, relying instead on a few magic tricks, most of which operating in screen-space.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;For these to work, you need before lighting to know material and normals, so you need to write a g-buffer anyways. Also you need temporal reprojection, so you want motion vectors and to compute lighting effects in separate passes (that you can then appropriately reproject, filter and composite).&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;I would venture to say also that this was done not because of the need for dynamic GI - there's very little from what I've seen in terms of moving lights and geometry is not destructible.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;I imagine instead, this is because the storage and runtime memory costs of baked lighting would be too big. Plus, it's easier to make lighting interactive for artists in such a system, rather than trying to write a realtime path-tracer that accurately simulates what your baking system results would be...&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Lastly, as we're already speculating things, I'd imagine that CDPr wanted really to focus on artists and art. A deferred renderer can help there in two ways. First, it's performance is less coupled with the number of objects and vertices on screen, as only the g-buffer pass depends on them, so artists can be a smidge less "careful" about these.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;Second, it's simpler, overall - and in an open-world game you already have to care about so many things, that having to carefully tune your gigantic foward+ shaders for occupancy is not a headache you want to have to deal with...&lt;/span&gt;&lt;/div&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;Lighting part 1: Analytic lights&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Obviously, no deferred rendering analysis can stop at the g-buffer, we split shading in two, and we have now to look at the second half, how lighting is done.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Here things become a bit dicier, as in the modern age of compute shaders, everything gets packed into structures that we cannot easily see. Even textures can be hard to read when they do not carry continuous data but pack who-knows-what into integers.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-akYpe-UlOyM/X9ulOwOPPXI/AAAAAAAACNA/-HtNJRvFXmQUng7aSSy0_iLR5eWNr2W7gCLcBGAsYHQ/s1614/006B.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="662" data-original-width="1614" height="262" src="https://1.bp.blogspot.com/-akYpe-UlOyM/X9ulOwOPPXI/AAAAAAAACNA/-HtNJRvFXmQUng7aSSy0_iLR5eWNr2W7gCLcBGAsYHQ/w640-h262/006B.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Normal packing and depth pyramid passes.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;Regardless, it's pretty clear that after all the depth/g-buffer work is said and done, a uber-summarization pass kicks in taking care of a bunch of depth-related stuff.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-zvaNqDpea10/X90MzaKCXJI/AAAAAAAACPQ/9pgbEMY5YCALgjJXWuw_89lzz582HzHnQCLcBGAsYHQ/s734/Capture.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="393" data-original-width="734" height="214" src="https://1.bp.blogspot.com/-zvaNqDpea10/X90MzaKCXJI/AAAAAAAACPQ/9pgbEMY5YCALgjJXWuw_89lzz582HzHnQCLcBGAsYHQ/w400-h214/Capture.PNG" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;RGBA8 packed normal (&amp;amp;roughness). Note the speckles that are a tell-tale of best-fit-normal encoding.&lt;br /&gt;Also, note that this happens after hair rendering - which we didn't cover.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;It first packs normal and roughness into a RGBA8 using Crytek's lookup-based best-fit normal encoding, then it creates a min-max mip pyramid of depth values.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;a href="https://lh3.googleusercontent.com/-MVF93QzrjPc/X9sOrGmmZzI/AAAAAAAACHI/2wOQhr621FkrvdYtxrkxqyMetItZTzOGwCLcBGAsYHQ/006C.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="420" data-original-width="1536" height="176" src="https://lh3.googleusercontent.com/-MVF93QzrjPc/X9sOrGmmZzI/AAAAAAAACHI/2wOQhr621FkrvdYtxrkxqyMetItZTzOGwCLcBGAsYHQ/w640-h176/006C.png" width="640" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The pyramid is then used to create what looks like a volumetric texture for clustered lighting.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-xCRd5MouyBg/X9ulXpg7NxI/AAAAAAAACNI/Mnlhw8tsoT4khzkGsJZdTWbiWBdqdmNPACLcBGAsYHQ/s1242/007.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="732" data-original-width="1242" height="236" src="https://1.bp.blogspot.com/-xCRd5MouyBg/X9ulXpg7NxI/AAAAAAAACNI/Mnlhw8tsoT4khzkGsJZdTWbiWBdqdmNPACLcBGAsYHQ/w400-h236/007.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A slice of what looks like the light cluster texture, and below one of the lighting buffers partially computed. Counting the pixels in the empty tiles, they seem to be 16x16 - while the clusters look like 32x32?&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;So - from what I can see it looks like a clustered deferred lighting system.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The clusters seem to be 32x32 pixels in screen-space (froxels), with 64 z-slices. The lighting though seems to be done at a 16x16 tile granularity, all via compute shader indirect dispatches.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;I would venture this is because CS are specialized by both the materials and lights present in a tile, and then dispatched accordingly - a common setup in contemporary deferred rendering systems (e.g. see Call of Duty Black Ops 3 and Uncharted 4 presentations on the topic).&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Analytic lighting pass outputs two RGBA16 buffers, which seems to be diffuse and specular contributions. Regarding the options for scene lights, I would not be surprised if all we have are spot/point/sphere lights and line/capsule lights. Most of Cyberpunk's lights are neons, so definitely line light support is a must.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;You'll also notice that a lot of the lighting is unshadowed, and I don't think I ever noticed multiple shadows under a single object/avatar. I'm sure that the engine does not have limitations in that aspect, but all this points at lighting that is heavily "authored" with artists carefully placing shadow-casting lights. I would also not be surprised if the lights have manually assigned bounding volumes to avoid leaks.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-9mBcJwANHls/X9ulet6mFUI/AAAAAAAACNU/sIAxNMz0fxMbggAenggd0xZQLJH1_XXuQCLcBGAsYHQ/s1588/008.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="440" data-original-width="1588" height="178" src="https://1.bp.blogspot.com/-9mBcJwANHls/X9ulet6mFUI/AAAAAAAACNU/sIAxNMz0fxMbggAenggd0xZQLJH1_XXuQCLcBGAsYHQ/w640-h178/008.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Final lighting buffer (for analytic lights) - diffuse and specular contributions.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;Lighting part 2: Shadows&lt;/b&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;But what we just saw does not mean that shadows are unsophisticated in Cyberpunk 2077, quite the contrary, there are definitely a number of tricks that have been employed, most of them not at all easy to reverse!&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;First of all, before the depth-prepass, there are always a bunch of draws into what looks like a shadowmap. I suspect this is a CSM, but in the capture I have looked at, I have never seen it used, only rendered into. This points to a system that updates shadowmaps over many frames, likely with only static objects?&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-cbhGJg48_Zo/X9sO0otQApI/AAAAAAAACHU/6qqPjiQznwYXo-RU2euIsWlhjcVKcwLPQCLcBGAsYHQ/009.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="644" data-original-width="1350" height="306" src="https://lh3.googleusercontent.com/-cbhGJg48_Zo/X9sO0otQApI/AAAAAAAACHU/6qqPjiQznwYXo-RU2euIsWlhjcVKcwLPQCLcBGAsYHQ/w640-h306/009.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Is this a shadowmap? Note that there are only a few events in this capture that write to it, none that reads - it's just used as a depth-stencil target, if RenderDoc is correct here...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;These multi-frame effects are complicated to capture, so I can't say if there are further caching systems (e.g. see the quadtree compressed shadows of Black Ops 3) at play.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;One thing that looks interesting is that if you travel fast enough through a level (e.g. in a car) you can see that the shadows take some time to "catch up" and they fade in incrementally in a peculiar fashion. It almost appears like there is a depth offset applied from the sun point of view, that over time gets reduced. Interesting!&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-RNRoYSAGoAI/X9ulnO7qUDI/AAAAAAAACNc/_Ge0dypU3UwdHN2srCXN4smNRN_j1m9oQCLcBGAsYHQ/s1726/010.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="606" data-original-width="1726" height="224" src="https://1.bp.blogspot.com/-RNRoYSAGoAI/X9ulnO7qUDI/AAAAAAAACNc/_Ge0dypU3UwdHN2srCXN4smNRN_j1m9oQCLcBGAsYHQ/w640-h224/010.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;This is hard to capture in an image, but note how the shadow in time seems to crawl "up" towards the sun.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;Sun shadows are pre-resolved into a screen-space buffer prior to the lighting compute pass, I guess to simplify compute shaders and achieve higher occupancy. This buffer is generated in a pass that binds quite a few textures, two of which look CSM-ish. One is clearly a CSM, with in my case five entries in a texture array, where slices 0 to 3 are different cascades, but the last slice appears to be the same cascade as slice 0 but from a slightly different perspective.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;There's surely a lot to reverse-engineer here if one was inclined to do the work!&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-38tlP29gG0M/X9ulrq40zQI/AAAAAAAACNg/QRyZf5ma0RoO0jIryhm_sfn02fSVFoHhQCLcBGAsYHQ/s1499/Capture.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="591" data-original-width="1499" height="252" src="https://1.bp.blogspot.com/-38tlP29gG0M/X9ulrq40zQI/AAAAAAAACNg/QRyZf5ma0RoO0jIryhm_sfn02fSVFoHhQCLcBGAsYHQ/w640-h252/Capture.PNG" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The slices of the texture on the bottom (in red) are clearly CSM. The partially rendered slices in gray are a mystery. The yellow/green texture is, clearly, resolved screen-space sun shadows, I've never, so far, seen the green channel used in a capture.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;All other shadows in the scene are some form of VSMs, computed again incrementally over time. I've seen 512x512 and 256x256 used, and in my captures, I can see five shadowmaps rendered per frame, but I'm guessing this depends on settings. Most of these seem only bound as render targets, so again it might be that it takes multiple frames to finish rendering them. One gets blurred (VSM) into a slice of a texture array - I've seen some with 10 slices and others with 20.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-HIs4TfNLeAY/X9sPfvI0-xI/AAAAAAAACHw/o-mxU7OOhgsfOA-dhNCIZjOduJV9WppGQCLcBGAsYHQ/Capture1.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="430" data-original-width="1297" height="212" src="https://lh3.googleusercontent.com/-HIs4TfNLeAY/X9sPfvI0-xI/AAAAAAAACHw/o-mxU7OOhgsfOA-dhNCIZjOduJV9WppGQCLcBGAsYHQ/w640-h212/Capture1.PNG" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A few of the VSM-ish shadowmaps on the left, and artefacts of the screen-space raymarched contact shadows on the right, e.g. under the left arm, the scissors and other objects in contact with the plane...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;Finally, we have what the game settings call "contact shadows" - which are screen-space, short-range raymarched shadows. These seem to be computed by the lighting compute shaders themselves, which would make sense as these know about lights and their directions...&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Overall, shadows are both simple and complex. The setup, with CSMs, VSMs, and optionally raymarching is not overly surprising, but I'm sure the devil is in the detail of how all these are generated and faded in. It's rare to see obvious artifacts, so the entire system has to be praised, especially in an open-world game!&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;Lighting part III: All the rest...&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Since booting the game for the first time I had the distinct sense that most lighting is actually not in the form of analytic lights - and indeed looking at the captures this seems to not be unfounded. At the same time, there are no lightmaps, and I doubt there's anything pre-baked at all. This is perhaps one of the most fascinating parts of the rendering.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-bbC6CTELyWg/X9ulxSo8mUI/AAAAAAAACNo/Q1Qqth8zrNcZkQHZ699GUtENhQoK78dQwCLcBGAsYHQ/s1652/011.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="598" data-original-width="1652" height="232" src="https://1.bp.blogspot.com/-bbC6CTELyWg/X9ulxSo8mUI/AAAAAAAACNo/Q1Qqth8zrNcZkQHZ699GUtENhQoK78dQwCLcBGAsYHQ/w640-h232/011.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;First pass highlighted is the bent-cone AO for this frame, remaining passes do smoothing and temporal reprojection.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;First of all, there is a very good half-res SSAO pass. This is computed right after the uber-depth-summarization pass mentioned before, and it uses the packed RGBA8 normal-roughness instead of the g-buffer one.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;It looks like it's computing bent normals and aperture cones - impossible to tell the exact technique, but it's definitely doing a great job, probably something along the lines of HBAO-GTAO. First, depth, normal/roughness, and motion vectors are all downsampled to half-res. Then a pass computes current-frame AO, and subsequent ones do bilateral filtering and temporal reprojection. The dithering pattern is also quite regular if I had to guess, probably Jorge's Gradient noise?&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;It's easy to guess that the separate diffuse-specular emitted from the lighting pass is there to make it easier to occlude both more correctly with the cone information.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-kL-t2u0d_B8/X9sPl0DJMVI/AAAAAAAACH4/43dZuZS7yWI7oEddbuLWljHzDPlZOIDegCLcBGAsYHQ/012.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="592" data-original-width="654" height="362" src="https://lh3.googleusercontent.com/-kL-t2u0d_B8/X9sPl0DJMVI/AAAAAAAACH4/43dZuZS7yWI7oEddbuLWljHzDPlZOIDegCLcBGAsYHQ/w400-h362/012.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;One of many specular probes that get updated in an array texture, generating blurred mips.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;Second, we have to look at indirect lighting. After the light clustering pass there are a bunch of draws that update a texture array of what appear to be spherically (or dual paraboloid?) unwrapped probes. Again, this is distributed across frames, not all slices of this array are updated per frame. It's not hard to see in captures that some part of the probe array gets updated with new probes, generating on the fly mipmaps, presumably GGX-prefiltered.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-uGNwRe4lM4g/X9sPoe8-cqI/AAAAAAAACH8/INPEcs7WMWoo7uuXs98yWUiRtIlEd6yagCLcBGAsYHQ/013.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="572" data-original-width="1312" height="175" src="https://lh3.googleusercontent.com/-uGNwRe4lM4g/X9sPoe8-cqI/AAAAAAAACH8/INPEcs7WMWoo7uuXs98yWUiRtIlEd6yagCLcBGAsYHQ/w400-h175/013.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A mysterious cubemap. It looks like it's compositing sky (I guess that dynamically updates with time of day) with some geometry. Is the red channel an extremely thing g-buffer?&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The source of the probe data is harder to find though, but in the main capture I'm using there seems to be something that looks like a specular cubemap relighting happening, it's not obvious to me if this is a different probe from the ones in the array or the source for the array data later on.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Also, it's hard to say whether or not these probes are hand placed in the level, if the relighting assumption is true, then I'd imagine that the locations are fixed, and perhaps artist placed volumes or planes to define the influence area of each probe / avoid leaks.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-REAm7lCte88/X9sPqlfNwsI/AAAAAAAACIA/lAZTrqsZh6Ut4O3PShY9CHDINl7COxcXwCLcBGAsYHQ/014.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="572" data-original-width="1542" height="238" src="https://lh3.googleusercontent.com/-REAm7lCte88/X9sPqlfNwsI/AAAAAAAACIA/lAZTrqsZh6Ut4O3PShY9CHDINl7COxcXwCLcBGAsYHQ/w640-h238/014.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;A slice of the volumetric lighting texture, and some disocclusion artefacts and leaks in a couple of frames.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;We have your "standard" volumetric lighting, computed in a 3d texture, with both temporal reprojection. The raymarching is clamped using the scene depth, presumably to save performance, but this, in turn, can lead to leaks and reprojection artifacts at times. Not too evident though in most cases.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-1-jMMhWcUi8/X9ul26ng4SI/AAAAAAAACNw/1cxKd1Rvn1k4fJaVwrOkwC6f7sh_hQUSwCLcBGAsYHQ/s1378/015.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="774" data-original-width="1378" height="360" src="https://1.bp.blogspot.com/-1-jMMhWcUi8/X9ul26ng4SI/AAAAAAAACNw/1cxKd1Rvn1k4fJaVwrOkwC6f7sh_hQUSwCLcBGAsYHQ/w640-h360/015.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Screen-Space Reflections&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Now, things get very interesting again. First, we have an is an amazing Screen-Space Reflection pass, which again uses the packed normal/roughness buffer and thus supports blurry reflections, and at least at my rendering settings, is done at full resolution.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;It uses previous-frame color data, before UI compositing for the reflection (using motion vectors to reproject). And it's quite a lot of noise, even if it employs a blue-noise texture for dithering!&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-DhE56d2JeXg/X9sPvWQpVKI/AAAAAAAACIM/ptQVfB6_3ykLsQrfnMqjblvhj9xmVYvtACLcBGAsYHQ/016.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="710" data-original-width="1314" height="346" src="https://lh3.googleusercontent.com/-DhE56d2JeXg/X9sPvWQpVKI/AAAAAAAACIM/ptQVfB6_3ykLsQrfnMqjblvhj9xmVYvtACLcBGAsYHQ/w640-h346/016.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Diffuse/Ambient GI, reading a volumetric cube, which is not easy to decode...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;Then, a indirect diffuse/ambient GI. Binds the g-buffer and a bunch of 64x64x64 volume textures that are hard to decode. From the inputs and outputs one can guess the volume is centered around the camera and contains indices to some sort of computed irradiance, maybe spherical harmonics or such.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The lighting is very soft/low-frequency and indirect shadows are not really visible in this pass. This might even by dynamic GI!&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Certainly is volumetric, which has the advantage of being "uniform" across all objects, moving or not, and this coherence shows in the final game.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-yh1PjDZP01I/X9ul7882KTI/AAAAAAAACN4/Hm4NIeWdIekrhtU8qZTgAvmwKqOkwog7wCLcBGAsYHQ/s1708/017.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="482" data-original-width="1708" height="180" src="https://1.bp.blogspot.com/-yh1PjDZP01I/X9ul7882KTI/AAAAAAAACN4/Hm4NIeWdIekrhtU8qZTgAvmwKqOkwog7wCLcBGAsYHQ/w640-h180/017.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Final lighting composite, diffuse plus specular, and specular-only.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;And finally, everything gets composited together: specular probes, SSR, SSAO, diffuse GI, analytic lighting. This pass emits again two buffers, one which seems to be final lighting, and a second with what appears to be only the specular parts.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;And here is where we can see what I said at the beginning. Most lighting is not from analytic lights! We don't see the usual tricks of the trade, with a lot of "fill" lights added by artists (albeit the light design is definitely very careful), instead indirect lighting is what makes most of the scene. This indirect lighting is not as "precise" as engines that rely more heavily on GI bakes and complicated encodings, but it is very uniform and regains high-frequency effects via the two very high-quality screen-space passes, the AO and reflection ones.&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family: arial;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-bdgbmkY6UIM/X9umBi5aKBI/AAAAAAAACN8/FwHp6pBmjLEI1E3NdCuFNoL21iHWl5I3gCLcBGAsYHQ/s1519/Capture2.PNG" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="565" data-original-width="1519" height="238" src="https://1.bp.blogspot.com/-bdgbmkY6UIM/X9umBi5aKBI/AAAAAAAACN8/FwHp6pBmjLEI1E3NdCuFNoL21iHWl5I3gCLcBGAsYHQ/w640-h238/Capture2.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-38jST1klN0s/X9umGWHCiXI/AAAAAAAACOA/W_A1KdeUCtUTOiCDEpBCaxu7gbWZWW-2ACLcBGAsYHQ/s1522/Capture3.PNG" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="560" data-original-width="1522" height="236" src="https://1.bp.blogspot.com/-38jST1klN0s/X9umGWHCiXI/AAAAAAAACOA/W_A1KdeUCtUTOiCDEpBCaxu7gbWZWW-2ACLcBGAsYHQ/w640-h236/Capture3.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;The screen-space passes are quite noisy, which in turn makes temporal reprojection really fundamental, and this is another extremely interesting aspect of this engine. Traditional wisdom says that reprojection does not work in games that have lots of transparent surfaces. The sci-fi worlds of Cyberpunk definitely qualify for this, but the engineers here did not get the news and made things work anyway!&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;And yes, sometimes it's possible to see reprojection artifact, and the entire shading can have a bit of "swimming" in motion, but in general, it's solid and coherent, qualities that even many engines using lightmaps cannot claim to have. Light leaks are not common, silhouettes are usually well shaded, properly occluded.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;b&gt;All the rest&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;There are lots of other effects in the engine we won't cover - for brevity and to keep my sanity. Hair is very interesting, appearing to render multiple depth slices and inject itself partially in the g-buffer with some pre-lighting and weird normal (fake anisotropic?) effect. Translucency/skin shading is surely another important effect I won't dissect.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-EuTVj_sfL5E/X9umMNhR2_I/AAAAAAAACOM/wPmGc_QtDB4KChTGl_kWmh9W9WLLUQxyACLcBGAsYHQ/s1302/018.png" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="498" data-original-width="1302" height="244" src="https://1.bp.blogspot.com/-EuTVj_sfL5E/X9umMNhR2_I/AAAAAAAACOM/wPmGc_QtDB4KChTGl_kWmh9W9WLLUQxyACLcBGAsYHQ/w640-h244/018.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Looks like charts caching lighting...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Before the frame is over though, we have to mention transparencies - as more magic is going on here for sure. First, there is a pass that seems to compute a light chart, I think for all transparencies, not just particles.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Glass can blur whatever is behind them, and this is done with a specialized pass, first rendering transparent geometry in a buffer that accumulates the blur amount, then a series of compute shaders end up creating three mips of the screen, and finally everything is composited back in the scene.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-hlgY9S_NmkA/X9umRhzIEmI/AAAAAAAACOU/zpr4fBrKMQ872Yxck3R2k_OSagfjRnPaQCLcBGAsYHQ/s1431/Capture4.PNG" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="619" data-original-width="1431" height="277" src="https://1.bp.blogspot.com/-hlgY9S_NmkA/X9umRhzIEmI/AAAAAAAACOU/zpr4fBrKMQ872Yxck3R2k_OSagfjRnPaQCLcBGAsYHQ/w640-h277/Capture4.PNG" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;After the "glass blur", transparencies are rendered again, together with particles, using the lighting information computed in the chart. At least at my rendering settings, everything here is done at full resolution.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-kYuFo70VMp8/X9umXTlWppI/AAAAAAAACOc/zKU17uWhNswP-etH5929wAhpE1RWyFrlgCLcBGAsYHQ/s1052/Capture5.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="640" data-original-width="1052" height="390" src="https://1.bp.blogspot.com/-kYuFo70VMp8/X9umXTlWppI/AAAAAAAACOc/zKU17uWhNswP-etH5929wAhpE1RWyFrlgCLcBGAsYHQ/w640-h390/Capture5.PNG" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Scene after glass blur (in the inset) and with the actual glass rendered on top (big image)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;Finally, the all-mighty temporal reprojection. I would really like to see the game without this, the difference before and after the temporal reprojection is quite amazing. There is some sort of dilated mask magic going on, but to be honest, I can't see anything too bizarre going on, it's astonishing how well it works.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Perhaps there are some very complicated secret recipes lurking somewhere in the shaders or beyond my ability to understand the capture.&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-gO2R-e5TmHs/X9umb0DXKFI/AAAAAAAACOk/1h6cMKV0PJcwb1Msz7rd_l-Z-pJoh8XgACLcBGAsYHQ/s1499/Capture6.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="625" data-original-width="1499" height="266" src="https://1.bp.blogspot.com/-gO2R-e5TmHs/X9umb0DXKFI/AAAAAAAACOk/1h6cMKV0PJcwb1Msz7rd_l-Z-pJoh8XgACLcBGAsYHQ/w640-h266/Capture6.PNG" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;On the left, current and previous frame, on the right, final image after temporal reprojection.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-rrvMn-e22vo/X9sSMk8zvcI/AAAAAAAACJ0/7YSc9F--T242NeQs1tL6WvS-XoMziocYgCLcBGAsYHQ/Capture7.PNG" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="" data-original-height="526" data-original-width="932" height="226" src="https://lh3.googleusercontent.com/-rrvMn-e22vo/X9sSMk8zvcI/AAAAAAAACJ0/7YSc9F--T242NeQs1tL6WvS-XoMziocYgCLcBGAsYHQ/w400-h226/Capture7.PNG" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;This is from a different frame, a mask that is used for the TAA pass later on...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;I wrote "finally" because I won't look further, i.e. the details of the post-effect stack, things here are not too surprising. Bloom is a big part of it, of course, almost adding another layer of indirect lighting, and it's top-notch as expected, stable, and wide.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p style="text-align: justify;"&gt;&lt;span style="font-family: arial;"&gt;Depth of field, of course, tone-mapping and auto-exposure... There are of course all the image-degradation fixings you'd expect and probably want to disable: film grain, lens flares, motion blur, chromatic aberration... Even the UI compositing is non-trivial, all done in compute, but who has the time... Now that I got all this off my chest, I can finally try to go and enjoy the game! Bye!&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/KM0KiLlotaY" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/136009820948484982/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=136009820948484982" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/136009820948484982" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/136009820948484982" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/KM0KiLlotaY/hallucinations-re-rendering-of.html" title=" Hallucinations re: the rendering of Cyberpunk 2077" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-Accm4KmCjcQ/X90IqbPkniI/AAAAAAAACO4/Y30F2-QUQuEN3oa44WvOhq4zrALKMpAHwCLcBGAsYHQ/s72-w400-h224-c/Capture.PNG" height="72" width="72" /><thr:total>12</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/12/hallucinations-re-rendering-of.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-2948069219974519110</id><published>2020-12-01T17:22:00.003-08:00</published><updated>2020-12-01T17:23:50.662-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Announcements" /><title type="text">Digital Dragons 2020</title><content type="html">&lt;span style="font-family: arial;"&gt;Slides from my two presentations at this year's Digital Dragons. Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;a href="https://www.dropbox.com/s/0cn9t10xy8f69yz/DD-OpenProblems.pdf?dl=0"&gt;Open Problems in Real-Time Rendering&lt;/a&gt;&lt;/span&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;A.k.a. Are we solving the wrong problems today?&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;We have been looking a lot at certain bits and pieces of math, but are we looking at the -right- pieces?&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial;"&gt;A reminder that math and physics don't matter, if they don't solve actual problems for people - artists, or players.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-j1UVoClAAwo/X8bsm3ZZUPI/AAAAAAAACFI/lDjxPTjpVnk4RUW1vKL9nNapYJjISj2MgCLcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="704" data-original-width="1254" height="225" src="https://lh3.googleusercontent.com/-j1UVoClAAwo/X8bsm3ZZUPI/AAAAAAAACFI/lDjxPTjpVnk4RUW1vKL9nNapYJjISj2MgCLcBGAsYHQ/w400-h225/image.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;i&gt;Note: Naty Hoffman in his presentation at &lt;a href="https://blog.selfshadow.com/publications/s2020-shading-course/"&gt;Siggraph 2020 physically based shading course&lt;/a&gt;&amp;nbsp;makes some similar (better!) remarks while he shows how we don't know Fresnel very well... Must read!&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;a href="https://www.dropbox.com/s/9z7p6kg3utjzf7f/dd-metaverse.pdf?dl=0"&gt;Rendering the Metaverse across Space and Time.&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;An introduction to Roblox and how its design and mission shapes the work we do to render shared worlds on almost any device, any graphics API - and how we Roblox has been achieving that for more than a decade now.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-Y2qpOnfYEzU/X8bsfpeEXWI/AAAAAAAACFE/IcLWuyYzPZQj7XsFGkD0YhxhIQshN5VCQCLcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="600" data-original-width="1094" height="220" src="https://lh3.googleusercontent.com/-Y2qpOnfYEzU/X8bsfpeEXWI/AAAAAAAACFE/IcLWuyYzPZQj7XsFGkD0YhxhIQshN5VCQCLcBGAsYHQ/w400-h220/image.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/ko4EkovKADM" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/2948069219974519110/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=2948069219974519110" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/2948069219974519110" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/2948069219974519110" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/ko4EkovKADM/digital-dragons-2020.html" title="Digital Dragons 2020" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-j1UVoClAAwo/X8bsm3ZZUPI/AAAAAAAACFI/lDjxPTjpVnk4RUW1vKL9nNapYJjISj2MgCLcBGAsYHQ/s72-w400-h225-c/image.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/12/digital-dragons-2020.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-5457500623859977439</id><published>2020-11-25T14:26:00.007-08:00</published><updated>2020-12-01T17:05:37.375-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Rendering tutorials" /><title type="text">Baking a Realistic Renderer from Scratch and other resources for Beginners in Computer Graphics</title><content type="html">&lt;p&gt;&lt;span style="font-family: arial;"&gt;Dump of a few things I got that can be useful for beginners in 3D Computer Graphics programming.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;Download &lt;a href="https://www.dropbox.com/s/e1zmz4n85xngaxw/3D%20Computer%20Graphics%20Resources%20for%20Beginners.pdf?dl=0"&gt;a snapshot of my "3D Computer Graphics for Beginners"&lt;/a&gt; curated collection of projects and resources. I know all the cool kids do this in GitHub and would call it "awesome something" - but I'm lazy and a contrarian so what you get is am ugly PDF made from a google docs page :)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-Ml2ri5CR6h8/X8bnvOxrCEI/AAAAAAAACEM/43-KEHHeMjU3MQTXckBX8m4cfed6wfq5ACLcBGAsYHQ/image.png" style="font-family: arial; margin-left: 1em; margin-right: 1em; text-align: center;"&gt;&lt;img alt="" data-original-height="512" data-original-width="1188" height="173" src="https://lh3.googleusercontent.com/-Ml2ri5CR6h8/X8bnvOxrCEI/AAAAAAAACEM/43-KEHHeMjU3MQTXckBX8m4cfed6wfq5ACLcBGAsYHQ/w400-h173/image.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;ul style="text-align: left;"&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;Past two weeks I was invited by my master's thesis professor, Andrea Abate, to give a (virtual) seminar at my alma mater, the University of Salerno. You can grab the materials I've made for this here:&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;Part 1: &lt;a href="https://www.dropbox.com/s/9nncapjrmp5lb1k/UNISA_1_GPU.pdf?dl=0"&gt;Where do GPUs come from&lt;/a&gt;. This is a rehash of a talk that I've been doing for a while now, I've posted at least another time about this &lt;a href="http://c0de517e.blogspot.com/2017/05/where-do-gpus-come-from.html"&gt;here&lt;/a&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: arial;"&gt;Part 2: &lt;a href="https://www.dropbox.com/s/dzya6p9pj92tq4y/UNISA_2_RENDERING.pdf?dl=0"&gt;Baking a Realistic Renderer from scratch&lt;/a&gt;. This one is novel - and gives the title to this post. In the slides, we go from zero to a path tracer in about two hours, doing the necessary math step by step and (live) coding the renderer in C, via &lt;a href="https://github.com/anael-seghezzi/CToy"&gt;CToy&lt;/a&gt;. &lt;a href="https://www.dropbox.com/s/19gkv65ly3z6gzy/UNISA_RT_CTOY.zip?dl=0"&gt;Here is the CToy build I used together with the sourcecode for all the steps&lt;/a&gt;.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-0w3qW7fP2z8/X8boVyNyYBI/AAAAAAAACEU/iT2QTQvI7z83hnvc-wp93XpwRkqKp3LrQCLcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="1240" data-original-width="1588" height="313" src="https://lh3.googleusercontent.com/-0w3qW7fP2z8/X8boVyNyYBI/AAAAAAAACEU/iT2QTQvI7z83hnvc-wp93XpwRkqKp3LrQCLcBGAsYHQ/w400-h313/image.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;If you're in the States, maybe you can fine here something to tinker with during this self-isolated thanksgiving. Enjoy your holidays!&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/fQ6JC3ZsS-c" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/5457500623859977439/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=5457500623859977439" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/5457500623859977439" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/5457500623859977439" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/fQ6JC3ZsS-c/baking-realistic-renderer-from-scratch.html" title="Baking a Realistic Renderer from Scratch and other resources for Beginners in Computer Graphics" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/-Ml2ri5CR6h8/X8bnvOxrCEI/AAAAAAAACEM/43-KEHHeMjU3MQTXckBX8m4cfed6wfq5ACLcBGAsYHQ/s72-w400-h173-c/image.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/11/baking-realistic-renderer-from-scratch.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-1799377145145367409</id><published>2020-06-05T14:43:00.003-07:00</published><updated>2020-06-06T22:41:47.312-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Off-topic" /><title type="text">OT: To my white friends. A few words on #BLM.</title><content type="html">&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Hi all.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;We all see what's going on in the US these days, so I'll cut to the chase. This isn't going to be a lecture, do not worry, nor I'm turning this blog into a political platform.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;But, I realized over the years that I've not been always part of the solution for our ongoing social issues, and I hope some of the following can help others.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;em style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;This is not about where to donate or what to do or not to do to help.&amp;nbsp;&lt;/em&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;This is about how to help yourself. It is our responsibility to solve our own conflicts, and only through that, we can be good to others.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;strong style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Forgive yourself. Then move forward.&lt;/strong&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;This is not easy. There is a reason why we minimize social issues, why our brains are always trying to see a justification. Yes, it sucks, but... But he shouldn't have done this. But let's see how it goes. We have to hear from both sides. But, but but...&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;You're fighting against yourself. We are all privileged in some way, we truly are.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;To be open to that means shaking your foundation. We've been given something that we didn't do anything to deserve. But we do deserve things! We are smart, we worked hard, we have our issues, we have our self-worth. We matter!&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Saying the word "privilege" is an attack, no matter if it registers consciously or not, it erodes some of our self-worth. Our brains, our very own humanity, is not built to accept it.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Have you ever looked at a person on the street and felt an idea forming in your mind, that perhaps they did something to deserve it. Perhaps their situation is a result of their actions?&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;That's the mechanism in action. We cannot accept that we are not the masters of our lives, that we don't have control. It's scary and uncomfortable, and we are built to resist it. What meaning does life has if the biggest differences between people are left to the toss of a coin?&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;This is not about justifying our actions or inactions. It's not about moral judgement at all. It's about understanding how ego and feeling work, understand that they are part of humanity and for a good reason.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;But also, once you truly understand it, you can move past them, not by suppressing them, but by knowing they exist for a reason, and not having them dominate your choices.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;This is not about judgment, it's not about being nice either. It's a continuous self-reflection that helps us live consciously. It's not easy, it's definitely uncomfortable, and there is no victory to be had.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;It is, what some might call, a practice, or a philosophy. You cannot win or lose, fail or succeed, because judgment is not part of any of this. It's about being conscious of our own humanity.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;strong style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;All lives matter?&lt;/strong&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;That said, I want to address a couple of issues that I think stem from our egos, maybe you will agree.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;The first is the phrase "all lives matter", which is always uttered by us, white people. Now, given the above, you might know where I'm going.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Why do people say this? Are they racist? What does it mean to be racist anyway? Is being fair racist now? Let's try to untangle these things.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;First, you have to realize that this is an emotional response, that your brain masks with rationalization. Wait a second, hear me out, don't get defensive now. I think you can see how the phrase is at face value, quite silly.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;When an acquaintance faces a loss, we say, I'm sorry for your loss. We do not say, I'm sorry for all the people that lost others in the world. Imagine being on the receiving end of a similar rebuttal. You feel strongly about something, and someone feels the need for interjecting and shifting the attention. You see the problem?&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;And it's a rationalization. It's obvious that "black lives matter" does not subtract from the worthiness of others, but it shines a light to a specific imbalance of power. A picture is worth a thousand words:&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/---YlmfqqVsE/Xtq2VpwTcBI/AAAAAAAAB_4/7_HlZosqCbUw7uZ4YZnq1bPqPHFcQPOagCLcBGAsYHQ/s1600/equity-300x225.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="225" data-original-width="300" src="https://1.bp.blogspot.com/---YlmfqqVsE/Xtq2VpwTcBI/AAAAAAAAB_4/7_HlZosqCbUw7uZ4YZnq1bPqPHFcQPOagCLcBGAsYHQ/s1600/equity-300x225.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;The "all lives matter" crowd is not about good or bad people, shades of racism. It's a natural response that we have. The feeling is human, but it is not a justification. It is our own responsibility to learn how to deal with feelings, understand what are they telling us, and act after we observed them, not driven by them.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;strong style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;There are bad people on both sides.&lt;/strong&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Now that we got the easy one out, this is going to be a bit more of a challenge.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;How do we feel about looting? Here we have a divide, the uncomfortable line. Should I say ACAB? Can I justify riots, destruction? What do they want to achieve! Don't they realize they're undermining the message, the mission? I stand for political change, for laws being passed, the bad apples removed, this doesn't help at all!&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;I understand. And you're right. But, realize this is a matter of perspective. And hold on! Because I'm not going to justify anyone here, just try to look at the problem from a different angle.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;The reason why we want change, actual action, push for laws, make donations, perhaps even study the problem in papers and publications, understand how's best to spend money, de-fund police and prioritize social programs and so on...&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;All these thoughts I understand, I grew up in a middle class, intellectual, left-wing, progressive family. I get fighting the good fight, being involved, I get socialism and welfare.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;What I didn't get, until recently, is how other people didn't see the same. How is it that even if we want the same objective, some people are looting and some people are reading?&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;In retrospect, the answer is obvious. It's because I believe in society. And why wouldn't I? It always worked great for me.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;The thing I cannot see is the perspective of someone that doesn't believe in it anymore. That is not willing to fix the social contract, it's just ok to tear it up because it never worked. I can imagine the scenarios. What if my life didn't matter much anymore? Would I be thinking of what's best for the world, or just watch it burn?&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Understand that you will never fully understand. That it is not the responsibility of others to explain either, nor it justifies actions. Actions will be the perspective of history, and what in the end did or not change society.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;I think that looting will probably not help, it's actually a complex effect like anything real world is, that's not the point.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;The point is that we cannot escape living lives from a given perspective. It's not because we're good or bad, it is yet another limitation of being human.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;If we get that, then hopefully we can understand how we feel, understand that others feel, and have less a need to justify nor judge.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Lastly, when it doubt, take responsibility. You might think "butwhatabout... X", or "yes, but...Y". And you're right. X and Y matter, it is true, it's not crazy, it's not a lie. But check if X and Y are about others, other communities, other people's behaviors, farther from you.&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;span data-preserver-spaces="true" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;Then, understand that responsibility starts with us, radiates from us. Again, this does not justify or diminish X and Y. They are still true, and important. But, as a great philosopher once said "I'm starting with the man in the mirror".&lt;/span&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #0e101a; margin-bottom: 0pt; margin-top: 0pt;"&gt;&lt;em style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; margin-bottom: 0pt; margin-top: 0pt;"&gt;As all my posts are, this is improvised, and I might revisit it in time. Stay safe. Love you all.&lt;/em&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/Y0LCXcm4F6Q" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/1799377145145367409/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=1799377145145367409" title="14 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1799377145145367409" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1799377145145367409" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/Y0LCXcm4F6Q/ot-from-perspective-of-white-man-few.html" title="OT: To my white friends. A few words on #BLM." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/---YlmfqqVsE/Xtq2VpwTcBI/AAAAAAAAB_4/7_HlZosqCbUw7uZ4YZnq1bPqPHFcQPOagCLcBGAsYHQ/s72-c/equity-300x225.jpg" height="72" width="72" /><thr:total>14</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/06/ot-from-perspective-of-white-man-few.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-8107934285054062871</id><published>2020-05-15T19:27:00.002-07:00</published><updated>2020-05-15T20:38:05.851-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Graphic rants" /><title type="text">Some thoughts on Unreal 5's Nanite - in way too many words</title><content type="html">&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Preface&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;For the past decade or two, improvements in videogame real-time rendering fidelity have always been going in locksteps with console releases, as these provide a large install base of relatively powerful (and power-efficient) GPUs that provide the anchoring for rendering technology and asset authoring.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Thus, now that the next next-generation is knocking at the door, we should start seeing more and more interesting, applied R&amp;amp;D coming out, after the relative slump of the last year or two. Exciting times!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Of course, though I'm not writing this because we're eager in general about tinkering with new next-gen toys, but because in the last two days we've been going through lots of excitement as we've seen a few great demos, starting a week ago with Sebastien Hillaire's new atmospheric sky simulation, then the Unreal 5 announcement showcasing Nanite's geometry and Lumen's GI, and finally NVidia releasing a new demo of their vision for RTX raytracing and cloud (as in datacenters) rendering.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Of all these, it's undeniable that Nanite is the one that got the most attention, at least from rendering professionals. Why is that? I don't think this is just because of visual appeal, albeit Brian is undeniably in the exclusive pantheon of most handsome rendering engineers (in my heart, only challenged by Drobot), we always expect beauty from Unreal demos.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-7jDqUDnEHHU/Xr9LR1TnJ_I/AAAAAAAAB-U/5S2qiwMtUX8aXQGof4whQDRqvUHd6LdUACLcBGAsYHQ/s1600/Screen%2BShot%2B2020-05-15%2Bat%2B7.08.57%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1136" data-original-width="1600" height="227" src="https://1.bp.blogspot.com/-7jDqUDnEHHU/Xr9LR1TnJ_I/AAAAAAAAB-U/5S2qiwMtUX8aXQGof4whQDRqvUHd6LdUACLcBGAsYHQ/s320/Screen%2BShot%2B2020-05-15%2Bat%2B7.08.57%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I think the real difference here between this and many other incredibly smart developments, is that rendering development has been incredibly unbalanced. While we know that we don't know anything about almost anything, when we look at the big picture, it's also undeniable that we spent a lot more effort in certain areas than others.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Shading, since we started this idea of PBR, has seen a ton of attention, ostensibly way past the point where innovation in that realm actually translates to benefits for artists and visual quality for end-users (remember, PBR started as an idea to reduce the amount of weird, ad-hoc controls and shaders we were asking artists to tune!). I would even venture that we know exact solutions for certain specific problems in the shading equation, while never having proved that these were the &lt;a href="https://c0de517e.blogspot.com/2019/05/seeing-whole-physically-based-picture.html"&gt;most significant source of error&lt;/a&gt; when looking at the end-to-end pipeline...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Light transport is arguably a much bigger problem, both algorithmically and in its influence in the end quality, and it's far from being solved... But we were not slacking. Most rendering innovation is light transport in real-time rendering: shadows, various ideas on occlusion and indirect illumination, area lighting and environment lighting, and so on and so forth. Important, yes. Definitely not "solved" yet. But an area where we applied the brunt force of hundreds of genius minds for the last decade, arriving now at solutions that are undeniably quite amazing.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;a href="https://c0de517e.blogspot.com/2019/06/the-value-of-pixels-presentation-slides.html"&gt;Art production on the other hand&lt;/a&gt;... We started with objects made of triangles and uv-mapped textures, and we largely are at objects made of triangles and uv-mapped textures. There has been some effort here and there to break free, from Lionhead's "mega meshes" to Carmack's "megatextures", but nothing that ultimately took hold in the industry.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-XNzaUwUjc9k/Xr9L25v4qaI/AAAAAAAAB-c/qN-J8D5AVIsbi70p7ojZIeHxgjFQ41CaACLcBGAsYHQ/s1600/Screen%2BShot%2B2020-05-15%2Bat%2B7.11.21%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="416" data-original-width="890" height="149" src="https://1.bp.blogspot.com/-XNzaUwUjc9k/Xr9L25v4qaI/AAAAAAAAB-c/qN-J8D5AVIsbi70p7ojZIeHxgjFQ41CaACLcBGAsYHQ/s320/Screen%2BShot%2B2020-05-15%2Bat%2B7.11.21%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Sure, we did, on the art side, started working in material layers (Substance et al), and with acquired data (photogrammetry, BRDF scanning), but that has been going mostly at a tooling level, with relatively "low tech" ideas (relatively!).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Yet, every time that we see something new (hello Dreams!) in the asset authoring domain, we get excited. We know that this matters, we agree. But we were perhaps still riding on the growth of big games being able to pay for sheer art grunt - even if we should know that saving on the human capital does not mean scaling down our production (necessarily), it means that people can focus their creativity on things that matter more.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Arguably it "had" to come from a third party engine. Games sell to users. Middleware sells to developers. Developer productivity is an end-product feature for an engine. Almost none of the successful gaming middleware was so due to being the most efficient implementation of a given concept, but because they understood (or outright created) the needs of their audience. Engineering excellence is not measured in instructions per cycle but in the ability to deliver amazing value to your customers. Sometimes this implies optimizing for IPC, sometimes it doesn't.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It's painfully obvious, I know, but I feel like it's worth reiterating when many professionals in our line of business used to deride the inefficiencies of Unity, notoriously, and even of course of Unreal itself which was never (and I think could never be) the absolute champion of rendering efficiency. Now both, of course, are hubs of excellence in rendering research.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So. Is this going to "be it"? Way too early to say. But any new piece of R&amp;amp;D in this area is amazing to see.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;How does this thing work?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-rYNTN-EAUJk/Xr9NUtwzH6I/AAAAAAAAB-w/X-Y9egPx_wYFYLW2BSPz9uLoplFVXRvVgCLcBGAsYHQ/s1600/Screen%2BShot%2B2020-05-15%2Bat%2B7.17.35%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="768" data-original-width="1184" height="207" src="https://1.bp.blogspot.com/-rYNTN-EAUJk/Xr9NUtwzH6I/AAAAAAAAB-w/X-Y9egPx_wYFYLW2BSPz9uLoplFVXRvVgCLcBGAsYHQ/s320/Screen%2BShot%2B2020-05-15%2Bat%2B7.17.35%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Who knows!&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Who cares!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, seriously. I know that we stand on the shoulders of the giants, and this is how progress is made, you don't need to tell me. And we're all eager to lean on Brian's and Graham's and all the rest of Epic's gang, (handsome) shoulders. But let's allow ourselves to be silly and wrong and imagine how this could be made. Puzzles are fun, and having everybody explore a single direction in R&amp;amp;D is a very dangerous thing.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-7e6i-bb_9E0/Xr9McAJ1wiI/AAAAAAAAB-o/_beSm8fJnqYyF036LmNEUDG6kU9aIDEuwCLcBGAsYHQ/s1600/Screen%2BShot%2B2020-05-15%2Bat%2B7.14.00%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="906" data-original-width="1160" height="249" src="https://1.bp.blogspot.com/-7e6i-bb_9E0/Xr9McAJ1wiI/AAAAAAAAB-o/_beSm8fJnqYyF036LmNEUDG6kU9aIDEuwCLcBGAsYHQ/s320/Screen%2BShot%2B2020-05-15%2Bat%2B7.14.00%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, let's start.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I think pixel-peeping the UE5 video is not particularly interesting. For what it's worth, I am not entirely sure that such a demo / vertical slice would not just run on a powerful enough GPU with semi-conventional techniques and just eating the memory footprint and killing the rasterizer. Desktop GPUs are so powerful that you can be very dumb and use a fraction of their power, still creating great results (and that's part of why consoles can "bridge the gap" or rather, most PC GPUs end up being not utilized as efficiently, in relative terms).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, let's start from the basic principles. I'd imagine that this technology is made with the explicit intent of being able to ingest any content (photogrammetry, movie assets, etc), that's to say, arbitrary triangle meshes, of whatever complexity and topology. I also would imagine that it would be ok to have some error when rendering them, as long as it's kept around the pixel/sub-pixel level.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;A few things seem to be a hard problem in crafting such technology:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;1) How to compress the data, so that we can hopefully still fit in the constraints of physical media (bluray) and we can push it through our vertex pipelines.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;2) How to LOD.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;2b) How to antialias, as we are effectively side-stepping normalmaps under our assumptions (baking detail from highpoly to intermediate cages).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;3) How to render pixel-sized geometric details efficiently.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;3b) How to do culling.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Of these problems, I would say the one it's hardest to talk about is the compression aspects. This is both a very well researched topic and something that interacts really with the specifics of the whole system in ways that, at least for me, make it impossible to use it as a starting point.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In fact, I'd say that the best approach for this is to start from rendering and work our way up.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Why can't we just use the hardware as is?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now, why is it hard to render pixel-sized or subpixel triangles?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Well, it isn't of course, a GPU just does it. But for the longest times GPUs with an almost universal assumption that there is a given pixel-to-triangle ratio (around an average of ten or so pixels per triangle), triangles do work-expansion. And this is really one of these cardinal ideas around which GPUs are balanced, we "expect" a given ratio between vertices and triangles, triangles to non-culled triangles, and finally triangles to pixels.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Many people, including myself, have been suggesting (to various vendors) the idea that such ratios should change (quite like other did, for example, ALU to TEX), but so far, unsuccessfully, and it's not hard to imagine why. We all know that gradients, and thus mipmaps et al, require 2x2 quads of course, so small triangles need to generate lots of partial quads wasting efficiency. Any GPU rendering pixel-size triangles would literally run at 1/4th of the compute efficiency.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Well, what if we don't need the gradients you ask? And I asked! But hardware people can be lazy. Once you know that you need quads then you can build your texture units to compute addressing in groups of 2x2, all the way down the memory lane. And you can build your work setup to create waves that in the very worst case will have wave_size/4 different triangles, and so on and so forth going "up" the pipeline.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Killing quads seems easy enough, making all the units up and downstream work with 4x more work isn't. In fact one could fundamentally argue that it would never be a good idea, because the raster is there (among other things) to -create- pixel work.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you have to have one-to-one raster to compute thread ratio, then one can argue that you wouldn't have a fixed function raster but rather some more instructions that do raster-like things for the compute pipeline... Perhaps near the texture units? I wonder how hardware raytracing works... :)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, so the hardware rasterizer is out of the window. What next? Here is where we start Dreaming...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Look, ma, no (hardware) raster!&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-wbqmEWW31FA/Xr9OF0ESfcI/AAAAAAAAB-8/5OTFfjsvwuoPaL92KdWx241raBqzQ-zWACLcBGAsYHQ/s1600/Screen%2BShot%2B2020-05-15%2Bat%2B7.21.02%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="836" data-original-width="1170" height="228" src="https://1.bp.blogspot.com/-wbqmEWW31FA/Xr9OF0ESfcI/AAAAAAAAB-8/5OTFfjsvwuoPaL92KdWx241raBqzQ-zWACLcBGAsYHQ/s320/Screen%2BShot%2B2020-05-15%2Bat%2B7.21.02%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Especially after Dreams, I think we all want non-orthodox rendering methods to be the answer. Volumes? SDF? Raymarching? Points? Perhaps we could even create crude shells around the geometry, raster them with the hardware, and leverage hardware raytracing (which ought to be "wider" and leveraging compute more than the fixed-function raster) for visibility inside the shell? I love it!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But as I start thinking of this a bit more, I don't think I would be able to make it work.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Volumes and SDFs are immensely powerful, but for this specific use-case, they would not guarantee that the original geometry is always preserved accurately, which I think is an important constraint. In general, I am always scared of leveraging data structures that require lots of iterations per pixel, but I'm probably wrong.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I really would like people to think more in that direction, but I failed. And the few "debug draw" frames from the Unreal presentation clearly show "arbitrary" triangles.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It is true though that, at least without pixel peeping every single frame, I could not notice any LOD switch / topology change, which with just triangle data sounds somewhat tricky even if triangles are that small.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The thing that "killed" the shell idea for me really though is that I don't think the hardware raster will help, because you'd need to output the depth of the fine geometry from a pixel shader, slowing down, if not killing outright, early depth rejection, which would be the only reason to leverage the hardware path anyways.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And we already know we can do all the culling work in software! We have games already shipped that move object culling, draw culling, triangle cluster, and even individual triangle culling to compute, pre-raster. We know we can already do better than the conventional hardware path when we dealing with complex geometry, and of course, all the CPU-side culling techniques still apply as well.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What's next? Another "obvious" source of inspiration is REYES, and Karis himself referenced to &lt;a href="http://www.cs.harvard.edu/~sjg/papers/gim.pdf"&gt;geometry images&lt;/a&gt;, that, if seen through the right distortion lens could remind of micropolygon grids.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Also, there are in the literature REYES implementations &lt;a href="https://markussteinberger.net/papers/GPUReyes.pdf"&gt;on the GPU&lt;/a&gt;, and other experiments with software rasterization, including ideas of "&lt;a href="http://graphics.stanford.edu/papers/fragmerging/shade_sig10.pdf"&gt;quad-merging&lt;/a&gt;" and so on.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, what does REYES do? Well, the idea there is to create regular grids of vertices, with the squares of the grid roughly pixel-sized. This allowed to then compute all shading on the grid in world space, which literally means shading and geometry detail are one-to-one (sort-of, actual implementations are more complex), while not needing all the topology information of arbitrary meshes (the connectivity is implicit, it's a grid).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It also means we compute shading pre-visibility (works even with path tracing! see Weta's &lt;a href="https://www.wetafx.co.nz/research-and-tech/technology/manuka/"&gt;Manuka&lt;/a&gt;), and the grid itself will provide a way to compute gradients and it serves as the unit of SIMD work.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Essentially, REYES maps the concepts that we know and love from HW raster (SIMD, gradients) to a different space (world/object instead of screen).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The question is now, do we need all that? I don't think we'd want to do shading this way, in fact, I doubt we want to do shading -at all- in our software solution, as it would be a million times harder than just resolving visibility.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And at the end we still have to rasterize the grid's triangle, the only thing that this provides in our case would be a compression format, essentially, mini-geometry images, and we don't care about that right now.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;From Karis on DigitalFoundry already spelled it out I think clearly. "The vast majority of triangles are software rasterized using hyper-optimized compute shaders specifically designed for the advantages we can exploit [...]".&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Would it be hard to imagine that we can extend &lt;a href="https://www.gdcvault.com/play/1023109/Optimizing-the-Graphics-Pipeline-With"&gt;Graham's ideas&lt;/a&gt; of GPU culling pipelines to distribute chunks of triangles to a software raster? Say that we removed the hard cases, we don't need to do shading, we don't even want to write gbuffers, just visibility (and some triangle IDs).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Chunks of triangles are small enough that one can send them to specialized shaders even bucketed for size or the need for clipping etc.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In the "simplest" case of unclipped, pixel-ish sizes triangles, it's not hard to beat the hardware raster with a "simple" shader that computes one triangle per thread.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In fact, this is certainly true for depth-only rendering, and I know that different people experimented with the idea for shadowmaps at the very least, not sure if it ever shipped in an era where these are often cached or the wasted raster work can be overlapped with other compute via async, but it's definitely possible.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, moving culling to compute and doing software rasterization in compute is definitely possible, and for small triangles, ought to be fast. One could even dream that some GPUs might have instructions to help visibility computation nowadays... But to be fair, I don't think that's the way here, with what we have right now.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now comes the real tricky things though. The software raster is easy to imagine, but how to do shading is not. I'm rather sure you do not want to write gbuffers or worse, do shading directly from the SW raster. You need to write a "visibility buffer".&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;As far as I know, here you have two options, you either &lt;a href="http://cg.ivd.kit.edu/publications/2015/dais/DAIS.pdf"&gt;write draw-IDs, UVs, gradients, and tangent-spaces&lt;/a&gt;, or you just &lt;a href="http://jcgt.org/published/0002/02/04/"&gt;write triangle/draw-IDs and barycentrics&lt;/a&gt;, then go back to the triangle data to compute UVs.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The &lt;a href="https://mynameismjp.wordpress.com/2016/03/25/bindless-texturing-for-deferred-rendering-and-decals/"&gt;first approach&lt;/a&gt; limits you to only one set of UVs (realistically) - that might not be a problem in many cases or if say, we had virtual texturing as well. It requires more bandwidth, but you do not need to access the geometric data "twice".&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The second decouples visibility from attribute fetching, and thus the vertex attributes can be arbitrary, but in general is more complex and I'd imagine you really don't want to have "fat" attributes when the geometry is this dense anyways, you really have to be careful with your inputs, so I guess it's overall less attractive.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Note that they both impose some limit on the number of draws you can do before you run out of IDs, but that's not a huge issue as one could find ways to "flush" the visibility buffer by resolving the shading (kind of what a mobile GPU does).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;With deferred rendering, we already moved roughly half of the shading out of the raster and into compute tiles. It was never a stretch of the imagination to think that we could move pieces out, and keep just visibility. I guess it's the natural next step to try to entirely get rid of the hardware raster (at least, when dealing with pixel-sized triangles)...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Compute-based culling, plus visibility buffers, plus compute-based raster. I guess what I'm saying is that the future is to implement mobile GPUs in software, huh?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Seriously though, &lt;a href="https://c0de517e.blogspot.com/2017/08/tiled-hardware-speculations.html"&gt;this has been in my mind for a while&lt;/a&gt;, and I know too little about GPU hardware to have a real opinion.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I wonder if the fact that we seem to be moving more and more towards concepts that exist in mobile GPU a proof that their design is smart, or a proof that such systems should not fundamentally be part of the hardware, because they can be efficiently implemented in software (and perhaps GPUs could help by providing some specialized instructions and data paths).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Also, would this imply not leveraging two of new cool GPU features we have now? Mesh shaders, and raytracing? Who knows.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;All of this, if it's even in the ballpark of something that can be realistically imagined, is still incredibly hard to actually make it work (I mean, even just on paper or in a demo, much less in a production system, complete with streaming and so on).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;On mobile hardware, there is a lot of (secret, magical) compression going on behind the scenes on the geometrical data, and this is without pushing pixel-sized triangles...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Of course, all this also implies throwing away quad-based gradients, but I guess that's not a huge stretch if the rest of the shading is mostly about fetching a single texture from an UV, directly.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And with raytracing (and honestly even some things in conventional deferred) we threw away quads already.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Or maybe one can take a page from REYES and bake everything into vertex data. One can even imagine that with so much geometrical detail, prefiltering becomes a lost war anyways and one really has to double-down on &lt;a href="https://research.activision.com/publications/2020-03/dynamic-temporal-antialiasing-and-upsampling-in-call-of-duty"&gt;temporal antialiasing&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Compression and LODs are the hard part in this scheme. Is it possible to extract chunks of regular topology, REYES-style, from arbitrary meshes? Sort of triangle-strips on steroids. Perhaps. Or maybe that doesn't matter as much, as long as you can stream really fast a lot of geometry.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If one managed to compress really well, one could argue that LODs are actually not that hard, especially if it's "just" about changing topology and reusing the vertex data, which for such dense meshes, and with triangles always being almost pixel-sized, it should be possible...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I guess that would be an decent use-case for cloud streaming, where a game could have terabytes of read-only data because they would not need to be delivered to the user's devices, and shared among many instances on the same hardware (bandwidth notwithstanding...).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I hope none of (the rather boring) things I wrote makes sense anyways, and they really likelt do not, as it's hard to even know what would really be hard, without starting to implement. And I&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&amp;nbsp;like to dream of what the next Dreams will look like... Maybe we don't need triangles at all! Render it on!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-YsHP8Ng0Z3Q/Xr9fIDJ3NBI/AAAAAAAAB_I/kF-U2siYaIAo0gaH_vi-Y0nvY-rMMTBgQCLcBGAsYHQ/s1600/Screen%2BShot%2B2020-05-15%2Bat%2B8.33.10%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="594" data-original-width="952" height="199" src="https://1.bp.blogspot.com/-YsHP8Ng0Z3Q/Xr9fIDJ3NBI/AAAAAAAAB_I/kF-U2siYaIAo0gaH_vi-Y0nvY-rMMTBgQCLcBGAsYHQ/s320/Screen%2BShot%2B2020-05-15%2Bat%2B8.33.10%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/K4oQ2LGQVtY" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/8107934285054062871/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=8107934285054062871" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/8107934285054062871" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/8107934285054062871" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/K4oQ2LGQVtY/some-thoughts-on-unreal-5s-nanite-in.html" title="Some thoughts on Unreal 5's Nanite - in way too many words" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-7jDqUDnEHHU/Xr9LR1TnJ_I/AAAAAAAAB-U/5S2qiwMtUX8aXQGof4whQDRqvUHd6LdUACLcBGAsYHQ/s72-c/Screen%2BShot%2B2020-05-15%2Bat%2B7.08.57%2BPM.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/05/some-thoughts-on-unreal-5s-nanite-in.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-7707982110664178341</id><published>2020-05-07T13:30:00.001-07:00</published><updated>2020-05-07T13:30:28.428-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Off-topic" /><title type="text">Menger sponge-ish</title><content type="html">&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Did these a while ago for the namecards of our rendering team at Roblox.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Figure someone might like them as desktop backgrounds...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;They were done in Processing, exported as SVGs and finalized in Inkscape.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/--amoJUfjMQg/XrRvhZ1_goI/AAAAAAAAB9I/BbxVhQWUEPMVmG-_CSkF7Skh467xtoZAACLcBGAsYHQ/s1600/Screen%2BShot%2B2020-05-07%2Bat%2B1.24.19%2BPM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="836" data-original-width="1460" height="183" src="https://1.bp.blogspot.com/--amoJUfjMQg/XrRvhZ1_goI/AAAAAAAAB9I/BbxVhQWUEPMVmG-_CSkF7Skh467xtoZAACLcBGAsYHQ/s320/Screen%2BShot%2B2020-05-07%2Bat%2B1.24.19%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Sample...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Grab the&amp;nbsp;&lt;a href="https://www.dropbox.com/s/me56gquzd4gpzka/Roblox%20Team%20Graphics.zip?dl=0"&gt;Images&lt;/a&gt;&amp;nbsp;here&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="https://www.dropbox.com/s/w43qp0f1tc2k6je/Roblox%20Team%20Sketches.pdf?dl=0"&gt;Sketches&lt;/a&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/a3UN9k_Cs7I" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/7707982110664178341/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=7707982110664178341" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/7707982110664178341" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/7707982110664178341" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/a3UN9k_Cs7I/menger-sponge-ish.html" title="Menger sponge-ish" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/--amoJUfjMQg/XrRvhZ1_goI/AAAAAAAAB9I/BbxVhQWUEPMVmG-_CSkF7Skh467xtoZAACLcBGAsYHQ/s72-c/Screen%2BShot%2B2020-05-07%2Bat%2B1.24.19%2BPM.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/05/menger-sponge-ish.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-4022828800918155407</id><published>2020-04-19T21:13:00.002-07:00</published><updated>2020-04-30T12:27:30.494-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="The industry" /><title type="text">The Technical Interview [LEAKED]</title><content type="html">&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Another small document made for the rendering team at Roblox (&lt;a href="https://c0de517e.blogspot.com/2019/08/engineering-career-guide-leaked.html"&gt;previous leak here&lt;/a&gt;).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;I believe in sharing knowledge, and I don't see, from videogame/realtime rendering teams many talking publicly about interviewing practices. I hope that it can be of some help.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="https://www.dropbox.com/s/2rm1pyu1vsno0sv/The%20Technical%20Interview.pdf?dl=0"&gt;Download here.&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"&gt;&lt;i&gt;P.s. these notes are about principles, and they can be implemented in many different ways - they won't really give much insight about the structure of the interviews we do. For that, you should come and interview with us :)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/vDi2VOUCHIU" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/4022828800918155407/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=4022828800918155407" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/4022828800918155407" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/4022828800918155407" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/vDi2VOUCHIU/the-technical-interview-leaked.html" title="The Technical Interview [LEAKED]" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/04/the-technical-interview-leaked.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-749078204889622806</id><published>2020-01-01T13:51:00.000-08:00</published><updated>2020-01-01T13:51:22.486-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Programming rants" /><title type="text">The grown-up programmer's (meta)manifesto</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Another year is almost over and years should bring wisdom. Most people make lists for things they want to do in the new year, here, let's write a manifesto for programmers.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;If you've been following me for a bit here or in an even-less-coherent form over twitter, these principles won't come as a surprise, but outside's cold, I'm taking a few days (mostly) away from work in my hometown, perfect time to organize some thoughts on this blog.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Meta-Rule 1: The only dogma is that we shall have none.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;I love the mathematical exactness of Computer Science, we sit at the foundation of mathematics (formal systems), reasoning (logic) with fascinating implications on philosophy as well. But that theoretical foundation has nothing to do with the actual job of programming computers.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;In practice, ours is a huge industry made of companies, teams, people, products and problems so heterogeneous that I doubt anyone can claim to understand it globally.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;It's rare to find truly "wrong" ideas or algorithms and technologies that have been superseded by newer systems that better them in all accounts. Most of our work deals in tradeoffs. Computers are binary, programming is not.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Ideas that are appropriate for a stable team of senior programmers are often not appropriate for a team that sees a rapid turnover or that wants to grow a significant amount of juniors.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Methodologies that work for innovative, research-driven projects are probably not the same that should be employed for less creative industries that on the other hand need to reliably evolve large, stable code-bases.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;And of course, different industries have completely different cultures, requirements, expectations, constraints.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;You can use goto(s).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;i&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Corollary: Understand your self-defenses.&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Cosmic horror. When overwhelmed with complexity our minds tend to raise shields. Most often these come in two varieties, depending on if you're in your fascination phase or in your grumpy one.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Hype: In the former case, we tend to mindlessly follow others, ideas spread through hype and are embraced even when they are not appropriate in a given context. Eventually, we get burned by these, most of us learn our lessons and technology goes from hype to well-understood tool.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Hate: This is the latter case, where on the other hand we harden around what we already know, the trusty tools and ideas we can rely upon, and see new ideas in an overly negative way.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Most times, this makes us actually effective, because most new ideas have high failure rates (research and innovation is defined by the high possibility of failure). Always predicting that something new will fail is a good bet. But this efficiency and resilience to variance comes with the risk of being blind to the next big thing.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;When the next big thing becomes obvious to all, it's usually too late to embrace it (the innovator's dilemma).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Note how both behaviors have virtuous traits. Hype helps new ideas to spread, and it's probably even necessary as we biased towards not wanting to move from our comfort zone, thus if we relied on perfect rationality for good new ideas to take their place in our collective tool belt, we would probably fail. And hate, as I wrote already, does indeed work most of the time, and makes people more effective at the job they do.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;We have to understand, at a meta-level, that collectively these waves of hype and hate are there for a reason. Human behavior exists for a reason, and it is mostly there to serve us.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;But if we understand this, then we can also be grounded and present to ourselves and understand when these behaviors do not serve us well. We should try to learn everything and idolize nothing. Know our history without becoming bound to it. Be curious without fully embracing something just because everyone else seems to be doing the same...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;i&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Corollary: Be skeptical of theories without context.&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Only math is absolute. Any other science deals with primitives that we haven't invented (a.k.a. reality), thus, we can only hope to create models (theories) that are useful (predictive) in specific contexts (under given assumptions). Absolute statements are almost always propaganda, over-simplifications. We tend to like them because they are, well, simpler, and simplicity is attractive in an overly complex world. But unfortunately, they also tend to be wrong.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;If a theory doesn't identify the conditions under which it applies, and the conditions under which it does not, then chances are it's not a good one. This applies even more broadly, to innovations, papers, algorithms, ideas in general.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Meta-Rule 2: Our minds are (usually) the scarcest resource, we should optimize for them.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? — Brian Kernighan, The Elements of Programming Style&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Again, it's unfortunate that we tend to take all these mantras as absolutes, we like to quote them, smart, famous people can't be wrong, right?&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;"Premature optimization is the root of all evil" amIrite?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Stop taking shortcuts to enlightenment. We need to actually think. To me, the famous quotes above is not really a call to not write clever code - we definitely do need to be clever, even often and often early on.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;But the perils both Knuth and Kernighan (among many others) were trying to communicate are the ones that come with our tendency as passionate engineers to think too much about the machine.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;And yes, I say that as someone who has few skills, but one of these few is a decent knowledge of modern hardware and how to exploit it. See. I didn't say that we should not think about the machine, we should. But the peril is to become persuaded that squeezing cycles or in other ways making the machine happy is the pinnacle of programming. The key part of what I wrote is "caring too much".&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;People (and products) are harder than hardware. Probably have always been, but it's especially true today with a stable industry and the commoditization of programming, where most software has hundreds of people behind and it's unlikely for new clever algorithms and implementations to be the key of the success of a product.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;i&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Corollary: Be as simple as possible.&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Or, do not overcomplicate. Do not overengineer. As simple as possible might very well mean not simple at all, but we should fight needless complexity as our worst enemy.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Complexity is also very tricky to define, and that's why someone's overengineering might be someone else beautifully minimal code. Say, for example, that I need to do some numerical optimization in a C++ program. I can probably write my own small optimizer in say a thousand lines of code, from scratch. Maybe Nelder-Mead or Differential Evolution.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Or I could link Eigen to give me basic vector math and reduce my code to a hundred lines. Or, I could link an external optimization library and pick a ready-made algorithm with a single function call. Heck, I could even do a call into a Mathematica kernel that can do some fancy auto-selection of a good algorithm to use.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;What is "simpler"? If you are a C++ programmer, you'll probably say one of the first two options. What if I said I'm doing this in Python? In that case, I'm pretty sure we would choose the latter ones! Why? Is it just because the library/module support in Python is better? I doubt it.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Complexity is contextual. It's not about the lines of code we write or the lines of code we depend on. It's about a window of concepts we care about. Our brain is limited and looks smarter than it is mostly because it aggressively focuses on certain things while ignoring others. We're perpetually blind.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;I think that this translates to coding as well. Like it or not, we can work only within a limited window. C/C++ programmers tend to be system-level programmers, and these are tools used when we need to focus our window on performance and memory. In this context, oftentimes writing relatively small amounts of code from scratch, with no dependencies, is easier than depending on lots of unknown "magical" code, because of attention is on a given level of execution and exactly what code we execute usually matters.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;On the other hand, if I'm working in Python or Mathematica I actually like to think I am blessed by not having to look at the lower levels of code execution. That is not where the window is, typically. Scripting is great to sketch and explore ideas, the minutiae of execution don't matter in this "prototyping" mode, they would actually be distractions. We don't really want to write Python code thinking how the interpreter is going to execute it.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Usually, every tool is good in a given context (tradeoffs), the context dictates what matters and what we can and should ignore, and when we talk about complexity we should think specifically of how conceptually simple the components we care about are.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;This also yields another corollary. If we chose the right tool, a good default is to be idiomatic. It's usually wrong to try to "bend" a tool that is made for a given thing to go way out of its comfort zone. It usually ends up in not very well hidden complexity (because we need to interface two different worlds) and also a loss of familiarity (others can't tell how things work, it's not obvious from the local context).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;While we shouldn't fear to go outside the familiar, we shouldn't do it if it's not necessary.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;i&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Corollary: Constraints are useful.&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;If it's true that our brain is limited to a given window, explicitly controlling said window by imposing constraints must be a useful tool.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;This shouldn't be shocking, programming is creativity, and creativity does thrive under constraints. The paradox of choice that Barry Schwartz describes applies very much to programming as well. Writer's block.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;I don't want to write much about this because I intend to write much more, and dedicate a future post to constraints in programming. I think that other than taking control, designing explicitly the window at which we operate for a given program, they can be useful when imposed artificially as well.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Over-constraining can help us focus on what matters for a given task, especially for people (like me) who tend to be "completionists" in programming - not happy if we don't know we did the "best" possible implementation. Here, adding constraints is a useful hack as we can re-define "best" to narrow the scope of a task.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/TBOseGUD4kc" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/749078204889622806/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=749078204889622806" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/749078204889622806" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/749078204889622806" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/TBOseGUD4kc/the-grown-up-programmers-metamanifesto.html" title="The grown-up programmer's (meta)manifesto" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2020/01/the-grown-up-programmers-metamanifesto.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-9120487219053111913</id><published>2019-12-01T19:11:00.002-08:00</published><updated>2019-12-02T21:17:28.547-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Rants" /><title type="text">Is true hacking dead? What we lost.</title><content type="html">&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I don't know how consciously or not, but now that I moved to San Mateo, I found myself listening to many audiobooks about the history of computing, videogames and the Silicon Valley, from the Jobs biography to the "classic" Hackers by Steven Levy, from "Console Wars" to "Bad Blood".&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;All of these I've been enjoying, even if some need to be taken with more of a grain of salt than others, and from most I've gained one or two interesting perspectives.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Hackers, in particular, struck some chords that are dear to me. Besides the history and the various personalities, some of which I didn't know of, one thing resonated: the hands-on, pragmatic, a-political nature of early hacking.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And no, before we keep going, I don't mean that we should not be political in our actions, today.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We are social animals and we should care about society and politics, in fact, it would seem to me that the only reason, at least if one is to take the book at its word, why early hacking was a-political is because hackers were fairly despicable a-social people.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But, it is interesting, because one could make the case that nowadays we live in a world where ideologies trump pragmatic realities, and perhaps we should understand why and take a step back.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What did hackers want? Access to computing. Computers were fascinating, mesmerizing and scarce. It wasn't a matter of software licenses, nobody cared about pieces of paper (or locked doors even), we wanted to be able to touch and tinker with the machine.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And everything was made to be tinker friendly in a golden age of computer hackerism, were kids like me could put sprites on a home television set by reading the c64 manual and playing with basic.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Nobody cared that the machine was not opensource, that the basic interpreter was licensed from Microsoft.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It was truly a huge movement, if we think about it for a second, even its tools were all about immediacy, graphics as a mean of direct feedback, live-coding.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We had one megahertz CPUs (in my times) working with size (not speed!) optimized interpreters.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Even at the ideological level, the goal was for everyone to have access, with systems like Lisp and even more clearly Smalltalk which were designed explicitly with the idea that the user was a tinkerer, always able to stop the world, inspect the inner workings, make some changes, and keep going.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We almost didn't have graphics, but it was in a way the golden age of graphics because people were mesmerized by the possibilities, especially excited about having immediate feedback loops, direct manipulation, fast iteration.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-XihZKqg3Z3Y/XeR7_-4sRHI/AAAAAAAAB5c/mG4HHeA09y4dYPBo2H7WZpBhOciQZY1XgCLcBGAsYHQ/s1600/hqdefault.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="360" data-original-width="480" height="240" src="https://1.bp.blogspot.com/-XihZKqg3Z3Y/XeR7_-4sRHI/AAAAAAAAB5c/mG4HHeA09y4dYPBo2H7WZpBhOciQZY1XgCLcBGAsYHQ/s320/hqdefault.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Sketchpad (Sutherland), which is mentioned in Alan Kay's&lt;br /&gt;&lt;a href="http://worrydream.com/EarlyHistoryOfSmalltalk/"&gt;"The Early History of Smalltalk"&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We lost all of this, basically all. We live in a time where it's impossible not to interface with a computer, computing is cheap and immensely powerful, yet it's nearly impossible to understand and contribute to it.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It is particularly interesting how we used to have the holy grail of live-coding on computers that shouldn't have been able to afford it, while today even the newest, fanciest languages focus primarily in being able to gobble up millions of lines of code in various modules while making iteration increasingly inefficient.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Not having direct access, the ability to stop the machine, list the code, modify and resume, was almost unthinkable. Not having an easily accessible programming language on your machine was unthinkable.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Today what was once a given, sounds in most contexts like science fiction. QBasic is in many ways still an environment that can teach people many lessons...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And again, what I find especially remarkable is that we had so much abstraction and immediacy on machines that shouldn't have been able to afford it. The 80ies were a sort of golden era for interpreters and VMs.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We went the IBM way, and we probably didn't realize it. All that we do today is built for structured teams of thousands of engineers. We prioritize big batch development over individual productivity.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;That's probably why we still have textual source (great for git and merging) over more expressive formats or even the old idea of serializing the entire state of a VM (again lisp, smalltalk) which sacrifices merging entirely to make hotpatching (dynamic software updates) trivial.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-fmdzlPCK2Ls/XeR8sS2y-mI/AAAAAAAAB5k/C3GyBFQrQI0SVg5MBAxk4XFGhSgZjlz_QCLcBGAsYHQ/s1600/ed8.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="783" data-original-width="964" height="259" src="https://1.bp.blogspot.com/-fmdzlPCK2Ls/XeR8sS2y-mI/AAAAAAAAB5k/C3GyBFQrQI0SVg5MBAxk4XFGhSgZjlz_QCLcBGAsYHQ/s320/ed8.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;The sad and inspiring story of &lt;a href="http://www.codersnotes.com/notes/a-constructive-look-at-templeos/"&gt;TempleOS&lt;/a&gt;,&lt;br /&gt;a.k.a. what the Raspberry Pi should have been.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now, to a degree this is entirely reasonable, when something becomes commoditized it's just another thing to be used, it loses its appeal.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We buy cars and go to mechanics, right? We don't know how to peek inside the engines anymore...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But what is striking to me is how that ideology is completely lost as well, replaced with one that prioritizes theoretical freedoms over actual ones.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We replaced the Commodore 64, which was entirely closed, proprietary yet hackable, with a linux-based monstrosity like the Raspberry-Pi, which is mostly opensource from what I understand (on the software side of things), yet might as well just be booting Windows and the vast majority of its uses would remain identical.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It's a cheap and fun toy for programmers, sure, but it mostly (entirely?) fails at making computation more accessible, which was its original goal.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In general, it feels like hacking is today dogmatic instead of pragmatic. Surely if everything was open-source... or distributed... or blockchain-based, immutable and lock-free with a pinch of functional programming... written this or this other way, then we would have a better, enlightened&amp;nbsp;society.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And it's not a joke, it's not an entirely a fringe phenomenon, there are vast arrays of engineers that are honestly invested in trying to change the world, but honestly think that solutions are to be found in the technical infrastructure of things. &lt;a href="https://breakermag.com/heres-the-dark-enlightenment-explainer-you-never-wanted/"&gt;&lt;span style="font-size: xx-small;"&gt;(by the way - wanna see something weird?)&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Perhaps we didn't truly graduate from our a-social tendencies, perhaps we're true to form in thinking that the machine and technology are more interesting than people, and groups, and culture...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Whatever the causes, we have software and hardware systems that strive to be entirely open, yet time and again are closed ones that are more accessible in practice, that really drive social revolutions.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Linux didn't change the desktop, nor the way software is made.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Look at my industry. Videogames.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What did make games tinkerable?&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Liberated individual creativity, art, even the ability to make a living?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Steam, the Apple app store, Microsoft XBLIG, Youtube, Twitch, Spotify, Patreon... Unity, Pico8, Dreams passing through Minecraft and Roblox and the game modding community... Not the blockchain, not linux or torrents and so on.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Even the Demoscene, one of the last bastions of true hackerism, is completely uninterested in the ideology of software licenses and contracts.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-dLrBm56ZG5Y/XeSJSLCTKUI/AAAAAAAAB5w/eBQWZ4KxGSU9pBclIY1wVRk6x-vW1SURQCLcBGAsYHQ/s1600/maxresdefault.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="720" data-original-width="1280" height="180" src="https://1.bp.blogspot.com/-dLrBm56ZG5Y/XeSJSLCTKUI/AAAAAAAAB5w/eBQWZ4KxGSU9pBclIY1wVRk6x-vW1SURQCLcBGAsYHQ/s320/maxresdefault.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Joseph White - &lt;a href="https://www.youtube.com/watch?v=87jfTIWosBw"&gt;Pico-8&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And ironically, probably by utter coincidence, but ironically indeed, all the new power brokers of this era, the Facebooks and Amazons, the Googles and Twitters and so on, fully embrace opensource stacks, hundreds of millions lines of codes powering the AIs, the networks of today.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The new IBMs do know very well that lines of code are for the most part worthless, but people and communities aren't, so it's a no brainer to opensource more if in change one gets more people involved in a project, and more engineers hired...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In the end, probably licenses don't mean much. And perhaps technology doesn't either. How we design our human-computer (and human-to-human) interfaces does. And if we don't start thinking about people and think that some lines of code or a contract can change the world, we'll be stuck in not understanding why we keep failing.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;See also: This inspiring keynote by Andy Van Dam &lt;a href="http://i3dsymposium.github.io/2019/keynotes/I3D2019_keynote_AndyVanDam.pdf"&gt;"Reflections on Unfinished Revolutions in Personal Computing"&lt;/a&gt;, and the work of &lt;a href="http://worrydream.com/#!/TheFutureOfProgramming"&gt;Brett Victor&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/KnMfrQZxuOs" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/9120487219053111913/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=9120487219053111913" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/9120487219053111913" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/9120487219053111913" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/KnMfrQZxuOs/is-true-hacking-dead-what-we-lost.html" title="Is true hacking dead? What we lost." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-XihZKqg3Z3Y/XeR7_-4sRHI/AAAAAAAAB5c/mG4HHeA09y4dYPBo2H7WZpBhOciQZY1XgCLcBGAsYHQ/s72-c/hqdefault.jpg" height="72" width="72" /><thr:total>13</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/12/is-true-hacking-dead-what-we-lost.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-224411329764712928</id><published>2019-08-29T14:45:00.001-07:00</published><updated>2019-09-04T16:27:04.434-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="The industry" /><title type="text">Engineering Career Guide [LEAKED]</title><content type="html">&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Q: How do I progress in my career as a (rendering) engineer?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;A: &lt;a href="https://www.dropbox.com/s/0z2p0qokdmm6eaw/Roblox%20Rendering%20-%20Career%20Guide%20v1.1public.pdf?dl=0"&gt;Start from here&lt;/a&gt;. &amp;lt;== DOWNLOAD LINK&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I hope this helps. It's not comprehensive and I did remove some bits that are specific to us (they shouldn't matter anyways), it's meant to be a starting point for discussions.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I could have written a separate blog post but in the end it would have been a rehash of the same ideas so I just decided to spill some beans...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-RSkGpG9z4mo/XWhHcahEOYI/AAAAAAAAB3I/79f8ugfCa5MZ_pA8GVVBDSHGroFc-4KMQCLcBGAs/s1600/Screen%2BShot%2B2019-08-29%2Bat%2B2.44.56%2BPM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="472" data-original-width="404" height="320" src="https://1.bp.blogspot.com/-RSkGpG9z4mo/XWhHcahEOYI/AAAAAAAAB3I/79f8ugfCa5MZ_pA8GVVBDSHGroFc-4KMQCLcBGAs/s320/Screen%2BShot%2B2019-08-29%2Bat%2B2.44.56%2BPM.png" width="273" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Not the download link! Just a Roblox monster.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/CHOzie_LJ3o" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/224411329764712928/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=224411329764712928" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/224411329764712928" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/224411329764712928" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/CHOzie_LJ3o/engineering-career-guide-leaked.html" title="Engineering Career Guide [LEAKED]" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-RSkGpG9z4mo/XWhHcahEOYI/AAAAAAAAB3I/79f8ugfCa5MZ_pA8GVVBDSHGroFc-4KMQCLcBGAs/s72-c/Screen%2BShot%2B2019-08-29%2Bat%2B2.44.56%2BPM.png" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/08/engineering-career-guide-leaked.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-2325675273021601247</id><published>2019-08-24T22:23:00.000-07:00</published><updated>2019-08-25T22:52:35.152-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Stupid rendering tricks" /><title type="text">Misunderstanding Multilayering (Diffuse-Specular Energy Conservation)</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Introduction to the problem&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In our last episode, &lt;a href="http://c0de517e.blogspot.com/2019/08/misunderstanding-multiscattering.html"&gt;"misunderstanding multiscattering"&lt;/a&gt;, we saw how to create a multiscattering BRDF mostly by intuition. We used the concept of directional albedo (a.k.a. directional-hemispherical reflectance) to normalize a specular BRDF and from there we derived a very simple closed-form approximation for GGX energy conservation.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We also showed that the directional albedo is the response of our BRDF in a white light furnace at different normal to view angles, and we typically have that information available in tabular form as it's a key component of the "split sum" approximation to the integrals needed for image-based lighting on contemporary BRDFs. Great!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This time, we'll show how the very same data, ideas, and intuitions, can be used to build multilayered BRDFs, and in particular to couple matte-specular models (diffuse lobes to specular lobes).&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Like the previous article, this is not anything particularly novel, this isn't Siggraph worthy material, just some notes on the subject.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Let's start, as always, with the problem, with a very quick recap of things everyone reading this will probably already know (my flight has been delayed a couple of hours, so yes, we have time for recaps).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Under the framework of geometrical optics we look for light interactions with materials at surfaces where the index of refraction changes. We assume that light travels in a medium of uniform IOR (e.g. air), and then eventually hits a surface with a different IOR and either gets reflected out of the surface, or refracted into it.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif; font-size: xx-small;"&gt;In fact in real-time rendering we only consider the air-&amp;gt;material interface, we don't handle nested objects (e.g. air-&amp;gt;glass-&amp;gt;water-&amp;gt;glass-&amp;gt;air) even when we render transparent materials or multilayered materials. Which is wrong, but it's just &lt;a href="http://c0de517e.blogspot.com/2019/05/seeing-whole-physically-based-picture.html"&gt;one of the many ways we are still totally wrong&lt;/a&gt; (and yet might or might not be right by not caring). Even for offline path-tracers, this is not entirely trivial, depending on how you do light transport.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We then consider, for a small but not infinitesimal patch of our surface, the statistics of how probable are these reflections and refraction in function of the light incident angle, a given outgoing angle we want to measure, and the surface patch normal, and these statistics create a BRDF "lobe".&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But BRDFs though don't typically have a single lobe: we usually have "metals" and "dielectrics" and in the latter case we have a specular and a diffuse lobe. How comes? Well, because we don't really consider a single interaction, that was sort-of a lie. We do create a lobe with the light that is scattered from the surface interaction, but we also have to consider the light that gets refracted into the surface. In the case of metals, the energy that goes into the material somehow disappears (becomes heat or maybe fairy dust who knows - physics) and we effectively have a single lobe.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;For dielectrics, though the refracted light keeps hitting molecules inside what's essentially a participating medium, and eventually taking random paths it comes back out from the surface and we model that as a diffuse lobe.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Diffuse lobes are reasonable when the "bouncing around" is such that it effectively randomizes the direction at which the light comes out, but still happens in such a small space that we consider the light coming out effectively at the same point it came in.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If that's not true, and the scattering distances are bigger, we have what we call "subsurface scattering" effects. If the direction is not randomized "enough", then instead we have transparent materials, and somewhere in the middle, we have what we usually address as participating media.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Any time that we consider multi-layered materials we have to model the way the light that is refracted by a layer reaches the next. At the very least, we have to know at least how much energy is "handled" by a given layer/lobe and how much is "passed down" to the subsequent lobes, as if we gave the same input light to all the layers we would sum the interactions up and potentially end up with more energy coming out of a material than it came in!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In theory we should understand much more than that, namely how the light travels in a given layer and reaches another one (its statistical distribution over directions and space), but for diffuse lobes found in dielectrics we can imagine that it doesn't matter much (anyways the light is going to be randomized...), so right now we just want to know how much energy survives the topmost specular lobe of a dielectric (gets refracted as opposed to reflected).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This might seem a lot of handwaving. And it is! This is the point of this post -and- the previous one!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We know that we have certain problems in our math, but should we care? How much should we care and why? Does it matter for the goal of generating photorealistic images easily? Remember, this is our goal, not fixing physics. Then again if we wanted to look at the physics there are &lt;a href="http://c0de517e.blogspot.com/2019/05/seeing-whole-physically-based-picture.html"&gt;a ton of assumptions that we are making anyways&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-jWOUYv7Ur3w/XWIU4peGdWI/AAAAAAAAB1I/NhVKw5y_wx0nGlzsG-fnszWkYBmhLfSLwCLcBGAs/s1600/9_bonus_spec_specdiff_specdiffF.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="512" data-original-width="1600" height="201" src="https://1.bp.blogspot.com/-jWOUYv7Ur3w/XWIU4peGdWI/AAAAAAAAB1I/NhVKw5y_wx0nGlzsG-fnszWkYBmhLfSLwCLcBGAs/s640/9_bonus_spec_specdiff_specdiffF.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Left to right: Specular only, Specular+Diffuse, Specular+Diffuse*(1-Fresnel)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It turns out that this problem matters a lot, much more in fact than the energy loss in non-multiscattering specular lobes. The multiscattering issue was small, happened only at high roughnesses and it was entirely fixable by artists tweaking specular albedo (typically controlled by Fresnel f0 parameter) a bit.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Tweaking albedo is fine because it still keeps the materials decoupled from lighting, the main issue we wanted to fix by embracing physically-based rendering models, and it's doable because the tweaks needed are small and entirely in the range of realistic albedos (which don't ever go to f0 = 1 for metals, and of course even less so for dielectrics).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Not having any energy conservation between specular and diffuse instead creates overly bright materials that can look fine in a certain scene but will glow unnaturally under different conditions, and it's quite hard for artists to make sure that the lobes are tuned in a way that doesn't produce more energy than they should.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In fact, most real-time rendering today works without multiscattering BRDFs, but (hopefully) it always considers some way of balancing specular and diffuse.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Solutions and pretty images&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now we know the problem -and- we know it matters, so we are justified in spending some time to investigate further. How? Well, as we did with the previous post, we bring back our friend the white furnace test. Pretty much any time we want to check for energy conservation, we take our materials and put them in a furnace!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-5Seewc4JIHs/XWIVYLsxIBI/AAAAAAAAB1Q/Ccb4q-t8FlUrnNVrCu0WxpLJirOBstN2ACLcBGAs/s1600/9b_furnace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="512" data-original-width="1600" height="203" src="https://1.bp.blogspot.com/-5Seewc4JIHs/XWIVYLsxIBI/AAAAAAAAB1Q/Ccb4q-t8FlUrnNVrCu0WxpLJirOBstN2ACLcBGAs/s640/9b_furnace.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;As for the previous time though, just putting a material in a furnace doesn't tell us that much. Yes, it's already apparent how the middle image looks unnaturally bright, but that's not a great test. What we want is to setup our scene so we expect the material to reflect back exactly all the light that comes in, no matter which path the light takes in the material and across the microfacets, and then see if we get more light than we expect or less.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We have to think, what is that is absorbing light in our materials? The specular reflects light out or refracts it in, it doesn't absorb, so all the energy loss is when we go "inside" the material, in the dielectrics case, in the diffuse layer. It stands to reason then that if we set our diffuse albedo to one, regardless of the specular parameters, we should be perfectly white in a white furnace. Let's see:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-EhWMFMpejEc/XWIVe76SdrI/AAAAAAAAB1U/UsVJFfkcBTwEGAFKLf2LLpGxQ2b414y1gCLcBGAs/s1600/9c_whitediffuse_specdiff_specdiffF_and_furnace.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="384" data-original-width="1600" height="152" src="https://1.bp.blogspot.com/-EhWMFMpejEc/XWIVe76SdrI/AAAAAAAAB1U/UsVJFfkcBTwEGAFKLf2LLpGxQ2b414y1gCLcBGAs/s640/9c_whitediffuse_specdiff_specdiffF_and_furnace.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Comparing no energy conservation to (1-Fresnel) with a fully white diffuse albedo.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Bingo! We see now that just adding diffuse with no attempt at energy conservation does indeed result in energy being created. And surprisingly it looks like that the simple idea of using (1-F) as a multiplication factor to normalize diffuse is indeed doing a very good job, in fact, it looks alright if it wasn't for the grazing angles... Why is that?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-iaU0vhsNrUE/XWIVyIDZ42I/AAAAAAAAB1g/OhuB9Ulhik0TJsRH-MCJIcSYU9pIB1PqgCLcBGAs/s1600/15_fresnel_furnace.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="175" data-original-width="1600" height="70" src="https://1.bp.blogspot.com/-iaU0vhsNrUE/XWIVyIDZ42I/AAAAAAAAB1g/OhuB9Ulhik0TJsRH-MCJIcSYU9pIB1PqgCLcBGAs/s640/15_fresnel_furnace.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;(1-Fresnel) at varying roughness (from 0.1 to 0.9)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-uB7q_7wU9_A/XWIV_FePkmI/AAAAAAAAB1k/wOaljK3RP3I1gfZVDvJmt9WC6_NxU22qwCLcBGAs/s1600/15_without_MSS.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="175" data-original-width="1600" height="70" src="https://1.bp.blogspot.com/-uB7q_7wU9_A/XWIV_FePkmI/AAAAAAAAB1k/wOaljK3RP3I1gfZVDvJmt9WC6_NxU22qwCLcBGAs/s640/15_without_MSS.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Same as above, but using a non-multiscattering Specular instead of the simple one presented in the last post.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Well if we think about it, it's fairly obvious. For the terms we commonly use, at the incident angle (N=V=L) the shadowing term has no effect and the NDF takes a constant value regardless of the roughness parameter, Fresnel dominates. At grazing angles, the shadowing term starts to matter, and there is where we see our simple normalization breaking down.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What we can try to fix this? If you read the previous post, it should be obvious by now. We have something that should be white in a furnace, it isn't, let's make it! We know how much energy the specular lobe will scatter back in the furnace, for any roughness, Fresnel f0, and viewing angle, this again is the split-sum table we use for environment map lighting. We know that a Lambert diffuse is correctly normalized, so it will scatter back all incoming energy if the albedo is set to one. So how much do we have to scale the lobe for the sum of the specular plus diffuse to be one, with an arbitrary specular and a unitary albedo diffuse? Obviously just by 1-E, where E is what we get from the split-sum table!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-7RjaWoY_DAg/XWIWQI8q2SI/AAAAAAAAB1o/onYtWR2tZcQc-19d35P_9LlSXJ4h9W-9ACLcBGAs/s1600/10_simpleEC.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="526" data-original-width="1096" height="191" src="https://1.bp.blogspot.com/-7RjaWoY_DAg/XWIWQI8q2SI/AAAAAAAAB1o/onYtWR2tZcQc-19d35P_9LlSXJ4h9W-9ACLcBGAs/s400/10_simpleEC.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;(1-E) energy conservation test, notice the more correct grazing angles.&lt;br /&gt;Note: some artifacts remain due to approximations in the Directional Albedo table I used.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Furnace fixed! And note, this works regardless of if we're using or not the multiscattering specular BRDF, as a non-multiscattering one will just behave as it's refracting more light to the diffuse layer, which in our case will still bounce it all back out. And, if we're using the simple renormalization for multiscattering presented in the previous post, we don't even need to compute a new table for directional albedo, as it's easy to derive how to analytically modify the output of the single scattering table to accommodate for the multiscattering correction (I'll leave this as an exercise for the reader, it's trivial and might motivate you to actually look at the definition of directional albedo...)&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;As it was for the multiscattering normalization idea, this is wrong and we can see immediately that it's wrong from the equation, even if the error won't show in the furnace, because we don't respect reciprocity (we consider only ndotv and not ndotl). It's even intuitive, as we don't seem to consider at all that the light going from the specular layer to the diffuse, scattering inside the material and eventually coming out, has to cross again the specular interface as it comes out!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Before we delve further into this, I want though to stop for a second and check out what we are doing (again, same as last time). Let's plot the 1-E multiplicative factor we're applying to diffuse and see what happens:&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-iVXHr38HG5M/XWIWvgv6xZI/AAAAAAAAB10/M3T6oyuKa8Y9HRaidP5BnZLM5lTBj7nqgCLcBGAs/s1600/10_NVfresnelECvsSimpleEC_noMS.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="1052" data-original-width="1600" height="210" src="https://1.bp.blogspot.com/-iVXHr38HG5M/XWIWvgv6xZI/AAAAAAAAB10/M3T6oyuKa8Y9HRaidP5BnZLM5lTBj7nqgCLcBGAs/s320/10_NVfresnelECvsSimpleEC_noMS.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;(1-E) normalization compared to (1-Fresnel) at varying roughness,&lt;br /&gt;for a non-multiscattering specular.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-scGoCeXkKzw/XWIWzvJwElI/AAAAAAAAB14/rlhs30zQuBgNwq5QLTQDZDP0hYTvftCIQCLcBGAs/s1600/10_NVfresnelECvsSimpleMS_EC.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="1040" data-original-width="1600" height="207" src="https://1.bp.blogspot.com/-scGoCeXkKzw/XWIWzvJwElI/AAAAAAAAB14/rlhs30zQuBgNwq5QLTQDZDP0hYTvftCIQCLcBGAs/s320/10_NVfresnelECvsSimpleMS_EC.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;br /&gt;Same as above, but using simple multiscattering specular.&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is interesting! Albeit we can couple diffuse with and without a multiscattering specular, the plots for the multiscattering case are much simpler, so much so that it's easy to derive, by hand, a function that would approximate them. Fun!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-hkZKdOr2teo/XWIXIkrBO2I/AAAAAAAAB2E/fvxK91436AQM1FzqI0X116VrKESt-qR2QCLcBGAs/s1600/11_approx_for_simpleECspecMSS.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="442" data-original-width="884" height="160" src="https://1.bp.blogspot.com/-hkZKdOr2teo/XWIXIkrBO2I/AAAAAAAAB2E/fvxK91436AQM1FzqI0X116VrKESt-qR2QCLcBGAs/s320/11_approx_for_simpleECspecMSS.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Approximation: mix( (vec3(1,1,1) - fresnel(f0,ndotv) ), vec3(1) - f0, roughness )&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And now, at last, let's have a look at a more correct solution that respects reciprocity and see if that matters or not for real-time rendering. This is quite hard to know intuitively, so we'll have just to implement something and check.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Luckily this is nothing new, in 2001 Kelemen and&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;László Szirmay-Kalos published "&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;A Microfacet Based Coupled Specular-Matte BRDF Model with Importance Sampling", and we can pretty much copy and paste their equation, which unsurprisingly ends up looking very close to the way we adjust for reciprocity in specular multiscattering (in fact Kulla and Conty cite the afore mentioned KSK paper in theirs).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Without further ado:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-90urHNSmqFI/XWIY5kEYq1I/AAAAAAAAB2Q/b5sP40xYLC4Y1ZrrenPJdF6_1HJbuFT6wCLcBGAs/s1600/12_rough01MSS_ecSimple_ecFresnel_ecProper.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="570" data-original-width="1600" height="114" src="https://1.bp.blogspot.com/-90urHNSmqFI/XWIY5kEYq1I/AAAAAAAAB2Q/b5sP40xYLC4Y1ZrrenPJdF6_1HJbuFT6wCLcBGAs/s320/12_rough01MSS_ecSimple_ecFresnel_ecProper.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Left to right: Simple EC, Fresnel EC, KSK EC.&lt;br /&gt;Simple Multiscattering GGX, Roughness 0.1.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-nnU0b3dTmR4/XWIZAUcT4QI/AAAAAAAAB2U/uKCzpZSVDjg_Aq0_KEoPQ_fa5_e9k7JVQCLcBGAs/s1600/13_rough03MSS_ecSimple_ecFresnel_ecProper.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="570" data-original-width="1600" height="114" src="https://1.bp.blogspot.com/-nnU0b3dTmR4/XWIZAUcT4QI/AAAAAAAAB2U/uKCzpZSVDjg_Aq0_KEoPQ_fa5_e9k7JVQCLcBGAs/s320/13_rough03MSS_ecSimple_ecFresnel_ecProper.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Same as above but for 0.3 roughness GGX.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div&gt;&lt;span style="font-family: arial, helvetica, sans-serif; text-align: justify;"&gt;And some more images. The difference between (1-F) and (1-E) can be seen only at low roughness. Difference is even less pronounced for table-based (1-E), the approximation showed above and the full KSK method.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: arial, helvetica, sans-serif; text-align: justify;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-l3rFP-ybrgc/XWNykQ5UslI/AAAAAAAAB2k/tMfjn6hl8nw6RQWw6nFSlgg3qjy4jb2AQCLcBGAs/s1600/14c_fresnel.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="235" data-original-width="1600" height="92" src="https://1.bp.blogspot.com/-l3rFP-ybrgc/XWNykQ5UslI/AAAAAAAAB2k/tMfjn6hl8nw6RQWw6nFSlgg3qjy4jb2AQCLcBGAs/s640/14c_fresnel.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;1-Fresnel; Roughness 0.1 to 0.9, GGX with simple multiscattering.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-Jn9ifsU1cSc/XWNy07yVJ5I/AAAAAAAAB2s/3PL2DvZiwVcIJC7-QbL-zkFi6hH7j17wwCLcBGAs/s1600/14b_ecSimpleApprox.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="235" data-original-width="1600" height="92" src="https://1.bp.blogspot.com/-Jn9ifsU1cSc/XWNy07yVJ5I/AAAAAAAAB2s/3PL2DvZiwVcIJC7-QbL-zkFi6hH7j17wwCLcBGAs/s640/14b_ecSimpleApprox.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Approximated 1-E.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-6IT649OOG1o/XWNzIiUXwKI/AAAAAAAAB20/Df-JLYmojDYwsGPP1N5cCUReTPe7-xQ7wCEwYBhgL/s1600/14_r01_09_mss_ESsimple.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="235" data-original-width="1600" height="92" src="https://1.bp.blogspot.com/-6IT649OOG1o/XWNzIiUXwKI/AAAAAAAAB20/Df-JLYmojDYwsGPP1N5cCUReTPe7-xQ7wCEwYBhgL/s640/14_r01_09_mss_ESsimple.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Table based 1-E.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-iZP503NwqhU/XWNzcmcWGmI/AAAAAAAAB28/b-nm1pHYGaImG68YtFHWUN-KuUnL9LTIQCLcBGAs/s1600/14d_proper.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="235" data-original-width="1600" height="92" src="https://1.bp.blogspot.com/-iZP503NwqhU/XWNzcmcWGmI/AAAAAAAAB28/b-nm1pHYGaImG68YtFHWUN-KuUnL9LTIQCLcBGAs/s640/14d_proper.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;KSK.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;span style="font-family: arial, helvetica, sans-serif; text-align: justify;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/x16Iwwb31QM" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/2325675273021601247/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=2325675273021601247" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/2325675273021601247" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/2325675273021601247" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/x16Iwwb31QM/misunderstanding-multilayering-diffuse.html" title="Misunderstanding Multilayering (Diffuse-Specular Energy Conservation)" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-jWOUYv7Ur3w/XWIU4peGdWI/AAAAAAAAB1I/NhVKw5y_wx0nGlzsG-fnszWkYBmhLfSLwCLcBGAs/s72-c/9_bonus_spec_specdiff_specdiffF.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/08/misunderstanding-multilayering-diffuse.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-1817878392045313013</id><published>2019-08-12T12:45:00.001-07:00</published><updated>2019-08-13T10:42:17.800-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Stupid rendering tricks" /><title type="text">Misunderstanding Multiscattering</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Today we will build a state-of-the-art multiscattering GGX BRDF for physically-based rendering.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Already done you say? Yes, you're right, by people who understand maths and physics, that's cheating. We instead will try to do the same trying to learn as little as possible...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you want to do this the right way instead, these are some excellent articles:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;a href="https://blog.selfshadow.com/2018/05/13/multi-faceted-part-1/"&gt;Stephen Hill - "A Multifaceted Exploration"&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;a href="http://advances.realtimerendering.com/s2018/index.htm"&gt;Danny Chan "Material advances in Call of Duty: WWII"&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;a href="http://advances.realtimerendering.com/s2019/index.htm"&gt;McAuley "A journey through implementing Multiscattering BRDFs and Area Lights"&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, ready?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Let's start from your vanilla contemporary GGX with all the correlated-Smith fixings. The following sequence of images is generated with Disney's BRDF explorer environment lighting mode. They show a metallic GGX withy varying roughness, from 0.3 to 0.9, using the common parametrization alpha = roughness squared.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif; font-size: xx-small;"&gt;Note: please always indicate the parametrization you are using in your articles and presentations. There are so many variants out there. Here I use one of the most common ones, even if, for what is worth probably the best idea is alpha = roughess^4, which is more perceptually linear and also manages to be a great approximation for the one-over-square-root Blinn-Phong Gloss to GGX mapping many engines prefer.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-i2eJQCaTwgc/XVG-bp1ITTI/AAAAAAAABy8/a8zksxtLFMA9ltJlpnNnm5HL3-36cqJ5QCLcBGAs/s1600/0_GGX_rough_03_to_09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="52" src="https://1.bp.blogspot.com/-i2eJQCaTwgc/XVG-bp1ITTI/AAAAAAAABy8/a8zksxtLFMA9ltJlpnNnm5HL3-36cqJ5QCLcBGAs/s640/0_GGX_rough_03_to_09.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We can notice how at high roughness the material looks noticeably darker.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is annoying, and smart people have worked hard to find and fix this issue.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Let's compare the image above with &lt;/span&gt;&lt;a href="https://blog.selfshadow.com/publications/s2017-shading-course/" style="font-family: arial, helvetica, sans-serif;"&gt;Kulla/Conty's Multiscattering GGX BRDF&lt;/a&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-2vEW7a6AMmY/XVG-r3WF95I/AAAAAAAABzE/Jm0kPTaAemc2Nwm3MkQZWqw63bBEG4u-ACLcBGAs/s1600/1_GGX_Kulla.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-2vEW7a6AMmY/XVG-r3WF95I/AAAAAAAABzE/Jm0kPTaAemc2Nwm3MkQZWqw63bBEG4u-ACLcBGAs/s640/1_GGX_Kulla.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Fixed!&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now, we could try to understand how this solution work, the math is already there. And you probably should, it's both interesting and useful to understand other related problems. But, let's try not to...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;First of all, we should ask why is this a problem? How do we know it is a problem? And also, if it is a problem, how big of a problem it is?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Let's start at the top. Why do we like "PBR"? It's not because we like physics, at least, I don't... And if we did like physics, this would be a small error to focus on, considering that &lt;a href="http://c0de517e.blogspot.com/2019/05/seeing-whole-physically-based-picture.html"&gt;we are surely committing worse sins in our end-to-end image pipeline&lt;/a&gt;...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Computer graphics is not predictive rendering. We don't try to simulate physics to make accurate simulations, that's not a goal (and the people who care about physics are an order of magnitude ahead of us). We make pretty pictures.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;At a given point, we noticed that using some physics to make pretty pictures allowed for easier workflows, decoupling materials from lighting, reducing the number of hacks and parameters, allowing to use libraries of real materials and so on.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We thought artists would be happier and be able to work more efficiently, while still being able to create a lot of different scenes. It took a while to move over all our workflows, but it was the right call.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, when we look for right and wrong, we have to start with art and artists. If there is a need we can identify there, then we can look at physics to see if the answers are there. In this case, we can say that yes, indeed we have a (small) problem.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It would be nice if our material parameters were orthogonal, and having things go darker as we change roughness is not ideal.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Let's move to step two then. Can physics help? Is this darkening physically correct, or not? How do we test? Enter the furnace! Let's put our "GGX coated" metallic object in a uniformly lit environment and see what happens:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-29MCNpBsPi4/XVG-_Oz-SYI/AAAAAAAABzM/oLwhPh-P8NEh_NDsJtIn32gzMsRcY0I8wCLcBGAs/s1600/2_GGX_furnace_09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="408" data-original-width="670" height="121" src="https://1.bp.blogspot.com/-29MCNpBsPi4/XVG-_Oz-SYI/AAAAAAAABzM/oLwhPh-P8NEh_NDsJtIn32gzMsRcY0I8wCLcBGAs/s200/2_GGX_furnace_09.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Light hits our surface, hits our microfacets. The microfacets reflect back some light, and refract some other, according to Fresnel. If we're assuming a metal people told us that the refracted light, that goes "inside" the surface, is quickly absorbed and never comes out (becomes heat).&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It's reasonable that even in a furnace our metallic object has a color, as some of the energy will be absorbed. But what if we take our microfacets and make them always reflect all the light, no absorption?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This means we need to set our f0 to 1 (remember, Fresnel is what controls how much light the microfacets scatter), let's try that and see what happens:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-o_P6HOqO7Ko/XVG_I2woT4I/AAAAAAAABzQ/fNLaEB4wJBgZru4dFsYf-V_Hcc6S8IBtgCLcBGAs/s1600/2_GGX_furnace_f0_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-o_P6HOqO7Ko/XVG_I2woT4I/AAAAAAAABzQ/fNLaEB4wJBgZru4dFsYf-V_Hcc6S8IBtgCLcBGAs/s640/2_GGX_furnace_f0_1.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The object is still not white. Something's wrong! Ok, the inquisitive reader might still say - how do you know it's wrong. Perhaps certain directions scatter more light and others less, so we still see some shading even if all the light eventually comes out...&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If we think of BRDF and lobes it's not easy to get correct intuition. Let's instead think of how a light path, starting from the camera, looks like. It might hit some of the microfacets, one or many times, bounce around then eventually escape and connect to the furnace environment which will always be a emitting a given contant energy.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;How much of that energy reaches the camera? All of it! Because regardless of which and how many microfacets we hit, all the energy is reflected and none is absorbed.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now we have an intuition of why the image above should be white, it isn't, so we have a problem in our math...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you studied BRDFs you know that in microfacet model we have a masking-shadowing visibility function that models which microfacets are occluded by others. What we don't typically model though is the fact that these occlusions are themselves microfacets, so the light should bounce around and eventually get out, not just be discarded.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is what the multiscattering models model and fix, and indeed if we did put in a furnace Kulla and Conty's GGX that we have shown before, it would generate a boring and correct white image for a fully reflective material, regardless of its roughness.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Kulla's model is not trivial though, and in many cases is likely not worth using to fix such a relatively minor problem. So. Can we be more ignorant? What if we knew how much light our BRDF gives out in a furnace, for a given roughness and viewing angle (fixing then again f0 = 1)? Could we just take that value and normalize the BRDF with it?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Spoiler alert, we can. And not only we can but it's also trivial to do, because we already have this "furnace" value in most modern engines, in the look-up tables used for the popular split-sum image based lighting approximation.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-G1jiPtc1l7s/XVG_SQy2OHI/AAAAAAAABzY/jksaz6Hw-dg-udX7KRUSCPiJzbzdb0LLwCLcBGAs/s1600/3_norm_DFG_table.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="602" data-original-width="1466" height="131" src="https://1.bp.blogspot.com/-G1jiPtc1l7s/XVG_SQy2OHI/AAAAAAAABzY/jksaz6Hw-dg-udX7KRUSCPiJzbzdb0LLwCLcBGAs/s320/3_norm_DFG_table.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The split-sum table boils down the "BRDF in a furnace" (also known as directional albedo or directional-hemispherical reflectance) to a scale and bias (add) factor to be applied to the Fresnel f0 value.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In our case, we want to normalize considering f0=1 so all we do is to scale our BRDF lobe by one over bias(roughness,ndotv) + scale(roughness,ndotv). This is the result:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-5vfXHBcw9Rc/XVG_g_nSLgI/AAAAAAAABzg/TY6QH9ZDGqE0HT6eg19LfdjF-8vzSy2IQCLcBGAs/s1600/4_GGX_norm_no_F0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-5vfXHBcw9Rc/XVG_g_nSLgI/AAAAAAAABzg/TY6QH9ZDGqE0HT6eg19LfdjF-8vzSy2IQCLcBGAs/s640/4_GGX_norm_no_F0.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Indeed, we're getting some energy back at high roughness, and if we tested this in a furnace it would come up white, correctly, at f0 = 1. But it's also different from Kulla's, in particular, color is not quite as saturated in the rough materials. How comes? Well again, if you studied this problem already (cheater!) you know the answer.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Proper multiscattering adds saturation because as light hits more and more microfacets before escaping the surface, we pick up more color (raising a color to a power results in a more saturated color). But so how can this be physically wrong, but still correct in our test?&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Well, it's simple, really. By not simulating this extra saturation we are still energy conserving, but we changed the meaning of our BRDF parameters. The f0 "meaning" in our "ignorant" multiscattering BRDF is not the same as Kulla's, it results in a different albedo, but the BRDF itself is still energy conserving, it's just a different parametrization.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Most importantly, I'd argue it's a better parametrization! &lt;b&gt;Then again, remember our objectives. We don't do physics for physics' sake, we do it to help our production.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We wanted to make our parameters more orthogonal so that artists don't need to artificially "brighten" our BRDF at high roughness. If we went with the "more correct" solution (about that, &lt;a href="https://knarkowicz.wordpress.com/2019/08/11/comparing-microfacet-multiple-scattering-with-real-life-measurements/"&gt;this recent post by Narkowicz&lt;/a&gt; is a great read) we would add a different dependency, now roughness instead of darkening our materials it makes them more saturated, which would kind of defeat the purpose.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;You can imagine some scenarios where this might be desirable, but I'd say it's almost always wrong for our use-cases.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If we wanted to simulate the added saturation, there are a few easy ways. Again, going for the most "ignorant" (simple) we can just scale the BRDF by 1+f0*(1/(bias(roughness,ndotv) + scale(roughness,ndotv)) - 1), resulting in the following:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-_cWJ7wzWjDY/XVG_yobCojI/AAAAAAAABzs/D2vZzCG9RJIZtzfjwmZIsDRS1IfSQhgEACLcBGAs/s1600/3_GGX_normalization.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-_cWJ7wzWjDY/XVG_yobCojI/AAAAAAAABzs/D2vZzCG9RJIZtzfjwmZIsDRS1IfSQhgEACLcBGAs/s640/3_GGX_normalization.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now we are close to Kulla's solution. This is still not entirely correct if you wonder why Kulla's approximation is better, as it might not show in images, it's because ours doesn't respect reciprocity.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This might be important for Sony Imageworks, as certain offline path-tracing light transport algorithms do require it, but it's fairly irrelevant for us.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, so now that we have found an approximation we're happy with we can (and should) go a step further and see what we are really doing. Yes, we have a formula, but it depends on some look-up tables.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This isn't a big issue as we need these tables around for image-based lighting anyways, but it would be an extra texture fetch and in general it's always important to double-check our math, so let's visualize the 1/(bias(roughness,ndotv) + scale(roughness,ndotv)) function we're using:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-Ic5GLsNXDCs/XVG_6AEowZI/AAAAAAAABzw/BiI5Gb5KRcYKzWMUwcaik9E4aruo2CqygCLcBGAs/s1600/4_F0_1_table.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="666" data-original-width="842" height="158" src="https://1.bp.blogspot.com/-Ic5GLsNXDCs/XVG_6AEowZI/AAAAAAAABzw/BiI5Gb5KRcYKzWMUwcaik9E4aruo2CqygCLcBGAs/s200/4_F0_1_table.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It looks remarkably simple! Indeed, it's so simple it has a trivial approximation, you don't even need any sophisticated tool to find it so I'll just show it: &lt;b&gt;1 + 2*alpha*alpha * ndotv&lt;/b&gt;. This fits very well:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-0QNtwFAhflM/XVHAI3tRFmI/AAAAAAAABz4/2OOR73QJXMYDXUjGkP1uTwzdgLBGA9mtQCLcBGAs/s1600/6_approx.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="560" data-original-width="750" height="148" src="https://1.bp.blogspot.com/-0QNtwFAhflM/XVHAI3tRFmI/AAAAAAAABz4/2OOR73QJXMYDXUjGkP1uTwzdgLBGA9mtQCLcBGAs/s200/6_approx.png" width="200" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Approximation compared to the correct normalization factor (gray surface)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-z8_bIWx0kj8/XVHATqIUVII/AAAAAAAABz8/cNfp_QT16zQi97-NOPlM4ta0Od5iA4wsACLcBGAs/s1600/6_GGX_approx1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-z8_bIWx0kj8/XVHATqIUVII/AAAAAAAABz8/cNfp_QT16zQi97-NOPlM4ta0Od5iA4wsACLcBGAs/s640/6_GGX_approx1.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-Wuff8tAsjcE/XVL04ZAetII/AAAAAAAAB0w/-12ZOEQrJHg-TjkS8_beP7oEn02CgkWDwCLcBGAs/s1600/6b_furnace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-Wuff8tAsjcE/XVL04ZAetII/AAAAAAAAB0w/-12ZOEQrJHg-TjkS8_beP7oEn02CgkWDwCLcBGAs/s640/6b_furnace.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;You can see that there is a bit of error in the furnace test. We could improve by doing a proper polynomial fit - yes, it turns out "2" and "1" in the formula above are not exactly the best constants.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Actually defining "best" would be a problem all on its own, because doing a simple mean-square minimization on the normalization function doesn't really make a lot of sense (we should care about end visuals, perceptive measures, which angles matter more and so on), and I think we already spent too much time for such a small fix.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Moreover, the actual rendered images are really hard to distinguish from the table-based solution.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What is interesting is to see what could we achieve if we wanted to be even simpler, dropping the dependency from ndotv. It turns out in this case&amp;nbsp;&lt;b&gt;1 + alpha*alpha&lt;/b&gt; does the trick decently as well.&lt;/span&gt;&lt;br /&gt; &lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This means that we're just applying a multiplicative factor to our BRDF to brighten it at high roughness, which just makes a lot of sense.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This of course adds more error and it starts to show as the BRDF shape changes, we get more energy at grazing angles on rough surfaces, but it might just be good enough depending on your needs:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-xO4Y3LCxTUE/XVHA-TG1h6I/AAAAAAAAB0Q/Nx76QgOqtVsisKRrtD60quespqDFP2ruwCLcBGAs/s1600/7_GGX_approx2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-xO4Y3LCxTUE/XVHA-TG1h6I/AAAAAAAAB0Q/Nx76QgOqtVsisKRrtD60quespqDFP2ruwCLcBGAs/s640/7_GGX_approx2.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-bU2vO-3XZcY/XVHBWI645YI/AAAAAAAAB0Y/QlMLsaxdqWoOIalFbB7M0RPQ89VqfbJyQCLcBGAs/s1600/5b_avg_furnace.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="140" data-original-width="1600" height="54" src="https://1.bp.blogspot.com/-bU2vO-3XZcY/XVHBWI645YI/AAAAAAAAB0Y/QlMLsaxdqWoOIalFbB7M0RPQ89VqfbJyQCLcBGAs/s640/5b_avg_furnace.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Under-exposed to highlight that with the simpler approximation sometimes we lose light, sometimes we add.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/YPkgg8XpErk" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/1817878392045313013/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=1817878392045313013" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1817878392045313013" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1817878392045313013" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/YPkgg8XpErk/misunderstanding-multiscattering.html" title="Misunderstanding Multiscattering" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-i2eJQCaTwgc/XVG-bp1ITTI/AAAAAAAABy8/a8zksxtLFMA9ltJlpnNnm5HL3-36cqJ5QCLcBGAs/s72-c/0_GGX_rough_03_to_09.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/08/misunderstanding-multiscattering.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-5459551505822130965</id><published>2019-07-18T08:29:00.001-07:00</published><updated>2019-07-22T05:29:47.524-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="The industry" /><title type="text">What makes "10x" engineers. A complete hypothesis.</title><content type="html">&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This happened on Twitter recently:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-hW-q_CN-wvs/XTBustrDdBI/AAAAAAAAByE/wHDUVKfMq3oOksO96xHz6OKG-lPKSbYnACLcBGAs/s1600/Screen%2BShot%2B2019-07-18%2Bat%2B3.03.58%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="923" data-original-width="1146" height="257" src="https://1.bp.blogspot.com/-hW-q_CN-wvs/XTBustrDdBI/AAAAAAAAByE/wHDUVKfMq3oOksO96xHz6OKG-lPKSbYnACLcBGAs/s320/Screen%2BShot%2B2019-07-18%2Bat%2B3.03.58%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It's a long thread and I censored the author's name because it doesn't matter and I don't want to add to the hate that already naturally happens on any social media these days.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;To be honest, I'm still not entirely sure it's not just a parody, but I think it isn't. Regardless, it seemed a good excuse for a blog post.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: arial, helvetica, sans-serif;"&gt;Let's for a moment forget about how good or bad the term is. I don't particularly love discussions around words.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: arial, helvetica, sans-serif;"&gt;I've never used "10x" in my career and I don't find it particularly great (also because it's linked to a certain start-up culture that I don't particularly enjoy), but I don't really want to open that can of worms.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial, helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What's wrong with a description of a "10x" engineer like the one above?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I hope it's obvious but I'll spell it out. It tries to describe an engineer not in terms of the work they do, the actual output and results, but in some kind of mystical terms.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Like you can infer people's skills by looking at how they dress, what they eat, what time they come to the office and so on.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It doesn't help that the attributes this person uses as signals for a "10x engineer" are all kinda on the introverted side of the spectrum, to be charitable, as introversion per-se is a test of some kind of smartness. It's close to the old Hollywood trope of the computer guy being a weird, overweight, sexually frustrated white guy.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, now that we closed the chapter on the critique of random people's tweets, let's get to something more interesting...&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Do "10x" engineers even exist? What are they? And what makes them?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Let's start from that last one.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What's a 10x engineer? Typically we think of "10x" engineers as people that are much more productive than the average when working with code. Code "wizards", "ninjas", "rockstars" or whatever else cringe-worthy moniker teenagers use.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In my experience, 10x engineers do exist. Even controlling for seniority, knowledge, and skills, productivity is not uniform among people.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I hope this is not controversial, one can know something, be even experienced in doing a given thing with a good track record, and yet not be as effective at doing it as others.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Should you hire only "10x" people? Definitely! Sort-of. In a way... We all look for excellent people, of course, and being able to distinguish good from great among a given seniority level is certainly important.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;That said, there are lots of ways to be excellent beyond coding. In a decently-sized team other aspects might even be more important, mentoring, coordination, project management and so on.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;As things grow code usually tends towards being an implementation detail, so to speak, secondary to product and people concerns.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Even if we just look at coding, there are lots of kinds of engineers, people who are great at handling huge, foreign code-bases, people who are great at fixing things, people who are great at creating new things, people who are great architects and so on...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Lots of things in which you can be "10x" - but still, the concept of productivity being separate from skill generally holds.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;These multipliers are also&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&amp;nbsp;of the hardest to assess in interviews because again we're saying it doesn't correlate with simply what a person has on the CV or their ability to answer technical questions. Correctly characterizing where this productivity comes from is thus of utmost importance.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Why are some people more effective than others, given the same skillset? Where does that effectiveness come from? Is it their choice of editors? Their typing speed? Some sort of flow-related supernatural focus?&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I think not.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;First Hypothesis: Output = Skill * Effort * Allocation&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Skill is knowledge and experience, what we usually mostly correlate with seniority levels. As an analogy, I would say this is the value of the chips you have, at a gambling table.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Effort, given the same workday, is mostly focus. It's a time management skill, the ability to execute your tasks in good-sized chunks. In the gambling analogy, this would be the number of chips you have.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Focus is partially environment-related, but what we don't say often enough is that a lot of it is a skill.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;A&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&amp;nbsp;lot of it also relates to how much a person likes doing a given thing, how fit he is for the job at hand. Effective managers that try to hire and allocate people to do the things they are passionate about, can thus help to get the most from the effort multiplier.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The last aspect, what I called allocation. This is how you spend the chips you have. &lt;b&gt;Second hypothesis: correct allocation is what "makes" a 10x engineer.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In other words, we all have a number of chips to spend each day on our tasks. And controlling for seniority levels more or less effectively capture this number, there isn't that much variance in that.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The part that has a lot of variance is the allocation. Not in what to do, as in prioritizing this bugfix to that feature (even if such skills are also fundamental and have very high variance we capture them well in job categories, think technical director versus principal engineer for example) but &lt;u&gt;how&lt;/u&gt;&amp;nbsp;we do things.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Do I use a scripting language, should I implement things in C, or maybe I should learn that fancy new language everyone's talking about? Do I rely on a library or write from scratch? Do I need to understand the overall architecture of this software? Do I need to understand the specifics of the functions I'm calling? When it's appropriate to be sloppy? Should I jump into prototyping or I need to learn about the state of the art first? Should I go deep or wide?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We always have a limited amount of resources, ability to keep things in our brain, of doing work. And software design has a lot of different dimensions, abstraction versus specificity, generalization versus integration, high-level versus low-level concerns and so on.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The ability to navigate this design space and selecting the right tools for the job, both in terms of concrete artifacts (code, libraries, languages, IDEs) and of abstract methodologies, makes a huge difference. One thing is to know about things, the other is to be able to&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;critically&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;evaluate tradeoffs and allocate (your) resources well.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Third Hypothesis. The reason why "10x" skills look mystical is that we don't have a solid theory for allocation choices.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;When we have a design space that lacks a solid theoretical framework to navigate it, all success looks random, unteachable, and mystical. This is why "10x" engineers are both rare and sometimes described in horrible ways like it was done in the twitter thread above.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Too much of programming is still an art, eventually some people "get it" after lots of exercise, but we don't really know how to replicate that success.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We accept that somehow of the huge talent pool of software engineers, some will somehow find a way to be productive at some things, and some will be less successful.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;---&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;Update: I was made aware of this, which is a much more concise way of vehiculating the same message:&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-tWCLXgovrV0/XTJFnm3MR_I/AAAAAAAAByU/ZIydLBNgaAgcCYfyLzxatq8nJRwZcrHKgCLcBGAs/s1600/Screen%2BShot%2B2019-07-20%2Bat%2B12.34.18%2BAM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="896" data-original-width="1164" height="246" src="https://1.bp.blogspot.com/-tWCLXgovrV0/XTJFnm3MR_I/AAAAAAAAByU/ZIydLBNgaAgcCYfyLzxatq8nJRwZcrHKgCLcBGAs/s320/Screen%2BShot%2B2019-07-20%2Bat%2B12.34.18%2BAM.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;It's great that I'm not alone in this...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/WITqsXQU0dY" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/5459551505822130965/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=5459551505822130965" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/5459551505822130965" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/5459551505822130965" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/WITqsXQU0dY/what-makes-10x-engineers-complete.html" title="What makes &quot;10x&quot; engineers. A complete hypothesis." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-hW-q_CN-wvs/XTBustrDdBI/AAAAAAAAByE/wHDUVKfMq3oOksO96xHz6OKG-lPKSbYnACLcBGAs/s72-c/Screen%2BShot%2B2019-07-18%2Bat%2B3.03.58%2BPM.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/07/what-makes-10x-engineers-complete.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-3077141949407666024</id><published>2019-06-02T18:25:00.002-07:00</published><updated>2019-06-02T18:29:56.022-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="The industry" /><title type="text">The Value of Pixels (presentation slides)</title><content type="html">&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Presented at the bay area game tech meetup, hosted at Roblox offices.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you want to be notified of future meetups, &lt;a href="https://www.meetup.com/Game-Engine-Emerging-Technologies/"&gt;join here&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;a href="https://www.dropbox.com/s/wnhedrfw070e014/PixelValue.pdf?dl=0"&gt;Download the slides here!&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif; margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="1131" data-original-width="1600" height="226" src="https://1.bp.blogspot.com/-cxJGGt_uYf4/XPR2nqAYNHI/AAAAAAAABw4/SmrgpwS3WYIL1K_ElqxdZl9OfNNfHJFJgCLcBGAs/s320/Screen%2BShot%2B2019-06-02%2Bat%2B6.21.50%2BPM.png" width="320" /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/RBEfNSqzFuA" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/3077141949407666024/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=3077141949407666024" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/3077141949407666024" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/3077141949407666024" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/RBEfNSqzFuA/the-value-of-pixels-presentation-slides.html" title="The Value of Pixels (presentation slides)" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-cxJGGt_uYf4/XPR2nqAYNHI/AAAAAAAABw4/SmrgpwS3WYIL1K_ElqxdZl9OfNNfHJFJgCLcBGAs/s72-c/Screen%2BShot%2B2019-06-02%2Bat%2B6.21.50%2BPM.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/06/the-value-of-pixels-presentation-slides.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-1240331901334375330</id><published>2019-05-15T23:34:00.000-07:00</published><updated>2019-05-16T23:06:33.363-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Graphic rants" /><title type="text">Seeing the whole Physically-Based picture.</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;Subtitle: Building our rendering on solidly shaky grounds.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Physically-Based Rendering has won. There is no question about it, after an initial period of reluctance, even artists have been converted and I don't think you can find many rendering systems nowadays, either offline or real-time, that hasn't embraced PBR. And PBR proved itself to even be able to adapt to multiple art styles, outside strict adherence to photorealism.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But, really, how much physics is there in our PBR renderers? Let's have a look.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Optics and Photometry.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://3.bp.blogspot.com/-cmD4DOEnV1Q/XNz-a5zY0BI/AAAAAAAABwA/Csh_Dsbx65QvIWod8MUou2Z82kVjSNCIQCLcBGAs/s1600/Paper.Pbr%2Bpost.1%2Bcopy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="734" data-original-width="1128" height="208" src="https://3.bp.blogspot.com/-cmD4DOEnV1Q/XNz-a5zY0BI/AAAAAAAABwA/Csh_Dsbx65QvIWod8MUou2Z82kVjSNCIQCLcBGAs/s320/Paper.Pbr%2Bpost.1%2Bcopy.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Starting from the top, we have to define our physical framework. Physics are models, made to "fit" reality in order to make predictions. Different models are appropriate for different contexts and problems. For rendering, we work with a framework called "geometrical optics".&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In G.O. light is composed of multiple frequencies which are assumed to be independent. Light travels in straight lines (in homogeneous media). It changes direction at changes of media (changes of IOR), where it can be absorbed, reflected or refracted. It travels instantaneously and it follows the path of least time (Fermat's principle).&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Is this a good framework? It's already making a lot of assumptions, and we know it cannot model all light behavior even when it comes to things that are easily visible: diffraction, interference, fluorescence, phosphorescence. But we say that these phenomena are not that common in everyday materials, and we might be right.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;That's not all though, even before we start rendering our first triangle, we make more assumptions. First, we define a color space, usually a trichromatic one, because of the visual system metamerism. Fine, but we know that's not correct for rendering. We know spectral rendering has in even sometimes dramatically different results, but we trust our artists can tune lighting, materials, and post-processing in the right way (even if the two things shouldn't be related) to generate nice images even if we restrict ourselves to RGB. Or at least, we hope.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Scattering&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-SeEvzp6Ioyw/XNz-feLwA0I/AAAAAAAABwE/_YYmJMWXmIk76CcD04PONWKLkf3fmskHwCLcBGAs/s1600/Paper.Pbr%2Bpost.2%2Bcopy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="734" data-original-width="1128" height="208" src="https://2.bp.blogspot.com/-SeEvzp6Ioyw/XNz-feLwA0I/AAAAAAAABwE/_YYmJMWXmIk76CcD04PONWKLkf3fmskHwCLcBGAs/s320/Paper.Pbr%2Bpost.2%2Bcopy.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Next, we have to define what happens when the light "hits" something (an IOR discontinuity). Well, who knows, light is really hard! Some electrons... resonate? Get polarized? Please let it not be something to do with quantum stuff... Anyhow, eventually they scatter some energy back... waves? particles? There is some interference at around the atomic level. Who knows, luckily, we have another framework that comes to rescue: microfacet theory.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Surfaces are made of microfacets, like a microscopic landscape, light rays hit, bounce around and eventually come out. If we integrate the behavior of said microfacets over a small area, we can compute a scattering probability (BRDF) from the distribution of the microfacets themselves and a lot of math and voila', rendering happens.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Over a small area? How small, by the way? Well, Naty Hoffman and Eric Heitz say around the order of magnitude of the projected area of a pixel. I say, around the order of magnitude of a light wavelength, and then the projected area thing is antialiasing applied "after". So probably it's the pixel thing that's right.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What are these microfacets made of? Ideal reflectors obeying only the Fresnel law for how much light is reflected and how much refracted. The refracted part gets into the material (for dielectrics, that somehow allow this behavior), scatters some more and eventually comes out. If it comes out still "near enough" we call that "diffuse" reflection.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Otherwise, we call that subsurface scattering. But how does the light scatter inside the material? It hits particles. Microflakes? But microfacet based diffuse models (e.g. Oren-Nayar) simply swap the facets from ideal reflectors to ideal diffusers (Lambert)...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Regardless. We know all these things! We have blog posts, Siggraph talks, and books. Physics... And this still is well in that "geometrical optics" framework. Rays of light hit things. So much so that we can create raytracers to brute-force these microscopic interactions and create our own BRDFs!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But, it is still reasonable to use geometrical optics for these interactions? They seem to be quite... small. Maybe diffraction now matters? It turns out, it does, and it's a well-known thing (if you read the papers from the sixties... Beckmann-Spizzichino), but we sweep it under the rug.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And well, we can't really derive the equations from the microfacets, that integral is itself hard, so the BRDFs that we use introduce, typically, a bunch of other assumptions. For example, they might disregard the fact that light can bounce around multiple times before "coming out".&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But who cares, nice pictures can be generated with this theory, and that's what matters. Moreover, someone did try to fit the resulting equations to real-world materials, right? The MERL database? I wonder how much error there is in that. Or how much it samples "well" real-world materials. Or how perceptual is the error metric used in estimating the error... Better to not think too much.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Fiat Lux!&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://4.bp.blogspot.com/-JAEH9aZJ400/XNz-jvxipBI/AAAAAAAABwI/z4ihf_FGgCkTlqwKvQKNIZycwc0R9EnVgCLcBGAs/s1600/Paper.Pbr%2Bpost.3%2Bcopy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="630" data-original-width="550" height="320" src="https://4.bp.blogspot.com/-JAEH9aZJ400/XNz-jvxipBI/AAAAAAAABwI/z4ihf_FGgCkTlqwKvQKNIZycwc0R9EnVgCLcBGAs/s320/Paper.Pbr%2Bpost.3%2Bcopy.png" width="279" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Are we done now? Far from it! In practice, we cannot just use the BRDF and brute-force light rays, not for real-time rendering, we're not Arnold. We need to compute a few more integrals!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We need to integrate over the light source, and over the surface area that is "seen" by the pixel, we're considering (pixel footprint). And that is incredibly hard, so hard we don't even try before having introduced a bunch more assumptions and approximations.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;First of all, when we talk about pixel footprint, we really mean that we consider some statistics of the surface normals.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We don't consider the fact that, for example, the "view rays" themselves change (and the light ones too), or that the surface normals don't really exist as an entity separate from actual surface geometry (which would cause shadowing and all other fun things). We assume these effects to be small.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Then, when we talk about light, we mostly mean simple geometric shapes that emit light from their surface. For example, a sphere. At each point, the light is emitted equally in all directions, and most often, it's also emitted with the same intensity over the surface.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And even then it's not enough to compute everything in closed-form. In fact, the more complex the light is, typically, the more approximated the BRDF will become. And then we'll fit these approximated BRDFs to the "real" one, and sum everything up. And sprinkle some of that pixel footprint thing on top somehow as well, but really that's done once on the "real" BRDF, even if we never actually use that!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So we have an approximation for very small lights, and maybe a good one for spheres, one for lines and capsules with some more handwaving, even more for polygonal lights, especially if textured and lastly one for far, "environment" light... We have approximations for "diffuse" and for "specular", for each of these. And maybe for static versus dynamic objects? A lot of math and different approximations.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We compare them and make sure that more-or-less the material looks the same under different kinds of light, and call it a day... The most ambitious of us might even export a scene to a path-tracer and compute some sort of ground-truth, to visually make sure things are at least reasonable...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- We're done, right?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://3.bp.blogspot.com/-v6ED1rieFe8/XNz-n48E9bI/AAAAAAAABwM/VzcqigDzhBgFd1GLkz9yhOHashlJdISSQCLcBGAs/s1600/Paper.Pbr%2Bpost.4%2Bcopy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="734" data-original-width="1128" height="208" src="https://3.bp.blogspot.com/-v6ED1rieFe8/XNz-n48E9bI/AAAAAAAABwM/VzcqigDzhBgFd1GLkz9yhOHashlJdISSQCLcBGAs/s320/Paper.Pbr%2Bpost.4%2Bcopy.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So... we get our final image. In all its Physically Based, 60fps, HDR glory! Spectacular.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Year after year people come up with better equations, tighter approximations, and we make shinier pixels as a result.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Is that all? Of course not! We are just getting started!&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In practice, materials are not just one surface... They can have layers! And they are never optically uniform! They sparkle! They are anisotropic, they have scratches. Really, look around, look at most things. Most things are sparkly and anisotropic, due to the way they are fabricated.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And nothing is a surface, really. It's mostly volume and particles. Even... air! So we need fog and volumetric models. But that's not just about the light that scatters in the air back to our virtual cameras, we should also consider how this scattering affects lighting at surfaces. Our rays of light are not that straight anymore! Participating volumes make our light sources more "diffuse". Bigger. All of them, also things like environment lighting! And... that should affect shadows too right?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And now that we think about shadows... all this complexity and unknowns are still only for what we call "direct" lighting! What about global illumination? What about the million other hacks and assumptions that we rely upon to render each or our frames?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Conclusions&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So. How much physics is there in a frame, really? And more importantly, what's the point of all this? Should we be ashamed of not knowing physics that well? Should we do physics more? Less?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-Gh-gcOe8c-M/XN2WV2Hr_-I/AAAAAAAABwc/V6dTPphmuKAae7Fau1sqXiAatLYlURU3gCLcBGAs/s1600/eric-widner-ewidner-ww2-paris-comms-room-001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="942" data-original-width="1600" height="188" src="https://2.bp.blogspot.com/-Gh-gcOe8c-M/XN2WV2Hr_-I/AAAAAAAABwc/V6dTPphmuKAae7Fau1sqXiAatLYlURU3gCLcBGAs/s320/eric-widner-ewidner-ww2-paris-comms-room-001.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I don't know. I personally do not know physics well and I'm not too ashamed. A lot of what we've been doing is reasonable, really. We went with GGX because its "tail" helps. All the lighting improvements served our products. All the assumptions, individually, looked reasonable.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But, there is a value I think in looking at our math and our approximations holistically, now that we are getting so good at photorealism.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Perhaps there is not too much value for example in going off the deep end of complexity when we think of BRDFs, if we can't then integrate them with complex lighting, or, in order to do so, we have to approximate them again.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Similarly, the features we focus on should be evaluated. Is it more important to have non-uniform emission in our light sources, or a different "tail" in GGX/T-R? A&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;nisotropic surfaces or sparkles? Spectral sampling? Thin-film? Non-lambertian diffuse? Of which kind? Accurate&amp;nbsp;energy conservation or multi-bounce in microfacets?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Is it better to use the best possible approximation for a given integral, even if we end up with many different ones, or should we just use a bunch of spherical gaussians, or LTCs and such, but keep the same representation everywhere? And in general, is most of our error still in the materials, or in the lights? This is very hard to tell from just looking at artist-made pictures, because artists will compensate any way they can!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But even more importantly - How much can we keep relying on simplifying assumptions in order to make our math work?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I suspect to answer these questions we'll need more data. Acquire from the real world. Brute force solutions. Then look at the data and understand what matters, what matters perceptually, what errors are we committing end-to-end, and what we should approximate better and how...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And we should not assume that because somewhere we have a bit of physics, we are doing things correctly. We are, after all, a field that forgot for decades basic things like color spaces and gamma.&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/L4a8fPdM6JM" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/1240331901334375330/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=1240331901334375330" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1240331901334375330" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1240331901334375330" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/L4a8fPdM6JM/seeing-whole-physically-based-picture.html" title="Seeing the whole Physically-Based picture." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://3.bp.blogspot.com/-cmD4DOEnV1Q/XNz-a5zY0BI/AAAAAAAABwA/Csh_Dsbx65QvIWod8MUou2Z82kVjSNCIQCLcBGAs/s72-c/Paper.Pbr%2Bpost.1%2Bcopy.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/05/seeing-whole-physically-based-picture.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-5198257821144765372</id><published>2019-05-15T15:03:00.003-07:00</published><updated>2019-05-15T15:13:07.583-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Programming tutorials" /><title type="text">NumPy by Example</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;This originally was in my &lt;a href="https://c0de517e.blogspot.com/2014/09/scientific-python-101.html"&gt;Scientific Python 101&lt;/a&gt;&amp;nbsp;article, I've split it now as it was a long article and sometimes I need just to have a look at this code as a reminder of how things work.&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;If you're interested in a similar "by example" introduction for Mathematica, &lt;a href="http://c0de517e.blogspot.com/2013/10/wolframs-mathematica-101.html"&gt;check this other one out&lt;/a&gt;.&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Execute each section in an IPython cell (copy and paste, then shift-enter)&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Set-up the environment:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# First, we'll have to import NumPy and SciPy packages.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# IPython has "magics" (macros) to help common tasks like this:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;%pylab&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# This will avoid scientific notation when printing, see also %precision&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;times new roman&amp;quot;; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal;"&gt;&lt;div style="margin: 0px; text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;np.set_printoptions(suppress = True)&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin: 0px; text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Optional: change the way division works:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;#from __future__ import division&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# 1/2 = 0.5 instead of integer division... problem is that then 2/2 would be float as well if we enable this, so, beware.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# In IPython notebook, cell execution is shift-enter&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# In IPython-QT enter evaluates and control-enter is used for multiline input&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Tab is used for completion, shift-tab after a function name shows its help&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Note that IPython will display the output of the LAST -expression- in a cell&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# but variable assignments in Python are NOT expressions, so they will&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# suppress output, unlike Matlab or Mathematica. You will need to add print&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# statements after the assignments in the following examples to see the output&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;data = [[1,2],[3,4],[5,6]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# if you want to suppress output in the rare cases it's generated, use ;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;data; # try without the ; to see the difference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# There is a magic for help as well&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;%quickref&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Also, you can use ? and ?? for details on a symbol&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;get_ipython().magic(u'pinfo %pylab')&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;/span&gt;&lt;div style="-webkit-text-stroke-width: 0px; color: black; font-family: Times; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: justify; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"&gt;&lt;div style="text-align: left;"&gt;&lt;div style="margin: 0px;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# In addition to the Python built-in functions help() and dir(symbol)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Other important magics are: %reset, %reset_selective, %whos&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# %prun (profile), %pdb (debug), %run, %edit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;1*3 # evaluate this in a separate cell...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;_*3 # ...now _ refers to the output of last evaluated cell&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# again, not that useful because you can't refer to the previous expression&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# evaluated inside a cell, just to the previous evaluation of an entire cell&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# A numpy array can be created from a homogeneous list-like object&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.array(data)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Or an uninitialized one can be created by specifying its shape&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.ndarray((3,3))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# There are also many other "constructors"&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.identity(5)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.zeros((4,5))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.ones((4,))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.linspace(2,3) # see also arange and logspace&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.random.random((4,4))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Arrays can also be created from functions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.fromfunction((lambda x: x*x), shape = (10,))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# ...or by parsing a string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.fromstring('1, 2', dtype=int, sep=',')&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Arrays are assigned by reference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2 = arr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# To create a copy, use copy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2 = arr.copy()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# An array shape is a descriptor, it can be changed with no copy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.zeros((4,4))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = arr.reshape((2,8)) # returns the same data in a new view&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# numpy also supports matrices, which are arrays contrained to be 2d&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;mat = np.asmatrix(arr)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Not all operations avoid copies, flatten creates a copy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr.flatten()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# While ravel doesn't&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.zeros((4,4))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr.ravel()&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# By default numpy arrays are created in C order (row-major), but&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small; text-align: left;"&gt;# you can arrange&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small; text-align: left;"&gt;them in fortran order as well on creation,&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# or make a fortran-order copy of an existing array&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.asfortranarray(arr)&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Data is always contiguously&amp;nbsp;packed in memory&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Arrays can be indexed as with python lists/tuples&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.zeros((4,4))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[0][0]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Or with a multidimensional index&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[0,0]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Negative indices start from the end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[-1,-1] # same as arr[3,3] for this array&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Or, like matlab, via splicing of a range: start:end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = arange(10)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[1:3] # elements 1,2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[:3] # 0,1,2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[5:] # 5,6,7,8,9&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[5:-1] # 5,6,7,8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[0:4:2] # step 2: 0,3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = arr.reshape(2,5)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[0,:] # first row&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[:,0] # first column&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Also, splicing works on a list of indices (see also choose)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = arr.reshape(10)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[[1,3,5]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# and with a numpy array of bools (see also where)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr=np.array([1,2,3])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2=np.array([0,3,2])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[arr &amp;gt; arr2]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# flat returns an 1D-iterator&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = arr.reshape(2,5)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr.flat[3] # same as arr.reshape(arr.size)[3]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Core operations on arrays are "ufunc"tions, element-wise&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# vectorized operations&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = arange(0,5)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2 = arange(5,10)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr + arr2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Operations on arrays of different shapes follow "broadcasting rules"&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.array([[0,1],[2,3]]) # shape (2,2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2 = np.array([1,1]) # shape (1,)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# If we do arr+arr2 arr2.ndim&lt;arr .ndim="" arr2="" as="" font="" interpreted="" is=""&gt;&lt;/arr&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# an input can be used if shape in all dimensions sizes, or if&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# the dimensions that don't match have size 1 in its shape&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr + arr2 # arr2 added to each row of arr!&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Broadcasting also works for assignment:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[...] = arr2 # [[1,1],[1,1]] note the [...] to access all contents&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2 = arr # without [...] we just say arr2 refers to the same object as arr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[1,:] = 0 # This now is [[1,1],[0,0]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# flat can be used with broadcasting too&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr.flat = 3 # [[3,3],[3,3]]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr.flat[[1,3]] = 2 # [[3,2],[2,3]]&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# broadcast "previews" broadcasting results&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;np.broadcast(np.array([1,2]), np.array([[1,2],[3,4]])).shape&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# It's possible to manually add ones in the shape using newaxis&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small; text-align: left;"&gt;# See also: expand_dims&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;print(arr[np.newaxis(),:,:].shape) # (1,2,2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;print(arr[:,np.newaxis(),:].shape) # (2,1,2)&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# There are many ways to generate list of indices as well&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = arange(5) # 0,1,2,3,4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[np.nonzero(arr)] += 2 # 0,3,4,5,6&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.identity(3)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[np.diag_indices(3)] = 0 # diagonal elements, same as np.diag(arg.shape[0])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[np.tril_indices(3)] = 1 # lower triangle elements&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr[np.unravel_index(5,(3,3))] = 2 # returns an index given the flattened index and a shape&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Iteration over arrays can be done with for loops and indices&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Oterating over single elements is of course slower than native&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# numpy operators. Prefer vector operations with splicing and masking&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Cython, Numba, Weave or Numexpr can be used when performance matters.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.arange(10)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;for idx in range(arr.size):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; print idx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# For multidimensiona arrays there are indices and iterators&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.identity(3)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;for idx in np.ndindex(arr.shape):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; print arr[idx]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;for idx, val in np.ndenumerate(arr):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; print idx, val # assigning to val won't change arr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;for val in arr.flat:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; print val # assigning to val won't change arr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;for val in np.nditer(arr):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; print val # same as before&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;for val in np.nditer(arr, op_flags=['readwrite']):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; val[...] += 1 # this changes arr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Vector and Matrix multiplication are done with dot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.array([1,2,3])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2 = np.identity(3)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;np.dot(arr2, arr)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Or by using the matrix object, note that 1d vectors&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# are interpreted as rows when "seen" by a matrix object&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;np.asmatrix(arr2) * np.asmatrix(arr).transpose()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Comparisons are also element-wise and generate masks&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr2 = np.array([2,0,0])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;print (arr2 &amp;gt; arr)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Branching can be done checking predicates for any true or all true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;if (arr2 &amp;gt; arr).any():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; print "at least one greater"&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Mapping a function over an array should NOT be done w/comprehensions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;arr = np.arange(5)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;[x*2 for x in arr] # this will return a list, not an array&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Instead use apply_along_axis, axis 0 is rows&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;np.apply_along_axis((lambda x: x*2), 0, arr)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# apply_along_axis is equivalent to a python loop, for simple expressions like the above, it's much slower than broadcasting&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# It's also possible to vectorize python functions, but they won't execute faster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;def test(x):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&amp;nbsp; &amp;nbsp; return x*2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;testV = np.vectorize(test)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;testV(arr)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Scipy adds a wealth of numerical analysis functions, it's simple&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# so I won't write about it.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Matplotlib (replicates Matlab plotting) is worth having a quick look.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# IPython supports matplotlib integration and can display plots inline&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;%matplotlib inline&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Unfortunately if you chose the inline backend you will lose the ability&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# of interacting with the plots (zooming, panning...)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Use a separate backend like %matplotlib qt if interaction is needed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Simple plots are simple&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;test = np.linspace(0, 2*pi)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, np.sin(test)) # %pylab imports matplotib too&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.show() # IPython will show automatically a plot in a cell, show() starts a new plot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, np.cos(test)) # a separate plot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, test) # this will be part of the cos plot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;#plt.show()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Multiple plots can also be done directly with a single plot statement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;test = np.arange(0., 5., 0.1)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Notes that ** is exponentiation.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Styles in strings: red squares and blue triangles&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, test**2, 'rs', test, test**3, 'b^')&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.show()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# It's also possible to do multiple plots in a grid with subplot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.subplot(211)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, np.sin(test))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.subplot(212)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, np.cos(test), 'r--')&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;#plt.show()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Matplotlib plots use a hierarchy of objects you can edit to&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# craft the final image. There are also global objects that are&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# used if you don't specify any. This is the same as before&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# using separate objects instead of the global ones&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;fig = plt.figure()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;axes1 = fig.add_subplot(211)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, np.sin(test), axes = axes1)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;axes2 = fig.add_subplot(212)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;plt.plot(test, np.cos(test), 'r--', axes = axes2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;#fig.show()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# All components that do rendering are called artists&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Figure and Axes are container artists&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Line2D, Rectangle, Text, AxesImage and so on are primitive artists&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Top-level commands like plot generate primitives to create a graphic&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Matplotlib is extensible via toolkits. Toolkits are very important.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# For example mplot3d is a toolkit that enables 3d drawing:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;from mpl_toolkits.mplot3d import Axes3D&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;fig = plt.figure()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;ax = fig.add_subplot(111, projection='3d')&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;points = np.random.random((100,3))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# note that scatter wants separate x,y,z arrays&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;ax.scatter(points[:,0], points[:,1], points[:,2])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;#fig.show()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# Matplotlib is quite extensive (and ugly) and can do much more&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# It can do animations, but it's very painful, by changing the&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# data artists use after having generated them. Not advised.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# What I end up doing is to generate a sequence on PNG from&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# matplotlib and play them in sequence. In general MPL is very slow.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# If you want to just plot functions, instead of discrete data,&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;# sympy plots are a usable alternative to manual sampling:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;from sympy import symbols as sym&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;from sympy import plotting as splt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;from sympy import sin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;x = sym('x')&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;courier new&amp;quot; , &amp;quot;courier&amp;quot; , monospace; font-size: x-small;"&gt;splt.plot(sin(x), (x, 0, 2*pi))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/2eQqAFClFUA" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/5198257821144765372/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=5198257821144765372" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/5198257821144765372" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/5198257821144765372" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/2eQqAFClFUA/numpy-by-example.html" title="NumPy by Example" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/05/numpy-by-example.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-7433446573153202734</id><published>2019-04-28T17:32:00.001-07:00</published><updated>2019-04-29T10:37:47.644-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="The industry" /><title type="text">On the “toxicity” of videogame production.</title><content type="html">&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;I was at a lovely dinner yesterday with some ex-gamedev friends and, unsurprisingly, we ended up talking about the past and the future, our experiences in the trenches of videogame production. It reminded me of many discussions I had on various social media channels, and I thought it would be nice to put something in writing. I hope it might help people who want to start their career in this creative industry. And perhaps even some veterans could find something interesting in reading this.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Disclaimer.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;These are my thoughts. Duh, right? Obvious, the usual canned text about not representing the views of our corporate overlords and such? Not the point.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The thing I want to remind you before we start is how unknowable an industry is. Or even a company, a team. We live in bubbles, even the ones among us with the most experience, with most curiosity, are bound by our human limits. That’s why we structure large companies and teams in hierarchies, right? Because nobody can see everything. Of course, as you ascend them you get more of a broad view, but from these heights, the details are quite blurry, and vice-versa, people at the “bottom” can be very aware of certain details but miss the whole.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is bad enough that even if internally you try hard, after a success or a failure, to understand what went right or wrong, most of the times you won’t capture objectively and exhaustively these factors. Often times we don’t know at all, and we fail to replicate success or to avoid failing again.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-8ft2h2wclCw/XMZEu1ZS3FI/AAAAAAAABvA/qzqAsq-Q6HY8s_0ZiQcp3XQjam-hdd0QQCLcBGAs/s1600/annihilationbanner.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="627" data-original-width="1200" height="167" src="https://2.bp.blogspot.com/-8ft2h2wclCw/XMZEu1ZS3FI/AAAAAAAABvA/qzqAsq-Q6HY8s_0ZiQcp3XQjam-hdd0QQCLcBGAs/s320/annihilationbanner.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Staring at the production monster might drive you insane.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, I can claim to be more experienced than some, less than some others, it truly doesn’t matter. Nobody is a source of truth in this, the best we can do is to bring a piece of the puzzle. This is, by the way, a good attitude both towards oneself, to know that we probably have myriads of blind spots, but also key to understand what other people say and write. Even the best investigative journalists out there can at best report a bit of truth, an honest point of view, not the whole picture.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;To name names, for example, think about &lt;a href="https://twitter.com/jasonschreier"&gt;Jason Schreier&lt;/a&gt;, whom I admire (have you read &lt;a href="https://www.amazon.com/Blood-Sweat-Pixels-Triumphant-Turbulent/dp/0062651234"&gt;“blood, sweat and pixels”&lt;/a&gt;? You should...) for his writing and his ability to do great, honest research. His work is exemplary, and still, I think it’s partial. In some cases, I know it is.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And that is ok, it’s intellectual laziness to think we can read some account and form strong opinions, know what we’re talking about. Journalism should provide a starting point for discussion, research, and thought. It’s like doing science.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;You chip away at the truth, but one single observation, no matter the prestige of the lab, means very little.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And if we need multiple studies to confirm something as simple as science, where things are objective, measurable and unchanging, think how hard is the truth when it comes to entities made of people…&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Hedging risk.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;One thing to understand is where the risk for abuse comes from. And I write this first not because it should be a personal responsibility to avoid abuse, but because it’s something that we don’t talk about. Yes, there is bad management, terrible things do exist, in this industry as in others, and they have to be exposed, and we have to fight. But that doesn’t help us to plan our careers and to take care of ourselves.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, where does the potential for abuse come from? Simply, imbalance of power. If you don’t have options, you are at risk, and in practice, the worst companies tend to be the ones with all the power, simply because it’s so simple to “slip” into abusing it. Sometimes without even truly realizing what the issue is.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, you should avoid EA or Activision. Nintendo, Microsoft and Sony, right, the big ones? No, that’s not the power I’m talking about, quite the opposite. Say you are an established computer engineer working for EA, in its main campus in the silicon valley, today. Who has power, EA or you, when Google, Facebook et al are more than eager to offer you a job? I’d say, as an educated guess, that the most risk comes in medium-sized companies located in countries without a big game industry, in roles where the offer is much bigger than the demand.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Does that mean that you should not seek a career in these roles, or seek a job in such companies? Definitely not, I started exactly like that, actually leaving a safer and even better-paid job to put myself in the above-mentioned scenario. It’s not that we shouldn’t do scary and dangerous things, but we have to be aware of what we are doing and why. My better half is an actress, she’s great and I admire her ambition, work ethic, and courage. Taking risks is fine when you understand them, you make conscious choices, you have a plan, and that plan should also include a path to stability.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Bad management or creative management?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Fact. Most great games are done in stressful conditions. Crunch, fear, failure, generally the entire thing being on fire. In fact, the production of most great games can be virtually indistinguishable from the production of terrible games, and it’s the main reason why I advise against choosing your employer only based on your love of the end product.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This I think is remarkable. And often times we are truly schizophrenic with our judgment and outrage. If a product fails, we might investigate the reasons for its failure and find some underlying problems in a company’s work conditions. Great! But at the same time, when products truly succeed we have the ability to look at the very same patterns and not just turn a blind eye to them, but actively celebrate them.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The heroic story of the team that didn’t know how to ship, but pulled all-nighters, rewrote the key system and created the thing that everyone remembers to this day. If we were to look at the top N games of all time, how many would have these stories behind their productions?&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Worse, this is not just about companies and corporations. Huge entities, shareholders, due dates and market pressure. It happens pretty much universally, from individual artists creating games with the sole purpose of expressing their ideas to indie studios trying to make rent, all the way to Hollywood-sized blockbuster productions. It happened yesterday, it happens today. Will it happen in the future? Should it?&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- The cost of creativity.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;One other thing to realize is how this is not a problem of videogame production, at all. Videogames don’t have a problem. Creative products do. Look at movies, at actors, film crews. Visual effects. Music? Theater? Visual arts? Would you really be surprised to learn there are exactly the same patterns in all these? That videogames are not the “worst” industry among the creative ones? I’m guessing you would not be surprised…&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is the thing we should really be thinking about. Nobody knows how to make great creative products. There is no recipe for fun, there is no way put innovation on a predictable schedule, there’s no telling how many takes will be needed to nail that scene in a movie, and so on. This is truly a hard problem, fundamentally hard, and not a problem we can solve. By definition, creativity, research, innovation, all these things are unknown, if we knew how to do them up-front, they would not be novel and creative. They are defined by their lack of predictability.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://4.bp.blogspot.com/-ZSCjAONXefU/XMZF3D60aVI/AAAAAAAABvI/lQZkSn_jjCkHEnYXHPeMjiZEWtiFrCcfQCLcBGAs/s1600/whiplash2.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="720" data-original-width="1280" height="180" src="https://4.bp.blogspot.com/-ZSCjAONXefU/XMZF3D60aVI/AAAAAAAABvI/lQZkSn_jjCkHEnYXHPeMjiZEWtiFrCcfQCLcBGAs/s320/whiplash2.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;In keeping with movie references...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And I don’t know if we know where we stand, truly. It’s a dilemma. On one hand, we want to care, as we should, about the wellbeing of everyone. We might even go as far as saying that if you are an artist, you shouldn’t sacrifice yourself to your art. But should you not? Should it be your choice, your life, and legacy? Probably.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But then we might say, it’s ok for the individual, but it’s not ok for a corporation to exploit and use artists for profit. When we create packaged products, we put creativity in a corporate box, it’s now the responsibility of the corporation to ensure the wellbeing of the employees, they should rise to higher standards. And that is absolutely true I would never question such fact.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Yet, our schizophrenia is still there. It’s not that simple, for example, we might like a given team that does certain products. And we might be worried when such a team is acquired by a large corporation because they might lose their edge, their way of doing things. You see the contradiction in that?&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In general (in a very, very general sense), large corporations are better, because they are ruled by money, investors looking at percentages, often banks and other institutions that don’t really know nor care about the products. And money is fairly risk-averse, it makes big publishers cash on sequels, big franchises, incremental improvements and so on. All things that bring more management, that sacrifice creativity for predictability. Yet we don’t really celebrate such things, do we? We celebrate the risk takers, the crazy ones…&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;- Not an absolution.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So tl;dr; creativity has a cost in all fields, it’s probably something we can’t solve, and we should understand our own willingness to take risks, our own objectives and paths in life. Our options exist on a wide spectrum, if you can you should probably expose yourself to lots of different things and see what works best for you. And what works best will change as your life changes as well.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But this doesn’t mean that shitty management doesn’t exist. That there aren’t better and worse ways of handling risks and creativity, that there is no science and no merit. Au contraire. And ours, being a relatively new industry in many ways, certainly the youngest among the big creative industries, still has a lot to learn, a lot to discuss. I think everyone who has a good amount of production experience has seen some amount of incompetence. And has seen or knows of truly bad situations, instances of abuse and evil, as I fear will always be the case when things involve people, in general.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It’s our responsibility to speak up, to fight, to think and debate. But it’s also our responsibility to not fall into easy narratives, oversimplifications, to think that it’s easy to separate good and bad, to identify from the outside and at a glance. Because it truly isn’t and we might end up doing more harm than help, as ignorance often does.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And yes.&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 14px; font-stretch: normal; line-height: normal; text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;These are only my 2c.&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/3tQ91YZp-28" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/7433446573153202734/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=7433446573153202734" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/7433446573153202734" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/7433446573153202734" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/3tQ91YZp-28/on-toxicity-of-videogame-production.html" title="On the “toxicity” of videogame production." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://2.bp.blogspot.com/-8ft2h2wclCw/XMZEu1ZS3FI/AAAAAAAABvA/qzqAsq-Q6HY8s_0ZiQcp3XQjam-hdd0QQCLcBGAs/s72-c/annihilationbanner.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/04/on-toxicity-of-videogame-production.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-1227269497239905022</id><published>2019-04-07T21:56:00.001-07:00</published><updated>2019-04-16T22:39:58.699-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="The industry" /><title type="text">How to choose your next job (why I went to Roblox)</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is one of those (rare?) posts that I wasn't sure how to write. I'm not a fan of talking about personal things here, and even more rarely do I write about companies.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But I too often see people, especially juniors entering the industry, coming with what I think are the wrong ideas of how looking for a job works, even making mistakes sometimes that lead to frustration, an inability to fit into a given environment, and can even make people want to quit an entire industry altogether.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;By far, &lt;u&gt;the number one mistake I see, are people who just want to go to work for projects that they are a fan of.&lt;/u&gt; In my industry, that means games they like to play. Not realizing that the end product does not really tell any story of how it was done and/or what your job will be like.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I do strongly advocate to try to follow your passions, that makes working so much better. And if you're lucky, your passion will even guide you to products you personally enjoy playing. But, that should not be - I repeat, SHOULD NOT BE - your first concern.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-duRKU7N2dEg/XKrZb0lYE8I/AAAAAAAABt0/8NNC1NZ77wQX22CFR1q8jJvgh9966rAuwCLcBGAs/s1600/airship%2Bstation.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="748" data-original-width="1600" height="149" src="https://2.bp.blogspot.com/-duRKU7N2dEg/XKrZb0lYE8I/AAAAAAAABt0/8NNC1NZ77wQX22CFR1q8jJvgh9966rAuwCLcBGAs/s320/airship%2Bstation.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;"Airship station"&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I've been extremely lucky in my career. I have worked for quite a few companies, on many games. I have almost always landed in places I love. Working on projects I love. But only once I've actually worked for a franchise I play (Call of Duty, but even there, I play the single player only, so perhaps you could say I don't really play most of that either).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, I'll do what most coaches do and elevate my small sample set, based on my personal experience, in a set of rules you might or might now want to follow. And at the end, also tell a bit about why I'm now working at Roblox. Deal? Good, let's go.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- Know thyself.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The first thing is to know yourself. Hopefully, if you paid attention and are honest, over the years you form an idea of who you are and what you like to do, what motivates you.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It's actually not easy, and many people struggle with it, but that might not be the end of the world either. If you don't know, then you at least know you don't and can reflect that in your education and career choices.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In my case, I think I could describe myself as follows:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I'm driven by curiosity. I love knowledge, learning, thinking. This is nothing particularly peculiar, if you look at theories of human desire and curiosity, gaining knowledge is one of the main universal motivators.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;My own intellectual strength lies mostly in logical thinking. I have always been drawn to math, formal systems. This is not to say I'm an extraordinary mathematician, but I do find it easier to work when I can have a certain degree of control and understanding.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I love creativity, creative expression, and art, particularly visual arts.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I'm a very social and open introvert. What this means is that I like people, but I've also always been primarily focused inwards, thinking, day-dreaming. Especially as a kid, I could get completely lost in my own thoughts. Nowadays, I try to be a more balanced person, but it's a conscious effort.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, so what does all this mean? How does it relate to finding a job? Well, to me, since a very young age, it meant I knew I would either be an artist or a computer scientist. And that either way it would probably involve computers.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;That's why I was involved as a kid in the demo scene. After high school, I decided I wasn't talented enough to make a living as an artist, and I chose computer science. In retrospect, I had a great intuition,&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;as even today I struggle in my own art to go out of certain mental models and constraints. I might have been a good technical artist, who knows, but I think I made the right call. Good job, nerdy teenage me!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- Know thy enemy.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What you like to do, what you can offer. This second "step" matures as you gain more work experience, again, if you pay some attention. If you don't know yet, it's not a problem - it means you can know your objectives are probably more exploratory than mine. Your understanding is something that is ever-evolving.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What does all that psychological stuff above mean when it comes to a job? Well, for me it means:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul&gt;&lt;li&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I'm not a ninja, a cowboy, or a rockstar. I'm pretty decent with hacking code I hope, as you would expect from anyone with some seniority, but I'm not the guy that will cruise through foreign source, write some mysterious lines, and make things work. I need to understand what I'm doing to be the most effective, and I have to consciously balance my pragmatism with my curiosity.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;On the other hand, I'm at my best when I'm early in a project. I gravitate towards R&amp;amp;D, solving problems that have unknowns. Assessing risks, doing prototypes, organizing work. Mentoring other people.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I don't care about technology or code per se. All are tools for a means to an end. I care about computer graphics, and that's what I know most about, but I am curious about anything. Even outside computer science. So, even in R&amp;amp;D, I would not work in the abstract, in the five-years out horizon, or on entirely theoretical matters. I rather prefer to be close to the product and people.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I'm a rendering engineer. At least that's what I've been doing for the past decade or so. But that's not enough. There are a million ways to be a rendering engineer. I think I'm best at working on novel problems, doing applied R&amp;amp;D, and doing so by caring about the entire pipeline, not only code.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;There are another million ways to do this job and are all useful in a company. There's no better or worse. If you know what you can offer and like, you will be able to communicate it more clearly and find better matches. We are all interested in that, in finding the perfect fit. One engineer can do terribly at one company, and thrive in another. It's a very complex handshake, but it all begins in understanding what you need.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- Profit?&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Note: I don't mean that everything I wrote above is something you have to think about any time you send a resume. First of all, &lt;u&gt;you should probably always talk to people, and never limit yourself&lt;/u&gt;. Yes, really. Send that CV. No, I don't care what you're doing, the timing, the company, just send that CV and have a talk. You never know what you might learn, don't make assumptions.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Second, it's silly to go through all this explicitly, every time you think of a job. But. If you know all this, if along the way you took some effort to be a bit aware of things, you will naturally be more clear in your interactions and probably end up finding opportunities that fit you.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://4.bp.blogspot.com/-RXV5S_rRjxI/XKrUDM_X5nI/AAAAAAAABtg/QcHqigF0IoQHd0nhAchx2bm64n5oB1KygCLcBGAs/s1600/rip%2Bur%2Btoaster.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="828" data-original-width="1600" height="165" src="https://4.bp.blogspot.com/-RXV5S_rRjxI/XKrUDM_X5nI/AAAAAAAABtg/QcHqigF0IoQHd0nhAchx2bm64n5oB1KygCLcBGAs/s320/rip%2Bur%2Btoaster.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;"Rip ur toaster"&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, let's now address the last point. Why Roblox? I have to be honest. I would not have written all this if a few people didn't ask me that question. Not many, most of my friends in the industry actually were very positive, heard good things, and actually made me more confident in the choice.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But in some cases, people didn't see immediately the connection between someone who has so far been doing only AAA games and almost only for consoles, and a company that makes a platform for games mostly aimed at kids, mostly on PC and mobile, and with graphics mostly made out of flat shaded blocks. So I thought that going through my point of view could be something interesting to write about.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Why Roblox and not, say Naughty Dog or Rockstar, Unity or Unreal? Assuming that I had a choice of course, in a dream world where I can pick...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Because I'm fascinated by the problem set.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now, let's be clear. I'm writing this blind, I actually intended to write it before my first day, to be entirely blind. My goal is not to talk about the job or the company. Also, I don't want to make comparisons. I am actually a stern proponent of the fact that computer graphics are far from being solved, both in terms of shiny pixels and associated research and even more so in terms of the production pipelines at large.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Instead, I simply want to explain why I ended up thinking that flat shading might be very interesting.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-PqlQ9CvaLgc/XKrUVZrO1pI/AAAAAAAABto/q_SOlT8E8OgbLpWeWiYco5k6Xi_aM7fewCLcBGAs/s1600/Stratosphere-Settlement-by-EBR.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="708" data-original-width="1480" height="153" src="https://2.bp.blogspot.com/-PqlQ9CvaLgc/XKrUVZrO1pI/AAAAAAAABto/q_SOlT8E8OgbLpWeWiYco5k6Xi_aM7fewCLcBGAs/s320/Stratosphere-Settlement-by-EBR.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;"Stratosphere Settlement"&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The way I see it, Roblox is trying to do two very hard things at once. First, it wants to be everywhere, from low-powered mobile devices to PCs to consoles, scaling the games automatically and appropriately. Second, these games are typically made by creatives that do not have necessarily the same technical knowledge as conventional game studios. In fact, the Roblox platform is used even as a teaching tool for kids, and many creators start on the platform as kids.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is a fascinating and scary idea. How to do graphics with primitives that are simpler than traditional DCC tools, but at the same time that render efficiently across so many runtimes? In Roblox, everything is dynamic. Everything streams, and start-up times are very important (a common thing with mobile gaming in general). There is no baking, the mantra for all rendering is that it has to be incremental, cached, and with graceful degradation.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And now, in this platform with these constraints, think of what you might want to do if you wanted to start moving more towards a conventional real-time rendering engine. What could you do to be closer to say, Unity, but retaining enough control to still be able to scale? I think one key idea is to constrain authoring in ways that allow attaching semantics to the assets. In other words, not having creators fully specify them to the same level as a conventional engine does, but leveraging that to "reinterpret" them a bit to perform well across the different devices.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I don't know, I'm not sure. But it got me thinking. And that was a good sign. Was it the right choice? Ask me in a year or so...&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/BnVtIeWZOl4" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/1227269497239905022/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=1227269497239905022" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1227269497239905022" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/1227269497239905022" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/BnVtIeWZOl4/how-to-choose-your-next-job-why-i-went.html" title="How to choose your next job (why I went to Roblox)" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://2.bp.blogspot.com/-duRKU7N2dEg/XKrZb0lYE8I/AAAAAAAABt0/8NNC1NZ77wQX22CFR1q8jJvgh9966rAuwCLcBGAs/s72-c/airship%2Bstation.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/04/how-to-choose-your-next-job-why-i-went.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-415197100506216932</id><published>2019-03-30T23:26:00.001-07:00</published><updated>2019-03-31T12:31:08.138-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Graphic rants" /><title type="text">An unbiased look at real-time raytracing</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Evaluating technology without hype or hate...&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;That would have been the title of my blog post if I published the version I had prepared after the DXR/RTX technology finally became public last&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;year, at GDC 2018.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But alas I didn't. It remained in my drafts folder. Siggraph came and went. Now another GDC, and I finally decided to can that and rewrite it.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Why? Not because I thought the topic wasn't interesting. Hype is easy to give in to. Fear of missing out, excitement about new toys to play with, tech for tech's sake... Hate is equally devious. Fear of change. Comfort zones, familiarity.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;These are all very interesting things to think about. And you should.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But can I claim I am an expert on this? I don't know, I am not a venture capitalist, and I could say I've been right a number of times, but I doubt that reaches the threshold of statistical significance.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Moreover, being old and grumpy and betting against new technologies is often an easy win. Innovation is hard!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And really, it doesn't matter much. This technology is already in the hardware, and it will stay for the future. It is backed by large companies, and more will come on board for sure. And yes, it could go the way of geometry shaders and other things that tried to work "against" the established GPU architectures, but even for these, we did spend some time to understand how they could help us...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, let's just assume we want to do some R&amp;amp;D in this RTRT thing and let's ask a different question. What should we be looking for?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;The do and do not list of RTRT research.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO NOT&lt;/b&gt; - Think that RTRT will make things simpler, or that (technical) simplicity is an objective. In real-time rendering, the pain comes from within. There's nothing that will stop people spending one month to save 0.1ms in any renderer.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Until power is out of the equation, we will always build complex systems to achieve the ultimate quality vs performance tradeoffs. When people say that shadow maps are hard for example, they mostly mean that fast shadow maps are hard. Nobody prevents us from rendering huge, high precision maps with high-quality filtering. Even rendering from multiple light samples and doing proper area lights. We don't do it, because of performance optimization.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And that's true for all complexity in a real-time renderer. When we add raytracing to the mix we only sign for more pain, hybrid algorithms, code paths, caching schemes and so on. And that's ok. Programmer's pain doesn't really matter much in the logistics of the production of today's games.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://4.bp.blogspot.com/-p6jIRwLASco/XKBcY32YMBI/AAAAAAAABs0/H_ofLYbnwrUoweNnGwJ2Wb96qx0e7Gp2gCLcBGAs/s1600/Call-of-Duty-Infinite-Warfare.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="900" data-original-width="1600" height="180" src="https://4.bp.blogspot.com/-p6jIRwLASco/XKBcY32YMBI/AAAAAAAABs0/H_ofLYbnwrUoweNnGwJ2Wb96qx0e7Gp2gCLcBGAs/s320/Call-of-Duty-Infinite-Warfare.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;How many rendering techniques can you see?&lt;br /&gt;How much pain was spent to save fractions of ms on each?&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;&lt;br /&gt;DO&lt;/b&gt; - Think about ray/memory/shading coherency and the GPU implications of raytracing. In other words, optimization. Right now, on high-end hardware, we can probably throw a few relatively naive raytracing effects and they will work because these GPUs are much more powerful than the consoles that constrain the scene and rendering complexity of most AAA games. They can render these scenes at obscene framerates and resolutions. So it might seem not a huge price to pay to drop back to 1080p and 60hz in order to have nicer effects. But this doesn't mean it's an efficient use of GPU power, and that won't stand long term.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Performance/quality considerations are a great culler of rendering techniques. We need to think about efficient raytracing.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO NOT&lt;/b&gt; - Focus on the "wrong" things. Specular reflections don't matter much. Perceptually they don't! Specular highlights, in general, are a strong indicator of shape and material in objects, but we are not good at spotting errors in the lighting environment that generates them. That's why cubemaps work so well. In fact, even for shiny floors and walls (planar mirrors) with objects near or in contact with them, we are fooled most of the times by relatively simple cheats. We see errors in screen-space reflections only because some times they fail catastrophically, and we're talking there about techniques that take fractions of milliseconds to compute. And reflections with raytracing are both too simple and too complex. Too simple, because they are an easy case of raytracing as rays tend to be very coherent. And too complex, because they require evaluating surface shading, which is hard to do in most engines outside screen-space and is slow as triggering different shaders with real-time raytracing is really not hardware friendly.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-OWzBpWVjWiE/XKBbWNpLrvI/AAAAAAAABss/apDpMU9HqvEz_t8A_yeKIvcWlMIDmjnPgCLcBGAs/s1600/wolf_car_new.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="720" data-original-width="1280" height="180" src="https://2.bp.blogspot.com/-OWzBpWVjWiE/XKBbWNpLrvI/AAAAAAAABss/apDpMU9HqvEz_t8A_yeKIvcWlMIDmjnPgCLcBGAs/s320/wolf_car_new.png" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Intel's demo: raytraced Wolfenstein (http://www.wolfrt.de/). Circa 2010.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;&lt;br /&gt;DO&lt;/b&gt; - Think about occlusion on the other hand. It's much more interesting, can be more hardware friendly, definitely is more engine friendly and most importantly it's likely to have a bigger visual impact. Correct shadows from area lights, but also correctly occluding indirect lighting, both specular and diffuse.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO NOT&lt;/b&gt; - Think that denoising will save the day. In the near future, for real-time rendering, it most likely will not. In fact in general denoising (even simple blurring that we sometimes already employ) can lift noise from high frequencies to lower ones, which under animation makes for worse artifacts.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO&lt;/b&gt; - Invest in caching and temporal accumulation ideas. Beyond screen-space. These will likely be more effective, and useful for a wide variety of effects. Also, do think about finer-grained solutions to launch work / update caches / update on demand. For this, real-time raytracing might help indirectly, because it needs in order to be performant the ability to launch shader work from other shaders. That general ability, if implemented in hardware, and exposed to programmers, could be useful in general, and it's one of the most interesting things to think about when we think of hardware raytracing.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO NOT&lt;/b&gt; - Make the wrong comparisons! RTX on / RTX off tells a lie, because what we can't see with "RTX off" is what the game could look like if we allocated all the power that RTX needs to pushing conventional techniques or even simply more assets. There are a lot of techniques we don't use today because we don't think they are on the right side of the quality/performance equation. We could use them, but we prefer to push more assets instead.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you want to be persuasive about raytracing, proper comparisons should be made. And proper comparisons should also take into account that rasterization without shading (visibility only) leaves compute units available for other work to be done in parallel.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;RTX hardware isn't free either! It costs chip area, even if you don't use it, but there's nothing we can do about that...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO NOT&lt;/b&gt; - Assume that scene complexity is fixed. This is a corollary of the previous point, but we should always think at the very least, for overall visual impact, if simply pushing more stuff is better than pushing a given particular idea for "shinier" stuff, because scene complexity is far from having "peaked".&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-U-DDrk13QCg/XKBdWEiSg_I/AAAAAAAABs8/y8gS-w6y1s4eLk-U6Nfn1mk0U_A1mEdIwCLcBGAs/s1600/Avengers_marvels_framestor_onelight.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="788" data-original-width="1400" height="180" src="https://1.bp.blogspot.com/-U-DDrk13QCg/XKBdWEiSg_I/AAAAAAAABs8/y8gS-w6y1s4eLk-U6Nfn1mk0U_A1mEdIwCLcBGAs/s320/Avengers_marvels_framestor_onelight.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Offline rendering might (might!) be essentially complexity-agnostic today.&lt;br /&gt;Real-time, not quite. (frame from Avengers Infinity War)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;&lt;br /&gt;DO&lt;/b&gt; - Think about cases where raytracing could outperform rasterization at its own game. This is hard, because raytracing likely will always have a quite high cost, both because of the memory traffic that is required to traverse the spatial subdivision structures, and because it uses the compute units, while the rasterizer is a small piece of hardware that can operate in parallel. But, that said, raytracing could win in a couple of ways.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;First, because it's much more fine-grained. For example, refreshing very small areas in a shadow map could perhaps be faster with a raytracer. Another way to say this is that there are certain cases where the number of pixels we need visibility for is much smaller than the number of primitives and vertices we'd need to traverse in a rasterizer.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The second thing to think about is how raytraced visibility goes wide, using the compute units and thus, the entire GPU. The rasterizer, on the other hand, can often be the bottleneck. And even if in many cases we can overlap other work to keep the GPU busy, that is not true in all cases!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO&lt;/b&gt; - Think about engineering costs if you want the technology to be used now. It's true that programmer's pain doesn't matter. But at the moment RTX covers a tiny slice of the market. Programmers could find their pain in completing more important tasks... Corollary: think about fallback techniques. If we're moving an effect to RTX, how will we render it on GPUs that don't support it? Will it look very different? Will it make authoring more painful? That is something we generally can't afford.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In general, be brutally honest about costs and feasibility of solutions. This is a good rule in general, but it is especially true for an emerging technology. You don't want to burn developers with techniques that look good on paper, but fail to ship.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;DO&lt;/b&gt; - Establish collaborations. Real-time raytracing is probably not going to sell more copies of a game. And if it's not going to save costs and make authoring more effective, if we're talking about uses in the runtime (an exception could be for uses in the artist tools themselves, e.g. to aid lightmap baking and/or previewing). It currently targets only a small audience, and you'll gain nothing by jumping on this too early.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, you probably should not pull your smartest R&amp;amp;D engineers from whatever they're doing to jump on this unless you have some very persuasive outside incentives... If not, you'll likely won't have many people to do raytracing related things.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Thus, you should probably see if you can leverage collaborations with external research groups...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/UbR5X_0hIMk" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/415197100506216932/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=415197100506216932" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/415197100506216932" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/415197100506216932" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/UbR5X_0hIMk/an-unbiased-look-at-real-time-raytracing.html" title="An unbiased look at real-time raytracing" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://4.bp.blogspot.com/-p6jIRwLASco/XKBcY32YMBI/AAAAAAAABs0/H_ofLYbnwrUoweNnGwJ2Wb96qx0e7Gp2gCLcBGAs/s72-c/Call-of-Duty-Infinite-Warfare.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/03/an-unbiased-look-at-real-time-raytracing.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-2941380308344683523</id><published>2019-03-24T17:48:00.000-07:00</published><updated>2019-03-24T18:01:47.279-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Programming tutorials" /><title type="text">GDC 2019 - Everyday (shallow) ML</title><content type="html">&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Here are the slides for my talk in the GDC 2019 Machine Learning tutorial day.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Lots of slides, many more than what was shown on stage...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-WSR6qvRw2fU/XJgmqDl6D9I/AAAAAAAABsM/r3AMZO423twdM3htpmEMv7_Q1MUyT5g7ACLcBGAs/s1600/Screen%2BShot%2B2019-03-24%2Bat%2B5.53.14%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="793" data-original-width="1600" height="158" src="https://2.bp.blogspot.com/-WSR6qvRw2fU/XJgmqDl6D9I/AAAAAAAABsM/r3AMZO423twdM3htpmEMv7_Q1MUyT5g7ACLcBGAs/s320/Screen%2BShot%2B2019-03-24%2Bat%2B5.53.14%2BPM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Plus!&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Code for my &lt;b&gt;"nvgPrint"&lt;/b&gt;, a nanoVG/OpenGL c++ library for super simple real-time, asynchronous plotting in C++.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Grab it till quantities last!&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;--&amp;nbsp;&lt;a href="https://www.dropbox.com/s/ft2wbncuxor9nfb/GDC2019-ShallowML-plus-nvgPrint.zip?dl=0"&gt;Download it all here!&lt;/a&gt;&amp;nbsp;--&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/xJs7AjFFlrU" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/2941380308344683523/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=2941380308344683523" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/2941380308344683523" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/2941380308344683523" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/xJs7AjFFlrU/gdc-2019-everyday-shallow-ml.html" title="GDC 2019 - Everyday (shallow) ML" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://2.bp.blogspot.com/-WSR6qvRw2fU/XJgmqDl6D9I/AAAAAAAABsM/r3AMZO423twdM3htpmEMv7_Q1MUyT5g7ACLcBGAs/s72-c/Screen%2BShot%2B2019-03-24%2Bat%2B5.53.14%2BPM.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/03/gdc-2019-everyday-shallow-ml.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-937459851244700400</id><published>2019-03-11T18:49:00.001-07:00</published><updated>2019-03-12T19:41:22.017-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Graphic rants" /><title type="text">Rendering doesn’t matter anymore?</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Apologies. I wanted to resist the clickbait title, but I couldn’t find anything much better...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And no, I’m not renouncing my ways as a rendering engineer, I’m not going to work on build systems or anything like that. Nor do I believe that real-time &lt;a href="http://c0de517e.blogspot.com/2013/12/shit-people-say-graphics-have-peaked.html"&gt;rendering has “peaked”&lt;/a&gt;&amp;nbsp;or that our pace and progress in image quality has seen slowdowns. There is still a ton of work to do, and the difference between good and bad graphics can be dramatic...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But what I want to talk about a bit more (I mentioned this &lt;a href="http://c0de517e.blogspot.com/2019/03/what-i-learned-at-activision.html"&gt;in my previous post&lt;/a&gt;) is what matters, and how do we decide that. ROI, perhaps an ugly term, but it gets the job done.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;From product.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I’ve spent most of my now thirteen-old professional career in videogames working on production teams. A.k.a. making games. And lots of games I’ve helped making, I actually average a game per year, even when I was in production, which is quite unusual I guess.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now, when you are in production, things are relatively simple. Ok, no, they are everything but. What I mean is that is straightforward... Ok, maybe still not the best description.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;You start with some sort of rough plan. Hopefully, the creative persons have ideas, they present them to you, and you start making a sketch. What are the risks, things to experiment first, what are tasks that are more well known.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Unless you are bootstrapping an engine from scratch or doing major tech changes, mostly you’ll be asked for a ton of features, things people want. An unreasonable amount of them. Ludicrous.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So you go on and prioritize, estimate, shuffle things until you have some plan that makes sense. It won’t, but we know that, we start working and as things change, we re-adjust that plan, kicking features off the list and moving thinks up the priority...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So you get a gigantic amount of work to do, you get on the ride and off you go, fighting fires as they happen, course-adjusting and bracing yourself for the landing. For the most part. There are some other skills involved here and there, but mostly it’s about steering this huge ship that has both a ton of momentum and the worst controls ever.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Naturally, there isn’t much time to think about philosophical questions and other bullshit like that. In fact, plenty of times the truth is that you start losing control over the priorities, even.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;That neat idea of reshuffling your list becomes more like a rough sort, and you don’t even necessarily have time or energy to understand why people who are asking for things need these things...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://2.bp.blogspot.com/-Go3KCgxWIGo/XIcRjFA8YZI/AAAAAAAABrM/TLo_jw7NWxck_Jw4-4M3dNRGW-pCd7rKACLcBGAs/s1600/resident_evil_2_licker_render1.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="1046" data-original-width="1600" height="209" src="https://2.bp.blogspot.com/-Go3KCgxWIGo/XIcRjFA8YZI/AAAAAAAABrM/TLo_jw7NWxck_Jw4-4M3dNRGW-pCd7rKACLcBGAs/s320/resident_evil_2_licker_render1.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Production, on a good day.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you go around and look at big enough productions, one pattern you will notice is that people start working without knowing the “why” of things. Which leads, no need to say, to quite sub-optimal solutions. But the production beast is an organic one, it’s unclean, it’s made by people and opinions and blood and sweat. &lt;a href="http://c0de517e.blogspot.com/2017/10/the-curse-of-success-why-nothing-great.html"&gt;Engineering is the art of handling all that and still shipping a great game&lt;/a&gt;, and it looks nothing like any idealized version of beauty some programmers might hold dear.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;To technology.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Then you move to some cushy job in some central technology department, right? And now you have a problem. You have time, at least, sometimes.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;You might want to work on things that help, or have a chance to help, more than a single product. If you do R&amp;amp;D, you will be doing things that have more risks and unknowns. In general, you aren’t so strongly tied to that list of features people are shuffling around day after day. Even when you are doing the only reasonable thing, which is to be attached to a product, you are not that close, you can’t be as you’re not part of the core team.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is an opportunity because you can have some time and freedom, but also a huge risk because, in the end, the product is all that matters. Being singularly focused on production is not necessarily the best strategy for great products, because that monster swallows and consumes everything, focused on getting “more”, but straying away too much is the road to masturbatory efforts that can be irrelevant at best, dangerous most often.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So, you start thinking of ROI. What should I do? What’s best? You probably have things from multiple teams that could be done, and you have other things that you can persuade teams they should want...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In my case, being a rendering person, the question boils down to, what matters in rendering? How do I estimate how much a thing weights? When you move from “vfx artists want this particle trail thing and you have to do it tomorrow” to look at things with an iota of horizon, how do you decide?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Rendering doesn’t matter...&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;...like it used to. Once upon a time, rendering made the games. Even more than that, entire genres. Doom, of course, is the obvious example, but there are many. The CD-ROM FMV game era. The hardware sprite and scrolling background fuelled platformers, shooters, and so on.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-eIKJ31Jeze0/XIcSg5YOjbI/AAAAAAAABrU/X9UxkLXV3EYdtrFqhR_L3-7XEIRfe44ggCLcBGAs/s1600/440176329_f9470dbd70_o-640x482.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="482" data-original-width="640" height="241" src="https://1.bp.blogspot.com/-eIKJ31Jeze0/XIcSg5YOjbI/AAAAAAAABrU/X9UxkLXV3EYdtrFqhR_L3-7XEIRfe44ggCLcBGAs/s320/440176329_f9470dbd70_o-640x482.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Chances are your engine won't create the next big videogame genre.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Then that ended, we arrived at a point where we had enough computing hardware that videogame genres are not defined by technology anymore. Perhaps this will change with VR/AR but for now let’s ignore them (they’re not hard to ignore either, these days).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But we still had a period where technology could be product defining. Call of Duty running at 60fps on ps3 and 360, for example, was quite unique, and that technical characteristic was instrumental to the product. Today doing a 60fps title is the norm, to ship at 30 is almost a gutsy move...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Rendering is thus restricted in the narrower field of aesthetics. It’s just... graphics. Sad if you think of that, right?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Well of course not! We have an ace up our sleeves, see. It’s true that technology is not genre-defining anymore, but AAA productions are insanely graphic-intensive. We love our computer graphics, and the amount of people dedicated to their care and feed is enormous. Everything is good again in the universe, rendering engineering reigns supreme.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So this is the first order of attack of the ROI problem. There are lots of things that are measurable in people and hours and dollars. These, pretty much, will automatically win over anything else. Let’s put them in the bucket of “really important stuff”.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;By the way, when I say “measurable”, I don’t mean you can measure them or that you will. You most definitely will not! What I mean is that you could think of them and have a strong feeling they relate to said measurable quantities...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Chasing shiny things.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So I said you can bucket things. Things that are required to ship the game first. Things that help people second. Third, you get all your shiny things, which are, incidentally today what you could call graphics R&amp;amp;D. A good part of the stuff I do!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Should we stop doing that? No, of course I will never admit to that, c'mon.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But more seriously, it obviously can’t be that simple. There will never be an end to thing that “help people”, even if the best possible scenario you can still make progress, nothing is ever perfect. So obviously you will reach a point where some rendering effect trumps a tiny pipeline improvement, at least that is a given!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Moreover, though it is not that computer-graphic techniques, even when they are purely visual, do not help content production. We could point at the obvious trend of physically-based rendering, and how that helped (after a lot of growing pains everyone had to go through) to curb the explosion of hacks and ad-hoc controls that we had to create assets before.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But even smaller things can help artists to get more freedom, say even things like antialiasing, for example, might mean that geometry and other sources of discontinuity can be use more leniently, without transforming the frame in an undecipherable mess.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Not only there are diminishing returns for productivity improvements as for any other things, but the split point between features and productivity is often tricky. We definitely do not wait till everything is perfect before pushing more features out, the production monster wants to be fed.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And we shall never, ever discount the gigantic effects of familiarity, the other big scary monster. It is not worth sacrificing everything to it, but we should respect it. To use a technique well, to master it takes a long time. Changing things, even if entirely for the better, with no drawbacks whatsoever, still implies that we need to pay the (often huge) costs of loss of familiarity.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So? How do you decide? How do you measure? Then again. You do not.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I hope he won’t mind me saying, this is one the paths to enlightenment forced on my by Christer, my former boss. How to put this. He has his tricks, not quite koans... So I learned that when he wasn’t persuaded about the opportunity of something, he would go and ask me to put things in more systematic ways, to try to narrow down that ever elusive “ROI”.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Then one time I think we were even arguing about how he could decide that a given initiative he was supporting would, in the end, be beneficial or the better course compared to another alternative. And he slipped and say that we don’t necessarily have to quantify this ROI thing! Of course, be both immediately caught that, even if we were over the phone he could almost sense my smile, but being the clever man he is, he managed to still be right despite the apparent idiosyncrasy...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The lesson is that we want to keep in mind that ROI thing. Not that we need to necessarily optimize for it and spend too much time chasing it. But we definitely need to keep it in mind, be always scared of the risk of doing irrelevant, or worse, damaging things. Keep ourselves accountable.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;It’s the question, not the answer.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;You might be excused to have thought that I put the question mark in the title, even if it isn’t in the form of a question, because of my poor English. But no, it was a clever thing you see, I actually went back halfway into writing this, and thought about it, and finally changed the punctuation. Only after deciding I would also write this, and feel so meta-clever. And again and ok, let’s stop this recursive loop...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And if I was really good at this, I could have jumped directly to the point and spared you all the blabbing, but I have time on my hands these days so. You’re welcome.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;In the end, it is true that certain games should even chase diminishing returns because that’s what you do when you’re up enough. And it’s totally true that you can’t really quantify ROI anyway, so often times you should just do what you want. If someone really thinks something is important, and it’s not offensively bad, there should be space for that. In other words, because we know we are bad at ROI, we should realize that to chase it we should not chase it all the time (surprisingly, &lt;a href="https://www.cs.swarthmore.edu/~meeden/DevelopmentalRobotics/lehman_ecj11.pdf"&gt;this is even a concept in optimization algorithms&lt;/a&gt;, by the way).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But! The questions are interesting.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;How important shiny things are? Is there a point when state of the art techniques become so complex that they are unfriendly both to either content or programmers integrating/iterating, so much so that they will be used sub-optimally? And simpler solutions would have been actually better instead?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Think for example of something perfectly physically accurate, that can produce perfect images, but that behaves poorly when the inputs are not exact. This is not even such a wild scenario, you can see plenty of PBR games that would have been most likely best off without copy-and-pasting the GGX formulas, just because they now go nuclear with specular and aliasing...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="https://3.bp.blogspot.com/-caC9SGRJiYg/XIcWJXtsmNI/AAAAAAAABro/pgsGu0tEkcsNSdUIPXVAUAiHJmlV08JJgCLcBGAs/s1600/bloodborne.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" data-original-height="676" data-original-width="1600" height="135" src="https://3.bp.blogspot.com/-caC9SGRJiYg/XIcWJXtsmNI/AAAAAAAABro/pgsGu0tEkcsNSdUIPXVAUAiHJmlV08JJgCLcBGAs/s320/bloodborne.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Bloodborne might not be the pinnacle of RTR, but it is imaginative...&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Even more interesting. &lt;b&gt;Is there a point where the attention to graphical perfection actually produces worse graphics? &lt;/b&gt;Could it be, for example, that the efforts required to create worlds that are perfect, truly great quality-wise, comes in the way of creating worlds that have the variety, the artistry, the iteration and look that in the end are most often correlated to what people think of great graphics?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Again. In the end, we should remember that we serve the product. Not photorealism, per se, but the product. We do believe that photorealism is a great tool to create games, and I won’t question that. But still we have to remember that photorealism is not the goal, technology per se is useless. It’s the product, that we work for.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And if I had to guess, I'd say in most products today both end-user image quality and in most cases, performance, are bottlenecked by asset production, not the lack of whatever latest cool rendering trick. In particular by:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The sheer ability of authoring assets. &lt;b&gt;Quantity / Variety.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The ability of iterating on assets. &lt;b&gt;Quality.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;The complexity of technical issues linked to art assets. Which in practice yield sub-optimal decision. &lt;b&gt;Performance &amp;amp; Quality.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: left;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And the very fixed granularity of assets and their editing tools, the overall inability&amp;nbsp;of performing large, sweeping art changes. The more an environment is "dressed" (authored) the more it hardens and resist change. &lt;b&gt;Art direction. &lt;/b&gt;&lt;i&gt;(and perhaps this also causes an over-reliance on some of the few tools that can do said sweeping changes, namely, post-effects)&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b style="text-decoration-line: underline;"&gt;N.B.&lt;/b&gt; All these &lt;b&gt;are&lt;/b&gt; &lt;b&gt;rendering&lt;/b&gt; &lt;b&gt;problems&lt;/b&gt;! Implementation, research, even hardware innovation. Despite the title, the argument here is not that rendering research in videogames is a waste of time, or beyond diminishing returns. Au contraire! It's more vital than ever, in our times of enormous asset pressure. But we have to think hard about what is useful to the end product.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;To make a stupid example. A very smart system to automatically generate rendering meshes from artist data (LODs, materials, instances etc) is probably orders of magnitude more important than say, a post-effect...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/2lIR99aY3QQ" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/937459851244700400/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=937459851244700400" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/937459851244700400" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/937459851244700400" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/2lIR99aY3QQ/rendering-doesnt-matter-anymore.html" title="Rendering doesn’t matter anymore?" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://2.bp.blogspot.com/-Go3KCgxWIGo/XIcRjFA8YZI/AAAAAAAABrM/TLo_jw7NWxck_Jw4-4M3dNRGW-pCd7rKACLcBGAs/s72-c/resident_evil_2_licker_render1.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/03/rendering-doesnt-matter-anymore.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-4612953230969420516</id><published>2019-03-01T12:07:00.004-08:00</published><updated>2019-04-01T18:56:44.281-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Announcements" /><title type="text">What I learned at Activision.</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Today is my last day at Activision.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Not quite the end of an era, but my six-year stint at Activision|Blizzard|King has been by far the longest I’ve so far worked for a given company, and I wanted to write something about it.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I don’t usually do things like this, but long gone are the times where I pretended this blog could stay anonymous. Also, I do think that we should really talk more about our experiences with teams and companies, be more open. I’ve never done that on this blog (albeit I’ve always been happy to chat about anything in person), so let me quickly fix that.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-gnjRWzX4ZAE/XHr2OTSPnOI/AAAAAAAABqg/C2y_Ys0RGpEGWA_qVE-0l-u7jjlZObA7QCLcBGAs/s1600/hqdefault.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="360" data-original-width="480" height="240" src="https://1.bp.blogspot.com/-gnjRWzX4ZAE/XHr2OTSPnOI/AAAAAAAABqg/C2y_Ys0RGpEGWA_qVE-0l-u7jjlZObA7QCLcBGAs/s320/hqdefault.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This has been my, to be honest quite lucky, video-game career trajectory:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- &lt;b&gt;Milestone &lt;/b&gt;(Italy, racing games). The indie company. Here, we were a family. And as most families, often loud and dysfunctional, sometimes fighting, but in the end, for me, it was always fair and always fun. We were pioneers, not because we were necessarily doing state-of-the-art things, but because nobody around us knew better, we had to figure out everything on our own. Eventually, that became a limiting factor for my own growth, but it was great to start there.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- &lt;b&gt;Electronic Arts&lt;/b&gt; (Canada, Fight Night team). My team at EAC was probably the best example of a well-organized game studio. Everything was neat, productions went smoothly, and we created some quite kick-ass graphics as well. EA, and probably even more so EA Sports is truly a game developer. And by that I mean that it takes part in the game development, we had shared guidelines, procedures, technologies, resources. Of course, each team could still have plenty of degrees of freedom to custom-fit the EA way to their specific reality, but you always felt part of a bigger ecosystem and had access to this gigantic wealth of knowledge and people across the globe. Fun times!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- &lt;b&gt;Relic &lt;/b&gt;(Space Marines, mostly). Relic had much more of the “indie” feel of my Milestone days. Not quite the same, we were a big team in an even bigger studio, part of a publicly traded company, but we were also exploring uncharted territory (for us), with very smart people and lots of last-minute hacking. I’m proud of what we achieved, it was fun and I loved the spirit we had in our rendering/optimization corner of the office. We did perhaps chew a bit more than we could though, doing something unprecedented for the studio. THQ was also failing fast, which didn’t help.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- &lt;b&gt;Capcom&lt;/b&gt; (Vancouver). This studio is now closed. It was an unlucky choice for me, our project was riddled with all kinds of problems, in all possible dimensions. Eventually, I was laid off, then the project was canceled, and a few years later, the studio went down. It was a very stressful time, day after day I was quite unhappy. Still, I have to say I met some excellent people and I’m glad that I now know them!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;- And now, &lt;b&gt;Activision&lt;/b&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It’s the people.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;One of the company mottos is “it’s the people”. I didn’t particularly think that these “values”, that all companies put forward, were particularly received in Activision’s case, at least when it came to Central Technology I always felt we didn’t pay much attention. But for me, it was the people, first and foremost.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Activision is the place where I found the smartest people around me, by far. And I’ve worked with very smart people, in great companies, but nothing touches this.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Now, I have to say, I have also a unique, very biased vantage point. Being a technical director in central technology means to interface mostly with the most senior technical people and the studio leadership. I was not in production and not working with a single studio. A different ballgame.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But still, I can’t even make list here! Ok, to give you a picture. ACME: Michael, Wade, Paul, Aki, I don’t think I can in a few words express the brilliance of these individuals. Paul’s technical abilities are unbeatable. He knows everything and can do anything. Wade is worse, infuriatingly smart, and any time I find the tiniest flaw in Michael’s life I have a sigh of relief (my girlfriend says he’s my work husband, even if I do have several man crushes to be honest, yes, there is a list). Aki started as an intern and was recently hired full time. I think he is already a better programmer than I am, and I definitely do not suffer from impostor’s syndrome...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Peter-Pike Sloan’s research team is the best R&amp;amp;D team I’ve ever seen, with people like Michal Iwanicki, Josiah Manson, Ari... But then again, I literally can’t make a list and I’m talking only about the rendering people, no actually, the rendering people I know best, even! My home team at Radical, which was a great studio in its own right, has been fantastic, Josh, Ryan, Tom, Peter, Andrew. CTN and that shadertoy genius of Paul Malin. And then the game teams. I mean, you can’t beat Drobot, can you? Jorge Jimenez! Dimitar Lazarov, Danny Chan, these are people who every project decide to completely change how Call of Duty renders things. Because why not, right? And of course, the people above me, Christer, whom I admired way before he landed at Activision but also Dave Cowling who hired me, and Andy our CTO who came to speak to us a year before he got hired, and even back then I thought he was an incredibly smart guy. And that's to speak just of the people in the Call of Duty orbit...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Truth is, if you know, you already know. If you don’t, it’s hard for me to tell you, so let’s just cut it short. Amazing people.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Not just smart.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, so we have smart people, blah blah. What gives, are you just showing off or is there a point to this? There is actually.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And the lesson is not even “how to hire smart people” or that you should hire smart people. To be honest, I don’t think we have a way, even if Christer (and myself even) did put a lot of time and effort thinking about the process, you can only affect some multipliers I think. Mostly, teams seem to me to build up from the gravitational pull, around a given company culture. Once you have a given number of people that value given things, they tend to grab other people who also share the same core values, even if you want to have different points of view.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;No, what Activision really taught me is that smart people don’t really matter, per se. Brilliance alone doesn’t mean that good things will happen to your products, actually, it can be dangerous because it can correlate with ego, especially if you haven’t reached the highest level of enlightenment yet.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;What’s interesting about this particular bunch of smart people, is that they are also what actors call “grounded”. There is little bullshit going around. Tech is not made for tech’s sake. We don’t even have an engine, in a time where even if you really just have a game, one game, one codebase, you would call silly codenames each library and each little bit of tech, and maybe put some big splash screens before your main titles. Made with.. xyz.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This is actually a lesson that originates from the early days of Call of Duty at IW. From what I’m told, IW never named their engine, because any time you name something it becomes a bit more of a thing, and you start working for it. And they were a studio making games, the game is the thing. Nothing else.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;This meshes just so well with the Activision way. So many people taught me so many lessons here, but the kind of fil rouge I found is this attention to what matters, when especially for us, rendering people, is so annoyingly easy to get distracted, quite literally, by the cool shiny thing that’s in the hype at the moment.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;You might even call it ROI, I sometimes do even if perhaps I should not, it sounds “bad”. But you have to be aware of what matters, what are the trade-offs, what should you spend your time on. Which doesn’t mean you are a drone doing complex math in Excel, quite the contrary, there is definitely space for doing things because you want to, and you like to.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Thing is, we cannot really compute the ROI of our tech stuff, especially for a thing that is so far from the product sales as rendering code is. But, we can be aware of these things. Even just thinking about them a bit makes a big difference.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Peter-Pike could be another example. I said I’ve never seen a better R&amp;amp;D team. Does it mean that there aren’t other teams that do research as good, or maybe even “better” sometimes? Of course, there are! The difference though is impact. Not only almost all our R&amp;amp;D work shipped on the given year’s title, but it’s also focused on what matters. Either help ship the title, technology that is needed to do what they want to do, or help the teams work better, technology to help productivity. Often both.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And this then again reflects also in the people. Yes, Peter-Pike is an accomplished academic, and his team does real research, meaning, things we don’t know how or even if we will solve. But he’s also incredibly pragmatic. He is hands-on coding all the times. More than I am. Better than I am!&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Activision and Electronic Arts...&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;...couldn’t be more different, contrary to the popular belief that lumps all the three-four big publishers into the same AAA bucket.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And that is also what was interesting and life-changing. You see, I truly love them both. They are great in their own right and the results speak for themselves. They both have great people, I don’t even need to tell you that.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But they work so differently.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;EA as I said, feels like a big game developer, a community. Sharing is one of the key values, finding the best ways of doing things, leveraging their size. It sounds very reasonable, and it is.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But Activision is almost the opposite. It feels like a publisher, who owns a number of internal studios. The studios, of course, are accountable to the publisher, but they are independent, that is key, core value. Central technology is not there to tell people how to do things, but as a publisher-side resource to help if possible. The teams are incredibly strong on their own, even in terms of R&amp;amp;D. And, at least from my vantage point, they get to call all their own shots. Which is again very reasonable, if you tell people they are accountable they should definitely have the freedom of choice too.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And yet again. Valuing independence versus valuing a shared community, the opposite viewpoints end up in practice creating results that are not that dissimilar. How comes?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you’ve been doing this for a while, it won’t be even surprising. The key is that we don’t really know what’s best. Companies and teams even technologies and products organize around given values, a cultural environment that was created probably when there were almost a handful of employees. And once you have these the truth is you can most often structure everything else around in a way that makes sense, that works.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We see this so often in code too. A handful of key decisions are made because of legacy or opinions. We’re going to be a deferred renderer. Well, now certain things are harder, others are easier. Certain stuff needs to happen early in the frame, other late, and you have certain bottlenecks and idle times, and you work from there, find smart ways to put work where the GPU is free, and shift techniques to remove bottlenecks and so on.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Which doesn't mean everything is ever perfect, mind you. We always have pain points and room for improvement, and different strategies yield different issues. To a degree, this is even lucky!&amp;nbsp; I don't make games, I help people and technology. The day Unity will solve all technical and organizational problems for game making is the day I'll be out of a job. At least in this industry...&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Ok, then why?&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you love all these companies. Why leave? What are you not telling...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Well.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I’m not too bright. And instead of keeping my great job, sometimes I venture into the unknown. But that’s a tale for another day...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://1.bp.blogspot.com/-VOHjRxz6tLQ/XHnTBhh8ASI/AAAAAAAABqU/j76VtJ12Lu8Hzf1NG3vCVixY73eSEp_2ACLcBGAs/s1600/atvi.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="809" data-original-width="1200" height="215" src="https://1.bp.blogspot.com/-VOHjRxz6tLQ/XHnTBhh8ASI/AAAAAAAABqU/j76VtJ12Lu8Hzf1NG3vCVixY73eSEp_2ACLcBGAs/s320/atvi.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/1csoZcOX_5s" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/4612953230969420516/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=4612953230969420516" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/4612953230969420516" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/4612953230969420516" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/1csoZcOX_5s/what-i-learned-at-activision.html" title="What I learned at Activision." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://1.bp.blogspot.com/-gnjRWzX4ZAE/XHr2OTSPnOI/AAAAAAAABqg/C2y_Ys0RGpEGWA_qVE-0l-u7jjlZObA7QCLcBGAs/s72-c/hqdefault.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/03/what-i-learned-at-activision.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-626896049449552397</id><published>2019-02-26T13:57:00.003-08:00</published><updated>2019-02-26T18:49:56.863-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Programming rants" /><title type="text">C++, it’s not you. It’s me.</title><content type="html">&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;How I learned not to worry and tolerate C++&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;If you follow the twitter-verse (ok, and you happen to be in the same small circle of grumpy gamedevs that forms my bubble) you might have noticed lately a rise of rage and sarcasm against C++ and the direction it's taking.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I don't want to post all the relevant bits, but the crux of the issue, for the lucky among you who don't do social media, is the growing disconnect between people woking on big, complex, performance-sensitive and often monolithic and legacy-ridden codebases that we find in game development, and the ideas of "modernity” of the C++ standard community.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Our use-case is perhaps peculiar. We maintain large codebases, with large teams, but we never did great at modularization. This is our fault, and I’m not sure why it happened. Maybe it’s a combination of factors, including certain platforms and compilers not working well with dynamic libraries, or performance concerns. But most likely, it’s also the product of a creative environment where experimentation is a necessity, planning is inherently hard and architecture work is often simply neglected due to other production pressures.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;The (AAA) gamedev use-case&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Whatever are the historical reasons, the reality is that we live in an environment where most often than not:&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We don’t care about the STL, not its performance improvements. We developed our own bespoke containers, both because we need very ad-hoc algorithms tuned to specific problem sizes, and because of design issues of the STL itself which made it impossible to use (e.g. its historical reluctance to play well with things like memory alignment).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We do care about all declinations of “performance”. Not only the final, all-optimizations enabled, code generation, but also performance in debug builds, and compiler performance. Iteration times.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We care about being able to reason about code. Simplicity, not counted as lines of code, but as the ability to clearly understand what a line of code does. &amp;nbsp; We often would prefer verbose, even in the eyes of some more arcane code, to unpredictable code, where to understand the relation between what we wrote and what happens requires a lot of &lt;/span&gt;context&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;, of “global” information.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Given this scenario, it should be clear to see how most of the C++ additions since C++11 have gone in the “wrong” direction. They are typically not adding any expressive power for our use-cases, but instead, bring lots of complexity to an already almost impossible-to-master language. Complexity that also “trickles” down to tooling, compilers, compile times, debuggers and so on.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It’s hard to overstate how bad this chasm is growing, with some direction being truly infuriating, but let me just bring a concrete example. Take the modernization of STL containers, say r-value references, initializer lists and all the ecosystem around that. Clearly, a huge feature for C++, allowing even significant savings for certain uses of the STL. And what you would call “a zero cost abstraction” - if you don’t use it, you don’t see it. Everyone’s happy, right?&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Quite the contrary! The prime example of something that is entirely useless for people who already know about the cost of constructors, temporaries and the like, designed their code thinking of how to layout and transform bits, instead of higher level concepts sketched in a UML diagram.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Useless but dangerous, as these concepts increased the complexity of the language exponentially, to the point that very few can really claim to understand all their nuances, and yet are still hard to entirely avoid in projects made by lots of people, and where you do not necessarily even have the control of all the code due to external libraries.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And when all this humongous effort is taken on one side, features that would truly help performance sensitive large “system” programming, are still completely ignored. C++ still doesn’t have a “restrict” keyword. Strict aliasing is incredibly troublesome and even getting worse with certain proposals. Threads and memory alignment were implemented first (and arguably better) in the good old C.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We still don’t have vector types, not to mention fancier features like the ability of “transposing” the memory layout of arrays of structures (into SOAs or AOSOA and so on). We don’t have anything to help tooling, or compile times, like standardized reflection, serialization or proper modules. And we keep adding metaprogramming (templates) features before tacking complexity and usability issues (e.g. concepts, that now are scheduled to be in C++20).&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;What’s C++ anyway?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;I think part of the disconnect, and even anger in the community, is due to a misinterpretation of what C++ is and always has been.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;There is this myth that C++ is a low-level, high-performance/system programming language. It’s false, and it has always been false.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Clearly, a language that didn’t bother until recently to implement threads, is not a language for high-performance anything. There is nothing in C++ that concerns with system programming either, that is the C part of it, really. And so on and so forth, the more you look the more evident that truth is. Even the ancient Fortran can say it’s more concerned with performance than C++. C++ is not ISPC, nor Cuda. It doesn’t come with algorithms and data structure for low-latency, constrained memory use-cases, neither does care about large-scale data cases. Even python can be seen as a better language for high-performance computation, due to its ability to quickly implement embedded-DSLs. Nowadays, a lot of high-performance code leverages specialized compilers that use are embedded in relatively high-level languages via reflection. None of that is possible in C++.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;C++ is a “zero cost abstraction” language. That part is true. But “zero cost” is not about performance. In fact, the guarantee that something won’t cost you anything when it’s not used doesn’t really mean that it will be fast when you do use it! What it gives, instead, is peace-of-mind. Bjarne said, do you like C? And its ecosystem? Great! Use this one, I guarantee I won’t screw with C, and if you like anything else I added, you get to use it.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And don’t get me wrong. This is genius. And a fundamental lesson that so many other languages still today don’t understand. Making a nice language is the easy part. If you’re even just a tourist of computer languages, have been exposed with concepts from veterans like Lisp and ML and so on, it’s not that hard to come up with a perfectly pleasant little language. And in fact, we have so, so many of them today. The hard part is selling such language! And if you don’t have a community with a strong need that nobody but you serve, that means you have to persuade people to hop over from whatever what they’re currently using. That is almost impossible.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Bjarne understood that the ecosystem is what matters most and C++ succeeded by being a drop-in replacement for C. Unfortunately now C++ is so complex, that creating a new language that seamlessly can work and replace it is a tall order, but it would also be an incredibly powerful tool for adoption.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;b&gt;Why things changed and what can we do about it?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Bjarne got marketing right, he probably understood people more than languages, which is not an insult, to the contrary! People are all that matters.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But if this is the premise, it wouldn’t even be surprising that C++ is drifting away from systems programming, from what C programmers care about. Nowadays, these use-cases are a minority.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;It is not unreasonable, from that point of view, to now try to appease to the cool kids writing web stuff. People who might be using python, or java, or go and so on. Programmers who are accustomed to working fast, gluing together frameworks and libraries more than they write any bespoke algorithm and data structure. In fact, when you think about it, adding OO to C was just what was trendiest at the time. It was a hype and marketing based decision, not really a smart one, as we now maybe see more clearly as the OO hype dissipates.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;But I don’t even think it’s necessarily a conscious design decision. This language is huge today. Its community its huge, and it decided to go the way of the design by committee. Should you never do that? In my circles, the answer is definitely no, design by committee is the death of technology. But let’s present a more positive way of looking at it.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;We know that democracy has a cost, a huge cost. It’s definitely not the most efficient way of governing, nor it produces the most brilliant decisions. It can be in fact, incredibly dumb. This is not news, even in the Roman Republic there were provisions for senators to elect a dictator for a temporary period when strong leadership was deemed necessary. Of course, the risk is for a dictator to become a tyrant, as Romans learned. So, democracies trade efficiency for risk aversion, variance for mean.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And that is what C++ is today. It’s an old language, even if it wants to play cool, it fundamentally is in maintenance mode, listening to a lot of people with a lot of ideas and going in the direction of the majority, not of strong design decisions. Sometimes people argue that the solution would be to have more representation of certain use cases in the committee.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;Perhaps a bit would help, but for how much I do like politics, I really don’t care about language ones. If I could vote on something, I would vote to remove people from the committee, make it a smaller one, not a noisier and bigger one, even if the noise was to argue “in my favor”. I simply don’t think you can have a lot of compromise in technology without ending up with something mediocre.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;So? So we live with C++. Not because we like it, but because we need the ecosystem. The compilers, the IDEs, the language extensions, the low-level intrinsics, the legacy code. We restrict our usage to mostly C, and grab whatever rare new feature happens to integrate decently in our workflows. Maybe one day some new language will come, we already use bits and pieces of other ones when needed.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;And maybe someday someone will learn the real lesson Bjarne had to teach, and really kill it!&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;There is actually no reason for example that a language could not compile its own syntax in its files, but also allow to include C++ headers. Yes, you’d have to suffer and pay the pain of integrating a C++ compiler in whatever you come up with, and yes, your language would most probably just be something that expands to C++. Exactly how C++ started on top of C. But it’s unsexy, boring work, so most people will write yet another C-ish thing with a bit of ML in it on top of LLVM and call it a day...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif;"&gt;&lt;i&gt;Addendum: "Alex" asked an interesting question in the comments - why don't we make our own. I tried to answer that as well if you have a look below!&amp;nbsp;&lt;/i&gt;&lt;/span&gt;&lt;span class="emoji" style="background-position: 0px 0px; border: 0px; font-family: &amp;quot;apple color emoji&amp;quot; , &amp;quot;segoe ui emoji&amp;quot; , &amp;quot;noto color emoji&amp;quot; , &amp;quot;android emoji&amp;quot; , &amp;quot;emojisymbols&amp;quot; , &amp;quot;emojione mozilla&amp;quot; , &amp;quot;twemoji mozilla&amp;quot; , &amp;quot;segoe ui symbol&amp;quot;; font-size: 28px; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;"&gt;&#x1f447;&lt;/span&gt;&lt;span style="font-family: &amp;quot;helvetica neue&amp;quot;, helvetica, arial, sans-serif; font-size: 28px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/_jRgJ-fUR6I" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/626896049449552397/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=626896049449552397" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/626896049449552397" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/626896049449552397" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/_jRgJ-fUR6I/c-its-not-you-its-me.html" title="C++, it’s not you. It’s me." /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><thr:total>8</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2019/02/c-its-not-you-its-me.html</feedburner:origLink></entry><entry><id>tag:blogger.com,1999:blog-6950833531562942289.post-6771148207689937724</id><published>2018-12-08T18:47:00.001-08:00</published><updated>2019-02-26T13:58:28.362-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Rendering ideas" /><title type="text">Computer Graphics R&amp;D: An industry perspective</title><content type="html">&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;Slides from a recent talk I gave at the University of British Columbia.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;a href="https://www.dropbox.com/s/hc5kb8lvnxavbgn/CG_RD_slides_UBC.pdf?dl=0"&gt;Download here.&lt;/a&gt;&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/C0de517e/~4/s6f05iUaP5c" height="1" width="1" alt=""/&gt;</content><link rel="replies" type="application/atom+xml" href="http://c0de517e.blogspot.com/feeds/6771148207689937724/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6950833531562942289&amp;postID=6771148207689937724" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/6771148207689937724" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6950833531562942289/posts/default/6771148207689937724" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/C0de517e/~3/s6f05iUaP5c/computer-graphics-r-industry-perspective.html" title="Computer Graphics R&amp;D: An industry perspective" /><author><name>DEADC0DE</name><uri>http://www.blogger.com/profile/01477408942876127202</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="https://img1.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://c0de517e.blogspot.com/2018/12/computer-graphics-r-industry-perspective.html</feedburner:origLink></entry></feed>
