1"use strict";(self.webpackChunkjulesfouchy_github_io=self.webpackChunkjulesfouchy_github_io||[]).push([[4148],{4137:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>f});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),c=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return a.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},m=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),d=c(n),m=r,f=d["".concat(l,".").concat(m)]||d[m]||u[m]||o;return n?a.createElement(f,i(i({ref:t},p),{},{components:n})):a.createElement(f,i({ref:t},p))}));function f(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var o=n.length,i=new Array(o);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:r,i[1]=s;for(var c=2;c<o;c++)i[c]=n[c];return a.createElement.apply(null,i)}return a.createElement.apply(null,n)}m.displayName="MDXCreateElement"},1356:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var a=n(7462),r=(n(7294),n(4137));const o={title:"Golden White Noise"},i=void 0,s={permalink:"/blog/2021/03/19/golden-white-noise",source:"@site/blog/2021-03-19-golden-white-noise.md",title:"Golden White Noise",description:"Every person interested in rendering through fragment shaders has already come across a function like this to generate some white noise:",date:"2021-03-19T00:00:00.000Z",formattedDate:"March 19, 2021",tags:[],readingTime:1.525,hasTruncateMarker:!0,authors:[],frontMatter:{title:"Golden White Noise"}},l={authorsImageUrls:[]},c=[],p={toc:c},d="wrapper";
1function u(e){let{components:t,...o}=e;return(0,r.kt)(d,(0,a.Z)({},p,o,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"Every person interested in rendering through fragment shaders has already come across a function like this to generate some white noise:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-glsl"},"float random(vec2 uv) {\n return fract(sin(dot(uv ,vec2(12.9898,78.233))) * 43758.5453);\n}\n")),(0,r.kt)("p",null,"And I used it too, until someone pointed out a big problem to me: on her device my artworks were all messed up! And it turned\nout that many people were actually encountering the same problem. (You can see the artifacts in the comparison at the end)"),(0,r.kt)("p",null,"After a bit of investigation I tracked it down to the ",(0,r.kt)("inlineCode",{parentName:"p"},"random")," function that was not producing reliable results!\nIt turned out that depending on the precision of floats supported by your GPU the results were different. For low precision floats the quality of the distribution gets noticeably degraded."),(0,r.kt)("p",null,"And at this moment I remembered that guy at the bottom of a StackOverflow discussion claiming that his ",(0,r.kt)("inlineCode",{parentName:"p"},"Gold Noise")," was much better.\nAnd guess what, he was right! So thank you Dominic Cerisano for this lovely piece of code!"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-glsl"},"// Gold Noise \xa92015 [email protected]\n// - based on the Golden Ratio\n// - uniform normalized distribution\n// - fastest static noise generator function (also runs at low precision)\n\nfloat PHI = 1.61803398874989484820459; // \u03a6 = Golden Ratio \n\nfloat gold_noise(in vec2 xy, in float seed){\n return fract(tan(distance(xy*PHI, xy)*seed)*xy.x);\n}\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Alternatively, you can rely on ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/ashima/webgl-noise"},"https://github.com/ashima/webgl-noise")," for your Perlin / simplex / fractal / ",(0,r.kt)("em",{parentName:"p"},"etc.")," noise functions since they don't make use of these pseudorandom number generators.")),(0,r.kt)("p",null,"And here is a comparison of the visual results. ",(0,r.kt)("inlineCode",{parentName:"p"},"Gold Noise")," produces the same (artifact-free) results on all the GPUs I could test with:"),(0,r.kt)("table",null,(0,r.kt)("thead",{parentName:"table"},(0,r.kt)("tr",{parentName:"thead"},(0,r.kt)("th",{parentName:"tr",align:null}),(0,r.kt)("th",{parentName:"tr",align:null},"Classic white noise"),(0,r.kt)("th",{parentName:"tr",align:null},"Gold Noise"))),(0,r.kt)("tbody",{parentName:"table"},(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("strong",{parentName:"td"},"Potato GPU")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("img",{alt:"classic potato",src:n(7292).Z,width:"650",height:"650"})),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("img",{alt:"golden potato",src:n(9552).Z,width:"650",height:"650"}))),(0,r.kt)("tr",{parentName:"tbody"},(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("strong",{parentName:"td"},"Good GPU")),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("img",{alt:"classic good",src:n(6633).Z,width:"650",height:"650"})),(0,r.kt)("td",{parentName:"tr",align:null},(0,r.kt)("img",{alt:"golden good",src:n(6878).Z,width:"650",height:"650"}))))),(0,r.kt)("admonition",{title:"Links",type:"info"},(0,r.kt)("p",{parentName:"admonition"},(0,r.kt)("a",{parentName:"p",href:"https://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl"},(0,r.kt)("em",{parentName:"a"},"The corresponding StackOverflow discussion")),(0,r.kt)("br",null),"\n",(0,r.kt)("a",{parentName:"p",href:"https://www.shadertoy.com/view/fsf3DN"},(0,r.kt)("em",{parentName:"a"},"A live comparison of the different types of white noise")))))}u.isMDXComponent=!0},6633:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/classic_good-2ca390608a6fb40f51a968da71ee716f.png"},7292:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/classic_potato-132779f4f081fbd883fdc61b5da57c42.png"},6878:(e,t,n)=>{n.d(t,{Z:()=>a});
1const a=n.p+"assets/images/golden_good-89ce89a2396dca3188420e62ec52cb68.png"},9552:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/golden_potato-6133e3bbe78d14874c7d00fbe65c85aa.png"}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.