From 84d625d97a62205cf917f7d1b442be83c118bb3a Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 7 Jun 2023 10:19:43 +0200 Subject: [PATCH 1/7] TAARenderPass: Fix color shift. (#26199) --- examples/jsm/postprocessing/TAARenderPass.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/jsm/postprocessing/TAARenderPass.js b/examples/jsm/postprocessing/TAARenderPass.js index 57eeb80c559989..cbbea08b6601b2 100644 --- a/examples/jsm/postprocessing/TAARenderPass.js +++ b/examples/jsm/postprocessing/TAARenderPass.js @@ -69,7 +69,6 @@ class TAARenderPass extends SSAARenderPass { const oldClearAlpha = renderer.getClearAlpha(); const sampleWeight = 1.0 / ( jitterOffsets.length ); - const accumulationWeight = this.accumulateIndex * sampleWeight; if ( this.accumulateIndex >= 0 && this.accumulateIndex < jitterOffsets.length ) { @@ -117,6 +116,7 @@ class TAARenderPass extends SSAARenderPass { } renderer.setClearColor( this.clearColor, this.clearAlpha ); + const accumulationWeight = this.accumulateIndex * sampleWeight; if ( accumulationWeight > 0 ) { @@ -133,7 +133,6 @@ class TAARenderPass extends SSAARenderPass { this.copyUniforms[ 'opacity' ].value = 1.0 - accumulationWeight; this.copyUniforms[ 'tDiffuse' ].value = this.holdRenderTarget.texture; renderer.setRenderTarget( writeBuffer ); - if ( accumulationWeight === 0 ) renderer.clear(); this.fsQuad.render( renderer ); } From cdaaca3cafb7804d4a08955ad0d462a262abd094 Mon Sep 17 00:00:00 2001 From: Omar Khalifa Date: Wed, 7 Jun 2023 11:31:06 +0300 Subject: [PATCH 2/7] Docs: Translating Loaders/managers section into Arabic (ar). (#26202) * update list.json to include the Loaders/managers section of arabic docs * add arabic translation for DefaultLoadingManager page * add arabic translation for LoadingManager page --- .../managers/DefaultLoadingManager.html | 68 +++++ .../ar/loaders/managers/LoadingManager.html | 236 ++++++++++++++++++ docs/list.json | 5 + 3 files changed, 309 insertions(+) create mode 100644 docs/api/ar/loaders/managers/DefaultLoadingManager.html create mode 100644 docs/api/ar/loaders/managers/LoadingManager.html diff --git a/docs/api/ar/loaders/managers/DefaultLoadingManager.html b/docs/api/ar/loaders/managers/DefaultLoadingManager.html new file mode 100644 index 00000000000000..7fa15480bc662f --- /dev/null +++ b/docs/api/ar/loaders/managers/DefaultLoadingManager.html @@ -0,0 +1,68 @@ + + + + + + + + + +

[name]

+ +

+ نسخة عالمية من [page:LoadingManager LoadingManager]، يستخدمها + معظم المحملات عندما لم يتم تحديد مدير مخصص.

+ + هذا سيكون كافيًا لمعظم الأغراض، ولكن قد يكون هناك أوقات عندما + ترغب في مديري تحميل منفصلين للقول، القوام والنماذج. +

+ +

مثال للكود

+ +

+ يمكنك تعيين [page:LoadingManager.onStart onStart]، + [page:LoadingManager.onLoad onLoad]، [page:LoadingManager.onProgress onProgress]، + [page:LoadingManager.onStart onError] وظائف لل + مدير. ستطبق هذه على أي محملات تستخدم + DefaultLoadingManager.

+ + يجب عدم الخلط بين هذه الوظائف المسماة بشكل مشابه + من المحملات الفردية، لأنها مخصصة لعرض المعلومات + حول الحالة العامة للتحميل، بدلاً من التعامل مع البيانات + التي تم تحميلها. +

+ +THREE.DefaultLoadingManager.onStart = function ( url, itemsLoaded, itemsTotal ) { + console.log( 'Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); +}; + +THREE.DefaultLoadingManager.onLoad = function ( ) { + console.log( 'Loading Complete!'); +}; + +THREE.DefaultLoadingManager.onProgress = function ( url, itemsLoaded, itemsTotal ) { + console.log( 'Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); +}; + +THREE.DefaultLoadingManager.onError = function ( url ) { + console.log( 'There was an error loading ' + url ); +}; + + +

الخصائص (Properties)

+

+ انظر صفحة [page:LoadingManager LoadingManager] لتفاصيل + الخصائص. +

+ +

الطرق (Methods)

+

+ انظر صفحة [page:LoadingManager LoadingManager] لتفاصيل الطرق. +

+ +

المصدر (Source)

+

+ [link:https://github.com/mrdoob/three.js/blob/master/src/loaders/LoadingManager.js src/loaders/LoadingManager.js] +

+ + diff --git a/docs/api/ar/loaders/managers/LoadingManager.html b/docs/api/ar/loaders/managers/LoadingManager.html new file mode 100644 index 00000000000000..bfe70192ed9d59 --- /dev/null +++ b/docs/api/ar/loaders/managers/LoadingManager.html @@ -0,0 +1,236 @@ + + + + + + + + + +

[name]

+ +

+ يتعامل ويتتبع البيانات المحملة والمعلقة. يتم إنشاء نسخة عالمية افتراضية + من هذه الفئة واستخدامها من قبل المحملات إذا لم يتم توفيرها + يدويًا - انظر [page:DefaultLoadingManager].

+ + بشكل عام يجب أن يكون ذلك كافيًا، ولكن هناك أوقات يمكن أن تكون فيها + مفيدًا لديك محملات منفصلة - على سبيل المثال إذا كنت ترغب في عرض + شرائط تحميل منفصلة للأشياء والقوام. +

+ +

مثال للكود

+ +

+ يوضح هذا المثال كيفية استخدام LoadingManager لتتبع التقدم + [page:OBJLoader]. +

+ + + const manager = new THREE.LoadingManager(); + manager.onStart = function ( url, itemsLoaded, itemsTotal ) { + console.log( 'Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); + }; + + manager.onLoad = function ( ) { + console.log( 'Loading complete!'); + }; + + manager.onProgress = function ( url, itemsLoaded, itemsTotal ) { + console.log( 'Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' ); + }; + + manager.onError = function ( url ) { + console.log( 'There was an error loading ' + url ); + }; + + const loader = new THREE.OBJLoader( manager ); + loader.load( 'file.obj', function ( object ) { + // + } ); + + +

+ بالإضافة إلى مراقبة التقدم، يمكن استخدام LoadingManager ل + تجاوز عناوين URL للموارد أثناء التحميل. قد يكون ذلك مفيدًا للأصول + القادمة من أحداث السحب والإفلات، WebSockets، WebRTC، أو غيرها من واجهات برمجة التطبيقات. A + مثال يظهر كيفية تحميل نموذج في الذاكرة باستخدام عناوين URL لـ Blob أدناه. +

+ + + // Blob or File objects created when dragging files into the webpage. + const blobs = {'fish.gltf': blob1, 'diffuse.png': blob2, 'normal.png': blob3}; + + const manager = new THREE.LoadingManager(); + + // Initialize loading manager with URL callback. + const objectURLs = []; + manager.setURLModifier( ( url ) => { + + url = URL.createObjectURL( blobs[ url ] ); + objectURLs.push( url ); + return url; + + } ); + + // Load as usual, then revoke the blob URLs. + const loader = new THREE.GLTFLoader( manager ); + loader.load( 'fish.gltf', (gltf) => { + + scene.add( gltf.scene ); + objectURLs.forEach( ( url ) => URL.revokeObjectURL( url ) ); + + }); + + +

أمثلة (Examples)

+ +

+ [example:webgl_loader_obj WebGL / loader / obj]
+ [example:webgl_postprocessing_outline WebGL / postprocesing / outline] +

+ +

المنشئ (Constructor)

+

+ [name]( [param:Function onLoad], [param:Function onProgress], + [param:Function onError] ) +

+

+ [page:Function onLoad] — (اختياري) سيتم استدعاء هذه الدالة عندما يتم + جميع المحملات.
+ [page:Function onProgress] — (اختياري) سيتم استدعاء هذه الدالة عند + اكتمال عنصر.
+ [page:Function onError] — (اختياري) سيتم استدعاء هذه الدالة عندما يواجه المحمل + أخطاء.
+ + ينشئ جديدًا [name]. +

+ +

الخصائص (Properties)

+ +

[property:Function onStart]

+

+ سيتم استدعاء هذه الدالة عند بدء التحميل. المعاملات هي:
+ [page:String url] — عنوان url للعنصر المحمل للتو.
+ [page:Integer itemsLoaded] — عدد العناصر المحملة حتى الآن.
+ [page:Integer itemsTotal] — إجمالي عدد العناصر التي يجب تحميلها.

+ + بشكل افتراضي هذا غير محدد. +

+ +

[property:Function onLoad]

+

+ سيتم استدعاء هذه الدالة عند اكتمال جميع التحميلات. بشكل افتراضي + هذا غير محدد، ما لم يتم تمريره في المنشئ. +

+ +

[property:Function onProgress]

+

+ سيتم استدعاء هذه الدالة عند اكتمال عنصر. المعاملات + هي:
+ [page:String url] — عنوان url للعنصر المحمل للتو.
+ [page:Integer itemsLoaded] — عدد العناصر المحملة حتى الآن.
+ [page:Integer itemsTotal] — إجمالي عدد العناصر التي يجب تحميلها.

+ + بشكل افتراضي هذا غير محدد، ما لم يتم تمريره في المنشئ. +

+ +

[property:Function onError]

+

+ سيتم استدعاء هذه الدالة عند حدوث خطأ في أي عنصر، مع الحجة:
+ [page:String url] — عنوان url للعنصر الذي حدث فيه خطأ.

+ + بشكل افتراضي هذا غير محدد، ما لم يتم تمريره في المنشئ. +

+ +

الطرق (Methods)

+ +

+ [method:this addHandler]( [param:Object regex], [param:Loader loader] ) +

+

+ [page:Object regex] — تعبير منتظم.
+ [page:Loader loader] — المحمل. +

+ +

+ يسجل محملًا مع التعبير المنتظم المعطى. يمكن استخدامه ل + تحديد أي محمل يجب استخدامه لتحميل ملفات معينة. A + حالة استخدام نموذجية هي الكتابة فوق المحمل الافتراضي للقوام. +

+ +// add handler for TGA textures +manager.addHandler( /\.tga$/i, new TGALoader() ); + + +

[method:Loader getHandler]( [param:String file] )

+

[page:String file] — مسار الملف.

+ +

+ يمكن استخدامه لاسترجاع المحمل المسجل لمسار الملف المعطى. +

+ +

[method:this removeHandler]( [param:Object regex] )

+

[page:Object regex] — تعبير منتظم.

+ +

يزيل المحمل للتعبير المنتظم المعطى.

+ +

[method:String resolveURL]( [param:String url] )

+

+ [page:String url] — عنوان url للتحميل

+ + بالنظر إلى عنوان URL، يستخدم رد الاتصال بتعديل URL (إن وجد) ويعيد + عنوان URL المحلول. إذا لم يتم تعيين تعديل URL، فسيتم إرجاع العنوان الأصلي. +

+ +

[method:this setURLModifier]( [param:Function callback] )

+

+ [page:Function callback] — رد اتصال تعديل URL. يتم استدعاؤه مع [page:String url] الحجة، + ويجب أن يعود [page:String resolvedURL].

+ + إذا تم توفيره، سيتم تمرير رد الاتصال لكل عنوان URL للمورد قبل + يتم إرسال طلب. قد يعود الرد الاتصال بالعنوان الأصلي، أو عنوان URL جديد ل + تجاوز سلوك التحميل. يمكن استخدام هذا السلوك لتحميل الأصول من + ملفات .ZIP، واجهات برمجة التطبيقات السحب والإفلات، وعناوين URI البيانات. +

+ +
+ +

+ + ملاحظة: تم تصميم الطرق التالية ليتم استدعاؤها داخليًا من قبل + المحملات. يجب ألا تستدعيها مباشرة. + +

+ +

[method:undefined itemStart]( [param:String url] )

+

+ [page:String url] — عنوان url للتحميل

+ + يجب استدعاء هذا من قبل أي محمل يستخدم المدير عندما يبدأ المحمل + تحميل عنوان url. +

+ +

[method:undefined itemEnd]( [param:String url] )

+

+ [page:String url] — عنوان url المحمَّل

+ + يجب استدعاء هذا من قبل أي محمل يستخدم المدير عند انتهاء المحمل + تحميل عنوان url. +

+ +

[method:undefined itemError]( [param:String url] )

+

+ [page:String url] — عنوان url المحمَّل

+ + يجب استدعاء هذا من قبل أي محمل يستخدم المدير عند حدوث خطأ في المحمل + تحميل عنوان url. +

+ +

المصدر (Source)

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/loaders/LoadingManager.js src/loaders/LoadingManager.js] +

+ + diff --git a/docs/list.json b/docs/list.json index dd00962d8158d8..1b4d82772d474f 100644 --- a/docs/list.json +++ b/docs/list.json @@ -637,6 +637,11 @@ "MaterialLoader": "api/ar/loaders/MaterialLoader", "ObjectLoader": "api/ar/loaders/ObjectLoader", "TextureLoader": "api/ar/loaders/TextureLoader" + }, + + "Loaders / Managers": { + "DefaultLoadingManager": "api/ar/loaders/managers/DefaultLoadingManager", + "LoadingManager": "api/ar/loaders/managers/LoadingManager" } } From 74b9e7ef8edd6baf9bc97f19825c3a361280cc7d Mon Sep 17 00:00:00 2001 From: WestLangley Date: Wed, 7 Jun 2023 04:32:57 -0400 Subject: [PATCH 3/7] Ignore tangents when flat shading (#26197) --- src/renderers/webgl/WebGLProgram.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index c90064186f0a75..4039753d6cefc8 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -536,7 +536,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { // - parameters.vertexTangents ? '#define USE_TANGENT' : '', + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUv1s ? '#define USE_UV1' : '', @@ -723,7 +723,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '', parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '', - parameters.vertexTangents ? '#define USE_TANGENT' : '', + parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '', parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '', parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '', parameters.vertexUv1s ? '#define USE_UV1' : '', From 07bbe50b51122a4336355363e90970dc6c94c2c3 Mon Sep 17 00:00:00 2001 From: ycw Date: Wed, 7 Jun 2023 16:34:23 +0800 Subject: [PATCH 4/7] Docs: Dedent code node content correctly. (#26115) * dedent * for loop * use dedent() --- docs/page.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/docs/page.js b/docs/page.js index a8ee9c3d0714e4..7c888613faeb51 100644 --- a/docs/page.js +++ b/docs/page.js @@ -106,16 +106,32 @@ function onDocumentLoad() { // handle code snippets formatting + function dedent( text ) { + + // ignores singleline text + const lines = text.split( '\n' ); + if ( lines.length <= 1 ) return text; + + // ignores blank text + const nonBlankLine = lines.filter( l => l.trim() )[ 0 ]; + if ( nonBlankLine === undefined ) return text; + + // strips indents if any + const m = nonBlankLine.match( /^([\t ]+)/ ); + if ( m ) text = lines.map( l => l.startsWith( m[ 1 ] ) ? l.substring( m[ 1 ].length ) : l ).join( '\n' ); + + // strips leading and trailing whitespaces finally + return text.trim(); + + } + const elements = document.getElementsByTagName( 'code' ); for ( let i = 0; i < elements.length; i ++ ) { const element = elements[ i ]; - text = element.textContent.trim(); - text = text.replace( /^\t\t/gm, '' ); - - element.textContent = text; + element.textContent = dedent( element.textContent ); } From 14ba68981194a8d1e0a16d9e0af00fa3dabd5146 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Wed, 7 Jun 2023 11:47:31 +0200 Subject: [PATCH 5/7] Update webgl_geometry_csg.html Update `three-bvh-csg` one more time. --- examples/webgl_geometry_csg.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/webgl_geometry_csg.html b/examples/webgl_geometry_csg.html index a801738163f778..fee4003c3b6d01 100644 --- a/examples/webgl_geometry_csg.html +++ b/examples/webgl_geometry_csg.html @@ -34,7 +34,7 @@ "three": "../build/three.module.js", "three/addons/": "./jsm/", "three-mesh-bvh": "https://unpkg.com/three-mesh-bvh@0.6.0/build/index.module.js", - "three-bvh-csg": "https://unpkg.com/three-bvh-csg@0.0.6/build/index.module.js" + "three-bvh-csg": "https://unpkg.com/three-bvh-csg@0.0.7/build/index.module.js" } } From df27d3be030a644883d233e0892f0e6792c615a1 Mon Sep 17 00:00:00 2001 From: sunag Date: Wed, 7 Jun 2023 13:34:31 -0300 Subject: [PATCH 6/7] WebGPURenderer: Backdrop Node - Part 2/3 (#26196) * WebGPURenderer: Depth buffer improvements * CameraNode: Added cameraNear, cameraFar * Object3DNode: Added modelScale, objectScale() * Added TextureBicubicNode, textureBicubic * TextureNode: Added .size(), level() and uv() * Added ViewportDepthTextureNode: viewportDepthTexture() * Added ViewportDepthNode: depth, depthTexture() * Added viewportMipTexture() * Update imports * Add webgpu_backdrop_area example * update title * CameraNode: Fix VIEW_MATRIX --- examples/files.json | 1 + examples/jsm/nodes/Nodes.js | 13 +- examples/jsm/nodes/accessors/CameraNode.js | 26 ++- examples/jsm/nodes/accessors/ModelNode.js | 1 + examples/jsm/nodes/accessors/Object3DNode.js | 12 +- .../jsm/nodes/accessors/TextureBicubicNode.js | 94 +++++++++ examples/jsm/nodes/accessors/TextureNode.js | 37 ++++ .../jsm/nodes/accessors/TextureSizeNode.js | 35 ++++ .../jsm/nodes/display/ViewportDepthNode.js | 69 +++++++ .../nodes/display/ViewportDepthTextureNode.js | 34 ++++ .../display/ViewportSharedTextureNode.js | 11 +- .../jsm/nodes/display/ViewportTextureNode.js | 38 ++-- examples/jsm/renderers/common/Renderer.js | 6 + .../jsm/renderers/webgpu/WebGPUBackend.js | 117 +++++++---- .../webgpu/utils/WebGPUTextureUtils.js | 6 +- .../jsm/renderers/webgpu/utils/WebGPUUtils.js | 6 +- examples/screenshots/webgpu_backdrop_area.jpg | Bin 0 -> 3413 bytes examples/webgpu_backdrop_area.html | 181 ++++++++++++++++++ test/e2e/puppeteer.js | 1 + 19 files changed, 622 insertions(+), 66 deletions(-) create mode 100644 examples/jsm/nodes/accessors/TextureBicubicNode.js create mode 100644 examples/jsm/nodes/accessors/TextureSizeNode.js create mode 100644 examples/jsm/nodes/display/ViewportDepthNode.js create mode 100644 examples/jsm/nodes/display/ViewportDepthTextureNode.js create mode 100644 examples/screenshots/webgpu_backdrop_area.jpg create mode 100644 examples/webgpu_backdrop_area.html diff --git a/examples/files.json b/examples/files.json index fda127ff56df75..8a231b23885987 100644 --- a/examples/files.json +++ b/examples/files.json @@ -307,6 +307,7 @@ "webgpu": [ "webgpu_audio_processing", "webgpu_backdrop", + "webgpu_backdrop_area", "webgpu_compute", "webgpu_cubemap_adjustments", "webgpu_cubemap_dynamic", diff --git a/examples/jsm/nodes/Nodes.js b/examples/jsm/nodes/Nodes.js index 9eaed9ad339f83..90a19fbbab3585 100644 --- a/examples/jsm/nodes/Nodes.js +++ b/examples/jsm/nodes/Nodes.js @@ -65,16 +65,17 @@ export * from './shadernode/ShaderNode.js'; export { default as BitangentNode, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, transformedBitangentView, transformedBitangentWorld } from './accessors/BitangentNode.js'; export { default as BufferAttributeNode, bufferAttribute, dynamicBufferAttribute } from './accessors/BufferAttributeNode.js'; export { default as BufferNode, buffer } from './accessors/BufferNode.js'; -export { default as CameraNode, cameraProjectionMatrix, cameraViewMatrix, cameraNormalMatrix, cameraWorldMatrix, cameraPosition } from './accessors/CameraNode.js'; +export { default as CameraNode, cameraProjectionMatrix, cameraViewMatrix, cameraNormalMatrix, cameraWorldMatrix, cameraPosition, cameraNear, cameraFar } from './accessors/CameraNode.js'; export { default as CubeTextureNode, cubeTexture } from './accessors/CubeTextureNode.js'; export { default as ExtendedMaterialNode, materialNormal } from './accessors/ExtendedMaterialNode.js'; export { default as InstanceNode, instance } from './accessors/InstanceNode.js'; export { default as MaterialNode, materialUV, materialAlphaTest, materialColor, materialShininess, materialEmissive, materialOpacity, materialSpecularColor, materialReflectivity, materialRoughness, materialMetalness, materialRotation } from './accessors/MaterialNode.js'; export { default as MaterialReferenceNode, materialReference } from './accessors/MaterialReferenceNode.js'; -export { default as ModelNode, modelDirection, modelViewMatrix, modelNormalMatrix, modelWorldMatrix, modelPosition, modelViewPosition } from './accessors/ModelNode.js'; +export { default as TextureBicubicNode, textureBicubic } from './accessors/TextureBicubicNode.js'; +export { default as ModelNode, modelDirection, modelViewMatrix, modelNormalMatrix, modelWorldMatrix, modelPosition, modelViewPosition, modelScale } from './accessors/ModelNode.js'; export { default as ModelViewProjectionNode, modelViewProjection } from './accessors/ModelViewProjectionNode.js'; export { default as NormalNode, normalGeometry, normalLocal, normalView, normalWorld, transformedNormalView, transformedNormalWorld } from './accessors/NormalNode.js'; -export { default as Object3DNode, objectDirection, objectViewMatrix, objectNormalMatrix, objectWorldMatrix, objectPosition, objectViewPosition } from './accessors/Object3DNode.js'; +export { default as Object3DNode, objectDirection, objectViewMatrix, objectNormalMatrix, objectWorldMatrix, objectPosition, objectScale, objectViewPosition } from './accessors/Object3DNode.js'; export { default as PointUVNode, pointUV } from './accessors/PointUVNode.js'; export { default as PositionNode, positionGeometry, positionLocal, positionWorld, positionWorldDirection, positionView, positionViewDirection } from './accessors/PositionNode.js'; export { default as ReferenceNode, reference } from './accessors/ReferenceNode.js'; @@ -82,7 +83,7 @@ export { default as ReflectVectorNode, reflectVector } from './accessors/Reflect export { default as SkinningNode, skinning } from './accessors/SkinningNode.js'; export { default as StorageBufferNode, storage } from './accessors/StorageBufferNode.js'; export { default as TangentNode, tangentGeometry, tangentLocal, tangentView, tangentWorld, transformedTangentView, transformedTangentWorld } from './accessors/TangentNode.js'; -export { default as TextureNode, texture, sampler } from './accessors/TextureNode.js'; +export { default as TextureNode, texture, /*textureLevel,*/ sampler } from './accessors/TextureNode.js'; export { default as UVNode, uv } from './accessors/UVNode.js'; export { default as UserDataNode, userData } from './accessors/UserDataNode.js'; @@ -95,8 +96,10 @@ export { default as NormalMapNode, normalMap, TBNViewMatrix } from './display/No export { default as PosterizeNode, posterize } from './display/PosterizeNode.js'; export { default as ToneMappingNode, toneMapping } from './display/ToneMappingNode.js'; export { default as ViewportNode, viewportCoordinate, viewportResolution, viewportTopLeft, viewportBottomLeft, viewportTopRight, viewportBottomRight } from './display/ViewportNode.js'; -export { default as ViewportTextureNode, viewportTexture } from './display/ViewportTextureNode.js'; +export { default as ViewportTextureNode, viewportTexture, viewportMipTexture } from './display/ViewportTextureNode.js'; export { default as ViewportSharedTextureNode, viewportSharedTexture } from './display/ViewportSharedTextureNode.js'; +export { default as ViewportDepthTextureNode, viewportDepthTexture } from './display/ViewportDepthTextureNode.js'; +export { default as ViewportDepthNode, viewZToOrthographicDepth, orthographicDepthToViewZ, viewZToPerspectiveDepth, perspectiveDepthToViewZ, depth, depthTexture } from './display/ViewportDepthNode.js'; // code export { default as ExpressionNode, expression } from './code/ExpressionNode.js'; diff --git a/examples/jsm/nodes/accessors/CameraNode.js b/examples/jsm/nodes/accessors/CameraNode.js index 7e41af5a01f62b..df37f6150be612 100644 --- a/examples/jsm/nodes/accessors/CameraNode.js +++ b/examples/jsm/nodes/accessors/CameraNode.js @@ -18,6 +18,10 @@ class CameraNode extends Object3DNode { return 'mat4'; + } else if ( scope === CameraNode.NEAR || scope === CameraNode.FAR ) { + + return 'float'; + } return super.getNodeType( builder ); @@ -30,13 +34,21 @@ class CameraNode extends Object3DNode { const uniformNode = this._uniformNode; const scope = this.scope; - if ( scope === CameraNode.PROJECTION_MATRIX ) { + if ( scope === CameraNode.VIEW_MATRIX ) { + + uniformNode.value = camera.matrixWorldInverse; + + } else if ( scope === CameraNode.PROJECTION_MATRIX ) { uniformNode.value = camera.projectionMatrix; - } else if ( scope === CameraNode.VIEW_MATRIX ) { + } else if ( scope === CameraNode.NEAR ) { - uniformNode.value = camera.matrixWorldInverse; + uniformNode.value = camera.near; + + } else if ( scope === CameraNode.FAR ) { + + uniformNode.value = camera.far; } else { @@ -56,6 +68,10 @@ class CameraNode extends Object3DNode { this._uniformNode.nodeType = 'mat4'; + } else if ( scope === CameraNode.NEAR || scope === CameraNode.FAR ) { + + this._uniformNode.nodeType = 'float'; + } return super.generate( builder ); @@ -65,10 +81,14 @@ class CameraNode extends Object3DNode { } CameraNode.PROJECTION_MATRIX = 'projectionMatrix'; +CameraNode.NEAR = 'near'; +CameraNode.FAR = 'far'; export default CameraNode; export const cameraProjectionMatrix = nodeImmutable( CameraNode, CameraNode.PROJECTION_MATRIX ); +export const cameraNear = nodeImmutable( CameraNode, CameraNode.NEAR ); +export const cameraFar = nodeImmutable( CameraNode, CameraNode.FAR ); export const cameraViewMatrix = nodeImmutable( CameraNode, CameraNode.VIEW_MATRIX ); export const cameraNormalMatrix = nodeImmutable( CameraNode, CameraNode.NORMAL_MATRIX ); export const cameraWorldMatrix = nodeImmutable( CameraNode, CameraNode.WORLD_MATRIX ); diff --git a/examples/jsm/nodes/accessors/ModelNode.js b/examples/jsm/nodes/accessors/ModelNode.js index d63adbd57b1242..831369a2fac17a 100644 --- a/examples/jsm/nodes/accessors/ModelNode.js +++ b/examples/jsm/nodes/accessors/ModelNode.js @@ -27,6 +27,7 @@ export const modelViewMatrix = nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX ) export const modelNormalMatrix = nodeImmutable( ModelNode, ModelNode.NORMAL_MATRIX ); export const modelWorldMatrix = nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX ); export const modelPosition = nodeImmutable( ModelNode, ModelNode.POSITION ); +export const modelScale = nodeImmutable( ModelNode, ModelNode.SCALE ); export const modelViewPosition = nodeImmutable( ModelNode, ModelNode.VIEW_POSITION ); addNodeClass( ModelNode ); diff --git a/examples/jsm/nodes/accessors/Object3DNode.js b/examples/jsm/nodes/accessors/Object3DNode.js index 516fc32a8d82bb..9cfa4505b08664 100644 --- a/examples/jsm/nodes/accessors/Object3DNode.js +++ b/examples/jsm/nodes/accessors/Object3DNode.js @@ -32,7 +32,7 @@ class Object3DNode extends Node { return 'mat3'; - } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION ) { + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { return 'vec3'; @@ -64,6 +64,12 @@ class Object3DNode extends Node { uniformNode.value.setFromMatrixPosition( object.matrixWorld ); + } else if ( scope === Object3DNode.SCALE ) { + + uniformNode.value = uniformNode.value || new Vector3(); + + uniformNode.value.setFromMatrixScale( object.matrixWorld ); + } else if ( scope === Object3DNode.DIRECTION ) { uniformNode.value = uniformNode.value || new Vector3(); @@ -95,7 +101,7 @@ class Object3DNode extends Node { this._uniformNode.nodeType = 'mat3'; - } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION ) { + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { this._uniformNode.nodeType = 'vec3'; @@ -127,6 +133,7 @@ Object3DNode.VIEW_MATRIX = 'viewMatrix'; Object3DNode.NORMAL_MATRIX = 'normalMatrix'; Object3DNode.WORLD_MATRIX = 'worldMatrix'; Object3DNode.POSITION = 'position'; +Object3DNode.SCALE = 'scale'; Object3DNode.VIEW_POSITION = 'viewPosition'; Object3DNode.DIRECTION = 'direction'; @@ -137,6 +144,7 @@ export const objectViewMatrix = nodeProxy( Object3DNode, Object3DNode.VIEW_MATRI export const objectNormalMatrix = nodeProxy( Object3DNode, Object3DNode.NORMAL_MATRIX ); export const objectWorldMatrix = nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX ); export const objectPosition = nodeProxy( Object3DNode, Object3DNode.POSITION ); +export const objectScale = nodeProxy( Object3DNode, Object3DNode.SCALE ); export const objectViewPosition = nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION ); addNodeClass( Object3DNode ); diff --git a/examples/jsm/nodes/accessors/TextureBicubicNode.js b/examples/jsm/nodes/accessors/TextureBicubicNode.js new file mode 100644 index 00000000000000..846450d8f12aca --- /dev/null +++ b/examples/jsm/nodes/accessors/TextureBicubicNode.js @@ -0,0 +1,94 @@ +import TempNode from '../core/TempNode.js'; +import { addNodeClass } from '../core/Node.js'; +import { add, mul, div } from '../math/OperatorNode.js'; +import { floor, ceil, fract, pow } from '../math/MathNode.js'; +import { nodeProxy, addNodeElement, float, vec2, vec4, int } from '../shadernode/ShaderNode.js'; + +// Mipped Bicubic Texture Filtering by N8 +// https://www.shadertoy.com/view/Dl2SDW + +const bC = 1.0 / 6.0; + +const w0 = ( a ) => mul( bC, mul( a, mul( a, a.negate().add( 3.0 ) ).sub( 3.0 ) ).add( 1.0 ) ); + +const w1 = ( a ) => mul( bC, mul( a, mul( a, mul( 3.0, a ).sub( 6.0 ) ) ).add( 4.0 ) ); + +const w2 = ( a ) => mul( bC, mul( a, mul( a, mul( - 3.0, a ).add( 3.0 ) ).add( 3.0 ) ).add( 1.0 ) ); + +const w3 = ( a ) => mul( bC, pow( a, 3 ) ); + +const g0 = ( a ) => w0( a ).add( w1( a ) ); + +const g1 = ( a ) => w2( a ).add( w3( a ) ); + +// h0 and h1 are the two offset functions +const h0 = ( a ) => add( - 1.0, w1( a ).div( w0( a ).add( w1( a ) ) ) ); + +const h1 = ( a ) => add( 1.0, w3( a ).div( w2( a ).add( w3( a ) ) ) ); + +const bicubic = ( textureNode, texelSize, lod ) => { + + const uv = textureNode.uvNode; + const uvScaled = mul( uv, texelSize.zw ).add( 0.5 ); + + const iuv = floor( uvScaled ); + const fuv = fract( uvScaled ); + + const g0x = g0( fuv.x ); + const g1x = g1( fuv.x ); + const h0x = h0( fuv.x ); + const h1x = h1( fuv.x ); + const h0y = h0( fuv.y ); + const h1y = h1( fuv.y ); + + const p0 = vec2( iuv.x.add( h0x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p1 = vec2( iuv.x.add( h1x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p2 = vec2( iuv.x.add( h0x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p3 = vec2( iuv.x.add( h1x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + + const a = g0( fuv.y ).mul( add( g0x.mul( textureNode.uv( p0 ).level( lod ) ), g1x.mul( textureNode.uv( p1 ).level( lod ) ) ) ); + const b = g1( fuv.y ).mul( add( g0x.mul( textureNode.uv( p2 ).level( lod ) ), g1x.mul( textureNode.uv( p3 ).level( lod ) ) ) ); + + return a.add( b ); + +}; + +const textureBicubicMethod = ( textureNode, lodNode ) => { + + const fLodSize = vec2( textureNode.size( int( lodNode ) ) ); + const cLodSize = vec2( textureNode.size( int( lodNode.add( 1.0 ) ) ) ); + const fLodSizeInv = div( 1.0, fLodSize ); + const cLodSizeInv = div( 1.0, cLodSize ); + const fSample = bicubic( textureNode, vec4( fLodSizeInv, fLodSize ), floor( lodNode ) ); + const cSample = bicubic( textureNode, vec4( cLodSizeInv, cLodSize ), ceil( lodNode ) ); + + return fract( lodNode ).mix( fSample, cSample ); + +}; + +class TextureBicubicNode extends TempNode { + + constructor( textureNode, blurNode = float( 3 ) ) { + + super( 'vec4' ); + + this.textureNode = textureNode; + this.blurNode = blurNode; + + } + + construct() { + + return textureBicubicMethod( this.textureNode, this.blurNode ); + + } + +} + +export default TextureBicubicNode; + +export const textureBicubic = nodeProxy( TextureBicubicNode ); + +addNodeElement( 'bicubic', textureBicubic ); + +addNodeClass( TextureBicubicNode ); diff --git a/examples/jsm/nodes/accessors/TextureNode.js b/examples/jsm/nodes/accessors/TextureNode.js index fce9e2f6fcfcdb..a2c33d40ec1c1c 100644 --- a/examples/jsm/nodes/accessors/TextureNode.js +++ b/examples/jsm/nodes/accessors/TextureNode.js @@ -1,5 +1,7 @@ import UniformNode from '../core/UniformNode.js'; import { uv } from './UVNode.js'; +import { textureSize } from './TextureSizeNode.js'; +import { context } from '../core/ContextNode.js'; import { addNodeClass } from '../core/Node.js'; import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; @@ -140,6 +142,32 @@ class TextureNode extends UniformNode { } + uv( uvNode ) { + + const textureNode = this.clone(); + textureNode.uvNode = uvNode; + + return textureNode; + + } + + level( levelNode ) { + + const textureNode = this.clone(); + textureNode.levelNode = levelNode; + + return context( textureNode, { + getMIPLevelAlgorithmNode: ( textureNode, levelNode ) => levelNode + } ); + + } + + size( levelNode ) { + + return textureSize( this, levelNode ); + + } + serialize( data ) { super.serialize( data ); @@ -156,13 +184,22 @@ class TextureNode extends UniformNode { } + clone() { + + return new this.constructor( this.value, this.uvNode, this.levelNode ); + + } + } export default TextureNode; export const texture = nodeProxy( TextureNode ); +//export const textureLevel = ( value, uv, level ) => texture( value, uv ).level( level ); + export const sampler = ( aTexture ) => ( aTexture.isNode === true ? aTexture : texture( aTexture ) ).convert( 'sampler' ); addNodeElement( 'texture', texture ); +//addNodeElement( 'textureLevel', textureLevel ); addNodeClass( TextureNode ); diff --git a/examples/jsm/nodes/accessors/TextureSizeNode.js b/examples/jsm/nodes/accessors/TextureSizeNode.js new file mode 100644 index 00000000000000..04501f1a16fdd1 --- /dev/null +++ b/examples/jsm/nodes/accessors/TextureSizeNode.js @@ -0,0 +1,35 @@ +import Node from '../core/Node.js'; +import { addNodeClass } from '../core/Node.js'; +import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; + +class TextureSizeNode extends Node { + + constructor( textureNode, levelNode = null ) { + + super( 'uvec2' ); + + this.isTextureSizeNode = true; + + this.textureNode = textureNode; + this.levelNode = levelNode; + + } + + generate( builder, output ) { + + const textureProperty = this.textureNode.build( builder, 'property' ); + const levelNode = this.levelNode.build( builder, 'int' ); + + return builder.format( `textureDimensions( ${textureProperty}, ${levelNode} )`, this.getNodeType( builder ), output ); + + } + +} + +export default TextureSizeNode; + +export const textureSize = nodeProxy( TextureSizeNode ); + +addNodeElement( 'textureSize', textureSize ); + +addNodeClass( TextureSizeNode ); diff --git a/examples/jsm/nodes/display/ViewportDepthNode.js b/examples/jsm/nodes/display/ViewportDepthNode.js new file mode 100644 index 00000000000000..7c31c7f4d6349e --- /dev/null +++ b/examples/jsm/nodes/display/ViewportDepthNode.js @@ -0,0 +1,69 @@ +import Node, { addNodeClass } from '../core/Node.js'; +import { nodeImmutable, nodeProxy } from '../shadernode/ShaderNode.js'; +import { cameraNear, cameraFar } from '../accessors/CameraNode.js'; +import { positionView } from '../accessors/PositionNode.js'; +import { viewportDepthTexture } from './ViewportDepthTextureNode.js'; + +class ViewportDepthNode extends Node { + + constructor( scope, textureNode = null ) { + + super( 'float' ); + + this.scope = scope; + this.textureNode = textureNode; + + this.isViewportDepthNode = true; + + } + + construct( /*builder*/ ) { + + const { scope } = this; + + let node = null; + + if ( scope === ViewportDepthNode.DEPTH ) { + + node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); + + } else if ( scope === ViewportDepthNode.DEPTH_TEXTURE ) { + + const texture = this.textureNode || viewportDepthTexture(); + + const viewZ = perspectiveDepthToViewZ( texture, cameraNear, cameraFar ); + node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); + + } + + return node; + + } + +} + +// NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera + +// -near maps to 0; -far maps to 1 +export const viewZToOrthographicDepth = ( viewZ, near, far ) => viewZ.add( near ).div( near.sub( far ) ); + +// maps orthographic depth in [ 0, 1 ] to viewZ +export const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).mul( depth ).sub( near ); + +// NOTE: https://twitter.com/gonnavis/status/1377183786949959682 + +// -near maps to 0; -far maps to 1 +export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( near.sub( far ).mul( viewZ ) ); + +// maps perspective depth in [ 0, 1 ] to viewZ +export const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) ); + +ViewportDepthNode.DEPTH = 'depth'; +ViewportDepthNode.DEPTH_TEXTURE = 'depthTexture'; + +export default ViewportDepthNode; + +export const depth = nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH ); +export const depthTexture = nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH_TEXTURE ); + +addNodeClass( ViewportDepthNode ); diff --git a/examples/jsm/nodes/display/ViewportDepthTextureNode.js b/examples/jsm/nodes/display/ViewportDepthTextureNode.js new file mode 100644 index 00000000000000..d090ad2b020b64 --- /dev/null +++ b/examples/jsm/nodes/display/ViewportDepthTextureNode.js @@ -0,0 +1,34 @@ +import ViewportTextureNode from './ViewportTextureNode.js'; +import { addNodeClass } from '../core/Node.js'; +import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; +import { viewportTopLeft } from './ViewportNode.js'; +import { DepthTexture, LinearMipmapLinearFilter, DepthFormat, UnsignedIntType } from 'three'; + +let sharedDepthbuffer = null; + +class ViewportDepthTextureNode extends ViewportTextureNode { + + constructor( uvNode = viewportTopLeft, levelNode = null ) { + + if ( sharedDepthbuffer === null ) { + + sharedDepthbuffer = new DepthTexture(); + sharedDepthbuffer.minFilter = LinearMipmapLinearFilter; + sharedDepthbuffer.type = UnsignedIntType; + sharedDepthbuffer.format = DepthFormat; + + } + + super( uvNode, levelNode, sharedDepthbuffer ); + + } + +} + +export default ViewportDepthTextureNode; + +export const viewportDepthTexture = nodeProxy( ViewportDepthTextureNode ); + +addNodeElement( 'viewportDepthTexture', viewportDepthTexture ); + +addNodeClass( ViewportDepthTextureNode ); diff --git a/examples/jsm/nodes/display/ViewportSharedTextureNode.js b/examples/jsm/nodes/display/ViewportSharedTextureNode.js index 108631ceb77921..853f26feeda7e6 100644 --- a/examples/jsm/nodes/display/ViewportSharedTextureNode.js +++ b/examples/jsm/nodes/display/ViewportSharedTextureNode.js @@ -2,20 +2,21 @@ import ViewportTextureNode from './ViewportTextureNode.js'; import { addNodeClass } from '../core/Node.js'; import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; import { viewportTopLeft } from './ViewportNode.js'; +import { FramebufferTexture } from 'three'; let sharedFramebuffer = null; class ViewportSharedTextureNode extends ViewportTextureNode { - constructor( uv = viewportTopLeft ) { + constructor( uvNode = viewportTopLeft, levelNode = null ) { - super( uv ); + if ( sharedFramebuffer === null ) { - } + sharedFramebuffer = new FramebufferTexture(); - constructFramebuffer( builder ) { + } - return sharedFramebuffer || ( sharedFramebuffer = super.constructFramebuffer( builder ) ); + super( uvNode, levelNode, sharedFramebuffer ); } diff --git a/examples/jsm/nodes/display/ViewportTextureNode.js b/examples/jsm/nodes/display/ViewportTextureNode.js index e1af41eb04ea1d..356f5c28b4681d 100644 --- a/examples/jsm/nodes/display/ViewportTextureNode.js +++ b/examples/jsm/nodes/display/ViewportTextureNode.js @@ -3,33 +3,28 @@ import { NodeUpdateType } from '../core/constants.js'; import { addNodeClass } from '../core/Node.js'; import { addNodeElement, nodeProxy } from '../shadernode/ShaderNode.js'; import { viewportTopLeft } from './ViewportNode.js'; -import { Vector2, FramebufferTexture } from 'three'; +import { Vector2, FramebufferTexture, LinearMipmapLinearFilter } from 'three'; const _size = new Vector2(); class ViewportTextureNode extends TextureNode { - constructor( uv = viewportTopLeft, level = null ) { + constructor( uvNode = viewportTopLeft, levelNode = null, framebufferTexture = null ) { - super( null, uv, level ); + if ( framebufferTexture === null ) { - this.isOutputTextureNode = true; - - this.updateBeforeType = NodeUpdateType.FRAME; - - } - - constructFramebuffer( /*builder*/ ) { + framebufferTexture = new FramebufferTexture(); + framebufferTexture.minFilter = LinearMipmapLinearFilter; - return new FramebufferTexture(); + } - } + super( framebufferTexture, uvNode, levelNode ); - construct( builder ) { + this.generateMipmaps = false; - if ( this.value === null ) this.value = this.constructFramebuffer( builder ); + this.isOutputTextureNode = true; - return super.construct( builder ); + this.updateBeforeType = NodeUpdateType.FRAME; } @@ -52,8 +47,19 @@ class ViewportTextureNode extends TextureNode { // + const currentGenerateMipmaps = framebufferTexture.generateMipmaps; + framebufferTexture.generateMipmaps = this.generateMipmaps; + renderer.copyFramebufferToTexture( framebufferTexture ); + framebufferTexture.generateMipmaps = currentGenerateMipmaps; + + } + + clone() { + + return new this.constructor( this.uvNode, this.levelNode, this.value ); + } } @@ -61,7 +67,9 @@ class ViewportTextureNode extends TextureNode { export default ViewportTextureNode; export const viewportTexture = nodeProxy( ViewportTextureNode ); +export const viewportMipTexture = nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } ); addNodeElement( 'viewportTexture', viewportTexture ); +addNodeElement( 'viewportMipTexture', viewportMipTexture ); addNodeClass( ViewportTextureNode ); diff --git a/examples/jsm/renderers/common/Renderer.js b/examples/jsm/renderers/common/Renderer.js index 77fb724074a53a..848b7f091b930b 100644 --- a/examples/jsm/renderers/common/Renderer.js +++ b/examples/jsm/renderers/common/Renderer.js @@ -42,6 +42,9 @@ class Renderer { this.sortObjects = true; + this.depth = true; + this.stencil = true; + // internals this._pixelRatio = 1; @@ -239,6 +242,9 @@ class Renderer { renderContext.scissorValue.copy( scissor ).multiplyScalar( pixelRatio ).floor(); renderContext.scissor = this._scissorTest && renderContext.scissorValue.equals( _screen ) === false; + renderContext.depth = this.depth; + renderContext.stencil = this.stencil; + // _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); diff --git a/examples/jsm/renderers/webgpu/WebGPUBackend.js b/examples/jsm/renderers/webgpu/WebGPUBackend.js index 203ed87903f58e..4b41c2372297c6 100644 --- a/examples/jsm/renderers/webgpu/WebGPUBackend.js +++ b/examples/jsm/renderers/webgpu/WebGPUBackend.js @@ -7,7 +7,7 @@ import { GPUFeatureName, GPUTextureFormat, GPULoadOp, GPUStoreOp, GPUIndexFormat import WebGPUNodeBuilder from './nodes/WGSLNodeBuilder.js'; import Backend from '../common/Backend.js'; -import { DepthFormat, WebGPUCoordinateSystem } from 'three'; +import { DepthTexture, DepthFormat, DepthStencilFormat, UnsignedInt248Type, UnsignedIntType, WebGPUCoordinateSystem } from 'three'; import WebGPUUtils from './utils/WebGPUUtils.js'; import WebGPUAttributeUtils from './utils/WebGPUAttributeUtils.js'; @@ -53,7 +53,8 @@ class WebGPUBackend extends Backend { this.device = null; this.context = null; this.colorBuffer = null; - this.depthBuffer = null; + + this.depthBuffers = new WeakMap(); this.utils = new WebGPUUtils( this ); this.attributeUtils = new WebGPUAttributeUtils( this ); @@ -184,7 +185,7 @@ class WebGPUBackend extends Backend { } - depthStencilAttachment.view = this.depthBuffer.createView(); + depthStencilAttachment.view = this._getDepthBufferGPU( renderContext ).createView(); } @@ -321,7 +322,7 @@ class WebGPUBackend extends Backend { } - descriptor.depthStencilAttachment.view = this.depthBuffer.createView(); + descriptor.depthStencilAttachment.view = this._getDepthBufferGPU( renderContext ).createView(); if ( color ) { @@ -670,7 +671,6 @@ class WebGPUBackend extends Backend { this._configureContext(); this._setupColorBuffer(); - this._setupDepthBuffer(); } @@ -696,30 +696,44 @@ class WebGPUBackend extends Backend { } - copyFramebufferToTexture( framebufferTexture, renderContext ) { + copyFramebufferToTexture( texture, renderContext ) { const renderContextData = this.get( renderContext ); const { encoder, descriptor } = renderContextData; - const sourceGPU = this.context.getCurrentTexture(); - const destinationGPU = this.get( framebufferTexture ).texture; + let sourceGPU = null; + + if ( texture.isFramebufferTexture ) { + + sourceGPU = this.context.getCurrentTexture(); + + } else if ( texture.isDepthTexture ) { + + sourceGPU = this._getDepthBufferGPU( renderContext ); + + } + + const destinationGPU = this.get( texture ).texture; renderContextData.currentPass.end(); encoder.copyTextureToTexture( { - texture: sourceGPU + texture: sourceGPU, + origin: { x: 0, y: 0, z: 0 } }, { - texture: destinationGPU + texture: destinationGPU }, [ - framebufferTexture.image.width, - framebufferTexture.image.height + texture.image.width, + texture.image.height ] ); + if ( texture.generateMipmaps ) this.textureUtils.generateMipmaps( texture ); + descriptor.colorAttachments[ 0 ].loadOp = GPULoadOp.Load; if ( renderContext.depth ) descriptor.depthStencilAttachment.depthLoadOp = GPULoadOp.Load; if ( renderContext.stencil ) descriptor.depthStencilAttachment.stencilLoadOp = GPULoadOp.Load; @@ -731,6 +745,65 @@ class WebGPUBackend extends Backend { // utils + _getDepthBufferGPU( renderContext ) { + + const { depthBuffers } = this; + const { width, height } = this.getDrawingBufferSize(); + + let depthTexture = depthBuffers.get( renderContext ); + + if ( depthTexture !== undefined && depthTexture.image.width === width && depthTexture.image.height === height ) { + + return this.get( depthTexture ).texture; + + } + + this._destroyDepthBufferGPU( renderContext ); + + depthTexture = new DepthTexture(); + depthTexture.name = 'depthBuffer'; + + if ( renderContext.stencil ) { + + depthTexture = new DepthTexture(); + depthTexture.format = DepthStencilFormat; + depthTexture.type = UnsignedInt248Type; + + } else if ( renderContext.depth ) { + + depthTexture = new DepthTexture(); + depthTexture.format = DepthFormat; + depthTexture.type = UnsignedIntType; + + } + + depthTexture.image.width = width; + depthTexture.image.height = height; + + this.textureUtils.createTexture( depthTexture, { sampleCount: this.parameters.sampleCount } ); + + depthBuffers.set( renderContext, depthTexture ); + + return this.get( depthTexture ).texture; + + } + + _destroyDepthBufferGPU( renderContext ) { + + const { depthBuffers } = this; + + const depthTexture = depthBuffers.get( renderContext ); + + if ( depthTexture !== undefined ) { + + this.textureUtils.destroyTexture( depthTexture ); + + depthBuffers.delete( renderContext ); + + } + + } + _configureContext() { this.context.configure( { @@ -763,26 +836,6 @@ class WebGPUBackend extends Backend { } - _setupDepthBuffer() { - - if ( this.depthBuffer ) this.depthBuffer.destroy(); - - const { width, height } = this.getDrawingBufferSize(); - - this.depthBuffer = this.device.createTexture( { - label: 'depthBuffer', - size: { - width: width, - height: height, - depthOrArrayLayers: 1 - }, - sampleCount: this.parameters.sampleCount, - format: GPUTextureFormat.Depth24PlusStencil8, - usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC - } ); - - } - } export default WebGPUBackend; diff --git a/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js b/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js index cf8c8033a7d9d1..b85aeffd353b16 100644 --- a/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js +++ b/examples/jsm/renderers/webgpu/utils/WebGPUTextureUtils.js @@ -86,7 +86,7 @@ class WebGPUTextureUtils { } - createTexture( texture ) { + createTexture( texture, options = {} ) { const backend = this.backend; const textureData = backend.get( texture ); @@ -104,9 +104,9 @@ class WebGPUTextureUtils { const mipLevelCount = this._getMipLevelCount( texture, width, height, needsMipmaps ); const format = texture.internalFormat || this._getFormat( texture ); //const sampleCount = texture.isRenderTargetTexture || texture.isDepthTexture ? backend.utils.getSampleCount( renderContext ) : 1; - const sampleCount = 1; + const sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1; - let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST; + let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC; if ( texture.isCompressedTexture !== true ) { diff --git a/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js b/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js index f99ed6eb88ee28..39d8d85d5b2990 100644 --- a/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js +++ b/examples/jsm/renderers/webgpu/utils/WebGPUUtils.js @@ -16,10 +16,14 @@ class WebGPUUtils { format = this.getTextureFormatGPU( renderContext.depthTexture ); - } else { + } else if ( renderContext.depth && renderContext.stencil ) { format = GPUTextureFormat.Depth24PlusStencil8; + } else if ( renderContext.depth ) { + + format = GPUTextureFormat.Depth24Plus; + } return format; diff --git a/examples/screenshots/webgpu_backdrop_area.jpg b/examples/screenshots/webgpu_backdrop_area.jpg new file mode 100644 index 0000000000000000000000000000000000000000..001fe203e0b94e476d12e5c1c76aa979a0fbc77f GIT binary patch literal 3413 zcmex=iF;N$`UAd82aiwDGkXk%h!W@hDLXJZFTlSKSKz#z!M@QZN*Gov5_lOQ9r zAmjfdjEjJ7WCc47=uik?WMXDvWn%|Afm;CRY-VPlV_AVN1*)tC$}zAAvI;30I#U-U>$dGXcJ4ZK_{h;?$4{I*b?NeztJkjIxOwa0qsLF4K70P+<*SdMK7aZ8?fZ|P zzZe;qA>IL!82$lzoRJ9>=IkK_0Zp(e6?1osf!KmTtr@Gvt1BaB&)!Jgq?{R@T#ObuKN n8l%)`5R9gR(Tp%!7K|2$qcy^4Z8%yRj@E|5u{QkA@c$+N?bpn5 literal 0 HcmV?d00001 diff --git a/examples/webgpu_backdrop_area.html b/examples/webgpu_backdrop_area.html new file mode 100644 index 00000000000000..5d5cd1a7f00d8a --- /dev/null +++ b/examples/webgpu_backdrop_area.html @@ -0,0 +1,181 @@ + + + + three.js - WebGPU - Backdrop Area + + + + + + +
+ three.js WebGPU - Backdrop Area +
+ + + + + + + + diff --git a/test/e2e/puppeteer.js b/test/e2e/puppeteer.js index 7e76a9a93825ac..43c3e5af4284e6 100644 --- a/test/e2e/puppeteer.js +++ b/test/e2e/puppeteer.js @@ -94,6 +94,7 @@ const exceptionList = [ // Awaiting for WebGPU support 'webgpu_audio_processing', 'webgpu_backdrop', + 'webgpu_backdrop_area', 'webgpu_compute', 'webgpu_cubemap_adjustments', 'webgpu_cubemap_dynamic', From 2b8f3608a4c645ba8f329958dcbe258c10ff480e Mon Sep 17 00:00:00 2001 From: Don McCurdy Date: Wed, 7 Jun 2023 13:00:42 -0400 Subject: [PATCH 7/7] Docs: Fix mistake in Color#getRGB signature. (#26210) --- docs/api/en/math/Color.html | 2 +- docs/api/it/math/Color.html | 2 +- docs/api/zh/math/Color.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/en/math/Color.html b/docs/api/en/math/Color.html index 010630b063127f..408ced10806d74 100644 --- a/docs/api/en/math/Color.html +++ b/docs/api/en/math/Color.html @@ -217,7 +217,7 @@

- [method:Color getRGB]( [param:Color target], [param:string colorSpace] = SRGBColorSpace ) + [method:Color getRGB]( [param:Color target], [param:string colorSpace] = LinearSRGBColorSpace )

[page:Color target] — the result will be copied into this object.

diff --git a/docs/api/it/math/Color.html b/docs/api/it/math/Color.html index 8460c5d8679e61..c4879fb67ead94 100644 --- a/docs/api/it/math/Color.html +++ b/docs/api/it/math/Color.html @@ -181,7 +181,7 @@

[method:Object getHSL]( [param:Object target], [param:string colorSpace] = L

-

[method:Color getRGB]( [param:Color target], [param:string colorSpace] = SRGBColorSpace )

+

[method:Color getRGB]( [param:Color target], [param:string colorSpace] = LinearSRGBColorSpace )

[page:Color target] - questo risultato sarà copiato in questo oggetto.

diff --git a/docs/api/zh/math/Color.html b/docs/api/zh/math/Color.html index 2e77617fb21007..8d31093444856b 100644 --- a/docs/api/zh/math/Color.html +++ b/docs/api/zh/math/Color.html @@ -182,7 +182,7 @@

[method:Object getHSL]( [param:Object target], [param:string colorSpace] = L

-

[method:Color getRGB]( [param:Color target], [param:string colorSpace] = SRGBColorSpace )

+

[method:Color getRGB]( [param:Color target], [param:string colorSpace] = LinearSRGBColorSpace )

[page:Color target] - 结果将复制到这个对象中.