webgpu_centroid_sampling.html 7.6 KB

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