main.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
  2. import {OrbitControls} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.js';
  3. const _NOISE_GLSL = `
  4. //
  5. // Description : Array and textureless GLSL 2D/3D/4D simplex
  6. // noise functions.
  7. // Author : Ian McEwan, Ashima Arts.
  8. // Maintainer : stegu
  9. // Lastmod : 20201014 (stegu)
  10. // License : Copyright (C) 2011 Ashima Arts. All rights reserved.
  11. // Distributed under the MIT License. See LICENSE file.
  12. // https://github.com/ashima/webgl-noise
  13. // https://github.com/stegu/webgl-noise
  14. //
  15. vec3 mod289(vec3 x) {
  16. return x - floor(x * (1.0 / 289.0)) * 289.0;
  17. }
  18. vec4 mod289(vec4 x) {
  19. return x - floor(x * (1.0 / 289.0)) * 289.0;
  20. }
  21. vec4 permute(vec4 x) {
  22. return mod289(((x*34.0)+1.0)*x);
  23. }
  24. vec4 taylorInvSqrt(vec4 r)
  25. {
  26. return 1.79284291400159 - 0.85373472095314 * r;
  27. }
  28. float snoise(vec3 v)
  29. {
  30. const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
  31. const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
  32. // First corner
  33. vec3 i = floor(v + dot(v, C.yyy) );
  34. vec3 x0 = v - i + dot(i, C.xxx) ;
  35. // Other corners
  36. vec3 g = step(x0.yzx, x0.xyz);
  37. vec3 l = 1.0 - g;
  38. vec3 i1 = min( g.xyz, l.zxy );
  39. vec3 i2 = max( g.xyz, l.zxy );
  40. // x0 = x0 - 0.0 + 0.0 * C.xxx;
  41. // x1 = x0 - i1 + 1.0 * C.xxx;
  42. // x2 = x0 - i2 + 2.0 * C.xxx;
  43. // x3 = x0 - 1.0 + 3.0 * C.xxx;
  44. vec3 x1 = x0 - i1 + C.xxx;
  45. vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
  46. vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
  47. // Permutations
  48. i = mod289(i);
  49. vec4 p = permute( permute( permute(
  50. i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
  51. + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
  52. + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
  53. // Gradients: 7x7 points over a square, mapped onto an octahedron.
  54. // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
  55. float n_ = 0.142857142857; // 1.0/7.0
  56. vec3 ns = n_ * D.wyz - D.xzx;
  57. vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
  58. vec4 x_ = floor(j * ns.z);
  59. vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
  60. vec4 x = x_ *ns.x + ns.yyyy;
  61. vec4 y = y_ *ns.x + ns.yyyy;
  62. vec4 h = 1.0 - abs(x) - abs(y);
  63. vec4 b0 = vec4( x.xy, y.xy );
  64. vec4 b1 = vec4( x.zw, y.zw );
  65. //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
  66. //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
  67. vec4 s0 = floor(b0)*2.0 + 1.0;
  68. vec4 s1 = floor(b1)*2.0 + 1.0;
  69. vec4 sh = -step(h, vec4(0.0));
  70. vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
  71. vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
  72. vec3 p0 = vec3(a0.xy,h.x);
  73. vec3 p1 = vec3(a0.zw,h.y);
  74. vec3 p2 = vec3(a1.xy,h.z);
  75. vec3 p3 = vec3(a1.zw,h.w);
  76. //Normalise gradients
  77. vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  78. p0 *= norm.x;
  79. p1 *= norm.y;
  80. p2 *= norm.z;
  81. p3 *= norm.w;
  82. // Mix final noise value
  83. vec4 m = max(0.5 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
  84. m = m * m;
  85. return 105.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
  86. dot(p2,x2), dot(p3,x3) ) );
  87. }
  88. float FBM(vec3 p) {
  89. float value = 0.0;
  90. float amplitude = 0.5;
  91. float frequency = 0.0;
  92. for (int i = 0; i < 6; ++i) {
  93. value += amplitude * snoise(p);
  94. p *= 2.0;
  95. amplitude *= 0.5;
  96. }
  97. return value;
  98. }
  99. `;
  100. class FogDemo {
  101. constructor() {
  102. this.Initialize_();
  103. }
  104. Initialize_() {
  105. THREE.ShaderChunk.fog_fragment = `
  106. #ifdef USE_FOG
  107. vec3 fogOrigin = cameraPosition;
  108. vec3 fogDirection = normalize(vWorldPosition - fogOrigin);
  109. float fogDepth = distance(vWorldPosition, fogOrigin);
  110. // f(p) = fbm( p + fbm( p ) )
  111. vec3 noiseSampleCoord = vWorldPosition * 0.00025 + vec3(
  112. 0.0, 0.0, fogTime * 0.025);
  113. float noiseSample = FBM(noiseSampleCoord + FBM(noiseSampleCoord)) * 0.5 + 0.5;
  114. fogDepth *= mix(noiseSample, 1.0, saturate((fogDepth - 5000.0) / 5000.0));
  115. fogDepth *= fogDepth;
  116. float heightFactor = 0.05;
  117. float fogFactor = heightFactor * exp(-fogOrigin.y * fogDensity) * (
  118. 1.0 - exp(-fogDepth * fogDirection.y * fogDensity)) / fogDirection.y;
  119. fogFactor = saturate(fogFactor);
  120. gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );
  121. #endif`;
  122. THREE.ShaderChunk.fog_pars_fragment = _NOISE_GLSL + `
  123. #ifdef USE_FOG
  124. uniform float fogTime;
  125. uniform vec3 fogColor;
  126. varying vec3 vWorldPosition;
  127. #ifdef FOG_EXP2
  128. uniform float fogDensity;
  129. #else
  130. uniform float fogNear;
  131. uniform float fogFar;
  132. #endif
  133. #endif`;
  134. THREE.ShaderChunk.fog_vertex = `
  135. #ifdef USE_FOG
  136. vWorldPosition = worldPosition.xyz;
  137. #endif`;
  138. THREE.ShaderChunk.fog_pars_vertex = `
  139. #ifdef USE_FOG
  140. varying vec3 vWorldPosition;
  141. #endif`;
  142. this.threejs_ = new THREE.WebGLRenderer({
  143. antialias: true,
  144. });
  145. this.threejs_.shadowMap.enabled = true;
  146. this.threejs_.shadowMap.type = THREE.PCFSoftShadowMap;
  147. this.threejs_.setPixelRatio(window.devicePixelRatio);
  148. this.threejs_.setSize(window.innerWidth, window.innerHeight);
  149. document.body.appendChild(this.threejs_.domElement);
  150. window.addEventListener('resize', () => {
  151. this.OnWindowResize_();
  152. }, false);
  153. const fov = 60;
  154. const aspect = 1920 / 1080;
  155. const near = 1.0;
  156. const far = 20000.0;
  157. this.camera_ = new THREE.PerspectiveCamera(fov, aspect, near, far);
  158. this.camera_.position.set(75, 20, 0);
  159. this.scene_ = new THREE.Scene();
  160. let light = new THREE.DirectionalLight(0xFFFFFF, 1.0);
  161. light.position.set(20, 100, 10);
  162. light.target.position.set(0, 0, 0);
  163. light.castShadow = true;
  164. light.shadow.bias = -0.001;
  165. light.shadow.mapSize.width = 2048;
  166. light.shadow.mapSize.height = 2048;
  167. light.shadow.camera.near = 0.1;
  168. light.shadow.camera.far = 500.0;
  169. light.shadow.camera.near = 0.5;
  170. light.shadow.camera.far = 500.0;
  171. light.shadow.camera.left = 100;
  172. light.shadow.camera.right = -100;
  173. light.shadow.camera.top = 100;
  174. light.shadow.camera.bottom = -100;
  175. this.scene_.add(light);
  176. light = new THREE.AmbientLight(0x101010);
  177. this.scene_.add(light);
  178. const controls = new OrbitControls(
  179. this.camera_, this.threejs_.domElement);
  180. controls.target.set(0, 20, 0);
  181. controls.update();
  182. this.shaders_ = [];
  183. const ModifyShader_ = (s) => {
  184. this.shaders_.push(s);
  185. s.uniforms.fogTime = {value: 0.0};
  186. }
  187. const sky = new THREE.Mesh(
  188. new THREE.SphereGeometry(10000, 32, 32),
  189. new THREE.MeshBasicMaterial({
  190. color: 0x8080FF,
  191. side: THREE.BackSide,
  192. })
  193. );
  194. sky.material.onBeforeCompile = ModifyShader_;
  195. this.scene_.add(sky);
  196. const ground = new THREE.Mesh(
  197. new THREE.PlaneGeometry(20000, 20000, 300, 300),
  198. new THREE.MeshStandardMaterial({
  199. color: 0x808080,
  200. })
  201. );
  202. ground.rotation.x = -Math.PI / 2.0;
  203. ground.material.onBeforeCompile = ModifyShader_;
  204. this.scene_.add(ground);
  205. const trunkMat = new THREE.MeshStandardMaterial({color: 0x808080});
  206. const leavesMat = new THREE.MeshStandardMaterial({color: 0x80FF80});
  207. const trunkGeo = new THREE.BoxGeometry(1, 1, 1);
  208. const leavesGeo = new THREE.ConeGeometry(1, 1, 32);
  209. trunkMat.onBeforeCompile = ModifyShader_;
  210. leavesMat.onBeforeCompile = ModifyShader_;
  211. for (let x = 0; x < 50; ++x) {
  212. for (let y = 0; y < 50; ++y) {
  213. const trunk = new THREE.Mesh(trunkGeo, trunkMat);
  214. const leaves = new THREE.Mesh(leavesGeo, leavesMat);
  215. trunk.scale.set(20, (Math.random() + 1.0) * 100.0, 20);
  216. trunk.position.set(
  217. 15000.0 * (Math.random() * 2.0 - 1.0),
  218. trunk.scale.y / 2.0,
  219. 15000.0 * (Math.random() * 2.0 - 1.0));
  220. leaves.scale.copy(trunk.scale);
  221. leaves.scale.set(100, trunk.scale.y * 5.0, 100);
  222. leaves.position.set(
  223. trunk.position.x,
  224. leaves.scale.y / 2 + (Math.random() + 1) * 25,
  225. trunk.position.z);
  226. this.scene_.add(trunk);
  227. this.scene_.add(leaves);
  228. }
  229. }
  230. const monolith = new THREE.Mesh(
  231. new THREE.BoxGeometry(500, 2000, 100),
  232. new THREE.MeshStandardMaterial({color: 0x000000, metalness: 0.9}));
  233. monolith.position.set(0, 1000, 5000);
  234. monolith.material.onBeforeCompile = ModifyShader_;
  235. this.scene_.add(monolith);
  236. // this.scene_.fog = new THREE.Fog(0xDFE9F3, 0.0, 500.0);
  237. this.scene_.fog = new THREE.FogExp2(0xDFE9F3, 0.0000005);
  238. this.totalTime_ = 0.0;
  239. this.previousRAF_ = null;
  240. this.RAF_();
  241. }
  242. OnWindowResize_() {
  243. this.camera_.aspect = window.innerWidth / window.innerHeight;
  244. this.camera_.updateProjectionMatrix();
  245. this.threejs_.setSize(window.innerWidth, window.innerHeight);
  246. }
  247. RAF_() {
  248. requestAnimationFrame((t) => {
  249. if (this.previousRAF_ === null) {
  250. this.previousRAF_ = t;
  251. }
  252. this.Step_((t - this.previousRAF_) * 0.001);
  253. this.previousRAF_ = t;
  254. this.threejs_.render(this.scene_, this.camera_);
  255. this.RAF_();
  256. });
  257. }
  258. Step_(timeElapsed) {
  259. this.totalTime_ += timeElapsed;
  260. for (let s of this.shaders_) {
  261. s.uniforms.fogTime.value = this.totalTime_;
  262. }
  263. }
  264. }
  265. let _APP = null;
  266. window.addEventListener('DOMContentLoaded', () => {
  267. _APP = new FogDemo();
  268. });