webgl_reversed_depth_buffer.html 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>three.js webgl - reverse depth buffer</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  7. <meta property="og:title" content="three.js webgl - reverse depth buffer">
  8. <meta property="og:type" content="website">
  9. <meta property="og:url" content="https://threejs.org/examples/webgl_reversed_depth_buffer.html">
  10. <meta property="og:image" content="https://threejs.org/examples/screenshots/webgl_reversed_depth_buffer.jpg">
  11. <link type="text/css" rel="stylesheet" href="main.css">
  12. <style>
  13. body {
  14. margin: 0;
  15. background-color: #000;
  16. color: #fff;
  17. font-family: Monospace;
  18. font-size: 13px;
  19. line-height: 24px;
  20. overscroll-behavior: none;
  21. }
  22. a {
  23. color: #ff0;
  24. text-decoration: none;
  25. }
  26. a:hover {
  27. text-decoration: underline;
  28. }
  29. #info {
  30. position: absolute;
  31. top: 0px;
  32. width: 100%;
  33. padding: 10px;
  34. box-sizing: border-box;
  35. text-align: center;
  36. -moz-user-select: none;
  37. -webkit-user-select: none;
  38. -ms-user-select: none;
  39. user-select: none;
  40. pointer-events: none;
  41. z-index: 1; /* TODO Solve this in HTML */
  42. }
  43. #container {
  44. display: flex;
  45. }
  46. #container_normal,
  47. #container_logarithmic,
  48. #container_reverse {
  49. width: 33%;
  50. display: inline-block;
  51. position: relative;
  52. }
  53. .container_label {
  54. position: absolute;
  55. bottom: 1em;
  56. width: 100%;
  57. color: white;
  58. z-index: 10;
  59. display: block;
  60. text-align: center;
  61. }
  62. #info_note {
  63. position: absolute;
  64. top: 24px;
  65. width: 100%;
  66. padding: 10px;
  67. box-sizing: border-box;
  68. text-align: center;
  69. color: rgba(255, 255, 255, 0.8);
  70. z-index: 2;
  71. }
  72. </style>
  73. </head>
  74. <body>
  75. <div id="container">
  76. <div id="container_normal"><h2 class="container_label">normal z-buffer</h2></div>
  77. <div id="container_logarithmic"><h2 class="container_label">logarithmic z-buffer</h2></div>
  78. <div id="container_reverse"><h2 class="container_label">reverse z-buffer</h2></div>
  79. </div>
  80. <div id="info">
  81. <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - reverse depth buffer<br/>
  82. </div>
  83. <div id="info_note">
  84. Note: For best results, a floating-point depth buffer should be used with post-processing. See <a href="https://developer.nvidia.com/blog/visualizing-depth-precision" target="_blank" rel="noopener">Visualizing Depth Precision</a>.
  85. </div>
  86. <script type="importmap">
  87. {
  88. "imports": {
  89. "three": "../build/three.module.js",
  90. "three/addons/": "./jsm/"
  91. }
  92. }
  93. </script>
  94. <script type="module">
  95. // https://webgpu.github.io/webgpu-samples/?sample=reversedZ
  96. import * as THREE from 'three';
  97. import Stats from 'three/addons/libs/stats.module.js';
  98. import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
  99. import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
  100. import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
  101. let stats, camera, reversedCamera, scene;
  102. let normalRenderer, logarithmicRenderer, reverseRenderer;
  103. let normalComposer, logarithmicComposer, reverseComposer;
  104. const meshes = [];
  105. const renderTarget = new THREE.WebGLRenderTarget();
  106. renderTarget.depthTexture = new THREE.DepthTexture();
  107. renderTarget.depthTexture.type = THREE.FloatType;
  108. init();
  109. animate();
  110. function init() {
  111. const container = document.getElementById( 'container' );
  112. stats = new Stats();
  113. container.appendChild( stats.dom );
  114. camera = new THREE.PerspectiveCamera( 72, 0.33 * window.innerWidth / window.innerHeight, 5, 9999 );
  115. camera.position.z = 12;
  116. reversedCamera = camera.clone();
  117. scene = new THREE.Scene();
  118. const xCount = 1;
  119. const yCount = 5;
  120. const numInstances = xCount * yCount;
  121. const d = 0.0001; // half distance between two planes
  122. const o = 0.5; // half x offset to shift planes so they are only partially overlapping
  123. const positions = new Float32Array( [
  124. - 1 - o, - 1, d,
  125. 1 - o, - 1, d,
  126. - 1 - o, 1, d,
  127. 1 - o, - 1, d,
  128. 1 - o, 1, d,
  129. - 1 - o, 1, d,
  130. - 1 + o, - 1, - d,
  131. 1 + o, - 1, - d,
  132. - 1 + o, 1, - d,
  133. 1 + o, - 1, - d,
  134. 1 + o, 1, - d,
  135. - 1 + o, 1, - d,
  136. ] );
  137. const colors = new Float32Array( [
  138. 1, 0, 0,
  139. 1, 0, 0,
  140. 1, 0, 0,
  141. 1, 0, 0,
  142. 1, 0, 0,
  143. 1, 0, 0,
  144. 0, 1, 0,
  145. 0, 1, 0,
  146. 0, 1, 0,
  147. 0, 1, 0,
  148. 0, 1, 0,
  149. 0, 1, 0,
  150. ] );
  151. const geometry = new THREE.BufferGeometry();
  152. geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
  153. geometry.setAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
  154. const material = new THREE.MeshBasicMaterial( { vertexColors: true } );
  155. for ( let i = 0; i < numInstances; i ++ ) {
  156. const mesh = new THREE.Mesh( geometry, material );
  157. meshes.push( mesh );
  158. scene.add( mesh );
  159. }
  160. let i = 0;
  161. for ( let x = 0; x < xCount; x ++ ) {
  162. for ( let y = 0; y < yCount; y ++ ) {
  163. const z = - 800 * i;
  164. const s = 1 + 50 * i;
  165. const mesh = meshes[ i ];
  166. mesh.position.set(
  167. x - xCount / 2 + 0.5,
  168. ( 4.0 - 0.2 * z ) * ( y - yCount / 2 + 1.0 ),
  169. z
  170. );
  171. mesh.scale.setScalar( s );
  172. i ++;
  173. }
  174. }
  175. const normalContainer = document.getElementById( 'container_normal' );
  176. normalRenderer = new THREE.WebGLRenderer();
  177. normalRenderer.setPixelRatio( window.devicePixelRatio );
  178. normalRenderer.setSize( 0.33 * window.innerWidth, window.innerHeight );
  179. normalRenderer.domElement.style.position = 'relative';
  180. normalContainer.appendChild( normalRenderer.domElement );
  181. normalComposer = new EffectComposer( normalRenderer, renderTarget );
  182. normalComposer.addPass( new RenderPass( scene, camera ) );
  183. normalComposer.addPass( new OutputPass() );
  184. const logarithmicContainer = document.getElementById( 'container_logarithmic' );
  185. logarithmicRenderer = new THREE.WebGLRenderer( { logarithmicDepthBuffer: true } );
  186. logarithmicRenderer.setPixelRatio( window.devicePixelRatio );
  187. logarithmicRenderer.setSize( 0.33 * window.innerWidth, window.innerHeight );
  188. logarithmicRenderer.domElement.style.position = 'relative';
  189. logarithmicContainer.appendChild( logarithmicRenderer.domElement );
  190. logarithmicComposer = new EffectComposer( logarithmicRenderer, renderTarget );
  191. logarithmicComposer.addPass( new RenderPass( scene, camera ) );
  192. logarithmicComposer.addPass( new OutputPass() );
  193. const reverseContainer = document.getElementById( 'container_reverse' );
  194. reverseRenderer = new THREE.WebGLRenderer( { reversedDepthBuffer: true } );
  195. reverseRenderer.setPixelRatio( window.devicePixelRatio );
  196. reverseRenderer.setSize( 0.33 * window.innerWidth, window.innerHeight );
  197. reverseRenderer.domElement.style.position = 'relative';
  198. reverseContainer.appendChild( reverseRenderer.domElement );
  199. reverseComposer = new EffectComposer( reverseRenderer, renderTarget );
  200. reverseComposer.addPass( new RenderPass( scene, reversedCamera ) );
  201. reverseComposer.addPass( new OutputPass() );
  202. window.addEventListener( 'resize', onWindowResize );
  203. onWindowResize();
  204. }
  205. function animate() {
  206. requestAnimationFrame( animate );
  207. const now = performance.now() / 1000;
  208. for ( let i = 0; i < meshes.length; i ++ ) {
  209. const angle = THREE.MathUtils.degToRad( 30 );
  210. const axis = new THREE.Vector3( Math.sin( now ), Math.cos( now ), 0 );
  211. meshes[ i ].quaternion.setFromAxisAngle( axis, angle );
  212. }
  213. render();
  214. }
  215. function render() {
  216. normalComposer.render();
  217. logarithmicComposer.render();
  218. reverseComposer.render();
  219. stats.update();
  220. }
  221. function onWindowResize() {
  222. const width = 0.33 * window.innerWidth;
  223. const height = window.innerHeight;
  224. const dpr = window.devicePixelRatio;
  225. normalComposer.setSize( width * dpr, height * dpr );
  226. logarithmicComposer.setSize( width * dpr, height * dpr );
  227. reverseComposer.setSize( width * dpr, height * dpr );
  228. normalRenderer.setSize( width, height );
  229. logarithmicRenderer.setSize( width, height );
  230. reverseRenderer.setSize( width, height );
  231. camera.aspect = 0.33 * window.innerWidth / window.innerHeight;
  232. camera.updateProjectionMatrix();
  233. reversedCamera.aspect = 0.33 * window.innerWidth / window.innerHeight;
  234. reversedCamera.updateProjectionMatrix();
  235. }
  236. </script>
  237. </body>
  238. </html>
粤ICP备19079148号