rayzee 4.8.11 → 4.8.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/rayzee.es.js +57 -31
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +1 -1
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/Passes/OIDNDenoiser.js +54 -17
package/package.json
CHANGED
|
@@ -383,23 +383,53 @@ export class OIDNDenoiser extends EventDispatcher {
|
|
|
383
383
|
// Ensure storage buffers are sized correctly (recreate on resolution change)
|
|
384
384
|
this._ensureGPUInputBuffers( width, height );
|
|
385
385
|
|
|
386
|
-
// Copy render target textures → GPU storage buffers
|
|
387
|
-
// copyTextureToBuffer requires
|
|
388
|
-
//
|
|
386
|
+
// Copy render target textures → tightly packed GPU storage buffers for oidn-web.
|
|
387
|
+
// copyTextureToBuffer requires bytesPerRow to be a multiple of 256. When the tight
|
|
388
|
+
// row size (width * 16) isn't aligned, copy via a padded staging buffer per texture
|
|
389
|
+
// then strip padding row-by-row.
|
|
389
390
|
const encoder = device.createCommandEncoder( { label: 'oidn-tex-to-buf' } );
|
|
390
|
-
const
|
|
391
|
+
const tightRowBytes = width * 16; // rgba32float
|
|
392
|
+
const paddedRowBytes = Math.ceil( tightRowBytes / 256 ) * 256;
|
|
393
|
+
const needsPadStrip = paddedRowBytes !== tightRowBytes;
|
|
394
|
+
const stagingBufs = [];
|
|
391
395
|
|
|
392
|
-
const copyTex = ( tex,
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
396
|
+
const copyTex = ( tex, tightBuf ) => {
|
|
397
|
+
|
|
398
|
+
if ( ! needsPadStrip ) {
|
|
399
|
+
|
|
400
|
+
encoder.copyTextureToBuffer(
|
|
401
|
+
{ texture: tex, mipLevel: 0 },
|
|
402
|
+
{ buffer: tightBuf, offset: 0, bytesPerRow: tightRowBytes, rowsPerImage: height },
|
|
403
|
+
{ width, height, depthOrArrayLayers: 1 }
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
} else {
|
|
407
|
+
|
|
408
|
+
const padBuf = device.createBuffer( { size: paddedRowBytes * height, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC } );
|
|
409
|
+
stagingBufs.push( padBuf );
|
|
410
|
+
|
|
411
|
+
encoder.copyTextureToBuffer(
|
|
412
|
+
{ texture: tex, mipLevel: 0 },
|
|
413
|
+
{ buffer: padBuf, offset: 0, bytesPerRow: paddedRowBytes, rowsPerImage: height },
|
|
414
|
+
{ width, height, depthOrArrayLayers: 1 }
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
for ( let row = 0; row < height; row ++ ) {
|
|
418
|
+
|
|
419
|
+
encoder.copyBufferToBuffer( padBuf, row * paddedRowBytes, tightBuf, row * tightRowBytes, tightRowBytes );
|
|
420
|
+
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
};
|
|
397
426
|
|
|
398
427
|
copyTex( textures.color, this._gpuInputBuffers.color );
|
|
399
428
|
copyTex( textures.albedo, this._gpuInputBuffers.albedo );
|
|
400
429
|
copyTex( textures.normal, this._gpuInputBuffers.normal );
|
|
401
430
|
|
|
402
431
|
device.queue.submit( [ encoder.finish() ] );
|
|
432
|
+
for ( const buf of stagingBufs ) buf.destroy();
|
|
403
433
|
|
|
404
434
|
// Cache alpha channel from input color buffer when transparent background is enabled.
|
|
405
435
|
// OIDN only processes RGB — the alpha channel is lost, so we read it before denoising.
|
|
@@ -440,7 +470,7 @@ export class OIDNDenoiser extends EventDispatcher {
|
|
|
440
470
|
this._destroyGPUInputBuffers();
|
|
441
471
|
|
|
442
472
|
const device = this.gpuDevice;
|
|
443
|
-
const byteSize = width * height *
|
|
473
|
+
const byteSize = width * height * 16; // rgba32float, tightly packed for oidn-web
|
|
444
474
|
const usage = GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC;
|
|
445
475
|
|
|
446
476
|
this._gpuInputBuffers.color = device.createBuffer( { label: 'oidn-in-color', size: byteSize, usage } );
|
|
@@ -466,7 +496,7 @@ export class OIDNDenoiser extends EventDispatcher {
|
|
|
466
496
|
*/
|
|
467
497
|
async _cacheInputAlpha( device, width, height ) {
|
|
468
498
|
|
|
469
|
-
const byteSize = width * height *
|
|
499
|
+
const byteSize = width * height * 16; // rgba32float, tightly packed
|
|
470
500
|
const staging = device.createBuffer( {
|
|
471
501
|
label: 'oidn-alpha-staging',
|
|
472
502
|
size: byteSize,
|
|
@@ -565,9 +595,16 @@ export class OIDNDenoiser extends EventDispatcher {
|
|
|
565
595
|
|
|
566
596
|
const device = this.gpuDevice;
|
|
567
597
|
const fullWidth = outputData.width;
|
|
598
|
+
const fullHeight = outputData.height;
|
|
568
599
|
const bytesPerPixel = 16; // rgba32float = 4 × float32
|
|
569
|
-
|
|
570
|
-
|
|
600
|
+
|
|
601
|
+
// Clamp tile to image bounds (edge tiles may extend past the image)
|
|
602
|
+
const clampedW = Math.min( tile.width, fullWidth - tile.x );
|
|
603
|
+
const clampedH = Math.min( tile.height, fullHeight - tile.y );
|
|
604
|
+
if ( clampedW <= 0 || clampedH <= 0 ) return;
|
|
605
|
+
|
|
606
|
+
const tileRowBytes = clampedW * bytesPerPixel;
|
|
607
|
+
const tileByteSize = clampedW * clampedH * bytesPerPixel;
|
|
571
608
|
|
|
572
609
|
const staging = device.createBuffer( {
|
|
573
610
|
size: tileByteSize,
|
|
@@ -577,7 +614,7 @@ export class OIDNDenoiser extends EventDispatcher {
|
|
|
577
614
|
// Copy each tile row from its position in the full output buffer
|
|
578
615
|
const enc = device.createCommandEncoder();
|
|
579
616
|
|
|
580
|
-
for ( let row = 0; row <
|
|
617
|
+
for ( let row = 0; row < clampedH; row ++ ) {
|
|
581
618
|
|
|
582
619
|
const srcOffset = ( ( tile.y + row ) * fullWidth + tile.x ) * bytesPerPixel;
|
|
583
620
|
const dstOffset = row * tileRowBytes;
|
|
@@ -591,7 +628,7 @@ export class OIDNDenoiser extends EventDispatcher {
|
|
|
591
628
|
staging.mapAsync( GPUMapMode.READ ).then( () => {
|
|
592
629
|
|
|
593
630
|
const f32 = new Float32Array( staging.getMappedRange() );
|
|
594
|
-
const tileImageData = new ImageData(
|
|
631
|
+
const tileImageData = new ImageData( clampedW, clampedH );
|
|
595
632
|
const exposure = this.getExposure();
|
|
596
633
|
const saturation = this.getSaturation();
|
|
597
634
|
const tmFn = TONE_MAP_FNS.get( this.getToneMapping() ) || TONE_MAP_FNS.get( ACESFilmicToneMapping );
|
|
@@ -617,8 +654,8 @@ export class OIDNDenoiser extends EventDispatcher {
|
|
|
617
654
|
|
|
618
655
|
if ( alpha ) {
|
|
619
656
|
|
|
620
|
-
const px = ( i >> 2 ) %
|
|
621
|
-
const py = ( i >> 2 ) /
|
|
657
|
+
const px = ( i >> 2 ) % clampedW;
|
|
658
|
+
const py = ( i >> 2 ) / clampedW | 0;
|
|
622
659
|
tileImageData.data[ i + 3 ] = alpha[ ( tile.y + py ) * alphaW + tile.x + px ];
|
|
623
660
|
|
|
624
661
|
} else {
|