graphics.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
  2. import Stats from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/libs/stats.module.js';
  3. import {WEBGL} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/WebGL.js';
  4. import {RenderPass} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/postprocessing/RenderPass.js';
  5. import {ShaderPass} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/postprocessing/ShaderPass.js';
  6. import {CopyShader} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/shaders/CopyShader.js';
  7. import {FXAAShader} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/shaders/FXAAShader.js';
  8. import {EffectComposer} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/postprocessing/EffectComposer.js';
  9. import {scattering_shader} from './scattering-shader.js';
  10. export const graphics = (function() {
  11. function _GetImageData(image) {
  12. const canvas = document.createElement('canvas');
  13. canvas.width = image.width;
  14. canvas.height = image.height;
  15. const context = canvas.getContext( '2d' );
  16. context.drawImage(image, 0, 0);
  17. return context.getImageData(0, 0, image.width, image.height);
  18. }
  19. function _GetPixel(imagedata, x, y) {
  20. const position = (x + imagedata.width * y) * 4;
  21. const data = imagedata.data;
  22. return {
  23. r: data[position],
  24. g: data[position + 1],
  25. b: data[position + 2],
  26. a: data[position + 3]
  27. };
  28. }
  29. class _Graphics {
  30. constructor(game) {
  31. }
  32. Initialize() {
  33. if (!WEBGL.isWebGL2Available()) {
  34. return false;
  35. }
  36. const canvas = document.createElement('canvas');
  37. const context = canvas.getContext('webgl2', {alpha: false});
  38. this._threejs = new THREE.WebGLRenderer({
  39. canvas: canvas,
  40. context: context,
  41. });
  42. this._threejs.setPixelRatio(window.devicePixelRatio);
  43. this._threejs.setSize(window.innerWidth, window.innerHeight);
  44. this._threejs.autoClear = false;
  45. const target = document.getElementById('target');
  46. target.appendChild(this._threejs.domElement);
  47. this._stats = new Stats();
  48. // target.appendChild(this._stats.dom);
  49. window.addEventListener('resize', () => {
  50. this._OnWindowResize();
  51. }, false);
  52. const fov = 60;
  53. const aspect = 1920 / 1080;
  54. const near = 0.1;
  55. const far = 100000.0;
  56. this._camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  57. this._camera.position.set(75, 20, 0);
  58. this._scene = new THREE.Scene();
  59. this._scene.background = new THREE.Color(0xaaaaaa);
  60. const renderPass = new RenderPass(this._scene, this._camera);
  61. const fxaaPass = new ShaderPass(FXAAShader);
  62. // const depthPass = new ShaderPass(scattering_shader.Shader);
  63. // this._depthPass = depthPass;
  64. this._composer = new EffectComposer(this._threejs);
  65. this._composer.addPass(renderPass);
  66. this._composer.addPass(fxaaPass);
  67. //this._composer.addPass(depthPass);
  68. this._target = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);
  69. this._target.texture.format = THREE.RGBFormat;
  70. this._target.texture.minFilter = THREE.NearestFilter;
  71. this._target.texture.magFilter = THREE.NearestFilter;
  72. this._target.texture.generateMipmaps = false;
  73. this._target.stencilBuffer = false;
  74. this._target.depthBuffer = true;
  75. this._target.depthTexture = new THREE.DepthTexture();
  76. this._target.depthTexture.format = THREE.DepthFormat;
  77. this._target.depthTexture.type = THREE.FloatType;
  78. this._threejs.setRenderTarget(this._target);
  79. this._postCamera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
  80. this._depthPass = new THREE.ShaderMaterial( {
  81. vertexShader: scattering_shader.VS,
  82. fragmentShader: scattering_shader.PS,
  83. uniforms: {
  84. cameraNear: { value: this.Camera.near },
  85. cameraFar: { value: this.Camera.far },
  86. cameraPosition: { value: this.Camera.position },
  87. cameraForward: { value: null },
  88. tDiffuse: { value: null },
  89. tDepth: { value: null },
  90. inverseProjection: { value: null },
  91. inverseView: { value: null },
  92. planetPosition: { value: null },
  93. planetRadius: { value: null },
  94. atmosphereRadius: { value: null },
  95. }
  96. } );
  97. var postPlane = new THREE.PlaneBufferGeometry( 2, 2 );
  98. var postQuad = new THREE.Mesh( postPlane, this._depthPass );
  99. this._postScene = new THREE.Scene();
  100. this._postScene.add( postQuad );
  101. this._CreateLights();
  102. return true;
  103. }
  104. _CreateLights() {
  105. let light = new THREE.DirectionalLight(0xFFFFFF, 1);
  106. light.position.set(100, 100, -100);
  107. light.target.position.set(0, 0, 0);
  108. light.castShadow = false;
  109. this._scene.add(light);
  110. light = new THREE.DirectionalLight(0x404040, 1);
  111. light.position.set(100, 100, -100);
  112. light.target.position.set(0, 0, 0);
  113. light.castShadow = false;
  114. this._scene.add(light);
  115. light = new THREE.DirectionalLight(0x404040, 1);
  116. light.position.set(100, 100, -100);
  117. light.target.position.set(0, 0, 0);
  118. light.castShadow = false;
  119. this._scene.add(light);
  120. light = new THREE.DirectionalLight(0x202040, 1);
  121. light.position.set(100, -100, 100);
  122. light.target.position.set(0, 0, 0);
  123. light.castShadow = false;
  124. this._scene.add(light);
  125. light = new THREE.AmbientLight(0xFFFFFF, 1.0);
  126. this._scene.add(light);
  127. }
  128. _OnWindowResize() {
  129. this._camera.aspect = window.innerWidth / window.innerHeight;
  130. this._camera.updateProjectionMatrix();
  131. this._threejs.setSize(window.innerWidth, window.innerHeight);
  132. this._composer.setSize(window.innerWidth, window.innerHeight);
  133. this._target.setSize(window.innerWidth, window.innerHeight);
  134. }
  135. get Scene() {
  136. return this._scene;
  137. }
  138. get Camera() {
  139. return this._camera;
  140. }
  141. Render(timeInSeconds) {
  142. this._threejs.setRenderTarget(this._target);
  143. this._threejs.clear();
  144. this._threejs.render(this._scene, this._camera);
  145. //this._composer.render();
  146. this._threejs.setRenderTarget( null );
  147. const forward = new THREE.Vector3();
  148. this._camera.getWorldDirection(forward);
  149. this._depthPass.uniforms.inverseProjection.value = this._camera.projectionMatrixInverse;
  150. this._depthPass.uniforms.inverseView.value = this._camera.matrixWorld;
  151. this._depthPass.uniforms.tDiffuse.value = this._target.texture;
  152. this._depthPass.uniforms.tDepth.value = this._target.depthTexture;
  153. this._depthPass.uniforms.cameraNear.value = this._camera.near;
  154. this._depthPass.uniforms.cameraFar.value = this._camera.far;
  155. this._depthPass.uniforms.cameraPosition.value = this._camera.position;
  156. this._depthPass.uniforms.cameraForward.value = forward;
  157. this._depthPass.uniforms.planetPosition.value = new THREE.Vector3(0, 0, 0);
  158. this._depthPass.uniforms.planetRadius.value = 4000.0;
  159. this._depthPass.uniforms.atmosphereRadius.value = 4400.0;
  160. this._depthPass.uniformsNeedUpdate = true;
  161. this._threejs.render( this._postScene, this._postCamera );
  162. this._stats.update();
  163. }
  164. }
  165. return {
  166. Graphics: _Graphics,
  167. GetPixel: _GetPixel,
  168. GetImageData: _GetImageData,
  169. };
  170. })();