main.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. import * as THREE from 'https://cdn.skypack.dev/[email protected]';
  2. class CloudGeneratorAtlas {
  3. constructor() {
  4. }
  5. async init_(threejs) {
  6. this.create_();
  7. this.onLoad = () => {};
  8. this.threejs_ = threejs;
  9. const header = await fetch('./shaders/header.glsl');
  10. const common = await fetch('./shaders/common.glsl');
  11. const oklab = await fetch('./shaders/oklab.glsl');
  12. const blends = await fetch('./shaders/blend-modes.glsl');
  13. const noise = await fetch('./shaders/noise.glsl');
  14. const vsh = await fetch('./shaders/vertex-shader.glsl');
  15. const fsh = await fetch('./shaders/generator-shader.glsl');
  16. const material = new THREE.ShaderMaterial({
  17. uniforms: {
  18. zLevel: { value: 0.0 },
  19. numCells: { value: 2.0 },
  20. },
  21. vertexShader: await vsh.text(),
  22. fragmentShader: (
  23. await header.text() + '\n' +
  24. await oklab.text() + '\n' +
  25. await common.text() + '\n' +
  26. await blends.text() + '\n' +
  27. await noise.text() + '\n' +
  28. await fsh.text())
  29. });
  30. this.material_ = material;
  31. this.scene_ = new THREE.Scene();
  32. this.camera_ = new THREE.OrthographicCamera(0, 1, 1, 0, 0.1, 1000);
  33. this.camera_.position.set(0, 0, 1);
  34. const geometry = new THREE.PlaneGeometry(1, 1);
  35. const plane = new THREE.Mesh(geometry, material);
  36. plane.position.set(0.5, 0.5, 0);
  37. this.scene_.add(plane);
  38. this.resolution_ = 32;
  39. this.rt_ = new THREE.WebGLRenderTarget(this.resolution_, this.resolution_);
  40. }
  41. create_() {
  42. this.manager_ = new THREE.LoadingManager();
  43. this.loader_ = new THREE.TextureLoader(this.manager_);
  44. this.textures_ = {};
  45. this.manager_.onLoad = () => {
  46. this.onLoad_();
  47. };
  48. }
  49. get Info() {
  50. return this.textures_;
  51. }
  52. render_(t) {
  53. this.material_.uniforms.zLevel.value = t;
  54. this.threejs_.setRenderTarget(this.rt_);
  55. this.threejs_.render(this.scene_, this.camera_);
  56. const pixelBuffer = new Uint8Array(this.resolution_ * this.resolution_ * 4);
  57. this.threejs_.readRenderTargetPixels(this.rt_, 0, 0, this.resolution_, this.resolution_, pixelBuffer );
  58. this.threejs_.setRenderTarget(null);
  59. this.threejs_.outputEncoding = THREE.LinearEncoding;
  60. return pixelBuffer;
  61. }
  62. onLoad_() {
  63. const X = this.resolution_;
  64. const Y = this.resolution_;
  65. this.textures_['diffuse'] = {
  66. textures: []
  67. };
  68. for (let i = 0; i < 64; i++) {
  69. this.textures_['diffuse'].textures.push(this.render_(i / 4.0));
  70. }
  71. for (let k in this.textures_) {
  72. const atlas = this.textures_[k];
  73. const data = new Uint8Array(atlas.textures.length * 4 * X * Y);
  74. for (let t = 0; t < atlas.textures.length; t++) {
  75. const curData = atlas.textures[t];
  76. const offset = t * (4 * X * Y);
  77. data.set(curData, offset);
  78. }
  79. // const diffuse = new THREE.DataArrayTexture(data, X, Y, atlas.textures.length);
  80. const diffuse = new THREE.Data3DTexture(data, X, Y, atlas.textures.length);
  81. diffuse.format = THREE.RGBAFormat;
  82. diffuse.type = THREE.UnsignedByteType;
  83. diffuse.minFilter = THREE.LinearFilter;
  84. diffuse.magFilter = THREE.LinearFilter;
  85. // diffuse.anisotropy = this.threejs_.capabilities.getMaxAnisotropy();
  86. diffuse.wrapS = THREE.RepeatWrapping;
  87. diffuse.wrapT = THREE.RepeatWrapping;
  88. diffuse.wrapR = THREE.RepeatWrapping;
  89. diffuse.generateMipmaps = true;
  90. diffuse.needsUpdate = true;
  91. atlas.atlas = diffuse;
  92. }
  93. this.onLoad();
  94. }
  95. Load() {
  96. this.onLoad_();
  97. }
  98. }
  99. class SDFFieldGenerator {
  100. constructor() {
  101. }
  102. async init_(threejs) {
  103. this.create_();
  104. this.onLoad = () => {};
  105. this.threejs_ = threejs;
  106. const header = await fetch('./shaders/header.glsl');
  107. const common = await fetch('./shaders/common.glsl');
  108. const oklab = await fetch('./shaders/oklab.glsl');
  109. const blends = await fetch('./shaders/blend-modes.glsl');
  110. const noise = await fetch('./shaders/noise.glsl');
  111. const vsh = await fetch('./shaders/vertex-shader.glsl');
  112. const fsh = await fetch('./shaders/sdf-generator-shader.glsl');
  113. const material = new THREE.ShaderMaterial({
  114. uniforms: {
  115. zLevel: { value: 0.0 },
  116. numCells: { value: 2.0 },
  117. },
  118. vertexShader: await vsh.text(),
  119. fragmentShader: (
  120. await header.text() + '\n' +
  121. await oklab.text() + '\n' +
  122. await common.text() + '\n' +
  123. await blends.text() + '\n' +
  124. await noise.text() + '\n' +
  125. await fsh.text())
  126. });
  127. this.material_ = material;
  128. this.scene_ = new THREE.Scene();
  129. this.camera_ = new THREE.OrthographicCamera(0, 1, 1, 0, 0.1, 1000);
  130. this.camera_.position.set(0, 0, 1);
  131. const geometry = new THREE.PlaneGeometry(1, 1);
  132. const plane = new THREE.Mesh(geometry, material);
  133. plane.position.set(0.5, 0.5, 0);
  134. this.scene_.add(plane);
  135. this.resolution_ = 128;
  136. this.rt_ = new THREE.WebGLRenderTarget(this.resolution_, this.resolution_);
  137. }
  138. create_() {
  139. this.manager_ = new THREE.LoadingManager();
  140. this.loader_ = new THREE.TextureLoader(this.manager_);
  141. this.textures_ = {};
  142. this.manager_.onLoad = () => {
  143. this.onLoad_();
  144. };
  145. }
  146. get Info() {
  147. return this.textures_;
  148. }
  149. render_(t) {
  150. this.material_.uniforms.zLevel.value = t;
  151. this.threejs_.setRenderTarget(this.rt_);
  152. this.threejs_.render(this.scene_, this.camera_);
  153. const pixelBuffer = new Uint8Array(this.resolution_ * this.resolution_ * 4);
  154. this.threejs_.readRenderTargetPixels(this.rt_, 0, 0, this.resolution_, this.resolution_, pixelBuffer );
  155. this.threejs_.setRenderTarget(null);
  156. this.threejs_.outputEncoding = THREE.LinearEncoding;
  157. return pixelBuffer;
  158. }
  159. onLoad_() {
  160. const X = this.resolution_;
  161. const Y = this.resolution_;
  162. const CHANNELS = 4;
  163. this.textures_['diffuse'] = {
  164. textures: []
  165. };
  166. for (let i = 0; i < 32; i++) {
  167. this.textures_['diffuse'].textures.push(this.render_(i));
  168. }
  169. for (let k in this.textures_) {
  170. const atlas = this.textures_[k];
  171. const data = new Uint8Array(atlas.textures.length * CHANNELS * X * Y);
  172. for (let t = 0; t < atlas.textures.length; t++) {
  173. const curData = atlas.textures[t];
  174. const offset = t * (CHANNELS * X * Y);
  175. data.set(curData, offset);
  176. }
  177. // const diffuse = new THREE.DataArrayTexture(data, X, Y, atlas.textures.length);
  178. const diffuse = new THREE.Data3DTexture(data, X, Y, atlas.textures.length);
  179. diffuse.format = THREE.RGBAFormat;
  180. diffuse.type = THREE.UnsignedByteType;
  181. diffuse.minFilter = THREE.LinearFilter;
  182. diffuse.magFilter = THREE.LinearFilter;
  183. diffuse.anisotropy = this.threejs_.capabilities.getMaxAnisotropy();
  184. diffuse.wrapS = THREE.RepeatWrapping;
  185. diffuse.wrapT = THREE.RepeatWrapping;
  186. diffuse.wrapR = THREE.ClampToEdgeWrapping;
  187. diffuse.generateMipmaps = true;
  188. diffuse.needsUpdate = true;
  189. atlas.atlas = diffuse;
  190. }
  191. this.onLoad();
  192. }
  193. Load() {
  194. this.onLoad_();
  195. }
  196. }
  197. class SimonDev {
  198. constructor() {
  199. }
  200. async initialize() {
  201. this.threejs_ = new THREE.WebGLRenderer();
  202. this.threejs_.outputEncoding = THREE.LinearEncoding;
  203. document.body.appendChild(this.threejs_.domElement);
  204. window.addEventListener('resize', () => {
  205. this.onWindowResize_();
  206. }, false);
  207. this.scene_ = new THREE.Scene();
  208. this.finalScene_ = new THREE.Scene();
  209. this.camera_ = new THREE.OrthographicCamera(0, 1, 1, 0, 0.1, 1000);
  210. this.camera_.position.set(0, 0, 1);
  211. this.rtScale_ = 0.5;
  212. this.rtParams_ = {
  213. type: THREE.HalfFloatType,
  214. magFilter: THREE.LinearFilter,
  215. minFilter: THREE.LinearMipmapLinearFilter,
  216. anisotropy: this.threejs_.capabilities.getMaxAnisotropy(),
  217. generateMipmaps: true,
  218. };
  219. this.rt_ = new THREE.WebGLRenderTarget(
  220. window.innerWidth * this.rtScale_, window.innerHeight * this.rtScale_, this.rtParams_);
  221. await this.setupProject_();
  222. }
  223. async setupProject_() {
  224. {
  225. const header = await fetch('./shaders/header.glsl');
  226. const common = await fetch('./shaders/common.glsl');
  227. const oklab = await fetch('./shaders/oklab.glsl');
  228. const blends = await fetch('./shaders/blend-modes.glsl');
  229. const noise = await fetch('./shaders/noise.glsl');
  230. const ui2d = await fetch('./shaders/ui2d.glsl');
  231. const vsh = await fetch('./shaders/vertex-shader.glsl');
  232. const fshComposite = await fetch('./shaders/fragment-shader-composite.glsl');
  233. const compositeMaterial = new THREE.ShaderMaterial({
  234. uniforms: {
  235. resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
  236. frameResolution: { value: new THREE.Vector2(this.rt_.width, this.rt_.height) },
  237. time: { value: 0.0 },
  238. frameTexture: { value: null },
  239. uiTextures: { value: null },
  240. },
  241. vertexShader: await vsh.text(),
  242. fragmentShader: (
  243. await header.text() + '\n' +
  244. await oklab.text() + '\n' +
  245. await common.text() + '\n' +
  246. await blends.text() + '\n' +
  247. await noise.text() + '\n' +
  248. await ui2d.text() + '\n' +
  249. await fshComposite.text())
  250. });
  251. this.compositeMaterial_ = compositeMaterial;
  252. const geometry = new THREE.PlaneGeometry(1, 1);
  253. const plane = new THREE.Mesh(geometry, compositeMaterial);
  254. plane.position.set(0.5, 0.5, 0);
  255. this.finalScene_.add(plane);
  256. }
  257. const header = await fetch('./shaders/header.glsl');
  258. const common = await fetch('./shaders/common.glsl');
  259. const oklab = await fetch('./shaders/oklab.glsl');
  260. const blends = await fetch('./shaders/blend-modes.glsl');
  261. const noise = await fetch('./shaders/noise.glsl');
  262. const ui2d = await fetch('./shaders/ui2d.glsl');
  263. const vsh = await fetch('./shaders/vertex-shader.glsl');
  264. const fsh = await fetch('./shaders/fragment-shader.glsl');
  265. const loader = new THREE.TextureLoader();
  266. const blueNoise = loader.load('./textures/HDR_L_0.png');
  267. blueNoise.wrapS = THREE.RepeatWrapping;
  268. blueNoise.wrapT = THREE.RepeatWrapping;
  269. blueNoise.minFilter = THREE.NearestFilter;
  270. blueNoise.magFilter = THREE.NearestFilter;
  271. const material = new THREE.ShaderMaterial({
  272. uniforms: {
  273. resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
  274. time: { value: 0.0 },
  275. frame: { value: 0 },
  276. perlinWorley: { value: null },
  277. sdfField: { value: null },
  278. blueNoise: { value: blueNoise },
  279. },
  280. vertexShader: await vsh.text(),
  281. fragmentShader: (
  282. await header.text() + '\n' +
  283. await oklab.text() + '\n' +
  284. await common.text() + '\n' +
  285. await blends.text() + '\n' +
  286. await noise.text() + '\n' +
  287. await ui2d.text() + '\n' +
  288. await fsh.text())
  289. });
  290. const diffuse = new CloudGeneratorAtlas(this.threejs_);
  291. await diffuse.init_(this.threejs_);
  292. diffuse.onLoad = () => {
  293. material.uniforms.perlinWorley.value = diffuse.Info['diffuse'].atlas;
  294. };
  295. diffuse.Load();
  296. const sdfTextureGenerator = new SDFFieldGenerator(this.threejs_);
  297. await sdfTextureGenerator.init_(this.threejs_);
  298. sdfTextureGenerator.onLoad = () => {
  299. material.uniforms.sdfField.value = sdfTextureGenerator.Info['diffuse'].atlas;
  300. };
  301. sdfTextureGenerator.Load();
  302. const geometry = new THREE.PlaneGeometry(1, 1);
  303. const plane = new THREE.Mesh(geometry, material);
  304. plane.position.set(0.5, 0.5, 0);
  305. this.scene_.add(plane);
  306. this.material_ = material;
  307. this.clock_ = new THREE.Clock();
  308. this.totalTime_ = 0;
  309. this.previousRAF_ = null;
  310. this.onWindowResize_();
  311. this.raf_();
  312. }
  313. onWindowResize_() {
  314. this.threejs_.setSize(window.innerWidth, window.innerHeight);
  315. this.rt_.setSize(window.innerWidth * this.rtScale_, window.innerHeight * this.rtScale_);
  316. this.material_.uniforms.resolution.value = new THREE.Vector2(this.rt_.width, this.rt_.height);
  317. this.compositeMaterial_.uniforms.resolution.value = new THREE.Vector2(window.innerWidth, window.innerHeight);
  318. this.compositeMaterial_.uniforms.frameResolution.value = new THREE.Vector2(this.rt_.width, this.rt_.height);
  319. }
  320. raf_() {
  321. requestAnimationFrame((t) => {
  322. this.step_(t - this.previousRAF_);
  323. this.render_();
  324. if (!this.clock_.running) {
  325. this.clock_.start();
  326. }
  327. setTimeout(() => {
  328. this.raf_();
  329. this.previousRAF_ = t;
  330. }, 1);
  331. });
  332. }
  333. step_(timeElapsed) {
  334. this.totalTime_ = this.clock_.getElapsedTime();
  335. this.material_.uniforms.time.value = this.totalTime_;
  336. this.material_.uniforms.frame.value = this.material_.uniforms.frame.value + 1;
  337. this.compositeMaterial_.uniforms.time.value = this.totalTime_;
  338. }
  339. render_() {
  340. this.threejs_.setRenderTarget(this.rt_);
  341. this.threejs_.render(this.scene_, this.camera_);
  342. this.threejs_.setRenderTarget(null);
  343. this.compositeMaterial_.uniforms.frameTexture.value = this.rt_.texture;
  344. this.threejs_.render(this.finalScene_, this.camera_);
  345. }
  346. }
  347. let APP_ = null;
  348. window.addEventListener('DOMContentLoaded', async () => {
  349. APP_ = new SimonDev();
  350. await APP_.initialize();
  351. });