@@ -130,6 +130,7 @@ const lightUniform = root.createUniform(DirectionalLight, {
130130} ) ;
131131
132132const jellyColorUniform = root . createUniform ( d . vec4f , d . vec4f ( 1.0 , 0.45 , 0.075 , 1.0 ) ) ;
133+ const jellyScatterUniform = root . createUniform ( d . f32 , JELLY_SCATTER_STRENGTH ) ;
133134const groundColorUniform = root . createUniform ( d . vec3f , d . vec3f ( 1.0 ) ) ;
134135const groundTextColorUniform = root . createUniform ( d . vec3f , d . vec3f ( 0.5 ) ) ;
135136
@@ -700,7 +701,7 @@ const rayMarch = (rayOrigin: d.v3f, rayDirection: d.v3f, _uv: d.v2f) => {
700701 const lightDir = std . neg ( lightUniform . $ . direction ) ;
701702
702703 const forward = std . max ( 0.0 , std . dot ( lightDir , refrDir ) ) ;
703- const scatter = scatterTint . mul ( JELLY_SCATTER_STRENGTH * forward * progress ** 3 ) ;
704+ const scatter = scatterTint . mul ( jellyScatterUniform . $ * forward * progress ** 3 ) ;
704705 refractedColor = env . mul ( T ) . add ( scatter ) ;
705706 }
706707
@@ -797,7 +798,15 @@ function render(timestamp: number) {
797798
798799 randomUniform . write ( d . vec2f ( ( Math . random ( ) - 0.5 ) * 2 , ( Math . random ( ) - 0.5 ) * 2 ) ) ;
799800
800- currentMouseX += ( targetMouseX - currentMouseX ) * 0.08 ;
801+ const reduce = motionMedia . matches || transparencyMedia . matches ;
802+ if ( reduce ) {
803+ currentMouseX = targetMouseX ;
804+ slider . restLen = Math . max ( 0.001 , Math . abs ( currentMouseX - slider . anchor [ 0 ] ) ) / ( slider . n - 1 ) ;
805+ } else {
806+ currentMouseX += ( targetMouseX - currentMouseX ) * 0.08 ;
807+ slider . restLen = 1.9 / ( slider . n - 1 ) ;
808+ }
809+
801810 slider . setDragX ( currentMouseX ) ;
802811 slider . update ( deltaTime ) ;
803812
@@ -845,6 +854,27 @@ const hcMedia = window.matchMedia('(forced-colors: active)');
845854const darkMedia = window . matchMedia ( '(prefers-color-scheme: dark)' ) ;
846855const contrastMedia = window . matchMedia ( '(prefers-contrast: more)' ) ;
847856
857+ const motionMedia = window . matchMedia ( '(prefers-reduced-motion: reduce)' ) ;
858+ const transparencyMedia = window . matchMedia ( '(prefers-reduced-transparency: reduce)' ) ;
859+
860+ const updateReducedFeatures = ( ) => {
861+ const reduce = motionMedia . matches || transparencyMedia . matches ;
862+
863+ if ( reduce ) {
864+ slider . damping = 1.0 ;
865+ slider . archStrength = 0.0 ;
866+ jellyScatterUniform . write ( 0.0 ) ;
867+ } else {
868+ slider . damping = 0.01 ;
869+ slider . archStrength = 2.0 ;
870+ jellyScatterUniform . write ( JELLY_SCATTER_STRENGTH ) ;
871+ }
872+ } ;
873+
874+ motionMedia . addEventListener ( 'change' , updateReducedFeatures ) ;
875+ transparencyMedia . addEventListener ( 'change' , updateReducedFeatures ) ;
876+ updateReducedFeatures ( ) ;
877+
848878const parseColor3 = ( colorStr : string ) : d . Infer < typeof d . vec3f > => {
849879 const match = colorStr . match ( / r g b a ? \( ( \d + ) , \s * ( \d + ) , \s * ( \d + ) / ) ;
850880 if ( match ) {
@@ -885,6 +915,8 @@ export function onCleanup() {
885915 hcMedia . removeEventListener ( 'change' , updateColors ) ;
886916 darkMedia . removeEventListener ( 'change' , updateColors ) ;
887917 contrastMedia . removeEventListener ( 'change' , updateColors ) ;
918+ motionMedia . removeEventListener ( 'change' , updateReducedFeatures ) ;
919+ transparencyMedia . removeEventListener ( 'change' , updateReducedFeatures ) ;
888920 cancelAnimationFrame ( animationFrameHandle ) ;
889921 resizeObserver . disconnect ( ) ;
890922 root . destroy ( ) ;
0 commit comments