import { timedResult } from "@thi.ng/bench/timed" ; import { hueRgb } from "@thi.ng/color/rgb/hue-rgb" ; import type { FloatSym , Vec2Sym , Vec3Sym } from "@thi.ng/shader-ast" ; import { renderPixels , targetJS } from "@thi.ng/shader-ast-js" ; import { fogExp2 } from "@thi.ng/shader-ast-stdlib/fog/exp2" ; import { diffuseLighting , halfLambert , } from "@thi.ng/shader-ast-stdlib/light/lambert" ; import { clamp01 } from "@thi.ng/shader-ast-stdlib/math/clamp" ; import { fit1101 } from "@thi.ng/shader-ast-stdlib/math/fit" ; import { lookat } from "@thi.ng/shader-ast-stdlib/matrix/lookat" ; import { raymarchAO } from "@thi.ng/shader-ast-stdlib/raymarch/ao" ; import { raymarchDir } from "@thi.ng/shader-ast-stdlib/raymarch/direction" ; import { raymarchNormal } from "@thi.ng/shader-ast-stdlib/raymarch/normal" ; import { rayPointAt } from "@thi.ng/shader-ast-stdlib/raymarch/point-at" ; import { raymarchScene } from "@thi.ng/shader-ast-stdlib/raymarch/scene" ; import { sdfBox3 } from "@thi.ng/shader-ast-stdlib/sdf/box" ; import { sdfRepeat3 } from "@thi.ng/shader-ast-stdlib/sdf/repeat" ; import { sdfSmoothUnion } from "@thi.ng/shader-ast-stdlib/sdf/smooth-union" ; import { sdfSphere } from "@thi.ng/shader-ast-stdlib/sdf/sphere" ; import { assign } from "@thi.ng/shader-ast/ast/assign" ; import { ifThen } from "@thi.ng/shader-ast/ast/controlflow" ; import { defn , ret } from "@thi.ng/shader-ast/ast/function" ; import { float , vec2 , vec3 , vec4 } from "@thi.ng/shader-ast/ast/lit" ; import { gte , mul } from "@thi.ng/shader-ast/ast/ops" ; import { program } from "@thi.ng/shader-ast/ast/scope" ; import { $x , $xyz } from "@thi.ng/shader-ast/ast/swizzle" ; import { sym } from "@thi.ng/shader-ast/ast/sym" ; import { mix } from "@thi.ng/shader-ast/builtin/math" ; import { sma } from "@thi.ng/transducers-stats/sma" ; import { comp } from "@thi.ng/transducers/comp" ; import { map } from "@thi.ng/transducers/map" ; import { normRange } from "@thi.ng/transducers/norm-range" ; import { slidingWindow } from "@thi.ng/transducers/sliding-window" ; import { step } from "@thi.ng/transducers/step" ; import { NUM_WORKERS , type , WorkerJob , type , WorkerResult } from "./api" ; const COLORS = [ ... map ( ( i ) => hueRgb ( [ ] , i ) , normRange ( NUM_WORKERS ) ) ] ; const scene = defn ( "vec2" , "scene" , [ "vec3" ] , ( pos ) => { let d1 ; let d2 ; let d3 ; let d4 ; return [ assign ( pos , sdfRepeat3 ( pos , vec3 ( 2.1 ) ) ) , ( d1 = sym ( sdfSphere ( pos , float ( 0.5 ) ) ) ) , ( d2 = sym ( sdfBox3 ( pos , vec3 ( 1 , 0.2 , 0.2 ) ) ) ) , ( d3 = sym ( sdfBox3 ( pos , vec3 ( 0.2 , 0.2 , 1 ) ) ) ) , ( d4 = sym ( sdfBox3 ( pos , vec3 ( 0.2 , 1 , 0.2 ) ) ) ) , ret ( vec2 ( sdfSmoothUnion ( sdfSmoothUnion ( sdfSmoothUnion ( d1 , d2 , float ( 0.2 ) ) , d3 , float ( 0.2 ) ) , d4 , float ( 0.2 ) ) , 1 ) ) , ] ; } ) ; const mainImage = defn ( "vec4" , "mainImage" , [ "vec2" , "vec2" , "vec3" , "vec3" , "vec3" ] , ( frag , res , eyePos , lightDir , tint ) => { let dir ; let result ; let isec ; let norm ; let material ; let diffuse ; const bg = vec3 ( 0.9 ) ; const ambient = vec3 ( 0.15 ) ; return [ ( dir = sym ( $xyz ( mul ( lookat ( eyePos , vec3 ( ) , vec3 ( 0 , 1 , 0 ) ) , vec4 ( raymarchDir ( frag , res , float ( 120 ) ) , 0 ) ) ) ) ) , ( result = sym ( raymarchScene ( scene , { steps : 80 , eps : 0.005 } ) ( eyePos , dir ) ) ) , ifThen ( gte ( $x ( result ) , float ( 10 ) ) , [ ret ( vec4 ( mul ( bg , tint ) , 1 ) ) ] ) , ( isec = sym ( rayPointAt ( eyePos , dir , $x ( result ) ) ) ) , ( norm = sym ( raymarchNormal ( scene ) ( isec , float ( 0.01 ) ) ) ) , ( material = sym ( fit1101 ( isec ) ) ) , ( diffuse = sym ( mul ( halfLambert ( norm , lightDir ) , raymarchAO ( scene ) ( isec , norm ) ) ) ) , ret ( vec4 ( mul ( mix ( clamp01 ( diffuseLighting ( diffuse , material , vec3 ( 1 ) , ambient ) ) , bg , fogExp2 ( $x ( result ) , float ( 0.2 ) ) ) , tint ) , 1 ) ) , ] ; } ) ; const shaderFunc = targetJS ( ) . compile ( program ( [ mainImage ] ) ) . mainImage ; const stats = step ( comp ( sma ( 10 ) , slidingWindow ( 24 ) ) ) ; const $self = < any > self ; self . addEventListener ( "message" , ( e ) => { const job = < WorkerJob > e . data ; const h = job . y2 - job . y1 ; const [ buf , time ] = timedResult ( ( ) => renderPixels ( ( frag ) => shaderFunc ( frag , [ job . width , job . height ] , [ Math . cos ( job . time ) * 2.5 , Math . cos ( job . time / 2 ) * 0.7 , Math . sin ( job . time ) * 2.5 , ] , [ 0.707 , 0.707 , 0 ] , COLORS [ job . id ] ) , new Uint32Array ( job . width * h ) , job . width , h , 0 , 0 , job . width , h , 0 , job . y1 , job . height ) ) ; $self . postMessage ( < WorkerResult > { buf , stats : stats ( time ) } , [ buf . buffer ] ) ; } ) ;