framefields 2.13.1 → 2.15.0
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/NOTICE.md +5 -1
- package/dist/audio/index.d.mts +5 -5
- package/dist/audio/index.mjs +10 -10
- package/dist/{audio-DIvi6hTD.mjs → audio-6TfPlfl4.mjs} +3 -3
- package/dist/{audio-DIvi6hTD.mjs.map → audio-6TfPlfl4.mjs.map} +1 -1
- package/dist/{audio-C4B9p_yq.d.mts → audio-7oqTUi4G.d.mts} +3 -3
- package/dist/{audio-C4B9p_yq.d.mts.map → audio-7oqTUi4G.d.mts.map} +1 -1
- package/dist/cli/check-worker.mjs +44 -44
- package/dist/cli.mjs +1 -1
- package/dist/cloud/index.d.mts.map +1 -1
- package/dist/cloud/index.mjs +1 -1
- package/dist/{cloud-Cj1TIme8.mjs → cloud-jnk1hPYf.mjs} +2 -2
- package/dist/{cloud-Cj1TIme8.mjs.map → cloud-jnk1hPYf.mjs.map} +1 -1
- package/dist/components/index.d.mts +13 -13
- package/dist/components/index.mjs +43 -43
- package/dist/{dist-Kbf-JTry.mjs → dist-BtI6ukB5.mjs} +2 -2
- package/dist/{dist-Kbf-JTry.mjs.map → dist-BtI6ukB5.mjs.map} +1 -1
- package/dist/{dist-CCrYOkcc.mjs → dist-COOpgG9G.mjs} +4 -3
- package/dist/{dist-CCrYOkcc.mjs.map → dist-COOpgG9G.mjs.map} +1 -1
- package/dist/{dist-DtPPPsZV.mjs → dist-XqlFM2a8.mjs} +14063 -5308
- package/dist/dist-XqlFM2a8.mjs.map +1 -0
- package/dist/{dist-CiTgmfUw.mjs → dist-f1zkl69f.mjs} +4 -4
- package/dist/dist-f1zkl69f.mjs.map +1 -0
- package/dist/{dist-B_rSWeOz.mjs → dist-umQOWz0a.mjs} +1 -1
- package/dist/effects/index.d.mts +5 -5
- package/dist/effects/index.mjs +35 -35
- package/dist/{effects-B-L3rLs6.mjs → effects-DlRMovU5.mjs} +2 -2
- package/dist/{effects-B-L3rLs6.mjs.map → effects-DlRMovU5.mjs.map} +1 -1
- package/dist/fonts/index.d.mts +1 -1
- package/dist/fonts/index.mjs +2 -2
- package/dist/{fonts-k5ll8NTE.mjs → fonts-BWYcXjyK.mjs} +3 -3
- package/dist/fonts-BWYcXjyK.mjs.map +1 -0
- package/dist/{gpu-D2HT3KcE.mjs → gpu-CH1PdM4T.mjs} +2 -2
- package/dist/{gpu-D2HT3KcE.mjs.map → gpu-CH1PdM4T.mjs.map} +1 -1
- package/dist/{index-rtCXNxGO.d.mts → index-BHTycml5.d.mts} +2 -2
- package/dist/{index-rtCXNxGO.d.mts.map → index-BHTycml5.d.mts.map} +1 -1
- package/dist/{index-BFTtXosj.d.mts → index-BVd6nXd5.d.mts} +2 -2
- package/dist/{index-BFTtXosj.d.mts.map → index-BVd6nXd5.d.mts.map} +1 -1
- package/dist/{index-ByhlTwxh.d.mts → index-BcxxxwhV.d.mts} +5 -5
- package/dist/{index-ByhlTwxh.d.mts.map → index-BcxxxwhV.d.mts.map} +1 -1
- package/dist/{index-CnZhBlob.d.mts → index-BnB_Ou2y.d.mts} +2 -2
- package/dist/index-BnB_Ou2y.d.mts.map +1 -0
- package/dist/{index-a6JrbAK0.d.mts → index-C-V6CAhP.d.mts} +32 -2
- package/dist/index-C-V6CAhP.d.mts.map +1 -0
- package/dist/{index-DBh3WphX.d.mts → index-CMhkkc56.d.mts} +44 -12
- package/dist/index-CMhkkc56.d.mts.map +1 -0
- package/dist/{index-BGlaws7-.d.mts → index-CYVpYGM-.d.mts} +3 -3
- package/dist/{index-BGlaws7-.d.mts.map → index-CYVpYGM-.d.mts.map} +1 -1
- package/dist/{index-DQ1U3HC3.d.mts → index-DhL7ckvs.d.mts} +7 -7
- package/dist/index-DhL7ckvs.d.mts.map +1 -0
- package/dist/{index-CtKUQ2VG.d.mts → index-DkAjKnhW.d.mts} +1487 -533
- package/dist/index-DkAjKnhW.d.mts.map +1 -0
- package/dist/{index-B08eSpaI.d.mts → index-RILu3ULT.d.mts} +2 -2
- package/dist/{index-B08eSpaI.d.mts.map → index-RILu3ULT.d.mts.map} +1 -1
- package/dist/{index-C5sgRLlG.d.mts → index-TCtdSXd7.d.mts} +3 -1
- package/dist/index-TCtdSXd7.d.mts.map +1 -0
- package/dist/{index-C2yaponf.d.mts → index-s2qQ8ifZ.d.mts} +911 -57
- package/dist/index-s2qQ8ifZ.d.mts.map +1 -0
- package/dist/index.d.mts +15 -15
- package/dist/index.mjs +52 -52
- package/dist/preview/index.d.mts +5 -5
- package/dist/preview/index.mjs +10 -10
- package/dist/preview-BeGF1Bb1.mjs +1002 -0
- package/dist/preview-BeGF1Bb1.mjs.map +1 -0
- package/dist/preview-engine/audio.mjs +1 -1
- package/dist/preview-engine/{chunk-64L4GUOF.mjs → chunk-4F3DG6YB.mjs} +2 -2
- package/dist/preview-engine/chunk-A2OTOW3B.mjs +4694 -0
- package/dist/preview-engine/chunk-BR56TQBP.mjs +5 -0
- package/dist/preview-engine/{chunk-ADLIF544.mjs → chunk-H2XKXXAU.mjs} +1 -1
- package/dist/preview-engine/chunk-NDUODAY2.mjs +3 -0
- package/dist/preview-engine/{chunk-FZ4RD7HV.mjs → chunk-QAQJSWUT.mjs} +1 -1
- package/dist/preview-engine/chunk-SWRGQTVC.mjs +138 -0
- package/dist/preview-engine/{chunk-52X7SURQ.mjs → chunk-TEA3GVBJ.mjs} +1 -1
- package/dist/preview-engine/chunk-VM2ZBPLM.mjs +644 -0
- package/dist/preview-engine/{chunk-UBY2UYEL.mjs → chunk-XSHNQJ7L.mjs} +1 -1
- package/dist/preview-engine/components.mjs +1 -1
- package/dist/preview-engine/effects.mjs +1 -1
- package/dist/preview-engine/fonts.mjs +1 -1
- package/dist/preview-engine/framefields.mjs +1 -1
- package/dist/preview-engine/player.mjs +2 -2
- package/dist/preview-engine/{renderers-DU7KPFVV.mjs → renderers-6C7NWWDX.mjs} +1 -1
- package/dist/preview-engine/renderers-HHVGNMSJ.mjs +206 -0
- package/dist/preview-engine/{src-YXNX4MLK.mjs → src-RCNEKIRP.mjs} +1 -1
- package/dist/preview-page/index.html +19 -0
- package/dist/preview-page/main.css +1 -0
- package/dist/preview-page/main.js +327 -0
- package/dist/{program-BfiB9ttP.mjs → program-CMigyfso.mjs} +919 -58
- package/dist/program-CMigyfso.mjs.map +1 -0
- package/dist/renderer/index.d.mts +4 -4
- package/dist/renderer/index.mjs +2 -2
- package/dist/{renderer-CoC64eam.mjs → renderer-0GMEL_Zi.mjs} +3 -3
- package/dist/{renderer-CoC64eam.mjs.map → renderer-0GMEL_Zi.mjs.map} +1 -1
- package/dist/{renderer-CSu_vYPn.mjs → renderer-3Wv2ZBJG.mjs} +3 -3
- package/dist/{renderer-CSu_vYPn.mjs.map → renderer-3Wv2ZBJG.mjs.map} +1 -1
- package/dist/{renderer-Dv_iRIyx.mjs → renderer-4nXkaAWu.mjs} +1280 -285
- package/dist/renderer-4nXkaAWu.mjs.map +1 -0
- package/dist/{renderer-TfeohPxt.mjs → renderer-6SnfLXeg.mjs} +3 -3
- package/dist/{renderer-TfeohPxt.mjs.map → renderer-6SnfLXeg.mjs.map} +1 -1
- package/dist/{renderer-D0xM67cK.mjs → renderer-8gHw3O0P.mjs} +2 -2
- package/dist/{renderer-D0xM67cK.mjs.map → renderer-8gHw3O0P.mjs.map} +1 -1
- package/dist/{renderer-C64_B8It.mjs → renderer-AOBglZHC.mjs} +2 -2
- package/dist/{renderer-B10HDC13.mjs → renderer-B0bSARK3.mjs} +3 -3
- package/dist/{renderer-B10HDC13.mjs.map → renderer-B0bSARK3.mjs.map} +1 -1
- package/dist/{renderer-DWYmJSrl.mjs → renderer-B2_tuRfl.mjs} +2 -2
- package/dist/{renderer-DWYmJSrl.mjs.map → renderer-B2_tuRfl.mjs.map} +1 -1
- package/dist/{renderer-mDBoz0zT.mjs → renderer-B82FhkEr.mjs} +3 -3
- package/dist/{renderer-mDBoz0zT.mjs.map → renderer-B82FhkEr.mjs.map} +1 -1
- package/dist/{renderer-DYeNNc_G.mjs → renderer-B9lzA0PY.mjs} +3 -3
- package/dist/{renderer-DYeNNc_G.mjs.map → renderer-B9lzA0PY.mjs.map} +1 -1
- package/dist/{renderer-BGchUBW_.mjs → renderer-BBSIWSry.mjs} +2 -2
- package/dist/{renderer-BGchUBW_.mjs.map → renderer-BBSIWSry.mjs.map} +1 -1
- package/dist/{renderer-GIlQ9lZq.mjs → renderer-BEKDMxbi.mjs} +2 -2
- package/dist/{renderer-GIlQ9lZq.mjs.map → renderer-BEKDMxbi.mjs.map} +1 -1
- package/dist/renderer-BERGAxqA.mjs +5 -0
- package/dist/{renderer-Bw0O--gW.mjs → renderer-BF960HY8.mjs} +3 -3
- package/dist/{renderer-Bw0O--gW.mjs.map → renderer-BF960HY8.mjs.map} +1 -1
- package/dist/{renderer-BhcTYhaP.mjs → renderer-BFwyVxCu.mjs} +3 -3
- package/dist/{renderer-BhcTYhaP.mjs.map → renderer-BFwyVxCu.mjs.map} +1 -1
- package/dist/{renderer-DYlx7VHo.mjs → renderer-BNiwcI3-.mjs} +2 -2
- package/dist/{renderer-DYlx7VHo.mjs.map → renderer-BNiwcI3-.mjs.map} +1 -1
- package/dist/{renderer-B3_GddgJ.mjs → renderer-BPbVb2Q4.mjs} +2 -2
- package/dist/{renderer-B3_GddgJ.mjs.map → renderer-BPbVb2Q4.mjs.map} +1 -1
- package/dist/renderer-BQ_YkBMt.mjs +6 -0
- package/dist/{renderer-Y1kjtOto.mjs → renderer-BUWxlA8T.mjs} +3 -3
- package/dist/{renderer-Y1kjtOto.mjs.map → renderer-BUWxlA8T.mjs.map} +1 -1
- package/dist/renderer-BW0Tjsv9.mjs +5 -0
- package/dist/{renderer-DtFZbE1j.mjs → renderer-BX8liu-e.mjs} +2 -2
- package/dist/{renderer-BOlHW3Mi.mjs → renderer-BXIwDAr_.mjs} +2 -2
- package/dist/{renderer-BOlHW3Mi.mjs.map → renderer-BXIwDAr_.mjs.map} +1 -1
- package/dist/{renderer-DzON3wDZ.mjs → renderer-B_Hy1W-g.mjs} +3 -3
- package/dist/{renderer-DzON3wDZ.mjs.map → renderer-B_Hy1W-g.mjs.map} +1 -1
- package/dist/{renderer-BM19iK8v.mjs → renderer-Bb6cvSgh.mjs} +2 -2
- package/dist/{renderer-BM19iK8v.mjs.map → renderer-Bb6cvSgh.mjs.map} +1 -1
- package/dist/{renderer-D0h1hTOo.mjs → renderer-BdppwWC9.mjs} +2 -2
- package/dist/{renderer-D0h1hTOo.mjs.map → renderer-BdppwWC9.mjs.map} +1 -1
- package/dist/{renderer-BTwuM9u-.mjs → renderer-Bhc24HVe.mjs} +3 -3
- package/dist/{renderer-BTwuM9u-.mjs.map → renderer-Bhc24HVe.mjs.map} +1 -1
- package/dist/{renderer-BZX932Lj.mjs → renderer-BiNA2wF0.mjs} +2 -2
- package/dist/{renderer-BZX932Lj.mjs.map → renderer-BiNA2wF0.mjs.map} +1 -1
- package/dist/{renderer-CkTehyRX.mjs → renderer-BmoBgTp5.mjs} +3 -3
- package/dist/{renderer-CkTehyRX.mjs.map → renderer-BmoBgTp5.mjs.map} +1 -1
- package/dist/{renderer-B3un4Pdi.mjs → renderer-BmqFmCWS.mjs} +3 -3
- package/dist/{renderer-B3un4Pdi.mjs.map → renderer-BmqFmCWS.mjs.map} +1 -1
- package/dist/{renderer-CHCRcCKw.mjs → renderer-BnVwAObV.mjs} +2 -2
- package/dist/{renderer-CHCRcCKw.mjs.map → renderer-BnVwAObV.mjs.map} +1 -1
- package/dist/{renderer-Cv9CKKWG.mjs → renderer-BxttZHme.mjs} +2 -2
- package/dist/{renderer-Cv9CKKWG.mjs.map → renderer-BxttZHme.mjs.map} +1 -1
- package/dist/renderer-BzyPdUD1.mjs +5 -0
- package/dist/renderer-C0hM-mtY.mjs +5 -0
- package/dist/renderer-C6cyUTvk.mjs +5 -0
- package/dist/{renderer-B6bK9rXm.mjs → renderer-C8E4XsSg.mjs} +2 -2
- package/dist/{renderer-B6bK9rXm.mjs.map → renderer-C8E4XsSg.mjs.map} +1 -1
- package/dist/renderer-C8zY3pzk.mjs +5 -0
- package/dist/{renderer-4nsuReW2.mjs → renderer-C9U-LY50.mjs} +3 -3
- package/dist/{renderer-4nsuReW2.mjs.map → renderer-C9U-LY50.mjs.map} +1 -1
- package/dist/{renderer-BvBqTAtk.mjs → renderer-CB2JVu5x.mjs} +3 -3
- package/dist/{renderer-BvBqTAtk.mjs.map → renderer-CB2JVu5x.mjs.map} +1 -1
- package/dist/{renderer-CQ4h8n7p.mjs → renderer-CC4YBJ8Z.mjs} +3 -3
- package/dist/{renderer-CQ4h8n7p.mjs.map → renderer-CC4YBJ8Z.mjs.map} +1 -1
- package/dist/renderer-CEkSOyKu.mjs +5 -0
- package/dist/{renderer-zLi2qFGT.mjs → renderer-CIycc5O-.mjs} +2 -2
- package/dist/{renderer-zLi2qFGT.mjs.map → renderer-CIycc5O-.mjs.map} +1 -1
- package/dist/renderer-CJYtfa4x.mjs +5 -0
- package/dist/{renderer-yNWYqvvq.mjs → renderer-CJraQlV-.mjs} +2 -2
- package/dist/{renderer-yNWYqvvq.mjs.map → renderer-CJraQlV-.mjs.map} +1 -1
- package/dist/renderer-CKMtHGZh.mjs +5 -0
- package/dist/renderer-CLzicoiy.mjs +5 -0
- package/dist/renderer-CM2A4BHd.mjs +5 -0
- package/dist/{renderer-BrEeUw7T.mjs → renderer-COWGWtob.mjs} +2 -2
- package/dist/{renderer-BrEeUw7T.mjs.map → renderer-COWGWtob.mjs.map} +1 -1
- package/dist/{renderer-uER8kn7f.mjs → renderer-COxG2XGf.mjs} +2 -2
- package/dist/{renderer-uER8kn7f.mjs.map → renderer-COxG2XGf.mjs.map} +1 -1
- package/dist/{renderer-C4hd6Cqi.mjs → renderer-CQDCIsQm.mjs} +2 -2
- package/dist/{renderer-C4hd6Cqi.mjs.map → renderer-CQDCIsQm.mjs.map} +1 -1
- package/dist/{renderer-Cfx_FCSf.mjs → renderer-CRUeag8i.mjs} +3 -3
- package/dist/{renderer-Cfx_FCSf.mjs.map → renderer-CRUeag8i.mjs.map} +1 -1
- package/dist/{renderer-CXrnzihz.mjs → renderer-CWVput06.mjs} +3 -3
- package/dist/{renderer-CXrnzihz.mjs.map → renderer-CWVput06.mjs.map} +1 -1
- package/dist/renderer-CZlHjcxr.mjs +5 -0
- package/dist/{renderer-BmyFfvVA.mjs → renderer-CbbnBLOB.mjs} +3 -3
- package/dist/{renderer-BmyFfvVA.mjs.map → renderer-CbbnBLOB.mjs.map} +1 -1
- package/dist/renderer-CbimvSU8.mjs +5 -0
- package/dist/renderer-Ccvc63yd.mjs +5 -0
- package/dist/renderer-Cdp-SGfq.mjs +5 -0
- package/dist/renderer-CeTcSs3e.mjs +5 -0
- package/dist/{renderer-_J9JcCMR.mjs → renderer-CfLZein2.mjs} +3 -3
- package/dist/{renderer-_J9JcCMR.mjs.map → renderer-CfLZein2.mjs.map} +1 -1
- package/dist/{renderer-D-mX1EVA.mjs → renderer-Ch-q1O-q.mjs} +3 -3
- package/dist/{renderer-D-mX1EVA.mjs.map → renderer-Ch-q1O-q.mjs.map} +1 -1
- package/dist/{renderer-uzU6dsdR.mjs → renderer-Ch5JvJWl.mjs} +2 -2
- package/dist/{renderer-uzU6dsdR.mjs.map → renderer-Ch5JvJWl.mjs.map} +1 -1
- package/dist/{renderer-BZMh2io2.mjs → renderer-ChtEzq-R.mjs} +2 -2
- package/dist/{renderer-BZMh2io2.mjs.map → renderer-ChtEzq-R.mjs.map} +1 -1
- package/dist/{renderer-B2IUPjhw.mjs → renderer-Cj9nTC5l.mjs} +3 -3
- package/dist/{renderer-B2IUPjhw.mjs.map → renderer-Cj9nTC5l.mjs.map} +1 -1
- package/dist/{renderer-CdXBRdFf.mjs → renderer-CqT8HsSS.mjs} +2 -2
- package/dist/{renderer-CdXBRdFf.mjs.map → renderer-CqT8HsSS.mjs.map} +1 -1
- package/dist/{renderer-CldjJmRR.mjs → renderer-CuQjMhdV.mjs} +2 -2
- package/dist/renderer-CvNuu52U.mjs +5 -0
- package/dist/renderer-CwciC0oI.mjs +5 -0
- package/dist/renderer-CysLUbIr.mjs +5 -0
- package/dist/{renderer-BsrKj6Td.mjs → renderer-Cz30EVws.mjs} +2 -2
- package/dist/{renderer-BsrKj6Td.mjs.map → renderer-Cz30EVws.mjs.map} +1 -1
- package/dist/renderer-D3A22Vxb.mjs +5 -0
- package/dist/renderer-D5SY9EmA.mjs +5 -0
- package/dist/renderer-D8h3ZvaE.mjs +5 -0
- package/dist/renderer-DE-B6N9n.mjs +5 -0
- package/dist/renderer-DETZTI7t.mjs +5 -0
- package/dist/{renderer-CC22Djgi.mjs → renderer-DHoX-5U_.mjs} +3 -3
- package/dist/{renderer-CC22Djgi.mjs.map → renderer-DHoX-5U_.mjs.map} +1 -1
- package/dist/{renderer-HKv5cBdp.mjs → renderer-DOkm0Ycd.mjs} +2 -2
- package/dist/{renderer-HKv5cBdp.mjs.map → renderer-DOkm0Ycd.mjs.map} +1 -1
- package/dist/{renderer-fG8Jy8Rx.d.mts → renderer-DU3f6ZrS.d.mts} +2 -2
- package/dist/{renderer-fG8Jy8Rx.d.mts.map → renderer-DU3f6ZrS.d.mts.map} +1 -1
- package/dist/{renderer-C98XwEIr.mjs → renderer-DUzv-shq.mjs} +2 -2
- package/dist/{renderer-C98XwEIr.mjs.map → renderer-DUzv-shq.mjs.map} +1 -1
- package/dist/renderer-DWnDj0IM.mjs +5 -0
- package/dist/renderer-DcGUIbQF.mjs +5 -0
- package/dist/renderer-Dfq6FoNO.mjs +5 -0
- package/dist/renderer-DhasXW6S.mjs +3 -0
- package/dist/{renderer-BEuXJY-C.mjs → renderer-DhnOWnEA.mjs} +3 -3
- package/dist/{renderer-BEuXJY-C.mjs.map → renderer-DhnOWnEA.mjs.map} +1 -1
- package/dist/{renderer-BIKkxw_Z.mjs → renderer-Dhy1XHzz.mjs} +3 -3
- package/dist/{renderer-BIKkxw_Z.mjs.map → renderer-Dhy1XHzz.mjs.map} +1 -1
- package/dist/renderer-DjCvpsV_.mjs +5 -0
- package/dist/{renderer-pn52dzZz.mjs → renderer-DjJshz9Y.mjs} +2 -2
- package/dist/{renderer-pn52dzZz.mjs.map → renderer-DjJshz9Y.mjs.map} +1 -1
- package/dist/{renderer-DhGZ41hQ.mjs → renderer-DmTUIdus.mjs} +3 -3
- package/dist/{renderer-DhGZ41hQ.mjs.map → renderer-DmTUIdus.mjs.map} +1 -1
- package/dist/{renderer-D_m6Qbsi.mjs → renderer-Dq7AioJa.mjs} +2 -2
- package/dist/{renderer-D_m6Qbsi.mjs.map → renderer-Dq7AioJa.mjs.map} +1 -1
- package/dist/renderer-DrAaM6JD.mjs +5 -0
- package/dist/{renderer-D-GWBoVT.mjs → renderer-Dt4sqNEu.mjs} +2 -2
- package/dist/{renderer-D-GWBoVT.mjs.map → renderer-Dt4sqNEu.mjs.map} +1 -1
- package/dist/{renderer-DCrKEVjb.mjs → renderer-Dtcs4idV.mjs} +3 -3
- package/dist/{renderer-DCrKEVjb.mjs.map → renderer-Dtcs4idV.mjs.map} +1 -1
- package/dist/renderer-Dxlv8LYm.mjs +5 -0
- package/dist/{renderer-CO9vE3sd.mjs → renderer-Gj8SrE2W.mjs} +2 -2
- package/dist/{renderer-CO9vE3sd.mjs.map → renderer-Gj8SrE2W.mjs.map} +1 -1
- package/dist/{renderer-DvHi_wXE.mjs → renderer-KfnXDJS0.mjs} +3 -3
- package/dist/{renderer-DvHi_wXE.mjs.map → renderer-KfnXDJS0.mjs.map} +1 -1
- package/dist/{renderer-7xQmXXMH.mjs → renderer-MXVlg4p5.mjs} +3 -3
- package/dist/{renderer-7xQmXXMH.mjs.map → renderer-MXVlg4p5.mjs.map} +1 -1
- package/dist/{renderer-YONlI6W-.mjs → renderer-N2b6QZ1E.mjs} +3 -3
- package/dist/{renderer-YONlI6W-.mjs.map → renderer-N2b6QZ1E.mjs.map} +1 -1
- package/dist/renderer-Pb43OO2t.mjs +5 -0
- package/dist/{renderer-DNynPM6X.mjs → renderer-Q7gDzm8c.mjs} +2 -2
- package/dist/{renderer-DNynPM6X.mjs.map → renderer-Q7gDzm8c.mjs.map} +1 -1
- package/dist/{renderer-BEhZiOT4.mjs → renderer-RCiANtRV.mjs} +2 -2
- package/dist/{renderer-BEhZiOT4.mjs.map → renderer-RCiANtRV.mjs.map} +1 -1
- package/dist/{renderer-Dm57W73p.mjs → renderer-Sig9nZcI.mjs} +2 -2
- package/dist/renderer-VQbm-cGr.mjs +5 -0
- package/dist/{renderer-DiZkZ0Pr.mjs → renderer-fabBgwQX.mjs} +3 -3
- package/dist/{renderer-DiZkZ0Pr.mjs.map → renderer-fabBgwQX.mjs.map} +1 -1
- package/dist/{renderer-Bw-_GZVw.mjs → renderer-g-0PCNoo.mjs} +3 -3
- package/dist/{renderer-Bw-_GZVw.mjs.map → renderer-g-0PCNoo.mjs.map} +1 -1
- package/dist/{renderer-QbSrnPZU.mjs → renderer-gmHKIbKI.mjs} +3 -3
- package/dist/{renderer-QbSrnPZU.mjs.map → renderer-gmHKIbKI.mjs.map} +1 -1
- package/dist/{renderer-CU6WT5jW.mjs → renderer-kVZwiRoK.mjs} +3 -3
- package/dist/{renderer-CU6WT5jW.mjs.map → renderer-kVZwiRoK.mjs.map} +1 -1
- package/dist/renderer-oPMypDM1.mjs +5 -0
- package/dist/{renderer-CRhEGqW4.mjs → renderer-p7tgxP-A.mjs} +3 -3
- package/dist/{renderer-CRhEGqW4.mjs.map → renderer-p7tgxP-A.mjs.map} +1 -1
- package/dist/{renderer-CO4NGvAh.mjs → renderer-tvYj306A.mjs} +81 -78
- package/dist/renderer-tvYj306A.mjs.map +1 -0
- package/dist/renderer-xvWGpVyp.mjs +5 -0
- package/dist/renderer-zafZbD6Q.mjs +5 -0
- package/dist/{renderers-CP8CFWDs-BufiCyn7.mjs → renderers-CP8CFWDs-DLjtjrwx.mjs} +2 -2
- package/dist/{renderers-CP8CFWDs-BufiCyn7.mjs.map → renderers-CP8CFWDs-DLjtjrwx.mjs.map} +1 -1
- package/dist/sam/index.d.mts +3 -3
- package/dist/sam/index.mjs +1 -1
- package/dist/signals/index.d.mts +5 -5
- package/dist/signals/index.mjs +4 -4
- package/dist/{src-BU6vm9sP-DdTHmCr4.mjs → src-B23p_eh7-Cj6-lvV6.mjs} +293 -6
- package/dist/src-B23p_eh7-Cj6-lvV6.mjs.map +1 -0
- package/dist/{src-DrP7fGJX.mjs → src-CoHAjviq.mjs} +1355 -178
- package/dist/src-CoHAjviq.mjs.map +1 -0
- package/dist/storage/index.mjs +1 -1
- package/package.json +63 -60
- package/dist/dist-CiTgmfUw.mjs.map +0 -1
- package/dist/dist-DtPPPsZV.mjs.map +0 -1
- package/dist/fonts-k5ll8NTE.mjs.map +0 -1
- package/dist/index-C2yaponf.d.mts.map +0 -1
- package/dist/index-C5sgRLlG.d.mts.map +0 -1
- package/dist/index-CnZhBlob.d.mts.map +0 -1
- package/dist/index-CtKUQ2VG.d.mts.map +0 -1
- package/dist/index-DBh3WphX.d.mts.map +0 -1
- package/dist/index-DQ1U3HC3.d.mts.map +0 -1
- package/dist/index-a6JrbAK0.d.mts.map +0 -1
- package/dist/preview-engine/chunk-5ZS46EFB.mjs +0 -5
- package/dist/preview-engine/chunk-N3XTDAL6.mjs +0 -2227
- package/dist/preview-engine/chunk-NCQHOGZK.mjs +0 -3
- package/dist/preview-engine/chunk-PH3UUX6A.mjs +0 -138
- package/dist/preview-engine/chunk-XCPRRMMW.mjs +0 -2462
- package/dist/preview-engine/renderers-ZMMQ7S2A.mjs +0 -228
- package/dist/preview-lHH8Tv4j.mjs +0 -2446
- package/dist/preview-lHH8Tv4j.mjs.map +0 -1
- package/dist/program-BfiB9ttP.mjs.map +0 -1
- package/dist/renderer-0rLmztAv.mjs +0 -5
- package/dist/renderer-B0pjOXFY.mjs +0 -5
- package/dist/renderer-B7J13reL.mjs +0 -5
- package/dist/renderer-BPGIKGgl.mjs +0 -5
- package/dist/renderer-Bv-Artj1.mjs +0 -5
- package/dist/renderer-BvLjbhcL.mjs +0 -5
- package/dist/renderer-By6awWaf.mjs +0 -5
- package/dist/renderer-C0rvsz7m.mjs +0 -5
- package/dist/renderer-CDgud_HB.mjs +0 -5
- package/dist/renderer-CDiRF3bG.mjs +0 -6
- package/dist/renderer-CIIEQd4B.mjs +0 -5
- package/dist/renderer-CJblwOA9.mjs +0 -5
- package/dist/renderer-CNMOXtXE.mjs +0 -5
- package/dist/renderer-CO4NGvAh.mjs.map +0 -1
- package/dist/renderer-COeSeNGg.mjs +0 -5
- package/dist/renderer-CUfElmtZ.mjs +0 -5
- package/dist/renderer-CYh2lFoJ.mjs +0 -5
- package/dist/renderer-CYtVZYMH.mjs +0 -5
- package/dist/renderer-CjxZlkjb.mjs +0 -5
- package/dist/renderer-Cpd6TvTC.mjs +0 -5
- package/dist/renderer-D3ziOPhX.mjs +0 -5
- package/dist/renderer-D5yp74NL.mjs +0 -3
- package/dist/renderer-DL-phtL5.mjs +0 -5
- package/dist/renderer-DSnmYnHg.mjs +0 -5
- package/dist/renderer-DUGfsT-E.mjs +0 -5
- package/dist/renderer-DW5af9x1.mjs +0 -5
- package/dist/renderer-DYMrol1t.mjs +0 -5
- package/dist/renderer-DekeUHaz.mjs +0 -5
- package/dist/renderer-Dt5uyJdZ.mjs +0 -5
- package/dist/renderer-Dv_iRIyx.mjs.map +0 -1
- package/dist/renderer-DwLQAnaK.mjs +0 -5
- package/dist/renderer-IXQP2CWM.mjs +0 -5
- package/dist/renderer-K-Pkw63O.mjs +0 -5
- package/dist/renderer-MPw2KH9P.mjs +0 -5
- package/dist/renderer-RPu8RMav.mjs +0 -5
- package/dist/renderer-dCqxd5N2.mjs +0 -5
- package/dist/renderer-lhjmE-Fp.mjs +0 -5
- package/dist/renderer-u9cmBuvM.mjs +0 -5
- package/dist/renderer-vH12jcpz.mjs +0 -5
- package/dist/src-BU6vm9sP-DdTHmCr4.mjs.map +0 -1
- package/dist/src-DrP7fGJX.mjs.map +0 -1
|
@@ -1,83 +1,29 @@
|
|
|
1
1
|
import "./chunk-DOL2i2sR.mjs";
|
|
2
2
|
import { It as getActiveMediaMetadata, _n as reportRenderDiagnostic, p as DEFAULT_DURATION_MS, rn as mediaSourceTime, vn as resolveBoolean, xn as resolveNumber } from "./dist-C8XSqfTx.mjs";
|
|
3
3
|
import { i as effectReach, n as defineRenderer, r as effectMaxPixelScale, s as resolveFrameNumber, t as audioRegistry, u as solveHomography } from "./renderer-BuvKGwk3.mjs";
|
|
4
|
-
import { $ as
|
|
5
|
-
import { a as createFullscreenPipeline, l as fragmentBindGroupLayout, n as PREMULTIPLIED_BLEND, t as FULLSCREEN_QUAD_WGSL } from "./gpu-
|
|
6
|
-
import { i as keyedGain, m as measureText, n as decodeAudioSource, s as resolveLayerDuration } from "./dist-
|
|
4
|
+
import { $ as measureMaxCaptionHeight, B as fractureModel, Dt as resolveMediaSourceUrl, Ft as Light3D, J as jointMatrices, Kt as defaultCubeFaceSize, Lt as Matrix4Math, S as blendClipLayers, Tt as trsMatrix, U as getPrimitiveGeometry, Ut as createRandom, V as generateExtrudedTextGeometry, Vt as cameraBasis, Wt as cubeFaceCameras, Zt as lensCenterDensity, _ as SpringBones, a as FRACTURE_INTERIOR_MATERIAL, b as applyConstraints, bt as srtLoader, f as ScreenSpaceRelightPipeline, ft as resolveTextSpans, gt as seatOnSurface, ht as scatterOnSurface, kt as Camera3D, m as SlugFontCache, mt as sampleMorphWeights, n as AudioLatentTrackCache, nt as parseDashArray, pt as rotateByQuat, st as poseNodes, tt as parseColor, u as Renderer3D, ut as resolveClips, wt as transformScale, x as bakeCrowdPalette, yt as spansText, z as fitSpansToText, zt as Vector3Math } from "./dist-XqlFM2a8.mjs";
|
|
5
|
+
import { a as createFullscreenPipeline, l as fragmentBindGroupLayout, n as PREMULTIPLIED_BLEND, t as FULLSCREEN_QUAD_WGSL } from "./gpu-CH1PdM4T.mjs";
|
|
6
|
+
import { i as keyedGain, m as measureText, n as decodeAudioSource, s as resolveLayerDuration } from "./dist-COOpgG9G.mjs";
|
|
7
7
|
import { o as TemporalDeflickerPipeline } from "./dist-DgZpN6IK.mjs";
|
|
8
|
-
import { B as
|
|
8
|
+
import { B as collectNodeOps, U as computeLayout, Y as initLayout, Z as mappedEase, et as numberAt, it as vec3At, q as evaluateTrackAtFrame, rt as sampleTrack } from "./program-CMigyfso.mjs";
|
|
9
9
|
import gsapModule from "gsap";
|
|
10
10
|
|
|
11
|
-
//#region ../../nodes/node-compositor/dist/renderers-
|
|
12
|
-
/**
|
|
13
|
-
* Solves a cubic bezier curve defined by control points (x1, y1) and (x2, y2)
|
|
14
|
-
* for a given progress parameter t in [0, 1].
|
|
15
|
-
*/
|
|
16
|
-
function solveCubicBezier(x1, y1, x2, y2, t) {
|
|
17
|
-
if (t <= 0) return 0;
|
|
18
|
-
if (t >= 1) return 1;
|
|
19
|
-
if (x1 === y1 && x2 === y2) return t;
|
|
20
|
-
let u = t;
|
|
21
|
-
for (let i = 0; i < 8; i++) {
|
|
22
|
-
const oneMinusU$1 = 1 - u;
|
|
23
|
-
const oneMinusU2 = oneMinusU$1 * oneMinusU$1;
|
|
24
|
-
const u2 = u * u;
|
|
25
|
-
const diff = 3 * oneMinusU2 * u * x1 + 3 * oneMinusU$1 * u2 * x2 + u2 * u - t;
|
|
26
|
-
if (Math.abs(diff) < 1e-6) break;
|
|
27
|
-
const dx = 3 * oneMinusU2 * x1 + 6 * oneMinusU$1 * u * (x2 - x1) + 3 * u2 * (1 - x2);
|
|
28
|
-
if (Math.abs(dx) < 1e-6) break;
|
|
29
|
-
u -= diff / dx;
|
|
30
|
-
u = Math.max(0, Math.min(1, u));
|
|
31
|
-
}
|
|
32
|
-
const oneMinusU = 1 - u;
|
|
33
|
-
const checkX = 3 * oneMinusU * oneMinusU * u * x1 + 3 * oneMinusU * u * u * x2 + u * u * u;
|
|
34
|
-
if (Math.abs(checkX - t) > .001) {
|
|
35
|
-
let low = 0;
|
|
36
|
-
let high = 1;
|
|
37
|
-
u = t;
|
|
38
|
-
for (let i = 0; i < 16; i++) {
|
|
39
|
-
const mid = (low + high) * .5;
|
|
40
|
-
const oMid = 1 - mid;
|
|
41
|
-
const xMid = 3 * oMid * oMid * mid * x1 + 3 * oMid * mid * mid * x2 + mid * mid * mid;
|
|
42
|
-
if (Math.abs(xMid - t) < 1e-5) {
|
|
43
|
-
u = mid;
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
if (xMid < t) low = mid;
|
|
47
|
-
else high = mid;
|
|
48
|
-
u = mid;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const oU = 1 - u;
|
|
52
|
-
return 3 * oU * oU * u * y1 + 3 * oU * u * u * y2 + u * u * u;
|
|
53
|
-
}
|
|
11
|
+
//#region ../../nodes/node-compositor/dist/renderers-CrRYcARA.mjs
|
|
54
12
|
const gsap = gsapModule.timeline ? gsapModule : gsapModule.default || gsapModule;
|
|
55
|
-
/** GSAP's shaping for a keyframe segment, so draw-time tracks ease like baked ones. */
|
|
56
|
-
function gsapEase(fps) {
|
|
57
|
-
return (ease, deltaFrames, t) => {
|
|
58
|
-
const e = mappedEase(ease, deltaFrames, fps);
|
|
59
|
-
const fn = typeof e === "function" ? e : gsap.parseEase(e);
|
|
60
|
-
return fn ? fn(t) : t;
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
function evaluateLive(live, frame, fps, signals) {
|
|
64
|
-
if ((live.track.source ?? { type: "keyframe" }).type === "keyframe") return evaluateKeyframes(live.track, frame - live.startFrame, gsapEase(fps));
|
|
65
|
-
return evaluateTrackAtFrame(live.track, frame, fps, {
|
|
66
|
-
startFrame: live.startFrame,
|
|
67
|
-
baseValues: live.stub,
|
|
68
|
-
signals
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
13
|
/** Seeks the compiled timeline to a frame and applies its live signal tracks. */
|
|
72
14
|
function seekTimeline(result, frame, fps) {
|
|
73
15
|
result.tl.seek(frame / fps);
|
|
74
16
|
for (const live of result.live) {
|
|
75
17
|
let f = Math.max(live.startFrame, Math.min(live.endFrame, frame));
|
|
76
18
|
if (live.step && live.step > 1) f = live.startFrame + Math.floor((f - live.startFrame) / live.step) * live.step;
|
|
77
|
-
live.stub[live.track.prop] =
|
|
19
|
+
live.stub[live.track.prop] = sampleTrack(live.track, f, fps, {
|
|
20
|
+
startFrame: live.startFrame,
|
|
21
|
+
base: live.stub,
|
|
22
|
+
signals: result.signals
|
|
23
|
+
});
|
|
78
24
|
}
|
|
79
25
|
}
|
|
80
|
-
const cache = /* @__PURE__ */ new Map();
|
|
26
|
+
const cache$1 = /* @__PURE__ */ new Map();
|
|
81
27
|
const nodesHashMemo = /* @__PURE__ */ new WeakMap();
|
|
82
28
|
/** Entries untouched for this long are dropped (and their timeline killed). */
|
|
83
29
|
const CACHE_TTL_MS = 1e4;
|
|
@@ -121,17 +67,17 @@ function release(value) {
|
|
|
121
67
|
* the least-recently-used entry if the cache is at capacity. Every dropped
|
|
122
68
|
* timeline MUST be killed — see `release`.
|
|
123
69
|
*/
|
|
124
|
-
function evictForInsert(cache$
|
|
70
|
+
function evictForInsert(cache$2, maxSize) {
|
|
125
71
|
const now = Date.now();
|
|
126
|
-
for (const [key, entry] of cache$
|
|
127
|
-
cache$
|
|
72
|
+
for (const [key, entry] of cache$2.entries()) if (now - entry.cacheTime > CACHE_TTL_MS) {
|
|
73
|
+
cache$2.delete(key);
|
|
128
74
|
release(entry.value);
|
|
129
75
|
}
|
|
130
|
-
if (cache$
|
|
131
|
-
const oldestKey = cache$
|
|
76
|
+
if (cache$2.size >= maxSize) {
|
|
77
|
+
const oldestKey = cache$2.keys().next().value;
|
|
132
78
|
if (oldestKey !== void 0) {
|
|
133
|
-
const oldest = cache$
|
|
134
|
-
cache$
|
|
79
|
+
const oldest = cache$2.get(oldestKey);
|
|
80
|
+
cache$2.delete(oldestKey);
|
|
135
81
|
if (oldest) release(oldest.value);
|
|
136
82
|
}
|
|
137
83
|
}
|
|
@@ -147,76 +93,26 @@ function stableStringify(obj) {
|
|
|
147
93
|
}).join(",") + "}";
|
|
148
94
|
}
|
|
149
95
|
function getCachedTimeline(cacheKey) {
|
|
150
|
-
const entry = cache.get(cacheKey);
|
|
96
|
+
const entry = cache$1.get(cacheKey);
|
|
151
97
|
if (entry) {
|
|
152
98
|
if (Date.now() - entry.cacheTime > CACHE_TTL_MS) {
|
|
153
|
-
cache.delete(cacheKey);
|
|
99
|
+
cache$1.delete(cacheKey);
|
|
154
100
|
release(entry.value);
|
|
155
101
|
return;
|
|
156
102
|
}
|
|
157
103
|
entry.cacheTime = Date.now();
|
|
158
|
-
cache.delete(cacheKey);
|
|
159
|
-
cache.set(cacheKey, entry);
|
|
104
|
+
cache$1.delete(cacheKey);
|
|
105
|
+
cache$1.set(cacheKey, entry);
|
|
160
106
|
return entry.value;
|
|
161
107
|
}
|
|
162
108
|
}
|
|
163
109
|
function setCachedTimeline(cacheKey, value) {
|
|
164
|
-
evictForInsert(cache, TIMELINE_CACHE_MAX);
|
|
165
|
-
cache.set(cacheKey, {
|
|
110
|
+
evictForInsert(cache$1, TIMELINE_CACHE_MAX);
|
|
111
|
+
cache$1.set(cacheKey, {
|
|
166
112
|
cacheTime: Date.now(),
|
|
167
113
|
value
|
|
168
114
|
});
|
|
169
115
|
}
|
|
170
|
-
function mappedEase(ease, durationFrames, fps = 24) {
|
|
171
|
-
if (!ease) return "none";
|
|
172
|
-
const { name, dir, params } = ease;
|
|
173
|
-
if (name === "none") return "none";
|
|
174
|
-
if (name === "spring") {
|
|
175
|
-
const damping = Math.max(.001, params?.[0] ?? 10);
|
|
176
|
-
const stiffness = Math.max(.001, params?.[1] ?? 100);
|
|
177
|
-
const mass = Math.max(.001, params?.[2] ?? 1);
|
|
178
|
-
return (p) => {
|
|
179
|
-
const t = p * (durationFrames && durationFrames > 0 ? durationFrames / (fps > 0 ? fps : 24) : 1);
|
|
180
|
-
const m = mass;
|
|
181
|
-
const k = stiffness;
|
|
182
|
-
const c = damping;
|
|
183
|
-
const w0 = Math.sqrt(k / m);
|
|
184
|
-
const zeta = c / (2 * Math.sqrt(k * m));
|
|
185
|
-
let x = 0;
|
|
186
|
-
if (zeta < 1) {
|
|
187
|
-
const wd = w0 * Math.sqrt(1 - zeta * zeta);
|
|
188
|
-
const A = -1;
|
|
189
|
-
const B = -zeta * w0 / wd;
|
|
190
|
-
x = Math.exp(-zeta * w0 * t) * (A * Math.cos(wd * t) + B * Math.sin(wd * t));
|
|
191
|
-
} else if (zeta === 1) {
|
|
192
|
-
const A = -1;
|
|
193
|
-
const B = -w0;
|
|
194
|
-
x = Math.exp(-w0 * t) * (A + B * t);
|
|
195
|
-
} else {
|
|
196
|
-
const r1 = -w0 * (zeta - Math.sqrt(zeta * zeta - 1));
|
|
197
|
-
const r2 = -w0 * (zeta + Math.sqrt(zeta * zeta - 1));
|
|
198
|
-
const C1 = -1 / (1 - r1 / r2);
|
|
199
|
-
const C2 = -1 - C1;
|
|
200
|
-
x = C1 * Math.exp(r1 * t) + C2 * Math.exp(r2 * t);
|
|
201
|
-
}
|
|
202
|
-
return 1 + x;
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
if (name === "cubic") {
|
|
206
|
-
const x1 = params?.[0] ?? .25;
|
|
207
|
-
const y1 = params?.[1] ?? .1;
|
|
208
|
-
const x2 = params?.[2] ?? .25;
|
|
209
|
-
const y2 = params?.[3] ?? 1;
|
|
210
|
-
return (p) => solveCubicBezier(x1, y1, x2, y2, p);
|
|
211
|
-
}
|
|
212
|
-
if (name === "hold") return (p) => p >= .9999 ? 1 : 0;
|
|
213
|
-
const easeName = name;
|
|
214
|
-
let suffix = "";
|
|
215
|
-
if (params && params.length > 0) suffix = `(${params.join(", ")})`;
|
|
216
|
-
else if (name === "back") suffix = "(1.7)";
|
|
217
|
-
else if (name === "elastic") suffix = "(1, 0.3)";
|
|
218
|
-
return `${easeName}.${dir}${suffix}`;
|
|
219
|
-
}
|
|
220
116
|
/** Props that switch rather than tween: each key is a set from its frame on. */
|
|
221
117
|
const DISCRETE_PROPS = new Set(["hidden", "muted"]);
|
|
222
118
|
function compileTrackToTimeline(tl, stub, track, startFrame, fps, durationFrames, signals, live, step) {
|
|
@@ -231,7 +127,11 @@ function compileTrackToTimeline(tl, stub, track, startFrame, fps, durationFrames
|
|
|
231
127
|
endFrame: startFrame + (Number.isFinite(durationFrames) ? durationFrames : Math.round(fps * 5)),
|
|
232
128
|
...stepped && { step }
|
|
233
129
|
};
|
|
234
|
-
stub[prop] =
|
|
130
|
+
stub[prop] = sampleTrack(track, startFrame, fps, {
|
|
131
|
+
startFrame,
|
|
132
|
+
base: stub,
|
|
133
|
+
signals
|
|
134
|
+
});
|
|
235
135
|
live.push(entry);
|
|
236
136
|
return {
|
|
237
137
|
dropped: 0,
|
|
@@ -366,6 +266,28 @@ function compileTrackToTimeline(tl, stub, track, startFrame, fps, durationFrames
|
|
|
366
266
|
maxAuthoredFrame
|
|
367
267
|
};
|
|
368
268
|
}
|
|
269
|
+
/** A camera's `x` / `y` / `z` are its eye, the same as `cameraX` / `cameraY` / `cameraZ`. */
|
|
270
|
+
const CAMERA_EYE = {
|
|
271
|
+
x: "cameraX",
|
|
272
|
+
y: "cameraY",
|
|
273
|
+
z: "cameraZ"
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* A layer's tracks, with a camera's `x` / `y` / `z` tracks driving its eye:
|
|
277
|
+
* the eye is read from `cameraX` / `cameraY` / `cameraZ`, which the static
|
|
278
|
+
* `x` / `y` / `z` seed, so a track left on `x` would never move it.
|
|
279
|
+
*/
|
|
280
|
+
function layerTracks(lop) {
|
|
281
|
+
const tracks = lop.animation?.tracks ?? [];
|
|
282
|
+
if (lop.kind !== "camera") return tracks;
|
|
283
|
+
return tracks.map((t) => {
|
|
284
|
+
const eye = CAMERA_EYE[t.prop];
|
|
285
|
+
return eye ? {
|
|
286
|
+
...t,
|
|
287
|
+
prop: eye
|
|
288
|
+
} : t;
|
|
289
|
+
});
|
|
290
|
+
}
|
|
369
291
|
/**
|
|
370
292
|
* Dedupe per compiled cache key — a fresh render of the same broken doc SHOULD
|
|
371
293
|
* re-warn. Single-frame renders are the exception: each `renderFrame` call has
|
|
@@ -434,6 +356,7 @@ function hashNodes(nodeOps, width, height, fps, durationSec) {
|
|
|
434
356
|
maxBlurRadius: lop.maxBlurRadius,
|
|
435
357
|
shakeTranslation: lop.shakeTranslation,
|
|
436
358
|
shakeRotation: lop.shakeRotation,
|
|
359
|
+
relativitySpeed: lop.relativitySpeed,
|
|
437
360
|
orbitRadius: lop.orbitRadius,
|
|
438
361
|
orbitAzimuth: lop.orbitAzimuth,
|
|
439
362
|
orbitElevation: lop.orbitElevation,
|
|
@@ -443,11 +366,35 @@ function hashNodes(nodeOps, width, height, fps, durationSec) {
|
|
|
443
366
|
specularIntensity: lop.specularIntensity,
|
|
444
367
|
ambientIntensity: lop.ambientIntensity,
|
|
445
368
|
metallic: lop.metallic,
|
|
369
|
+
emissive: lop.emissive,
|
|
370
|
+
emissiveIntensity: lop.emissiveIntensity,
|
|
371
|
+
clearcoat: lop.clearcoat,
|
|
372
|
+
clearcoatRoughness: lop.clearcoatRoughness,
|
|
373
|
+
anisotropy: lop.anisotropy,
|
|
374
|
+
anisotropyRotation: lop.anisotropyRotation,
|
|
375
|
+
subsurface: lop.subsurface,
|
|
376
|
+
subsurfaceColor: lop.subsurfaceColor,
|
|
377
|
+
sheen: lop.sheen,
|
|
378
|
+
sheenColor: lop.sheenColor,
|
|
379
|
+
sheenRoughness: lop.sheenRoughness,
|
|
380
|
+
iridescence: lop.iridescence,
|
|
381
|
+
iridescenceThickness: lop.iridescenceThickness,
|
|
382
|
+
iridescenceIor: lop.iridescenceIor,
|
|
383
|
+
triplanar: lop.triplanar,
|
|
384
|
+
triplanarScale: lop.triplanarScale,
|
|
385
|
+
triplanarSharpness: lop.triplanarSharpness,
|
|
446
386
|
lightType: lop.lightType,
|
|
387
|
+
color: lop.color,
|
|
447
388
|
intensity: lop.intensity,
|
|
448
389
|
radius: lop.radius,
|
|
449
390
|
angle: lop.angle,
|
|
450
391
|
penumbra: lop.penumbra,
|
|
392
|
+
exposure: lop.exposure,
|
|
393
|
+
hdri: typeof lop.hdri === "string" ? lop.hdri : Boolean(lop.hdri),
|
|
394
|
+
volumetricFog: lop.volumetricFog,
|
|
395
|
+
volumetricFogDensity: lop.volumetricFogDensity,
|
|
396
|
+
volumetricFogAnisotropy: lop.volumetricFogAnisotropy,
|
|
397
|
+
volumetricFogNoiseStrength: lop.volumetricFogNoiseStrength,
|
|
451
398
|
animationProgress: lop.animationProgress,
|
|
452
399
|
animationTime: lop.animationTime,
|
|
453
400
|
animationSpeed: lop.animationSpeed,
|
|
@@ -540,13 +487,30 @@ function compileTimeline(renderId, virtualMedia, options) {
|
|
|
540
487
|
is3D: lop.is3D ?? (lop.kind === "camera" || lop.kind === "light" || lop.kind === "model3d" ? true : false),
|
|
541
488
|
z: lop.z ?? (lop.kind === "camera" ? lop.z ?? -1500 : 0),
|
|
542
489
|
scaleZ: lop.scaleZ ?? 1,
|
|
543
|
-
twoSided: lop.twoSided ??
|
|
490
|
+
twoSided: lop.twoSided ?? lop.kind !== "light",
|
|
544
491
|
material: lop.material,
|
|
545
492
|
shininess: lop.shininess,
|
|
546
493
|
roughness: lop.roughness,
|
|
547
494
|
specularIntensity: lop.specularIntensity,
|
|
548
495
|
ambientIntensity: lop.ambientIntensity,
|
|
549
496
|
metallic: lop.metallic,
|
|
497
|
+
emissive: lop.emissive,
|
|
498
|
+
emissiveIntensity: lop.emissiveIntensity,
|
|
499
|
+
clearcoat: lop.clearcoat,
|
|
500
|
+
clearcoatRoughness: lop.clearcoatRoughness,
|
|
501
|
+
anisotropy: lop.anisotropy,
|
|
502
|
+
anisotropyRotation: lop.anisotropyRotation,
|
|
503
|
+
subsurface: lop.subsurface,
|
|
504
|
+
subsurfaceColor: lop.subsurfaceColor,
|
|
505
|
+
sheen: lop.sheen,
|
|
506
|
+
sheenColor: lop.sheenColor,
|
|
507
|
+
sheenRoughness: lop.sheenRoughness,
|
|
508
|
+
iridescence: lop.iridescence,
|
|
509
|
+
iridescenceThickness: lop.iridescenceThickness,
|
|
510
|
+
iridescenceIor: lop.iridescenceIor,
|
|
511
|
+
triplanar: lop.triplanar,
|
|
512
|
+
triplanarScale: lop.triplanarScale,
|
|
513
|
+
triplanarSharpness: lop.triplanarSharpness,
|
|
550
514
|
animationProgress: lop.animationProgress ?? 0,
|
|
551
515
|
animationTime: lop.animationTime ?? 0,
|
|
552
516
|
animationSpeed: lop.animationSpeed ?? 1,
|
|
@@ -570,17 +534,23 @@ function compileTimeline(renderId, virtualMedia, options) {
|
|
|
570
534
|
maxBlurRadius: lop.maxBlurRadius ?? lop.dof?.maxBlurRadius ?? 24,
|
|
571
535
|
shakeTranslation: lop.shakeTranslation ?? (lop.shake?.enabled ? lop.shake?.translationAmplitude ?? 0 : 0),
|
|
572
536
|
shakeRotation: lop.shakeRotation ?? (lop.shake?.enabled ? lop.shake?.rotationAmplitude ?? 0 : 0),
|
|
537
|
+
relativitySpeed: lop.relativitySpeed ?? lop.relativity?.speed ?? 0,
|
|
573
538
|
orbitRadius: lop.orbitRadius,
|
|
574
539
|
orbitAzimuth: lop.orbitAzimuth,
|
|
575
540
|
orbitElevation: lop.orbitElevation,
|
|
576
541
|
lightType: lop.lightType,
|
|
542
|
+
color: lop.color,
|
|
577
543
|
intensity: lop.intensity ?? (lop.kind === "light" ? 1 : void 0),
|
|
578
544
|
radius: lop.radius,
|
|
579
545
|
angle: lop.angle,
|
|
580
546
|
penumbra: lop.penumbra,
|
|
581
|
-
decay: lop.decay
|
|
547
|
+
decay: lop.decay,
|
|
548
|
+
exposure: lop.exposure,
|
|
549
|
+
volumetricFogDensity: lop.volumetricFogDensity,
|
|
550
|
+
volumetricFogAnisotropy: lop.volumetricFogAnisotropy,
|
|
551
|
+
volumetricFogNoiseStrength: lop.volumetricFogNoiseStrength
|
|
582
552
|
};
|
|
583
|
-
for (const track of lop
|
|
553
|
+
for (const track of layerTracks(lop)) if ((track.source ?? { type: "keyframe" }).type !== "keyframe") stub[track.prop] = evaluateTrackAtFrame(track, lop.startFrame ?? 0, fps, {
|
|
584
554
|
startFrame: lop.startFrame ?? 0,
|
|
585
555
|
baseValues: stub,
|
|
586
556
|
signals
|
|
@@ -610,7 +580,7 @@ function compileTimeline(renderId, virtualMedia, options) {
|
|
|
610
580
|
const durationMs = resolveLayerDuration(void 0, childMeta?.durationMs ?? void 0, composeDuration, layerType);
|
|
611
581
|
durationFrames = Math.max(1, Math.round(durationMs / 1e3 * fps));
|
|
612
582
|
}
|
|
613
|
-
for (const track of lop
|
|
583
|
+
for (const track of layerTracks(lop)) {
|
|
614
584
|
const { dropped, maxAuthoredFrame } = compileTrackToTimeline(tl, stub, track, startFrame, fps, durationFrames, signals, live, lop.animation?.frameStep);
|
|
615
585
|
if (dropped > 0) truncations.push({
|
|
616
586
|
layerId,
|
|
@@ -633,6 +603,7 @@ function compileTimeline(renderId, virtualMedia, options) {
|
|
|
633
603
|
tl.seek(1e-6);
|
|
634
604
|
tl.seek(0);
|
|
635
605
|
const compileResult = {
|
|
606
|
+
key: cacheKey,
|
|
636
607
|
tl,
|
|
637
608
|
targetsById,
|
|
638
609
|
nodes: nodeOps,
|
|
@@ -687,6 +658,232 @@ function compileLayerTimeline(layerId, animation, baseVolume, baseMuted, fps) {
|
|
|
687
658
|
return result;
|
|
688
659
|
}
|
|
689
660
|
/**
|
|
661
|
+
* Character animation for the compositor: poses a model from its clip
|
|
662
|
+
* layers, look-at and IK constraints (targets in scene coordinates) and
|
|
663
|
+
* spring bones (replayed from frame 0 and cached, so frames render the
|
|
664
|
+
* same in any order); and the per-instance records of skinned crowds.
|
|
665
|
+
*/
|
|
666
|
+
const transformPoint$1 = (m, p) => [
|
|
667
|
+
m[0] * p[0] + m[4] * p[1] + m[8] * p[2] + m[12],
|
|
668
|
+
m[1] * p[0] + m[5] * p[1] + m[9] * p[2] + m[13],
|
|
669
|
+
m[2] * p[0] + m[6] * p[1] + m[10] * p[2] + m[14]
|
|
670
|
+
];
|
|
671
|
+
const transformDir = (m, v) => [
|
|
672
|
+
m[0] * v[0] + m[4] * v[1] + m[8] * v[2],
|
|
673
|
+
m[1] * v[0] + m[5] * v[1] + m[9] * v[2],
|
|
674
|
+
m[2] * v[0] + m[6] * v[1] + m[10] * v[2]
|
|
675
|
+
];
|
|
676
|
+
/**
|
|
677
|
+
* A mesh's morph weights: the clip's (or the file's defaults), with any
|
|
678
|
+
* target the layer names in `morphs` set from its track. Names match
|
|
679
|
+
* case-insensitively against the mesh's `morphTargetNames`.
|
|
680
|
+
*/
|
|
681
|
+
function namedMorphWeights(names, base, morphs, clock) {
|
|
682
|
+
if (!morphs || !names?.length) return base;
|
|
683
|
+
const out = [...base];
|
|
684
|
+
const index = new Map(names.map((n, i) => [n.toLowerCase(), i]));
|
|
685
|
+
for (const [name, track] of Object.entries(morphs)) {
|
|
686
|
+
const i = index.get(name.toLowerCase());
|
|
687
|
+
if (i !== void 0) out[i] = numberAt(track, clock, out[i] ?? 0);
|
|
688
|
+
}
|
|
689
|
+
return out;
|
|
690
|
+
}
|
|
691
|
+
/** Whether a node needs the rig evaluator (anything beyond one plain clip). */
|
|
692
|
+
function hasRig(n) {
|
|
693
|
+
return Boolean(n.animationLayers?.length || n.ik?.length || n.lookAt?.length || n.springBones?.length || n.pose && Object.keys(n.pose).length || n.aim?.length || n.drive?.length);
|
|
694
|
+
}
|
|
695
|
+
/** Local rotation for Euler degrees, applied Z, then Y, then X (R = Rz · Ry · Rx), like layers. */
|
|
696
|
+
function eulerQuat(rx, ry, rz) {
|
|
697
|
+
const h = (d) => d * Math.PI / 360;
|
|
698
|
+
const [sx, cx] = [Math.sin(h(rx)), Math.cos(h(rx))];
|
|
699
|
+
const [sy, cy] = [Math.sin(h(ry)), Math.cos(h(ry))];
|
|
700
|
+
const [sz, cz] = [Math.sin(h(rz)), Math.cos(h(rz))];
|
|
701
|
+
return [
|
|
702
|
+
cz * cy * sx - sz * sy * cx,
|
|
703
|
+
cz * sy * cx + sz * cy * sx,
|
|
704
|
+
sz * cy * cx - cz * sy * sx,
|
|
705
|
+
cz * cy * cx + sz * sy * sx
|
|
706
|
+
];
|
|
707
|
+
}
|
|
708
|
+
function jointPoses(p, clock) {
|
|
709
|
+
return Object.entries(p.node.pose ?? {}).map(([joint, j]) => ({
|
|
710
|
+
joint,
|
|
711
|
+
rotation: eulerQuat(numberAt(j.rotateX, clock, 0), numberAt(j.rotateY, clock, 0), numberAt(j.rotateZ, clock, 0)),
|
|
712
|
+
offset: [
|
|
713
|
+
numberAt(j.x, clock, 0),
|
|
714
|
+
numberAt(j.y, clock, 0),
|
|
715
|
+
numberAt(j.z, clock, 0)
|
|
716
|
+
],
|
|
717
|
+
weight: numberAt(j.weight, clock, 1),
|
|
718
|
+
mode: j.mode ?? "additive"
|
|
719
|
+
}));
|
|
720
|
+
}
|
|
721
|
+
function clipLayers(p, frame) {
|
|
722
|
+
const layers = p.node.animationLayers;
|
|
723
|
+
if (!layers?.length) return p.clip ? [{
|
|
724
|
+
clip: p.clip,
|
|
725
|
+
time: p.clipSec,
|
|
726
|
+
weight: 1
|
|
727
|
+
}] : [];
|
|
728
|
+
const out = [];
|
|
729
|
+
for (const l of layers) {
|
|
730
|
+
const [clip] = resolveClips(p.model, [l.clip]);
|
|
731
|
+
if (!clip) continue;
|
|
732
|
+
let time = (l.timeOffset ?? 0) + frame / p.fps * (l.speed ?? 1);
|
|
733
|
+
if (clip.duration > 0) time = l.loop ?? true ? (time % clip.duration + clip.duration) % clip.duration : Math.min(Math.max(time, 0), clip.duration);
|
|
734
|
+
out.push({
|
|
735
|
+
clip,
|
|
736
|
+
time,
|
|
737
|
+
weight: numberAt(l.weight, {
|
|
738
|
+
frame,
|
|
739
|
+
fps: p.fps
|
|
740
|
+
}, 1),
|
|
741
|
+
mask: l.mask
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
return out;
|
|
745
|
+
}
|
|
746
|
+
function constraintsAt(p, frame, toModel) {
|
|
747
|
+
const clock = {
|
|
748
|
+
frame,
|
|
749
|
+
fps: p.fps
|
|
750
|
+
};
|
|
751
|
+
const point = (t) => transformPoint$1(toModel, vec3At(t, clock));
|
|
752
|
+
const direction = (t) => transformDir(toModel, vec3At(t, clock));
|
|
753
|
+
return {
|
|
754
|
+
pose: jointPoses(p, clock),
|
|
755
|
+
aim: (p.node.aim ?? []).map((a) => ({
|
|
756
|
+
joint: a.joint,
|
|
757
|
+
direction: direction(a.direction),
|
|
758
|
+
weight: numberAt(a.weight, clock, 1),
|
|
759
|
+
...a.axis && { axis: a.axis }
|
|
760
|
+
})),
|
|
761
|
+
ik: (p.node.ik ?? []).map((c) => ({
|
|
762
|
+
chain: c.chain,
|
|
763
|
+
target: point(c.target),
|
|
764
|
+
pole: c.poleTarget ? point(c.poleTarget) : void 0,
|
|
765
|
+
weight: numberAt(c.weight, clock, 1)
|
|
766
|
+
})),
|
|
767
|
+
drive: [...p.model.drivers ?? [], ...p.node.drive ?? []],
|
|
768
|
+
lookAt: (p.node.lookAt ?? []).map((c) => ({
|
|
769
|
+
joint: c.joint,
|
|
770
|
+
target: point(c.target),
|
|
771
|
+
weight: numberAt(c.weight, clock, 1),
|
|
772
|
+
maxAngleDeg: c.maxAngleDeg ?? 70,
|
|
773
|
+
axis: c.axis ?? [
|
|
774
|
+
0,
|
|
775
|
+
0,
|
|
776
|
+
1
|
|
777
|
+
]
|
|
778
|
+
}))
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
/** The pose before springs: blended clips, then constraints. */
|
|
782
|
+
function basePose(p, frame, toModel) {
|
|
783
|
+
const rig = blendClipLayers(p.model, clipLayers(p, frame));
|
|
784
|
+
applyConstraints(rig, constraintsAt(p, frame, toModel));
|
|
785
|
+
return rig;
|
|
786
|
+
}
|
|
787
|
+
const springStates = /* @__PURE__ */ new Map();
|
|
788
|
+
function springsAt(p, toModel, rig) {
|
|
789
|
+
const chains = p.node.springBones;
|
|
790
|
+
if (!chains?.length) return void 0;
|
|
791
|
+
const config = JSON.stringify([
|
|
792
|
+
chains,
|
|
793
|
+
p.node.animationLayers,
|
|
794
|
+
p.node.pose,
|
|
795
|
+
p.node.aim,
|
|
796
|
+
p.fps
|
|
797
|
+
]);
|
|
798
|
+
let s = springStates.get(p.key);
|
|
799
|
+
const frame = Math.max(0, Math.floor(p.frame));
|
|
800
|
+
if (!s || s.model !== p.model || s.config !== config || s.frame > frame) {
|
|
801
|
+
const gravityModel = (g) => transformDir(toModel, g ?? [
|
|
802
|
+
0,
|
|
803
|
+
0,
|
|
804
|
+
0
|
|
805
|
+
]);
|
|
806
|
+
s = {
|
|
807
|
+
model: p.model,
|
|
808
|
+
config,
|
|
809
|
+
springs: new SpringBones(rig, chains.map((c) => ({
|
|
810
|
+
...c,
|
|
811
|
+
gravity: gravityModel(c.gravity)
|
|
812
|
+
}))),
|
|
813
|
+
frame: -1
|
|
814
|
+
};
|
|
815
|
+
if (springStates.size > 256) springStates.clear();
|
|
816
|
+
springStates.set(p.key, s);
|
|
817
|
+
}
|
|
818
|
+
for (let f = s.frame + 1; f <= frame; f++) {
|
|
819
|
+
s.springs.step(basePose(p, f, toModel), 1 / p.fps);
|
|
820
|
+
s.frame = f;
|
|
821
|
+
}
|
|
822
|
+
return s.springs;
|
|
823
|
+
}
|
|
824
|
+
/** Model-space node matrices for this frame. */
|
|
825
|
+
function poseCharacter(p) {
|
|
826
|
+
if (!hasRig(p.node) && !p.model.drivers?.length) return poseNodes(p.model, p.clip, p.clipSec);
|
|
827
|
+
const toModel = Matrix4Math.invert(p.sceneRoot) ?? Matrix4Math.identity();
|
|
828
|
+
const rig = basePose(p, p.frame, toModel);
|
|
829
|
+
springsAt(p, toModel, rig)?.apply(rig);
|
|
830
|
+
return rig.world();
|
|
831
|
+
}
|
|
832
|
+
const bakes = /* @__PURE__ */ new WeakMap();
|
|
833
|
+
const palettes = /* @__PURE__ */ new WeakMap();
|
|
834
|
+
/** A baked palette on the GPU, uploaded once. */
|
|
835
|
+
function paletteBuffer(device, palette) {
|
|
836
|
+
let buffer = palettes.get(palette);
|
|
837
|
+
if (!buffer) {
|
|
838
|
+
buffer = device.createBuffer({
|
|
839
|
+
label: "CrowdPalette",
|
|
840
|
+
size: Math.max(64, palette.byteLength),
|
|
841
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
|
|
842
|
+
});
|
|
843
|
+
device.queue.writeBuffer(buffer, 0, palette);
|
|
844
|
+
palettes.set(palette, buffer);
|
|
845
|
+
}
|
|
846
|
+
return buffer;
|
|
847
|
+
}
|
|
848
|
+
/** The model's crowd palette for these clips, baked once. */
|
|
849
|
+
function crowdBake(model, crowd) {
|
|
850
|
+
const key = JSON.stringify([crowd.clips, crowd.fps ?? 30]);
|
|
851
|
+
let byKey = bakes.get(model);
|
|
852
|
+
if (!byKey) {
|
|
853
|
+
byKey = /* @__PURE__ */ new Map();
|
|
854
|
+
bakes.set(model, byKey);
|
|
855
|
+
}
|
|
856
|
+
let bake = byKey.get(key);
|
|
857
|
+
if (!bake) {
|
|
858
|
+
const clips = resolveClips(model, crowd.clips);
|
|
859
|
+
if (!clips.length) return void 0;
|
|
860
|
+
bake = bakeCrowdPalette(model, clips, crowd.fps ?? 30);
|
|
861
|
+
byKey.set(key, bake);
|
|
862
|
+
}
|
|
863
|
+
return bake;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Instance `i`'s second record: (first baked frame, frames per loop, phase
|
|
867
|
+
* in frames, frames per second of playback). Unset fields come from the seed: clip i % n, a random
|
|
868
|
+
* phase, a speed within `speedRange`.
|
|
869
|
+
*/
|
|
870
|
+
function crowdRecord(bake, crowd, i, anim) {
|
|
871
|
+
const rand = createRandom((crowd.seed ?? 1) * 7919 + i * 104729);
|
|
872
|
+
const pick = rand();
|
|
873
|
+
const speedDraw = rand();
|
|
874
|
+
const clipIndex = (anim.clip ?? i) % bake.clips.length;
|
|
875
|
+
const range = bake.clips[Math.max(0, clipIndex)];
|
|
876
|
+
const [s0, s1] = crowd.speedRange ?? [1, 1];
|
|
877
|
+
const offset = anim.animOffset ?? ((crowd.phase ?? "random") === "random" ? pick * range.duration : 0);
|
|
878
|
+
const rate = range.duration > 0 ? range.count / range.duration : bake.fps;
|
|
879
|
+
return [
|
|
880
|
+
range.base,
|
|
881
|
+
range.count,
|
|
882
|
+
offset * rate,
|
|
883
|
+
(anim.animSpeed ?? s0 + (s1 - s0) * speedDraw) * rate
|
|
884
|
+
];
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
690
887
|
* Which container kinds paint their own background.
|
|
691
888
|
*
|
|
692
889
|
* flex/block/box all accept an optional `background` in the program schema.
|
|
@@ -698,6 +895,110 @@ function shouldPaintContainerBackground(kind, background) {
|
|
|
698
895
|
if (!background) return false;
|
|
699
896
|
return kind === "flex" || kind === "block" || kind === "box";
|
|
700
897
|
}
|
|
898
|
+
/** Largest face a cube camera picks on its own; `lens.cubeSize` may go higher. */
|
|
899
|
+
const DEFAULT_MAX_FACE = 4096;
|
|
900
|
+
/**
|
|
901
|
+
* The cube camera an authored camera asks for, or null for an ordinary
|
|
902
|
+
* perspective view. A camera with `relativity` is always a cube camera, even
|
|
903
|
+
* at speed 0, so a shot that accelerates from rest never switches pipelines.
|
|
904
|
+
*/
|
|
905
|
+
function resolveCubeCamera(authored, camera, speed, width, height, maxTextureSize) {
|
|
906
|
+
const projection = authored?.lens?.projection ?? "perspective";
|
|
907
|
+
const relativity = authored?.relativity;
|
|
908
|
+
if (projection === "perspective" && !relativity) return null;
|
|
909
|
+
const lens = {
|
|
910
|
+
projection,
|
|
911
|
+
fov: camera.fov,
|
|
912
|
+
zoom: camera.zoom
|
|
913
|
+
};
|
|
914
|
+
const requested = authored?.lens?.cubeSize;
|
|
915
|
+
const faceSize = Math.min(maxTextureSize, requested ?? defaultCubeFaceSize(lens, width, height, Math.min(DEFAULT_MAX_FACE, maxTextureSize)));
|
|
916
|
+
const basis = cameraBasis(camera);
|
|
917
|
+
const observer = relativity ? {
|
|
918
|
+
speed,
|
|
919
|
+
direction: relativity.direction ? Vector3Math.normalize(relativity.direction) : basis.forward,
|
|
920
|
+
doppler: relativity.doppler ?? true,
|
|
921
|
+
beaming: relativity.beaming ?? true,
|
|
922
|
+
exposure: relativity.exposure ?? "auto"
|
|
923
|
+
} : null;
|
|
924
|
+
return {
|
|
925
|
+
faceSize,
|
|
926
|
+
remap: {
|
|
927
|
+
...lens,
|
|
928
|
+
basis,
|
|
929
|
+
observer
|
|
930
|
+
},
|
|
931
|
+
centerDensity: lensCenterDensity(lens, width, height)
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Whether the pieces are all still where they started at `frame` (or there
|
|
936
|
+
* is no track): the layer looks whole, and its cut faces, hidden inside,
|
|
937
|
+
* need not draw (where pieces meet, a cut face can tie the surface's depth).
|
|
938
|
+
*/
|
|
939
|
+
function fractureWhole(model, spec, frame) {
|
|
940
|
+
const track = spec.track;
|
|
941
|
+
const stride = (model.nodes?.length ?? 0) * 7;
|
|
942
|
+
if (!track?.length || !stride) return true;
|
|
943
|
+
const frames = Math.floor(track.length / stride);
|
|
944
|
+
const at = Math.min(Math.max(Math.ceil(frame), 0), frames - 1) * stride;
|
|
945
|
+
for (let i = 0; i < stride; i++) if (track[at + i] !== track[i]) return false;
|
|
946
|
+
return true;
|
|
947
|
+
}
|
|
948
|
+
/** The fractured model for a node's source model (cached per model and spec). */
|
|
949
|
+
function fracturedModel(model, spec) {
|
|
950
|
+
return fractureModel(model, spec).model;
|
|
951
|
+
}
|
|
952
|
+
function poseAt(track, at) {
|
|
953
|
+
return {
|
|
954
|
+
p: [
|
|
955
|
+
track[at],
|
|
956
|
+
track[at + 1],
|
|
957
|
+
track[at + 2]
|
|
958
|
+
],
|
|
959
|
+
q: [
|
|
960
|
+
track[at + 3],
|
|
961
|
+
track[at + 4],
|
|
962
|
+
track[at + 5],
|
|
963
|
+
track[at + 6]
|
|
964
|
+
]
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
function blend(a, b, t) {
|
|
968
|
+
if (t <= 0) return a;
|
|
969
|
+
const sign = a.q.reduce((s, v, i) => s + v * b.q[i], 0) < 0 ? -1 : 1;
|
|
970
|
+
const q = a.q.map((v, i) => v + (b.q[i] * sign - v) * t);
|
|
971
|
+
const len = Math.hypot(...q) || 1;
|
|
972
|
+
return {
|
|
973
|
+
p: a.p.map((v, i) => v + (b.p[i] - v) * t),
|
|
974
|
+
q: q.map((v) => v / len)
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Model-space matrices of the pieces' nodes at `frame`. The track is in the
|
|
979
|
+
* layer's parent space (physics reads the layer's own x/y/z, as for any
|
|
980
|
+
* body), and `layerProps` is the layer's matrix in that space, L. A piece
|
|
981
|
+
* at pose (p, q) has node matrix L⁻¹ · T(p) · R(q) · S, so with its inverse
|
|
982
|
+
* bind T(−centroid) a vertex lands at parent · (p + q · S · (v − centroid)):
|
|
983
|
+
* pieces fly in their group, like other bodies. Undefined without a track.
|
|
984
|
+
*/
|
|
985
|
+
function fracturePose(model, spec, frame, layerProps, scale$1) {
|
|
986
|
+
const track = spec.track;
|
|
987
|
+
const pieces = model.nodes?.length ?? 0;
|
|
988
|
+
const stride = pieces * 7;
|
|
989
|
+
if (!track?.length || !stride || track.length % stride !== 0) return void 0;
|
|
990
|
+
const frames = track.length / stride;
|
|
991
|
+
const f = Math.min(Math.max(frame, 0), frames - 1);
|
|
992
|
+
const f0 = Math.floor(f);
|
|
993
|
+
const f1 = Math.min(frames - 1, f0 + 1);
|
|
994
|
+
const toModel = Matrix4Math.invert(layerProps) ?? Matrix4Math.identity();
|
|
995
|
+
const out = [];
|
|
996
|
+
for (let i = 0; i < pieces; i++) {
|
|
997
|
+
const { p, q } = blend(poseAt(track, f0 * stride + i * 7), poseAt(track, f1 * stride + i * 7), f - f0);
|
|
998
|
+
out.push(Matrix4Math.multiply(toModel, trsMatrix(p, q, scale$1)));
|
|
999
|
+
}
|
|
1000
|
+
return out;
|
|
1001
|
+
}
|
|
701
1002
|
const TRANSFORMS = new Set([
|
|
702
1003
|
"position",
|
|
703
1004
|
"rotation",
|
|
@@ -729,6 +1030,253 @@ function compatibleMeshDraws(a, b) {
|
|
|
729
1030
|
for (const key of keys) if (!TRANSFORMS.has(key) && !sameValue(left[key], right[key])) return false;
|
|
730
1031
|
return true;
|
|
731
1032
|
}
|
|
1033
|
+
/** Two frames of one value: the latest and the one before it. */
|
|
1034
|
+
var Slots = class {
|
|
1035
|
+
frame = NaN;
|
|
1036
|
+
value;
|
|
1037
|
+
prevFrame = NaN;
|
|
1038
|
+
prevValue;
|
|
1039
|
+
write(frame, value) {
|
|
1040
|
+
if (frame !== this.frame) {
|
|
1041
|
+
this.prevFrame = this.frame;
|
|
1042
|
+
this.prevValue = this.value;
|
|
1043
|
+
}
|
|
1044
|
+
this.frame = frame;
|
|
1045
|
+
this.value = value;
|
|
1046
|
+
}
|
|
1047
|
+
/** The value at `frame`, if it is one of the two held. */
|
|
1048
|
+
at(frame) {
|
|
1049
|
+
if (frame === this.frame) return this.value;
|
|
1050
|
+
if (frame === this.prevFrame) return this.prevValue;
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
var MotionHistory = class {
|
|
1054
|
+
states = /* @__PURE__ */ new Map();
|
|
1055
|
+
instances;
|
|
1056
|
+
vertices;
|
|
1057
|
+
camera = new Slots();
|
|
1058
|
+
/** Frames recorded, latest last (two kept). */
|
|
1059
|
+
frames = new Slots();
|
|
1060
|
+
constructor(device) {
|
|
1061
|
+
this.instances = new GpuPairs(device, "Instances");
|
|
1062
|
+
this.vertices = new GpuPairs(device, "Vertices");
|
|
1063
|
+
}
|
|
1064
|
+
/** Whether rendering `frame` must render `frame - 1` first to know its motion. */
|
|
1065
|
+
needsPrevious(frame) {
|
|
1066
|
+
return frame > 0 && this.frames.at(frame - 1) === void 0;
|
|
1067
|
+
}
|
|
1068
|
+
previousCamera(frame) {
|
|
1069
|
+
return this.camera.at(frame - 1);
|
|
1070
|
+
}
|
|
1071
|
+
/** A mesh's state at `frame - 1`, shaped for the velocity pass. */
|
|
1072
|
+
previousMesh(key, frame, now) {
|
|
1073
|
+
const prev = this.states.get(key)?.at(frame - 1);
|
|
1074
|
+
if (prev?.kind !== "mesh") return void 0;
|
|
1075
|
+
const out = { modelMatrix: prev.modelMatrix };
|
|
1076
|
+
if (now.skinning && prev.skinning?.length === now.skinning.length) out.skinningMatrices = prev.skinning;
|
|
1077
|
+
const copy = this.instances.at(key, frame - 1);
|
|
1078
|
+
if (now.instanceBuffer && copy && prev.instanceBytes === now.instanceBuffer.size) out.instanceBuffer = copy;
|
|
1079
|
+
const vertices = this.vertices.at(key, frame - 1);
|
|
1080
|
+
if (now.vertexBytes && vertices && prev.vertexBytes === now.vertexBytes) out.vertexBuffer = vertices;
|
|
1081
|
+
if (now.wind && prev.windTime !== void 0) out.wind = {
|
|
1082
|
+
...now.wind,
|
|
1083
|
+
time: prev.windTime
|
|
1084
|
+
};
|
|
1085
|
+
if (now.crowd && prev.crowdTime !== void 0) out.crowd = {
|
|
1086
|
+
...now.crowd,
|
|
1087
|
+
time: prev.crowdTime
|
|
1088
|
+
};
|
|
1089
|
+
return out;
|
|
1090
|
+
}
|
|
1091
|
+
previousQuad(key, frame) {
|
|
1092
|
+
const prev = this.states.get(key)?.at(frame - 1);
|
|
1093
|
+
return prev?.kind === "quad" ? prev.modelMatrix : void 0;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Records a mesh at `frame`; its instance records and deformed vertices
|
|
1097
|
+
* (when the GPU deforms it) are copied in `encoder`.
|
|
1098
|
+
*/
|
|
1099
|
+
recordMesh(encoder, key, frame, state, buffers) {
|
|
1100
|
+
const { instanceBuffer, vertices } = buffers;
|
|
1101
|
+
if (instanceBuffer) this.instances.copy(encoder, key, frame, instanceBuffer, instanceBuffer.size, GPUBufferUsage.STORAGE);
|
|
1102
|
+
if (vertices) this.vertices.copy(encoder, key, frame, vertices.buffer, vertices.bytes, GPUBufferUsage.VERTEX);
|
|
1103
|
+
this.slots(key).write(frame, {
|
|
1104
|
+
kind: "mesh",
|
|
1105
|
+
...state,
|
|
1106
|
+
...state.skinning && { skinning: state.skinning.slice() },
|
|
1107
|
+
instanceBytes: instanceBuffer?.size,
|
|
1108
|
+
vertexBytes: vertices?.bytes
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
previousSlug(key, frame) {
|
|
1112
|
+
const prev = this.states.get(key)?.at(frame - 1);
|
|
1113
|
+
return prev?.kind === "slug" ? prev : void 0;
|
|
1114
|
+
}
|
|
1115
|
+
/** Records a text plane at `frame`; glyph records are copied (batches are rebuilt each frame). */
|
|
1116
|
+
recordSlug(key, frame, modelMatrix, batches) {
|
|
1117
|
+
this.slots(key).write(frame, {
|
|
1118
|
+
kind: "slug",
|
|
1119
|
+
modelMatrix,
|
|
1120
|
+
batches: batches.map((b) => ({
|
|
1121
|
+
...b,
|
|
1122
|
+
instances: b.instances.slice(0, b.instanceCount * 24)
|
|
1123
|
+
}))
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
recordQuad(key, frame, modelMatrix) {
|
|
1127
|
+
this.slots(key).write(frame, {
|
|
1128
|
+
kind: "quad",
|
|
1129
|
+
modelMatrix
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
recordFrame(frame, camera) {
|
|
1133
|
+
this.camera.write(frame, camera);
|
|
1134
|
+
this.frames.write(frame, true);
|
|
1135
|
+
}
|
|
1136
|
+
slots(key) {
|
|
1137
|
+
let s = this.states.get(key);
|
|
1138
|
+
if (!s) {
|
|
1139
|
+
s = new Slots();
|
|
1140
|
+
this.states.set(key, s);
|
|
1141
|
+
}
|
|
1142
|
+
return s;
|
|
1143
|
+
}
|
|
1144
|
+
};
|
|
1145
|
+
/** GPU copies of a buffer per key, one per frame parity. */
|
|
1146
|
+
var GpuPairs = class {
|
|
1147
|
+
pairs = /* @__PURE__ */ new Map();
|
|
1148
|
+
constructor(device, label) {
|
|
1149
|
+
this.device = device;
|
|
1150
|
+
this.label = label;
|
|
1151
|
+
}
|
|
1152
|
+
at(key, frame) {
|
|
1153
|
+
return this.pairs.get(key)?.[frame & 1];
|
|
1154
|
+
}
|
|
1155
|
+
copy(encoder, key, frame, source, bytes, usage) {
|
|
1156
|
+
const pair = this.pairs.get(key) ?? [];
|
|
1157
|
+
const slot = frame & 1;
|
|
1158
|
+
let copy = pair[slot];
|
|
1159
|
+
if (!copy || copy.size !== bytes) {
|
|
1160
|
+
copy?.destroy();
|
|
1161
|
+
copy = this.device.createBuffer({
|
|
1162
|
+
label: `MotionHistory${this.label}:${key}`,
|
|
1163
|
+
size: bytes,
|
|
1164
|
+
usage: usage | GPUBufferUsage.COPY_DST
|
|
1165
|
+
});
|
|
1166
|
+
pair[slot] = copy;
|
|
1167
|
+
this.pairs.set(key, pair);
|
|
1168
|
+
}
|
|
1169
|
+
encoder.copyBufferToBuffer(source, 0, copy, 0, bytes);
|
|
1170
|
+
}
|
|
1171
|
+
};
|
|
1172
|
+
const histories = /* @__PURE__ */ new Map();
|
|
1173
|
+
/** The motion history of one composition render (by render id). */
|
|
1174
|
+
function motionHistory(device, renderId) {
|
|
1175
|
+
let h = histories.get(renderId);
|
|
1176
|
+
if (!h) {
|
|
1177
|
+
if (histories.size > 64) histories.clear();
|
|
1178
|
+
h = new MotionHistory(device);
|
|
1179
|
+
histories.set(renderId, h);
|
|
1180
|
+
}
|
|
1181
|
+
return h;
|
|
1182
|
+
}
|
|
1183
|
+
/** T · Rz · Ry · Rx · S: the transform the compositor draws a model with. */
|
|
1184
|
+
function nodeMatrix(n) {
|
|
1185
|
+
const rad = Math.PI / 180;
|
|
1186
|
+
const s = n.scale ?? 1;
|
|
1187
|
+
let m = Matrix4Math.translate(n.x ?? 0, n.y ?? 0, n.z ?? 0);
|
|
1188
|
+
if (n.rotateZ) m = Matrix4Math.multiply(m, Matrix4Math.rotateZ(n.rotateZ * rad));
|
|
1189
|
+
if (n.rotateY) m = Matrix4Math.multiply(m, Matrix4Math.rotateY(n.rotateY * rad));
|
|
1190
|
+
if (n.rotateX) m = Matrix4Math.multiply(m, Matrix4Math.rotateX(n.rotateX * rad));
|
|
1191
|
+
return Matrix4Math.multiply(m, Matrix4Math.scale(s * (n.scaleX ?? 1), s * (n.scaleY ?? 1), s * (n.scaleZ ?? 1)));
|
|
1192
|
+
}
|
|
1193
|
+
const isModel = (v) => typeof v === "object" && v !== null && "meshes" in v;
|
|
1194
|
+
/** The surface's mesh: in memory, rebuilt from its primitive spec, or loaded. */
|
|
1195
|
+
async function surfaceModel(n, load) {
|
|
1196
|
+
if (isModel(n.modelData)) return n.modelData;
|
|
1197
|
+
if (n.primitive3d) return getPrimitiveGeometry(n.primitive3d);
|
|
1198
|
+
if (n.src) return load(n.src, n);
|
|
1199
|
+
}
|
|
1200
|
+
const NO_PRE = {
|
|
1201
|
+
q: [
|
|
1202
|
+
0,
|
|
1203
|
+
0,
|
|
1204
|
+
0,
|
|
1205
|
+
1
|
|
1206
|
+
],
|
|
1207
|
+
s: 1
|
|
1208
|
+
};
|
|
1209
|
+
function composeQuat(a, b) {
|
|
1210
|
+
return [
|
|
1211
|
+
a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1],
|
|
1212
|
+
a[3] * b[1] - a[0] * b[2] + a[1] * b[3] + a[2] * b[0],
|
|
1213
|
+
a[3] * b[2] + a[0] * b[1] - a[1] * b[0] + a[2] * b[3],
|
|
1214
|
+
a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2]
|
|
1215
|
+
];
|
|
1216
|
+
}
|
|
1217
|
+
/** The variant's lowest point after its own rotation and scale: the largest y (up is -y). */
|
|
1218
|
+
function variantBottom(model, pre) {
|
|
1219
|
+
const b = model.bounds;
|
|
1220
|
+
if (!b) return 0;
|
|
1221
|
+
let bottom = Number.NEGATIVE_INFINITY;
|
|
1222
|
+
for (let k = 0; k < 8; k++) {
|
|
1223
|
+
const corner = [
|
|
1224
|
+
k & 1 ? b.max[0] : b.min[0],
|
|
1225
|
+
k & 2 ? b.max[1] : b.min[1],
|
|
1226
|
+
k & 4 ? b.max[2] : b.min[2]
|
|
1227
|
+
];
|
|
1228
|
+
bottom = Math.max(bottom, rotateByQuat(pre.q, corner)[1] * pre.s);
|
|
1229
|
+
}
|
|
1230
|
+
return bottom;
|
|
1231
|
+
}
|
|
1232
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
1233
|
+
/**
|
|
1234
|
+
* Instance transforms for a scatter: points on the surface, each seated on
|
|
1235
|
+
* its variant's base (instance i draws variant i % bottoms.length; bottoms
|
|
1236
|
+
* already include the variant's own rotation and scale).
|
|
1237
|
+
*/
|
|
1238
|
+
function scatterTransforms(scatter, surface, bottoms) {
|
|
1239
|
+
const surfaceNode = scatter.surface;
|
|
1240
|
+
const key = JSON.stringify([bottoms, surface.bounds?.size]);
|
|
1241
|
+
const hit = cache.get(scatter);
|
|
1242
|
+
if (hit && hit.key === key) return hit.out;
|
|
1243
|
+
const { points } = scatterOnSurface({
|
|
1244
|
+
model: surface,
|
|
1245
|
+
matrix: nodeMatrix(surfaceNode)
|
|
1246
|
+
}, scatter);
|
|
1247
|
+
const n = Math.max(1, bottoms.length);
|
|
1248
|
+
const out = points.map((p, i) => {
|
|
1249
|
+
const [x, y, z] = seatOnSurface(p, bottoms[i % n] ?? 0, scatter.sink ?? 0);
|
|
1250
|
+
return {
|
|
1251
|
+
x,
|
|
1252
|
+
y,
|
|
1253
|
+
z,
|
|
1254
|
+
rotation: p.rotation,
|
|
1255
|
+
scale: p.scale
|
|
1256
|
+
};
|
|
1257
|
+
});
|
|
1258
|
+
cache.set(scatter, {
|
|
1259
|
+
key,
|
|
1260
|
+
out
|
|
1261
|
+
});
|
|
1262
|
+
return out;
|
|
1263
|
+
}
|
|
1264
|
+
/** The wind a mesh of `model` sways in at `seconds`, or undefined when calm. */
|
|
1265
|
+
function meshWind(wind, model, seconds) {
|
|
1266
|
+
if (!wind) return void 0;
|
|
1267
|
+
const b = model.bounds;
|
|
1268
|
+
const height = b ? b.size[1] : 0;
|
|
1269
|
+
if (!b || height <= 0) return void 0;
|
|
1270
|
+
return {
|
|
1271
|
+
amplitudeDeg: wind.amplitudeDeg ?? 8,
|
|
1272
|
+
frequency: wind.frequency ?? .4,
|
|
1273
|
+
direction: wind.direction ?? [1, 0],
|
|
1274
|
+
waveScale: wind.waveScale ?? 600,
|
|
1275
|
+
time: seconds,
|
|
1276
|
+
baseY: b.max[1],
|
|
1277
|
+
height
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
732
1280
|
function translate(tx, ty) {
|
|
733
1281
|
return {
|
|
734
1282
|
a: 1,
|
|
@@ -855,16 +1403,20 @@ const MAX_RASTER_SCALE = 4;
|
|
|
855
1403
|
* Pixels per layout px to rasterize a 2D layer at, so it stays sharp when its
|
|
856
1404
|
* transform onto the canvas scales it up by `axisScale` (the transform's
|
|
857
1405
|
* larger axis scale). Rounded up to a quarter, so an animated zoom reuses a
|
|
858
|
-
* few texture sizes instead of allocating new ones every frame;
|
|
1406
|
+
* few texture sizes instead of allocating new ones every frame; not below 1
|
|
859
1407
|
* (a shrunk layer keeps its layout raster). Capped, rounded down to a quarter,
|
|
860
1408
|
* by MAX_RASTER_SCALE, by `limits.maxDimension` (the GPU's texture side), by
|
|
861
1409
|
* `limits.maxPixels` (a pixel budget for one texture) and by
|
|
862
1410
|
* `limits.effects`, the highest scale the layer's effects keep their look at.
|
|
1411
|
+
* The texture side is a hard limit: a layer longer than it at layout scale
|
|
1412
|
+
* (a tall reel strip, a long scroll) rasterizes just under it, below 1.
|
|
863
1413
|
*/
|
|
864
1414
|
function layerRasterScale(axisScale, size, limits) {
|
|
865
1415
|
const w = Math.max(1, size.width);
|
|
866
1416
|
const h = Math.max(1, size.height);
|
|
867
1417
|
const cap = Math.min(MAX_RASTER_SCALE, limits.maxDimension / Math.max(w, h), Math.sqrt(limits.maxPixels / (w * h)), limits.effects);
|
|
1418
|
+
const fits = limits.maxDimension / Math.max(w, h);
|
|
1419
|
+
if (fits < 1) return Math.floor(fits * 1024) / 1024;
|
|
868
1420
|
const wanted = Math.ceil(axisScale * 4 - 1e-6) / 4;
|
|
869
1421
|
return Math.max(1, Math.min(wanted, Math.floor(cap * 4 + 1e-6) / 4));
|
|
870
1422
|
}
|
|
@@ -1084,6 +1636,25 @@ function has3DTransform(target, lop) {
|
|
|
1084
1636
|
return false;
|
|
1085
1637
|
}
|
|
1086
1638
|
const meshHasAlpha = /* @__PURE__ */ new WeakMap();
|
|
1639
|
+
/**
|
|
1640
|
+
* How far a text node's ink can reach past its layout box, in px: an outside
|
|
1641
|
+
* stroke reaches its full width past the outline (any other alignment, half),
|
|
1642
|
+
* a shadow its offset plus blur. One px of slack covers antialiasing.
|
|
1643
|
+
*/
|
|
1644
|
+
function textInkOutset(target, lop) {
|
|
1645
|
+
const num = (v) => typeof v === "number" && v > 0 ? v : 0;
|
|
1646
|
+
const width = num(target?.strokeWidth ?? lop.strokeWidth);
|
|
1647
|
+
const stroke = Boolean(target?.stroke ?? target?.strokeColor ?? lop.stroke) ? lop.strokeAlign === "outside" ? width : width / 2 : 0;
|
|
1648
|
+
let shadow = 0;
|
|
1649
|
+
const shadows = lop.shadows;
|
|
1650
|
+
if (Array.isArray(shadows)) for (const s of shadows) shadow = Math.max(shadow, Math.max(Math.abs(s.offset?.x ?? 0), Math.abs(s.offset?.y ?? 0)) + 2 * num(s.blurRadius));
|
|
1651
|
+
const reach = stroke + shadow;
|
|
1652
|
+
return reach > 0 ? Math.ceil(reach) + 1 : 0;
|
|
1653
|
+
}
|
|
1654
|
+
/** Bytes of a mesh's vertex buffer: 16 floats per vertex. */
|
|
1655
|
+
function deformedBytes(mesh) {
|
|
1656
|
+
return mesh.positions.length / 3 * 64;
|
|
1657
|
+
}
|
|
1087
1658
|
function hasVertexAlpha(mesh) {
|
|
1088
1659
|
const cached = meshHasAlpha.get(mesh);
|
|
1089
1660
|
if (cached !== void 0) return cached;
|
|
@@ -1177,6 +1748,8 @@ const audioTrackLatentCache = /* @__PURE__ */ new Map();
|
|
|
1177
1748
|
const swarmStateMap = /* @__PURE__ */ new WeakMap();
|
|
1178
1749
|
const deviceRenderer3DCache = /* @__PURE__ */ new WeakMap();
|
|
1179
1750
|
/** One Renderer3D per device, target format and MSAA sample count. */
|
|
1751
|
+
/** The command encoder the 3D pools were last recycled for, per device. */
|
|
1752
|
+
const poolEncoder = /* @__PURE__ */ new WeakMap();
|
|
1180
1753
|
function getRenderer3D(device, format, sampleCount) {
|
|
1181
1754
|
let byConfig = deviceRenderer3DCache.get(device);
|
|
1182
1755
|
if (!byConfig) {
|
|
@@ -1329,8 +1902,37 @@ function surfaceProps(target, lop, mat) {
|
|
|
1329
1902
|
out.emissiveIntensity = target?.emissiveIntensity ?? lop.emissiveIntensity ?? mat?.emissiveStrength ?? 1;
|
|
1330
1903
|
}
|
|
1331
1904
|
if (lop.castShadow !== void 0) out.castShadow = lop.castShadow;
|
|
1905
|
+
out.toon = target?.toon ?? lop.toon;
|
|
1906
|
+
out.outline = target?.outline ?? lop.outline;
|
|
1907
|
+
const file = mat?.surface;
|
|
1908
|
+
const lobes = {
|
|
1909
|
+
clearcoat: target?.clearcoat ?? lop.clearcoat ?? file?.clearcoat,
|
|
1910
|
+
clearcoatRoughness: target?.clearcoatRoughness ?? lop.clearcoatRoughness ?? file?.clearcoatRoughness,
|
|
1911
|
+
anisotropy: target?.anisotropy ?? lop.anisotropy ?? file?.anisotropy,
|
|
1912
|
+
anisotropyRotation: target?.anisotropyRotation ?? lop.anisotropyRotation ?? file?.anisotropyRotation,
|
|
1913
|
+
subsurface: target?.subsurface ?? lop.subsurface ?? file?.subsurface,
|
|
1914
|
+
subsurfaceColor: target?.subsurfaceColor ?? lop.subsurfaceColor ?? file?.subsurfaceColor,
|
|
1915
|
+
sheen: target?.sheen ?? lop.sheen ?? file?.sheen,
|
|
1916
|
+
sheenColor: target?.sheenColor ?? lop.sheenColor ?? file?.sheenColor,
|
|
1917
|
+
sheenRoughness: target?.sheenRoughness ?? lop.sheenRoughness ?? file?.sheenRoughness,
|
|
1918
|
+
iridescence: target?.iridescence ?? lop.iridescence ?? file?.iridescence,
|
|
1919
|
+
iridescenceThickness: target?.iridescenceThickness ?? lop.iridescenceThickness ?? file?.iridescenceThickness,
|
|
1920
|
+
iridescenceIor: target?.iridescenceIor ?? lop.iridescenceIor ?? file?.iridescenceIor
|
|
1921
|
+
};
|
|
1922
|
+
for (const [key, value] of Object.entries(lobes)) if (value !== void 0) out[key] = value;
|
|
1923
|
+
const triplanar = target?.triplanar ?? lop.triplanar;
|
|
1924
|
+
if (triplanar !== void 0) out.triplanar = triplanar;
|
|
1925
|
+
const triplanarScale = target?.triplanarScale ?? lop.triplanarScale;
|
|
1926
|
+
if (triplanarScale !== void 0) out.triplanarScale = triplanarScale;
|
|
1927
|
+
const triplanarSharpness = target?.triplanarSharpness ?? lop.triplanarSharpness;
|
|
1928
|
+
if (triplanarSharpness !== void 0) out.triplanarSharpness = triplanarSharpness;
|
|
1332
1929
|
return out;
|
|
1333
1930
|
}
|
|
1931
|
+
/** A transform's mean scale: the average length of its basis columns. */
|
|
1932
|
+
function matrixScale(m) {
|
|
1933
|
+
const c = (i) => Math.hypot(m[i], m[i + 1], m[i + 2]);
|
|
1934
|
+
return (c(0) + c(4) + c(8)) / 3;
|
|
1935
|
+
}
|
|
1334
1936
|
function computeContainerScissor(matrix, width, height) {
|
|
1335
1937
|
const corners = [
|
|
1336
1938
|
matrix.transformPoint(new DOMPoint(0, 0)),
|
|
@@ -1642,6 +2244,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1642
2244
|
const inheritedSeekOffset = props.inheritedSeekOffset ?? 0;
|
|
1643
2245
|
const shiftedFrame = Math.max(0, frame != null && fps != null ? frame + Math.round(inheritedSeekOffset * fps) : frame ?? 0);
|
|
1644
2246
|
const compositionFrame = props.compositionFrame ?? shiftedFrame;
|
|
2247
|
+
const historyOnly = props.motionHistoryOnly === true;
|
|
1645
2248
|
const compTex = ctx.renderer.getTemporaryTexture(nativeWidth, nativeHeight, [...props.excludeTextures || [], targetTexture]);
|
|
1646
2249
|
const compView = compTex.createView();
|
|
1647
2250
|
const composeDuration = virtualMedia?.metadata?.durationMs ?? DEFAULT_DURATION_MS;
|
|
@@ -1651,9 +2254,15 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1651
2254
|
durationSec
|
|
1652
2255
|
});
|
|
1653
2256
|
const { targetsById } = compiled;
|
|
2257
|
+
if (!historyOnly && frame != null && sceneMotionBlur(virtualMedia) && motionHistory(ctx.device, compiled.key).needsPrevious(shiftedFrame)) await renderMotionHistory(args, frame - 1);
|
|
1654
2258
|
seekTimeline(compiled, shiftedFrame, fps ?? 24);
|
|
1655
|
-
getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d)
|
|
1656
|
-
getScreenSpaceRelightPipeline(ctx.device, ctx.renderer.format ?? "rgba8unorm")
|
|
2259
|
+
const r3d = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
2260
|
+
const relightPipe = getScreenSpaceRelightPipeline(ctx.device, ctx.renderer.format ?? "rgba8unorm");
|
|
2261
|
+
if (poolEncoder.get(ctx.device) !== encoder) {
|
|
2262
|
+
poolEncoder.set(ctx.device, encoder);
|
|
2263
|
+
r3d.resetPools();
|
|
2264
|
+
relightPipe.resetPools();
|
|
2265
|
+
}
|
|
1657
2266
|
const clearColor = parseColor(vop.backgroundColor);
|
|
1658
2267
|
ctx.renderer.beginFrame(encoder, compView, clearColor, nativeWidth, nativeHeight, "clear").end();
|
|
1659
2268
|
let currentCompTex = compTex;
|
|
@@ -1724,6 +2333,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1724
2333
|
const textStyle = {
|
|
1725
2334
|
fontSize: node.fontSize ?? 48,
|
|
1726
2335
|
fontWeight: node.fontWeight,
|
|
2336
|
+
fontVariations: node.fontVariations,
|
|
1727
2337
|
fontFamily: node.fontFamily,
|
|
1728
2338
|
letterSpacing: node.letterSpacing,
|
|
1729
2339
|
lineHeight: node.lineHeight,
|
|
@@ -1787,6 +2397,11 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1787
2397
|
0
|
|
1788
2398
|
];
|
|
1789
2399
|
let dofEnabled = false;
|
|
2400
|
+
/** Shutter motion blur of the 3D scene, and what its draws looked like a frame ago. */
|
|
2401
|
+
let motionBlur = null;
|
|
2402
|
+
let history = null;
|
|
2403
|
+
/** Set when the camera draws a cube map and remaps it through its lens. */
|
|
2404
|
+
let cubeCamera = null;
|
|
1790
2405
|
const sceneLights = [];
|
|
1791
2406
|
let sceneEnvironment = null;
|
|
1792
2407
|
let sceneBloom = null;
|
|
@@ -1849,6 +2464,13 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1849
2464
|
camera.fStop = camStub?.fStop ?? camOp?.dof?.fStop ?? 2.8;
|
|
1850
2465
|
camera.maxBlurRadius = camStub?.maxBlurRadius ?? camOp?.dof?.maxBlurRadius ?? 24;
|
|
1851
2466
|
}
|
|
2467
|
+
const blur = camOp?.motionBlur;
|
|
2468
|
+
if (blur && fps) {
|
|
2469
|
+
motionBlur = blur === true ? {} : blur;
|
|
2470
|
+
history = motionHistory(ctx.device, compiled.key);
|
|
2471
|
+
}
|
|
2472
|
+
cubeCamera = resolveCubeCamera(camOp, camera, camStub?.relativitySpeed ?? camOp?.relativity?.speed ?? 0, nativeWidth, nativeHeight, ctx.device.limits.maxTextureDimension2D);
|
|
2473
|
+
if (cubeCamera && dofEnabled) throw new Error(`Camera '${camOp?.id}' is a cube camera (${camOp?.relativity ? "relativity" : camOp?.lens?.projection}) with depth of field: depth of field needs a single perspective view.`);
|
|
1852
2474
|
for (const lvm of lightVMs) {
|
|
1853
2475
|
const lop = lvm.operation;
|
|
1854
2476
|
const targetId = lop.id || lop.inputHandleId;
|
|
@@ -1863,8 +2485,23 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1863
2485
|
const lightType = target?.lightType ?? lop.lightType ?? "point";
|
|
1864
2486
|
if (lightType === "environment") {
|
|
1865
2487
|
const intensity$1 = target?.intensity ?? lop.intensity;
|
|
2488
|
+
const vfDensity = target?.volumetricFogDensity ?? lop.volumetricFogDensity;
|
|
2489
|
+
const vfAnisotropy = target?.volumetricFogAnisotropy ?? lop.volumetricFogAnisotropy;
|
|
2490
|
+
const vfNoiseStrength = target?.volumetricFogNoiseStrength ?? lop.volumetricFogNoiseStrength;
|
|
2491
|
+
const rawVf = lop.volumetricFog;
|
|
2492
|
+
const baseVf = rawVf === true ? {} : rawVf && typeof rawVf === "object" ? { ...rawVf } : void 0;
|
|
2493
|
+
const volumetricFog = baseVf ? {
|
|
2494
|
+
...baseVf,
|
|
2495
|
+
...vfDensity !== void 0 && { density: vfDensity },
|
|
2496
|
+
...vfAnisotropy !== void 0 && { anisotropy: vfAnisotropy },
|
|
2497
|
+
...vfNoiseStrength !== void 0 && { noise: {
|
|
2498
|
+
...typeof baseVf.noise === "object" ? baseVf.noise : {},
|
|
2499
|
+
strength: vfNoiseStrength
|
|
2500
|
+
} }
|
|
2501
|
+
} : void 0;
|
|
1866
2502
|
sceneEnvironment = {
|
|
1867
2503
|
preset: lop.preset,
|
|
2504
|
+
hdri: lop.hdri,
|
|
1868
2505
|
top: lop.top,
|
|
1869
2506
|
horizon: lop.horizon,
|
|
1870
2507
|
bottom: lop.bottom,
|
|
@@ -1874,6 +2511,10 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1874
2511
|
toneMapping: lop.toneMapping,
|
|
1875
2512
|
fog: lop.fog,
|
|
1876
2513
|
floor: lop.floor,
|
|
2514
|
+
outlines: lop.outlines,
|
|
2515
|
+
ssr: lop.ssr,
|
|
2516
|
+
gi: lop.gi,
|
|
2517
|
+
...volumetricFog && { volumetricFog },
|
|
1877
2518
|
...intensity$1 !== void 0 && { intensity: intensity$1 }
|
|
1878
2519
|
};
|
|
1879
2520
|
sceneBloom = lop.bloom === true ? {} : lop.bloom && typeof lop.bloom === "object" ? { ...lop.bloom } : null;
|
|
@@ -1891,6 +2532,10 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1891
2532
|
const angle = target?.angle ?? lop.angle ?? 45;
|
|
1892
2533
|
const penumbra = target?.penumbra ?? lop.penumbra ?? .2;
|
|
1893
2534
|
const decay = target?.decay ?? lop.decay ?? 1;
|
|
2535
|
+
const width = typeof (target?.width ?? lop.width) === "number" ? target?.width ?? lop.width : void 0;
|
|
2536
|
+
const height = typeof (target?.height ?? lop.height) === "number" ? target?.height ?? lop.height : void 0;
|
|
2537
|
+
const twoSided = Boolean(target?.twoSided ?? lop.twoSided);
|
|
2538
|
+
const rotation = target?.rotation ?? lop.rotation ?? 0;
|
|
1894
2539
|
sceneLights.push({
|
|
1895
2540
|
type: lightType,
|
|
1896
2541
|
color,
|
|
@@ -1905,10 +2550,15 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1905
2550
|
targetY,
|
|
1906
2551
|
targetZ
|
|
1907
2552
|
],
|
|
2553
|
+
...Array.isArray(lop.direction) && { direction: lop.direction },
|
|
1908
2554
|
radius,
|
|
1909
2555
|
angle,
|
|
1910
2556
|
penumbra,
|
|
1911
2557
|
decay,
|
|
2558
|
+
...width !== void 0 && { width },
|
|
2559
|
+
...height !== void 0 && { height },
|
|
2560
|
+
twoSided,
|
|
2561
|
+
rotation,
|
|
1912
2562
|
castShadow: Boolean(lop.castShadow),
|
|
1913
2563
|
shadowSoftness: target?.shadowSoftness ?? lop.shadowSoftness,
|
|
1914
2564
|
shadowDarkness: target?.shadowDarkness ?? lop.shadowDarkness
|
|
@@ -1942,16 +2592,79 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1942
2592
|
eye: reliefEye
|
|
1943
2593
|
} };
|
|
1944
2594
|
};
|
|
2595
|
+
/** Each queued item with its motion key: owner id and its index among the owner's items. */
|
|
2596
|
+
const motionItems = () => {
|
|
2597
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2598
|
+
return pending3DItems.map((item) => {
|
|
2599
|
+
if (item.owner === void 0) return [item, void 0];
|
|
2600
|
+
const n = seen.get(item.owner) ?? 0;
|
|
2601
|
+
seen.set(item.owner, n + 1);
|
|
2602
|
+
return [item, `${item.owner}#${n}`];
|
|
2603
|
+
});
|
|
2604
|
+
};
|
|
2605
|
+
/** Writes this frame's draws (and camera) into the motion history. */
|
|
2606
|
+
const recordMotion = (h, cam) => {
|
|
2607
|
+
const r3d$1 = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
2608
|
+
for (const [item, key] of motionItems()) {
|
|
2609
|
+
if (!key) continue;
|
|
2610
|
+
if (item.kind === "mesh") h.recordMesh(encoder, key, shiftedFrame, {
|
|
2611
|
+
modelMatrix: r3d$1.meshModelMatrix(item.opts),
|
|
2612
|
+
skinning: item.opts.skinningMatrices,
|
|
2613
|
+
windTime: item.opts.wind?.time,
|
|
2614
|
+
crowdTime: item.opts.crowd?.time
|
|
2615
|
+
}, {
|
|
2616
|
+
instanceBuffer: item.opts.instanceBuffer,
|
|
2617
|
+
vertices: item.meshBuffers && {
|
|
2618
|
+
buffer: item.meshBuffers.vertexBuffer,
|
|
2619
|
+
bytes: deformedBytes(item.mesh)
|
|
2620
|
+
}
|
|
2621
|
+
});
|
|
2622
|
+
else if (item.kind === "quad") h.recordQuad(key, shiftedFrame, r3d$1.quadModelMatrix(item.opts));
|
|
2623
|
+
else h.recordSlug(key, shiftedFrame, r3d$1.quadModelMatrix(item.opts), item.batches);
|
|
2624
|
+
}
|
|
2625
|
+
h.recordFrame(shiftedFrame, cam);
|
|
2626
|
+
};
|
|
2627
|
+
/** Draws the queued items' screen motion since the last frame, then blurs `color` by it into `into`. */
|
|
2628
|
+
const blurScene = (h, cam, color, into, blur, floor) => {
|
|
2629
|
+
const r3d$1 = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
2630
|
+
const vel = r3d$1.beginVelocityPass(encoder, nativeWidth, nativeHeight, cam, h.previousCamera(shiftedFrame) ?? cam);
|
|
2631
|
+
if (floor) r3d$1.drawFloorVelocity(vel.pass, vel.cameraBindGroup, floor);
|
|
2632
|
+
for (const [item, key] of motionItems()) if (item.kind === "mesh") {
|
|
2633
|
+
const prev = key ? h.previousMesh(key, shiftedFrame, {
|
|
2634
|
+
skinning: item.opts.skinningMatrices,
|
|
2635
|
+
instanceBuffer: item.opts.instanceBuffer,
|
|
2636
|
+
vertexBytes: item.meshBuffers && deformedBytes(item.mesh),
|
|
2637
|
+
wind: item.opts.wind,
|
|
2638
|
+
crowd: item.opts.crowd
|
|
2639
|
+
}) : void 0;
|
|
2640
|
+
r3d$1.drawMeshVelocity(vel.pass, vel.cameraBindGroup, item.meshBuffers ?? item.mesh, item.texture, item.opts, prev);
|
|
2641
|
+
} else if (item.kind === "quad") r3d$1.drawQuadVelocity(vel.pass, vel.cameraBindGroup, item.texture, item.opts, key ? h.previousQuad(key, shiftedFrame) : void 0);
|
|
2642
|
+
else r3d$1.drawSlugVelocity(vel.pass, vel.cameraBindGroup, item.batches, item.opts, item.stackBase, key ? h.previousSlug(key, shiftedFrame) : void 0);
|
|
2643
|
+
vel.pass.end();
|
|
2644
|
+
r3d$1.applyMotionBlur(encoder, color, vel.velocity, into.createView(), {
|
|
2645
|
+
shutterAngle: blur.shutter,
|
|
2646
|
+
sampleCount: blur.samples,
|
|
2647
|
+
maxBlur: blur.maxBlur
|
|
2648
|
+
});
|
|
2649
|
+
};
|
|
1945
2650
|
const flush3DPass = (curTex, curView, curExcludes) => {
|
|
1946
2651
|
if (pending3DItems.length === 0 || !camera) return {
|
|
1947
2652
|
finalTex: curTex,
|
|
1948
2653
|
finalView: curView
|
|
1949
2654
|
};
|
|
1950
|
-
const r3d = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
2655
|
+
const r3d$1 = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
1951
2656
|
for (const item of pending3DItems) {
|
|
1952
2657
|
if (item.kind !== "mesh") continue;
|
|
1953
|
-
if (item.opts.morphWeights?.length) item.meshBuffers = r3d.morphMesh(encoder, item.mesh, item.opts.morphWeights, item.opts.wireframe);
|
|
1954
|
-
if (item.opts.audioDeform) item.meshBuffers = r3d.deformMesh(encoder, item.mesh, item.opts.audioDeform, item.opts.wireframe, item.meshBuffers);
|
|
2658
|
+
if (item.opts.morphWeights?.length) item.meshBuffers = r3d$1.morphMesh(encoder, item.mesh, item.opts.morphWeights, item.opts.wireframe);
|
|
2659
|
+
if (item.opts.audioDeform) item.meshBuffers = r3d$1.deformMesh(encoder, item.mesh, item.opts.audioDeform, item.opts.wireframe, item.meshBuffers);
|
|
2660
|
+
}
|
|
2661
|
+
if (historyOnly) {
|
|
2662
|
+
if (history) recordMotion(history, camera);
|
|
2663
|
+
pending3DItems.length = 0;
|
|
2664
|
+
return {
|
|
2665
|
+
finalTex: curTex,
|
|
2666
|
+
finalView: curView
|
|
2667
|
+
};
|
|
1955
2668
|
}
|
|
1956
2669
|
const itemTextures = pendingTextures();
|
|
1957
2670
|
const scene3dTex = ctx.renderer.getTemporaryTexture(nativeWidth, nativeHeight, [
|
|
@@ -1961,17 +2674,25 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1961
2674
|
...itemTextures
|
|
1962
2675
|
]);
|
|
1963
2676
|
const scene3dView = scene3dTex.createView();
|
|
2677
|
+
const outlineSetting = sceneEnvironment?.outlines;
|
|
2678
|
+
const outlines = outlineSetting === true ? {} : outlineSetting || null;
|
|
2679
|
+
const volumetricFogEnabled = Boolean(sceneEnvironment?.volumetricFog);
|
|
2680
|
+
const screenIndirectEnabled = Boolean(sceneEnvironment?.ssr || sceneEnvironment?.gi);
|
|
2681
|
+
const geometryEnabled = dofEnabled || Boolean(outlines) || volumetricFogEnabled || screenIndirectEnabled;
|
|
1964
2682
|
let linearDepthTex;
|
|
1965
2683
|
let linearDepthView;
|
|
1966
|
-
if (
|
|
1967
|
-
linearDepthTex = r3d.getOrCreateLinearDepthTexture(nativeWidth, nativeHeight);
|
|
2684
|
+
if (geometryEnabled) {
|
|
2685
|
+
linearDepthTex = r3d$1.getOrCreateLinearDepthTexture(nativeWidth, nativeHeight);
|
|
1968
2686
|
linearDepthView = linearDepthTex.createView();
|
|
1969
2687
|
}
|
|
1970
2688
|
const shadow = [];
|
|
1971
2689
|
const shadowLights = sceneLights.filter((light) => (light.lightType ?? light.type) !== "ambient").map((light, index) => ({
|
|
1972
2690
|
light,
|
|
1973
2691
|
index
|
|
1974
|
-
})).filter(({ light }) =>
|
|
2692
|
+
})).filter(({ light }) => {
|
|
2693
|
+
const k = light.lightType ?? light.type;
|
|
2694
|
+
return light.castShadow && (k === "directional" || k === "spot" || k === "rect" || k === "point");
|
|
2695
|
+
});
|
|
1975
2696
|
if (shadowLights.length > 0) {
|
|
1976
2697
|
const casters = [];
|
|
1977
2698
|
const receivers = [];
|
|
@@ -1982,7 +2703,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1982
2703
|
buffers: item.meshBuffers,
|
|
1983
2704
|
opts: item.opts
|
|
1984
2705
|
};
|
|
1985
|
-
receivers.push(r3d.worldBounds(caster));
|
|
2706
|
+
receivers.push(r3d$1.worldBounds(caster));
|
|
1986
2707
|
if (item.opts.castShadow !== false && item.opts.material !== "unlit") casters.push(caster);
|
|
1987
2708
|
} else if (item.kind === "quad") {
|
|
1988
2709
|
const caster = {
|
|
@@ -1990,16 +2711,26 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
1990
2711
|
texture: item.texture,
|
|
1991
2712
|
opts: item.opts
|
|
1992
2713
|
};
|
|
1993
|
-
receivers.push(r3d.worldBounds(caster));
|
|
2714
|
+
receivers.push(r3d$1.worldBounds(caster));
|
|
1994
2715
|
if (item.opts.castShadow === true) casters.push(caster);
|
|
1995
2716
|
}
|
|
1996
|
-
if (casters.length > 0)
|
|
1997
|
-
const
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
})
|
|
2002
|
-
|
|
2717
|
+
if (casters.length > 0) {
|
|
2718
|
+
const totalShadowLayers = shadowLights.reduce((sum, { light }) => sum + ((light.lightType ?? light.type) === "point" ? 6 : 1), 0);
|
|
2719
|
+
const allPointShadows = shadowLights.every(({ light }) => (light.lightType ?? light.type) === "point");
|
|
2720
|
+
const resolvedShadowMapSize = shadowMapSize ?? (allPointShadows ? 1024 : 2048);
|
|
2721
|
+
let currentLayer = 0;
|
|
2722
|
+
for (const { light, index } of shadowLights) {
|
|
2723
|
+
const needed = (light.lightType ?? light.type) === "point" ? 6 : 1;
|
|
2724
|
+
const result = r3d$1.renderShadowMap(encoder, light, index, casters, receivers, {
|
|
2725
|
+
mapSize: resolvedShadowMapSize,
|
|
2726
|
+
layer: currentLayer,
|
|
2727
|
+
layerCount: totalShadowLayers
|
|
2728
|
+
});
|
|
2729
|
+
if (result) {
|
|
2730
|
+
shadow.push(result);
|
|
2731
|
+
currentLayer += result.layerCount ?? needed;
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2003
2734
|
}
|
|
2004
2735
|
}
|
|
2005
2736
|
const isGlass = (item) => item.kind === "mesh" && (item.opts.material === "glass" || item.opts.material === "acrylic" || item.opts.material === "frosted");
|
|
@@ -2009,7 +2740,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2009
2740
|
const forward = Vector3Math.subtract(camera.target, camera.eye);
|
|
2010
2741
|
for (const item of pending3DItems) if (isGlass(item)) glass.push(item);
|
|
2011
2742
|
else if (item.kind === "mesh" && item.opts.transparent) {
|
|
2012
|
-
const bounds = r3d.worldBounds({
|
|
2743
|
+
const bounds = r3d$1.worldBounds({
|
|
2013
2744
|
kind: "mesh",
|
|
2014
2745
|
mesh: item.mesh,
|
|
2015
2746
|
opts: item.opts
|
|
@@ -2043,7 +2774,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2043
2774
|
for (let j = i; j < end; j++) {
|
|
2044
2775
|
const item = opaque[j];
|
|
2045
2776
|
if (item.kind !== "mesh") throw new Error("Invalid mesh batch");
|
|
2046
|
-
const matrix = r3d.meshModelMatrix(item.opts);
|
|
2777
|
+
const matrix = r3d$1.meshModelMatrix(item.opts);
|
|
2047
2778
|
data.set(matrix, (j - i) * 32);
|
|
2048
2779
|
data.set(item.opts.normalMatrix ?? Light3D.computeNormalMatrix(matrix), (j - i) * 32 + 16);
|
|
2049
2780
|
}
|
|
@@ -2053,7 +2784,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2053
2784
|
...first.opts,
|
|
2054
2785
|
modelMatrix: Matrix4Math.identity(),
|
|
2055
2786
|
normalMatrix: Matrix4Math.identity(),
|
|
2056
|
-
instanceBuffer: r3d.uploadInstanceData(data),
|
|
2787
|
+
instanceBuffer: r3d$1.uploadInstanceData(data),
|
|
2057
2788
|
instanceCount: end - i,
|
|
2058
2789
|
matrixInstances: true
|
|
2059
2790
|
}
|
|
@@ -2066,65 +2797,192 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2066
2797
|
...transparent.map(({ item }) => item),
|
|
2067
2798
|
...glass
|
|
2068
2799
|
];
|
|
2800
|
+
if (cubeCamera) {
|
|
2801
|
+
const single = [screenIndirectEnabled && "screen-space reflections and GI (ssr, gi)", motionBlur && "motion blur"].filter(Boolean);
|
|
2802
|
+
if (single.length) throw new Error(`A cube camera (${cubeCamera.remap.projection ?? "lens"}) cannot draw ${single.join(" or ")}: they need a single perspective view.`);
|
|
2803
|
+
}
|
|
2069
2804
|
const floorSpec = sceneEnvironment?.floor;
|
|
2070
|
-
|
|
2071
|
-
|
|
2805
|
+
const sceneShadow = shadow.length ? shadow : null;
|
|
2806
|
+
/** The floor's mirror image from `view`, blurred by its roughness, when the eye is above it. */
|
|
2807
|
+
const floorReflection = (view, width, height) => {
|
|
2808
|
+
if (!floorSpec || typeof floorSpec.y !== "number" || view.eye[1] >= floorSpec.y) return null;
|
|
2072
2809
|
const reflectedCamera = {
|
|
2073
|
-
...
|
|
2810
|
+
...view,
|
|
2074
2811
|
eye: [
|
|
2075
|
-
|
|
2076
|
-
2 * floorSpec.y -
|
|
2077
|
-
|
|
2812
|
+
view.eye[0],
|
|
2813
|
+
2 * floorSpec.y - view.eye[1],
|
|
2814
|
+
view.eye[2]
|
|
2078
2815
|
],
|
|
2079
2816
|
target: [
|
|
2080
|
-
|
|
2081
|
-
2 * floorSpec.y -
|
|
2082
|
-
|
|
2817
|
+
view.target[0],
|
|
2818
|
+
2 * floorSpec.y - view.target[1],
|
|
2819
|
+
view.target[2]
|
|
2083
2820
|
],
|
|
2084
2821
|
up: [
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2822
|
+
view.up[0],
|
|
2823
|
+
view.up[1],
|
|
2824
|
+
view.up[2]
|
|
2088
2825
|
]
|
|
2089
2826
|
};
|
|
2090
|
-
const { pass: reflPass, cameraBindGroup: reflCamBind, lightsBindGroup: reflLightsBind, reflectionTexture: reflTex } = r3d.beginReflectionPass(encoder,
|
|
2827
|
+
const { pass: reflPass, cameraBindGroup: reflCamBind, lightsBindGroup: reflLightsBind, reflectionTexture: reflTex } = r3d$1.beginReflectionPass(encoder, width, height, reflectedCamera, sceneLights, {
|
|
2091
2828
|
environment: sceneEnvironment,
|
|
2092
2829
|
shadow: null
|
|
2093
2830
|
});
|
|
2094
|
-
for (const item of ordered) if (item.kind === "quad") r3d.drawTextureQuad(reflPass, reflCamBind, reflLightsBind, item.texture, item.opts, false);
|
|
2095
|
-
else if (item.kind === "slug") r3d.drawSlugText(reflPass, reflCamBind, reflLightsBind, item.batches, item.opts, item.stackBase, false);
|
|
2096
|
-
else if (item.kind === "mesh") r3d.drawMesh3D(reflPass, reflCamBind, reflLightsBind, item.meshBuffers ?? item.mesh, item.texture, item.opts, false);
|
|
2831
|
+
for (const item of ordered) if (item.kind === "quad") r3d$1.drawTextureQuad(reflPass, reflCamBind, reflLightsBind, item.texture, item.opts, false);
|
|
2832
|
+
else if (item.kind === "slug") r3d$1.drawSlugText(reflPass, reflCamBind, reflLightsBind, item.batches, item.opts, item.stackBase, false);
|
|
2833
|
+
else if (item.kind === "mesh") r3d$1.drawMesh3D(reflPass, reflCamBind, reflLightsBind, item.meshBuffers ?? item.mesh, item.texture, item.opts, false);
|
|
2097
2834
|
reflPass.end();
|
|
2098
|
-
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2835
|
+
return r3d$1.blurReflection(encoder, reflTex, floorSpec.roughness ?? .35);
|
|
2836
|
+
};
|
|
2837
|
+
/**
|
|
2838
|
+
* One forward pass over the batch: floor, then the sorted draws.
|
|
2839
|
+
* `glassBackdrop` is the 2D picture glass refracts: undefined draws
|
|
2840
|
+
* glass over the 3D scene alone (a cube face), null leaves the glass
|
|
2841
|
+
* out (the pre-pass that makes that picture).
|
|
2842
|
+
*/
|
|
2843
|
+
const drawView = (target, screenIndirect, writeHdr, glassBackdrop) => {
|
|
2844
|
+
const begun = r3d$1.beginPass(encoder, target.color, target.width, target.height, target.view, "clear", {
|
|
2845
|
+
r: 0,
|
|
2846
|
+
g: 0,
|
|
2847
|
+
b: 0,
|
|
2848
|
+
a: 0
|
|
2849
|
+
}, target.geometry, sceneLights, {
|
|
2850
|
+
environment: sceneEnvironment,
|
|
2851
|
+
shadow: sceneShadow,
|
|
2852
|
+
screenIndirect
|
|
2853
|
+
}, writeHdr, target.hdr);
|
|
2854
|
+
const { pass: pass$1, cameraBindGroup, lightsBindGroup } = begun;
|
|
2855
|
+
if (floorSpec && target.reflection) r3d$1.drawFloor(pass$1, cameraBindGroup, lightsBindGroup, target.reflection, floorSpec, geometryEnabled, writeHdr);
|
|
2856
|
+
for (const item of ordered) {
|
|
2857
|
+
if (glassBackdrop === null && isGlass(item)) continue;
|
|
2858
|
+
if (item.kind === "quad") r3d$1.drawTextureQuad(pass$1, cameraBindGroup, lightsBindGroup, item.texture, item.opts, geometryEnabled);
|
|
2859
|
+
else if (item.kind === "slug") r3d$1.drawSlugText(pass$1, cameraBindGroup, lightsBindGroup, item.batches, item.opts, item.stackBase, geometryEnabled);
|
|
2860
|
+
else if (item.kind === "mesh") r3d$1.drawMesh3D(pass$1, cameraBindGroup, lightsBindGroup, item.meshBuffers ?? item.mesh, item.texture, isGlass(item) ? {
|
|
2861
|
+
...item.opts,
|
|
2862
|
+
backdrop: glassBackdrop ?? void 0
|
|
2863
|
+
} : item.opts, geometryEnabled);
|
|
2864
|
+
}
|
|
2865
|
+
pass$1.end();
|
|
2866
|
+
return begun;
|
|
2867
|
+
};
|
|
2868
|
+
const sceneSeconds = shiftedFrame / Math.max(1, fps ?? 24);
|
|
2117
2869
|
let final3dTex = scene3dTex;
|
|
2118
|
-
|
|
2870
|
+
let mainReflection = null;
|
|
2871
|
+
let mainPass = null;
|
|
2872
|
+
if (cubeCamera) {
|
|
2873
|
+
const size = cubeCamera.faceSize;
|
|
2874
|
+
const cube = r3d$1.getOrCreateCubeTexture(size, false);
|
|
2875
|
+
const hdrCube = sceneBloom ? r3d$1.getOrCreateCubeTexture(size, true) : null;
|
|
2876
|
+
const faceOutlines = outlines && {
|
|
2877
|
+
...outlines,
|
|
2878
|
+
referenceHeight: (outlines.referenceHeight ?? 1080) * 2 * cubeCamera.centerDensity / nativeHeight
|
|
2879
|
+
};
|
|
2880
|
+
const post = Boolean(faceOutlines) || volumetricFogEnabled;
|
|
2881
|
+
const faceExcludes = [
|
|
2882
|
+
curTex,
|
|
2883
|
+
targetTexture,
|
|
2884
|
+
scene3dTex,
|
|
2885
|
+
...curExcludes,
|
|
2886
|
+
...itemTextures
|
|
2887
|
+
];
|
|
2888
|
+
const faceTex = post ? ctx.renderer.getTemporaryTexture(size, size, faceExcludes) : null;
|
|
2889
|
+
const fogTex = faceOutlines && volumetricFogEnabled ? ctx.renderer.getTemporaryTexture(size, size, [...faceExcludes, ...faceTex ? [faceTex] : []]) : null;
|
|
2890
|
+
const faceGeometry = geometryEnabled ? r3d$1.getOrCreateLinearDepthTexture(size, size) : null;
|
|
2891
|
+
cubeFaceCameras(camera.eye, camera.near, camera.far).forEach((face, i) => {
|
|
2892
|
+
const faceView = r3d$1.cubeFaceView(cube, i);
|
|
2893
|
+
const { cameraBindGroup, lightsBindGroup } = drawView({
|
|
2894
|
+
view: face,
|
|
2895
|
+
width: size,
|
|
2896
|
+
height: size,
|
|
2897
|
+
color: faceTex ? faceTex.createView() : faceView,
|
|
2898
|
+
geometry: faceGeometry?.createView(),
|
|
2899
|
+
hdr: hdrCube ? r3d$1.cubeFaceView(hdrCube, i) : void 0,
|
|
2900
|
+
reflection: floorReflection(face, size, size)
|
|
2901
|
+
}, void 0, Boolean(sceneBloom), void 0);
|
|
2902
|
+
if (!faceTex || !faceGeometry) return;
|
|
2903
|
+
if (volumetricFogEnabled) r3d$1.resolveGeometry(encoder, faceGeometry);
|
|
2904
|
+
let source = faceTex;
|
|
2905
|
+
if (faceOutlines) {
|
|
2906
|
+
const inked = fogTex ?? null;
|
|
2907
|
+
r3d$1.applyOutlines(encoder, faceTex, faceGeometry, inked ? inked.createView() : faceView, face, faceOutlines, sceneEnvironment?.fog);
|
|
2908
|
+
if (!inked) return;
|
|
2909
|
+
source = inked;
|
|
2910
|
+
}
|
|
2911
|
+
if (volumetricFogEnabled && sceneEnvironment) r3d$1.applyVolumetricFog(encoder, source, faceGeometry, faceView, cameraBindGroup, lightsBindGroup, sceneEnvironment, sceneSeconds, shiftedFrame);
|
|
2912
|
+
});
|
|
2913
|
+
r3d$1.remapLens(encoder, cube, hdrCube, scene3dView, nativeWidth, nativeHeight, cubeCamera.remap);
|
|
2914
|
+
} else {
|
|
2915
|
+
mainReflection = floorReflection(camera, nativeWidth, nativeHeight);
|
|
2916
|
+
const target = {
|
|
2917
|
+
view: camera,
|
|
2918
|
+
width: nativeWidth,
|
|
2919
|
+
height: nativeHeight,
|
|
2920
|
+
color: scene3dView,
|
|
2921
|
+
geometry: linearDepthView,
|
|
2922
|
+
reflection: mainReflection
|
|
2923
|
+
};
|
|
2924
|
+
if (screenIndirectEnabled && sceneEnvironment) {
|
|
2925
|
+
const { cameraBuffer: radianceCamera } = drawView(target, "radiance", true, curTex);
|
|
2926
|
+
r3d$1.traceScreenIndirect(encoder, radianceCamera, sceneEnvironment);
|
|
2927
|
+
}
|
|
2928
|
+
let glassBackdrop = curTex;
|
|
2929
|
+
if (glass.length) {
|
|
2930
|
+
drawView(target, screenIndirectEnabled ? "apply" : void 0, false, null);
|
|
2931
|
+
glassBackdrop = ctx.renderer.composite(encoder, curTex, scene3dTex, "normal", [
|
|
2932
|
+
targetTexture,
|
|
2933
|
+
scene3dTex,
|
|
2934
|
+
...curExcludes
|
|
2935
|
+
]);
|
|
2936
|
+
}
|
|
2937
|
+
mainPass = drawView(target, screenIndirectEnabled ? "apply" : void 0, Boolean(sceneBloom), glassBackdrop);
|
|
2938
|
+
}
|
|
2939
|
+
if (mainPass && outlines && linearDepthTex) {
|
|
2940
|
+
if (dofEnabled || volumetricFogEnabled) r3d$1.resolveGeometry(encoder, linearDepthTex);
|
|
2941
|
+
const outlinedTex = ctx.renderer.getTemporaryTexture(nativeWidth, nativeHeight, [
|
|
2942
|
+
curTex,
|
|
2943
|
+
targetTexture,
|
|
2944
|
+
scene3dTex,
|
|
2945
|
+
linearDepthTex,
|
|
2946
|
+
...curExcludes
|
|
2947
|
+
]);
|
|
2948
|
+
r3d$1.applyOutlines(encoder, scene3dTex, linearDepthTex, outlinedTex.createView(), camera, outlines, sceneEnvironment?.fog);
|
|
2949
|
+
final3dTex = outlinedTex;
|
|
2950
|
+
}
|
|
2951
|
+
if (mainPass && volumetricFogEnabled && sceneEnvironment && linearDepthTex) {
|
|
2952
|
+
const vfogTex = ctx.renderer.getTemporaryTexture(nativeWidth, nativeHeight, [
|
|
2953
|
+
curTex,
|
|
2954
|
+
targetTexture,
|
|
2955
|
+
scene3dTex,
|
|
2956
|
+
final3dTex,
|
|
2957
|
+
linearDepthTex,
|
|
2958
|
+
...curExcludes
|
|
2959
|
+
]);
|
|
2960
|
+
r3d$1.applyVolumetricFog(encoder, final3dTex, linearDepthTex, vfogTex.createView(), mainPass.cameraBindGroup, mainPass.lightsBindGroup, sceneEnvironment, sceneSeconds, shiftedFrame);
|
|
2961
|
+
final3dTex = vfogTex;
|
|
2962
|
+
}
|
|
2963
|
+
if (mainPass && dofEnabled && linearDepthTex) {
|
|
2119
2964
|
const dofResultTex = ctx.renderer.getTemporaryTexture(nativeWidth, nativeHeight, [
|
|
2120
2965
|
curTex,
|
|
2121
2966
|
targetTexture,
|
|
2122
2967
|
scene3dTex,
|
|
2968
|
+
final3dTex,
|
|
2123
2969
|
...curExcludes
|
|
2124
2970
|
]);
|
|
2125
|
-
r3d.applyDepthOfField(encoder,
|
|
2971
|
+
r3d$1.applyDepthOfField(encoder, final3dTex, linearDepthTex, dofResultTex.createView(), mainPass.cameraBuffer);
|
|
2126
2972
|
final3dTex = dofResultTex;
|
|
2127
2973
|
}
|
|
2974
|
+
if (motionBlur && history) {
|
|
2975
|
+
const blurredTex = ctx.renderer.getTemporaryTexture(nativeWidth, nativeHeight, [
|
|
2976
|
+
curTex,
|
|
2977
|
+
targetTexture,
|
|
2978
|
+
scene3dTex,
|
|
2979
|
+
final3dTex,
|
|
2980
|
+
...curExcludes
|
|
2981
|
+
]);
|
|
2982
|
+
blurScene(history, camera, final3dTex, blurredTex, motionBlur, floorSpec && mainReflection ? floorSpec : void 0);
|
|
2983
|
+
final3dTex = blurredTex;
|
|
2984
|
+
}
|
|
2985
|
+
if (history) recordMotion(history, camera);
|
|
2128
2986
|
if (sceneBloom) {
|
|
2129
2987
|
const bloomTex = ctx.renderer.getTemporaryTexture(nativeWidth, nativeHeight, [
|
|
2130
2988
|
curTex,
|
|
@@ -2133,7 +2991,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2133
2991
|
scene3dTex,
|
|
2134
2992
|
...curExcludes
|
|
2135
2993
|
]);
|
|
2136
|
-
r3d.applyBloom(encoder, final3dTex, bloomTex, sceneBloom, r3d.hdrSource());
|
|
2994
|
+
r3d$1.applyBloom(encoder, final3dTex, bloomTex, sceneBloom, r3d$1.hdrSource());
|
|
2137
2995
|
final3dTex = bloomTex;
|
|
2138
2996
|
}
|
|
2139
2997
|
const nextTex = ctx.renderer.composite(encoder, curTex, final3dTex, "normal", [targetTexture, ...curExcludes]);
|
|
@@ -2185,15 +3043,17 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2185
3043
|
let activeExcludes = excludes;
|
|
2186
3044
|
const mattesByOwner = /* @__PURE__ */ new Map();
|
|
2187
3045
|
const reliefsByOwner = /* @__PURE__ */ new Map();
|
|
3046
|
+
const texturesByOwner = /* @__PURE__ */ new Map();
|
|
2188
3047
|
for (const vm of vms) {
|
|
2189
3048
|
const op$1 = vm.operation;
|
|
2190
3049
|
if (op$1?.matteOf) mattesByOwner.set(op$1.matteOf, vm);
|
|
2191
3050
|
if (op$1?.reliefOf) reliefsByOwner.set(op$1.reliefOf, vm);
|
|
3051
|
+
if (op$1?.textureOf) texturesByOwner.set(op$1.textureOf, vm);
|
|
2192
3052
|
}
|
|
2193
3053
|
for (const child of sorted) {
|
|
2194
3054
|
const lop = child.operation;
|
|
2195
3055
|
if (lop.kind === "camera" || lop.kind === "light") continue;
|
|
2196
|
-
if (lop.matteOf || lop.reliefOf) continue;
|
|
3056
|
+
if (lop.matteOf || lop.reliefOf || lop.textureOf) continue;
|
|
2197
3057
|
const targetId = lop.id || lop.inputHandleId;
|
|
2198
3058
|
const target = targetId ? targetsById[targetId] : void 0;
|
|
2199
3059
|
const isChild3D = Boolean(target?.is3D ?? lop.is3D) || Boolean(camera && ((target?.z ?? lop.z ?? 0) !== 0 || lop.is3D)) || Boolean(parent3DMatrix);
|
|
@@ -2252,10 +3112,37 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2252
3112
|
amount: lop.reliefAmount ?? 0
|
|
2253
3113
|
});
|
|
2254
3114
|
}
|
|
3115
|
+
const textureVM = lop.textureLayerId ? texturesByOwner.get(lop.id) : void 0;
|
|
3116
|
+
let wrapTexture;
|
|
3117
|
+
if (textureVM) {
|
|
3118
|
+
const texture = await isolate(textureVM, nodeIndex);
|
|
3119
|
+
activeExcludes = [...activeExcludes, texture];
|
|
3120
|
+
nodeIndex += 1;
|
|
3121
|
+
const r = rects[lop.textureLayerId];
|
|
3122
|
+
const uvRect = r ? [
|
|
3123
|
+
r.x / targetW,
|
|
3124
|
+
r.y / targetH,
|
|
3125
|
+
r.width / targetW,
|
|
3126
|
+
r.height / targetH
|
|
3127
|
+
] : [
|
|
3128
|
+
0,
|
|
3129
|
+
0,
|
|
3130
|
+
1,
|
|
3131
|
+
1
|
|
3132
|
+
];
|
|
3133
|
+
const from = pending3DItems.length;
|
|
3134
|
+
wrapTexture = () => {
|
|
3135
|
+
for (const item of pending3DItems.slice(from)) {
|
|
3136
|
+
if (item.kind !== "mesh") continue;
|
|
3137
|
+
item.texture = texture;
|
|
3138
|
+
item.opts.uvRect = uvRect;
|
|
3139
|
+
}
|
|
3140
|
+
};
|
|
3141
|
+
}
|
|
2255
3142
|
const matteVM = lop.matteId ? mattesByOwner.get(lop.id) : void 0;
|
|
2256
3143
|
if (matteVM) {
|
|
2257
3144
|
const mode = matteVM.operation.matteMode ?? "alpha";
|
|
2258
|
-
const blend = mode === "luma" ? "luma-in" : mode === "luma-inverted" ? "luma-out" : mode === "alpha-inverted" ? "destination-out" : "destination-in";
|
|
3145
|
+
const blend$1 = mode === "luma" ? "luma-in" : mode === "luma-inverted" ? "luma-out" : mode === "alpha-inverted" ? "destination-out" : "destination-in";
|
|
2259
3146
|
if (isChild3D) {
|
|
2260
3147
|
let coverage = await isolate(matteVM, nodeIndex);
|
|
2261
3148
|
activeExcludes = [...activeExcludes, coverage];
|
|
@@ -2273,7 +3160,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2273
3160
|
b: 1,
|
|
2274
3161
|
a: 1
|
|
2275
3162
|
}, targetW, targetH, "clear").end();
|
|
2276
|
-
coverage = ctx.renderer.composite(encoder, white, coverage, blend, [
|
|
3163
|
+
coverage = ctx.renderer.composite(encoder, white, coverage, blend$1, [
|
|
2277
3164
|
targetTexture,
|
|
2278
3165
|
activeTex,
|
|
2279
3166
|
...activeExcludes,
|
|
@@ -2285,6 +3172,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2285
3172
|
const before = pending3DItems.length;
|
|
2286
3173
|
const res$1 = await renderLayerVM(child, nodeIndex, activeTex, activeView, activeExcludes, accumulatedOpacity, parentMatrix, parentRect, targetW, targetH, parent3DMatrix, isRootScene);
|
|
2287
3174
|
for (const item of pending3DItems.slice(before)) item.opts.matte = coverage;
|
|
3175
|
+
wrapTexture?.();
|
|
2288
3176
|
if (res$1) {
|
|
2289
3177
|
if (res$1.finalTex !== activeTex) activeExcludes = [...activeExcludes, res$1.finalTex];
|
|
2290
3178
|
activeTex = res$1.finalTex;
|
|
@@ -2296,7 +3184,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2296
3184
|
activeExcludes = [...activeExcludes, contentTex];
|
|
2297
3185
|
nodeIndex += 1;
|
|
2298
3186
|
const matteTex = await isolate(matteVM, nodeIndex);
|
|
2299
|
-
const masked = ctx.renderer.composite(encoder, contentTex, matteTex, blend, [
|
|
3187
|
+
const masked = ctx.renderer.composite(encoder, contentTex, matteTex, blend$1, [
|
|
2300
3188
|
targetTexture,
|
|
2301
3189
|
activeTex,
|
|
2302
3190
|
...activeExcludes,
|
|
@@ -2313,6 +3201,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2313
3201
|
continue;
|
|
2314
3202
|
}
|
|
2315
3203
|
const res = await renderLayerVM(child, nodeIndex, activeTex, activeView, activeExcludes, accumulatedOpacity, parentMatrix, parentRect, targetW, targetH, parent3DMatrix, isRootScene);
|
|
3204
|
+
wrapTexture?.();
|
|
2316
3205
|
if (res) {
|
|
2317
3206
|
if (res.finalTex !== activeTex) activeExcludes = [...activeExcludes, res.finalTex];
|
|
2318
3207
|
activeTex = res.finalTex;
|
|
@@ -2345,8 +3234,10 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2345
3234
|
if (shiftedFrame < startFrame) return;
|
|
2346
3235
|
if (durationFrames !== void 0 && shiftedFrame >= startFrame + durationFrames) return;
|
|
2347
3236
|
}
|
|
3237
|
+
const isTrue3D = Boolean(target?.is3D ?? lop.is3D) || Boolean(camera && ((target?.z ?? lop.z ?? 0) !== 0 || lop.is3D));
|
|
3238
|
+
if (historyOnly && !isContainer && kind !== "model3d" && !isTrue3D && !has3DTransform(target, lop)) return;
|
|
2348
3239
|
if (kind === "model3d") {
|
|
2349
|
-
const r3d = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
3240
|
+
const r3d$1 = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
2350
3241
|
let modelSrc = lop.modelData ?? lop.src;
|
|
2351
3242
|
if (!modelSrc && lop.text3dOptions) {
|
|
2352
3243
|
const tOpts = lop.text3dOptions;
|
|
@@ -2366,13 +3257,14 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2366
3257
|
if (!modelSrc) return;
|
|
2367
3258
|
let model;
|
|
2368
3259
|
try {
|
|
2369
|
-
model = typeof modelSrc === "object" && modelSrc !== null && "meshes" in modelSrc ? modelSrc : await r3d.loadModelAsync(modelSrc, lop.modelFormat ?? "auto", {
|
|
3260
|
+
model = typeof modelSrc === "object" && modelSrc !== null && "meshes" in modelSrc ? modelSrc : await r3d$1.loadModelAsync(modelSrc, lop.modelFormat ?? "auto", {
|
|
2370
3261
|
center: lop.center,
|
|
2371
3262
|
normalizeSize: lop.normalizeSize
|
|
2372
3263
|
});
|
|
2373
3264
|
} catch (err) {
|
|
2374
3265
|
throw new Error(`Failed to load 3D model ${lop.id ?? "(unnamed)"}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
2375
3266
|
}
|
|
3267
|
+
if (model && lop.fracture3d) model = fracturedModel(model, lop.fracture3d);
|
|
2376
3268
|
if (!model || model.meshes.length === 0) return;
|
|
2377
3269
|
const baseX$1 = lop.x ?? 0;
|
|
2378
3270
|
const baseY$1 = lop.y ?? 0;
|
|
@@ -2428,6 +3320,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2428
3320
|
const instOpt = lop.instances3d;
|
|
2429
3321
|
const rawMeshes = Array.isArray(instOpt.mesh) ? instOpt.mesh : instOpt.mesh ? [instOpt.mesh] : lop.modelData ? [lop.modelData] : lop.primitive3d ? [getPrimitiveGeometry(lop.primitive3d)] : [];
|
|
2430
3322
|
const variants = [];
|
|
3323
|
+
const variantPres = [];
|
|
2431
3324
|
for (const m of rawMeshes) {
|
|
2432
3325
|
let vModel;
|
|
2433
3326
|
if (typeof m === "object" && m !== null) {
|
|
@@ -2435,25 +3328,56 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2435
3328
|
else if (m.modelData && "meshes" in m.modelData) vModel = m.modelData;
|
|
2436
3329
|
else if (m.primitive3d) vModel = getPrimitiveGeometry(m.primitive3d);
|
|
2437
3330
|
else if (m.src) try {
|
|
2438
|
-
vModel = r3d.loadModel(m.src, m.modelFormat ?? "auto", {
|
|
3331
|
+
vModel = r3d$1.loadModel(m.src, m.modelFormat ?? "auto", {
|
|
2439
3332
|
center: m.center,
|
|
2440
3333
|
normalizeSize: m.normalizeSize
|
|
2441
3334
|
});
|
|
2442
3335
|
} catch {}
|
|
2443
3336
|
}
|
|
2444
|
-
if (vModel && vModel.meshes && vModel.meshes.length > 0)
|
|
3337
|
+
if (vModel && vModel.meshes && vModel.meshes.length > 0) {
|
|
3338
|
+
variants.push(vModel);
|
|
3339
|
+
const isNode = !("meshes" in m);
|
|
3340
|
+
variantPres.push(isNode ? {
|
|
3341
|
+
q: quatFromEulerAngles(m.rotateX ?? 0, m.rotateY ?? 0, m.rotateZ ?? 0),
|
|
3342
|
+
s: m.scale ?? 1
|
|
3343
|
+
} : NO_PRE);
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
if (variants.length === 0 && model) {
|
|
3347
|
+
variants.push(model);
|
|
3348
|
+
variantPres.push(NO_PRE);
|
|
3349
|
+
}
|
|
3350
|
+
if (lop.scatter3d && variants.length > 0) {
|
|
3351
|
+
const scatter = lop.scatter3d;
|
|
3352
|
+
const surface = await surfaceModel(scatter.surface, (src, n) => r3d$1.loadModelAsync(src, n.modelFormat ?? "auto", {
|
|
3353
|
+
center: n.center,
|
|
3354
|
+
normalizeSize: n.normalizeSize
|
|
3355
|
+
}));
|
|
3356
|
+
instOpt.transforms = surface ? scatterTransforms(scatter, surface, variants.map((v, k) => variantBottom(v, variantPres[k]))) : [];
|
|
3357
|
+
instOpt.count = instOpt.transforms.length;
|
|
2445
3358
|
}
|
|
2446
|
-
if (variants.length === 0 && model) variants.push(model);
|
|
2447
3359
|
if (variants.length > 0) {
|
|
2448
3360
|
const count = instOpt.bodies && Array.isArray(instOpt.bodies) && instOpt.bodies.length > 0 ? instOpt.bodies.length : instOpt.count ?? (Array.isArray(instOpt.transforms) ? instOpt.transforms.length : 0);
|
|
2449
3361
|
if (count > 0) {
|
|
2450
3362
|
const numVariants = variants.length;
|
|
2451
3363
|
const bucketCounts = new Uint32Array(numVariants);
|
|
2452
3364
|
for (let i$1 = 0; i$1 < count; i$1++) bucketCounts[i$1 % numVariants]++;
|
|
3365
|
+
const crowdCfg = lop.crowd;
|
|
3366
|
+
const crowdBakes = variants.map((v) => crowdCfg ? crowdBake(v, crowdCfg) : void 0);
|
|
3367
|
+
const strides = crowdBakes.map((b) => b ? 32 : 16);
|
|
3368
|
+
const crowdOpts = (bake, mesh) => {
|
|
3369
|
+
const baked = bake?.meshes.get(mesh);
|
|
3370
|
+
if (!bake || !baked) return void 0;
|
|
3371
|
+
return {
|
|
3372
|
+
palette: paletteBuffer(ctx.device, baked.palette),
|
|
3373
|
+
jointCount: baked.jointCount,
|
|
3374
|
+
time: (shiftedFrame ?? 0) / (fps || 30)
|
|
3375
|
+
};
|
|
3376
|
+
};
|
|
2453
3377
|
const bucketItems = [];
|
|
2454
3378
|
const bucketBounds = [];
|
|
2455
3379
|
for (let k = 0; k < numVariants; k++) {
|
|
2456
|
-
bucketItems.push(new Float32Array(bucketCounts[k] *
|
|
3380
|
+
bucketItems.push(new Float32Array(bucketCounts[k] * strides[k]));
|
|
2457
3381
|
bucketBounds.push({
|
|
2458
3382
|
min: [
|
|
2459
3383
|
Infinity,
|
|
@@ -2482,7 +3406,8 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2482
3406
|
const cursor = bucketCursors[k];
|
|
2483
3407
|
const bData = bucketItems[k];
|
|
2484
3408
|
const bBox = bucketBounds[k];
|
|
2485
|
-
const off = cursor *
|
|
3409
|
+
const off = cursor * strides[k];
|
|
3410
|
+
let ianim = {};
|
|
2486
3411
|
let ix = 0;
|
|
2487
3412
|
let iy = 0;
|
|
2488
3413
|
let iz = 0;
|
|
@@ -2539,6 +3464,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2539
3464
|
} else if (typeof instOpt.instanceAt === "function") {
|
|
2540
3465
|
const t = instOpt.instanceAt(i$1, shiftedFrame ?? 0, fps || 30);
|
|
2541
3466
|
if (!t) continue;
|
|
3467
|
+
ianim = t;
|
|
2542
3468
|
ix = t.x ?? 0;
|
|
2543
3469
|
iy = t.y ?? 0;
|
|
2544
3470
|
iz = t.z ?? 0;
|
|
@@ -2585,6 +3511,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2585
3511
|
}
|
|
2586
3512
|
} else if (Array.isArray(instOpt.transforms) && instOpt.transforms[i$1]) {
|
|
2587
3513
|
const t = instOpt.transforms[i$1];
|
|
3514
|
+
ianim = t;
|
|
2588
3515
|
ix = t.x ?? 0;
|
|
2589
3516
|
iy = t.y ?? 0;
|
|
2590
3517
|
iz = t.z ?? 0;
|
|
@@ -2631,6 +3558,16 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2631
3558
|
}
|
|
2632
3559
|
} else continue;
|
|
2633
3560
|
bucketCursors[k]++;
|
|
3561
|
+
const pre = variantPres[k];
|
|
3562
|
+
if (pre !== NO_PRE) {
|
|
3563
|
+
[iqx, iqy, iqz, iqw] = composeQuat([
|
|
3564
|
+
iqx,
|
|
3565
|
+
iqy,
|
|
3566
|
+
iqz,
|
|
3567
|
+
iqw
|
|
3568
|
+
], pre.q);
|
|
3569
|
+
iscale *= pre.s;
|
|
3570
|
+
}
|
|
2634
3571
|
bData[off + 0] = ix;
|
|
2635
3572
|
bData[off + 1] = iy;
|
|
2636
3573
|
bData[off + 2] = iz;
|
|
@@ -2647,7 +3584,10 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2647
3584
|
bData[off + 13] = ieg;
|
|
2648
3585
|
bData[off + 14] = ieb;
|
|
2649
3586
|
bData[off + 15] = iew;
|
|
2650
|
-
const
|
|
3587
|
+
const bake = crowdBakes[k];
|
|
3588
|
+
if (bake && crowdCfg) bData.set(crowdRecord(bake, crowdCfg, i$1, ianim), off + 16);
|
|
3589
|
+
const vb = variants[k].bounds;
|
|
3590
|
+
const rad = (vb ? vb.boundingSphereRadius + Math.hypot(...vb.center) : 50) * iscale;
|
|
2651
3591
|
bBox.min[0] = Math.min(bBox.min[0], ix - rad);
|
|
2652
3592
|
bBox.min[1] = Math.min(bBox.min[1], iy - rad);
|
|
2653
3593
|
bBox.min[2] = Math.min(bBox.min[2], iz - rad);
|
|
@@ -2659,15 +3599,26 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2659
3599
|
const bCount = bucketCursors[k];
|
|
2660
3600
|
if (bCount === 0) continue;
|
|
2661
3601
|
const v = variants[k];
|
|
2662
|
-
const activeSlice = bCount === bucketCounts[k] ? bucketItems[k] : bucketItems[k].subarray(0, bCount *
|
|
2663
|
-
const instanceBuffer = r3d.uploadInstanceData(activeSlice);
|
|
3602
|
+
const activeSlice = bCount === bucketCounts[k] ? bucketItems[k] : bucketItems[k].subarray(0, bCount * strides[k]);
|
|
3603
|
+
const instanceBuffer = r3d$1.uploadInstanceData(activeSlice);
|
|
2664
3604
|
const bounds = Number.isFinite(bucketBounds[k].min[0]) ? bucketBounds[k] : void 0;
|
|
2665
3605
|
for (const mesh of v.meshes) {
|
|
2666
3606
|
const mat = mesh.materialName ? v.materials[mesh.materialName] : void 0;
|
|
3607
|
+
const diffuse = mat?.diffuseColor ?? [
|
|
3608
|
+
1,
|
|
3609
|
+
1,
|
|
3610
|
+
1,
|
|
3611
|
+
1
|
|
3612
|
+
];
|
|
2667
3613
|
const meshOpts = {
|
|
2668
3614
|
modelMatrix: finalModelMatrix,
|
|
2669
3615
|
opacity: modelOpacity * (mat?.opacity ?? 1),
|
|
2670
|
-
colorTint
|
|
3616
|
+
colorTint: [
|
|
3617
|
+
colorTint[0] * diffuse[0],
|
|
3618
|
+
colorTint[1] * diffuse[1],
|
|
3619
|
+
colorTint[2] * diffuse[2],
|
|
3620
|
+
colorTint[3] * (diffuse[3] ?? 1)
|
|
3621
|
+
],
|
|
2671
3622
|
transparent: false,
|
|
2672
3623
|
twoSided: target?.twoSided ?? lop.twoSided ?? true,
|
|
2673
3624
|
wireframe: Boolean(target?.wireframe ?? lop.wireframe),
|
|
@@ -2679,12 +3630,15 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2679
3630
|
...surfaceProps(target, lop, mat),
|
|
2680
3631
|
instanceBuffer,
|
|
2681
3632
|
instanceCount: bCount,
|
|
2682
|
-
bounds
|
|
3633
|
+
bounds,
|
|
3634
|
+
wind: meshWind(lop.wind, v, (shiftedFrame ?? 0) / (fps || 30)),
|
|
3635
|
+
crowd: crowdOpts(crowdBakes[k], mesh)
|
|
2683
3636
|
};
|
|
2684
3637
|
pending3DItems.push({
|
|
3638
|
+
owner: lop.id,
|
|
2685
3639
|
kind: "mesh",
|
|
2686
3640
|
mesh,
|
|
2687
|
-
texture: mat ? await r3d.materialTexture(mat) : void 0,
|
|
3641
|
+
texture: mat ? await r3d$1.materialTexture(mat) : void 0,
|
|
2688
3642
|
opts: meshOpts
|
|
2689
3643
|
});
|
|
2690
3644
|
}
|
|
@@ -2800,7 +3754,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2800
3754
|
else if (m.modelData && "meshes" in m.modelData) vModel = m.modelData;
|
|
2801
3755
|
else if (m.primitive3d) vModel = getPrimitiveGeometry(m.primitive3d);
|
|
2802
3756
|
else if (m.src) try {
|
|
2803
|
-
vModel = r3d.loadModel(m.src, m.modelFormat ?? "auto", {
|
|
3757
|
+
vModel = r3d$1.loadModel(m.src, m.modelFormat ?? "auto", {
|
|
2804
3758
|
center: m.center,
|
|
2805
3759
|
normalizeSize: m.normalizeSize
|
|
2806
3760
|
});
|
|
@@ -2905,7 +3859,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2905
3859
|
};
|
|
2906
3860
|
let swarmState = swarmStateMap.get(lop);
|
|
2907
3861
|
if (!swarmState || swarmState.device !== ctx.device) {
|
|
2908
|
-
swarmState = r3d.swarm3dPipeline.createState(staticConfig);
|
|
3862
|
+
swarmState = r3d$1.swarm3dPipeline.createState(staticConfig);
|
|
2909
3863
|
swarmStateMap.set(lop, swarmState);
|
|
2910
3864
|
}
|
|
2911
3865
|
const targetF = shiftedFrame ?? 0;
|
|
@@ -2995,7 +3949,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
2995
3949
|
emitterPos
|
|
2996
3950
|
};
|
|
2997
3951
|
};
|
|
2998
|
-
r3d.swarm3dPipeline.advance(swarmState, staticConfig, targetF, fps || 30, frameSampler);
|
|
3952
|
+
r3d$1.swarm3dPipeline.advance(swarmState, staticConfig, targetF, fps || 30, frameSampler);
|
|
2999
3953
|
if (variants.length > 0) {
|
|
3000
3954
|
const sliceCount = swarmState.sliceCount;
|
|
3001
3955
|
for (let vIdx = 0; vIdx < variants.length; vIdx++) {
|
|
@@ -3021,9 +3975,10 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3021
3975
|
firstInstance
|
|
3022
3976
|
};
|
|
3023
3977
|
pending3DItems.push({
|
|
3978
|
+
owner: lop.id,
|
|
3024
3979
|
kind: "mesh",
|
|
3025
3980
|
mesh,
|
|
3026
|
-
texture: mat ? await r3d.materialTexture(mat) : void 0,
|
|
3981
|
+
texture: mat ? await r3d$1.materialTexture(mat) : void 0,
|
|
3027
3982
|
opts: meshOpts
|
|
3028
3983
|
});
|
|
3029
3984
|
}
|
|
@@ -3051,9 +4006,10 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3051
4006
|
firstInstance: sparkFirst
|
|
3052
4007
|
};
|
|
3053
4008
|
pending3DItems.push({
|
|
4009
|
+
owner: lop.id,
|
|
3054
4010
|
kind: "mesh",
|
|
3055
4011
|
mesh,
|
|
3056
|
-
texture: mat ? await r3d.materialTexture(mat) : void 0,
|
|
4012
|
+
texture: mat ? await r3d$1.materialTexture(mat) : void 0,
|
|
3057
4013
|
opts: sparkOpts
|
|
3058
4014
|
});
|
|
3059
4015
|
}
|
|
@@ -3075,7 +4031,22 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3075
4031
|
if (lop.loop ?? true) clipSec %= clip.duration;
|
|
3076
4032
|
}
|
|
3077
4033
|
const sceneRoot = Matrix4Math.multiply(finalModelMatrix, model.rootTransform ?? Matrix4Math.identity());
|
|
3078
|
-
const
|
|
4034
|
+
const layerProps = Matrix4Math.multiply(Matrix4Math.translate(sampledX$1 - posX, sampledY$1 - posY, 0), localM);
|
|
4035
|
+
const wholeFracture = Boolean(lop.fracture3d && fractureWhole(model, lop.fracture3d, shiftedFrame ?? 0));
|
|
4036
|
+
const posed = lop.fracture3d && !wholeFracture && fracturePose(model, lop.fracture3d, shiftedFrame ?? 0, layerProps, [
|
|
4037
|
+
scX,
|
|
4038
|
+
scY,
|
|
4039
|
+
scZ
|
|
4040
|
+
]) || (model.nodes ? poseCharacter({
|
|
4041
|
+
model,
|
|
4042
|
+
node: lop,
|
|
4043
|
+
frame: shiftedFrame ?? 0,
|
|
4044
|
+
fps: fps || 30,
|
|
4045
|
+
clip,
|
|
4046
|
+
clipSec,
|
|
4047
|
+
sceneRoot,
|
|
4048
|
+
key: `${compiled.key}:${lop.id}`
|
|
4049
|
+
}) : void 0);
|
|
3079
4050
|
const skinCache = /* @__PURE__ */ new Map();
|
|
3080
4051
|
const placeMesh = (mesh) => {
|
|
3081
4052
|
if (!posed) return { matrix: sceneRoot };
|
|
@@ -3136,6 +4107,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3136
4107
|
}
|
|
3137
4108
|
}
|
|
3138
4109
|
for (const mesh of model.meshes) {
|
|
4110
|
+
if (wholeFracture && mesh.materialName === FRACTURE_INTERIOR_MATERIAL) continue;
|
|
3139
4111
|
const mat = mesh.materialName ? model.materials[mesh.materialName] : void 0;
|
|
3140
4112
|
const placed = placeMesh(mesh);
|
|
3141
4113
|
const meshSkin = placed.joints ?? skinningMatrices;
|
|
@@ -3238,7 +4210,10 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3238
4210
|
}
|
|
3239
4211
|
const meshOpts = {
|
|
3240
4212
|
modelMatrix: placed.matrix,
|
|
3241
|
-
morphWeights: sampleMorphWeights(mesh, clip, clipSec),
|
|
4213
|
+
morphWeights: namedMorphWeights(mesh.morphTargetNames, sampleMorphWeights(mesh, clip, clipSec), target?.morphs ?? lop.morphs, {
|
|
4214
|
+
frame: shiftedFrame ?? 0,
|
|
4215
|
+
fps: fps || 30
|
|
4216
|
+
}),
|
|
3242
4217
|
opacity: modelOpacity * (mat?.opacity ?? 1),
|
|
3243
4218
|
colorTint: meshColorTint,
|
|
3244
4219
|
transparent: mat?.alphaMode === "blend" || modelOpacity * (mat?.opacity ?? 1) < 1 || meshColorTint[3] < 1 || hasVertexAlpha(mesh),
|
|
@@ -3257,16 +4232,19 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3257
4232
|
ambientIntensity: target?.ambientIntensity ?? lop.ambientIntensity ?? 1,
|
|
3258
4233
|
metallic: target?.metallic ?? lop.metallic ?? mat?.metallic,
|
|
3259
4234
|
...surfaceProps(target, lop, mat),
|
|
3260
|
-
ior: target?.ior ?? lop.ior,
|
|
4235
|
+
ior: target?.ior ?? lop.ior ?? mat?.ior,
|
|
3261
4236
|
dispersion: target?.dispersion ?? lop.dispersion,
|
|
3262
4237
|
thickness: target?.thickness ?? lop.thickness,
|
|
3263
|
-
|
|
4238
|
+
...mat?.thickness !== void 0 ? { worldThickness: mat.thickness * matrixScale(placed.matrix) } : {},
|
|
4239
|
+
audioDeform: meshAudioDeform,
|
|
4240
|
+
wind: meshWind(lop.wind, model, (shiftedFrame ?? 0) / (fps || 30))
|
|
3264
4241
|
};
|
|
3265
|
-
if (mat) meshOpts.maps = await r3d.materialMaps(mat);
|
|
4242
|
+
if (mat) meshOpts.maps = await r3d$1.materialMaps(mat);
|
|
3266
4243
|
pending3DItems.push({
|
|
4244
|
+
owner: lop.id,
|
|
3267
4245
|
kind: "mesh",
|
|
3268
4246
|
mesh,
|
|
3269
|
-
texture: mat ? await r3d.materialTexture(mat) : void 0,
|
|
4247
|
+
texture: mat ? await r3d$1.materialTexture(mat) : void 0,
|
|
3270
4248
|
opts: meshOpts
|
|
3271
4249
|
});
|
|
3272
4250
|
}
|
|
@@ -3326,14 +4304,17 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3326
4304
|
padX = Math.max(80, Math.ceil(rect.width * .2));
|
|
3327
4305
|
padY = Math.max(50, Math.ceil(rect.height * .5));
|
|
3328
4306
|
}
|
|
4307
|
+
if (kind === "text" && !isPathText) {
|
|
4308
|
+
const ink = textInkOutset(target, lop);
|
|
4309
|
+
padX = Math.max(padX, ink);
|
|
4310
|
+
padY = Math.max(padY, ink);
|
|
4311
|
+
}
|
|
3329
4312
|
const layerW = isPathText ? targetW : rect.width + padX * 2;
|
|
3330
4313
|
const layerH = isPathText ? targetH : rect.height + padY * 2;
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
const anchorX = lop.anchorX ?? .5;
|
|
3336
|
-
const anchorY = lop.anchorY ?? .5;
|
|
4314
|
+
localX -= padX;
|
|
4315
|
+
localY -= padY;
|
|
4316
|
+
const anchorX = isPathText ? (lop.anchorX ?? .5) * rect.width / layerW : (padX + (lop.anchorX ?? .5) * rect.width) / layerW;
|
|
4317
|
+
const anchorY = isPathText ? (lop.anchorY ?? .5) * rect.height / layerH : (padY + (lop.anchorY ?? .5) * rect.height) / layerH;
|
|
3337
4318
|
const localMatrix = toDOMMatrix(buildLayerMatrix({
|
|
3338
4319
|
x: localX,
|
|
3339
4320
|
y: localY,
|
|
@@ -3343,8 +4324,8 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3343
4324
|
scale: scale$1,
|
|
3344
4325
|
scaleX,
|
|
3345
4326
|
scaleY,
|
|
3346
|
-
anchorX
|
|
3347
|
-
anchorY
|
|
4327
|
+
anchorX,
|
|
4328
|
+
anchorY
|
|
3348
4329
|
}));
|
|
3349
4330
|
const layerMatrix = parentMatrix.multiply(localMatrix);
|
|
3350
4331
|
const blendMode = lop.blendMode || "normal";
|
|
@@ -3356,8 +4337,8 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3356
4337
|
const rotateZ = target?.rotateZ ?? lop.rotateZ ?? 0;
|
|
3357
4338
|
const translateZ = target?.translateZ ?? lop.translateZ ?? 0;
|
|
3358
4339
|
const perspective = target?.perspective ?? lop.perspective ?? 0;
|
|
3359
|
-
const perspectiveOriginX = target?.perspectiveOriginX ?? lop.perspectiveOriginX ??
|
|
3360
|
-
const perspectiveOriginY = target?.perspectiveOriginY ?? lop.perspectiveOriginY ??
|
|
4340
|
+
const perspectiveOriginX = target?.perspectiveOriginX ?? lop.perspectiveOriginX ?? anchorX;
|
|
4341
|
+
const perspectiveOriginY = target?.perspectiveOriginY ?? lop.perspectiveOriginY ?? anchorY;
|
|
3361
4342
|
const backfaceVisibility = target?.backfaceVisibility ?? lop.backfaceVisibility ?? "visible";
|
|
3362
4343
|
let quad3D = null;
|
|
3363
4344
|
if (is3D) {
|
|
@@ -3386,7 +4367,6 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3386
4367
|
if (backfaceVisibility === "hidden" && Transform3DMath.computeSignedArea(q) < 0) return;
|
|
3387
4368
|
quad3D = q;
|
|
3388
4369
|
}
|
|
3389
|
-
const isTrue3D = Boolean(target?.is3D ?? lop.is3D) || Boolean(camera && ((target?.z ?? lop.z ?? 0) !== 0 || lop.is3D));
|
|
3390
4370
|
if (isContainer) {
|
|
3391
4371
|
if (lop.transformStyle === "preserve-3d" && isTrue3D) {
|
|
3392
4372
|
let current3DMatrix = Matrix4Math.identity();
|
|
@@ -3471,30 +4451,6 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3471
4451
|
}, { opacity: 1 });
|
|
3472
4452
|
borderPass.end();
|
|
3473
4453
|
}
|
|
3474
|
-
let modelMatrix;
|
|
3475
|
-
if (parent3DMatrix) {
|
|
3476
|
-
let localM = Matrix4Math.identity();
|
|
3477
|
-
const childX = target?.x ?? lop.x ?? 0;
|
|
3478
|
-
const childY = target?.y ?? lop.y ?? 0;
|
|
3479
|
-
const childZ = target?.z ?? lop.z ?? 0;
|
|
3480
|
-
localM = Matrix4Math.multiply(localM, Matrix4Math.translate(childX, childY, childZ));
|
|
3481
|
-
const rxRad = (target?.rotateX ?? lop.rotateX ?? 0) * Math.PI / 180;
|
|
3482
|
-
const ryRad = (target?.rotateY ?? lop.rotateY ?? 0) * Math.PI / 180;
|
|
3483
|
-
const rzRad = ((target?.rotateZ ?? lop.rotateZ ?? 0) !== 0 ? target?.rotateZ ?? lop.rotateZ ?? 0 : rotation) * (Math.PI / 180);
|
|
3484
|
-
if (rzRad !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.rotateZ(rzRad));
|
|
3485
|
-
if (ryRad !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.rotateY(ryRad));
|
|
3486
|
-
if (rxRad !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.rotateX(rxRad));
|
|
3487
|
-
const sx = layerW * scale$1 * scaleX;
|
|
3488
|
-
const sy = layerH * scale$1 * scaleY;
|
|
3489
|
-
const sz = target?.scaleZ ?? lop.scaleZ ?? 1;
|
|
3490
|
-
localM = Matrix4Math.multiply(localM, Matrix4Math.scale(sx, sy, sz));
|
|
3491
|
-
const ax = lop.anchorX ?? .5;
|
|
3492
|
-
const ay = lop.anchorY ?? .5;
|
|
3493
|
-
const pivotX = .5 - ax;
|
|
3494
|
-
const pivotY = .5 - ay;
|
|
3495
|
-
if (pivotX !== 0 || pivotY !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.translate(pivotX, pivotY, 0));
|
|
3496
|
-
modelMatrix = Matrix4Math.multiply(parent3DMatrix, localM);
|
|
3497
|
-
}
|
|
3498
4454
|
const quadOpts = {
|
|
3499
4455
|
position: [
|
|
3500
4456
|
localX + layerW * .5,
|
|
@@ -3527,10 +4483,21 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3527
4483
|
ambientIntensity: target?.ambientIntensity ?? lop.ambientIntensity,
|
|
3528
4484
|
metallic: target?.metallic ?? lop.metallic,
|
|
3529
4485
|
...surfaceProps(target, lop),
|
|
3530
|
-
...modelMatrix && { modelMatrix },
|
|
3531
4486
|
...reliefOpts(lop.id, localX, localY, layerW, layerH)
|
|
3532
4487
|
};
|
|
4488
|
+
if (parent3DMatrix) {
|
|
4489
|
+
const r3d$1 = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
4490
|
+
quadOpts.modelMatrix = Matrix4Math.multiply(parent3DMatrix, r3d$1.quadModelMatrix({
|
|
4491
|
+
...quadOpts,
|
|
4492
|
+
position: [
|
|
4493
|
+
target?.x ?? lop.x ?? 0,
|
|
4494
|
+
target?.y ?? lop.y ?? 0,
|
|
4495
|
+
target?.z ?? lop.z ?? 0
|
|
4496
|
+
]
|
|
4497
|
+
}));
|
|
4498
|
+
}
|
|
3533
4499
|
pending3DItems.push({
|
|
4500
|
+
owner: lop.id,
|
|
3534
4501
|
kind: "quad",
|
|
3535
4502
|
texture: activeGroupTex$1,
|
|
3536
4503
|
opts: quadOpts
|
|
@@ -3639,7 +4606,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
3639
4606
|
finalView: activeView
|
|
3640
4607
|
};
|
|
3641
4608
|
}
|
|
3642
|
-
const shouldClip = lop.overflow
|
|
4609
|
+
const shouldClip = (target?.overflow ?? lop.overflow) === "hidden";
|
|
3643
4610
|
const scissorRect = shouldClip ? computeContainerScissor(layerMatrix, layerW, layerH) : null;
|
|
3644
4611
|
const clipRadius = shouldClip ? Math.min(target?.borderRadius ?? lop.borderRadius ?? 0, layerW / 2, layerH / 2) : 0;
|
|
3645
4612
|
if ((kind === "flex" || kind === "block") && (!Array.isArray(lop.effects) || lop.effects.length === 0) && clipRadius <= 0 && !shouldPaintContainerBackground(kind, lop.background) && layerOpacity === 1 && blendMode === "normal" && !lop.borderWidth && !lop.borderColor && (typeof lop.relighting !== "object" || !lop.relighting) && (typeof lop.relight !== "object" || !lop.relight) && (typeof target?.relighting !== "object" || !target?.relighting) && (typeof target?.relight !== "object" || !target?.relight) && (typeof lop.deflicker !== "object" || !lop.deflicker) && (typeof target?.deflicker !== "object" || !target?.deflicker)) {
|
|
@@ -4034,6 +5001,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
4034
5001
|
fontFamily: lop.fontFamily,
|
|
4035
5002
|
fontStyle: lop.fontStyle,
|
|
4036
5003
|
fontWeight: lop.fontWeight,
|
|
5004
|
+
fontVariations: lop.fontVariations,
|
|
4037
5005
|
fill: target?.fill ?? target?.color ?? lop.fill,
|
|
4038
5006
|
align: lop.align,
|
|
4039
5007
|
direction: lop.direction,
|
|
@@ -4284,8 +5252,9 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
4284
5252
|
if (Math.hypot(vx, vy) > .5) {
|
|
4285
5253
|
if (!isTrue3D && !(is3D && quad3D)) {
|
|
4286
5254
|
const reach = shutterAngle / 360;
|
|
4287
|
-
const
|
|
4288
|
-
const
|
|
5255
|
+
const side = ctx.device.limits.maxTextureDimension2D;
|
|
5256
|
+
const padX$1 = Math.min(Math.ceil(Math.abs(vx) * rasterScale * reach), Math.max(0, Math.floor((side - texW) / 2)));
|
|
5257
|
+
const padY$1 = Math.min(Math.ceil(Math.abs(vy) * rasterScale * reach), Math.max(0, Math.floor((side - texH) / 2)));
|
|
4289
5258
|
blurPadX = padX$1 / rasterScale;
|
|
4290
5259
|
blurPadY = padY$1 / rasterScale;
|
|
4291
5260
|
const paddedTex = ctx.renderer.getTemporaryTexture(texW + padX$1 * 2, texH + padY$1 * 2, [
|
|
@@ -4350,30 +5319,6 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
4350
5319
|
}, { opacity: 1 });
|
|
4351
5320
|
borderPass.end();
|
|
4352
5321
|
}
|
|
4353
|
-
let modelMatrix;
|
|
4354
|
-
if (parent3DMatrix) {
|
|
4355
|
-
let localM = Matrix4Math.identity();
|
|
4356
|
-
const childX = target?.x ?? lop.x ?? 0;
|
|
4357
|
-
const childY = target?.y ?? lop.y ?? 0;
|
|
4358
|
-
const childZ = target?.z ?? lop.z ?? 0;
|
|
4359
|
-
localM = Matrix4Math.multiply(localM, Matrix4Math.translate(childX, childY, childZ));
|
|
4360
|
-
const rxRad = (target?.rotateX ?? lop.rotateX ?? 0) * Math.PI / 180;
|
|
4361
|
-
const ryRad = (target?.rotateY ?? lop.rotateY ?? 0) * Math.PI / 180;
|
|
4362
|
-
const rzRad = ((target?.rotateZ ?? lop.rotateZ ?? 0) !== 0 ? target?.rotateZ ?? lop.rotateZ ?? 0 : rotation) * (Math.PI / 180);
|
|
4363
|
-
if (rzRad !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.rotateZ(rzRad));
|
|
4364
|
-
if (ryRad !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.rotateY(ryRad));
|
|
4365
|
-
if (rxRad !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.rotateX(rxRad));
|
|
4366
|
-
const sx = layerW * scale$1 * scaleX;
|
|
4367
|
-
const sy = layerH * scale$1 * scaleY;
|
|
4368
|
-
const sz = target?.scaleZ ?? lop.scaleZ ?? 1;
|
|
4369
|
-
localM = Matrix4Math.multiply(localM, Matrix4Math.scale(sx, sy, sz));
|
|
4370
|
-
const ax = lop.anchorX ?? .5;
|
|
4371
|
-
const ay = lop.anchorY ?? .5;
|
|
4372
|
-
const pivotX = .5 - ax;
|
|
4373
|
-
const pivotY = .5 - ay;
|
|
4374
|
-
if (pivotX !== 0 || pivotY !== 0) localM = Matrix4Math.multiply(localM, Matrix4Math.translate(pivotX, pivotY, 0));
|
|
4375
|
-
modelMatrix = Matrix4Math.multiply(parent3DMatrix, localM);
|
|
4376
|
-
}
|
|
4377
5322
|
const quadOpts = {
|
|
4378
5323
|
position: [
|
|
4379
5324
|
localX + layerW * .5,
|
|
@@ -4406,16 +5351,28 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
4406
5351
|
ambientIntensity: target?.ambientIntensity ?? lop.ambientIntensity,
|
|
4407
5352
|
metallic: target?.metallic ?? lop.metallic,
|
|
4408
5353
|
...surfaceProps(target, lop),
|
|
4409
|
-
...modelMatrix && { modelMatrix },
|
|
4410
5354
|
...reliefOpts(lop.id, localX, localY, layerW, layerH)
|
|
4411
5355
|
};
|
|
5356
|
+
if (parent3DMatrix) {
|
|
5357
|
+
const r3d$1 = getRenderer3D(ctx.device, ctx.renderer.format ?? "rgba8unorm", sampleCount3d);
|
|
5358
|
+
quadOpts.modelMatrix = Matrix4Math.multiply(parent3DMatrix, r3d$1.quadModelMatrix({
|
|
5359
|
+
...quadOpts,
|
|
5360
|
+
position: [
|
|
5361
|
+
target?.x ?? lop.x ?? 0,
|
|
5362
|
+
target?.y ?? lop.y ?? 0,
|
|
5363
|
+
target?.z ?? lop.z ?? 0
|
|
5364
|
+
]
|
|
5365
|
+
}));
|
|
5366
|
+
}
|
|
4412
5367
|
const quadHasContent = layerHasRaster || Boolean(quadOpts.borderWidth && quadOpts.borderWidth > 0 && quadOpts.borderColor);
|
|
4413
5368
|
if (!glyphBatches || quadHasContent) pending3DItems.push({
|
|
5369
|
+
owner: lop.id,
|
|
4414
5370
|
kind: "quad",
|
|
4415
5371
|
texture: renderedTex,
|
|
4416
5372
|
opts: quadOpts
|
|
4417
5373
|
});
|
|
4418
5374
|
if (glyphBatches && glyphBatches.length > 0) pending3DItems.push({
|
|
5375
|
+
owner: lop.id,
|
|
4419
5376
|
kind: "slug",
|
|
4420
5377
|
batches: glyphBatches,
|
|
4421
5378
|
opts: quadOpts,
|
|
@@ -4542,6 +5499,7 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
4542
5499
|
...props.excludeTextures || []
|
|
4543
5500
|
];
|
|
4544
5501
|
currentCompTex = (await renderNodeTree(virtualMedia.children ?? [], compTex, compView, initialExcludes, 1, new DOMMatrix(), null, nativeWidth, nativeHeight, null, true)).finalTex;
|
|
5502
|
+
if (history && camera) history.recordFrame(shiftedFrame, camera);
|
|
4545
5503
|
ctx.renderer.popTransform();
|
|
4546
5504
|
ctx.renderer.popScissor();
|
|
4547
5505
|
const finalPass = ctx.renderer.beginFrame(encoder, targetView, {
|
|
@@ -4559,6 +5517,43 @@ const CompositorWebGPURenderer = async (args) => {
|
|
|
4559
5517
|
args.pass = finalPass;
|
|
4560
5518
|
}
|
|
4561
5519
|
};
|
|
5520
|
+
/** Whether a composition's camera asks for shutter motion blur. */
|
|
5521
|
+
function sceneMotionBlur(virtualMedia) {
|
|
5522
|
+
return collectNodeOps(virtualMedia.children).some((vm) => {
|
|
5523
|
+
const op = vm.operation;
|
|
5524
|
+
return op?.kind === "camera" && Boolean(op.motionBlur);
|
|
5525
|
+
});
|
|
5526
|
+
}
|
|
5527
|
+
/**
|
|
5528
|
+
* Renders `frame` of the composition into a scratch target only to record
|
|
5529
|
+
* its 3D motion history (the frame after it reads it).
|
|
5530
|
+
*/
|
|
5531
|
+
async function renderMotionHistory(args, frame) {
|
|
5532
|
+
const { ctx, encoder, props, targetTexture, targetWidth, targetHeight } = args;
|
|
5533
|
+
const excludeTextures = [...props.excludeTextures ?? [], targetTexture];
|
|
5534
|
+
const scratch = ctx.renderer.getTemporaryTexture(targetWidth, targetHeight, excludeTextures);
|
|
5535
|
+
const view = scratch.createView();
|
|
5536
|
+
const sub = {
|
|
5537
|
+
...args,
|
|
5538
|
+
targetView: view,
|
|
5539
|
+
targetTexture: scratch,
|
|
5540
|
+
pass: ctx.renderer.beginFrame(encoder, view, {
|
|
5541
|
+
r: 0,
|
|
5542
|
+
g: 0,
|
|
5543
|
+
b: 0,
|
|
5544
|
+
a: 0
|
|
5545
|
+
}, targetWidth, targetHeight, "clear"),
|
|
5546
|
+
props: {
|
|
5547
|
+
...props,
|
|
5548
|
+
frame,
|
|
5549
|
+
...props.compositionFrame !== void 0 && { compositionFrame: props.compositionFrame - 1 },
|
|
5550
|
+
motionHistoryOnly: true,
|
|
5551
|
+
excludeTextures
|
|
5552
|
+
}
|
|
5553
|
+
};
|
|
5554
|
+
await CompositorWebGPURenderer(sub);
|
|
5555
|
+
sub.pass.end();
|
|
5556
|
+
}
|
|
4562
5557
|
/** Pixels of room around a border texture for its anti-aliased edge. */
|
|
4563
5558
|
const BORDER_AA_MARGIN = 2;
|
|
4564
5559
|
/**
|
|
@@ -4732,4 +5727,4 @@ var renderers_default = defineRenderer({ WebGPURenderer: CompositorWebGPURendere
|
|
|
4732
5727
|
|
|
4733
5728
|
//#endregion
|
|
4734
5729
|
export { Transform3DMath, renderers_default as default, has3DTransform };
|
|
4735
|
-
//# sourceMappingURL=renderer-
|
|
5730
|
+
//# sourceMappingURL=renderer-4nXkaAWu.mjs.map
|