Files
WebGPU-FFT-Ocean-Demo/events.js
2025-12-31 14:22:45 +01:00

480 lines
8.3 KiB
JavaScript

export class events {
getDomElements( ) {
const statusElement = document.getElementById( "status" );
const canvas = document.getElementById( "gfx" );
const waveHeightSlider = document.getElementById( "waveHeight" );
const waveHeightValue = document.getElementById( "waveHeightValue" );
const wavelengthSlider = document.getElementById( "wavelengthSlider" );
const wavelengthValue = document.getElementById( "wavelengthValue" );
const resolutionSlider = document.getElementById( "resolutionSlider" );
const resolutionValue = document.getElementById( "resolutionValue" );
const tilingSlider = document.getElementById( "tilingSlider" );
const tilingValue = document.getElementById( "tilingValue" );
const wireframeToggle = document.getElementById( "wireframeToggle" );
const pauseToggle = document.getElementById( "pauseToggle" );
const shadingModeSelect = document.getElementById( "shadingMode" );
const stepButton = document.getElementById( "stepButton" );
const dumpHeightButton = document.getElementById( "dumpHeightButton" );
return {
statusElement,
canvas,
waveHeightSlider,
waveHeightValue,
wavelengthSlider,
wavelengthValue,
resolutionSlider,
resolutionValue,
tilingSlider,
tilingValue,
wireframeToggle,
pauseToggle,
shadingModeSelect,
stepButton,
dumpHeightButton
};
}
setup( ) {
const domElements = this.getDomElements( );
const waveHeightSlider = domElements.waveHeightSlider;
const waveHeightValue = domElements.waveHeightValue;
const wavelengthSlider = domElements.wavelengthSlider;
const wavelengthValue = domElements.wavelengthValue;
const resolutionSlider = domElements.resolutionSlider;
const resolutionValue = domElements.resolutionValue;
const tilingSlider = domElements.tilingSlider;
const tilingValue = domElements.tilingValue;
const wireframeToggle = domElements.wireframeToggle;
const pauseToggle = domElements.pauseToggle;
const shadingModeSelect = domElements.shadingModeSelect;
const stepButton = domElements.stepButton;
const dumpHeightButton = domElements.dumpHeightButton;
const getPrimaryPipeline = this.getPrimaryPipeline;
const getPipelines = this.getPipelines;
const rebuildScene = this.rebuildScene;
const getScene = this.getScene;
const getRenderSystem = this.getRenderSystem;
if ( this.resizeCanvasToDisplay ) {
window.addEventListener( "resize", function( ) {
this.resizeCanvasToDisplay( );
}.bind( this ) );
}
const self = this;
if ( waveHeightSlider && waveHeightValue ) {
const primary = getPrimaryPipeline( );
waveHeightSlider.value = primary ? String( primary.heightScale ) : "33";
waveHeightValue.textContent = primary ? primary.heightScale.toFixed( 0 ) : "33";
waveHeightSlider.addEventListener( "input", function( event ) {
const target = event.target;
const value = parseFloat( target.value );
if ( isNaN( value ) ) {
return;
}
const pipelines = getPipelines( );
for ( const p of pipelines ) {
p.setHeightScale( value );
}
waveHeightValue.textContent = value.toFixed( 0 );
} );
}
if ( wavelengthSlider && wavelengthValue ) {
const primary = getPrimaryPipeline( );
const initialWavelength = primary && typeof primary.wavelengthScale === "number"
? primary.wavelengthScale
: 1.0;
wavelengthSlider.value = String( initialWavelength );
wavelengthValue.textContent = initialWavelength.toFixed( 2 );
wavelengthSlider.addEventListener( "input", function( event ) {
const target = event.target;
const value = parseFloat( target.value );
if ( isNaN( value ) || value <= 0 ) {
return;
}
if ( self.setCurrentWavelengthScale ) {
self.setCurrentWavelengthScale( value );
}
const pipelines = getPipelines( );
for ( const p of pipelines ) {
if ( typeof p.setWavelengthScale === "function" ) {
p.setWavelengthScale( value );
}
}
wavelengthValue.textContent = value.toFixed( 2 );
} );
}
if ( wireframeToggle ) {
const primary = getPrimaryPipeline( );
wireframeToggle.checked = primary ? primary.renderMode === "wireframe" : false;
wireframeToggle.addEventListener( "change", function( event ) {
const target = event.target;
const pipelines = getPipelines( );
if ( target.checked ) {
for ( const p of pipelines ) {
p.setRenderMode( "wireframe" );
}
} else {
for ( const p of pipelines ) {
p.setRenderMode( "solid" );
}
}
rebuildScene( );
} );
}
if ( pauseToggle ) {
pauseToggle.checked = false;
pauseToggle.addEventListener( "change", function( event ) {
const target = event.target;
const pipelines = getPipelines( );
for ( const p of pipelines ) {
p.setPaused( target.checked );
}
} );
}
if ( shadingModeSelect ) {
shadingModeSelect.value = "lighting";
shadingModeSelect.addEventListener( "change", function( event ) {
const target = event.target;
const value = target.value;
const pipelines = getPipelines( );
for ( const p of pipelines ) {
p.setShadingMode( value );
}
} );
}
if ( stepButton ) {
stepButton.addEventListener( "click", function( ) {
const pipelines = getPipelines( );
for ( const p of pipelines ) {
p.stepOnce( 1 / 60 );
}
const scene = getScene( );
const renderSystem = getRenderSystem( );
if ( scene && renderSystem ) {
renderSystem.render( scene );
}
} );
}
if ( dumpHeightButton ) {
dumpHeightButton.addEventListener( "click", function( ) {
const pipeline = getPrimaryPipeline( );
if ( !pipeline ) {
return;
}
const block = pipeline.getBlockByName( "ocean" );
if ( !block ) {
return;
}
const colPass = block.getPass( "ColFFT" );
if ( !colPass || !colPass.shader ) {
return;
}
colPass.shader.debugBuffer( "heightField" )
.then( function( data ) {
if ( !data || !data.length ) {
console.log( "heightField debug: empty buffer" );
return;
}
let min = data[ 0 ];
let max = data[ 0 ];
let sum = 0;
for ( let i = 0; i < data.length; i++ ) {
const v = data[ i ];
if ( v < min ) min = v;
if ( v > max ) max = v;
sum += v;
}
const avg = sum / data.length;
console.log( "heightField debug:",
"size =", data.length,
"min =", min,
"max =", max,
"avg =", avg
);
} )
.catch( function( error ) {
console.error( "heightField debug failed:", error );
} );
} );
}
if ( resolutionSlider && resolutionValue ) {
const applyResolutionFromSlider = function( ) {
const raw = parseFloat( resolutionSlider.value );
if ( isNaN( raw ) ) {
return;
}
let targetSize = 64;
if ( raw < 48 ) {
targetSize = 32;
} else if ( raw < 96 ) {
targetSize = 64;
} else if ( raw < 192 ) {
targetSize = 128;
} else if ( raw < 384 ) {
targetSize = 256;
} else if ( raw < 768 ) {
targetSize = 512;
} else if ( raw < 1536 ) {
targetSize = 1024;
} else {
targetSize = 2048;
}
resolutionSlider.value = String( targetSize );
resolutionValue.textContent = String( targetSize );
if ( self.setCurrentMeshResolution ) {
self.setCurrentMeshResolution( targetSize );
}
rebuildScene( );
};
applyResolutionFromSlider( );
resolutionSlider.addEventListener( "input", function( ) {
applyResolutionFromSlider( );
} );
}
if ( tilingSlider && tilingValue ) {
const applyTilingFromSlider = function( ) {
const raw = parseInt( tilingSlider.value, 10 );
if ( isNaN( raw ) || raw < 1 ) {
return;
}
const tileRange = raw - 1;
tilingValue.textContent = String( raw );
if ( self.setCurrentTiling ) {
self.setCurrentTiling( raw );
}
rebuildScene( );
};
applyTilingFromSlider( );
tilingSlider.addEventListener( "input", function( ) {
applyTilingFromSlider( );
} );
}
if ( domElements.canvas && this.setAutoRotate ) {
domElements.canvas.addEventListener( "pointerdown", function( ) {
this.setAutoRotate( false );
}.bind( this ) );
}
}
}