graphics.js 8.7 KB

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