webgpu_centroid_sampling.html 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. <html lang="en">
  2. <head>
  3. <title>three.js webgpu - centroid sampling</title>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  6. <meta property="og:title" content="three.js webgpu - centroid sampling">
  7. <meta property="og:type" content="website">
  8. <meta property="og:url" content="https://threejs.org/examples/webgpu_centroid_sampling.html">
  9. <meta property="og:image" content="https://threejs.org/examples/screenshots/webgpu_centroid_sampling.jpg">
  10. <link type="text/css" rel="stylesheet" href="main.css">
  11. </head>
  12. <style>
  13. body {
  14. margin: 0;
  15. overflow: hidden;
  16. width: 100vw;
  17. height: 100vh;
  18. }
  19. #demo {
  20. display: flex;
  21. flex-direction: row;
  22. align-items: center;
  23. }
  24. .renderer-wrapper {
  25. display: flex;
  26. flex-direction: column;
  27. align-items: center;
  28. }
  29. #antialiasing-disabled {
  30. border-right: 1px solid black;
  31. }
  32. canvas {
  33. width: 100%;
  34. height: 100%;
  35. }
  36. </style>
  37. <body>
  38. <div id="demo">
  39. <div id="antialiasing-disabled" class="renderer-wrapper">
  40. <div>antialiasing disabled</div>
  41. </div>
  42. <div id="antialiasing-enabled" class="renderer-wrapper">
  43. <div>antialiasing enabled</div>
  44. </div>
  45. </div>
  46. <script type="importmap">
  47. {
  48. "imports": {
  49. "three": "../build/three.webgpu.js",
  50. "three/webgpu": "../build/three.webgpu.js",
  51. "three/tsl": "../build/three.tsl.js",
  52. "three/addons/": "./jsm/"
  53. }
  54. }
  55. </script>
  56. <script type="module">
  57. import * as THREE from 'three/webgpu';
  58. import { varying, uv, texture, Fn } from 'three/tsl';
  59. import { Inspector } from 'three/addons/inspector/Inspector.js';
  60. let rendererAntialiasingEnabled;
  61. let rendererAntialiasingDisabled;
  62. let camera;
  63. let scene;
  64. let gui;
  65. const effectController = {
  66. sampling: 'normal'
  67. };
  68. const atlasCanvas = document.createElement( 'canvas' );
  69. atlasCanvas.width = 16;
  70. atlasCanvas.height = 16;
  71. const ctx = atlasCanvas.getContext( '2d' );
  72. ctx.fillStyle = 'red';
  73. ctx.fillRect( 0, 0, 8, 8 );
  74. const redUVs = [ 0, 1, 0.5, 1, 0.5, 0.5, 0, 0.5 ];
  75. ctx.fillStyle = 'green';
  76. ctx.fillRect( 8, 0, 8, 8 );
  77. const greenUVs = [ 1, 1, 0.5, 1, 0.5, 0.5, 1, 0.5 ];
  78. ctx.fillStyle = 'blue';
  79. ctx.fillRect( 0, 8, 8, 8 );
  80. const blueUVs = [ 0, 0, 0.5, 0, 0.5, 0.5, 0, 0.5 ];
  81. ctx.fillStyle = 'yellow';
  82. ctx.fillRect( 8, 8, 8, 8 );
  83. const yellowUVs = [ 1, 0, 0.5, 0, 0.5, 0.5, 1, 0.5 ];
  84. const faces = [ redUVs, greenUVs, blueUVs, yellowUVs ];
  85. const canvasTexture = new THREE.CanvasTexture( atlasCanvas );
  86. canvasTexture.colorSpace = THREE.SRGBColorSpace;
  87. canvasTexture.mapping = THREE.UVMapping;
  88. canvasTexture.wrapS = THREE.RepeatWrapping;
  89. canvasTexture.wrapT = THREE.RepeatWrapping;
  90. canvasTexture.magFilter = THREE.NearestFilter;
  91. canvasTexture.minFilter = THREE.NearestFilter;
  92. canvasTexture.format = THREE.RGBAFormat;
  93. canvasTexture.type = THREE.UnsignedByteType;
  94. const forceWebGL = false;
  95. init();
  96. function init() {
  97. camera = new THREE.PerspectiveCamera();
  98. camera.fov = 60;
  99. camera.near = 1;
  100. camera.far = 2100;
  101. camera.position.z = 50;
  102. scene = new THREE.Scene();
  103. const makeFaceGeometry = ( uvs ) => {
  104. const geometry = new THREE.BufferGeometry();
  105. const positions = [ - 1, - 1, 0, 1, - 1, 0, 1, 1, 0, - 1, 1, 0 ];
  106. geometry.setAttribute(
  107. 'position',
  108. new THREE.BufferAttribute( new Float32Array( positions ), 3 )
  109. );
  110. const indices = [ 0, 1, 2, 2, 3, 0 ];
  111. geometry.setIndex( indices );
  112. geometry.setAttribute(
  113. 'uv',
  114. new THREE.BufferAttribute( new Float32Array( uvs ), 2 )
  115. );
  116. return geometry;
  117. };
  118. const material = new THREE.MeshBasicNodeMaterial();
  119. const testUV = varying( uv(), 'testUV' );
  120. const createShader = ( type, sampling ) => {
  121. return Fn( () => {
  122. testUV.setInterpolation( type, sampling );
  123. return texture( canvasTexture, testUV ).rgb;
  124. } );
  125. };
  126. const withFlatFirstShader = createShader( THREE.InterpolationSamplingType.FLAT, THREE.InterpolationSamplingMode.FIRST );
  127. const withFlatEitherShader = createShader( THREE.InterpolationSamplingType.FLAT, THREE.InterpolationSamplingMode.EITHER );
  128. const withSampleShader = Fn( () => {
  129. testUV.setInterpolation( THREE.InterpolationSamplingType.PERSPECTIVE, THREE.InterpolationSamplingMode.SAMPLE );
  130. return texture( canvasTexture, testUV ).rgb;
  131. } );
  132. const withInterpolationShader = Fn( () => {
  133. testUV.setInterpolation( THREE.InterpolationSamplingType.PERSPECTIVE, THREE.InterpolationSamplingMode.CENTROID );
  134. return texture( canvasTexture, testUV ).rgb;
  135. } );
  136. const withoutInterpolationShader = Fn( () => {
  137. return texture( canvasTexture, uv() ).rgb;
  138. } );
  139. material.colorNode = withoutInterpolationShader();
  140. const faceMeshes = [];
  141. for ( let x = - 5; x < 5; x ++ ) {
  142. for ( let y = - 5; y < 5; y ++ ) {
  143. const face = faces[ Math.floor( Math.random() * faces.length ) ];
  144. const geometry = makeFaceGeometry( face );
  145. const mesh = new THREE.Mesh( geometry, material );
  146. mesh.position.set( x * 2, y * 2, 0 );
  147. faceMeshes.push( mesh );
  148. scene.add( mesh );
  149. }
  150. }
  151. // Create Standard Renderer
  152. rendererAntialiasingDisabled = new THREE.WebGPURenderer( {
  153. antialias: false,
  154. forceWebGL: forceWebGL
  155. } );
  156. rendererAntialiasingDisabled.setPixelRatio( window.devicePixelRatio );
  157. rendererAntialiasingDisabled.setSize( window.innerWidth / 2, window.innerHeight );
  158. rendererAntialiasingDisabled.setAnimationLoop( animateStandard );
  159. // Create antialiased renderer
  160. rendererAntialiasingEnabled = new THREE.WebGPURenderer( {
  161. antialias: true,
  162. forceWebGL: forceWebGL
  163. } );
  164. document.body.querySelector( '#antialiasing-enabled' ).appendChild( rendererAntialiasingEnabled.domElement );
  165. rendererAntialiasingEnabled.setPixelRatio( window.devicePixelRatio );
  166. rendererAntialiasingEnabled.setSize( window.innerWidth / 2, window.innerHeight );
  167. rendererAntialiasingEnabled.setAnimationLoop( animateAliased );
  168. rendererAntialiasingEnabled.inspector = new Inspector();
  169. document.body.querySelector( '#antialiasing-disabled' ).appendChild( rendererAntialiasingDisabled.domElement );
  170. document.body.querySelector( '#antialiasing-disabled' ).appendChild( rendererAntialiasingDisabled.domElement );
  171. onWindowResize();
  172. window.addEventListener( 'resize', onWindowResize );
  173. gui = rendererAntialiasingEnabled.inspector.createParameters( 'Settings' );
  174. gui.add( effectController, 'sampling', [
  175. THREE.InterpolationSamplingMode.NORMAL,
  176. THREE.InterpolationSamplingMode.CENTROID,
  177. THREE.InterpolationSamplingMode.SAMPLE,
  178. 'flat first',
  179. 'flat either'
  180. ] ).onChange( () => {
  181. const interpolationShaderLib = {
  182. [ THREE.InterpolationSamplingMode.NORMAL ]: withoutInterpolationShader,
  183. [ THREE.InterpolationSamplingMode.CENTROID ]: withInterpolationShader,
  184. [ THREE.InterpolationSamplingMode.SAMPLE ]: withSampleShader,
  185. [ 'flat first' ]: withFlatFirstShader,
  186. [ 'flat either' ]: withFlatEitherShader
  187. };
  188. const shader = interpolationShaderLib[ effectController.sampling ];
  189. for ( let i = 0; i < faceMeshes.length; i ++ ) {
  190. faceMeshes[ i ].material.colorNode = shader();
  191. faceMeshes[ i ].material.needsUpdate = true;
  192. }
  193. } );
  194. }
  195. function onWindowResize() {
  196. const halfWidth = window.innerWidth / 2;
  197. rendererAntialiasingDisabled.setSize( halfWidth, window.innerHeight );
  198. rendererAntialiasingEnabled.setSize( halfWidth, window.innerHeight );
  199. const aspect = ( halfWidth ) / window.innerHeight;
  200. camera.aspect = aspect;
  201. camera.updateProjectionMatrix();
  202. }
  203. function animateStandard() {
  204. rendererAntialiasingDisabled.render( scene, camera );
  205. }
  206. function animateAliased() {
  207. rendererAntialiasingEnabled.render( scene, camera );
  208. }
  209. </script>
  210. </body>
  211. </html>
粤ICP备19079148号