diff --git a/build/helix.js b/build/helix.js index 310ad995..cc9cd2d3 100644 --- a/build/helix.js +++ b/build/helix.js @@ -7,7 +7,7 @@ var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function unwrapExports (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x.default : x; + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } function createCommonjsModule(fn, module) { @@ -1899,8 +1899,8 @@ } DeviceInfo.Viewers = Viewers; var format = 1; - var last_updated = "2018-10-17T15:31:16Z"; - var devices = [{"type":"android","rules":[{"mdmh":"asus/*/Nexus 7/*"},{"ua":"Nexus 7"}],"dpi":[320.8,323],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"asus/*/ASUS_Z00AD/*"},{"ua":"ASUS_Z00AD"}],"dpi":[403,404.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel XL/*"},{"ua":"Pixel XL"}],"dpi":[537.9,533],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel/*"},{"ua":"Pixel"}],"dpi":[432.6,436.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC6435LVW/*"},{"ua":"HTC6435LVW"}],"dpi":[449.7,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One XL/*"},{"ua":"HTC One XL"}],"dpi":[315.3,314.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"htc/*/Nexus 9/*"},{"ua":"Nexus 9"}],"dpi":289,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One M9/*"},{"ua":"HTC One M9"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One_M8/*"},{"ua":"HTC One_M8"}],"dpi":[449.7,447.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One/*"},{"ua":"HTC One"}],"dpi":472.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Huawei/*/Nexus 6P/*"},{"ua":"Nexus 6P"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Huawei/*/BLN-L24/*"},{"ua":"HONORBLN-L24"}],"dpi":480,"bw":4,"ac":500},{"type":"android","rules":[{"mdmh":"Huawei/*/BKL-L09/*"},{"ua":"BKL-L09"}],"dpi":403,"bw":3.47,"ac":500},{"type":"android","rules":[{"mdmh":"LENOVO/*/Lenovo PB2-690Y/*"},{"ua":"Lenovo PB2-690Y"}],"dpi":[457.2,454.713],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5X/*"},{"ua":"Nexus 5X"}],"dpi":[422,419.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS345/*"},{"ua":"LGMS345"}],"dpi":[221.7,219.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D800/*"},{"ua":"LG-D800"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D850/*"},{"ua":"LG-D850"}],"dpi":[537.9,541.9],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/VS985 4G/*"},{"ua":"VS985 4G"}],"dpi":[537.9,535.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5/*"},{"ua":"Nexus 5 B"}],"dpi":[442.4,444.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 4/*"},{"ua":"Nexus 4"}],"dpi":[319.8,318.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LG-P769/*"},{"ua":"LG-P769"}],"dpi":[240.6,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS323/*"},{"ua":"LGMS323"}],"dpi":[206.6,204.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGLS996/*"},{"ua":"LGLS996"}],"dpi":[403.4,401.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/4560MMX/*"},{"ua":"4560MMX"}],"dpi":[240,219.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/A250/*"},{"ua":"Micromax A250"}],"dpi":[480,446.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/Micromax AQ4501/*"},{"ua":"Micromax AQ4501"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/G5/*"},{"ua":"Moto G (5) Plus"}],"dpi":[403.4,403],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/DROID RAZR/*"},{"ua":"DROID RAZR"}],"dpi":[368.1,256.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT830C/*"},{"ua":"XT830C"}],"dpi":[254,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1021/*"},{"ua":"XT1021"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1023/*"},{"ua":"XT1023"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1028/*"},{"ua":"XT1028"}],"dpi":[326.6,327.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1034/*"},{"ua":"XT1034"}],"dpi":[326.6,328.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1053/*"},{"ua":"XT1053"}],"dpi":[315.3,316.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1562/*"},{"ua":"XT1562"}],"dpi":[403.4,402.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/Nexus 6/*"},{"ua":"Nexus 6 B"}],"dpi":[494.3,489.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1063/*"},{"ua":"XT1063"}],"dpi":[295,296.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1064/*"},{"ua":"XT1064"}],"dpi":[295,295.6],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1092/*"},{"ua":"XT1092"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1095/*"},{"ua":"XT1095"}],"dpi":[422,423.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/G4/*"},{"ua":"Moto G (4)"}],"dpi":401,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/A0001/*"},{"ua":"A0001"}],"dpi":[403.4,401],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE E1005/*"},{"ua":"ONE E1005"}],"dpi":[442.4,441.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A2005/*"},{"ua":"ONE A2005"}],"dpi":[391.9,405.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONEPLUS A5000/*"},{"ua":"ONEPLUS A5000 "}],"dpi":[403.411,399.737],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A5010/*"},{"ua":"ONEPLUS A5010"}],"dpi":[403,400],"bw":2,"ac":1000},{"type":"android","rules":[{"mdmh":"OPPO/*/X909/*"},{"ua":"X909"}],"dpi":[442.4,444.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9082/*"},{"ua":"GT-I9082"}],"dpi":[184.7,185.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G360P/*"},{"ua":"SM-G360P"}],"dpi":[196.7,205.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Nexus S/*"},{"ua":"Nexus S"}],"dpi":[234.5,229.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[304.8,303.9],"bw":5,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T230NU/*"},{"ua":"SM-T230NU"}],"dpi":216,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-T399/*"},{"ua":"SGH-T399"}],"dpi":[217.7,231.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-M919/*"},{"ua":"SGH-M919"}],"dpi":[440.8,437.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N9005/*"},{"ua":"SM-N9005"}],"dpi":[386.4,387],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SM-N900A/*"},{"ua":"SAMSUNG-SM-N900A"}],"dpi":[386.4,387.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9500/*"},{"ua":"GT-I9500"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9505/*"},{"ua":"GT-I9505"}],"dpi":439.4,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900F/*"},{"ua":"SM-G900F"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900M/*"},{"ua":"SM-G900M"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G800F/*"},{"ua":"SM-G800F"}],"dpi":326.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G906S/*"},{"ua":"SM-G906S"}],"dpi":[562.7,572.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[306.7,304.8],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T535/*"},{"ua":"SM-T535"}],"dpi":[142.6,136.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920C/*"},{"ua":"SM-N920C"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920P/*"},{"ua":"SM-N920P"}],"dpi":[386.3655,390.144],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920W8/*"},{"ua":"SM-N920W8"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300I/*"},{"ua":"GT-I9300I"}],"dpi":[304.8,305.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9195/*"},{"ua":"GT-I9195"}],"dpi":[249.4,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-L520/*"},{"ua":"SPH-L520"}],"dpi":[249.4,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SGH-I717/*"},{"ua":"SAMSUNG-SGH-I717"}],"dpi":285.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-D710/*"},{"ua":"SPH-D710"}],"dpi":[217.7,204.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-N7100/*"},{"ua":"GT-N7100"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SCH-I605/*"},{"ua":"SCH-I605"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Galaxy Nexus/*"},{"ua":"Galaxy Nexus"}],"dpi":[315.3,314.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910H/*"},{"ua":"SM-N910H"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910C/*"},{"ua":"SM-N910C"}],"dpi":[515.2,520.2],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G130M/*"},{"ua":"SM-G130M"}],"dpi":[165.9,164.8],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G928I/*"},{"ua":"SM-G928I"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920F/*"},{"ua":"SM-G920F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920P/*"},{"ua":"SM-G920P"}],"dpi":[522.5,577],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925F/*"},{"ua":"SM-G925F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925V/*"},{"ua":"SM-G925V"}],"dpi":[522.5,576.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G930F/*"},{"ua":"SM-G930F"}],"dpi":576.6,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G935F/*"},{"ua":"SM-G935F"}],"dpi":533,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G950F/*"},{"ua":"SM-G950F"}],"dpi":[562.707,565.293],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G955U/*"},{"ua":"SM-G955U"}],"dpi":[522.514,525.762],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G955F/*"},{"ua":"SM-G955F"}],"dpi":[522.514,525.762],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/C6903/*"},{"ua":"C6903"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/D6653/*"},{"ua":"D6653"}],"dpi":[428.6,427.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6653/*"},{"ua":"E6653"}],"dpi":[428.6,425.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6853/*"},{"ua":"E6853"}],"dpi":[403.4,401.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/SGP321/*"},{"ua":"SGP321"}],"dpi":[224.7,224.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"TCT/*/ALCATEL ONE TOUCH Fierce/*"},{"ua":"ALCATEL ONE TOUCH Fierce"}],"dpi":[240,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"THL/*/thl 5000/*"},{"ua":"thl 5000"}],"dpi":[480,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Fly/*/IQ4412/*"},{"ua":"IQ4412"}],"dpi":307.9,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"ZTE/*/ZTE Blade L2/*"},{"ua":"ZTE Blade L2"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"BENEVE/*/VR518/*"},{"ua":"VR518"}],"dpi":480,"bw":3,"ac":500},{"type":"ios","rules":[{"res":[640,960]}],"dpi":[325.1,328.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[640,1136]}],"dpi":[317.1,320.2],"bw":3,"ac":1000},{"type":"ios","rules":[{"res":[750,1334]}],"dpi":326.4,"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1242,2208]}],"dpi":[453.6,458.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2001]}],"dpi":[410.9,415.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2436]}],"dpi":458,"bw":4,"ac":1000}]; + var last_updated = "2018-02-20T22:55:10Z"; + var devices = [{"type":"android","rules":[{"mdmh":"asus/*/Nexus 7/*"},{"ua":"Nexus 7"}],"dpi":[320.8,323],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"asus/*/ASUS_Z00AD/*"},{"ua":"ASUS_Z00AD"}],"dpi":[403,404.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel XL/*"},{"ua":"Pixel XL"}],"dpi":[537.9,533],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel/*"},{"ua":"Pixel"}],"dpi":[432.6,436.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC6435LVW/*"},{"ua":"HTC6435LVW"}],"dpi":[449.7,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One XL/*"},{"ua":"HTC One XL"}],"dpi":[315.3,314.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"htc/*/Nexus 9/*"},{"ua":"Nexus 9"}],"dpi":289,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One M9/*"},{"ua":"HTC One M9"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One_M8/*"},{"ua":"HTC One_M8"}],"dpi":[449.7,447.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One/*"},{"ua":"HTC One"}],"dpi":472.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Huawei/*/Nexus 6P/*"},{"ua":"Nexus 6P"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LENOVO/*/Lenovo PB2-690Y/*"},{"ua":"Lenovo PB2-690Y"}],"dpi":[457.2,454.713],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5X/*"},{"ua":"Nexus 5X"}],"dpi":[422,419.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS345/*"},{"ua":"LGMS345"}],"dpi":[221.7,219.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D800/*"},{"ua":"LG-D800"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D850/*"},{"ua":"LG-D850"}],"dpi":[537.9,541.9],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/VS985 4G/*"},{"ua":"VS985 4G"}],"dpi":[537.9,535.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5/*"},{"ua":"Nexus 5 B"}],"dpi":[442.4,444.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 4/*"},{"ua":"Nexus 4"}],"dpi":[319.8,318.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LG-P769/*"},{"ua":"LG-P769"}],"dpi":[240.6,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS323/*"},{"ua":"LGMS323"}],"dpi":[206.6,204.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGLS996/*"},{"ua":"LGLS996"}],"dpi":[403.4,401.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/4560MMX/*"},{"ua":"4560MMX"}],"dpi":[240,219.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/A250/*"},{"ua":"Micromax A250"}],"dpi":[480,446.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/Micromax AQ4501/*"},{"ua":"Micromax AQ4501"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/G5/*"},{"ua":"Moto G (5) Plus"}],"dpi":[403.4,403],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/DROID RAZR/*"},{"ua":"DROID RAZR"}],"dpi":[368.1,256.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT830C/*"},{"ua":"XT830C"}],"dpi":[254,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1021/*"},{"ua":"XT1021"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1023/*"},{"ua":"XT1023"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1028/*"},{"ua":"XT1028"}],"dpi":[326.6,327.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1034/*"},{"ua":"XT1034"}],"dpi":[326.6,328.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1053/*"},{"ua":"XT1053"}],"dpi":[315.3,316.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1562/*"},{"ua":"XT1562"}],"dpi":[403.4,402.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/Nexus 6/*"},{"ua":"Nexus 6 B"}],"dpi":[494.3,489.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1063/*"},{"ua":"XT1063"}],"dpi":[295,296.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1064/*"},{"ua":"XT1064"}],"dpi":[295,295.6],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1092/*"},{"ua":"XT1092"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1095/*"},{"ua":"XT1095"}],"dpi":[422,423.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/G4/*"},{"ua":"Moto G (4)"}],"dpi":401,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/A0001/*"},{"ua":"A0001"}],"dpi":[403.4,401],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE E1005/*"},{"ua":"ONE E1005"}],"dpi":[442.4,441.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A2005/*"},{"ua":"ONE A2005"}],"dpi":[391.9,405.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONEPLUS A5000/*"},{"ua":"ONEPLUS A5000 "}],"dpi":[403.411,399.737],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A5010/*"},{"ua":"ONEPLUS A5010"}],"dpi":[403,400],"bw":2,"ac":1000},{"type":"android","rules":[{"mdmh":"OPPO/*/X909/*"},{"ua":"X909"}],"dpi":[442.4,444.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9082/*"},{"ua":"GT-I9082"}],"dpi":[184.7,185.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G360P/*"},{"ua":"SM-G360P"}],"dpi":[196.7,205.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Nexus S/*"},{"ua":"Nexus S"}],"dpi":[234.5,229.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[304.8,303.9],"bw":5,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T230NU/*"},{"ua":"SM-T230NU"}],"dpi":216,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-T399/*"},{"ua":"SGH-T399"}],"dpi":[217.7,231.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-M919/*"},{"ua":"SGH-M919"}],"dpi":[440.8,437.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N9005/*"},{"ua":"SM-N9005"}],"dpi":[386.4,387],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SM-N900A/*"},{"ua":"SAMSUNG-SM-N900A"}],"dpi":[386.4,387.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9500/*"},{"ua":"GT-I9500"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9505/*"},{"ua":"GT-I9505"}],"dpi":439.4,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900F/*"},{"ua":"SM-G900F"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900M/*"},{"ua":"SM-G900M"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G800F/*"},{"ua":"SM-G800F"}],"dpi":326.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G906S/*"},{"ua":"SM-G906S"}],"dpi":[562.7,572.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[306.7,304.8],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T535/*"},{"ua":"SM-T535"}],"dpi":[142.6,136.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920C/*"},{"ua":"SM-N920C"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920P/*"},{"ua":"SM-N920P"}],"dpi":[386.3655,390.144],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920W8/*"},{"ua":"SM-N920W8"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300I/*"},{"ua":"GT-I9300I"}],"dpi":[304.8,305.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9195/*"},{"ua":"GT-I9195"}],"dpi":[249.4,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-L520/*"},{"ua":"SPH-L520"}],"dpi":[249.4,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SGH-I717/*"},{"ua":"SAMSUNG-SGH-I717"}],"dpi":285.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-D710/*"},{"ua":"SPH-D710"}],"dpi":[217.7,204.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-N7100/*"},{"ua":"GT-N7100"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SCH-I605/*"},{"ua":"SCH-I605"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Galaxy Nexus/*"},{"ua":"Galaxy Nexus"}],"dpi":[315.3,314.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910H/*"},{"ua":"SM-N910H"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910C/*"},{"ua":"SM-N910C"}],"dpi":[515.2,520.2],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G130M/*"},{"ua":"SM-G130M"}],"dpi":[165.9,164.8],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G928I/*"},{"ua":"SM-G928I"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920F/*"},{"ua":"SM-G920F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920P/*"},{"ua":"SM-G920P"}],"dpi":[522.5,577],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925F/*"},{"ua":"SM-G925F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925V/*"},{"ua":"SM-G925V"}],"dpi":[522.5,576.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G930F/*"},{"ua":"SM-G930F"}],"dpi":576.6,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G935F/*"},{"ua":"SM-G935F"}],"dpi":533,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G950F/*"},{"ua":"SM-G950F"}],"dpi":[562.707,565.293],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G955U/*"},{"ua":"SM-G955U"}],"dpi":[522.514,525.762],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/C6903/*"},{"ua":"C6903"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/D6653/*"},{"ua":"D6653"}],"dpi":[428.6,427.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6653/*"},{"ua":"E6653"}],"dpi":[428.6,425.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6853/*"},{"ua":"E6853"}],"dpi":[403.4,401.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/SGP321/*"},{"ua":"SGP321"}],"dpi":[224.7,224.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"TCT/*/ALCATEL ONE TOUCH Fierce/*"},{"ua":"ALCATEL ONE TOUCH Fierce"}],"dpi":[240,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"THL/*/thl 5000/*"},{"ua":"thl 5000"}],"dpi":[480,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Fly/*/IQ4412/*"},{"ua":"IQ4412"}],"dpi":307.9,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"ZTE/*/ZTE Blade L2/*"},{"ua":"ZTE Blade L2"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"BENEVE/*/VR518/*"},{"ua":"VR518"}],"dpi":480,"bw":3,"ac":500},{"type":"ios","rules":[{"res":[640,960]}],"dpi":[325.1,328.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[640,1136]}],"dpi":[317.1,320.2],"bw":3,"ac":1000},{"type":"ios","rules":[{"res":[750,1334]}],"dpi":326.4,"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1242,2208]}],"dpi":[453.6,458.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2001]}],"dpi":[410.9,415.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2436]}],"dpi":458,"bw":4,"ac":1000}]; var DPDB_CACHE = { format: format, last_updated: last_updated, @@ -1990,7 +1990,6 @@ }; Dpdb.prototype.matchRule_ = function (rule, ua, screenWidth, screenHeight) { if (!rule.ua && !rule.res) return false; - if (rule.ua && rule.ua.substring(0, 2) === 'SM') rule.ua = rule.ua.substring(0, 7); if (rule.ua && ua.indexOf(rule.ua) < 0) return false; if (rule.res) { if (!rule.res[0] || !rule.res[1]) return false; @@ -2674,7 +2673,7 @@ }; var commonjsGlobal$$1 = typeof window !== 'undefined' ? window : typeof commonjsGlobal$$1 !== 'undefined' ? commonjsGlobal$$1 : typeof self !== 'undefined' ? self : {}; function unwrapExports$$1 (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + return x && x.__esModule ? x['default'] : x; } function createCommonjsModule$$1(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; @@ -3377,7 +3376,7 @@ }); var CardboardVRDisplay = unwrapExports$$1(cardboardVrDisplay); - var version = "0.10.8"; + var version = "0.10.7"; var DefaultConfig = { ADDITIONAL_VIEWERS: [], @@ -3586,6 +3585,14 @@ } }; + ShaderLibrary._files['lighting_blinn_phong.glsl'] = '/*// schlick-beckman\nfloat hx_lightVisibility(vec3 normal, vec3 viewDir, float roughness, float nDotL)\n{\n float nDotV = max(-dot(normal, viewDir), 0.0);\n float r = roughness * roughness * 0.797896;\n float g1 = nDotV * (1.0 - r) + r;\n float g2 = nDotL * (1.0 - r) + r;\n return .25 / (g1 * g2);\n}*/\n\nfloat hx_blinnPhongDistribution(float roughness, vec3 normal, vec3 halfVector)\n{\n float roughnessSqr = clamp(roughness * roughness, 0.0001, .9999);\n// roughnessSqr *= roughnessSqr;\n float halfDotNormal = max(-dot(halfVector, normal), 0.0);\n return pow(halfDotNormal, 2.0/roughnessSqr - 2.0) / roughnessSqr;\n}\n\nvoid hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n float nDotL = -dot(lightDir, geometry.normal);\n vec3 irradiance = max(nDotL, 0.0) * lightColor; // in fact irradiance / PI\n\n vec3 halfVector = normalize(lightDir + viewDir);\n\n float distribution = hx_blinnPhongDistribution(geometry.roughness, geometry.normal, halfVector);\n\n float halfDotLight = max(dot(halfVector, lightDir), 0.0);\n float cosAngle = 1.0 - halfDotLight;\n // to the 5th power\n vec3 fresnel = normalSpecularReflectance + (1.0 - normalSpecularReflectance)*pow(cosAngle, 5.0);\n\n #ifdef HX_USE_TRANSLUCENCY\n // light for flipped normal\n diffuseColor += geometry.translucency * max(-nDotL, 0.0) * lightColor;\n #endif\n\n// / PI factor is encoded in light colour\n diffuseColor = irradiance;\n specularColor = irradiance * fresnel * distribution;\n\n//#ifdef HX_VISIBILITY\n// specularColor *= hx_lightVisibility(normal, lightDir, geometry.roughness, nDotL);\n//#endif\n}'; + + ShaderLibrary._files['lighting_debug.glsl'] = 'void hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n diffuseColor = vec3(0.0);\n specularColor = vec3(0.0);\n}'; + + ShaderLibrary._files['lighting_ggx.glsl'] = '#ifdef HX_VISIBILITY_TERM\nfloat hx_geometryTerm(vec3 normal, vec3 dir, float k)\n{\n float d = max(-dot(normal, dir), 0.0);\n return d / (d * (1.0 - k) + k);\n}\n\n// schlick-beckman\nfloat hx_lightVisibility(vec3 normal, vec3 viewDir, vec3 lightDir, float roughness)\n{\n float k = roughness + 1.0;\n k = k * k * .125;\n return hx_geometryTerm(normal, viewDir, k) * hx_geometryTerm(normal, lightDir, k);\n}\n#endif\n\nfloat hx_ggxDistribution(float roughness, vec3 normal, vec3 halfVector)\n{\n float roughSqr = roughness*roughness;\n float halfDotNormal = max(-dot(halfVector, normal), 0.0);\n float denom = (halfDotNormal * halfDotNormal) * (roughSqr - 1.0) + 1.0;\n return roughSqr / (denom * denom);\n}\n\n// light dir is to the lit surface\n// view dir is to the lit surface\nvoid hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n float nDotL = -dot(lightDir, geometry.normal);\n vec3 irradiance = max(nDotL, 0.0) * lightColor; // in fact irradiance / PI\n\n vec3 halfVector = normalize(lightDir + viewDir);\n\n float mappedRoughness = geometry.roughness * geometry.roughness;\n\n float distribution = hx_ggxDistribution(mappedRoughness, geometry.normal, halfVector);\n\n float halfDotLight = max(dot(halfVector, lightDir), 0.0);\n float cosAngle = 1.0 - halfDotLight;\n vec3 fresnel = normalSpecularReflectance + (1.0 - normalSpecularReflectance) * pow(cosAngle, 5.0);\n\n diffuseColor = irradiance;\n\n #ifdef HX_USE_TRANSLUCENCY\n // light for flipped normal\n diffuseColor += geometry.translucency * max(-nDotL, 0.0) * lightColor;\n #endif\n\n specularColor = irradiance * fresnel * distribution;\n\n#ifdef HX_VISIBILITY_TERM\n specularColor *= hx_lightVisibility(geometry.normal, viewDir, lightDir, geometry.roughness);\n#endif\n}'; + + ShaderLibrary._files['lighting_lambert.glsl'] = '// also make sure specular probes are ignores\n#define HX_SKIP_SPECULAR\n\n// light dir is to the lit surface\n// view dir is to the lit surface\nvoid hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n float nDotL = -dot(lightDir, geometry.normal);\n diffuseColor = max(nDotL, 0.0) * lightColor;\n\n #ifdef HX_USE_TRANSLUCENCY\n // light for flipped normal\n diffuseColor += geometry.translucency * max(-nDotL, 0.0) * lightColor;\n #endif\n\n specularColor = vec3(0.0);\n}'; + ShaderLibrary._files['debug_bounds_fragment.glsl'] = 'uniform vec4 color;\n\nvoid main()\n{\n hx_FragColor = color;\n}'; ShaderLibrary._files['debug_bounds_vertex.glsl'] = '\nvertex_attribute vec4 hx_position;\n\nuniform mat4 hx_wvpMatrix;\n\nvoid main()\n{\n gl_Position = hx_wvpMatrix * hx_position;\n}'; @@ -3596,14 +3603,6 @@ ShaderLibrary._files['debug_normals_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D sampler;\n\nvoid main()\n{\n // extractChannel comes from a macro\n vec3 normal = hx_decodeNormal(texture2D(sampler, uv));\n // swizzle so that it looks more naturally like tangent space normal maps\n hx_FragColor = vec4(normal.xzy * vec3(.5, .5, -.5) + .5, 1.0);\n}'; - ShaderLibrary._files['lighting_blinn_phong.glsl'] = '/*// schlick-beckman\nfloat hx_lightVisibility(vec3 normal, vec3 viewDir, float roughness, float nDotL)\n{\n float nDotV = max(-dot(normal, viewDir), 0.0);\n float r = roughness * roughness * 0.797896;\n float g1 = nDotV * (1.0 - r) + r;\n float g2 = nDotL * (1.0 - r) + r;\n return .25 / (g1 * g2);\n}*/\n\nfloat hx_blinnPhongDistribution(float roughness, vec3 normal, vec3 halfVector)\n{\n float roughnessSqr = clamp(roughness * roughness, 0.0001, .9999);\n// roughnessSqr *= roughnessSqr;\n float halfDotNormal = max(-dot(halfVector, normal), 0.0);\n return pow(halfDotNormal, 2.0/roughnessSqr - 2.0) / roughnessSqr;\n}\n\nvoid hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n float nDotL = -dot(lightDir, geometry.normal);\n vec3 irradiance = max(nDotL, 0.0) * lightColor; // in fact irradiance / PI\n\n vec3 halfVector = normalize(lightDir + viewDir);\n\n float distribution = hx_blinnPhongDistribution(geometry.roughness, geometry.normal, halfVector);\n\n float halfDotLight = max(dot(halfVector, lightDir), 0.0);\n float cosAngle = 1.0 - halfDotLight;\n // to the 5th power\n vec3 fresnel = normalSpecularReflectance + (1.0 - normalSpecularReflectance)*pow(cosAngle, 5.0);\n\n #ifdef HX_USE_TRANSLUCENCY\n // light for flipped normal\n diffuseColor += geometry.translucency * max(-nDotL, 0.0) * lightColor;\n #endif\n\n// / PI factor is encoded in light colour\n diffuseColor = irradiance;\n specularColor = irradiance * fresnel * distribution;\n\n//#ifdef HX_VISIBILITY\n// specularColor *= hx_lightVisibility(normal, lightDir, geometry.roughness, nDotL);\n//#endif\n}'; - - ShaderLibrary._files['lighting_debug.glsl'] = 'void hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n diffuseColor = vec3(0.0);\n specularColor = vec3(0.0);\n}'; - - ShaderLibrary._files['lighting_ggx.glsl'] = '#ifdef HX_VISIBILITY_TERM\nfloat hx_geometryTerm(vec3 normal, vec3 dir, float k)\n{\n float d = max(-dot(normal, dir), 0.0);\n return d / (d * (1.0 - k) + k);\n}\n\n// schlick-beckman\nfloat hx_lightVisibility(vec3 normal, vec3 viewDir, vec3 lightDir, float roughness)\n{\n float k = roughness + 1.0;\n k = k * k * .125;\n return hx_geometryTerm(normal, viewDir, k) * hx_geometryTerm(normal, lightDir, k);\n}\n#endif\n\nfloat hx_ggxDistribution(float roughness, vec3 normal, vec3 halfVector)\n{\n float roughSqr = roughness*roughness;\n float halfDotNormal = max(-dot(halfVector, normal), 0.0);\n float denom = (halfDotNormal * halfDotNormal) * (roughSqr - 1.0) + 1.0;\n return roughSqr / (denom * denom);\n}\n\n// light dir is to the lit surface\n// view dir is to the lit surface\nvoid hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n float nDotL = -dot(lightDir, geometry.normal);\n vec3 irradiance = max(nDotL, 0.0) * lightColor; // in fact irradiance / PI\n\n vec3 halfVector = normalize(lightDir + viewDir);\n\n float mappedRoughness = geometry.roughness * geometry.roughness;\n\n float distribution = hx_ggxDistribution(mappedRoughness, geometry.normal, halfVector);\n\n float halfDotLight = max(dot(halfVector, lightDir), 0.0);\n float cosAngle = 1.0 - halfDotLight;\n vec3 fresnel = normalSpecularReflectance + (1.0 - normalSpecularReflectance) * pow(cosAngle, 5.0);\n\n diffuseColor = irradiance;\n\n #ifdef HX_USE_TRANSLUCENCY\n // light for flipped normal\n diffuseColor += geometry.translucency * max(-nDotL, 0.0) * lightColor;\n #endif\n\n specularColor = irradiance * fresnel * distribution;\n\n#ifdef HX_VISIBILITY_TERM\n specularColor *= hx_lightVisibility(geometry.normal, viewDir, lightDir, geometry.roughness);\n#endif\n}'; - - ShaderLibrary._files['lighting_lambert.glsl'] = '// also make sure specular probes are ignores\n#define HX_SKIP_SPECULAR\n\n// light dir is to the lit surface\n// view dir is to the lit surface\nvoid hx_brdf(in HX_GeometryData geometry, in vec3 lightDir, in vec3 viewDir, in vec3 viewPos, in vec3 lightColor, vec3 normalSpecularReflectance, out vec3 diffuseColor, out vec3 specularColor)\n{\n float nDotL = -dot(lightDir, geometry.normal);\n diffuseColor = max(nDotL, 0.0) * lightColor;\n\n #ifdef HX_USE_TRANSLUCENCY\n // light for flipped normal\n diffuseColor += geometry.translucency * max(-nDotL, 0.0) * lightColor;\n #endif\n\n specularColor = vec3(0.0);\n}'; - ShaderLibrary._files['directional_light.glsl'] = 'struct HX_DirectionalLight\n{\n vec3 color;\n vec3 direction; // in view space?\n\n int castShadows;\n\n mat4 shadowMapMatrices[4];\n vec4 splitDistances;\n\n float depthBias;\n float maxShadowDistance; // = light.splitDistances[light.numCascades - 1]\n};\n\nvoid hx_calculateLight(HX_DirectionalLight light, HX_GeometryData geometry, vec3 viewVector, vec3 viewPosition, vec3 normalSpecularReflectance, out vec3 diffuse, out vec3 specular)\n{\n hx_brdf(geometry, light.direction, viewVector, viewPosition, light.color, normalSpecularReflectance, diffuse, specular);\n}\n\nmat4 hx_getShadowMatrix(HX_DirectionalLight light, vec3 viewPos)\n{\n #if HX_NUM_SHADOW_CASCADES > 1\n // not very efficient :(\n for (int i = 0; i < HX_NUM_SHADOW_CASCADES - 1; ++i) {\n if (viewPos.y < light.splitDistances[i])\n return light.shadowMapMatrices[i];\n }\n return light.shadowMapMatrices[HX_NUM_SHADOW_CASCADES - 1];\n #else\n return light.shadowMapMatrices[0];\n #endif\n}\n\n#ifdef HX_FRAGMENT_SHADER\nfloat hx_calculateShadows(HX_DirectionalLight light, sampler2D shadowMap, vec3 viewPos)\n{\n mat4 shadowMatrix = hx_getShadowMatrix(light, viewPos);\n vec4 shadowMapCoord = shadowMatrix * vec4(viewPos, 1.0);\n float shadow = hx_readShadow(shadowMap, shadowMapCoord, light.depthBias);\n\n // this can occur when meshInstance.castShadows = false, or using inherited bounds\n bool isOutside = max(shadowMapCoord.x, shadowMapCoord.y) > 1.0 || min(shadowMapCoord.x, shadowMapCoord.y) < 0.0;\n if (isOutside) shadow = 1.0;\n\n // this makes sure that anything beyond the last cascade is unshadowed\n return max(shadow, float(viewPos.y > light.maxShadowDistance));\n}\n#endif'; ShaderLibrary._files['light_probe.glsl'] = '#define HX_PROBE_K0 .00098\n#define HX_PROBE_K1 .9921\n\nstruct HX_DiffuseProbe\n{\n vec3 sh[9]; // rotated to be in view space\n vec3 position;\n float intensity;\n float sizeSqr;\n};\n\nstruct HX_SpecularProbe\n{\n vec3 position;\n float intensity;\n float sizeSqr;\n float numMips;\n};\n\nfloat hx_getProbeWeight(vec3 viewPos, vec3 pos, float sizeSqr)\n{\n vec3 diff = viewPos - pos;\n float distSqr = dot(diff, diff);\n float weight = 1.0 / distSqr;\n\n if (sizeSqr > 0.0)\n weight *= saturate(1.0 - distSqr / sizeSqr);\n\n return weight;\n}\n\n\nfloat hx_getProbeWeight(HX_SpecularProbe probe, vec3 viewPos)\n{\n return hx_getProbeWeight(viewPos, probe.position, probe.sizeSqr);\n}\n\nfloat hx_getProbeWeight(HX_DiffuseProbe probe, vec3 viewPos)\n{\n return hx_getProbeWeight(viewPos, probe.position, probe.sizeSqr);\n}\n\nvec3 hx_calculateSpecularProbeLight(HX_SpecularProbe probe, samplerCube texture, vec3 reflectedViewDir, vec3 fresnelColor, float roughness)\n{\n #ifdef HX_SKIP_SPECULAR\n return vec3(0.0);\n #endif\n\n #if defined(HX_TEXTURE_LOD) || defined (HX_GLSL_300_ES)\n // knald method:\n float power = 2.0/(roughness * roughness) - 2.0;\n float factor = (exp2(-10.0/sqrt(power)) - HX_PROBE_K0)/HX_PROBE_K1;\n float mipLevel = probe.numMips * (1.0 - clamp(factor, 0.0, 1.0));\n #ifdef HX_GLSL_300_ES\n vec4 specProbeSample = textureLod(texture, reflectedViewDir.xzy, mipLevel);\n #else\n vec4 specProbeSample = textureCubeLodEXT(texture, reflectedViewDir.xzy, mipLevel);\n #endif\n #else\n vec4 specProbeSample = textureCube(texture, reflectedViewDir.xzy);\n #endif\n return hx_gammaToLinear(specProbeSample.xyz) * fresnelColor * probe.intensity;\n}'; @@ -3668,6 +3667,18 @@ ShaderLibrary._files['sh_skybox_fragment.glsl'] = 'varying_in vec3 viewWorldDir;\n\nuniform vec3 hx_sh[9];\n\nHX_GeometryData hx_geometry()\n{\n HX_GeometryData data;\n data.color = vec4(hx_evaluateSH(hx_sh, normalize(viewWorldDir.xzy)), 1.0);\n data.emission = vec3(0.0);\n return data;\n}'; + ShaderLibrary._files['blend_color_copy_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D sampler;\n\nuniform vec4 blendColor;\n\nvoid main()\n{\n // extractChannel comes from a macro\n hx_FragColor = texture2D(sampler, uv) * blendColor;\n}\n'; + + ShaderLibrary._files['copy_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D sampler;\n\nvoid main()\n{\n // extractChannel comes from a macro\n hx_FragColor = vec4(extractChannels(texture2D(sampler, uv)));\n\n#ifndef COPY_ALPHA\n hx_FragColor.a = 1.0;\n#endif\n}\n'; + + ShaderLibrary._files['copy_to_gamma_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D sampler;\n\nvoid main()\n{\n hx_FragColor = hx_linearToGamma(texture2D(sampler, uv));\n}'; + + ShaderLibrary._files['copy_vertex.glsl'] = 'vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nvarying_out vec2 uv;\n\nvoid main()\n{\n uv = hx_texCoord;\n gl_Position = hx_position;\n}'; + + ShaderLibrary._files['null_fragment.glsl'] = 'void main()\n{\n hx_FragColor = vec4(1.0);\n}\n'; + + ShaderLibrary._files['null_vertex.glsl'] = 'vertex_attribute vec4 hx_position;\n\nvoid main()\n{\n gl_Position = hx_position;\n}'; + ShaderLibrary._files['bloom_composite_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D bloomTexture;\nuniform sampler2D hx_backBuffer;\nuniform float strength;\n\nvoid main()\n{\n hx_FragColor = texture2D(hx_backBuffer, uv) + texture2D(bloomTexture, uv) * strength;\n}'; ShaderLibrary._files['bloom_composite_vertex.glsl'] = 'vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nvarying_out vec2 uv;\n\nvoid main()\n{\n uv = hx_texCoord;\n gl_Position = hx_position;\n}'; @@ -3694,7 +3705,7 @@ ShaderLibrary._files['ssr_stencil_fragment.glsl'] = 'uniform sampler2D hx_gbufferSpecular;\n\nvarying_in vec2 uv;\n\nuniform float maxRoughness;\n\nvoid main()\n{\n vec4 specularSample = texture2D(hx_gbufferSpecular, uv);\n if (specularSample.x > maxRoughness)\n discard;\n}\n\n'; - ShaderLibrary._files['taa_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform vec2 hx_rcpRenderTargetResolution;\nuniform sampler2D hx_backBuffer;\nuniform sampler2D historyBuffer;\n\nuniform float alpha;\nuniform float gamma;\n\nvoid main()\n{\n vec4 col = texture2D(hx_backBuffer, uv);\n vec3 c = col.xyz; // \"c\"enter\n vec2 oldUV = hx_getPreviousFrameUV(uv);\n vec3 old = texture2D(historyBuffer, oldUV).xyz;\n float amount = alpha;\n\n // out of bounds: take new value completely\n if (oldUV.x < 0.0 || oldUV.x > 1.0 || oldUV.y < 0.0 || oldUV.y > 1.0)\n amount = 1.0;\n\n // neighbourhood clamping: the old colour is only considered valid if it\'s within the bounds of the current neighbours\n // https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf [Karis2014]\n vec3 l = texture2D(hx_backBuffer, uv - vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 r = texture2D(hx_backBuffer, uv + vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 t = texture2D(hx_backBuffer, uv - vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 b = texture2D(hx_backBuffer, uv + vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 minBound = min(min(min(min(l, r), t), b), c);\n vec3 maxBound = max(max(max(max(l, r), t), b), c);\n\n // just treat rgb space as a regular 3D space\n if (any(lessThan(old, minBound)) || any(greaterThan(old, maxBound))) {\n // variance clipping\n // http://developer.download.nvidia.com/gameworks/events/GDC2016/msalvi_temporal_supersampling.pdf\n // moments\n vec3 m1 = l + r + t + b + c;\n vec3 m2 = l * l + r * r + t * t + b * b + c * c;\n // variance\n vec3 mu = m1 / 5.0;\n vec3 sigma = sqrt(m2 / 5.0 - mu * mu);\n\n vec3 d = c - old;\n\n // find relevant AABB planes (those closest to the ray, know this from ray direction)\n vec3 planes = mu - sign(d) * gamma * sigma;\n\n // clip to old AABB to make sure it\'s never bigger\n planes = max(planes, minBound);\n planes = min(planes, maxBound);\n\n\n // clip segment [old -> C] against new AABB\n // C is always inside AABB\n vec3 tm = (planes - old) / d;\n vec3 absD = abs(d);\n\n float t = 0.0;\n\n if (absD.x > 0.0003)\n t = max(tm.x, t);\n if (absD.y > 0.0003)\n t = max(tm.y, t);\n if (absD.z > 0.0003)\n t = max(tm.z, t);\n\n old += t * d;\n }\n\n hx_FragColor.xyz = mix(old, c, amount);\n hx_FragColor.w = col.w;\n}'; + ShaderLibrary._files['taa_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform vec2 hx_rcpRenderTargetResolution;\nuniform sampler2D hx_backBuffer;\nuniform sampler2D historyBuffer;\n\nuniform float alpha;\nuniform float gamma;\n\nvoid main()\n{\n vec4 col = texture2D(hx_backBuffer, uv);\n vec3 c = col.xyz; // \"c\"enter\n vec2 oldUV = hx_getPreviousFrameUV(uv);\n vec3 old = texture2D(historyBuffer, oldUV).xyz;\n float amount = alpha;\n\n // out of bounds: take new value completely\n// if (oldUV.x < 0.0 || oldUV.x > 1.0 || oldUV.y < 0.0 || oldUV.y > 1.0)\n// amount = 1.0;\n\n // neighbourhood clamping: the old colour is only considered valid if it\'s within the bounds of the current neighbours\n // https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf [Karis2014]\n vec3 l = texture2D(hx_backBuffer, uv - vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 r = texture2D(hx_backBuffer, uv + vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 t = texture2D(hx_backBuffer, uv - vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 b = texture2D(hx_backBuffer, uv + vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 minBound = min(min(min(min(l, r), t), b), c);\n vec3 maxBound = max(max(max(max(l, r), t), b), c);\n\n // just treat rgb space as a regular 3D space\n // variance clipping\n // http://developer.download.nvidia.com/gameworks/events/GDC2016/msalvi_temporal_supersampling.pdf\n // moments\n vec3 m1 = l + r + t + b + c;\n vec3 m2 = l * l + r * r + t * t + b * b + c * c;\n // variance\n vec3 mu = m1 / 5.0;\n vec3 sigma = sqrt(m2 / 5.0 - mu * mu);\n\n vec3 d = c - old;\n\n // find relevant AABB planes (those closest to the ray, know this from ray direction)\n vec3 planes = mu - sign(d) * gamma * sigma;\n\n // clip to old AABB to make sure it\'s never bigger\n planes = max(planes, minBound);\n planes = min(planes, maxBound);\n\n // clip segment [old -> C] against new AABB\n // C is always inside AABB\n vec3 tm = (planes - old) / d;\n vec3 absD = abs(d);\n\n float tf = (max(tm.x, tm.y), tm.z);\n\n // if already inside the box, or somehow overshooting target (?)\n if (tf >= -0.001 && tf <= 1.001)\n old += tf * d;\n\n hx_FragColor.xyz = mix(old, c, amount);\n hx_FragColor.w = col.w;\n}'; ShaderLibrary._files['tonemap_filmic_fragment.glsl'] = 'void main()\n{\n vec3 x = hx_getToneMapScaledColor().xyz * 16.0;\n\n // Uncharted 2 tonemapping (http://filmicworlds.com/blog/filmic-tonemapping-operators/)\n\n float A = 0.15;\n float B = 0.50;\n float C = 0.10;\n float D = 0.20;\n float E = 0.02;\n float F = 0.30;\n float W = 11.2;\n\n hx_FragColor.xyz = hx_gammaToLinear(((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F);\n hx_FragColor.w = 1.0;\n}'; @@ -3702,18 +3713,6 @@ ShaderLibrary._files['tonemap_reinhard_fragment.glsl'] = 'void main()\n{\n vec4 color = hx_getToneMapScaledColor();\n float lum = hx_luminance(color);\n hx_FragColor = color / (1.0 + lum);\n}'; - ShaderLibrary._files['blend_color_copy_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D sampler;\n\nuniform vec4 blendColor;\n\nvoid main()\n{\n // extractChannel comes from a macro\n hx_FragColor = texture2D(sampler, uv) * blendColor;\n}\n'; - - ShaderLibrary._files['copy_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D sampler;\n\nvoid main()\n{\n // extractChannel comes from a macro\n hx_FragColor = vec4(extractChannels(texture2D(sampler, uv)));\n\n#ifndef COPY_ALPHA\n hx_FragColor.a = 1.0;\n#endif\n}\n'; - - ShaderLibrary._files['copy_to_gamma_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D sampler;\n\nvoid main()\n{\n hx_FragColor = hx_linearToGamma(texture2D(sampler, uv));\n}'; - - ShaderLibrary._files['copy_vertex.glsl'] = 'vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nvarying_out vec2 uv;\n\nvoid main()\n{\n uv = hx_texCoord;\n gl_Position = hx_position;\n}'; - - ShaderLibrary._files['null_fragment.glsl'] = 'void main()\n{\n hx_FragColor = vec4(1.0);\n}\n'; - - ShaderLibrary._files['null_vertex.glsl'] = 'vertex_attribute vec4 hx_position;\n\nvoid main()\n{\n gl_Position = hx_position;\n}'; - ShaderLibrary._files['esm_blur_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D source;\nuniform vec2 direction; // this is 1/pixelSize\n\nfloat readValue(vec2 coord)\n{\n float v = texture2D(source, coord).x;\n return v;\n// return exp(HX_ESM_CONSTANT * v);\n}\n\nvoid main()\n{\n float total = readValue(uv);\n\n for (int i = 1; i <= RADIUS; ++i) {\n vec2 offset = direction * float(i);\n total += readValue(uv + offset) + readValue(uv - offset);\n }\n\n// hx_FragColor = vec4(log(total * RCP_NUM_SAMPLES) / HX_ESM_CONSTANT);\n hx_FragColor = vec4(total * RCP_NUM_SAMPLES);\n}'; ShaderLibrary._files['shadow_esm.glsl'] = 'vec4 hx_getShadowMapValue(float depth)\n{\n // I wish we could write exp directly, but precision issues (can\'t encode real floats)\n return vec4(exp(HX_ESM_CONSTANT * depth));\n// so when blurring, we\'ll need to do ln(sum(exp())\n// return vec4(depth);\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n float shadowSample = texture2D(shadowMap, shadowMapCoord.xy).x;\n shadowMapCoord.z += depthBias;\n// float diff = shadowSample - shadowMapCoord.z;\n// return saturate(HX_ESM_DARKENING * exp(HX_ESM_CONSTANT * diff));\n return saturate(HX_ESM_DARKENING * shadowSample * exp(-HX_ESM_CONSTANT * shadowMapCoord.z));\n}'; @@ -3726,6 +3725,14 @@ ShaderLibrary._files['vsm_blur_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D source;\nuniform vec2 direction; // this is 1/pixelSize\n\nvec2 readValues(vec2 coord)\n{\n vec4 s = texture2D(source, coord);\n #if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n return s.xy;\n #else\n return vec2(hx_RG8ToFloat(s.xy), hx_RG8ToFloat(s.zw));\n #endif\n}\n\nvoid main()\n{\n vec2 total = readValues(uv);\n\n for (int i = 1; i <= RADIUS; ++i) {\n vec2 offset = direction * float(i);\n total += readValues(uv + offset) + readValues(uv - offset);\n }\n\n total *= RCP_NUM_SAMPLES;\n\n#if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n hx_FragColor = vec4(total, 0.0, 1.0);\n#else\n hx_FragColor.xy = hx_floatToRG8(total.x);\n hx_FragColor.zw = hx_floatToRG8(total.y);\n#endif\n}'; + ShaderLibrary._files['snippets_general.glsl'] = '#define HX_LOG_10 2.302585093\n#define HX_PI 3.1415926\n\n#ifdef HX_GLSL_300_ES\n // replace some outdated function names\n vec4 texture2D(sampler2D s, vec2 uv) { return texture(s, uv); }\n vec4 textureCube(samplerCube s, vec3 uvw) { return texture(s, uvw); }\n\n #define vertex_attribute in\n #define varying_in in\n #define varying_out out\n\n #ifdef HX_FRAGMENT_SHADER\n out vec4 hx_FragColor;\n #endif\n#else\n #define vertex_attribute attribute\n #define varying_in varying\n #define varying_out varying\n #define hx_FragColor gl_FragColor\n#endif\n\nfloat saturate(float value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec2 saturate(vec2 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec3 saturate(vec3 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec4 saturate(vec4 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\n// Only for 0 - 1\nvec4 hx_floatToRGBA8(float value)\n{\n vec4 enc = value * vec4(1.0, 255.0, 65025.0, 16581375.0);\n // cannot fract first value or 1 would not be encodable\n enc.yzw = fract(enc.yzw);\n return enc - enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);\n}\n\nfloat hx_RGBA8ToFloat(vec4 rgba)\n{\n return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));\n}\n\nvec2 hx_floatToRG8(float value)\n{\n vec2 enc = vec2(1.0, 255.0) * value;\n enc.y = fract(enc.y);\n enc.x -= enc.y / 255.0;\n return enc;\n}\n\nfloat hx_RG8ToFloat(vec2 rg)\n{\n return dot(rg, vec2(1.0, 1.0/255.0));\n}\n\nvec2 hx_encodeNormal(vec3 normal)\n{\n vec2 data;\n float p = sqrt(-normal.y*8.0 + 8.0);\n data = normal.xz / p + .5;\n return data;\n}\n\nvec2 hx_decodeMotionVector(vec4 data)\n{\n vec2 vel;\n vel.x = hx_RG8ToFloat(data.xy);\n vel.y = hx_RG8ToFloat(data.zw);\n return vel * 2.0 - 1.0;\n}\n\nvec3 hx_decodeNormal(vec4 data)\n{\n vec3 normal;\n data.xy = data.xy*4.0 - 2.0;\n float f = dot(data.xy, data.xy);\n float g = sqrt(1.0 - f * .25);\n normal.xz = data.xy * g;\n normal.y = -(1.0 - f * .5);\n return normal;\n}\n\nfloat hx_log10(float val)\n{\n return log(val) / HX_LOG_10;\n}\n\nvec4 hx_gammaToLinear(vec4 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec3 hx_gammaToLinear(vec3 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec4 hx_linearToGamma(vec4 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\nvec3 hx_linearToGamma(vec3 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\n/*float hx_sampleLinearDepth(sampler2D tex, vec2 uv)\n{\n return hx_RGBA8ToFloat(texture2D(tex, uv));\n}*/\n\nfloat hx_decodeLinearDepth(vec4 samp)\n{\n return hx_RG8ToFloat(samp.zw);\n}\n\nvec3 hx_getFrustumVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unprojNear = unprojectionMatrix * vec4(position, -1.0, 1.0);\n vec4 unprojFar = unprojectionMatrix * vec4(position, 1.0, 1.0);\n return unprojFar.xyz/unprojFar.w - unprojNear.xyz/unprojNear.w;\n}\n\n// view vector with z = 1, so we can use nearPlaneDist + linearDepth * (farPlaneDist - nearPlaneDist) as a scale factor to find view space position\nvec3 hx_getLinearDepthViewVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unproj = unprojectionMatrix * vec4(position, 0.0, 1.0);\n unproj /= unproj.w;\n return unproj.xyz / unproj.y;\n}\n\n// THIS IS FOR NON_LINEAR DEPTH!\nfloat hx_depthToViewY(float depth, mat4 projectionMatrix)\n{\n return projectionMatrix[3][2] / (depth * 2.0 - 1.0 - projectionMatrix[1][2]);\n}\n\nvec3 hx_getNormalSpecularReflectance(float metallicness, float insulatorNormalSpecularReflectance, vec3 color)\n{\n return mix(vec3(insulatorNormalSpecularReflectance), color, metallicness);\n}\n\nvec3 hx_fresnel(vec3 normalSpecularReflectance, vec3 lightDir, vec3 halfVector)\n{\n float cosAngle = 1.0 - max(dot(halfVector, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n return normalSpecularReflectance + (1.0 - normalSpecularReflectance) * power;\n}\n\n// https://seblagarde.wordpress.com/2011/08/17/hello-world/\nvec3 hx_fresnelProbe(vec3 normalSpecularReflectance, vec3 lightDir, vec3 normal, float roughness)\n{\n float cosAngle = 1.0 - max(dot(normal, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n float gloss = (1.0 - roughness) * (1.0 - roughness);\n vec3 bound = max(vec3(gloss), normalSpecularReflectance);\n return normalSpecularReflectance + (bound - normalSpecularReflectance) * power;\n}\n\n\nfloat hx_luminance(vec4 color)\n{\n return dot(color.xyz, vec3(.30, 0.59, .11));\n}\n\nfloat hx_luminance(vec3 color)\n{\n return dot(color, vec3(.30, 0.59, .11));\n}\n\n// linear variant of smoothstep\nfloat hx_linearStep(float lower, float upper, float x)\n{\n return clamp((x - lower) / (upper - lower), 0.0, 1.0);\n}\n\nvec4 hx_sampleDefaultDither(sampler2D ditherTexture, vec2 uv)\n{\n vec4 s = texture2D(ditherTexture, uv);\n\n #ifndef HX_FLOAT_TEXTURES\n s = s * 2.0 - 1.0;\n #endif\n\n return s;\n}\n\nvec3 hx_evaluateSH(vec3 sh[9], vec3 dir)\n{\n dir = dir.xzy;\n vec3 col = sh[0] +\n sh[1] * dir.y + sh[2] * dir.z + sh[3] * dir.x +\n sh[4] * dir.x * dir.y + sh[5] * dir.y * dir.z + sh[6] * (3.0 * dir.z * dir.z - 1.0) +\n sh[7] * dir.z * dir.x + sh[8] * (dir.x * dir.x - dir.y * dir.y);\n\n col = max(col, vec3(0.0));\n return col;\n}\n\n// I\'m keeping this for reference, even tho it doesn\'t work in iOS\nvoid hx_sumSH(in vec3 a[9], in float weight, inout vec3 b[9])\n{\n // have to manually unroll this, on some platforms the loop is weirdly slow\n b[0] += a[0] * weight;\n b[1] += a[1] * weight;\n b[2] += a[2] * weight;\n b[3] += a[3] * weight;\n b[4] += a[4] * weight;\n b[5] += a[5] * weight;\n b[6] += a[6] * weight;\n b[7] += a[7] * weight;\n b[8] += a[8] * weight;\n}\n\nvec3 hx_intersectCubeMap(vec3 rayOrigin, vec3 cubeCenter, vec3 rayDir, float cubeSize)\n{\n vec3 t = (cubeSize * sign(rayDir) - (rayOrigin - cubeCenter)) / rayDir;\n float minT = min(min(t.x, t.y), t.z);\n return rayOrigin + minT * rayDir;\n}\n\n// sadly, need a parameter due to a bug in Internet Explorer / Edge. Just pass in 0.\n#ifdef HX_USE_SKINNING_TEXTURE\n#define HX_RCP_MAX_SKELETON_JOINTS 1.0 / float(HX_MAX_SKELETON_JOINTS - 1)\nmat4 hx_getSkinningMatrixImpl(vec4 weights, vec4 indices, sampler2D tex)\n{\n mat4 m = mat4(0.0);\n for (int i = 0; i < 4; ++i) {\n mat4 t;\n float index = indices[i] * HX_RCP_MAX_SKELETON_JOINTS;\n t[0] = texture2D(tex, vec2(index, 0.0));\n t[1] = texture2D(tex, vec2(index, 0.5));\n t[2] = texture2D(tex, vec2(index, 1.0));\n t[3] = vec4(0.0, 0.0, 0.0, 1.0);\n m += weights[i] * t;\n }\n return m;\n}\n#define hx_getSkinningMatrix(v) hx_getSkinningMatrixImpl(hx_jointWeights, hx_jointIndices, hx_skinningTexture)\n#else\n#define hx_getSkinningMatrix(v) ( hx_jointWeights.x * mat4(hx_skinningMatrices[int(hx_jointIndices.x) * 3], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.y * mat4(hx_skinningMatrices[int(hx_jointIndices.y) * 3], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.z * mat4(hx_skinningMatrices[int(hx_jointIndices.z) * 3], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.w * mat4(hx_skinningMatrices[int(hx_jointIndices.w) * 3], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) )\n#endif'; + + ShaderLibrary._files['snippets_geometry.glsl'] = 'struct HX_GeometryData\n{\n vec4 color;\n vec3 normal;\n float metallicness;\n float normalSpecularReflectance;\n float roughness;\n float occlusion;\n vec3 emission;\n vec4 data; // this can be anything the lighting model requires\n #ifdef HX_USE_TRANSLUCENCY\n vec3 translucency;\n #endif\n};'; + + ShaderLibrary._files['snippets_reproject.glsl'] = '#ifdef HX_MOTION_VECTORS\nuniform sampler2D hx_motionVectorBuffer;\n#else\nuniform sampler2D hx_normalDepthBuffer;\nuniform float hx_cameraNearPlaneDistance;\nuniform float hx_cameraFrustumRange;\nuniform mat4 hx_inverseProjectionMatrix;\nuniform mat4 hx_cameraWorldMatrix;\nuniform mat4 hx_prevViewProjectionMatrix;\nuniform vec2 hx_cameraJitter;\n#endif\n\n\nvec2 hx_getMotionVector(vec2 uv)\n{\n#ifdef HX_MOTION_VECTORS\n return hx_decodeMotionVector(texture2D(hx_motionVectorBuffer, uv));\n#else\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n float depth = hx_decodeLinearDepth(normalDepth);\n float absViewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n\n // unproject any point on the view ray to view space:\n vec2 ndc = uv * 2.0 - 1.0;\n // view projection matrix is jittered, so hx_inverseProjectionMatrix will \"unjitter\"\n // so we need to reapply the jitter to counter this\n vec3 viewDir = hx_getLinearDepthViewVector(ndc + hx_cameraJitter, hx_inverseProjectionMatrix);\n\n // reconstruct world position based on linear depth\n vec3 viewPos = viewDir * absViewY;\n vec4 worldPos = hx_cameraWorldMatrix * vec4(viewPos, 1.0);\n\n // reproject with previous frame matrix\n vec4 oldProj = hx_prevViewProjectionMatrix * worldPos;\n return (ndc - oldProj.xy / oldProj.w) * .5;\n#endif\n}\n\nvec2 hx_getPreviousFrameUV(vec2 currentUV)\n{\n return currentUV - hx_getMotionVector(currentUV);\n}'; + + ShaderLibrary._files['snippets_tonemap.glsl'] = 'varying_in vec2 uv;\n\n#ifdef HX_ADAPTIVE\nuniform sampler2D hx_luminanceMap;\nuniform float hx_luminanceMipLevel;\n#endif\n\nuniform float hx_exposure;\nuniform float hx_key;\n\nuniform sampler2D hx_backBuffer;\n\n\nvec4 hx_getToneMapScaledColor()\n{\n #ifdef HX_ADAPTIVE\n #ifdef HX_GLSL_300_ES\n float referenceLuminance = textureLod(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #else\n float referenceLuminance = texture2DLodEXT(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #endif\n referenceLuminance = exp(referenceLuminance) - 1.0;\n referenceLuminance = clamp(referenceLuminance, .08, 1000.0);\n float exposure = hx_key / referenceLuminance * hx_exposure;\n #else\n float exposure = hx_exposure;\n #endif\n return texture2D(hx_backBuffer, uv) * exposure;\n}'; + ShaderLibrary._files['2d_to_cube_vertex.glsl'] = '// position to write to\nvertex_attribute vec4 hx_position;\n\n// the corner of the cube map\nvertex_attribute vec3 corner;\n\nvarying_out vec3 direction;\n\nvoid main()\n{\n direction = corner;\n gl_Position = hx_position;\n}\n'; ShaderLibrary._files['equirectangular_from_cube_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform samplerCube sampler;\n\nvoid main()\n{\n vec3 dir;\n\n float theta = (-(uv.x * 2.0 - 1.0) + .5) * HX_PI;\n float phi = (uv.y * 2.0 - 1.0) * HX_PI / 2.0;\n\n dir.x = cos(theta) * cos(phi);\n dir.y = -sin(phi);\n dir.z = sin(theta) * cos(phi);\n\n hx_FragColor = textureCube(sampler, dir);\n}'; @@ -3736,14 +3743,6 @@ ShaderLibrary._files['smooth_heightmap_fragment.glsl'] = 'varying_in vec2 uv;\n\nuniform sampler2D reference; // the source (8 bit) texture\nuniform sampler2D source;\n\nuniform vec2 stepSize;\n\nvoid main()\n{\n float gauss[4];\n gauss[0] = 0.201788613113303;\n gauss[1] = 0.17755834971394;\n gauss[2] = 0.120969095455128;\n gauss[3] = 0.063811162332456;\n float refHeight = texture2D(reference, uv).x;\n float total = hx_RGBA8ToFloat(texture2D(source, uv)) * gauss[0];\n float totalWeight = gauss[0];\n float currentWeightL = 1.0;\n float currentWeightR = 1.0;\n vec2 offset = vec2(0.0);\n\n\n for (int i = 0; i < 3; ++i) {\n offset += stepSize;\n float refLeft = texture2D(reference, uv - offset).x;\n float refRight = texture2D(reference, uv + offset).x;\n float heightLeft = hx_RGBA8ToFloat(texture2D(source, uv - offset));\n float heightRight = hx_RGBA8ToFloat(texture2D(source, uv + offset));\n // smooth out over N pixels that have the same reference height in the source image\n currentWeightL = max(currentWeightL - abs(refLeft - refHeight) * 5.0, 0.0);\n currentWeightR = max(currentWeightR - abs(refRight - refHeight) * 5.0, 0.0);\n totalWeight += (currentWeightL + currentWeightR) * gauss[i + 1];\n total += (heightLeft * currentWeightL + heightRight * currentWeightR) * gauss[i + 1];\n }\n\n hx_FragColor = hx_floatToRGBA8(total / totalWeight);\n}\n'; - ShaderLibrary._files['snippets_general.glsl'] = '#define HX_LOG_10 2.302585093\n#define HX_PI 3.1415926\n\n#ifdef HX_GLSL_300_ES\n // replace some outdated function names\n vec4 texture2D(sampler2D s, vec2 uv) { return texture(s, uv); }\n vec4 textureCube(samplerCube s, vec3 uvw) { return texture(s, uvw); }\n\n #define vertex_attribute in\n #define varying_in in\n #define varying_out out\n\n #ifdef HX_FRAGMENT_SHADER\n out vec4 hx_FragColor;\n #endif\n#else\n #define vertex_attribute attribute\n #define varying_in varying\n #define varying_out varying\n #define hx_FragColor gl_FragColor\n#endif\n\nfloat saturate(float value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec2 saturate(vec2 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec3 saturate(vec3 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec4 saturate(vec4 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\n// Only for 0 - 1\nvec4 hx_floatToRGBA8(float value)\n{\n vec4 enc = value * vec4(1.0, 255.0, 65025.0, 16581375.0);\n // cannot fract first value or 1 would not be encodable\n enc.yzw = fract(enc.yzw);\n return enc - enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);\n}\n\nfloat hx_RGBA8ToFloat(vec4 rgba)\n{\n return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));\n}\n\nvec2 hx_floatToRG8(float value)\n{\n vec2 enc = vec2(1.0, 255.0) * value;\n enc.y = fract(enc.y);\n enc.x -= enc.y / 255.0;\n return enc;\n}\n\nfloat hx_RG8ToFloat(vec2 rg)\n{\n return dot(rg, vec2(1.0, 1.0/255.0));\n}\n\nvec2 hx_encodeNormal(vec3 normal)\n{\n vec2 data;\n float p = sqrt(-normal.y*8.0 + 8.0);\n data = normal.xz / p + .5;\n return data;\n}\n\nvec2 hx_decodeMotionVector(vec4 data)\n{\n vec2 vel;\n vel.x = hx_RG8ToFloat(data.xy);\n vel.y = hx_RG8ToFloat(data.zw);\n return vel * 2.0 - 1.0;\n}\n\nvec3 hx_decodeNormal(vec4 data)\n{\n vec3 normal;\n data.xy = data.xy*4.0 - 2.0;\n float f = dot(data.xy, data.xy);\n float g = sqrt(1.0 - f * .25);\n normal.xz = data.xy * g;\n normal.y = -(1.0 - f * .5);\n return normal;\n}\n\nfloat hx_log10(float val)\n{\n return log(val) / HX_LOG_10;\n}\n\nvec4 hx_gammaToLinear(vec4 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec3 hx_gammaToLinear(vec3 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec4 hx_linearToGamma(vec4 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\nvec3 hx_linearToGamma(vec3 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\n/*float hx_sampleLinearDepth(sampler2D tex, vec2 uv)\n{\n return hx_RGBA8ToFloat(texture2D(tex, uv));\n}*/\n\nfloat hx_decodeLinearDepth(vec4 samp)\n{\n return hx_RG8ToFloat(samp.zw);\n}\n\nvec3 hx_getFrustumVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unprojNear = unprojectionMatrix * vec4(position, -1.0, 1.0);\n vec4 unprojFar = unprojectionMatrix * vec4(position, 1.0, 1.0);\n return unprojFar.xyz/unprojFar.w - unprojNear.xyz/unprojNear.w;\n}\n\n// view vector with z = 1, so we can use nearPlaneDist + linearDepth * (farPlaneDist - nearPlaneDist) as a scale factor to find view space position\nvec3 hx_getLinearDepthViewVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unproj = unprojectionMatrix * vec4(position, 0.0, 1.0);\n unproj /= unproj.w;\n return unproj.xyz / unproj.y;\n}\n\n// THIS IS FOR NON_LINEAR DEPTH!\nfloat hx_depthToViewY(float depth, mat4 projectionMatrix)\n{\n return projectionMatrix[3][2] / (depth * 2.0 - 1.0 - projectionMatrix[1][2]);\n}\n\nvec3 hx_getNormalSpecularReflectance(float metallicness, float insulatorNormalSpecularReflectance, vec3 color)\n{\n return mix(vec3(insulatorNormalSpecularReflectance), color, metallicness);\n}\n\nvec3 hx_fresnel(vec3 normalSpecularReflectance, vec3 lightDir, vec3 halfVector)\n{\n float cosAngle = 1.0 - max(dot(halfVector, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n return normalSpecularReflectance + (1.0 - normalSpecularReflectance) * power;\n}\n\n// https://seblagarde.wordpress.com/2011/08/17/hello-world/\nvec3 hx_fresnelProbe(vec3 normalSpecularReflectance, vec3 lightDir, vec3 normal, float roughness)\n{\n float cosAngle = 1.0 - max(dot(normal, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n float gloss = (1.0 - roughness) * (1.0 - roughness);\n vec3 bound = max(vec3(gloss), normalSpecularReflectance);\n return normalSpecularReflectance + (bound - normalSpecularReflectance) * power;\n}\n\n\nfloat hx_luminance(vec4 color)\n{\n return dot(color.xyz, vec3(.30, 0.59, .11));\n}\n\nfloat hx_luminance(vec3 color)\n{\n return dot(color, vec3(.30, 0.59, .11));\n}\n\n// linear variant of smoothstep\nfloat hx_linearStep(float lower, float upper, float x)\n{\n return clamp((x - lower) / (upper - lower), 0.0, 1.0);\n}\n\nvec4 hx_sampleDefaultDither(sampler2D ditherTexture, vec2 uv)\n{\n vec4 s = texture2D(ditherTexture, uv);\n\n #ifndef HX_FLOAT_TEXTURES\n s = s * 2.0 - 1.0;\n #endif\n\n return s;\n}\n\nvec3 hx_evaluateSH(vec3 sh[9], vec3 dir)\n{\n dir = dir.xzy;\n vec3 col = sh[0] +\n sh[1] * dir.y + sh[2] * dir.z + sh[3] * dir.x +\n sh[4] * dir.x * dir.y + sh[5] * dir.y * dir.z + sh[6] * (3.0 * dir.z * dir.z - 1.0) +\n sh[7] * dir.z * dir.x + sh[8] * (dir.x * dir.x - dir.y * dir.y);\n\n col = max(col, vec3(0.0));\n return col;\n}\n\n// I\'m keeping this for reference, even tho it doesn\'t work in iOS\nvoid hx_sumSH(in vec3 a[9], in float weight, inout vec3 b[9])\n{\n // have to manually unroll this, on some platforms the loop is weirdly slow\n b[0] += a[0] * weight;\n b[1] += a[1] * weight;\n b[2] += a[2] * weight;\n b[3] += a[3] * weight;\n b[4] += a[4] * weight;\n b[5] += a[5] * weight;\n b[6] += a[6] * weight;\n b[7] += a[7] * weight;\n b[8] += a[8] * weight;\n}\n\nvec3 hx_intersectCubeMap(vec3 rayOrigin, vec3 cubeCenter, vec3 rayDir, float cubeSize)\n{\n vec3 t = (cubeSize * sign(rayDir) - (rayOrigin - cubeCenter)) / rayDir;\n float minT = min(min(t.x, t.y), t.z);\n return rayOrigin + minT * rayDir;\n}\n\n// sadly, need a parameter due to a bug in Internet Explorer / Edge. Just pass in 0.\n#ifdef HX_USE_SKINNING_TEXTURE\n#define HX_RCP_MAX_SKELETON_JOINTS 1.0 / float(HX_MAX_SKELETON_JOINTS - 1)\nmat4 hx_getSkinningMatrixImpl(vec4 weights, vec4 indices, sampler2D tex)\n{\n mat4 m = mat4(0.0);\n for (int i = 0; i < 4; ++i) {\n mat4 t;\n float index = indices[i] * HX_RCP_MAX_SKELETON_JOINTS;\n t[0] = texture2D(tex, vec2(index, 0.0));\n t[1] = texture2D(tex, vec2(index, 0.5));\n t[2] = texture2D(tex, vec2(index, 1.0));\n t[3] = vec4(0.0, 0.0, 0.0, 1.0);\n m += weights[i] * t;\n }\n return m;\n}\n#define hx_getSkinningMatrix(v) hx_getSkinningMatrixImpl(hx_jointWeights, hx_jointIndices, hx_skinningTexture)\n#else\n#define hx_getSkinningMatrix(v) ( hx_jointWeights.x * mat4(hx_skinningMatrices[int(hx_jointIndices.x) * 3], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.y * mat4(hx_skinningMatrices[int(hx_jointIndices.y) * 3], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.z * mat4(hx_skinningMatrices[int(hx_jointIndices.z) * 3], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.w * mat4(hx_skinningMatrices[int(hx_jointIndices.w) * 3], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) )\n#endif'; - - ShaderLibrary._files['snippets_geometry.glsl'] = 'struct HX_GeometryData\n{\n vec4 color;\n vec3 normal;\n float metallicness;\n float normalSpecularReflectance;\n float roughness;\n float occlusion;\n vec3 emission;\n vec4 data; // this can be anything the lighting model requires\n #ifdef HX_USE_TRANSLUCENCY\n vec3 translucency;\n #endif\n};'; - - ShaderLibrary._files['snippets_reproject.glsl'] = '#ifdef HX_MOTION_VECTORS\nuniform sampler2D hx_motionVectorBuffer;\n#else\nuniform sampler2D hx_normalDepthBuffer;\nuniform float hx_cameraNearPlaneDistance;\nuniform float hx_cameraFrustumRange;\nuniform mat4 hx_inverseProjectionMatrix;\nuniform mat4 hx_cameraWorldMatrix;\nuniform mat4 hx_prevViewProjectionMatrix;\nuniform vec2 hx_cameraJitter;\n#endif\n\n\nvec2 hx_getMotionVector(vec2 uv)\n{\n#ifdef HX_MOTION_VECTORS\n return hx_decodeMotionVector(texture2D(hx_motionVectorBuffer, uv));\n#else\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n float depth = hx_decodeLinearDepth(normalDepth);\n float absViewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n\n // unproject any point on the view ray to view space:\n vec2 ndc = uv * 2.0 - 1.0;\n // view projection matrix is jittered, so hx_inverseProjectionMatrix will \"unjitter\"\n // so we need to reapply the jitter to counter this\n vec3 viewDir = hx_getLinearDepthViewVector(ndc + hx_cameraJitter, hx_inverseProjectionMatrix);\n\n // reconstruct world position based on linear depth\n vec3 viewPos = viewDir * absViewY;\n vec4 worldPos = hx_cameraWorldMatrix * vec4(viewPos, 1.0);\n\n // reproject with previous frame matrix\n vec4 oldProj = hx_prevViewProjectionMatrix * worldPos;\n return (ndc - oldProj.xy / oldProj.w) * .5;\n#endif\n}\n\nvec2 hx_getPreviousFrameUV(vec2 currentUV)\n{\n return currentUV - hx_getMotionVector(currentUV);\n}'; - - ShaderLibrary._files['snippets_tonemap.glsl'] = 'varying_in vec2 uv;\n\n#ifdef HX_ADAPTIVE\nuniform sampler2D hx_luminanceMap;\nuniform float hx_luminanceMipLevel;\n#endif\n\nuniform float hx_exposure;\nuniform float hx_key;\n\nuniform sampler2D hx_backBuffer;\n\n\nvec4 hx_getToneMapScaledColor()\n{\n #ifdef HX_ADAPTIVE\n #ifdef HX_GLSL_300_ES\n float referenceLuminance = textureLod(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #else\n float referenceLuminance = texture2DLodEXT(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #endif\n referenceLuminance = exp(referenceLuminance) - 1.0;\n referenceLuminance = clamp(referenceLuminance, .08, 1000.0);\n float exposure = hx_key / referenceLuminance * hx_exposure;\n #else\n float exposure = hx_exposure;\n #endif\n return texture2D(hx_backBuffer, uv) * exposure;\n}'; - ShaderLibrary._files['ao_blur_fragment.glsl'] = 'varying_in vec2 uv1;\nvarying_in vec2 uv2;\nvarying_in vec2 uv3;\nvarying_in vec2 uv4;\n\nuniform sampler2D source;\n\nvoid main()\n{\n vec4 total = texture2D(source, uv1) + texture2D(source, uv2) + texture2D(source, uv3) + texture2D(source, uv4);\n hx_FragColor = total * .25;\n}'; ShaderLibrary._files['ao_blur_vertex.glsl'] = 'vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nvarying_out vec2 uv1;\nvarying_out vec2 uv2;\nvarying_out vec2 uv3;\nvarying_out vec2 uv4;\n\nuniform vec2 pixelSize;\n\nvoid main()\n{\n uv1 = hx_texCoord + vec2(-1.5, .5) * pixelSize;\n uv2 = hx_texCoord + vec2(.5, .5) * pixelSize;\n uv3 = hx_texCoord + vec2(.5, -1.5) * pixelSize;\n uv4 = hx_texCoord + vec2(-1.5, -1.5) * pixelSize;\n gl_Position = hx_position;\n}'; @@ -27061,7 +27060,7 @@ ShaderLibrary.get("taa_fragment.glsl") ); this._pass.setTexture("historyBuffer", this._historyTexture); - this.alpha = .01; + this.alpha = .1; this.gamma = 1.0; } diff --git a/build/helix.min.js b/build/helix.min.js index 8644f651..0cb27dff 100644 --- a/build/helix.min.js +++ b/build/helix.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define("HX",["exports"],e):e(t.HX={})}(this,function(t){"use strict";var c="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var e,i,n=(function(t,e){t.exports=function(){var t,e,i="undefined"!=typeof window?window:void 0!==c?c:"undefined"!=typeof self?self:{},n=function(){return/Android/i.test(navigator.userAgent)||/iPhone|iPad|iPod/i.test(navigator.userAgent)},s=function(t,e){for(var i=0,n=t.length;it.TEXTURE31){console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"),n.push(null,null);break}s||(s=t.getParameter(t.ACTIVE_TEXTURE)),t.activeTexture(a),n.push(t.getParameter(o),null);break;case t.ACTIVE_TEXTURE:s=t.getParameter(t.ACTIVE_TEXTURE),n.push(null);break;default:n.push(t.getParameter(o))}}i(t);for(var r=0;rt.TEXTURE31)break;t.activeTexture(a),t.bindTexture(t.TEXTURE_2D,h);break;case t.TEXTURE_BINDING_CUBE_MAP:var a=e[++r];if(at.TEXTURE31)break;t.activeTexture(a),t.bindTexture(t.TEXTURE_CUBE_MAP,h);break;case t.VIEWPORT:t.viewport(h[0],h[1],h[2],h[3]);break;case t.BLEND:case t.CULL_FACE:case t.DEPTH_TEST:case t.SCISSOR_TEST:case t.STENCIL_TEST:h?t.enable(o):t.disable(o);break;default:console.log("No GL restore behavior for 0x"+o.toString(16))}s&&t.activeTexture(s)}}else i(t)},S=["attribute vec2 position;","attribute vec3 texCoord;","varying vec2 vTexCoord;","uniform vec4 viewportOffsetScale[2];","void main() {"," vec4 viewport = viewportOffsetScale[int(texCoord.z)];"," vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;"," gl_Position = vec4( position, 1.0, 1.0 );","}"].join("\n"),O=["precision mediump float;","uniform sampler2D diffuse;","varying vec2 vTexCoord;","void main() {"," gl_FragColor = texture2D(diffuse, vTexCoord);","}"].join("\n");function C(t,e,i,n){this.gl=t,this.cardboardUI=e,this.bufferScale=i,this.dirtySubmitFrameBindings=n,this.ctxAttribs=t.getContextAttributes(),this.meshWidth=20,this.meshHeight=20,this.bufferWidth=t.drawingBufferWidth,this.bufferHeight=t.drawingBufferHeight,this.realBindFramebuffer=t.bindFramebuffer,this.realEnable=t.enable,this.realDisable=t.disable,this.realColorMask=t.colorMask,this.realClearColor=t.clearColor,this.realViewport=t.viewport,c()||(this.realCanvasWidth=Object.getOwnPropertyDescriptor(t.canvas.__proto__,"width"),this.realCanvasHeight=Object.getOwnPropertyDescriptor(t.canvas.__proto__,"height")),this.isPatched=!1,this.lastBoundFramebuffer=null,this.cullFace=!1,this.depthTest=!1,this.blend=!1,this.scissorTest=!1,this.stencilTest=!1,this.viewport=[0,0,0,0],this.colorMask=[!0,!0,!0,!0],this.clearColor=[0,0,0,0],this.attribs={position:0,texCoord:1},this.program=A(t,S,O,this.attribs),this.uniforms=x(t,this.program),this.viewportOffsetScale=new Float32Array(8),this.setTextureBounds(),this.vertexBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),this.indexCount=0,this.renderTarget=t.createTexture(),this.framebuffer=t.createFramebuffer(),this.depthStencilBuffer=null,this.depthBuffer=null,this.stencilBuffer=null,this.ctxAttribs.depth&&this.ctxAttribs.stencil?this.depthStencilBuffer=t.createRenderbuffer():this.ctxAttribs.depth?this.depthBuffer=t.createRenderbuffer():this.ctxAttribs.stencil&&(this.stencilBuffer=t.createRenderbuffer()),this.patch(),this.onResize()}C.prototype.destroy=function(){var t=this.gl;this.unpatch(),t.deleteProgram(this.program),t.deleteBuffer(this.vertexBuffer),t.deleteBuffer(this.indexBuffer),t.deleteTexture(this.renderTarget),t.deleteFramebuffer(this.framebuffer),this.depthStencilBuffer&&t.deleteRenderbuffer(this.depthStencilBuffer),this.depthBuffer&&t.deleteRenderbuffer(this.depthBuffer),this.stencilBuffer&&t.deleteRenderbuffer(this.stencilBuffer),this.cardboardUI&&this.cardboardUI.destroy()},C.prototype.onResize=function(){var t=this.gl,e=this,i=[t.RENDERBUFFER_BINDING,t.TEXTURE_BINDING_2D,t.TEXTURE0];v(t,i,function(t){e.realBindFramebuffer.call(t,t.FRAMEBUFFER,null),e.scissorTest&&e.realDisable.call(t,t.SCISSOR_TEST),e.realColorMask.call(t,!0,!0,!0,!0),e.realViewport.call(t,0,0,t.drawingBufferWidth,t.drawingBufferHeight),e.realClearColor.call(t,0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),e.realBindFramebuffer.call(t,t.FRAMEBUFFER,e.framebuffer),t.bindTexture(t.TEXTURE_2D,e.renderTarget),t.texImage2D(t.TEXTURE_2D,0,e.ctxAttribs.alpha?t.RGBA:t.RGB,e.bufferWidth,e.bufferHeight,0,e.ctxAttribs.alpha?t.RGBA:t.RGB,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e.renderTarget,0),e.ctxAttribs.depth&&e.ctxAttribs.stencil?(t.bindRenderbuffer(t.RENDERBUFFER,e.depthStencilBuffer),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,e.bufferWidth,e.bufferHeight),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,e.depthStencilBuffer)):e.ctxAttribs.depth?(t.bindRenderbuffer(t.RENDERBUFFER,e.depthBuffer),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_COMPONENT16,e.bufferWidth,e.bufferHeight),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.RENDERBUFFER,e.depthBuffer)):e.ctxAttribs.stencil&&(t.bindRenderbuffer(t.RENDERBUFFER,e.stencilBuffer),t.renderbufferStorage(t.RENDERBUFFER,t.STENCIL_INDEX8,e.bufferWidth,e.bufferHeight),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.STENCIL_ATTACHMENT,t.RENDERBUFFER,e.stencilBuffer)),!t.checkFramebufferStatus(t.FRAMEBUFFER)===t.FRAMEBUFFER_COMPLETE&&console.error("Framebuffer incomplete!"),e.realBindFramebuffer.call(t,t.FRAMEBUFFER,e.lastBoundFramebuffer),e.scissorTest&&e.realEnable.call(t,t.SCISSOR_TEST),e.realColorMask.apply(t,e.colorMask),e.realViewport.apply(t,e.viewport),e.realClearColor.apply(t,e.clearColor)}),this.cardboardUI&&this.cardboardUI.onResize()},C.prototype.patch=function(){if(!this.isPatched){var s=this,e=this.gl.canvas,r=this.gl;c()||(e.width=g()*this.bufferScale,e.height=M()*this.bufferScale,Object.defineProperty(e,"width",{configurable:!0,enumerable:!0,get:function(){return s.bufferWidth},set:function(t){s.bufferWidth=t,s.realCanvasWidth.set.call(e,t),s.onResize()}}),Object.defineProperty(e,"height",{configurable:!0,enumerable:!0,get:function(){return s.bufferHeight},set:function(t){s.bufferHeight=t,s.realCanvasHeight.set.call(e,t),s.onResize()}})),this.lastBoundFramebuffer=r.getParameter(r.FRAMEBUFFER_BINDING),null==this.lastBoundFramebuffer&&(this.lastBoundFramebuffer=this.framebuffer,this.gl.bindFramebuffer(r.FRAMEBUFFER,this.framebuffer)),this.gl.bindFramebuffer=function(t,e){s.lastBoundFramebuffer=e||s.framebuffer,s.realBindFramebuffer.call(r,t,s.lastBoundFramebuffer)},this.cullFace=r.getParameter(r.CULL_FACE),this.depthTest=r.getParameter(r.DEPTH_TEST),this.blend=r.getParameter(r.BLEND),this.scissorTest=r.getParameter(r.SCISSOR_TEST),this.stencilTest=r.getParameter(r.STENCIL_TEST),r.enable=function(t){switch(t){case r.CULL_FACE:s.cullFace=!0;break;case r.DEPTH_TEST:s.depthTest=!0;break;case r.BLEND:s.blend=!0;break;case r.SCISSOR_TEST:s.scissorTest=!0;break;case r.STENCIL_TEST:s.stencilTest=!0}s.realEnable.call(r,t)},r.disable=function(t){switch(t){case r.CULL_FACE:s.cullFace=!1;break;case r.DEPTH_TEST:s.depthTest=!1;break;case r.BLEND:s.blend=!1;break;case r.SCISSOR_TEST:s.scissorTest=!1;break;case r.STENCIL_TEST:s.stencilTest=!1}s.realDisable.call(r,t)},this.colorMask=r.getParameter(r.COLOR_WRITEMASK),r.colorMask=function(t,e,i,n){s.colorMask[0]=t,s.colorMask[1]=e,s.colorMask[2]=i,s.colorMask[3]=n,s.realColorMask.call(r,t,e,i,n)},this.clearColor=r.getParameter(r.COLOR_CLEAR_VALUE),r.clearColor=function(t,e,i,n){s.clearColor[0]=t,s.clearColor[1]=e,s.clearColor[2]=i,s.clearColor[3]=n,s.realClearColor.call(r,t,e,i,n)},this.viewport=r.getParameter(r.VIEWPORT),r.viewport=function(t,e,i,n){s.viewport[0]=t,s.viewport[1]=e,s.viewport[2]=i,s.viewport[3]=n,s.realViewport.call(r,t,e,i,n)},this.isPatched=!0,D(e)}},C.prototype.unpatch=function(){if(this.isPatched){var t=this.gl,e=this.gl.canvas;c()||(Object.defineProperty(e,"width",this.realCanvasWidth),Object.defineProperty(e,"height",this.realCanvasHeight)),e.width=this.bufferWidth,e.height=this.bufferHeight,t.bindFramebuffer=this.realBindFramebuffer,t.enable=this.realEnable,t.disable=this.realDisable,t.colorMask=this.realColorMask,t.clearColor=this.realClearColor,t.viewport=this.realViewport,this.lastBoundFramebuffer==this.framebuffer&&t.bindFramebuffer(t.FRAMEBUFFER,null),this.isPatched=!1,setTimeout(function(){D(e)},1)}},C.prototype.setTextureBounds=function(t,e){t||(t=[0,0,.5,1]),e||(e=[.5,0,.5,1]),this.viewportOffsetScale[0]=t[0],this.viewportOffsetScale[1]=t[1],this.viewportOffsetScale[2]=t[2],this.viewportOffsetScale[3]=t[3],this.viewportOffsetScale[4]=e[0],this.viewportOffsetScale[5]=e[1],this.viewportOffsetScale[6]=e[2],this.viewportOffsetScale[7]=e[3]},C.prototype.submitFrame=function(){var t=this.gl,e=this,i=[];if(this.dirtySubmitFrameBindings||i.push(t.CURRENT_PROGRAM,t.ARRAY_BUFFER_BINDING,t.ELEMENT_ARRAY_BUFFER_BINDING,t.TEXTURE_BINDING_2D,t.TEXTURE0),v(t,i,function(t){e.realBindFramebuffer.call(t,t.FRAMEBUFFER,null),e.cullFace&&e.realDisable.call(t,t.CULL_FACE),e.depthTest&&e.realDisable.call(t,t.DEPTH_TEST),e.blend&&e.realDisable.call(t,t.BLEND),e.scissorTest&&e.realDisable.call(t,t.SCISSOR_TEST),e.stencilTest&&e.realDisable.call(t,t.STENCIL_TEST),e.realColorMask.call(t,!0,!0,!0,!0),e.realViewport.call(t,0,0,t.drawingBufferWidth,t.drawingBufferHeight),(e.ctxAttribs.alpha||c())&&(e.realClearColor.call(t,0,0,0,1),t.clear(t.COLOR_BUFFER_BIT)),t.useProgram(e.program),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,e.indexBuffer),t.bindBuffer(t.ARRAY_BUFFER,e.vertexBuffer),t.enableVertexAttribArray(e.attribs.position),t.enableVertexAttribArray(e.attribs.texCoord),t.vertexAttribPointer(e.attribs.position,2,t.FLOAT,!1,20,0),t.vertexAttribPointer(e.attribs.texCoord,3,t.FLOAT,!1,20,8),t.activeTexture(t.TEXTURE0),t.uniform1i(e.uniforms.diffuse,0),t.bindTexture(t.TEXTURE_2D,e.renderTarget),t.uniform4fv(e.uniforms.viewportOffsetScale,e.viewportOffsetScale),t.drawElements(t.TRIANGLES,e.indexCount,t.UNSIGNED_SHORT,0),e.cardboardUI&&e.cardboardUI.renderNoState(),e.realBindFramebuffer.call(e.gl,t.FRAMEBUFFER,e.framebuffer),e.ctxAttribs.preserveDrawingBuffer||(e.realClearColor.call(t,0,0,0,0),t.clear(t.COLOR_BUFFER_BIT)),e.dirtySubmitFrameBindings||e.realBindFramebuffer.call(t,t.FRAMEBUFFER,e.lastBoundFramebuffer),e.cullFace&&e.realEnable.call(t,t.CULL_FACE),e.depthTest&&e.realEnable.call(t,t.DEPTH_TEST),e.blend&&e.realEnable.call(t,t.BLEND),e.scissorTest&&e.realEnable.call(t,t.SCISSOR_TEST),e.stencilTest&&e.realEnable.call(t,t.STENCIL_TEST),e.realColorMask.apply(t,e.colorMask),e.realViewport.apply(t,e.viewport),!e.ctxAttribs.alpha&&e.ctxAttribs.preserveDrawingBuffer||e.realClearColor.apply(t,e.clearColor)}),c()){var n=t.canvas;n.width==e.bufferWidth&&n.height==e.bufferHeight||(e.bufferWidth=n.width,e.bufferHeight=n.height,e.onResize())}},C.prototype.updateDeviceInfo=function(n){var t=this.gl,s=this,e=[t.ARRAY_BUFFER_BINDING,t.ELEMENT_ARRAY_BUFFER_BINDING];v(t,e,function(t){var e=s.computeMeshVertices_(s.meshWidth,s.meshHeight,n);if(t.bindBuffer(t.ARRAY_BUFFER,s.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),!s.indexCount){var i=s.computeMeshIndices_(s.meshWidth,s.meshHeight);t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,s.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,i,t.STATIC_DRAW),s.indexCount=i.length}})},C.prototype.computeMeshVertices_=function(t,e,i){for(var n=new Float32Array(2*t*e*5),s=i.getLeftEyeVisibleTanAngles(),r=i.getLeftEyeNoLensTanAngles(),o=i.getLeftEyeVisibleScreenRect(r),a=0,h=0;h<2;h++){for(var u=0;ue-42&&t.clientXs.clientHeight-42?i(t):t.clientX<42&&t.clientY<42&&n(t)},s.addEventListener("click",this.listener,!1)},z.prototype.onResize=function(){var t=this.gl,p=this,e=[t.ARRAY_BUFFER_BINDING];v(t,e,function(i){var r=[],o=i.drawingBufferWidth/2,t=Math.max(screen.width,screen.height)*window.devicePixelRatio,e=i.drawingBufferWidth/t,n=e*window.devicePixelRatio,s=4*n/2,a=42*n,h=28*n/2,u=14*n;function l(t,e){var i=(90-t)*b,n=Math.cos(i),s=Math.sin(i);r.push(.3125*n*h+o,.3125*s*h+h),r.push(e*n*h+o,e*s*h+h)}r.push(o-s,a),r.push(o-s,i.drawingBufferHeight),r.push(o+s,a),r.push(o+s,i.drawingBufferHeight),p.gearOffset=r.length/2;for(var c=0;c<=6;c++){var _=60*c;l(_,1),l(_+12,1),l(_+20,.75),l(_+40,.75),l(_+48,1)}function d(t,e){r.push(u+t,i.drawingBufferHeight-u-e)}p.gearVertexCount=r.length/2-p.gearOffset,p.arrowOffset=r.length/2;var f=s/Math.sin(45*b);d(0,h),d(h,0),d(h+f,f),d(f,h+f),d(f,h-f),d(0,h),d(h,2*h),d(h+f,2*h-f),d(f,h-f),d(0,h),d(f,h-s),d(28*n,h-s),d(f,h+s),d(28*n,h+s),p.arrowVertexCount=r.length/2-p.arrowOffset,i.bindBuffer(i.ARRAY_BUFFER,p.vertexBuffer),i.bufferData(i.ARRAY_BUFFER,new Float32Array(r),i.STATIC_DRAW)})},z.prototype.render=function(){var t=this.gl,e=this,i=[t.CULL_FACE,t.DEPTH_TEST,t.BLEND,t.SCISSOR_TEST,t.STENCIL_TEST,t.COLOR_WRITEMASK,t.VIEWPORT,t.CURRENT_PROGRAM,t.ARRAY_BUFFER_BINDING];v(t,i,function(t){t.disable(t.CULL_FACE),t.disable(t.DEPTH_TEST),t.disable(t.BLEND),t.disable(t.SCISSOR_TEST),t.disable(t.STENCIL_TEST),t.colorMask(!0,!0,!0,!0),t.viewport(0,0,t.drawingBufferWidth,t.drawingBufferHeight),e.renderNoState()})},z.prototype.renderNoState=function(){var t,e,i,n,s,r,o,a,h,u,l=this.gl;l.useProgram(this.program),l.bindBuffer(l.ARRAY_BUFFER,this.vertexBuffer),l.enableVertexAttribArray(this.attribs.position),l.vertexAttribPointer(this.attribs.position,2,l.FLOAT,!1,8,0),l.uniform4f(this.uniforms.color,1,1,1,1),t=this.projMat,e=0,i=l.drawingBufferWidth,n=0,s=l.drawingBufferHeight,a=1/(e-i),h=1/(n-s),u=1/((r=.1)-(o=1024)),t[0]=-2*a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*u,t[11]=0,t[12]=(e+i)*a,t[13]=(s+n)*h,t[14]=(o+r)*u,t[15]=1,l.uniformMatrix4fv(this.uniforms.projectionMat,!1,this.projMat),l.drawArrays(l.TRIANGLE_STRIP,0,4),l.drawArrays(l.TRIANGLE_STRIP,this.gearOffset,this.gearVertexCount),l.drawArrays(l.TRIANGLE_STRIP,this.arrowOffset,this.arrowVertexCount)},R.prototype.distortInverse=function(t){for(var e=0,i=1,n=t-this.distort(e);1e-4Math.abs(t.z)?k.set(-t.y,t.x,0):k.set(0,-t.z,t.y)):k.crossVectors(t,e),this.x=k.x,this.y=k.y,this.z=k.z,this.w=Y,this.normalize(),this}};var V=new G({widthMeters:.11,heightMeters:.062,bevelMeters:.004}),X=new G({widthMeters:.1038,heightMeters:.0584,bevelMeters:.004}),H={CardboardV1:new Z({id:"CardboardV1",label:"Cardboard I/O 2014",fov:40,interLensDistance:.06,baselineLensDistance:.035,screenLensDistance:.042,distortionCoefficients:[.441,.156],inverseCoefficients:[-.4410035,.42756155,-.4804439,.5460139,-.58821183,.5733938,-.48303202,.33299083,-.17573841,.0651772,-.01488963,.001559834]}),CardboardV2:new Z({id:"CardboardV2",label:"Cardboard I/O 2015",fov:60,interLensDistance:.064,baselineLensDistance:.035,screenLensDistance:.039,distortionCoefficients:[.34,.55],inverseCoefficients:[-.33836704,-.18162185,.862655,-1.2462051,1.0560602,-.58208317,.21609078,-.05444823,.009177956,-.0009904169,6183535e-11,-16981803e-13]})};function W(t,e){this.viewer=H.CardboardV2,this.updateDeviceParams(t),this.distortion=new R(this.viewer.distortionCoefficients);for(var i=0;i 1"),0):2*Math.acos(n.w)),this.estimatedGravity.x.toFixed(1),this.estimatedGravity.y.toFixed(1),this.estimatedGravity.z.toFixed(1),this.measuredGravity.x.toFixed(1),this.measuredGravity.y.toFixed(1),this.measuredGravity.z.toFixed(1));var r=new Q;r.copy(this.filterQ),r.multiply(s),this.filterQ.slerp(r,1-this.kFilter),this.previousFilterQ.copy(this.filterQ)},tt.prototype.getOrientation=function(){return this.filterQ},tt.prototype.accelToQuaternion_=function(t){var e=new F;e.copy(t),e.normalize();var i=new Q;return i.setFromUnitVectors(new F(0,0,-1),e),i.inverse(),i},tt.prototype.gyroToQuaternionDelta_=function(t,e){var i=new Q,n=new F;return n.copy(t),n.normalize(),i.setFromAxisAngle(n,t.length()*e),i},et.prototype.getPrediction=function(t,e,i){if(!this.previousTimestampS)return this.previousQ.copy(t),this.previousTimestampS=i,t;var n=new F;n.copy(e),n.normalize();var s=e.length();if(s<20*U)return this.isDebug&&console.log("Moving slowly, at %s deg/s: no prediction",(B*s).toFixed(1)),this.outQ.copy(t),this.previousQ.copy(t),this.outQ;var r=s*this.predictionTimeS;return this.deltaQ.setFromAxisAngle(n,r),this.outQ.copy(this.previousQ),this.outQ.multiply(this.deltaQ),this.previousQ.copy(t),this.previousTimestampS=i,this.outQ},it.prototype.getPosition=function(){return null},it.prototype.getOrientation=function(){var t=void 0;if(this.isWithoutDeviceMotion&&this._deviceOrientationQ){this.deviceOrientationFixQ=this.deviceOrientationFixQ||(n=(new Q).setFromAxisAngle(new F(0,0,-1),0),s=new Q,-90===window.orientation?s.setFromAxisAngle(new F(0,1,0),Math.PI/-2):s.setFromAxisAngle(new F(0,1,0),Math.PI/2),n.multiply(s)),this.deviceOrientationFilterToWorldQ=this.deviceOrientationFilterToWorldQ||((i=new Q).setFromAxisAngle(new F(1,0,0),-Math.PI/2),i),t=this._deviceOrientationQ;var e=new Q;return e.copy(t),e.multiply(this.deviceOrientationFilterToWorldQ),e.multiply(this.resetQ),e.multiply(this.worldToScreenQ),e.multiplyQuaternions(this.deviceOrientationFixQ,e),this.yawOnly&&(e.x=0,e.z=0,e.normalize()),this.orientationOut_[0]=e.x,this.orientationOut_[1]=e.y,this.orientationOut_[2]=e.z,this.orientationOut_[3]=e.w,this.orientationOut_}var i,n,s,r=this.filter.getOrientation();t=this.posePredictor.getPrediction(r,this.gyroscope,this.previousTimestampS);var e=new Q;return e.copy(this.filterToWorldQ),e.multiply(this.resetQ),e.multiply(t),e.multiply(this.worldToScreenQ),this.yawOnly&&(e.x=0,e.z=0,e.normalize()),this.orientationOut_[0]=e.x,this.orientationOut_[1]=e.y,this.orientationOut_[2]=e.z,this.orientationOut_[3]=e.w,this.orientationOut_},it.prototype.resetPose=function(){this.resetQ.copy(this.filter.getOrientation()),this.resetQ.x=0,this.resetQ.y=0,this.resetQ.z*=-1,this.resetQ.normalize(),p()&&this.resetQ.multiply(this.inverseWorldToScreenQ),this.resetQ.multiply(this.originalPoseAdjustQ)},it.prototype.onDeviceOrientation_=function(t){this._deviceOrientationQ=this._deviceOrientationQ||new Q;var e=t.alpha,i=t.beta,n=t.gamma;e=(e||0)*Math.PI/180,i=(i||0)*Math.PI/180,n=(n||0)*Math.PI/180,this._deviceOrientationQ.setFromEulerYXZ(i,e,-n)},it.prototype.onDeviceMotion_=function(t){this.updateDeviceMotion_(t)},it.prototype.updateDeviceMotion_=function(t){var e=t.accelerationIncludingGravity,i=t.rotationRate,n=t.timeStamp/1e3,s=n-this.previousTimestampS;return s<0?L("fusion-pose-sensor:invalid:non-monotonic","Invalid timestamps detected: non-monotonic timestamp from devicemotion"):s<=.001||1l.capabilities.maxLayers)t(new Error("Invalid number of layers."));else{var i=h[0];if(i.source){var n=i.leftBounds||mt,s=i.rightBounds||At;if(u){var r=l.layer_;r.source!==i.source&&(r.source=i.source);for(var o=0;o<4;o++)r.leftBounds[o]=n[o],r.rightBounds[o]=s[o];return l.wrapForFullscreen(l.layer_.source),l.updatePresent_(),void e()}if(l.layer_={predistorted:i.predistorted,source:i.source,leftBounds:n.slice(0),rightBounds:s.slice(0)},l.waitingForPresent_=!1,l.layer_&&l.layer_.source){var a=l.wrapForFullscreen(l.layer_.source);l.addFullscreenListeners_(a,function(){var t=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;l.isPresenting=a===t,l.isPresenting?(screen.orientation&&screen.orientation.lock&&screen.orientation.lock("landscape-primary").catch(function(t){console.error("screen.orientation.lock() failed due to",t.message)}),l.waitingForPresent_=!1,l.beginPresent_(),e()):(screen.orientation&&screen.orientation.unlock&&screen.orientation.unlock(),l.removeFullscreenWrapper(),l.disableWakeLock(),l.endPresent_(),l.removeFullscreenListeners_()),l.fireVRDisplayPresentChange_()},function(){l.waitingForPresent_&&(l.removeFullscreenWrapper(),l.removeFullscreenListeners_(),l.disableWakeLock(),l.waitingForPresent_=!1,l.isPresenting=!1,t(new Error("Unable to present.")))}),function(t){if(_())return!1;if(t.requestFullscreen)t.requestFullscreen();else if(t.webkitRequestFullscreen)t.webkitRequestFullscreen();else if(t.mozRequestFullScreen)t.mozRequestFullScreen();else{if(!t.msRequestFullscreen)return!1;t.msRequestFullscreen()}return!0}(a)?(l.enableWakeLock(),l.waitingForPresent_=!0):(c()||_())&&(l.enableWakeLock(),l.isPresenting=!0,l.beginPresent_(),l.fireVRDisplayPresentChange_(),e())}l.waitingForPresent_||c()||(m(),t(new Error("Unable to present.")))}else e()}else t(new Error("VRDisplay is not capable of presenting."))})},Nt.prototype.exitPresent=function(){var i=this.isPresenting,n=this;return this.isPresenting=!1,this.layer_=null,this.disableWakeLock(),new Promise(function(t,e){i?(!m()&&c()&&(n.endPresent_(),n.fireVRDisplayPresentChange_()),_()&&(n.removeFullscreenWrapper(),n.removeFullscreenListeners_(),n.endPresent_(),n.fireVRDisplayPresentChange_()),t()):e(new Error("Was not presenting to VRDisplay."))})},Nt.prototype.getLayers=function(){return this.layer_?[this.layer_]:[]},Nt.prototype.fireVRDisplayPresentChange_=function(){var t=new CustomEvent("vrdisplaypresentchange",{detail:{display:this}});window.dispatchEvent(t)},Nt.prototype.fireVRDisplayConnect_=function(){var t=new CustomEvent("vrdisplayconnect",{detail:{display:this}});window.dispatchEvent(t)},Nt.prototype.addFullscreenListeners_=function(t,e,i){this.removeFullscreenListeners_(),this.fullscreenEventTarget_=t,this.fullscreenChangeHandler_=e,this.fullscreenErrorHandler_=i,e&&(document.fullscreenEnabled?t.addEventListener("fullscreenchange",e,!1):document.webkitFullscreenEnabled?t.addEventListener("webkitfullscreenchange",e,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenchange",e,!1):document.msFullscreenEnabled&&t.addEventListener("msfullscreenchange",e,!1)),i&&(document.fullscreenEnabled?t.addEventListener("fullscreenerror",i,!1):document.webkitFullscreenEnabled?t.addEventListener("webkitfullscreenerror",i,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenerror",i,!1):document.msFullscreenEnabled&&t.addEventListener("msfullscreenerror",i,!1))},Nt.prototype.removeFullscreenListeners_=function(){if(this.fullscreenEventTarget_){var t=this.fullscreenEventTarget_;if(this.fullscreenChangeHandler_){var e=this.fullscreenChangeHandler_;t.removeEventListener("fullscreenchange",e,!1),t.removeEventListener("webkitfullscreenchange",e,!1),document.removeEventListener("mozfullscreenchange",e,!1),t.removeEventListener("msfullscreenchange",e,!1)}if(this.fullscreenErrorHandler_){var i=this.fullscreenErrorHandler_;t.removeEventListener("fullscreenerror",i,!1),t.removeEventListener("webkitfullscreenerror",i,!1),document.removeEventListener("mozfullscreenerror",i,!1),t.removeEventListener("msfullscreenerror",i,!1)}this.fullscreenEventTarget_=null,this.fullscreenChangeHandler_=null,this.fullscreenErrorHandler_=null}},Nt.prototype.enableWakeLock=function(){this.wakelock_&&this.wakelock_.enable()},Nt.prototype.disableWakeLock=function(){this.wakelock_&&this.wakelock_.disable()},Nt.prototype.beginPresent_=function(){},Nt.prototype.endPresent_=function(){},Nt.prototype.submitFrame=function(t){};var Dt={ADDITIONAL_VIEWERS:[],DEFAULT_VIEWER:"",MOBILE_WAKE_LOCK:!0,DEBUG:(Nt.prototype.getEyeParameters=function(t){return null},!1),DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1},Et={LEFT:"left",RIGHT:"right"};function wt(t){var e=N({},Dt);t=N(e,t||{}),Nt.call(this,{wakelock:t.MOBILE_WAKE_LOCK}),this.config=t,this.displayName="Cardboard VRDisplay",this.capabilities=new Tt({hasPosition:!1,hasOrientation:!0,hasExternalDisplay:!1,canPresent:!0,maxLayers:1}),this.stageParameters=null,this.bufferScale_=this.config.BUFFER_SCALE,this.poseSensor_=new ot(this.config),this.distorter_=null,this.cardboardUI_=null,this.dpdb_=new K(this.config.DPDB_URL,this.onDeviceParamsUpdated_.bind(this)),this.deviceInfo_=new W(this.dpdb_.getDeviceParams(),t.ADDITIONAL_VIEWERS),this.viewerSelector_=new lt(t.DEFAULT_VIEWER),this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)),this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()),this.config.ROTATE_INSTRUCTIONS_DISABLED||(this.rotateInstructions_=new at),c()&&window.addEventListener("resize",this.onResize_.bind(this))}return(wt.prototype=Object.create(Nt.prototype))._getPose=function(){return{position:null,orientation:this.poseSensor_.getOrientation(),linearVelocity:null,linearAcceleration:null,angularVelocity:null,angularAcceleration:null}},wt.prototype._resetPose=function(){this.poseSensor_.resetPose&&this.poseSensor_.resetPose()},wt.prototype._getFieldOfView=function(t){var e;if(t==Et.LEFT)e=this.deviceInfo_.getFieldOfViewLeftEye();else{if(t!=Et.RIGHT)return console.error("Invalid eye provided: %s",t),null;e=this.deviceInfo_.getFieldOfViewRightEye()}return e},wt.prototype._getEyeOffset=function(t){var e;if(t==Et.LEFT)e=[.5*-this.deviceInfo_.viewer.interLensDistance,0,0];else{if(t!=Et.RIGHT)return console.error("Invalid eye provided: %s",t),null;e=[.5*this.deviceInfo_.viewer.interLensDistance,0,0]}return e},wt.prototype.getEyeParameters=function(t){var e=this._getEyeOffset(t),i=this._getFieldOfView(t),n={offset:e,renderWidth:.5*this.deviceInfo_.device.width*this.bufferScale_,renderHeight:this.deviceInfo_.device.height*this.bufferScale_};return Object.defineProperty(n,"fieldOfView",{enumerable:!0,get:function(){return I("VRFieldOfView","VRFrameData's projection matrices"),i}}),n},wt.prototype.onDeviceParamsUpdated_=function(t){this.config.DEBUG&&console.log("DPDB reported that device params were updated."),this.deviceInfo_.updateDeviceParams(t),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_)},wt.prototype.updateBounds_=function(){this.layer_&&this.distorter_&&(this.layer_.leftBounds||this.layer_.rightBounds)&&this.distorter_.setTextureBounds(this.layer_.leftBounds,this.layer_.rightBounds)},wt.prototype.beginPresent_=function(){var t=this.layer_.source.getContext("webgl");t||(t=this.layer_.source.getContext("experimental-webgl")),t||(t=this.layer_.source.getContext("webgl2")),t&&(this.layer_.predistorted?this.config.CARDBOARD_UI_DISABLED||(t.canvas.width=g()*this.bufferScale_,t.canvas.height=M()*this.bufferScale_,this.cardboardUI_=new z(t)):(this.config.CARDBOARD_UI_DISABLED||(this.cardboardUI_=new z(t)),this.distorter_=new C(t,this.cardboardUI_,this.config.BUFFER_SCALE,this.config.DIRTY_SUBMIT_FRAME_BINDINGS),this.distorter_.updateDeviceInfo(this.deviceInfo_)),this.cardboardUI_&&this.cardboardUI_.listen(function(t){this.viewerSelector_.show(this.layer_.source.parentElement),t.stopPropagation(),t.preventDefault()}.bind(this),function(t){this.exitPresent(),t.stopPropagation(),t.preventDefault()}.bind(this)),this.rotateInstructions_&&(p()&&y()?this.rotateInstructions_.showTemporarily(3e3,this.layer_.source.parentElement):this.rotateInstructions_.update()),this.orientationHandler=this.onOrientationChange_.bind(this),window.addEventListener("orientationchange",this.orientationHandler),this.vrdisplaypresentchangeHandler=this.updateBounds_.bind(this),window.addEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler),this.fireVRDisplayDeviceParamsChange_())},wt.prototype.endPresent_=function(){this.distorter_&&(this.distorter_.destroy(),this.distorter_=null),this.cardboardUI_&&(this.cardboardUI_.destroy(),this.cardboardUI_=null),this.rotateInstructions_&&this.rotateInstructions_.hide(),this.viewerSelector_.hide(),window.removeEventListener("orientationchange",this.orientationHandler),window.removeEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler)},wt.prototype.updatePresent_=function(){this.endPresent_(),this.beginPresent_()},wt.prototype.submitFrame=function(t){if(this.distorter_)this.updateBounds_(),this.distorter_.submitFrame();else if(this.cardboardUI_&&this.layer_){var e=this.layer_.source.getContext("webgl").canvas;e.width==this.lastWidth&&e.height==this.lastHeight||this.cardboardUI_.onResize(),this.lastWidth=e.width,this.lastHeight=e.height,this.cardboardUI_.render()}},wt.prototype.onOrientationChange_=function(t){this.viewerSelector_.hide(),this.rotateInstructions_&&this.rotateInstructions_.update(),this.onResize_()},wt.prototype.onResize_=function(t){if(this.layer_){var e=this.layer_.source.getContext("webgl");e.canvas.setAttribute("style",["position: absolute","top: 0","left: 0","width: 100vw","height: 100vh","border: 0","margin: 0","padding: 0px","box-sizing: content-box"].join("; ")+";"),D(e.canvas)}},wt.prototype.onViewerChanged_=function(t){this.deviceInfo_.setViewer(t),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_),this.fireVRDisplayDeviceParamsChange_()},wt.prototype.fireVRDisplayDeviceParamsChange_=function(){var t=new CustomEvent("vrdisplaydeviceparamschange",{detail:{vrdisplay:this,deviceInfo:this.deviceInfo_}});window.dispatchEvent(t)},wt.VRFrameData=function(){this.leftProjectionMatrix=new Float32Array(16),this.leftViewMatrix=new Float32Array(16),this.rightProjectionMatrix=new Float32Array(16),this.rightViewMatrix=new Float32Array(16),this.pose=null},wt.VRDisplay=Nt,wt}()}(e={exports:{}},e.exports),(t=e.exports)&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t),a={ADDITIONAL_VIEWERS:[],DEFAULT_VIEWER:"",PROVIDE_MOBILE_VRDISPLAY:!0,GET_VR_DISPLAYS_TIMEOUT:1e3,MOBILE_WAKE_LOCK:!0,DEBUG:!1,DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1};function h(t){this.config=r(r({},a),t),this.polyfillDisplays=[],this.enabled=!1,this.hasNative="getVRDisplays"in navigator,this.native={},this.native.getVRDisplays=navigator.getVRDisplays,this.native.VRFrameData=window.VRFrameData,this.native.VRDisplay=window.VRDisplay,(!this.hasNative||this.config.PROVIDE_MOBILE_VRDISPLAY&&n())&&(this.enable(),this.getVRDisplays().then(function(t){t&&t[0]&&t[0].fireVRDisplayConnect_&&t[0].fireVRDisplayConnect_()}))}h.prototype.getPolyfillDisplays=function(){if(this._polyfillDisplaysPopulated)return this.polyfillDisplays;if(n()){var t=new o({ADDITIONAL_VIEWERS:this.config.ADDITIONAL_VIEWERS,DEFAULT_VIEWER:this.config.DEFAULT_VIEWER,MOBILE_WAKE_LOCK:this.config.MOBILE_WAKE_LOCK,DEBUG:this.config.DEBUG,DPDB_URL:this.config.DPDB_URL,CARDBOARD_UI_DISABLED:this.config.CARDBOARD_UI_DISABLED,K_FILTER:this.config.K_FILTER,PREDICTION_TIME_S:this.config.PREDICTION_TIME_S,ROTATE_INSTRUCTIONS_DISABLED:this.config.ROTATE_INSTRUCTIONS_DISABLED,YAW_ONLY:this.config.YAW_ONLY,BUFFER_SCALE:this.config.BUFFER_SCALE,DIRTY_SUBMIT_FRAME_BINDINGS:this.config.DIRTY_SUBMIT_FRAME_BINDINGS});this.polyfillDisplays.push(t)}return this._polyfillDisplaysPopulated=!0,this.polyfillDisplays},h.prototype.enable=function(){if(this.enabled=!0,this.hasNative&&this.native.VRFrameData){var e=this.native.VRFrameData,i=new this.native.VRFrameData,n=this.native.VRDisplay.prototype.getFrameData;window.VRDisplay.prototype.getFrameData=function(t){t instanceof e?n.call(this,t):(n.call(this,i),t.pose=i.pose,s(i.leftProjectionMatrix,t.leftProjectionMatrix),s(i.rightProjectionMatrix,t.rightProjectionMatrix),s(i.leftViewMatrix,t.leftViewMatrix),s(i.rightViewMatrix,t.rightViewMatrix))}}navigator.getVRDisplays=this.getVRDisplays.bind(this),window.VRDisplay=o.VRDisplay,window.VRFrameData=o.VRFrameData},h.prototype.getVRDisplays=function(){var e,i=this,n=this.config;if(!this.hasNative)return Promise.resolve(this.getPolyfillDisplays());var s,t=this.native.getVRDisplays.call(navigator),r=new Promise(function(t){e=setTimeout(function(){console.warn("Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill."),t([])},n.GET_VR_DISPLAYS_TIMEOUT)});return(s=[t,r],Promise.race?Promise.race(s):new Promise(function(t,e){for(var i=0;i -hx_cameraNearPlaneDistance) ?\n\t\t\t\t\t\t(-hx_cameraNearPlaneDistance - ray0.z) / rayDir.z : maxDistance;\n\n vec3 ray1 = ray0 + rayDir * rayLength;\n\n // only need the w component for perspective correct interpolation\n // need to get adjusted ray end\'s uv value\n vec4 hom0 = hx_projectionMatrix * vec4(ray0, 1.0);\n vec4 hom1 = hx_projectionMatrix * vec4(ray1, 1.0);\n float rcpW0 = 1.0 / hom0.w;\n float rcpW1 = 1.0 / hom1.w;\n\n hom0 *= rcpW0;\n hom1 *= rcpW1;\n\n // expressed in pixels, so we can snap to 1\n // need to figure out the ratio between 1 pixel and the entire line "width" (if primarily vertical, it\'s actually height)\n\n // line dimensions in pixels:\n\n vec2 pixelSize = (hom1.xy - hom0.xy) * hx_renderTargetResolution * .5;\n\n // line-"width" = max(abs(pixelSize.x), abs(pixelSize.y))\n // ratio pixel/width = 1 / max(abs(pixelSize.x), abs(pixelSize.y))\n\n float stepRatio = 1.0 / max(abs(pixelSize.x), abs(pixelSize.y)) * stepSize;\n\n vec2 uvEnd = hom1.xy * .5 + .5;\n\n vec2 dUV = (uvEnd - uv) * stepRatio;\n hitUV = uv;\n\n // linear depth\n float rayDepth = (-ray0.z - hx_cameraNearPlaneDistance) * hx_rcpCameraFrustumRange;\n float rayPerspDepth0 = rayDepth * rcpW0;\n float rayPerspDepth1 = (-ray1.z - hx_cameraNearPlaneDistance) * hx_rcpCameraFrustumRange * rcpW1;\n float rayPerspDepth = rayPerspDepth0;\n // could probably optimize this:\n float dRayD = (rayPerspDepth1 - rayPerspDepth0) * stepRatio;\n\n float rcpW = rcpW0;\n float dRcpW = (rcpW1 - rcpW0) * stepRatio;\n float sceneDepth = rayDepth;\n\n float amount = 0.0;\n\n hitUV += dUV * dither.z;\n rayPerspDepth += dRayD * dither.z;\n rcpW += dRcpW * dither.z;\n\n float sampleCount;\n for (int i = 0; i < NUM_SAMPLES; ++i) {\n rayDepth = rayPerspDepth / rcpW;\n\n sceneDepth = hx_sampleLinearDepth(hx_gbufferDepth, hitUV);\n\n if (rayDepth > sceneDepth + .001) {\n amount = float(sceneDepth < 1.0);\n sampleCount = float(i);\n break;\n }\n\n hitUV += dUV;\n rayPerspDepth += dRayD;\n rcpW += dRcpW;\n }\n\n hitZ = -hx_cameraNearPlaneDistance - sceneDepth * hx_cameraFrustumRange;\n\n amount *= clamp((1.0 - (sampleCount - float(NUM_SAMPLES)) / float(NUM_SAMPLES)) * 5.0, 0.0, 1.0);\n return amount;\n}\n\nvoid main()\n{\n vec4 colorSample = hx_gammaToLinear(texture2D(hx_gbufferColor, uv));\n vec4 specularSample = texture2D(hx_gbufferSpecular, uv);\n float depth = hx_sampleLinearDepth(hx_gbufferDepth, uv);\n vec3 normalSpecularReflectance;\n float roughness;\n float metallicness;\n hx_decodeReflectionData(colorSample, specularSample, normalSpecularReflectance, roughness, metallicness);\n vec3 normal = hx_decodeNormal(texture2D(hx_gbufferNormals, uv));\n vec3 reflDir = reflect(normalize(viewDir), normal);\n\n vec3 fresnel = hx_fresnel(normalSpecularReflectance, reflDir, normal);\n // not physically correct, but attenuation is required to look good\n\n // step for every pixel\n\n float absViewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n vec3 viewSpacePos = absViewY * viewDir;\n\n float hitY = 0.0;\n vec2 hitUV;\n float amount = raytrace(viewSpacePos, reflDir, hitY, hitUV);\n float fadeFactor = 1.0 - clamp(reflDir.z * 2.0, 0.0, 1.0);\n\n vec2 borderFactors = abs(hitUV * 2.0 - 1.0);\n borderFactors = (1.0 - borderFactors) * 10.0;\n fadeFactor *= clamp(borderFactors.x, 0.0, 1.0) * clamp(borderFactors.y, 0.0, 1.0);\n\n float diff = viewSpacePos.y - hitY;\n fadeFactor *= hx_linearStep(-1.0, 0.0, diff);\n fadeFactor *= hx_linearStep(maxRoughness, 0.0, roughness);\n\n vec4 reflColor = texture2D(hx_frontBuffer, hitUV);\n\n float amountUsed = amount * fadeFactor;\n hx_FragColor = vec4(fresnel * reflColor.xyz, amountUsed);\n}\n\n',f._files["ssr_stencil_fragment.glsl"]="uniform sampler2D hx_gbufferSpecular;\n\nvarying_in vec2 uv;\n\nuniform float maxRoughness;\n\nvoid main()\n{\n vec4 specularSample = texture2D(hx_gbufferSpecular, uv);\n if (specularSample.x > maxRoughness)\n discard;\n}\n\n",f._files["taa_fragment.glsl"]="varying_in vec2 uv;\n\nuniform vec2 hx_rcpRenderTargetResolution;\nuniform sampler2D hx_backBuffer;\nuniform sampler2D historyBuffer;\n\nuniform float alpha;\nuniform float gamma;\n\nvoid main()\n{\n\tvec4 col = texture2D(hx_backBuffer, uv);\n\tvec3 c = col.xyz; // \"c\"enter\n\tvec2 oldUV = hx_getPreviousFrameUV(uv);\n\tvec3 old = texture2D(historyBuffer, oldUV).xyz;\n\tfloat amount = alpha;\n\n\t// out of bounds: take new value completely\n\tif (oldUV.x < 0.0 || oldUV.x > 1.0 || oldUV.y < 0.0 || oldUV.y > 1.0)\n\t amount = 1.0;\n\n // neighbourhood clamping: the old colour is only considered valid if it's within the bounds of the current neighbours\n // https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf [Karis2014]\n vec3 l = texture2D(hx_backBuffer, uv - vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 r = texture2D(hx_backBuffer, uv + vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 t = texture2D(hx_backBuffer, uv - vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 b = texture2D(hx_backBuffer, uv + vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 minBound = min(min(min(min(l, r), t), b), c);\n vec3 maxBound = max(max(max(max(l, r), t), b), c);\n\n // just treat rgb space as a regular 3D space\n if (any(lessThan(old, minBound)) || any(greaterThan(old, maxBound))) {\n // variance clipping\n // http://developer.download.nvidia.com/gameworks/events/GDC2016/msalvi_temporal_supersampling.pdf\n // moments\n vec3 m1 = l + r + t + b + c;\n vec3 m2 = l * l + r * r + t * t + b * b + c * c;\n // variance\n vec3 mu = m1 / 5.0;\n vec3 sigma = sqrt(m2 / 5.0 - mu * mu);\n\n vec3 d = c - old;\n\n // find relevant AABB planes (those closest to the ray, know this from ray direction)\n vec3 planes = mu - sign(d) * gamma * sigma;\n\n // clip to old AABB to make sure it's never bigger\n planes = max(planes, minBound);\n planes = min(planes, maxBound);\n\n\n // clip segment [old -> C] against new AABB\n // C is always inside AABB\n vec3 tm = (planes - old) / d;\n vec3 absD = abs(d);\n\n float t = 0.0;\n\n if (absD.x > 0.0003)\n t = max(tm.x, t);\n if (absD.y > 0.0003)\n t = max(tm.y, t);\n if (absD.z > 0.0003)\n t = max(tm.z, t);\n\n old += t * d;\n }\n\n hx_FragColor.xyz = mix(old, c, amount);\n hx_FragColor.w = col.w;\n}",f._files["tonemap_filmic_fragment.glsl"]="void main()\n{\n\tvec3 x = hx_getToneMapScaledColor().xyz * 16.0;\n\n // Uncharted 2 tonemapping (http://filmicworlds.com/blog/filmic-tonemapping-operators/)\n\n\tfloat A = 0.15;\n float B = 0.50;\n float C = 0.10;\n float D = 0.20;\n float E = 0.02;\n float F = 0.30;\n float W = 11.2;\n\n hx_FragColor.xyz = hx_gammaToLinear(((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F);\n hx_FragColor.w = 1.0;\n}",f._files["tonemap_reference_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D hx_backBuffer;\n\nvoid main()\n{\n\tvec4 color = texture2D(hx_backBuffer, uv);\n\tfloat lum = clamp(hx_luminance(color), 0.0, 1000.0);\n\tfloat l = log(1.0 + lum);\n\thx_FragColor = vec4(l, l, l, 1.0);\n}",f._files["tonemap_reinhard_fragment.glsl"]="void main()\n{\n\tvec4 color = hx_getToneMapScaledColor();\n\tfloat lum = hx_luminance(color);\n\thx_FragColor = color / (1.0 + lum);\n}",f._files["esm_blur_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D source;\nuniform vec2 direction; // this is 1/pixelSize\n\nfloat readValue(vec2 coord)\n{\n float v = texture2D(source, coord).x;\n return v;\n// return exp(HX_ESM_CONSTANT * v);\n}\n\nvoid main()\n{\n float total = readValue(uv);\n\n\tfor (int i = 1; i <= RADIUS; ++i) {\n\t vec2 offset = direction * float(i);\n\t\ttotal += readValue(uv + offset) + readValue(uv - offset);\n\t}\n\n//\thx_FragColor = vec4(log(total * RCP_NUM_SAMPLES) / HX_ESM_CONSTANT);\n\thx_FragColor = vec4(total * RCP_NUM_SAMPLES);\n}",f._files["shadow_esm.glsl"]="vec4 hx_getShadowMapValue(float depth)\n{\n // I wish we could write exp directly, but precision issues (can't encode real floats)\n return vec4(exp(HX_ESM_CONSTANT * depth));\n// so when blurring, we'll need to do ln(sum(exp())\n// return vec4(depth);\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n float shadowSample = texture2D(shadowMap, shadowMapCoord.xy).x;\n shadowMapCoord.z += depthBias;\n// float diff = shadowSample - shadowMapCoord.z;\n// return saturate(HX_ESM_DARKENING * exp(HX_ESM_CONSTANT * diff));\n return saturate(HX_ESM_DARKENING * shadowSample * exp(-HX_ESM_CONSTANT * shadowMapCoord.z));\n}",f._files["shadow_hard.glsl"]="vec4 hx_getShadowMapValue(float depth)\n{\n return hx_floatToRGBA8(depth);\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n float shadowSample = hx_RGBA8ToFloat(texture2D(shadowMap, shadowMapCoord.xy));\n float diff = shadowMapCoord.z - shadowSample - depthBias;\n return float(diff < 0.0);\n}",f._files["shadow_pcf.glsl"]="#ifdef HX_PCF_DITHER_SHADOWS\n uniform sampler2D hx_dither2D;\n uniform vec2 hx_dither2DTextureScale;\n#endif\n\nuniform vec2 hx_poissonDisk[32];\n\nvec4 hx_getShadowMapValue(float depth)\n{\n return hx_floatToRGBA8(depth);\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n float shadowTest = 0.0;\n\n #ifdef HX_PCF_DITHER_SHADOWS\n vec4 dither = hx_sampleDefaultDither(hx_dither2D, gl_FragCoord.xy * hx_dither2DTextureScale);\n dither = vec4(dither.x, -dither.y, dither.y, dither.x) * HX_PCF_SOFTNESS; // add radius scale\n #endif\n\n for (int i = 0; i < HX_PCF_NUM_SHADOW_SAMPLES; ++i) {\n vec2 offset;\n #ifdef HX_PCF_DITHER_SHADOWS\n offset.x = dot(dither.xy, hx_poissonDisk[i]);\n offset.y = dot(dither.zw, hx_poissonDisk[i]);\n #else\n offset = hx_poissonDisk[i] * HX_PCF_SOFTNESS;\n #endif\n float shadowSample = hx_RGBA8ToFloat(texture2D(shadowMap, shadowMapCoord.xy + offset));\n float diff = shadowMapCoord.z - shadowSample - depthBias;\n shadowTest += float(diff < 0.0);\n }\n\n return shadowTest * HX_PCF_RCP_NUM_SHADOW_SAMPLES;\n}",f._files["shadow_vsm.glsl"]="#derivatives\n\nvec4 hx_getShadowMapValue(float depth)\n{\n float dx = dFdx(depth);\n float dy = dFdy(depth);\n float moment2 = depth * depth + 0.25*(dx*dx + dy*dy);\n\n #if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n return vec4(depth, moment2, 0.0, 1.0);\n #else\n return vec4(hx_floatToRG8(depth), hx_floatToRG8(moment2));\n #endif\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n vec4 s = texture2D(shadowMap, shadowMapCoord.xy);\n #if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n vec2 moments = s.xy;\n #else\n vec2 moments = vec2(hx_RG8ToFloat(s.xy), hx_RG8ToFloat(s.zw));\n #endif\n shadowMapCoord.z += depthBias;\n\n float variance = moments.y - moments.x * moments.x;\n variance = clamp(variance + HX_VSM_MIN_VARIANCE, 0.0, 1.0);\n\n float diff = shadowMapCoord.z - moments.x;\n float upperBound = 1.0;\n\n // transparents could be closer to the light than casters\n if (diff > 0.0)\n upperBound = variance / (variance + diff*diff);\n\n return saturate((upperBound - HX_VSM_LIGHT_BLEED_REDUCTION) * HX_VSM_RCP_LIGHT_BLEED_REDUCTION_RANGE);\n}",f._files["vsm_blur_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D source;\nuniform vec2 direction; // this is 1/pixelSize\n\nvec2 readValues(vec2 coord)\n{\n vec4 s = texture2D(source, coord);\n #if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n return s.xy;\n #else\n return vec2(hx_RG8ToFloat(s.xy), hx_RG8ToFloat(s.zw));\n #endif\n}\n\nvoid main()\n{\n vec2 total = readValues(uv);\n\n\tfor (int i = 1; i <= RADIUS; ++i) {\n\t vec2 offset = direction * float(i);\n\t\ttotal += readValues(uv + offset) + readValues(uv - offset);\n\t}\n\n total *= RCP_NUM_SAMPLES;\n\n#if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n hx_FragColor = vec4(total, 0.0, 1.0);\n#else\n\thx_FragColor.xy = hx_floatToRG8(total.x);\n\thx_FragColor.zw = hx_floatToRG8(total.y);\n#endif\n}",f._files["2d_to_cube_vertex.glsl"]="// position to write to\nvertex_attribute vec4 hx_position;\n\n// the corner of the cube map\nvertex_attribute vec3 corner;\n\nvarying_out vec3 direction;\n\nvoid main()\n{\n direction = corner;\n gl_Position = hx_position;\n}\n",f._files["equirectangular_from_cube_fragment.glsl"]="varying_in vec2 uv;\n\nuniform samplerCube sampler;\n\nvoid main()\n{\n vec3 dir;\n\n float theta = (-(uv.x * 2.0 - 1.0) + .5) * HX_PI;\n float phi = (uv.y * 2.0 - 1.0) * HX_PI / 2.0;\n\n dir.x = cos(theta) * cos(phi);\n\tdir.y = -sin(phi);\n\tdir.z = sin(theta) * cos(phi);\n\n hx_FragColor = textureCube(sampler, dir);\n}",f._files["equirectangular_to_cube_fragment.glsl"]="#define RECIPROCAL_PI2 0.15915494\n#define RECIPROCAL_PI 0.31830989\n\nvarying_in vec3 direction;\n\nuniform sampler2D source;\n\nvoid main()\n{\n vec3 dir = normalize(direction);\n vec2 uv;\n\n uv.x = -atan( dir.z, dir.x ) * RECIPROCAL_PI2 - .25;\n\tuv.y = 0.5 - asin(dir.y) * RECIPROCAL_PI;\n hx_FragColor = texture2D(source, uv);\n}\n",f._files["greyscale_to_rgba8.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D source;\n\nvoid main()\n{\n hx_FragColor = hx_floatToRGBA8(texture2D(source, uv).x);\n}\n",f._files["smooth_heightmap_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D reference; // the source (8 bit) texture\nuniform sampler2D source;\n\nuniform vec2 stepSize;\n\nvoid main()\n{\n float gauss[4];\n gauss[0] = 0.201788613113303;\n gauss[1] = 0.17755834971394;\n gauss[2] = 0.120969095455128;\n gauss[3] = 0.063811162332456;\n float refHeight = texture2D(reference, uv).x;\n float total = hx_RGBA8ToFloat(texture2D(source, uv)) * gauss[0];\n float totalWeight = gauss[0];\n float currentWeightL = 1.0;\n float currentWeightR = 1.0;\n vec2 offset = vec2(0.0);\n\n\n for (int i = 0; i < 3; ++i) {\n offset += stepSize;\n float refLeft = texture2D(reference, uv - offset).x;\n float refRight = texture2D(reference, uv + offset).x;\n float heightLeft = hx_RGBA8ToFloat(texture2D(source, uv - offset));\n float heightRight = hx_RGBA8ToFloat(texture2D(source, uv + offset));\n // smooth out over N pixels that have the same reference height in the source image\n currentWeightL = max(currentWeightL - abs(refLeft - refHeight) * 5.0, 0.0);\n currentWeightR = max(currentWeightR - abs(refRight - refHeight) * 5.0, 0.0);\n totalWeight += (currentWeightL + currentWeightR) * gauss[i + 1];\n total += (heightLeft * currentWeightL + heightRight * currentWeightR) * gauss[i + 1];\n }\n\n hx_FragColor = hx_floatToRGBA8(total / totalWeight);\n}\n",f._files["snippets_general.glsl"]="#define HX_LOG_10 2.302585093\n#define HX_PI 3.1415926\n\n#ifdef HX_GLSL_300_ES\n // replace some outdated function names\n vec4 texture2D(sampler2D s, vec2 uv) { return texture(s, uv); }\n vec4 textureCube(samplerCube s, vec3 uvw) { return texture(s, uvw); }\n\n #define vertex_attribute in\n #define varying_in in\n #define varying_out out\n\n #ifdef HX_FRAGMENT_SHADER\n out vec4 hx_FragColor;\n #endif\n#else\n #define vertex_attribute attribute\n #define varying_in varying\n #define varying_out varying\n #define hx_FragColor gl_FragColor\n#endif\n\nfloat saturate(float value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec2 saturate(vec2 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec3 saturate(vec3 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec4 saturate(vec4 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\n// Only for 0 - 1\nvec4 hx_floatToRGBA8(float value)\n{\n vec4 enc = value * vec4(1.0, 255.0, 65025.0, 16581375.0);\n // cannot fract first value or 1 would not be encodable\n enc.yzw = fract(enc.yzw);\n return enc - enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);\n}\n\nfloat hx_RGBA8ToFloat(vec4 rgba)\n{\n return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));\n}\n\nvec2 hx_floatToRG8(float value)\n{\n vec2 enc = vec2(1.0, 255.0) * value;\n enc.y = fract(enc.y);\n enc.x -= enc.y / 255.0;\n return enc;\n}\n\nfloat hx_RG8ToFloat(vec2 rg)\n{\n return dot(rg, vec2(1.0, 1.0/255.0));\n}\n\nvec2 hx_encodeNormal(vec3 normal)\n{\n vec2 data;\n float p = sqrt(-normal.y*8.0 + 8.0);\n data = normal.xz / p + .5;\n return data;\n}\n\nvec2 hx_decodeMotionVector(vec4 data)\n{\n vec2 vel;\n vel.x = hx_RG8ToFloat(data.xy);\n vel.y = hx_RG8ToFloat(data.zw);\n return vel * 2.0 - 1.0;\n}\n\nvec3 hx_decodeNormal(vec4 data)\n{\n vec3 normal;\n data.xy = data.xy*4.0 - 2.0;\n float f = dot(data.xy, data.xy);\n float g = sqrt(1.0 - f * .25);\n normal.xz = data.xy * g;\n normal.y = -(1.0 - f * .5);\n return normal;\n}\n\nfloat hx_log10(float val)\n{\n return log(val) / HX_LOG_10;\n}\n\nvec4 hx_gammaToLinear(vec4 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec3 hx_gammaToLinear(vec3 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec4 hx_linearToGamma(vec4 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\nvec3 hx_linearToGamma(vec3 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\n/*float hx_sampleLinearDepth(sampler2D tex, vec2 uv)\n{\n return hx_RGBA8ToFloat(texture2D(tex, uv));\n}*/\n\nfloat hx_decodeLinearDepth(vec4 samp)\n{\n return hx_RG8ToFloat(samp.zw);\n}\n\nvec3 hx_getFrustumVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unprojNear = unprojectionMatrix * vec4(position, -1.0, 1.0);\n vec4 unprojFar = unprojectionMatrix * vec4(position, 1.0, 1.0);\n return unprojFar.xyz/unprojFar.w - unprojNear.xyz/unprojNear.w;\n}\n\n// view vector with z = 1, so we can use nearPlaneDist + linearDepth * (farPlaneDist - nearPlaneDist) as a scale factor to find view space position\nvec3 hx_getLinearDepthViewVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unproj = unprojectionMatrix * vec4(position, 0.0, 1.0);\n unproj /= unproj.w;\n return unproj.xyz / unproj.y;\n}\n\n// THIS IS FOR NON_LINEAR DEPTH!\nfloat hx_depthToViewY(float depth, mat4 projectionMatrix)\n{\n return projectionMatrix[3][2] / (depth * 2.0 - 1.0 - projectionMatrix[1][2]);\n}\n\nvec3 hx_getNormalSpecularReflectance(float metallicness, float insulatorNormalSpecularReflectance, vec3 color)\n{\n return mix(vec3(insulatorNormalSpecularReflectance), color, metallicness);\n}\n\nvec3 hx_fresnel(vec3 normalSpecularReflectance, vec3 lightDir, vec3 halfVector)\n{\n float cosAngle = 1.0 - max(dot(halfVector, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n return normalSpecularReflectance + (1.0 - normalSpecularReflectance) * power;\n}\n\n// https://seblagarde.wordpress.com/2011/08/17/hello-world/\nvec3 hx_fresnelProbe(vec3 normalSpecularReflectance, vec3 lightDir, vec3 normal, float roughness)\n{\n float cosAngle = 1.0 - max(dot(normal, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n float gloss = (1.0 - roughness) * (1.0 - roughness);\n vec3 bound = max(vec3(gloss), normalSpecularReflectance);\n return normalSpecularReflectance + (bound - normalSpecularReflectance) * power;\n}\n\n\nfloat hx_luminance(vec4 color)\n{\n return dot(color.xyz, vec3(.30, 0.59, .11));\n}\n\nfloat hx_luminance(vec3 color)\n{\n return dot(color, vec3(.30, 0.59, .11));\n}\n\n// linear variant of smoothstep\nfloat hx_linearStep(float lower, float upper, float x)\n{\n return clamp((x - lower) / (upper - lower), 0.0, 1.0);\n}\n\nvec4 hx_sampleDefaultDither(sampler2D ditherTexture, vec2 uv)\n{\n vec4 s = texture2D(ditherTexture, uv);\n\n #ifndef HX_FLOAT_TEXTURES\n s = s * 2.0 - 1.0;\n #endif\n\n return s;\n}\n\nvec3 hx_evaluateSH(vec3 sh[9], vec3 dir)\n{\n dir = dir.xzy;\n vec3 col = sh[0] +\n sh[1] * dir.y + sh[2] * dir.z + sh[3] * dir.x +\n sh[4] * dir.x * dir.y + sh[5] * dir.y * dir.z + sh[6] * (3.0 * dir.z * dir.z - 1.0) +\n sh[7] * dir.z * dir.x + sh[8] * (dir.x * dir.x - dir.y * dir.y);\n\n col = max(col, vec3(0.0));\n return col;\n}\n\n// I'm keeping this for reference, even tho it doesn't work in iOS\nvoid hx_sumSH(in vec3 a[9], in float weight, inout vec3 b[9])\n{\n // have to manually unroll this, on some platforms the loop is weirdly slow\n b[0] += a[0] * weight;\n b[1] += a[1] * weight;\n b[2] += a[2] * weight;\n b[3] += a[3] * weight;\n b[4] += a[4] * weight;\n b[5] += a[5] * weight;\n b[6] += a[6] * weight;\n b[7] += a[7] * weight;\n b[8] += a[8] * weight;\n}\n\nvec3 hx_intersectCubeMap(vec3 rayOrigin, vec3 cubeCenter, vec3 rayDir, float cubeSize)\n{\n vec3 t = (cubeSize * sign(rayDir) - (rayOrigin - cubeCenter)) / rayDir;\n float minT = min(min(t.x, t.y), t.z);\n return rayOrigin + minT * rayDir;\n}\n\n// sadly, need a parameter due to a bug in Internet Explorer / Edge. Just pass in 0.\n#ifdef HX_USE_SKINNING_TEXTURE\n#define HX_RCP_MAX_SKELETON_JOINTS 1.0 / float(HX_MAX_SKELETON_JOINTS - 1)\nmat4 hx_getSkinningMatrixImpl(vec4 weights, vec4 indices, sampler2D tex)\n{\n mat4 m = mat4(0.0);\n for (int i = 0; i < 4; ++i) {\n mat4 t;\n float index = indices[i] * HX_RCP_MAX_SKELETON_JOINTS;\n t[0] = texture2D(tex, vec2(index, 0.0));\n t[1] = texture2D(tex, vec2(index, 0.5));\n t[2] = texture2D(tex, vec2(index, 1.0));\n t[3] = vec4(0.0, 0.0, 0.0, 1.0);\n m += weights[i] * t;\n }\n return m;\n}\n#define hx_getSkinningMatrix(v) hx_getSkinningMatrixImpl(hx_jointWeights, hx_jointIndices, hx_skinningTexture)\n#else\n#define hx_getSkinningMatrix(v) ( hx_jointWeights.x * mat4(hx_skinningMatrices[int(hx_jointIndices.x) * 3], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.y * mat4(hx_skinningMatrices[int(hx_jointIndices.y) * 3], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.z * mat4(hx_skinningMatrices[int(hx_jointIndices.z) * 3], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.w * mat4(hx_skinningMatrices[int(hx_jointIndices.w) * 3], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) )\n#endif",f._files["snippets_geometry.glsl"]="struct HX_GeometryData\n{\n vec4 color;\n vec3 normal;\n float metallicness;\n float normalSpecularReflectance;\n float roughness;\n float occlusion;\n vec3 emission;\n vec4 data; // this can be anything the lighting model requires\n #ifdef HX_USE_TRANSLUCENCY\n vec3 translucency;\n #endif\n};",f._files["snippets_reproject.glsl"]='#ifdef HX_MOTION_VECTORS\nuniform sampler2D hx_motionVectorBuffer;\n#else\nuniform sampler2D hx_normalDepthBuffer;\nuniform float hx_cameraNearPlaneDistance;\nuniform float hx_cameraFrustumRange;\nuniform mat4 hx_inverseProjectionMatrix;\nuniform mat4 hx_cameraWorldMatrix;\nuniform mat4 hx_prevViewProjectionMatrix;\nuniform vec2 hx_cameraJitter;\n#endif\n\n\nvec2 hx_getMotionVector(vec2 uv)\n{\n#ifdef HX_MOTION_VECTORS\n return hx_decodeMotionVector(texture2D(hx_motionVectorBuffer, uv));\n#else\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n float depth = hx_decodeLinearDepth(normalDepth);\n float absViewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n\n // unproject any point on the view ray to view space:\n vec2 ndc = uv * 2.0 - 1.0;\n // view projection matrix is jittered, so hx_inverseProjectionMatrix will "unjitter"\n // so we need to reapply the jitter to counter this\n vec3 viewDir = hx_getLinearDepthViewVector(ndc + hx_cameraJitter, hx_inverseProjectionMatrix);\n\n // reconstruct world position based on linear depth\n vec3 viewPos = viewDir * absViewY;\n vec4 worldPos = hx_cameraWorldMatrix * vec4(viewPos, 1.0);\n\n // reproject with previous frame matrix\n vec4 oldProj = hx_prevViewProjectionMatrix * worldPos;\n return (ndc - oldProj.xy / oldProj.w) * .5;\n#endif\n}\n\nvec2 hx_getPreviousFrameUV(vec2 currentUV)\n{\n return currentUV - hx_getMotionVector(currentUV);\n}',f._files["snippets_tonemap.glsl"]="varying_in vec2 uv;\n\n#ifdef HX_ADAPTIVE\nuniform sampler2D hx_luminanceMap;\nuniform float hx_luminanceMipLevel;\n#endif\n\nuniform float hx_exposure;\nuniform float hx_key;\n\nuniform sampler2D hx_backBuffer;\n\n\nvec4 hx_getToneMapScaledColor()\n{\n #ifdef HX_ADAPTIVE\n #ifdef HX_GLSL_300_ES\n float referenceLuminance = textureLod(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #else\n float referenceLuminance = texture2DLodEXT(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #endif\n referenceLuminance = exp(referenceLuminance) - 1.0;\n referenceLuminance = clamp(referenceLuminance, .08, 1000.0);\n\tfloat exposure = hx_key / referenceLuminance * hx_exposure;\n\t#else\n\tfloat exposure = hx_exposure;\n\t#endif\n return texture2D(hx_backBuffer, uv) * exposure;\n}",f._files["ao_blur_fragment.glsl"]="varying_in vec2 uv1;\nvarying_in vec2 uv2;\nvarying_in vec2 uv3;\nvarying_in vec2 uv4;\n\nuniform sampler2D source;\n\nvoid main()\n{\n vec4 total = texture2D(source, uv1) + texture2D(source, uv2) + texture2D(source, uv3) + texture2D(source, uv4);\n\thx_FragColor = total * .25;\n}",f._files["ao_blur_vertex.glsl"]="vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nvarying_out vec2 uv1;\nvarying_out vec2 uv2;\nvarying_out vec2 uv3;\nvarying_out vec2 uv4;\n\nuniform vec2 pixelSize;\n\nvoid main()\n{\n\tuv1 = hx_texCoord + vec2(-1.5, .5) * pixelSize;\n\tuv2 = hx_texCoord + vec2(.5, .5) * pixelSize;\n\tuv3 = hx_texCoord + vec2(.5, -1.5) * pixelSize;\n\tuv4 = hx_texCoord + vec2(-1.5, -1.5) * pixelSize;\n\tgl_Position = hx_position;\n}",f._files["hbao_fragment.glsl"]="uniform float hx_cameraFrustumRange;\nuniform float hx_cameraNearPlaneDistance;\nuniform vec2 hx_rcpRenderTargetResolution;\nuniform mat4 hx_projectionMatrix;\n\nuniform float strengthPerRay;\nuniform float halfSampleRadius;\nuniform float bias;\nuniform float rcpFallOffDistance;\nuniform vec2 ditherScale;\n\nuniform sampler2D hx_normalDepthBuffer;\nuniform sampler2D sampleDirTexture;\nuniform sampler2D ditherTexture;\n\nvarying_in vec2 uv;\nvarying_in vec3 viewDir;\nvarying_in vec3 frustumCorner;\n\nvec3 getViewPos(vec2 sampleUV)\n{\n vec4 smp = texture2D(hx_normalDepthBuffer, sampleUV);\n float depth = hx_decodeLinearDepth(smp);\n float viewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n vec3 viewPos = frustumCorner * vec3(sampleUV.x * 2.0 - 1.0, 1.0, sampleUV.y * 2.0 - 1.0);\n return viewPos * viewY;\n}\n\n// Retrieves the occlusion factor for a particular sample\nfloat getSampleOcclusion(vec2 sampleUV, vec3 centerViewPos, vec3 centerNormal, vec3 tangent, inout float topOcclusion)\n{\n vec3 sampleViewPos = getViewPos(sampleUV);\n\n // get occlusion factor based on candidate horizon elevation\n vec3 horizonVector = sampleViewPos - centerViewPos;\n float horizonVectorLength = length(horizonVector);\n\n float occlusion;\n\n // If the horizon vector points away from the tangent, make an estimate\n if (dot(tangent, horizonVector) < 0.0)\n occlusion = .5;\n else\n occlusion = dot(centerNormal, horizonVector) / horizonVectorLength;\n\n // this adds occlusion only if angle of the horizon vector is higher than the previous highest one without branching\n float diff = max(occlusion - topOcclusion, 0.0);\n topOcclusion = max(occlusion, topOcclusion);\n\n // attenuate occlusion contribution using distance function 1 - (d/f)^2\n float distanceFactor = 1.0 - saturate(horizonVectorLength * rcpFallOffDistance);\n return diff * distanceFactor;\n}\n\n// Retrieves the occlusion for a given ray\nfloat getRayOcclusion(vec2 direction, float jitter, vec2 projectedRadii, vec3 centerViewPos, vec3 centerNormal)\n{\n // calculate the nearest neighbour sample along the direction vector\n vec2 texelSizedStep = direction * hx_rcpRenderTargetResolution;\n direction *= projectedRadii;\n\n // gets the tangent for the current ray, this will be used to handle opposing horizon vectors\n // Tangent is corrected with respect to face normal by projecting it onto the tangent plane defined by the normal\n vec3 tangent = getViewPos(uv + texelSizedStep) - centerViewPos;\n tangent -= dot(centerNormal, tangent) * centerNormal;\n\n vec2 stepUV = direction.xy / float(NUM_SAMPLES_PER_RAY - 1);\n\n // jitter the starting position for ray marching between the nearest neighbour and the sample step size\n vec2 jitteredOffset = mix(texelSizedStep, stepUV, jitter);\n //stepUV *= 1.0 + jitter * .1;\n vec2 sampleUV = uv + jitteredOffset;\n\n // top occlusion keeps track of the occlusion contribution of the last found occluder.\n // set to bias value to avoid near-occluders\n float topOcclusion = bias;\n float occlusion = 0.0;\n\n // march!\n for (int step = 0; step < NUM_SAMPLES_PER_RAY; ++step) {\n occlusion += getSampleOcclusion(sampleUV, centerViewPos, centerNormal, tangent, topOcclusion);\n sampleUV += stepUV;\n }\n\n return occlusion;\n}\n\nvoid main()\n{\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n vec3 centerNormal = hx_decodeNormal(normalDepth);\n float centerDepth = hx_decodeLinearDepth(normalDepth);\n float viewY = hx_cameraNearPlaneDistance + centerDepth * hx_cameraFrustumRange;\n vec3 centerViewPos = viewY * viewDir;\n\n // clamp z to a minimum, so the radius does not get excessively large in screen-space\n float projRadius = halfSampleRadius / max(centerViewPos.y, 7.0);\n vec2 projectedRadii = projRadius * vec2(hx_projectionMatrix[0][0], hx_projectionMatrix[1][2]);\n\n // do not take more steps than there are pixels\n float totalOcclusion = 0.0;\n\n vec2 randomFactors = texture2D(ditherTexture, uv * ditherScale).xy;\n\n vec2 rayUV = vec2(0.0);\n for (int i = 0; i < NUM_RAYS; ++i) {\n rayUV.x = (float(i) + randomFactors.x) / float(NUM_RAYS);\n vec2 sampleDir = texture2D(sampleDirTexture, rayUV).xy * 2.0 - 1.0;\n totalOcclusion += getRayOcclusion(sampleDir, randomFactors.y, projectedRadii, centerViewPos, centerNormal);\n }\n\n totalOcclusion = 1.0 - clamp(strengthPerRay * totalOcclusion, 0.0, 1.0);\n hx_FragColor = vec4(vec3(totalOcclusion), 1.0);\n}",f._files["hbao_vertex.glsl"]="vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nuniform mat4 hx_inverseProjectionMatrix;\n\nvarying_out vec2 uv;\nvarying_out vec3 viewDir;\nvarying_out vec3 frustumCorner;\n\nvoid main()\n{\n uv = hx_texCoord;\n viewDir = hx_getLinearDepthViewVector(hx_position.xy, hx_inverseProjectionMatrix);\n frustumCorner = hx_getLinearDepthViewVector(vec2(1.0, 1.0), hx_inverseProjectionMatrix);\n gl_Position = hx_position;\n}",f._files["ssao_fragment.glsl"]='uniform mat4 hx_projectionMatrix;\nuniform mat4 hx_cameraWorldMatrix;\nuniform float hx_cameraFrustumRange;\nuniform float hx_cameraNearPlaneDistance;\n\nuniform vec2 ditherScale;\nuniform float strengthPerSample;\nuniform float rcpFallOffDistance;\nuniform float sampleRadius;\nuniform vec3 samples[NUM_SAMPLES]; // w contains bias\n\nuniform sampler2D ditherTexture;\nuniform sampler2D hx_normalDepthBuffer;\n\nvarying_in vec2 uv;\n\nvoid main()\n{\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n vec3 centerNormal = hx_decodeNormal(normalDepth);\n float centerDepth = hx_decodeLinearDepth(normalDepth);\n float totalOcclusion = 0.0;\n vec3 dither = texture2D(ditherTexture, uv * ditherScale).xyz;\n vec3 randomPlaneNormal = normalize(dither - .5);\n float w = hx_cameraNearPlaneDistance + centerDepth * hx_cameraFrustumRange;\n float centerY = centerDepth * hx_cameraFrustumRange; // can ignore nearDist\n vec3 sampleRadii;\n sampleRadii.xz = sampleRadius * .5 / w * vec2(hx_projectionMatrix[0][0], hx_projectionMatrix[1][2]);\n sampleRadii.y = sampleRadius;\n\n for (int i = 0; i < NUM_SAMPLES; ++i) {\n vec3 sampleOffset = reflect(samples[i], randomPlaneNormal);\n vec3 normOffset = normalize(sampleOffset);\n\n // mirror sample position to the positive side of the plane\n float cosFactor = dot(normOffset, centerNormal);\n float sign = sign(cosFactor);\n sampleOffset *= sign;\n cosFactor *= sign;\n\n vec3 scaledOffset = sampleOffset * sampleRadii;\n\n vec2 samplePos = uv + scaledOffset.xz;\n normalDepth = texture2D(hx_normalDepthBuffer, samplePos);\n float occluderDepth = hx_decodeLinearDepth(normalDepth);\n\n // can ignore nearDist\n float occluderY = hx_cameraFrustumRange * occluderDepth;\n float sampleY = centerY + scaledOffset.y;\n\n float distanceFactor = max(1.0 - (sampleY - occluderY) * rcpFallOffDistance, 0.0);\n\n // at this point, occlusion really means occlusion, and not the output "colour" (ie 1 = completely occluded)\n float sampleOcclusion = float(occluderY < sampleY);\n\n // if cosFactor = 0, the sample is coplanar, and occludes less\n totalOcclusion += sampleOcclusion * distanceFactor * cosFactor;\n }\n hx_FragColor = vec4(vec3(1.0 - totalOcclusion * strengthPerSample), 1.0);\n}';var _={shuffle:function(t){for(var e,i,n=t.length;0!==n;)i=Math.floor(Math.random()*n),e=t[n-=1],t[n]=t[i],t[i]=e;return t},forEach:function(t,e){for(var i in t)t.hasOwnProperty(i)&&e(t[i],i)}};function r(){this._listeners=[],this._lookUp={}}function o(){this._isRunning=!1,this._dt=0,this._currentTime=0,this._tickFunc=this._tick.bind(this),this._animationFrame=void 0,this.onTick=new r}function T(t,e,i,n){this.r=0,this.g=0,this.b=0,this.a=1,this.set(t,e,i,n)}r.prototype={bind:function(t,e){this._lookUp[t]=this._listeners.length;var i=e?t.bind(e):t;this._listeners.push(i)},unbind:function(t){var e=this._lookUp[t];void 0!==e&&(this._listeners.splice(e,1),delete this._lookUp[t])},unbindAll:function(){this._listeners=[],this._lookUp={}},dispatch:function(t){for(var e=this._listeners.length,i=0;i>>16)/255,this.g=((65280&t)>>>8)/255,this.b=(255&t)/255):(this.r=t,this.g=e,this.b=i,this.a=void 0===n?1:n)},scale:function(t){this.r*=t,this.g*=t,this.b*=t},hex:function(){return 255*Math.min(this.r,1)<<16|255*Math.min(this.g,1)<<8|255*Math.min(this.b,1)},luminance:function(){return.3*this.r+.59*this.g+.11*this.b},gammaToLinear:function(t){return t=t||new T,He.OPTIONS.usePreciseGammaCorrection?(t.r=Math.pow(this.r,2.2),t.g=Math.pow(this.g,2.2),t.b=Math.pow(this.b,2.2)):(t.r=this.r*this.r,t.g=this.g*this.g,t.b=this.b*this.b),t.a=this.a,t},linearToGamma:function(t){return t=t||new T,He.OPTIONS.usePreciseGammaCorrection?(t.r=Math.pow(this.r,.454545),t.g=Math.pow(this.g,.454545),t.b=Math.pow(this.b,.454545)):(t.r=Math.sqrt(this.r),t.g=Math.sqrt(this.g),t.b=Math.sqrt(this.b)),t.a=this.a,t},copyFrom:function(t){this.r=t.r,this.g=t.g,this.b=t.b,this.a=t.a},toString:function(){return"Color("+this.r+", "+this.g+", "+this.b+", "+this.a+")"},clone:function(){var t=new T;return t.r=this.r,t.g=this.g,t.b=this.b,t.a=this.a,t}},T.BLACK=new T(0,0,0,1),T.ZERO=new T(0,0,0,0),T.RED=new T(1,0,0,1),T.GREEN=new T(0,1,0,1),T.BLUE=new T(0,0,1,1),T.YELLOW=new T(1,1,0,1),T.MAGENTA=new T(1,0,1,1),T.CYAN=new T(0,1,1,1),T.WHITE=new T(1,1,1,1),T.HALF=new T(.5,.5,.5,.5);var u={GENERAL:"precision highp float;\n\n"+f.get("snippets_general.glsl")+"\n\n",VERSION:""},l={printShaderCode:function(t){for(var e=t.split("\n"),i="",n=0;nthis.x&&(this.x=t.x),t.y>this.y&&(this.y=t.y),t.z>this.z&&(this.z=t.z),t.w>this.w&&(this.w=t.w),this},maximize3:function(t){return t.x>this.x&&(this.x=t.x),t.y>this.y&&(this.y=t.y),t.z>this.z&&(this.z=t.z),this},minimize:function(t){return t.xthis._maximumX&&(this._maximumX=t._maximumX),t._maximumY>this._maximumY&&(this._maximumY=t._maximumY),t._maximumZ>this._maximumZ&&(this._maximumZ=t._maximumZ)),this._updateCenterAndExtent())},$.prototype.growToIncludeMinMax=function(t,e){this._expanse!==K.EXPANSE_INFINITE&&(this._expanse===K.EXPANSE_EMPTY?(this._minimumX=t.x,this._minimumY=t.y,this._minimumZ=t.z,this._maximumX=e.x,this._maximumY=e.y,this._maximumZ=e.z,this._expanse=K.EXPANSE_FINITE):(t.xthis._maximumX&&(this._maximumX=e.x),e.y>this._maximumY&&(this._maximumY=e.y),e.z>this._maximumZ&&(this._maximumZ=e.z)),this._updateCenterAndExtent())},$.prototype.transform=function(t){var e=new $;return e.transformFrom(this,t),e},$.prototype.transformFrom=function(t,e){if(t._expanse===K.EXPANSE_FINITE){var i=e._m,n=i[0],s=i[1],r=i[2],o=i[4],a=i[5],h=i[6],u=i[8],l=i[9],c=i[10],_=t._center.x,d=t._center.y,f=t._center.z,p=this._center.x=n*_+o*d+u*f+i[12],g=this._center.y=s*_+a*d+l*f+i[13],M=this._center.z=r*_+h*d+c*f+i[14];n<0&&(n=-n),s<0&&(s=-s),r<0&&(r=-r),o<0&&(o=-o),a<0&&(a=-a),h<0&&(h=-h),u<0&&(u=-u),l<0&&(l=-l),c<0&&(c=-c),_=t._halfExtentX,d=t._halfExtentY,f=t._halfExtentZ;var m=this._halfExtentX=n*_+o*d+u*f,A=this._halfExtentY=s*_+a*d+l*f,x=this._halfExtentZ=r*_+h*d+c*f;this._minimumX=p-m,this._minimumY=g-A,this._minimumZ=M-x,this._maximumX=p+m,this._maximumY=g+A,this._maximumZ=M+x,this._expanse=t._expanse}else this.clear(t._expanse)},$.prototype.intersectsConvexSolid=function(t,e){if(this._expanse===K.EXPANSE_INFINITE||this._expanse===K.EXPANSE_INHERIT)return!0;if(this._expanse===K.EXPANSE_EMPTY)return!1;for(var i=this._minimumX,n=this._minimumY,s=this._minimumZ,r=this._maximumX,o=this._maximumY,a=this._maximumZ,h=0;ht._minimumX&&this._minimumXt._minimumY&&this._minimumYt._minimumZ&&this._minimumZ>16&32768,n=e>>12&2047,s=e>>23&255;return s<103?i:142>114-s)+(n>>113-s&1):(i|=s-112<<10|n>>1,i+=1&n)}),encodeToFloat16Array:function(t){for(var e=At.encodeHalfFloat,i=[],n=0;nti.DEFAULT_TEXTURE_MAX_ANISOTROPY&&(t=ti.DEFAULT_TEXTURE_MAX_ANISOTROPY),this._maxAnisotropy=t,this.bind(),ti.EXT_TEXTURE_FILTER_ANISOTROPIC&&B.gl.texParameteri(this._glTarget,ti.EXT_TEXTURE_FILTER_ANISOTROPIC.TEXTURE_MAX_ANISOTROPY_EXT,t),e.bindTexture(this._glTarget,null)},get format(){return this._format},get dataType(){return this._dataType},isReady:function(){return this._isReady},bind:function(t){var e=B.gl;void 0!==t&&e.activeTexture(e.TEXTURE0+t),e.bindTexture(this._glTarget,this._texture)}};var Nt=0;function Dt(){Tt.call(this,B.gl.TEXTURE_2D),this.name="hx_texture2d_"+Nt++,this._default=Dt.DEFAULT,this._width=0,this._height=0,this.wrapMode=ii.DEFAULT}Dt._initDefault=function(){var t=new Uint8Array([255,0,255,255]);(Dt.DEFAULT=new Dt).uploadData(t,1,1,!0),Dt.DEFAULT.filter=ei.NEAREST_NOMIP},(Dt.prototype=Object.create(Tt.prototype,{numMips:{get:function(){return Math.floor(yt.log2(Math.max(this._width,this._height)))}},wrapMode:{get:function(){return this._wrapMode},set:function(t){var e=B.gl;this._wrapMode=t,this.bind(),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,t.s),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,t.t),e.bindTexture(e.TEXTURE_2D,null)}},width:{get:function(){return this._width}},height:{get:function(){return this._height}}})).initEmpty=function(t,e,i,n){this._data=null;var s=B.gl;this._format=i=i||li.RGBA,this._dataType=n=n||ci.UNSIGNED_BYTE,this.bind(),this._width=t,this._height=e;var r=li.getDefaultInternalFormat(i,n);s.texImage2D(s.TEXTURE_2D,0,r,t,e,0,i,n,null),this._isReady=!0,s.bindTexture(s.TEXTURE_2D,null)},Dt.prototype.uploadData=function(t,e,i,n,s,r,o){var a=B.gl;!ti.EXT_HALF_FLOAT_TEXTURES||r!==ci.HALF_FLOAT||t instanceof Uint16Array||(t=At.encodeToFloat16Array(t)),o||(this._width=e,this._height=i,this._format=s||li.RGBA,this._dataType=r||ci.UNSIGNED_BYTE),s=this._format,r=this._dataType,n=void 0!==n&&n,this.bind();var h=li.getDefaultInternalFormat(s,r);a.texImage2D(a.TEXTURE_2D,o||0,h,e,i,0,s,r,t),n&&a.generateMipmap(a.TEXTURE_2D),this._isReady=!0,a.bindTexture(a.TEXTURE_2D,null)},Dt.prototype.uploadImage=function(t,e,i,n,s,r,o){var a=B.gl;o||(this._width=e,this._height=i,this._format=s||li.RGBA,this._dataType=r||ci.UNSIGNED_BYTE),s=this._format,r=this._dataType,n=void 0===n||n,yt.isPowerOfTwo(e)&&yt.isPowerOfTwo(i)||(n=!1,this.filter===ei.NEAREST?this.filter=ei.NEAREST_NOMIP:this.filter===ei.BILINEAR?this.filter=ei.BILINEAR_NOMIP:this.filter!==ei.TRILINEAR&&this.filter!==ei.TRILINEAR_ANISOTROPIC||(this.filter=ei.BILINEAR_NOMIP),this.wrapMode=ii.CLAMP),this.bind();var h=li.getDefaultInternalFormat(s,r);a.texImage2D(a.TEXTURE_2D,o||0,h,s,r,t),n&&a.generateMipmap(a.TEXTURE_2D),this._isReady=!0,a.bindTexture(a.TEXTURE_2D,null)},Dt.prototype.uploadCompressedData=function(t,e,i,n,s,r){var o=B.gl;r||(this._width=e,this._height=i,this._format=li.RGBA,this._dataType=ci.UNSIGNED_BYTE),this.bind(),o.compressedTexImage2D(o.TEXTURE_2D,r||0,s,e,i,0,t),n&&o.generateMipmap(o.TEXTURE_2D),this._isReady=!0,o.bindTexture(o.TEXTURE_2D,null)},Dt.prototype.toString=function(){return"[Texture2D(name="+this.name+")]"};var Et,wt,Lt,It={getSettersPerPass:function(t){return void 0===It._passTable&&It._init(),It._findSetters(t,It._passTable)},getSettersPerInstance:function(t){return void 0===It._instanceTable&&It._init(),It._findSetters(t,It._instanceTable)},_findSetters:function(t,e){var i=[];for(var n in e)if(e.hasOwnProperty(n)){var s=t.getUniformBufferIndex(n);if(-1!==s){var r=new e[n];i.push(r),r.slot=s,r.pass=t}}return i},_init:function(){It._passTable={},It._instanceTable={},It._passTable.hx_lights=vt,It._passTable.hx_lightingCells=St}};function vt(){}function St(){}function Ot(t,e){this.x=t||0,this.y=e||0}function Ct(t,e,i,n){this.points=null,this.decayFactor=i||.99,this.initialDistance=e||1,this.maxTests=n||2e4,this.mode=void 0===t?Ct.CIRCULAR:t,this._currentDistance=0,this.reset()}function jt(t,e,i,n){this.points=null,this.mode=void 0===t?jt.SPHERICAL:t,this.initialDistance=e||1,this.decayFactor=i||.99,this.maxTests=n||2e4,this._currentDistance=0,this.reset()}function Pt(t,e,i,n){this.x=t||0,this.y=e||0,this.z=i||0,this.w=void 0===n?1:n}function bt(){this.enabled=!0,this.onChange=new r,this._targets=[]}function zt(){this._position=new q(0,0,0,1),this._rotation=new Pt,this._euler=new q(0,0,0,0),this._scale=new q(1,1,1,1),this._matrix=new Rt,this._eulerInvalid=!0,this._eulerChangeListener=new bt,this._eulerChangeListener.add(this._euler,"x"),this._eulerChangeListener.add(this._euler,"y"),this._eulerChangeListener.add(this._euler,"z"),this._eulerChangeListener.onChange.bind(this._onEulerChanged,this),this._changeListener=new bt,this._changeListener.add(this._position,"x"),this._changeListener.add(this._position,"y"),this._changeListener.add(this._position,"z"),this._changeListener.add(this._scale,"x"),this._changeListener.add(this._scale,"y"),this._changeListener.add(this._scale,"z"),this._changeListener.onChange.bind(this._invalidateMatrix,this),this._rotationChangeListener=new bt,this._rotationChangeListener.add(this._rotation,"x"),this._rotationChangeListener.add(this._rotation,"y"),this._rotationChangeListener.add(this._rotation,"z"),this._rotationChangeListener.add(this._rotation,"w"),this._rotationChangeListener.onChange.bind(this._onRotationChanged,this)}function Rt(t,e,i,n,s,r,o,a,h,u,l,c,_,d,f,p){this.set(t,e,i,n,s,r,o,a,h,u,l,c,_,d,f,p)}vt.prototype.execute=function(t){this.pass.setUniformBufferByIndex(this.slot,t._lightingUniformBuffer)},St.prototype.execute=function(t){this.pass.setUniformBufferByIndex(this.slot,t._lightingCellsUniformBuffer)},Ot.add=function(t,e,i){return(i=i||new Ot).x=t.x+e.x,i.y=t.y+e.y,i},Ot.subtract=function(t,e,i){return(i=i||new Ot).x=t.x-e.x,i.y=t.y-e.y,i},Ot.scale=function(t,e,i){return(i=i||new Ot).x=t.x*e,i.y=t.y*e,i},Ot.prototype={set:function(t,e){this.x=t,this.y=e},dot:function(t){return t.x*this.x+t.y*this.y},get lengthSqr(){return this.x*this.x+this.y*this.y},get length(){return Math.sqrt(this.x*this.x+this.y*this.y)},normalize:function(){var t=1/this.length;this.x*=t,this.y*=t},clone:function(){return new Ot(this.x,this.y)},add:function(t){this.x+=t.x,this.y+=t.y},addScaled:function(t,e){this.x+=t.x*e,this.y+=t.y*e},subtract:function(t){this.x-=t.x,this.y-=t.y},subtractScaled:function(t,e){return this.x-=t.x*e,this.y-=t.y*e,this},scale:function(t){this.x*=t,this.y*=t},negate:function(){this.x=-this.x,this.y=-this.y},negativeOf:function(t){this.x=-t.x,this.y=-t.y},abs:function(){this.x=Math.abs(this.x),this.y=Math.abs(this.y)},fromPolarCoordinates:function(t,e){this.x=t*Math.cos(e),this.y=t*Math.sin(e)},copyFrom:function(t){this.x=t.x,this.y=t.y},distanceTo:function(t){var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},squareDistanceTo:function(t){var e=t.x-this.x,i=t.y-this.y;return e*e+i*i},lerp:function(t,e,i){var n=t.x,s=t.y;this.x=n+(e.x-n)*i,this.y=s+(e.y-s)*i},maximize:function(t){t.x>this.x&&(this.x=t.x),t.y>this.y&&(this.y=t.y)},minimize:function(t){t.x>2);return i},getAdjugate:function(t,e,i){for(var n=(i=i||new Rt)._m,s=0;s<16;++s)n[s]=this.cofactor(s>>2,3&s);return i},determinant:function(){var t=this._m;return t[0]*this.determinant3x3(0,0)-t[4]*this.determinant3x3(0,1)+t[8]*this.determinant3x3(0,2)-t[12]*this.determinant3x3(0,3)},inverseOf:function(t){var e=t.determinant();if(0===e)return null;var i=1/e,n=i*t.cofactor(0,0),s=i*t.cofactor(0,1),r=i*t.cofactor(0,2),o=i*t.cofactor(0,3),a=i*t.cofactor(1,0),h=i*t.cofactor(1,1),u=i*t.cofactor(1,2),l=i*t.cofactor(1,3),c=i*t.cofactor(2,0),_=i*t.cofactor(2,1),d=i*t.cofactor(2,2),f=i*t.cofactor(2,3),p=i*t.cofactor(3,0),g=i*t.cofactor(3,1),M=i*t.cofactor(3,2),m=i*t.cofactor(3,3),A=this._m;return A[0]=n,A[1]=s,A[2]=r,A[3]=o,A[4]=a,A[5]=h,A[6]=u,A[7]=l,A[8]=c,A[9]=_,A[10]=d,A[11]=f,A[12]=p,A[13]=g,A[14]=M,A[15]=m,this},inverseAffineOf:function(t){var e=t._m,i=e[0],n=e[1],s=e[2],r=e[4],o=e[5],a=e[6],h=e[8],u=e[9],l=e[10],c=e[12],_=e[13],d=e[14],f=i*(o*l-u*a)-r*(n*l-u*s)+h*(n*a-o*s);if(0===f)return null;var p=1/f,g=(o*l-u*a)*p,M=(u*s-n*l)*p,m=(n*a-o*s)*p,A=(h*a-r*l)*p,x=(i*l-h*s)*p,y=(r*s-i*a)*p,T=(r*u-h*o)*p,N=(h*n-i*u)*p,D=(i*o-r*n)*p,E=this._m;return E[0]=g,E[1]=M,E[2]=m,E[3]=0,E[4]=A,E[5]=x,E[6]=y,E[7]=0,E[8]=T,E[9]=N,E[10]=D,E[11]=0,E[12]=-g*c-A*_-T*d,E[13]=-M*c-x*_-N*d,E[14]=-m*c-y*_-D*d,E[15]=1,this},writeNormalMatrix:function(t,e){e=e||0;var i=this._m,n=i[0],s=i[1],r=i[2],o=i[4],a=i[5],h=i[6],u=i[8],l=i[9],c=i[10],_=1/(n*(a*c-l*h)-o*(s*c-l*r)+u*(s*h-a*r));t[e]=(a*c-l*h)*_,t[e+1]=(u*h-o*c)*_,t[e+2]=(o*l-u*a)*_,t[e+3]=(l*r-s*c)*_,t[e+4]=(n*c-u*r)*_,t[e+5]=(u*s-n*l)*_,t[e+6]=(s*h-a*r)*_,t[e+7]=(o*r-n*h)*_,t[e+8]=(n*a-o*s)*_},writeData:function(t,e){e=e||0;for(var i=this._m,n=0;n<16;++n)t[e+n]=i[n]},writeData4x3:function(t,e){var i=this._m;t[e=e||0]=i[0],t[e+1]=i[4],t[e+2]=i[8],t[e+3]=i[12],t[e+4]=i[1],t[e+5]=i[5],t[e+6]=i[9],t[e+7]=i[13],t[e+8]=i[2],t[e+9]=i[6],t[e+10]=i[10],t[e+11]=i[14]},invert:function(){return this.inverseOf(this)},invertAffine:function(){return this.inverseAffineOf(this)},append:function(t){return this.multiply(t,this)},prepend:function(t){return this.multiply(this,t)},appendAffine:function(t){return this.multiplyAffine(t,this)},prependAffine:function(t){return this.multiplyAffine(this,t)},add:function(t){var e=this._m,i=t._m;return e[0]+=i[0],e[1]+=i[1],e[2]+=i[2],e[3]+=i[3],e[4]+=i[4],e[5]+=i[5],e[6]+=i[6],e[7]+=i[7],e[8]+=i[8],e[9]+=i[9],e[10]+=i[10],e[11]+=i[11],e[12]+=i[12],e[13]+=i[13],e[14]+=i[14],e[15]+=i[15],this},addAffine:function(t){var e=this._m,i=t._m;return e[0]+=i[0],e[1]+=i[1],e[2]+=i[2],e[4]+=i[4],e[5]+=i[5],e[6]+=i[6],e[8]+=i[8],e[9]+=i[9],e[10]+=i[10],this},subtract:function(t){var e=this._m,i=t._m;return e[0]-=i[0],e[1]-=i[1],e[2]-=i[2],e[3]-=i[3],e[4]-=i[4],e[5]-=i[5],e[6]-=i[6],e[7]-=i[7],e[8]-=i[8],e[9]-=i[9],e[10]-=i[10],e[11]-=i[11],e[12]-=i[12],e[13]-=i[13],e[14]-=i[14],e[15]-=i[15],this},subtractAffine:function(t){var e=this._m,i=t._m;return e[0]-=i[0],e[1]-=i[1],e[2]-=i[2],e[4]-=i[4],e[5]-=i[5],e[6]-=i[6],e[8]-=i[8],e[9]-=i[9],e[10]-=i[10],this},appendScale:function(t,e,i){t instanceof q?(e=t.y,i=t.z,t=t.x):void 0===e&&(e=i=t);var n=this._m;return n[0]*=t,n[1]*=e,n[2]*=i,n[4]*=t,n[5]*=e,n[6]*=i,n[8]*=t,n[9]*=e,n[10]*=i,n[12]*=t,n[13]*=e,n[14]*=i,this},prependScale:function(t,e,i){t instanceof q?(e=t.y,i=t.z,t=t.x):void 0===e&&(e=i=t);var n=this._m;return n[0]*=t,n[1]*=t,n[2]*=t,n[3]*=t,n[4]*=e,n[5]*=e,n[6]*=e,n[7]*=e,n[8]*=i,n[9]*=i,n[10]*=i,n[11]*=i,this},appendTranslation:function(t,e,i){void 0===e&&(e=t.y,i=t.z,t=t.x);var n=this._m;return n[12]+=t,n[13]+=e,n[14]+=i,this},prependTranslation:function(t,e,i){void 0===e&&(e=t.y,i=t.z,t=t.x);var n=this._m;return n[12]+=n[0]*t+n[4]*e+n[8]*i,n[13]+=n[1]*t+n[5]*e+n[9]*i,n[14]+=n[2]*t+n[6]*e+n[10]*i,n[15]+=n[3]*t+n[7]*e+n[11]*i,this},appendQuaternion:function(t){var e=this._m,i=t.x,n=t.y,s=t.z,r=t.w,o=1-2*(n*n+s*s),a=2*(i*n+r*s),h=2*(i*s-r*n),u=2*(i*n-r*s),l=1-2*(i*i+s*s),c=2*(n*s+r*i),_=2*(i*s+r*n),d=2*(n*s-r*i),f=1-2*(i*i+n*n),p=e[0],g=e[1],M=e[2],m=e[4],A=e[5],x=e[6],y=e[8],T=e[9],N=e[10],D=e[12],E=e[13],w=e[14];return e[0]=o*p+u*g+_*M,e[1]=a*p+l*g+d*M,e[2]=h*p+c*g+f*M,e[4]=o*m+u*A+_*x,e[5]=a*m+l*A+d*x,e[6]=h*m+c*A+f*x,e[8]=o*y+u*T+_*N,e[9]=a*y+l*T+d*N,e[10]=h*y+c*T+f*N,e[12]=o*D+u*E+_*w,e[13]=a*D+l*E+d*w,e[14]=h*D+c*E+f*w,this},prependQuaternion:function(t){var e=this._m,i=t.x,n=t.y,s=t.z,r=t.w,o=e[0],a=e[1],h=e[2],u=e[4],l=e[5],c=e[6],_=e[8],d=e[9],f=e[10],p=1-2*(n*n+s*s),g=2*(i*n+r*s),M=2*(i*s-r*n),m=2*(i*n-r*s),A=1-2*(i*i+s*s),x=2*(n*s+r*i),y=2*(i*s+r*n),T=2*(n*s-r*i),N=1-2*(i*i+n*n);return e[0]=o*p+u*g+_*M,e[1]=a*p+l*g+d*M,e[2]=h*p+c*g+f*M,e[4]=o*m+u*A+_*x,e[5]=a*m+l*A+d*x,e[6]=h*m+c*A+f*x,e[8]=o*y+u*T+_*N,e[9]=a*y+l*T+d*N,e[10]=h*y+c*T+f*N,this},appendRotationAxisAngle:function(t,e){var i=this._m,n=Math.cos(e),s=Math.sin(e),r=1/t.length,o=t.x*r,a=t.y*r,h=t.z*r,u=1-n,l=u*o*o+n,c=u*o*a+s*h,_=u*o*h-s*a,d=u*o*a-s*h,f=u*a*a+n,p=u*a*h+s*o,g=u*o*h+s*a,M=u*a*h-s*o,m=u*h*h+n,A=i[0],x=i[1],y=i[2],T=i[4],N=i[5],D=i[6],E=i[8],w=i[9],L=i[10],I=i[12],v=i[13],S=i[14];return i[0]=l*A+d*x+g*y,i[1]=c*A+f*x+M*y,i[2]=_*A+p*x+m*y,i[4]=l*T+d*N+g*D,i[5]=c*T+f*N+M*D,i[6]=_*T+p*N+m*D,i[8]=l*E+d*w+g*L,i[9]=c*E+f*w+M*L,i[10]=_*E+p*w+m*L,i[12]=l*I+d*v+g*S,i[13]=c*I+f*v+M*S,i[14]=_*I+p*v+m*S,this},prependRotationAxisAngle:function(t,e){var i=this._m,n=Math.cos(e),s=Math.sin(e),r=1/t.length,o=t.x*r,a=t.y*r,h=t.z*r,u=1-n,l=i[0],c=i[1],_=i[2],d=i[4],f=i[5],p=i[6],g=i[8],M=i[9],m=i[10],A=u*o*o+n,x=u*o*a+s*h,y=u*o*h-s*a,T=u*o*a-s*h,N=u*a*a+n,D=u*a*h+s*o,E=u*o*h+s*a,w=u*a*h-s*o,L=u*h*h+n;return i[0]=l*A+d*x+g*y,i[1]=c*A+f*x+M*y,i[2]=_*A+p*x+m*y,i[4]=l*T+d*N+g*D,i[5]=c*T+f*N+M*D,i[6]=_*T+p*N+m*D,i[8]=l*E+d*w+g*L,i[9]=c*E+f*w+M*L,i[10]=_*E+p*w+m*L,this},getRow:function(t,e){var i=this._m;return(e=e||new q).x=i[t],e.y=i[4|t],e.z=i[8|t],e.w=i[12|t],e},setRow:function(t,e){var i=this._m;return i[t]=e.x,i[4|t]=e.y,i[8|t]=e.z,i[12|t]=e.w,this},getElement:function(t,e){return this._m[t|e<<2]},setElement:function(t,e,i){return this._m[t|e<<2]=i,this},getColumn:function(t,e){var i=this._m;return t<<=2,(e=e||new q).x=i[t],e.y=i[1|t],e.z=i[2|t],e.w=i[3|t],e},setColumn:function(t,e){var i=this._m;return i[t<<=2]=e.x,i[1|t]=e.y,i[2|t]=e.z,i[3|t]=e.w,this},copyColumn:function(t,e){var i=this._m,n=e._m;return i[t<<=2]=n[t],i[1|t]=n[1|t],i[2|t]=n[2|t],i[3|t]=n[3|t],this},lookAt:(Et=new q,wt=new q,Lt=new q,function(t,e,i){if(i=i||q.Z_AXIS,q.subtract(t,e,wt),wt.normalize(),q.cross(wt,i,Et),Math.abs(Et.lengthSqr)<1e-4){var n=new q(i.x,i.z,i.y,0);q.cross(wt,n,Et),Math.abs(Et.lengthSqr)<=1e-4&&(n.set(i.z,i.y,i.z,0),q.cross(wt,n,Et))}Et.normalize(),q.cross(Et,wt,Lt);var s=this._m;return s[0]=Et.x,s[1]=Et.y,s[2]=Et.z,s[3]=0,s[4]=wt.x,s[5]=wt.y,s[6]=wt.z,s[7]=0,s[8]=Lt.x,s[9]=Lt.y,s[10]=Lt.z,s[11]=0,s[12]=e.x,s[13]=e.y,s[14]=e.z,s[15]=1,this}),compose:function(t,e,i){var n=e?t:t.position;return e=e||t.rotation,(i=i||t.scale)?this.fromScale(i):this.copyFrom(Rt.IDENTITY),this.appendQuaternion(e),this.appendTranslation(n),this},decompose:function(t,e,i){var n;t=t||new zt,n=void 0===e?(e=t.rotation,i=t.scale,t.position):t;var s=this._m,r=s[0],o=s[1],a=s[2],h=s[4],u=s[5],l=s[6],c=s[8],_=s[9],d=s[10],f=o*l-a*u,p=a*h-r*l,g=r*u-o*h,M=yt.sign(f*c+p*_+g*d);i.x=M*Math.sqrt(r*r+o*o+a*a),i.y=M*Math.sqrt(h*h+u*u+l*l),i.z=M*Math.sqrt(c*c+_*_+d*d),.999>5;return t&=~(e<<5),this._hash[e]&1<>5;t&=~(i<<5),e[i]=(e[i]||0)|1<>5;t&=~(i<<5),e[i]=(e[i]||0)&~(1<=this._morphWeights.length||(this._morphPositions[t]=e,i&&this._morphNormals&&(this._morphNormals[t]=i),this._morphWeights[t]=e?n:0)},Wi.prototype._updateBounds=function(){this._bounds=this._mesh.bounds},Wi.prototype._initMorphData=function(){if(this._morphPositions=null,this._morphNormals=null,this._morphWeights=null,this._mesh.hasMorphData){this._morphPositions=[];var t=8;this._mesh.hasMorphNormals&&(this._morphNormals=[],t=4),this._morphWeights=new Float32Array(t);for(var e=0;es&&(s=t._maximumX),t._maximumY>r&&(r=t._maximumY),t._maximumZ>o&&(o=t._maximumZ),t._minimumXthis.duration&&(this.duration=t.time)},_updateFrames:function(){this._keyFrames.sort(function(t,e){return t.time-e.time});var t=this._keyFrames[0],e=this._keyFrames[this._keyFrames.length-1];0o?(this._time=o,this._isPlaying=!1):this._time<0&&(this._time=0,this._isPlaying=!1)),0<=t){for(;this.looping&&this._time>=o;)this._currentFrameIndex=0,this._time-=o,++a;for(;++this._currentFrameIndex===s&&(this._currentFrameIndex=0),(i=n.getKeyFrame(this._currentFrameIndex)).timethis._time;);}return this.wraps=a,this.frame1=e,this.frame2=i,this.ratio=(this._time-e.time)/(i.time-e.time),!0}},$n.prototype={getWeight:function(t){return this._weights[t]},getMorphTargetName:function(t){return this._knownTargets[t]},setWeight:function(t,e){var i=this._weights[t];i!==e&&(void 0===i&&this._knownTargets.push(t),this._stateInvalid=!0,this._weights[t]=e)},update:function(){this._stateInvalid&&(this._knownTargets.sort(this._sortMorphs),this._stateInvalid=!1,this.onChange.dispatch())},clone:function(){var t=new $n;for(var e in this._weights)t.setWeight(e,this._weights[e]);return t},_sortMorphs:function(t,e){return this._weights[e.name]-this._weights[t.name]}};var ts=0;function es(t){Qi.call(this),this.name="hx_morphanimation_"+ts++,this._morphPose=t||new $n}(es.prototype=Object.create(Qi.prototype,{morphPose:{get:function(){return this._morphPose},set:function(t){this._morphPose=t,this._assignMorphPose(t)}}})).setWeight=function(t,e){this._morphPose.setWeight(t,e)},es.prototype.onAdded=function(){this.entity.morphPose=this._morphPose},es.prototype.onRemoved=function(){this.entity.morphPose=null},es.prototype.onUpdate=function(t){this._morphPose.update()},es.prototype.clone=function(){var t=new es(this._morphPose.clone());return t.name=this.name,t},Qi.register("morphAnimation",es);var is=0;function ns(){Qi.call(this),this.name="hx_layeredanimation_"+is++,this.playbackRate=1,this._layers=[],this._time=0,this._looping=!0}(ns.prototype=Object.create(Qi.prototype,{time:{get:function(){return this._time},set:function(t){this._time=t;for(var e=0;e>15,i=t>>10&31,n=1023&t;return 31===i?n?Number.NaN:e?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY:i?Math.pow(2,i-15)*(1+n/1024):n/1024*6103515625e-14},getFloat32:function(){var t=this._dataView.getFloat32(this.offset,this.endian);return this.offset+=4,t},getFloat64:function(){var t=this._dataView.getFloat64(this.offset,this.endian);return this.offset+=8,t},skipAlign:function(t){for(;this.offset%t;)++this.offset},getUint8Array:function(t){return this._readArray(t,Uint8Array,1,this.getUint8)},getUint16Array:function(t){return this._readArray(t,Uint16Array,2,this.getUint16)},getUint32Array:function(t){return this._readArray(t,Uint32Array,4,this.getUint32)},getInt8Array:function(t){return this._readArray(t,Int8Array,1,this.getInt8)},getInt16Array:function(t){return this._readArray(t,Int16Array,2,this.getInt16)},getInt32Array:function(t){return this._readArray(t,Int32Array,4,this.getInt32)},getInt64AsFloat64Array:function(t){for(var e=new Float64Array(t),i=0;i>8&255),e+=String.fromCharCode(t>>16&255),e+=String.fromCharCode(t>>24&255)){case"DXT1":return this._blockSize=8,void(this._format=ti.EXT_COMPRESSED_TEXTURE_S3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT);case"DXT3":return this._blockSize=16,void(this._format=ti.EXT_COMPRESSED_TEXTURE_S3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT);case"DXT5":return this._blockSize=16,void(this._format=ti.EXT_COMPRESSED_TEXTURE_S3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT);case"DX10":return this._blockSize=16,void this._parseDX10Header()}switch(t){case 111:return this._blockSize=1,this._format=li.RED||li.RGBA,void(this._dataType=ci.HALF_FLOAT||"Float16");case 112:return this._blockSize=2,this._format=li.RG||li.RGBA,void(this._dataType=ci.HALF_FLOAT||"Float16");case 113:return this._blockSize=4,this._format=li.RGBA,void(this._dataType=ci.HALF_FLOAT||"Float16");case 114:return this._blockSize=1,this._format=li.RED||li.RGBA,void(this._dataType=ci.FLOAT);case 112:return this._blockSize=2,this._format=li.RG||li.RGBA,void(this._dataType=ci.FLOAT);case 116:return this._blockSize=4,this._format=li.RGBA,void(this._dataType=ci.FLOAT);default:return void this._notifyFailure("Unsupported texture format!")}},xr.prototype._parseData=function(){for(var t=this._type===je?6:1,e=[],i=0;i>2)*Math.max(1,s+3>>2)*this._blockSize;r=this._stream.getUint8Array(a)}e[o][i]=r,0===(n>>=1)&&(n=1),0===(s>>=1)&&(s=1)}this._uploadData(e)},xr.prototype._uploadData=function(t){for(var e=1===this._mipLevels,i=this._width,n=this._height,s="Float16"===this._dataType?ci.FLOAT:this._dataType,r=0;r>=1)&&(i=1),0===(n>>=1)&&(n=1)}},xr.prototype._parseUncompressedMipData=function(t,e){var i=t*e*this._blockSize;return this._blockSize<4&&!ti.WEBGL_2?this._parseUnsupportedFormat(i):this._parseStraightDataBlock(i)},xr.prototype._parseUnsupportedFormat=function(t){var e,i;switch(t=t/this._blockSize*4,this._dataType){case ci.FLOAT:e=new Float32Array(t),i=this._stream.getFloat32.bind(this._stream);break;case ci.HALF_FLOAT:e=new Uint16Array(t),i=this._stream.getUint16.bind(this._stream);break;case"Float16":e=new Float32Array(t),i=this._stream.getFloat16.bind(this._stream)}for(var n=0,s=0;s>1;(n=n||new Dt).initEmpty(e,s,t.format,Dr(t.dataType)),fr||(fr=new we(f.get("equirectangular_from_cube_fragment.glsl")));var r=B.getCurrentRenderTarget(),o=new gt(n);return o.init(),B.setRenderTarget(o),B.clear(),fr.execute(t),B.setRenderTarget(r),i&&n.generateMipmap(),n}};function Dr(t){return t!==ci.HALF_FLOAT||ti.EXT_COLOR_BUFFER_HALF_FLOAT?t!==ci.FLOAT||ti.EXT_COLOR_BUFFER_FLOAT||(t=ti.EXT_COLOR_BUFFER_HALF_FLOAT?ci.HALF_FLOAT:ci.UNSIGNED_BYTE):t=ti.EXT_COLOR_BUFFER_FLOAT?ci.FLOAT:ci.UNSIGNED_BYTE,t}function Er(){ar.call(this,or.DATA_BINARY)}(Er.prototype=Object.create(ar.prototype)).parse=function(t,e){var i;this.options.equiToCube?(i=new Dt,e=e||new je):(e=e||new Dt,i=this.options.heightMap?new Dt:e),this._stream=new zs(t),this._stream.endian=js,this._texture=i,this._generateMips=void 0===this.options.generateMipmaps||this.options.generateMipmaps,this._flipY=!1,this._gamma=1,this._exposure=Math.pow(2,this.options.exposure||0),this._colorCorr=new T(1,1,1),this._parseHeader(),this._parseData(),this.options.equiToCube&&Nr.toCube(i,this.options.cubeSize,this._generateMips,e),this._notifyComplete(e)},Er.prototype._parseHeader=function(){var t=this._readLine();for(console.assert("#?RADIANCE"===t||"#?RGBE"===t,"Incorrect file format!");""!==t;){var e=(t=this._readLine()).split("=");switch(e[0]){case"GAMMA":this._gamma=parseFloat(e[1]);break;case"FORMAT":console.assert("32-bit_rle_rgbe"===e[1]||"32-bit_rle_xyze"===e[1],"Incorrect format!");break;case"EXPOSURE":this._exposure*=parseFloat(e[1]);break;case"COLORCORR":var i=e[1].replace(/^\s+|\s+$/g,"").split(" ");this._colorCorr.set(i[0],i[1],i[2])}}e=(t=this._readLine()).split(" "),this._parseSize(e[0],parseInt(e[1])),this._parseSize(e[2],parseInt(e[3]))},Er.prototype._parseSize=function(t,e){switch(t){case"+X":this._width=e;break;case"-X":this._width=e,console.warn("Flipping horizontal orientation not currently supported");break;case"-Y":this._height=e;break;case"+Y":this._height=e,console.warn("Flipping vertical orientation not currently supported")}},Er.prototype._readLine=function(){for(var t,e="";"\n"!==(t=this._stream.getChar());)e+=t;return e},Er.prototype._parseData=function(){var t,e=this._stream.getUint16();if(this._stream.offset-=2,514===e){t=this._parseNewRLE();var i=ti.HDR_DATA_TYPE;i!==ci.HALF_FLOAT||ti.CAN_UPLOAD_HALF_FLOAT||(i=ci.FLOAT),this._texture.uploadData(t,this._width,this._height,this._generateMips,li.RGB,i)}else this._notifyFailure("Obsolete HDR file version!")},Er.prototype._parseNewRLE=function(){for(var t=!this.options.ldr&&ti.HDR_DATA_TYPE!==ci.UNSIGNED_BYTE,e=this._width*this._height,i=this._width,n=new(t?Float32Array:Uint8Array)(3*e),s=0,r=0;r=E._lodRangeStartSqr&&m=_._lodRangeStartSqr&&u<_._lodRangeEndSqr&&0!==_.numInstances&&this.visitMeshInstance(_,n,i,u)}}},_h.prototype.visitMeshInstance=function(t,e,i,n){for(var s=t.skeleton,r=t.skeletonMatrices,o=De.DIR_LIGHT_SHADOW_MAP_PASS,a=He.OPTIONS.numShadowCascades,h=0;h=_._lodRangeStartSqr&&u<_._lodRangeEndSqr&&0!==_.numInstances&&this.visitMeshInstance(_,n,i,u)}},yh.prototype.visitMeshInstance=function(t,e,i,n){var s=this._octantPlanes,r=i.classifyAgainstPlane(s[0]),o=i.classifyAgainstPlane(s[1]),a=i.classifyAgainstPlane(s[2]),h=i.classifyAgainstPlane(s[3]),u=i.classifyAgainstPlane(s[4]),l=i.classifyAgainstPlane(s[5]);0<=o&&a<=0&&0<=u&&l<=0&&this._addTo(t,0,i,e,n),o<=0&&0<=a&&u<=0&&0<=l&&this._addTo(t,1,i,e,n),0<=r&&h<=0&&0<=u&&0<=l&&this._addTo(t,2,i,e,n),r<=0&&0<=h&&u<=0&&l<=0&&this._addTo(t,3,i,e,n),r<=0&&o<=0&&a<=0&&h<=0&&this._addTo(t,4,i,e,n),0<=r&&0<=o&&0<=a&&0<=h&&this._addTo(t,5,i,e,n)},yh.prototype._addTo=function(t,e,i,n,s){var r=t.skeleton,o=t.skeletonMatrices,a=this._renderItemPool,h=this._renderLists[e],u=t.material,l=a.getItem();l.material=u,l.meshInstance=t,l.skeleton=r,l.skeletonMatrices=o,l.renderOrderHint=s,l.worldBounds=i,h.push(l)},yh.prototype.qualifiesBounds=function(t){return t.intersectsBound(this._lightBounds)},yh.prototype.qualifies=function(t,e){return t.hierarchyVisible&&(e||t.worldBounds.intersectsBound(this._lightBounds))},Th.prototype={render:(dh=new q,function(t,e,i,n){var s=t.entity;s.worldMatrix.getColumn(3,dh),this._cubeCamera.farDistance=t._radius,this._cubeCamera.position=dh,this._casterCollector.setLightBounds(s.worldBounds),this._casterCollector.collect(this._cubeCamera,n,i),B.setInvertCulling(!0);for(var r=1/e.size,o=0;o<6;++o){var a=e.getNextRect(),h=this._cubeCamera.getFaceCamera(o);B.setViewport(a);var u=a.width*r,l=a.height*r,c=a.x*r,_=a.y*r;t._shadowTiles[o].set(.5*u,.5*l,.5*u+c,.5*l+_),hh(this,h,De.POINT_LIGHT_SHADOW_MAP_PASS,this._casterCollector.getRenderList(o),t)}B.setInvertCulling(!1),B.setColorMask(!0)})},(Nh.prototype=Object.create(jn.prototype)).getRenderList=function(){return this._renderList},Nh.prototype.collect=function(t,e,i){this.reset(),this._camera=t,this._renderList=[],i.worldMatrix.getColumn(3,this._viewCameraPos),t.worldMatrix.getColumn(1,this._cameraYAxis),this._frustumPlanes=t.frustum.planes,this._renderItemPool.reset(),e.acceptVisitor(this),this._renderList.sort(nh)},Nh.prototype.visitEntity=function(t){var e=t.components.meshInstance;if(e)for(var i=0,n=e.length;i=s._lodRangeStartSqr&&_n.t*n.t)break;r.transformFrom(s,a.objectMatrix),this._testMesh(r,a.meshInstance.mesh,n)&&(t=a.worldMatrix,n.entity=a.meshInstance.entity,n.component=a.meshInstance)}return n.entity&&(t.transformPoint(n.point,n.point),t.transformNormal(n.faceNormal,n.faceNormal)),n},Gh.prototype._testMesh=function(t,e,i){for(var n=t.direction,s=t.origin,r=s.x,o=s.y,a=s.z,h=n.x,u=n.y,l=n.z,c=e.getVertexAttributeByName("hx_position"),_=e.getVertexData(c.streamIndex),d=e.getIndexData(),f=e.getVertexStride(c.streamIndex),p=d.length,g=c.offset,M=!1,m=0;m=i.t)){var z=b*h+r,R=b*u+o,U=b*l+a,B=z-T,F=R-N,k=U-D,Y=E*E+w*w+L*L,Q=I*I+v*v+S*S,G=E*I+w*v+L*S,V=Y*Q-G*G;if(0!==V){var X=B*E+F*w+k*L,H=B*I+F*v+k*S,W=1/V,Z=(Q*X-G*H)*W,q=(Y*H-G*X)*W,K=1-Z-q;0<=K&&K<=1&&0<=Z&&Z<=1&&0<=q&&q<=1&&(i.faceNormal.set(O,C,j,0),i.point.set(z,R,U,1),i.barycentric.set(K,Z,q,0),i.mesh=e,i.t=b,i.faceIndex=m,M=!0)}}}}return i.faceNormal.normalize(),M},Gh.prototype._sortPotentialFunc=function(t,e){return t.closestDistanceSqr-e.closestDistanceSqr},Hh.prototype={update:function(t){this._currentFPS=1e3/t,this._runningSum-=this._frames[this._index],this._runningSum+=this._currentFPS,this._averageFPS=this._runningSum/this._numFrames,this._frames[this._index++]=this._currentFPS,this._index===this._numFrames&&(this._index=0),(void 0===this._maxFPS||this._currentFPS>this._maxFPS)&&(this._maxFPS=this._currentFPS),(void 0===this._minFPS||this._currentFPSt.TEXTURE31){console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"),n.push(null,null);break}s||(s=t.getParameter(t.ACTIVE_TEXTURE)),t.activeTexture(a),n.push(t.getParameter(o),null);break;case t.ACTIVE_TEXTURE:s=t.getParameter(t.ACTIVE_TEXTURE),n.push(null);break;default:n.push(t.getParameter(o))}}i(t);for(var r=0;rt.TEXTURE31)break;t.activeTexture(a),t.bindTexture(t.TEXTURE_2D,h);break;case t.TEXTURE_BINDING_CUBE_MAP:var a=e[++r];if(at.TEXTURE31)break;t.activeTexture(a),t.bindTexture(t.TEXTURE_CUBE_MAP,h);break;case t.VIEWPORT:t.viewport(h[0],h[1],h[2],h[3]);break;case t.BLEND:case t.CULL_FACE:case t.DEPTH_TEST:case t.SCISSOR_TEST:case t.STENCIL_TEST:h?t.enable(o):t.disable(o);break;default:console.log("No GL restore behavior for 0x"+o.toString(16))}s&&t.activeTexture(s)}}else i(t)},S=["attribute vec2 position;","attribute vec3 texCoord;","varying vec2 vTexCoord;","uniform vec4 viewportOffsetScale[2];","void main() {"," vec4 viewport = viewportOffsetScale[int(texCoord.z)];"," vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;"," gl_Position = vec4( position, 1.0, 1.0 );","}"].join("\n"),O=["precision mediump float;","uniform sampler2D diffuse;","varying vec2 vTexCoord;","void main() {"," gl_FragColor = texture2D(diffuse, vTexCoord);","}"].join("\n");function C(t,e,i,n){this.gl=t,this.cardboardUI=e,this.bufferScale=i,this.dirtySubmitFrameBindings=n,this.ctxAttribs=t.getContextAttributes(),this.meshWidth=20,this.meshHeight=20,this.bufferWidth=t.drawingBufferWidth,this.bufferHeight=t.drawingBufferHeight,this.realBindFramebuffer=t.bindFramebuffer,this.realEnable=t.enable,this.realDisable=t.disable,this.realColorMask=t.colorMask,this.realClearColor=t.clearColor,this.realViewport=t.viewport,c()||(this.realCanvasWidth=Object.getOwnPropertyDescriptor(t.canvas.__proto__,"width"),this.realCanvasHeight=Object.getOwnPropertyDescriptor(t.canvas.__proto__,"height")),this.isPatched=!1,this.lastBoundFramebuffer=null,this.cullFace=!1,this.depthTest=!1,this.blend=!1,this.scissorTest=!1,this.stencilTest=!1,this.viewport=[0,0,0,0],this.colorMask=[!0,!0,!0,!0],this.clearColor=[0,0,0,0],this.attribs={position:0,texCoord:1},this.program=A(t,S,O,this.attribs),this.uniforms=x(t,this.program),this.viewportOffsetScale=new Float32Array(8),this.setTextureBounds(),this.vertexBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),this.indexCount=0,this.renderTarget=t.createTexture(),this.framebuffer=t.createFramebuffer(),this.depthStencilBuffer=null,this.depthBuffer=null,this.stencilBuffer=null,this.ctxAttribs.depth&&this.ctxAttribs.stencil?this.depthStencilBuffer=t.createRenderbuffer():this.ctxAttribs.depth?this.depthBuffer=t.createRenderbuffer():this.ctxAttribs.stencil&&(this.stencilBuffer=t.createRenderbuffer()),this.patch(),this.onResize()}C.prototype.destroy=function(){var t=this.gl;this.unpatch(),t.deleteProgram(this.program),t.deleteBuffer(this.vertexBuffer),t.deleteBuffer(this.indexBuffer),t.deleteTexture(this.renderTarget),t.deleteFramebuffer(this.framebuffer),this.depthStencilBuffer&&t.deleteRenderbuffer(this.depthStencilBuffer),this.depthBuffer&&t.deleteRenderbuffer(this.depthBuffer),this.stencilBuffer&&t.deleteRenderbuffer(this.stencilBuffer),this.cardboardUI&&this.cardboardUI.destroy()},C.prototype.onResize=function(){var t=this.gl,e=this,i=[t.RENDERBUFFER_BINDING,t.TEXTURE_BINDING_2D,t.TEXTURE0];v(t,i,function(t){e.realBindFramebuffer.call(t,t.FRAMEBUFFER,null),e.scissorTest&&e.realDisable.call(t,t.SCISSOR_TEST),e.realColorMask.call(t,!0,!0,!0,!0),e.realViewport.call(t,0,0,t.drawingBufferWidth,t.drawingBufferHeight),e.realClearColor.call(t,0,0,0,1),t.clear(t.COLOR_BUFFER_BIT),e.realBindFramebuffer.call(t,t.FRAMEBUFFER,e.framebuffer),t.bindTexture(t.TEXTURE_2D,e.renderTarget),t.texImage2D(t.TEXTURE_2D,0,e.ctxAttribs.alpha?t.RGBA:t.RGB,e.bufferWidth,e.bufferHeight,0,e.ctxAttribs.alpha?t.RGBA:t.RGB,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e.renderTarget,0),e.ctxAttribs.depth&&e.ctxAttribs.stencil?(t.bindRenderbuffer(t.RENDERBUFFER,e.depthStencilBuffer),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,e.bufferWidth,e.bufferHeight),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,e.depthStencilBuffer)):e.ctxAttribs.depth?(t.bindRenderbuffer(t.RENDERBUFFER,e.depthBuffer),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_COMPONENT16,e.bufferWidth,e.bufferHeight),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.RENDERBUFFER,e.depthBuffer)):e.ctxAttribs.stencil&&(t.bindRenderbuffer(t.RENDERBUFFER,e.stencilBuffer),t.renderbufferStorage(t.RENDERBUFFER,t.STENCIL_INDEX8,e.bufferWidth,e.bufferHeight),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.STENCIL_ATTACHMENT,t.RENDERBUFFER,e.stencilBuffer)),!t.checkFramebufferStatus(t.FRAMEBUFFER)===t.FRAMEBUFFER_COMPLETE&&console.error("Framebuffer incomplete!"),e.realBindFramebuffer.call(t,t.FRAMEBUFFER,e.lastBoundFramebuffer),e.scissorTest&&e.realEnable.call(t,t.SCISSOR_TEST),e.realColorMask.apply(t,e.colorMask),e.realViewport.apply(t,e.viewport),e.realClearColor.apply(t,e.clearColor)}),this.cardboardUI&&this.cardboardUI.onResize()},C.prototype.patch=function(){if(!this.isPatched){var s=this,e=this.gl.canvas,r=this.gl;c()||(e.width=g()*this.bufferScale,e.height=M()*this.bufferScale,Object.defineProperty(e,"width",{configurable:!0,enumerable:!0,get:function(){return s.bufferWidth},set:function(t){s.bufferWidth=t,s.realCanvasWidth.set.call(e,t),s.onResize()}}),Object.defineProperty(e,"height",{configurable:!0,enumerable:!0,get:function(){return s.bufferHeight},set:function(t){s.bufferHeight=t,s.realCanvasHeight.set.call(e,t),s.onResize()}})),this.lastBoundFramebuffer=r.getParameter(r.FRAMEBUFFER_BINDING),null==this.lastBoundFramebuffer&&(this.lastBoundFramebuffer=this.framebuffer,this.gl.bindFramebuffer(r.FRAMEBUFFER,this.framebuffer)),this.gl.bindFramebuffer=function(t,e){s.lastBoundFramebuffer=e||s.framebuffer,s.realBindFramebuffer.call(r,t,s.lastBoundFramebuffer)},this.cullFace=r.getParameter(r.CULL_FACE),this.depthTest=r.getParameter(r.DEPTH_TEST),this.blend=r.getParameter(r.BLEND),this.scissorTest=r.getParameter(r.SCISSOR_TEST),this.stencilTest=r.getParameter(r.STENCIL_TEST),r.enable=function(t){switch(t){case r.CULL_FACE:s.cullFace=!0;break;case r.DEPTH_TEST:s.depthTest=!0;break;case r.BLEND:s.blend=!0;break;case r.SCISSOR_TEST:s.scissorTest=!0;break;case r.STENCIL_TEST:s.stencilTest=!0}s.realEnable.call(r,t)},r.disable=function(t){switch(t){case r.CULL_FACE:s.cullFace=!1;break;case r.DEPTH_TEST:s.depthTest=!1;break;case r.BLEND:s.blend=!1;break;case r.SCISSOR_TEST:s.scissorTest=!1;break;case r.STENCIL_TEST:s.stencilTest=!1}s.realDisable.call(r,t)},this.colorMask=r.getParameter(r.COLOR_WRITEMASK),r.colorMask=function(t,e,i,n){s.colorMask[0]=t,s.colorMask[1]=e,s.colorMask[2]=i,s.colorMask[3]=n,s.realColorMask.call(r,t,e,i,n)},this.clearColor=r.getParameter(r.COLOR_CLEAR_VALUE),r.clearColor=function(t,e,i,n){s.clearColor[0]=t,s.clearColor[1]=e,s.clearColor[2]=i,s.clearColor[3]=n,s.realClearColor.call(r,t,e,i,n)},this.viewport=r.getParameter(r.VIEWPORT),r.viewport=function(t,e,i,n){s.viewport[0]=t,s.viewport[1]=e,s.viewport[2]=i,s.viewport[3]=n,s.realViewport.call(r,t,e,i,n)},this.isPatched=!0,D(e)}},C.prototype.unpatch=function(){if(this.isPatched){var t=this.gl,e=this.gl.canvas;c()||(Object.defineProperty(e,"width",this.realCanvasWidth),Object.defineProperty(e,"height",this.realCanvasHeight)),e.width=this.bufferWidth,e.height=this.bufferHeight,t.bindFramebuffer=this.realBindFramebuffer,t.enable=this.realEnable,t.disable=this.realDisable,t.colorMask=this.realColorMask,t.clearColor=this.realClearColor,t.viewport=this.realViewport,this.lastBoundFramebuffer==this.framebuffer&&t.bindFramebuffer(t.FRAMEBUFFER,null),this.isPatched=!1,setTimeout(function(){D(e)},1)}},C.prototype.setTextureBounds=function(t,e){t||(t=[0,0,.5,1]),e||(e=[.5,0,.5,1]),this.viewportOffsetScale[0]=t[0],this.viewportOffsetScale[1]=t[1],this.viewportOffsetScale[2]=t[2],this.viewportOffsetScale[3]=t[3],this.viewportOffsetScale[4]=e[0],this.viewportOffsetScale[5]=e[1],this.viewportOffsetScale[6]=e[2],this.viewportOffsetScale[7]=e[3]},C.prototype.submitFrame=function(){var t=this.gl,e=this,i=[];if(this.dirtySubmitFrameBindings||i.push(t.CURRENT_PROGRAM,t.ARRAY_BUFFER_BINDING,t.ELEMENT_ARRAY_BUFFER_BINDING,t.TEXTURE_BINDING_2D,t.TEXTURE0),v(t,i,function(t){e.realBindFramebuffer.call(t,t.FRAMEBUFFER,null),e.cullFace&&e.realDisable.call(t,t.CULL_FACE),e.depthTest&&e.realDisable.call(t,t.DEPTH_TEST),e.blend&&e.realDisable.call(t,t.BLEND),e.scissorTest&&e.realDisable.call(t,t.SCISSOR_TEST),e.stencilTest&&e.realDisable.call(t,t.STENCIL_TEST),e.realColorMask.call(t,!0,!0,!0,!0),e.realViewport.call(t,0,0,t.drawingBufferWidth,t.drawingBufferHeight),(e.ctxAttribs.alpha||c())&&(e.realClearColor.call(t,0,0,0,1),t.clear(t.COLOR_BUFFER_BIT)),t.useProgram(e.program),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,e.indexBuffer),t.bindBuffer(t.ARRAY_BUFFER,e.vertexBuffer),t.enableVertexAttribArray(e.attribs.position),t.enableVertexAttribArray(e.attribs.texCoord),t.vertexAttribPointer(e.attribs.position,2,t.FLOAT,!1,20,0),t.vertexAttribPointer(e.attribs.texCoord,3,t.FLOAT,!1,20,8),t.activeTexture(t.TEXTURE0),t.uniform1i(e.uniforms.diffuse,0),t.bindTexture(t.TEXTURE_2D,e.renderTarget),t.uniform4fv(e.uniforms.viewportOffsetScale,e.viewportOffsetScale),t.drawElements(t.TRIANGLES,e.indexCount,t.UNSIGNED_SHORT,0),e.cardboardUI&&e.cardboardUI.renderNoState(),e.realBindFramebuffer.call(e.gl,t.FRAMEBUFFER,e.framebuffer),e.ctxAttribs.preserveDrawingBuffer||(e.realClearColor.call(t,0,0,0,0),t.clear(t.COLOR_BUFFER_BIT)),e.dirtySubmitFrameBindings||e.realBindFramebuffer.call(t,t.FRAMEBUFFER,e.lastBoundFramebuffer),e.cullFace&&e.realEnable.call(t,t.CULL_FACE),e.depthTest&&e.realEnable.call(t,t.DEPTH_TEST),e.blend&&e.realEnable.call(t,t.BLEND),e.scissorTest&&e.realEnable.call(t,t.SCISSOR_TEST),e.stencilTest&&e.realEnable.call(t,t.STENCIL_TEST),e.realColorMask.apply(t,e.colorMask),e.realViewport.apply(t,e.viewport),!e.ctxAttribs.alpha&&e.ctxAttribs.preserveDrawingBuffer||e.realClearColor.apply(t,e.clearColor)}),c()){var n=t.canvas;n.width==e.bufferWidth&&n.height==e.bufferHeight||(e.bufferWidth=n.width,e.bufferHeight=n.height,e.onResize())}},C.prototype.updateDeviceInfo=function(n){var t=this.gl,s=this,e=[t.ARRAY_BUFFER_BINDING,t.ELEMENT_ARRAY_BUFFER_BINDING];v(t,e,function(t){var e=s.computeMeshVertices_(s.meshWidth,s.meshHeight,n);if(t.bindBuffer(t.ARRAY_BUFFER,s.vertexBuffer),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),!s.indexCount){var i=s.computeMeshIndices_(s.meshWidth,s.meshHeight);t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,s.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,i,t.STATIC_DRAW),s.indexCount=i.length}})},C.prototype.computeMeshVertices_=function(t,e,i){for(var n=new Float32Array(2*t*e*5),s=i.getLeftEyeVisibleTanAngles(),r=i.getLeftEyeNoLensTanAngles(),o=i.getLeftEyeVisibleScreenRect(r),a=0,h=0;h<2;h++){for(var u=0;ue-42&&t.clientXs.clientHeight-42?i(t):t.clientX<42&&t.clientY<42&&n(t)},s.addEventListener("click",this.listener,!1)},z.prototype.onResize=function(){var t=this.gl,p=this,e=[t.ARRAY_BUFFER_BINDING];v(t,e,function(i){var r=[],o=i.drawingBufferWidth/2,t=Math.max(screen.width,screen.height)*window.devicePixelRatio,e=i.drawingBufferWidth/t,n=e*window.devicePixelRatio,s=4*n/2,a=42*n,h=28*n/2,u=14*n;function l(t,e){var i=(90-t)*b,n=Math.cos(i),s=Math.sin(i);r.push(.3125*n*h+o,.3125*s*h+h),r.push(e*n*h+o,e*s*h+h)}r.push(o-s,a),r.push(o-s,i.drawingBufferHeight),r.push(o+s,a),r.push(o+s,i.drawingBufferHeight),p.gearOffset=r.length/2;for(var c=0;c<=6;c++){var _=60*c;l(_,1),l(_+12,1),l(_+20,.75),l(_+40,.75),l(_+48,1)}function d(t,e){r.push(u+t,i.drawingBufferHeight-u-e)}p.gearVertexCount=r.length/2-p.gearOffset,p.arrowOffset=r.length/2;var f=s/Math.sin(45*b);d(0,h),d(h,0),d(h+f,f),d(f,h+f),d(f,h-f),d(0,h),d(h,2*h),d(h+f,2*h-f),d(f,h-f),d(0,h),d(f,h-s),d(28*n,h-s),d(f,h+s),d(28*n,h+s),p.arrowVertexCount=r.length/2-p.arrowOffset,i.bindBuffer(i.ARRAY_BUFFER,p.vertexBuffer),i.bufferData(i.ARRAY_BUFFER,new Float32Array(r),i.STATIC_DRAW)})},z.prototype.render=function(){var t=this.gl,e=this,i=[t.CULL_FACE,t.DEPTH_TEST,t.BLEND,t.SCISSOR_TEST,t.STENCIL_TEST,t.COLOR_WRITEMASK,t.VIEWPORT,t.CURRENT_PROGRAM,t.ARRAY_BUFFER_BINDING];v(t,i,function(t){t.disable(t.CULL_FACE),t.disable(t.DEPTH_TEST),t.disable(t.BLEND),t.disable(t.SCISSOR_TEST),t.disable(t.STENCIL_TEST),t.colorMask(!0,!0,!0,!0),t.viewport(0,0,t.drawingBufferWidth,t.drawingBufferHeight),e.renderNoState()})},z.prototype.renderNoState=function(){var t,e,i,n,s,r,o,a,h,u,l=this.gl;l.useProgram(this.program),l.bindBuffer(l.ARRAY_BUFFER,this.vertexBuffer),l.enableVertexAttribArray(this.attribs.position),l.vertexAttribPointer(this.attribs.position,2,l.FLOAT,!1,8,0),l.uniform4f(this.uniforms.color,1,1,1,1),t=this.projMat,e=0,i=l.drawingBufferWidth,n=0,s=l.drawingBufferHeight,a=1/(e-i),h=1/(n-s),u=1/((r=.1)-(o=1024)),t[0]=-2*a,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*h,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*u,t[11]=0,t[12]=(e+i)*a,t[13]=(s+n)*h,t[14]=(o+r)*u,t[15]=1,l.uniformMatrix4fv(this.uniforms.projectionMat,!1,this.projMat),l.drawArrays(l.TRIANGLE_STRIP,0,4),l.drawArrays(l.TRIANGLE_STRIP,this.gearOffset,this.gearVertexCount),l.drawArrays(l.TRIANGLE_STRIP,this.arrowOffset,this.arrowVertexCount)},R.prototype.distortInverse=function(t){for(var e=0,i=1,n=t-this.distort(e);1e-4Math.abs(t.z)?k.set(-t.y,t.x,0):k.set(0,-t.z,t.y)):k.crossVectors(t,e),this.x=k.x,this.y=k.y,this.z=k.z,this.w=Y,this.normalize(),this}};var V=new G({widthMeters:.11,heightMeters:.062,bevelMeters:.004}),X=new G({widthMeters:.1038,heightMeters:.0584,bevelMeters:.004}),H={CardboardV1:new Z({id:"CardboardV1",label:"Cardboard I/O 2014",fov:40,interLensDistance:.06,baselineLensDistance:.035,screenLensDistance:.042,distortionCoefficients:[.441,.156],inverseCoefficients:[-.4410035,.42756155,-.4804439,.5460139,-.58821183,.5733938,-.48303202,.33299083,-.17573841,.0651772,-.01488963,.001559834]}),CardboardV2:new Z({id:"CardboardV2",label:"Cardboard I/O 2015",fov:60,interLensDistance:.064,baselineLensDistance:.035,screenLensDistance:.039,distortionCoefficients:[.34,.55],inverseCoefficients:[-.33836704,-.18162185,.862655,-1.2462051,1.0560602,-.58208317,.21609078,-.05444823,.009177956,-.0009904169,6183535e-11,-16981803e-13]})};function W(t,e){this.viewer=H.CardboardV2,this.updateDeviceParams(t),this.distortion=new R(this.viewer.distortionCoefficients);for(var i=0;i 1"),0):2*Math.acos(n.w)),this.estimatedGravity.x.toFixed(1),this.estimatedGravity.y.toFixed(1),this.estimatedGravity.z.toFixed(1),this.measuredGravity.x.toFixed(1),this.measuredGravity.y.toFixed(1),this.measuredGravity.z.toFixed(1));var r=new Q;r.copy(this.filterQ),r.multiply(s),this.filterQ.slerp(r,1-this.kFilter),this.previousFilterQ.copy(this.filterQ)},tt.prototype.getOrientation=function(){return this.filterQ},tt.prototype.accelToQuaternion_=function(t){var e=new F;e.copy(t),e.normalize();var i=new Q;return i.setFromUnitVectors(new F(0,0,-1),e),i.inverse(),i},tt.prototype.gyroToQuaternionDelta_=function(t,e){var i=new Q,n=new F;return n.copy(t),n.normalize(),i.setFromAxisAngle(n,t.length()*e),i},et.prototype.getPrediction=function(t,e,i){if(!this.previousTimestampS)return this.previousQ.copy(t),this.previousTimestampS=i,t;var n=new F;n.copy(e),n.normalize();var s=e.length();if(s<20*U)return this.isDebug&&console.log("Moving slowly, at %s deg/s: no prediction",(B*s).toFixed(1)),this.outQ.copy(t),this.previousQ.copy(t),this.outQ;var r=s*this.predictionTimeS;return this.deltaQ.setFromAxisAngle(n,r),this.outQ.copy(this.previousQ),this.outQ.multiply(this.deltaQ),this.previousQ.copy(t),this.previousTimestampS=i,this.outQ},it.prototype.getPosition=function(){return null},it.prototype.getOrientation=function(){var t=void 0;if(this.isWithoutDeviceMotion&&this._deviceOrientationQ){this.deviceOrientationFixQ=this.deviceOrientationFixQ||(n=(new Q).setFromAxisAngle(new F(0,0,-1),0),s=new Q,-90===window.orientation?s.setFromAxisAngle(new F(0,1,0),Math.PI/-2):s.setFromAxisAngle(new F(0,1,0),Math.PI/2),n.multiply(s)),this.deviceOrientationFilterToWorldQ=this.deviceOrientationFilterToWorldQ||((i=new Q).setFromAxisAngle(new F(1,0,0),-Math.PI/2),i),t=this._deviceOrientationQ;var e=new Q;return e.copy(t),e.multiply(this.deviceOrientationFilterToWorldQ),e.multiply(this.resetQ),e.multiply(this.worldToScreenQ),e.multiplyQuaternions(this.deviceOrientationFixQ,e),this.yawOnly&&(e.x=0,e.z=0,e.normalize()),this.orientationOut_[0]=e.x,this.orientationOut_[1]=e.y,this.orientationOut_[2]=e.z,this.orientationOut_[3]=e.w,this.orientationOut_}var i,n,s,r=this.filter.getOrientation();t=this.posePredictor.getPrediction(r,this.gyroscope,this.previousTimestampS);var e=new Q;return e.copy(this.filterToWorldQ),e.multiply(this.resetQ),e.multiply(t),e.multiply(this.worldToScreenQ),this.yawOnly&&(e.x=0,e.z=0,e.normalize()),this.orientationOut_[0]=e.x,this.orientationOut_[1]=e.y,this.orientationOut_[2]=e.z,this.orientationOut_[3]=e.w,this.orientationOut_},it.prototype.resetPose=function(){this.resetQ.copy(this.filter.getOrientation()),this.resetQ.x=0,this.resetQ.y=0,this.resetQ.z*=-1,this.resetQ.normalize(),p()&&this.resetQ.multiply(this.inverseWorldToScreenQ),this.resetQ.multiply(this.originalPoseAdjustQ)},it.prototype.onDeviceOrientation_=function(t){this._deviceOrientationQ=this._deviceOrientationQ||new Q;var e=t.alpha,i=t.beta,n=t.gamma;e=(e||0)*Math.PI/180,i=(i||0)*Math.PI/180,n=(n||0)*Math.PI/180,this._deviceOrientationQ.setFromEulerYXZ(i,e,-n)},it.prototype.onDeviceMotion_=function(t){this.updateDeviceMotion_(t)},it.prototype.updateDeviceMotion_=function(t){var e=t.accelerationIncludingGravity,i=t.rotationRate,n=t.timeStamp/1e3,s=n-this.previousTimestampS;return s<0?L("fusion-pose-sensor:invalid:non-monotonic","Invalid timestamps detected: non-monotonic timestamp from devicemotion"):s<=.001||1l.capabilities.maxLayers)t(new Error("Invalid number of layers."));else{var i=h[0];if(i.source){var n=i.leftBounds||mt,s=i.rightBounds||At;if(u){var r=l.layer_;r.source!==i.source&&(r.source=i.source);for(var o=0;o<4;o++)r.leftBounds[o]=n[o],r.rightBounds[o]=s[o];return l.wrapForFullscreen(l.layer_.source),l.updatePresent_(),void e()}if(l.layer_={predistorted:i.predistorted,source:i.source,leftBounds:n.slice(0),rightBounds:s.slice(0)},l.waitingForPresent_=!1,l.layer_&&l.layer_.source){var a=l.wrapForFullscreen(l.layer_.source);l.addFullscreenListeners_(a,function(){var t=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;l.isPresenting=a===t,l.isPresenting?(screen.orientation&&screen.orientation.lock&&screen.orientation.lock("landscape-primary").catch(function(t){console.error("screen.orientation.lock() failed due to",t.message)}),l.waitingForPresent_=!1,l.beginPresent_(),e()):(screen.orientation&&screen.orientation.unlock&&screen.orientation.unlock(),l.removeFullscreenWrapper(),l.disableWakeLock(),l.endPresent_(),l.removeFullscreenListeners_()),l.fireVRDisplayPresentChange_()},function(){l.waitingForPresent_&&(l.removeFullscreenWrapper(),l.removeFullscreenListeners_(),l.disableWakeLock(),l.waitingForPresent_=!1,l.isPresenting=!1,t(new Error("Unable to present.")))}),function(t){if(_())return!1;if(t.requestFullscreen)t.requestFullscreen();else if(t.webkitRequestFullscreen)t.webkitRequestFullscreen();else if(t.mozRequestFullScreen)t.mozRequestFullScreen();else{if(!t.msRequestFullscreen)return!1;t.msRequestFullscreen()}return!0}(a)?(l.enableWakeLock(),l.waitingForPresent_=!0):(c()||_())&&(l.enableWakeLock(),l.isPresenting=!0,l.beginPresent_(),l.fireVRDisplayPresentChange_(),e())}l.waitingForPresent_||c()||(m(),t(new Error("Unable to present.")))}else e()}else t(new Error("VRDisplay is not capable of presenting."))})},Nt.prototype.exitPresent=function(){var i=this.isPresenting,n=this;return this.isPresenting=!1,this.layer_=null,this.disableWakeLock(),new Promise(function(t,e){i?(!m()&&c()&&(n.endPresent_(),n.fireVRDisplayPresentChange_()),_()&&(n.removeFullscreenWrapper(),n.removeFullscreenListeners_(),n.endPresent_(),n.fireVRDisplayPresentChange_()),t()):e(new Error("Was not presenting to VRDisplay."))})},Nt.prototype.getLayers=function(){return this.layer_?[this.layer_]:[]},Nt.prototype.fireVRDisplayPresentChange_=function(){var t=new CustomEvent("vrdisplaypresentchange",{detail:{display:this}});window.dispatchEvent(t)},Nt.prototype.fireVRDisplayConnect_=function(){var t=new CustomEvent("vrdisplayconnect",{detail:{display:this}});window.dispatchEvent(t)},Nt.prototype.addFullscreenListeners_=function(t,e,i){this.removeFullscreenListeners_(),this.fullscreenEventTarget_=t,this.fullscreenChangeHandler_=e,this.fullscreenErrorHandler_=i,e&&(document.fullscreenEnabled?t.addEventListener("fullscreenchange",e,!1):document.webkitFullscreenEnabled?t.addEventListener("webkitfullscreenchange",e,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenchange",e,!1):document.msFullscreenEnabled&&t.addEventListener("msfullscreenchange",e,!1)),i&&(document.fullscreenEnabled?t.addEventListener("fullscreenerror",i,!1):document.webkitFullscreenEnabled?t.addEventListener("webkitfullscreenerror",i,!1):document.mozFullScreenEnabled?document.addEventListener("mozfullscreenerror",i,!1):document.msFullscreenEnabled&&t.addEventListener("msfullscreenerror",i,!1))},Nt.prototype.removeFullscreenListeners_=function(){if(this.fullscreenEventTarget_){var t=this.fullscreenEventTarget_;if(this.fullscreenChangeHandler_){var e=this.fullscreenChangeHandler_;t.removeEventListener("fullscreenchange",e,!1),t.removeEventListener("webkitfullscreenchange",e,!1),document.removeEventListener("mozfullscreenchange",e,!1),t.removeEventListener("msfullscreenchange",e,!1)}if(this.fullscreenErrorHandler_){var i=this.fullscreenErrorHandler_;t.removeEventListener("fullscreenerror",i,!1),t.removeEventListener("webkitfullscreenerror",i,!1),document.removeEventListener("mozfullscreenerror",i,!1),t.removeEventListener("msfullscreenerror",i,!1)}this.fullscreenEventTarget_=null,this.fullscreenChangeHandler_=null,this.fullscreenErrorHandler_=null}},Nt.prototype.enableWakeLock=function(){this.wakelock_&&this.wakelock_.enable()},Nt.prototype.disableWakeLock=function(){this.wakelock_&&this.wakelock_.disable()},Nt.prototype.beginPresent_=function(){},Nt.prototype.endPresent_=function(){},Nt.prototype.submitFrame=function(t){};var Dt={ADDITIONAL_VIEWERS:[],DEFAULT_VIEWER:"",MOBILE_WAKE_LOCK:!0,DEBUG:(Nt.prototype.getEyeParameters=function(t){return null},!1),DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1},Et={LEFT:"left",RIGHT:"right"};function wt(t){var e=N({},Dt);t=N(e,t||{}),Nt.call(this,{wakelock:t.MOBILE_WAKE_LOCK}),this.config=t,this.displayName="Cardboard VRDisplay",this.capabilities=new Tt({hasPosition:!1,hasOrientation:!0,hasExternalDisplay:!1,canPresent:!0,maxLayers:1}),this.stageParameters=null,this.bufferScale_=this.config.BUFFER_SCALE,this.poseSensor_=new ot(this.config),this.distorter_=null,this.cardboardUI_=null,this.dpdb_=new K(this.config.DPDB_URL,this.onDeviceParamsUpdated_.bind(this)),this.deviceInfo_=new W(this.dpdb_.getDeviceParams(),t.ADDITIONAL_VIEWERS),this.viewerSelector_=new lt(t.DEFAULT_VIEWER),this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)),this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()),this.config.ROTATE_INSTRUCTIONS_DISABLED||(this.rotateInstructions_=new at),c()&&window.addEventListener("resize",this.onResize_.bind(this))}return(wt.prototype=Object.create(Nt.prototype))._getPose=function(){return{position:null,orientation:this.poseSensor_.getOrientation(),linearVelocity:null,linearAcceleration:null,angularVelocity:null,angularAcceleration:null}},wt.prototype._resetPose=function(){this.poseSensor_.resetPose&&this.poseSensor_.resetPose()},wt.prototype._getFieldOfView=function(t){var e;if(t==Et.LEFT)e=this.deviceInfo_.getFieldOfViewLeftEye();else{if(t!=Et.RIGHT)return console.error("Invalid eye provided: %s",t),null;e=this.deviceInfo_.getFieldOfViewRightEye()}return e},wt.prototype._getEyeOffset=function(t){var e;if(t==Et.LEFT)e=[.5*-this.deviceInfo_.viewer.interLensDistance,0,0];else{if(t!=Et.RIGHT)return console.error("Invalid eye provided: %s",t),null;e=[.5*this.deviceInfo_.viewer.interLensDistance,0,0]}return e},wt.prototype.getEyeParameters=function(t){var e=this._getEyeOffset(t),i=this._getFieldOfView(t),n={offset:e,renderWidth:.5*this.deviceInfo_.device.width*this.bufferScale_,renderHeight:this.deviceInfo_.device.height*this.bufferScale_};return Object.defineProperty(n,"fieldOfView",{enumerable:!0,get:function(){return I("VRFieldOfView","VRFrameData's projection matrices"),i}}),n},wt.prototype.onDeviceParamsUpdated_=function(t){this.config.DEBUG&&console.log("DPDB reported that device params were updated."),this.deviceInfo_.updateDeviceParams(t),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_)},wt.prototype.updateBounds_=function(){this.layer_&&this.distorter_&&(this.layer_.leftBounds||this.layer_.rightBounds)&&this.distorter_.setTextureBounds(this.layer_.leftBounds,this.layer_.rightBounds)},wt.prototype.beginPresent_=function(){var t=this.layer_.source.getContext("webgl");t||(t=this.layer_.source.getContext("experimental-webgl")),t||(t=this.layer_.source.getContext("webgl2")),t&&(this.layer_.predistorted?this.config.CARDBOARD_UI_DISABLED||(t.canvas.width=g()*this.bufferScale_,t.canvas.height=M()*this.bufferScale_,this.cardboardUI_=new z(t)):(this.config.CARDBOARD_UI_DISABLED||(this.cardboardUI_=new z(t)),this.distorter_=new C(t,this.cardboardUI_,this.config.BUFFER_SCALE,this.config.DIRTY_SUBMIT_FRAME_BINDINGS),this.distorter_.updateDeviceInfo(this.deviceInfo_)),this.cardboardUI_&&this.cardboardUI_.listen(function(t){this.viewerSelector_.show(this.layer_.source.parentElement),t.stopPropagation(),t.preventDefault()}.bind(this),function(t){this.exitPresent(),t.stopPropagation(),t.preventDefault()}.bind(this)),this.rotateInstructions_&&(p()&&y()?this.rotateInstructions_.showTemporarily(3e3,this.layer_.source.parentElement):this.rotateInstructions_.update()),this.orientationHandler=this.onOrientationChange_.bind(this),window.addEventListener("orientationchange",this.orientationHandler),this.vrdisplaypresentchangeHandler=this.updateBounds_.bind(this),window.addEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler),this.fireVRDisplayDeviceParamsChange_())},wt.prototype.endPresent_=function(){this.distorter_&&(this.distorter_.destroy(),this.distorter_=null),this.cardboardUI_&&(this.cardboardUI_.destroy(),this.cardboardUI_=null),this.rotateInstructions_&&this.rotateInstructions_.hide(),this.viewerSelector_.hide(),window.removeEventListener("orientationchange",this.orientationHandler),window.removeEventListener("vrdisplaypresentchange",this.vrdisplaypresentchangeHandler)},wt.prototype.updatePresent_=function(){this.endPresent_(),this.beginPresent_()},wt.prototype.submitFrame=function(t){if(this.distorter_)this.updateBounds_(),this.distorter_.submitFrame();else if(this.cardboardUI_&&this.layer_){var e=this.layer_.source.getContext("webgl").canvas;e.width==this.lastWidth&&e.height==this.lastHeight||this.cardboardUI_.onResize(),this.lastWidth=e.width,this.lastHeight=e.height,this.cardboardUI_.render()}},wt.prototype.onOrientationChange_=function(t){this.viewerSelector_.hide(),this.rotateInstructions_&&this.rotateInstructions_.update(),this.onResize_()},wt.prototype.onResize_=function(t){if(this.layer_){var e=this.layer_.source.getContext("webgl");e.canvas.setAttribute("style",["position: absolute","top: 0","left: 0","width: 100vw","height: 100vh","border: 0","margin: 0","padding: 0px","box-sizing: content-box"].join("; ")+";"),D(e.canvas)}},wt.prototype.onViewerChanged_=function(t){this.deviceInfo_.setViewer(t),this.distorter_&&this.distorter_.updateDeviceInfo(this.deviceInfo_),this.fireVRDisplayDeviceParamsChange_()},wt.prototype.fireVRDisplayDeviceParamsChange_=function(){var t=new CustomEvent("vrdisplaydeviceparamschange",{detail:{vrdisplay:this,deviceInfo:this.deviceInfo_}});window.dispatchEvent(t)},wt.VRFrameData=function(){this.leftProjectionMatrix=new Float32Array(16),this.leftViewMatrix=new Float32Array(16),this.rightProjectionMatrix=new Float32Array(16),this.rightViewMatrix=new Float32Array(16),this.pose=null},wt.VRDisplay=Nt,wt}()}(e={exports:{}},e.exports),(t=e.exports)&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t),a={ADDITIONAL_VIEWERS:[],DEFAULT_VIEWER:"",PROVIDE_MOBILE_VRDISPLAY:!0,GET_VR_DISPLAYS_TIMEOUT:1e3,MOBILE_WAKE_LOCK:!0,DEBUG:!1,DPDB_URL:"https://dpdb.webvr.rocks/dpdb.json",K_FILTER:.98,PREDICTION_TIME_S:.04,CARDBOARD_UI_DISABLED:!1,ROTATE_INSTRUCTIONS_DISABLED:!1,YAW_ONLY:!1,BUFFER_SCALE:.5,DIRTY_SUBMIT_FRAME_BINDINGS:!1};function h(t){this.config=r(r({},a),t),this.polyfillDisplays=[],this.enabled=!1,this.hasNative="getVRDisplays"in navigator,this.native={},this.native.getVRDisplays=navigator.getVRDisplays,this.native.VRFrameData=window.VRFrameData,this.native.VRDisplay=window.VRDisplay,(!this.hasNative||this.config.PROVIDE_MOBILE_VRDISPLAY&&n())&&(this.enable(),this.getVRDisplays().then(function(t){t&&t[0]&&t[0].fireVRDisplayConnect_&&t[0].fireVRDisplayConnect_()}))}h.prototype.getPolyfillDisplays=function(){if(this._polyfillDisplaysPopulated)return this.polyfillDisplays;if(n()){var t=new o({ADDITIONAL_VIEWERS:this.config.ADDITIONAL_VIEWERS,DEFAULT_VIEWER:this.config.DEFAULT_VIEWER,MOBILE_WAKE_LOCK:this.config.MOBILE_WAKE_LOCK,DEBUG:this.config.DEBUG,DPDB_URL:this.config.DPDB_URL,CARDBOARD_UI_DISABLED:this.config.CARDBOARD_UI_DISABLED,K_FILTER:this.config.K_FILTER,PREDICTION_TIME_S:this.config.PREDICTION_TIME_S,ROTATE_INSTRUCTIONS_DISABLED:this.config.ROTATE_INSTRUCTIONS_DISABLED,YAW_ONLY:this.config.YAW_ONLY,BUFFER_SCALE:this.config.BUFFER_SCALE,DIRTY_SUBMIT_FRAME_BINDINGS:this.config.DIRTY_SUBMIT_FRAME_BINDINGS});this.polyfillDisplays.push(t)}return this._polyfillDisplaysPopulated=!0,this.polyfillDisplays},h.prototype.enable=function(){if(this.enabled=!0,this.hasNative&&this.native.VRFrameData){var e=this.native.VRFrameData,i=new this.native.VRFrameData,n=this.native.VRDisplay.prototype.getFrameData;window.VRDisplay.prototype.getFrameData=function(t){t instanceof e?n.call(this,t):(n.call(this,i),t.pose=i.pose,s(i.leftProjectionMatrix,t.leftProjectionMatrix),s(i.rightProjectionMatrix,t.rightProjectionMatrix),s(i.leftViewMatrix,t.leftViewMatrix),s(i.rightViewMatrix,t.rightViewMatrix))}}navigator.getVRDisplays=this.getVRDisplays.bind(this),window.VRDisplay=o.VRDisplay,window.VRFrameData=o.VRFrameData},h.prototype.getVRDisplays=function(){var e,i=this,n=this.config;if(!this.hasNative)return Promise.resolve(this.getPolyfillDisplays());var s,t=this.native.getVRDisplays.call(navigator),r=new Promise(function(t){e=setTimeout(function(){console.warn("Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill."),t([])},n.GET_VR_DISPLAYS_TIMEOUT)});return(s=[t,r],Promise.race?Promise.race(s):new Promise(function(t,e){for(var i=0;i -hx_cameraNearPlaneDistance) ?\n\t\t\t\t\t\t(-hx_cameraNearPlaneDistance - ray0.z) / rayDir.z : maxDistance;\n\n vec3 ray1 = ray0 + rayDir * rayLength;\n\n // only need the w component for perspective correct interpolation\n // need to get adjusted ray end\'s uv value\n vec4 hom0 = hx_projectionMatrix * vec4(ray0, 1.0);\n vec4 hom1 = hx_projectionMatrix * vec4(ray1, 1.0);\n float rcpW0 = 1.0 / hom0.w;\n float rcpW1 = 1.0 / hom1.w;\n\n hom0 *= rcpW0;\n hom1 *= rcpW1;\n\n // expressed in pixels, so we can snap to 1\n // need to figure out the ratio between 1 pixel and the entire line "width" (if primarily vertical, it\'s actually height)\n\n // line dimensions in pixels:\n\n vec2 pixelSize = (hom1.xy - hom0.xy) * hx_renderTargetResolution * .5;\n\n // line-"width" = max(abs(pixelSize.x), abs(pixelSize.y))\n // ratio pixel/width = 1 / max(abs(pixelSize.x), abs(pixelSize.y))\n\n float stepRatio = 1.0 / max(abs(pixelSize.x), abs(pixelSize.y)) * stepSize;\n\n vec2 uvEnd = hom1.xy * .5 + .5;\n\n vec2 dUV = (uvEnd - uv) * stepRatio;\n hitUV = uv;\n\n // linear depth\n float rayDepth = (-ray0.z - hx_cameraNearPlaneDistance) * hx_rcpCameraFrustumRange;\n float rayPerspDepth0 = rayDepth * rcpW0;\n float rayPerspDepth1 = (-ray1.z - hx_cameraNearPlaneDistance) * hx_rcpCameraFrustumRange * rcpW1;\n float rayPerspDepth = rayPerspDepth0;\n // could probably optimize this:\n float dRayD = (rayPerspDepth1 - rayPerspDepth0) * stepRatio;\n\n float rcpW = rcpW0;\n float dRcpW = (rcpW1 - rcpW0) * stepRatio;\n float sceneDepth = rayDepth;\n\n float amount = 0.0;\n\n hitUV += dUV * dither.z;\n rayPerspDepth += dRayD * dither.z;\n rcpW += dRcpW * dither.z;\n\n float sampleCount;\n for (int i = 0; i < NUM_SAMPLES; ++i) {\n rayDepth = rayPerspDepth / rcpW;\n\n sceneDepth = hx_sampleLinearDepth(hx_gbufferDepth, hitUV);\n\n if (rayDepth > sceneDepth + .001) {\n amount = float(sceneDepth < 1.0);\n sampleCount = float(i);\n break;\n }\n\n hitUV += dUV;\n rayPerspDepth += dRayD;\n rcpW += dRcpW;\n }\n\n hitZ = -hx_cameraNearPlaneDistance - sceneDepth * hx_cameraFrustumRange;\n\n amount *= clamp((1.0 - (sampleCount - float(NUM_SAMPLES)) / float(NUM_SAMPLES)) * 5.0, 0.0, 1.0);\n return amount;\n}\n\nvoid main()\n{\n vec4 colorSample = hx_gammaToLinear(texture2D(hx_gbufferColor, uv));\n vec4 specularSample = texture2D(hx_gbufferSpecular, uv);\n float depth = hx_sampleLinearDepth(hx_gbufferDepth, uv);\n vec3 normalSpecularReflectance;\n float roughness;\n float metallicness;\n hx_decodeReflectionData(colorSample, specularSample, normalSpecularReflectance, roughness, metallicness);\n vec3 normal = hx_decodeNormal(texture2D(hx_gbufferNormals, uv));\n vec3 reflDir = reflect(normalize(viewDir), normal);\n\n vec3 fresnel = hx_fresnel(normalSpecularReflectance, reflDir, normal);\n // not physically correct, but attenuation is required to look good\n\n // step for every pixel\n\n float absViewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n vec3 viewSpacePos = absViewY * viewDir;\n\n float hitY = 0.0;\n vec2 hitUV;\n float amount = raytrace(viewSpacePos, reflDir, hitY, hitUV);\n float fadeFactor = 1.0 - clamp(reflDir.z * 2.0, 0.0, 1.0);\n\n vec2 borderFactors = abs(hitUV * 2.0 - 1.0);\n borderFactors = (1.0 - borderFactors) * 10.0;\n fadeFactor *= clamp(borderFactors.x, 0.0, 1.0) * clamp(borderFactors.y, 0.0, 1.0);\n\n float diff = viewSpacePos.y - hitY;\n fadeFactor *= hx_linearStep(-1.0, 0.0, diff);\n fadeFactor *= hx_linearStep(maxRoughness, 0.0, roughness);\n\n vec4 reflColor = texture2D(hx_frontBuffer, hitUV);\n\n float amountUsed = amount * fadeFactor;\n hx_FragColor = vec4(fresnel * reflColor.xyz, amountUsed);\n}\n\n',f._files["ssr_stencil_fragment.glsl"]="uniform sampler2D hx_gbufferSpecular;\n\nvarying_in vec2 uv;\n\nuniform float maxRoughness;\n\nvoid main()\n{\n vec4 specularSample = texture2D(hx_gbufferSpecular, uv);\n if (specularSample.x > maxRoughness)\n discard;\n}\n\n",f._files["taa_fragment.glsl"]="varying_in vec2 uv;\n\nuniform vec2 hx_rcpRenderTargetResolution;\nuniform sampler2D hx_backBuffer;\nuniform sampler2D historyBuffer;\n\nuniform float alpha;\nuniform float gamma;\n\nvoid main()\n{\n\tvec4 col = texture2D(hx_backBuffer, uv);\n\tvec3 c = col.xyz; // \"c\"enter\n\tvec2 oldUV = hx_getPreviousFrameUV(uv);\n\tvec3 old = texture2D(historyBuffer, oldUV).xyz;\n\tfloat amount = alpha;\n\n\t// out of bounds: take new value completely\n//\tif (oldUV.x < 0.0 || oldUV.x > 1.0 || oldUV.y < 0.0 || oldUV.y > 1.0)\n//\t amount = 1.0;\n\n // neighbourhood clamping: the old colour is only considered valid if it's within the bounds of the current neighbours\n // https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf [Karis2014]\n vec3 l = texture2D(hx_backBuffer, uv - vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 r = texture2D(hx_backBuffer, uv + vec2(hx_rcpRenderTargetResolution.x, 0.0)).xyz;\n vec3 t = texture2D(hx_backBuffer, uv - vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 b = texture2D(hx_backBuffer, uv + vec2(0.0, hx_rcpRenderTargetResolution.y)).xyz;\n vec3 minBound = min(min(min(min(l, r), t), b), c);\n vec3 maxBound = max(max(max(max(l, r), t), b), c);\n\n // just treat rgb space as a regular 3D space\n // variance clipping\n // http://developer.download.nvidia.com/gameworks/events/GDC2016/msalvi_temporal_supersampling.pdf\n // moments\n vec3 m1 = l + r + t + b + c;\n vec3 m2 = l * l + r * r + t * t + b * b + c * c;\n // variance\n vec3 mu = m1 / 5.0;\n vec3 sigma = sqrt(m2 / 5.0 - mu * mu);\n\n vec3 d = c - old;\n\n // find relevant AABB planes (those closest to the ray, know this from ray direction)\n vec3 planes = mu - sign(d) * gamma * sigma;\n\n // clip to old AABB to make sure it's never bigger\n planes = max(planes, minBound);\n planes = min(planes, maxBound);\n\n // clip segment [old -> C] against new AABB\n // C is always inside AABB\n vec3 tm = (planes - old) / d;\n vec3 absD = abs(d);\n\n float tf = (max(tm.x, tm.y), tm.z);\n\n // if already inside the box, or somehow overshooting target (?)\n if (tf >= -0.001 && tf <= 1.001)\n old += tf * d;\n\n hx_FragColor.xyz = mix(old, c, amount);\n hx_FragColor.w = col.w;\n}",f._files["tonemap_filmic_fragment.glsl"]="void main()\n{\n\tvec3 x = hx_getToneMapScaledColor().xyz * 16.0;\n\n // Uncharted 2 tonemapping (http://filmicworlds.com/blog/filmic-tonemapping-operators/)\n\n\tfloat A = 0.15;\n float B = 0.50;\n float C = 0.10;\n float D = 0.20;\n float E = 0.02;\n float F = 0.30;\n float W = 11.2;\n\n hx_FragColor.xyz = hx_gammaToLinear(((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F);\n hx_FragColor.w = 1.0;\n}",f._files["tonemap_reference_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D hx_backBuffer;\n\nvoid main()\n{\n\tvec4 color = texture2D(hx_backBuffer, uv);\n\tfloat lum = clamp(hx_luminance(color), 0.0, 1000.0);\n\tfloat l = log(1.0 + lum);\n\thx_FragColor = vec4(l, l, l, 1.0);\n}",f._files["tonemap_reinhard_fragment.glsl"]="void main()\n{\n\tvec4 color = hx_getToneMapScaledColor();\n\tfloat lum = hx_luminance(color);\n\thx_FragColor = color / (1.0 + lum);\n}",f._files["esm_blur_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D source;\nuniform vec2 direction; // this is 1/pixelSize\n\nfloat readValue(vec2 coord)\n{\n float v = texture2D(source, coord).x;\n return v;\n// return exp(HX_ESM_CONSTANT * v);\n}\n\nvoid main()\n{\n float total = readValue(uv);\n\n\tfor (int i = 1; i <= RADIUS; ++i) {\n\t vec2 offset = direction * float(i);\n\t\ttotal += readValue(uv + offset) + readValue(uv - offset);\n\t}\n\n//\thx_FragColor = vec4(log(total * RCP_NUM_SAMPLES) / HX_ESM_CONSTANT);\n\thx_FragColor = vec4(total * RCP_NUM_SAMPLES);\n}",f._files["shadow_esm.glsl"]="vec4 hx_getShadowMapValue(float depth)\n{\n // I wish we could write exp directly, but precision issues (can't encode real floats)\n return vec4(exp(HX_ESM_CONSTANT * depth));\n// so when blurring, we'll need to do ln(sum(exp())\n// return vec4(depth);\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n float shadowSample = texture2D(shadowMap, shadowMapCoord.xy).x;\n shadowMapCoord.z += depthBias;\n// float diff = shadowSample - shadowMapCoord.z;\n// return saturate(HX_ESM_DARKENING * exp(HX_ESM_CONSTANT * diff));\n return saturate(HX_ESM_DARKENING * shadowSample * exp(-HX_ESM_CONSTANT * shadowMapCoord.z));\n}",f._files["shadow_hard.glsl"]="vec4 hx_getShadowMapValue(float depth)\n{\n return hx_floatToRGBA8(depth);\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n float shadowSample = hx_RGBA8ToFloat(texture2D(shadowMap, shadowMapCoord.xy));\n float diff = shadowMapCoord.z - shadowSample - depthBias;\n return float(diff < 0.0);\n}",f._files["shadow_pcf.glsl"]="#ifdef HX_PCF_DITHER_SHADOWS\n uniform sampler2D hx_dither2D;\n uniform vec2 hx_dither2DTextureScale;\n#endif\n\nuniform vec2 hx_poissonDisk[32];\n\nvec4 hx_getShadowMapValue(float depth)\n{\n return hx_floatToRGBA8(depth);\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n float shadowTest = 0.0;\n\n #ifdef HX_PCF_DITHER_SHADOWS\n vec4 dither = hx_sampleDefaultDither(hx_dither2D, gl_FragCoord.xy * hx_dither2DTextureScale);\n dither = vec4(dither.x, -dither.y, dither.y, dither.x) * HX_PCF_SOFTNESS; // add radius scale\n #endif\n\n for (int i = 0; i < HX_PCF_NUM_SHADOW_SAMPLES; ++i) {\n vec2 offset;\n #ifdef HX_PCF_DITHER_SHADOWS\n offset.x = dot(dither.xy, hx_poissonDisk[i]);\n offset.y = dot(dither.zw, hx_poissonDisk[i]);\n #else\n offset = hx_poissonDisk[i] * HX_PCF_SOFTNESS;\n #endif\n float shadowSample = hx_RGBA8ToFloat(texture2D(shadowMap, shadowMapCoord.xy + offset));\n float diff = shadowMapCoord.z - shadowSample - depthBias;\n shadowTest += float(diff < 0.0);\n }\n\n return shadowTest * HX_PCF_RCP_NUM_SHADOW_SAMPLES;\n}",f._files["shadow_vsm.glsl"]="#derivatives\n\nvec4 hx_getShadowMapValue(float depth)\n{\n float dx = dFdx(depth);\n float dy = dFdy(depth);\n float moment2 = depth * depth + 0.25*(dx*dx + dy*dy);\n\n #if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n return vec4(depth, moment2, 0.0, 1.0);\n #else\n return vec4(hx_floatToRG8(depth), hx_floatToRG8(moment2));\n #endif\n}\n\nfloat hx_readShadow(sampler2D shadowMap, vec4 shadowMapCoord, float depthBias)\n{\n vec4 s = texture2D(shadowMap, shadowMapCoord.xy);\n #if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n vec2 moments = s.xy;\n #else\n vec2 moments = vec2(hx_RG8ToFloat(s.xy), hx_RG8ToFloat(s.zw));\n #endif\n shadowMapCoord.z += depthBias;\n\n float variance = moments.y - moments.x * moments.x;\n variance = clamp(variance + HX_VSM_MIN_VARIANCE, 0.0, 1.0);\n\n float diff = shadowMapCoord.z - moments.x;\n float upperBound = 1.0;\n\n // transparents could be closer to the light than casters\n if (diff > 0.0)\n upperBound = variance / (variance + diff*diff);\n\n return saturate((upperBound - HX_VSM_LIGHT_BLEED_REDUCTION) * HX_VSM_RCP_LIGHT_BLEED_REDUCTION_RANGE);\n}",f._files["vsm_blur_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D source;\nuniform vec2 direction; // this is 1/pixelSize\n\nvec2 readValues(vec2 coord)\n{\n vec4 s = texture2D(source, coord);\n #if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n return s.xy;\n #else\n return vec2(hx_RG8ToFloat(s.xy), hx_RG8ToFloat(s.zw));\n #endif\n}\n\nvoid main()\n{\n vec2 total = readValues(uv);\n\n\tfor (int i = 1; i <= RADIUS; ++i) {\n\t vec2 offset = direction * float(i);\n\t\ttotal += readValues(uv + offset) + readValues(uv - offset);\n\t}\n\n total *= RCP_NUM_SAMPLES;\n\n#if defined(HX_HALF_FLOAT_TEXTURES_LINEAR) || defined(HX_FLOAT_TEXTURES_LINEAR)\n hx_FragColor = vec4(total, 0.0, 1.0);\n#else\n\thx_FragColor.xy = hx_floatToRG8(total.x);\n\thx_FragColor.zw = hx_floatToRG8(total.y);\n#endif\n}",f._files["snippets_general.glsl"]="#define HX_LOG_10 2.302585093\n#define HX_PI 3.1415926\n\n#ifdef HX_GLSL_300_ES\n // replace some outdated function names\n vec4 texture2D(sampler2D s, vec2 uv) { return texture(s, uv); }\n vec4 textureCube(samplerCube s, vec3 uvw) { return texture(s, uvw); }\n\n #define vertex_attribute in\n #define varying_in in\n #define varying_out out\n\n #ifdef HX_FRAGMENT_SHADER\n out vec4 hx_FragColor;\n #endif\n#else\n #define vertex_attribute attribute\n #define varying_in varying\n #define varying_out varying\n #define hx_FragColor gl_FragColor\n#endif\n\nfloat saturate(float value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec2 saturate(vec2 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec3 saturate(vec3 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\nvec4 saturate(vec4 value)\n{\n return clamp(value, 0.0, 1.0);\n}\n\n// Only for 0 - 1\nvec4 hx_floatToRGBA8(float value)\n{\n vec4 enc = value * vec4(1.0, 255.0, 65025.0, 16581375.0);\n // cannot fract first value or 1 would not be encodable\n enc.yzw = fract(enc.yzw);\n return enc - enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);\n}\n\nfloat hx_RGBA8ToFloat(vec4 rgba)\n{\n return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));\n}\n\nvec2 hx_floatToRG8(float value)\n{\n vec2 enc = vec2(1.0, 255.0) * value;\n enc.y = fract(enc.y);\n enc.x -= enc.y / 255.0;\n return enc;\n}\n\nfloat hx_RG8ToFloat(vec2 rg)\n{\n return dot(rg, vec2(1.0, 1.0/255.0));\n}\n\nvec2 hx_encodeNormal(vec3 normal)\n{\n vec2 data;\n float p = sqrt(-normal.y*8.0 + 8.0);\n data = normal.xz / p + .5;\n return data;\n}\n\nvec2 hx_decodeMotionVector(vec4 data)\n{\n vec2 vel;\n vel.x = hx_RG8ToFloat(data.xy);\n vel.y = hx_RG8ToFloat(data.zw);\n return vel * 2.0 - 1.0;\n}\n\nvec3 hx_decodeNormal(vec4 data)\n{\n vec3 normal;\n data.xy = data.xy*4.0 - 2.0;\n float f = dot(data.xy, data.xy);\n float g = sqrt(1.0 - f * .25);\n normal.xz = data.xy * g;\n normal.y = -(1.0 - f * .5);\n return normal;\n}\n\nfloat hx_log10(float val)\n{\n return log(val) / HX_LOG_10;\n}\n\nvec4 hx_gammaToLinear(vec4 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec3 hx_gammaToLinear(vec3 color)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n color.x = pow(color.x, 2.2);\n color.y = pow(color.y, 2.2);\n color.z = pow(color.z, 2.2);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n color.xyz *= color.xyz;\n #endif\n return color;\n}\n\nvec4 hx_linearToGamma(vec4 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\nvec3 hx_linearToGamma(vec3 linear)\n{\n #if defined(HX_GAMMA_CORRECTION_PRECISE)\n linear.x = pow(linear.x, 0.454545);\n linear.y = pow(linear.y, 0.454545);\n linear.z = pow(linear.z, 0.454545);\n #elif defined(HX_GAMMA_CORRECTION_FAST)\n linear.xyz = sqrt(linear.xyz);\n #endif\n return linear;\n}\n\n/*float hx_sampleLinearDepth(sampler2D tex, vec2 uv)\n{\n return hx_RGBA8ToFloat(texture2D(tex, uv));\n}*/\n\nfloat hx_decodeLinearDepth(vec4 samp)\n{\n return hx_RG8ToFloat(samp.zw);\n}\n\nvec3 hx_getFrustumVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unprojNear = unprojectionMatrix * vec4(position, -1.0, 1.0);\n vec4 unprojFar = unprojectionMatrix * vec4(position, 1.0, 1.0);\n return unprojFar.xyz/unprojFar.w - unprojNear.xyz/unprojNear.w;\n}\n\n// view vector with z = 1, so we can use nearPlaneDist + linearDepth * (farPlaneDist - nearPlaneDist) as a scale factor to find view space position\nvec3 hx_getLinearDepthViewVector(vec2 position, mat4 unprojectionMatrix)\n{\n vec4 unproj = unprojectionMatrix * vec4(position, 0.0, 1.0);\n unproj /= unproj.w;\n return unproj.xyz / unproj.y;\n}\n\n// THIS IS FOR NON_LINEAR DEPTH!\nfloat hx_depthToViewY(float depth, mat4 projectionMatrix)\n{\n return projectionMatrix[3][2] / (depth * 2.0 - 1.0 - projectionMatrix[1][2]);\n}\n\nvec3 hx_getNormalSpecularReflectance(float metallicness, float insulatorNormalSpecularReflectance, vec3 color)\n{\n return mix(vec3(insulatorNormalSpecularReflectance), color, metallicness);\n}\n\nvec3 hx_fresnel(vec3 normalSpecularReflectance, vec3 lightDir, vec3 halfVector)\n{\n float cosAngle = 1.0 - max(dot(halfVector, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n return normalSpecularReflectance + (1.0 - normalSpecularReflectance) * power;\n}\n\n// https://seblagarde.wordpress.com/2011/08/17/hello-world/\nvec3 hx_fresnelProbe(vec3 normalSpecularReflectance, vec3 lightDir, vec3 normal, float roughness)\n{\n float cosAngle = 1.0 - max(dot(normal, lightDir), 0.0);\n // to the 5th power\n float power = pow(cosAngle, 5.0);\n float gloss = (1.0 - roughness) * (1.0 - roughness);\n vec3 bound = max(vec3(gloss), normalSpecularReflectance);\n return normalSpecularReflectance + (bound - normalSpecularReflectance) * power;\n}\n\n\nfloat hx_luminance(vec4 color)\n{\n return dot(color.xyz, vec3(.30, 0.59, .11));\n}\n\nfloat hx_luminance(vec3 color)\n{\n return dot(color, vec3(.30, 0.59, .11));\n}\n\n// linear variant of smoothstep\nfloat hx_linearStep(float lower, float upper, float x)\n{\n return clamp((x - lower) / (upper - lower), 0.0, 1.0);\n}\n\nvec4 hx_sampleDefaultDither(sampler2D ditherTexture, vec2 uv)\n{\n vec4 s = texture2D(ditherTexture, uv);\n\n #ifndef HX_FLOAT_TEXTURES\n s = s * 2.0 - 1.0;\n #endif\n\n return s;\n}\n\nvec3 hx_evaluateSH(vec3 sh[9], vec3 dir)\n{\n dir = dir.xzy;\n vec3 col = sh[0] +\n sh[1] * dir.y + sh[2] * dir.z + sh[3] * dir.x +\n sh[4] * dir.x * dir.y + sh[5] * dir.y * dir.z + sh[6] * (3.0 * dir.z * dir.z - 1.0) +\n sh[7] * dir.z * dir.x + sh[8] * (dir.x * dir.x - dir.y * dir.y);\n\n col = max(col, vec3(0.0));\n return col;\n}\n\n// I'm keeping this for reference, even tho it doesn't work in iOS\nvoid hx_sumSH(in vec3 a[9], in float weight, inout vec3 b[9])\n{\n // have to manually unroll this, on some platforms the loop is weirdly slow\n b[0] += a[0] * weight;\n b[1] += a[1] * weight;\n b[2] += a[2] * weight;\n b[3] += a[3] * weight;\n b[4] += a[4] * weight;\n b[5] += a[5] * weight;\n b[6] += a[6] * weight;\n b[7] += a[7] * weight;\n b[8] += a[8] * weight;\n}\n\nvec3 hx_intersectCubeMap(vec3 rayOrigin, vec3 cubeCenter, vec3 rayDir, float cubeSize)\n{\n vec3 t = (cubeSize * sign(rayDir) - (rayOrigin - cubeCenter)) / rayDir;\n float minT = min(min(t.x, t.y), t.z);\n return rayOrigin + minT * rayDir;\n}\n\n// sadly, need a parameter due to a bug in Internet Explorer / Edge. Just pass in 0.\n#ifdef HX_USE_SKINNING_TEXTURE\n#define HX_RCP_MAX_SKELETON_JOINTS 1.0 / float(HX_MAX_SKELETON_JOINTS - 1)\nmat4 hx_getSkinningMatrixImpl(vec4 weights, vec4 indices, sampler2D tex)\n{\n mat4 m = mat4(0.0);\n for (int i = 0; i < 4; ++i) {\n mat4 t;\n float index = indices[i] * HX_RCP_MAX_SKELETON_JOINTS;\n t[0] = texture2D(tex, vec2(index, 0.0));\n t[1] = texture2D(tex, vec2(index, 0.5));\n t[2] = texture2D(tex, vec2(index, 1.0));\n t[3] = vec4(0.0, 0.0, 0.0, 1.0);\n m += weights[i] * t;\n }\n return m;\n}\n#define hx_getSkinningMatrix(v) hx_getSkinningMatrixImpl(hx_jointWeights, hx_jointIndices, hx_skinningTexture)\n#else\n#define hx_getSkinningMatrix(v) ( hx_jointWeights.x * mat4(hx_skinningMatrices[int(hx_jointIndices.x) * 3], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.x) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.y * mat4(hx_skinningMatrices[int(hx_jointIndices.y) * 3], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.y) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.z * mat4(hx_skinningMatrices[int(hx_jointIndices.z) * 3], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.z) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) + hx_jointWeights.w * mat4(hx_skinningMatrices[int(hx_jointIndices.w) * 3], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 1], hx_skinningMatrices[int(hx_jointIndices.w) * 3 + 2], vec4(0.0, 0.0, 0.0, 1.0)) )\n#endif",f._files["snippets_geometry.glsl"]="struct HX_GeometryData\n{\n vec4 color;\n vec3 normal;\n float metallicness;\n float normalSpecularReflectance;\n float roughness;\n float occlusion;\n vec3 emission;\n vec4 data; // this can be anything the lighting model requires\n #ifdef HX_USE_TRANSLUCENCY\n vec3 translucency;\n #endif\n};",f._files["snippets_reproject.glsl"]='#ifdef HX_MOTION_VECTORS\nuniform sampler2D hx_motionVectorBuffer;\n#else\nuniform sampler2D hx_normalDepthBuffer;\nuniform float hx_cameraNearPlaneDistance;\nuniform float hx_cameraFrustumRange;\nuniform mat4 hx_inverseProjectionMatrix;\nuniform mat4 hx_cameraWorldMatrix;\nuniform mat4 hx_prevViewProjectionMatrix;\nuniform vec2 hx_cameraJitter;\n#endif\n\n\nvec2 hx_getMotionVector(vec2 uv)\n{\n#ifdef HX_MOTION_VECTORS\n return hx_decodeMotionVector(texture2D(hx_motionVectorBuffer, uv));\n#else\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n float depth = hx_decodeLinearDepth(normalDepth);\n float absViewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n\n // unproject any point on the view ray to view space:\n vec2 ndc = uv * 2.0 - 1.0;\n // view projection matrix is jittered, so hx_inverseProjectionMatrix will "unjitter"\n // so we need to reapply the jitter to counter this\n vec3 viewDir = hx_getLinearDepthViewVector(ndc + hx_cameraJitter, hx_inverseProjectionMatrix);\n\n // reconstruct world position based on linear depth\n vec3 viewPos = viewDir * absViewY;\n vec4 worldPos = hx_cameraWorldMatrix * vec4(viewPos, 1.0);\n\n // reproject with previous frame matrix\n vec4 oldProj = hx_prevViewProjectionMatrix * worldPos;\n return (ndc - oldProj.xy / oldProj.w) * .5;\n#endif\n}\n\nvec2 hx_getPreviousFrameUV(vec2 currentUV)\n{\n return currentUV - hx_getMotionVector(currentUV);\n}',f._files["snippets_tonemap.glsl"]="varying_in vec2 uv;\n\n#ifdef HX_ADAPTIVE\nuniform sampler2D hx_luminanceMap;\nuniform float hx_luminanceMipLevel;\n#endif\n\nuniform float hx_exposure;\nuniform float hx_key;\n\nuniform sampler2D hx_backBuffer;\n\n\nvec4 hx_getToneMapScaledColor()\n{\n #ifdef HX_ADAPTIVE\n #ifdef HX_GLSL_300_ES\n float referenceLuminance = textureLod(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #else\n float referenceLuminance = texture2DLodEXT(hx_luminanceMap, uv, hx_luminanceMipLevel).x;\n #endif\n referenceLuminance = exp(referenceLuminance) - 1.0;\n referenceLuminance = clamp(referenceLuminance, .08, 1000.0);\n\tfloat exposure = hx_key / referenceLuminance * hx_exposure;\n\t#else\n\tfloat exposure = hx_exposure;\n\t#endif\n return texture2D(hx_backBuffer, uv) * exposure;\n}",f._files["2d_to_cube_vertex.glsl"]="// position to write to\nvertex_attribute vec4 hx_position;\n\n// the corner of the cube map\nvertex_attribute vec3 corner;\n\nvarying_out vec3 direction;\n\nvoid main()\n{\n direction = corner;\n gl_Position = hx_position;\n}\n",f._files["equirectangular_from_cube_fragment.glsl"]="varying_in vec2 uv;\n\nuniform samplerCube sampler;\n\nvoid main()\n{\n vec3 dir;\n\n float theta = (-(uv.x * 2.0 - 1.0) + .5) * HX_PI;\n float phi = (uv.y * 2.0 - 1.0) * HX_PI / 2.0;\n\n dir.x = cos(theta) * cos(phi);\n\tdir.y = -sin(phi);\n\tdir.z = sin(theta) * cos(phi);\n\n hx_FragColor = textureCube(sampler, dir);\n}",f._files["equirectangular_to_cube_fragment.glsl"]="#define RECIPROCAL_PI2 0.15915494\n#define RECIPROCAL_PI 0.31830989\n\nvarying_in vec3 direction;\n\nuniform sampler2D source;\n\nvoid main()\n{\n vec3 dir = normalize(direction);\n vec2 uv;\n\n uv.x = -atan( dir.z, dir.x ) * RECIPROCAL_PI2 - .25;\n\tuv.y = 0.5 - asin(dir.y) * RECIPROCAL_PI;\n hx_FragColor = texture2D(source, uv);\n}\n",f._files["greyscale_to_rgba8.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D source;\n\nvoid main()\n{\n hx_FragColor = hx_floatToRGBA8(texture2D(source, uv).x);\n}\n",f._files["smooth_heightmap_fragment.glsl"]="varying_in vec2 uv;\n\nuniform sampler2D reference; // the source (8 bit) texture\nuniform sampler2D source;\n\nuniform vec2 stepSize;\n\nvoid main()\n{\n float gauss[4];\n gauss[0] = 0.201788613113303;\n gauss[1] = 0.17755834971394;\n gauss[2] = 0.120969095455128;\n gauss[3] = 0.063811162332456;\n float refHeight = texture2D(reference, uv).x;\n float total = hx_RGBA8ToFloat(texture2D(source, uv)) * gauss[0];\n float totalWeight = gauss[0];\n float currentWeightL = 1.0;\n float currentWeightR = 1.0;\n vec2 offset = vec2(0.0);\n\n\n for (int i = 0; i < 3; ++i) {\n offset += stepSize;\n float refLeft = texture2D(reference, uv - offset).x;\n float refRight = texture2D(reference, uv + offset).x;\n float heightLeft = hx_RGBA8ToFloat(texture2D(source, uv - offset));\n float heightRight = hx_RGBA8ToFloat(texture2D(source, uv + offset));\n // smooth out over N pixels that have the same reference height in the source image\n currentWeightL = max(currentWeightL - abs(refLeft - refHeight) * 5.0, 0.0);\n currentWeightR = max(currentWeightR - abs(refRight - refHeight) * 5.0, 0.0);\n totalWeight += (currentWeightL + currentWeightR) * gauss[i + 1];\n total += (heightLeft * currentWeightL + heightRight * currentWeightR) * gauss[i + 1];\n }\n\n hx_FragColor = hx_floatToRGBA8(total / totalWeight);\n}\n",f._files["ao_blur_fragment.glsl"]="varying_in vec2 uv1;\nvarying_in vec2 uv2;\nvarying_in vec2 uv3;\nvarying_in vec2 uv4;\n\nuniform sampler2D source;\n\nvoid main()\n{\n vec4 total = texture2D(source, uv1) + texture2D(source, uv2) + texture2D(source, uv3) + texture2D(source, uv4);\n\thx_FragColor = total * .25;\n}",f._files["ao_blur_vertex.glsl"]="vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nvarying_out vec2 uv1;\nvarying_out vec2 uv2;\nvarying_out vec2 uv3;\nvarying_out vec2 uv4;\n\nuniform vec2 pixelSize;\n\nvoid main()\n{\n\tuv1 = hx_texCoord + vec2(-1.5, .5) * pixelSize;\n\tuv2 = hx_texCoord + vec2(.5, .5) * pixelSize;\n\tuv3 = hx_texCoord + vec2(.5, -1.5) * pixelSize;\n\tuv4 = hx_texCoord + vec2(-1.5, -1.5) * pixelSize;\n\tgl_Position = hx_position;\n}",f._files["hbao_fragment.glsl"]="uniform float hx_cameraFrustumRange;\nuniform float hx_cameraNearPlaneDistance;\nuniform vec2 hx_rcpRenderTargetResolution;\nuniform mat4 hx_projectionMatrix;\n\nuniform float strengthPerRay;\nuniform float halfSampleRadius;\nuniform float bias;\nuniform float rcpFallOffDistance;\nuniform vec2 ditherScale;\n\nuniform sampler2D hx_normalDepthBuffer;\nuniform sampler2D sampleDirTexture;\nuniform sampler2D ditherTexture;\n\nvarying_in vec2 uv;\nvarying_in vec3 viewDir;\nvarying_in vec3 frustumCorner;\n\nvec3 getViewPos(vec2 sampleUV)\n{\n vec4 smp = texture2D(hx_normalDepthBuffer, sampleUV);\n float depth = hx_decodeLinearDepth(smp);\n float viewY = hx_cameraNearPlaneDistance + depth * hx_cameraFrustumRange;\n vec3 viewPos = frustumCorner * vec3(sampleUV.x * 2.0 - 1.0, 1.0, sampleUV.y * 2.0 - 1.0);\n return viewPos * viewY;\n}\n\n// Retrieves the occlusion factor for a particular sample\nfloat getSampleOcclusion(vec2 sampleUV, vec3 centerViewPos, vec3 centerNormal, vec3 tangent, inout float topOcclusion)\n{\n vec3 sampleViewPos = getViewPos(sampleUV);\n\n // get occlusion factor based on candidate horizon elevation\n vec3 horizonVector = sampleViewPos - centerViewPos;\n float horizonVectorLength = length(horizonVector);\n\n float occlusion;\n\n // If the horizon vector points away from the tangent, make an estimate\n if (dot(tangent, horizonVector) < 0.0)\n occlusion = .5;\n else\n occlusion = dot(centerNormal, horizonVector) / horizonVectorLength;\n\n // this adds occlusion only if angle of the horizon vector is higher than the previous highest one without branching\n float diff = max(occlusion - topOcclusion, 0.0);\n topOcclusion = max(occlusion, topOcclusion);\n\n // attenuate occlusion contribution using distance function 1 - (d/f)^2\n float distanceFactor = 1.0 - saturate(horizonVectorLength * rcpFallOffDistance);\n return diff * distanceFactor;\n}\n\n// Retrieves the occlusion for a given ray\nfloat getRayOcclusion(vec2 direction, float jitter, vec2 projectedRadii, vec3 centerViewPos, vec3 centerNormal)\n{\n // calculate the nearest neighbour sample along the direction vector\n vec2 texelSizedStep = direction * hx_rcpRenderTargetResolution;\n direction *= projectedRadii;\n\n // gets the tangent for the current ray, this will be used to handle opposing horizon vectors\n // Tangent is corrected with respect to face normal by projecting it onto the tangent plane defined by the normal\n vec3 tangent = getViewPos(uv + texelSizedStep) - centerViewPos;\n tangent -= dot(centerNormal, tangent) * centerNormal;\n\n vec2 stepUV = direction.xy / float(NUM_SAMPLES_PER_RAY - 1);\n\n // jitter the starting position for ray marching between the nearest neighbour and the sample step size\n vec2 jitteredOffset = mix(texelSizedStep, stepUV, jitter);\n //stepUV *= 1.0 + jitter * .1;\n vec2 sampleUV = uv + jitteredOffset;\n\n // top occlusion keeps track of the occlusion contribution of the last found occluder.\n // set to bias value to avoid near-occluders\n float topOcclusion = bias;\n float occlusion = 0.0;\n\n // march!\n for (int step = 0; step < NUM_SAMPLES_PER_RAY; ++step) {\n occlusion += getSampleOcclusion(sampleUV, centerViewPos, centerNormal, tangent, topOcclusion);\n sampleUV += stepUV;\n }\n\n return occlusion;\n}\n\nvoid main()\n{\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n vec3 centerNormal = hx_decodeNormal(normalDepth);\n float centerDepth = hx_decodeLinearDepth(normalDepth);\n float viewY = hx_cameraNearPlaneDistance + centerDepth * hx_cameraFrustumRange;\n vec3 centerViewPos = viewY * viewDir;\n\n // clamp z to a minimum, so the radius does not get excessively large in screen-space\n float projRadius = halfSampleRadius / max(centerViewPos.y, 7.0);\n vec2 projectedRadii = projRadius * vec2(hx_projectionMatrix[0][0], hx_projectionMatrix[1][2]);\n\n // do not take more steps than there are pixels\n float totalOcclusion = 0.0;\n\n vec2 randomFactors = texture2D(ditherTexture, uv * ditherScale).xy;\n\n vec2 rayUV = vec2(0.0);\n for (int i = 0; i < NUM_RAYS; ++i) {\n rayUV.x = (float(i) + randomFactors.x) / float(NUM_RAYS);\n vec2 sampleDir = texture2D(sampleDirTexture, rayUV).xy * 2.0 - 1.0;\n totalOcclusion += getRayOcclusion(sampleDir, randomFactors.y, projectedRadii, centerViewPos, centerNormal);\n }\n\n totalOcclusion = 1.0 - clamp(strengthPerRay * totalOcclusion, 0.0, 1.0);\n hx_FragColor = vec4(vec3(totalOcclusion), 1.0);\n}",f._files["hbao_vertex.glsl"]="vertex_attribute vec4 hx_position;\nvertex_attribute vec2 hx_texCoord;\n\nuniform mat4 hx_inverseProjectionMatrix;\n\nvarying_out vec2 uv;\nvarying_out vec3 viewDir;\nvarying_out vec3 frustumCorner;\n\nvoid main()\n{\n uv = hx_texCoord;\n viewDir = hx_getLinearDepthViewVector(hx_position.xy, hx_inverseProjectionMatrix);\n frustumCorner = hx_getLinearDepthViewVector(vec2(1.0, 1.0), hx_inverseProjectionMatrix);\n gl_Position = hx_position;\n}",f._files["ssao_fragment.glsl"]='uniform mat4 hx_projectionMatrix;\nuniform mat4 hx_cameraWorldMatrix;\nuniform float hx_cameraFrustumRange;\nuniform float hx_cameraNearPlaneDistance;\n\nuniform vec2 ditherScale;\nuniform float strengthPerSample;\nuniform float rcpFallOffDistance;\nuniform float sampleRadius;\nuniform vec3 samples[NUM_SAMPLES]; // w contains bias\n\nuniform sampler2D ditherTexture;\nuniform sampler2D hx_normalDepthBuffer;\n\nvarying_in vec2 uv;\n\nvoid main()\n{\n vec4 normalDepth = texture2D(hx_normalDepthBuffer, uv);\n vec3 centerNormal = hx_decodeNormal(normalDepth);\n float centerDepth = hx_decodeLinearDepth(normalDepth);\n float totalOcclusion = 0.0;\n vec3 dither = texture2D(ditherTexture, uv * ditherScale).xyz;\n vec3 randomPlaneNormal = normalize(dither - .5);\n float w = hx_cameraNearPlaneDistance + centerDepth * hx_cameraFrustumRange;\n float centerY = centerDepth * hx_cameraFrustumRange; // can ignore nearDist\n vec3 sampleRadii;\n sampleRadii.xz = sampleRadius * .5 / w * vec2(hx_projectionMatrix[0][0], hx_projectionMatrix[1][2]);\n sampleRadii.y = sampleRadius;\n\n for (int i = 0; i < NUM_SAMPLES; ++i) {\n vec3 sampleOffset = reflect(samples[i], randomPlaneNormal);\n vec3 normOffset = normalize(sampleOffset);\n\n // mirror sample position to the positive side of the plane\n float cosFactor = dot(normOffset, centerNormal);\n float sign = sign(cosFactor);\n sampleOffset *= sign;\n cosFactor *= sign;\n\n vec3 scaledOffset = sampleOffset * sampleRadii;\n\n vec2 samplePos = uv + scaledOffset.xz;\n normalDepth = texture2D(hx_normalDepthBuffer, samplePos);\n float occluderDepth = hx_decodeLinearDepth(normalDepth);\n\n // can ignore nearDist\n float occluderY = hx_cameraFrustumRange * occluderDepth;\n float sampleY = centerY + scaledOffset.y;\n\n float distanceFactor = max(1.0 - (sampleY - occluderY) * rcpFallOffDistance, 0.0);\n\n // at this point, occlusion really means occlusion, and not the output "colour" (ie 1 = completely occluded)\n float sampleOcclusion = float(occluderY < sampleY);\n\n // if cosFactor = 0, the sample is coplanar, and occludes less\n totalOcclusion += sampleOcclusion * distanceFactor * cosFactor;\n }\n hx_FragColor = vec4(vec3(1.0 - totalOcclusion * strengthPerSample), 1.0);\n}';var _={shuffle:function(t){for(var e,i,n=t.length;0!==n;)i=Math.floor(Math.random()*n),e=t[n-=1],t[n]=t[i],t[i]=e;return t},forEach:function(t,e){for(var i in t)t.hasOwnProperty(i)&&e(t[i],i)}};function r(){this._listeners=[],this._lookUp={}}function o(){this._isRunning=!1,this._dt=0,this._currentTime=0,this._tickFunc=this._tick.bind(this),this._animationFrame=void 0,this.onTick=new r}function T(t,e,i,n){this.r=0,this.g=0,this.b=0,this.a=1,this.set(t,e,i,n)}r.prototype={bind:function(t,e){this._lookUp[t]=this._listeners.length;var i=e?t.bind(e):t;this._listeners.push(i)},unbind:function(t){var e=this._lookUp[t];void 0!==e&&(this._listeners.splice(e,1),delete this._lookUp[t])},unbindAll:function(){this._listeners=[],this._lookUp={}},dispatch:function(t){for(var e=this._listeners.length,i=0;i>>16)/255,this.g=((65280&t)>>>8)/255,this.b=(255&t)/255):(this.r=t,this.g=e,this.b=i,this.a=void 0===n?1:n)},scale:function(t){this.r*=t,this.g*=t,this.b*=t},hex:function(){return 255*Math.min(this.r,1)<<16|255*Math.min(this.g,1)<<8|255*Math.min(this.b,1)},luminance:function(){return.3*this.r+.59*this.g+.11*this.b},gammaToLinear:function(t){return t=t||new T,He.OPTIONS.usePreciseGammaCorrection?(t.r=Math.pow(this.r,2.2),t.g=Math.pow(this.g,2.2),t.b=Math.pow(this.b,2.2)):(t.r=this.r*this.r,t.g=this.g*this.g,t.b=this.b*this.b),t.a=this.a,t},linearToGamma:function(t){return t=t||new T,He.OPTIONS.usePreciseGammaCorrection?(t.r=Math.pow(this.r,.454545),t.g=Math.pow(this.g,.454545),t.b=Math.pow(this.b,.454545)):(t.r=Math.sqrt(this.r),t.g=Math.sqrt(this.g),t.b=Math.sqrt(this.b)),t.a=this.a,t},copyFrom:function(t){this.r=t.r,this.g=t.g,this.b=t.b,this.a=t.a},toString:function(){return"Color("+this.r+", "+this.g+", "+this.b+", "+this.a+")"},clone:function(){var t=new T;return t.r=this.r,t.g=this.g,t.b=this.b,t.a=this.a,t}},T.BLACK=new T(0,0,0,1),T.ZERO=new T(0,0,0,0),T.RED=new T(1,0,0,1),T.GREEN=new T(0,1,0,1),T.BLUE=new T(0,0,1,1),T.YELLOW=new T(1,1,0,1),T.MAGENTA=new T(1,0,1,1),T.CYAN=new T(0,1,1,1),T.WHITE=new T(1,1,1,1),T.HALF=new T(.5,.5,.5,.5);var u={GENERAL:"precision highp float;\n\n"+f.get("snippets_general.glsl")+"\n\n",VERSION:""},l={printShaderCode:function(t){for(var e=t.split("\n"),i="",n=0;nthis.x&&(this.x=t.x),t.y>this.y&&(this.y=t.y),t.z>this.z&&(this.z=t.z),t.w>this.w&&(this.w=t.w),this},maximize3:function(t){return t.x>this.x&&(this.x=t.x),t.y>this.y&&(this.y=t.y),t.z>this.z&&(this.z=t.z),this},minimize:function(t){return t.xthis._maximumX&&(this._maximumX=t._maximumX),t._maximumY>this._maximumY&&(this._maximumY=t._maximumY),t._maximumZ>this._maximumZ&&(this._maximumZ=t._maximumZ)),this._updateCenterAndExtent())},$.prototype.growToIncludeMinMax=function(t,e){this._expanse!==K.EXPANSE_INFINITE&&(this._expanse===K.EXPANSE_EMPTY?(this._minimumX=t.x,this._minimumY=t.y,this._minimumZ=t.z,this._maximumX=e.x,this._maximumY=e.y,this._maximumZ=e.z,this._expanse=K.EXPANSE_FINITE):(t.xthis._maximumX&&(this._maximumX=e.x),e.y>this._maximumY&&(this._maximumY=e.y),e.z>this._maximumZ&&(this._maximumZ=e.z)),this._updateCenterAndExtent())},$.prototype.transform=function(t){var e=new $;return e.transformFrom(this,t),e},$.prototype.transformFrom=function(t,e){if(t._expanse===K.EXPANSE_FINITE){var i=e._m,n=i[0],s=i[1],r=i[2],o=i[4],a=i[5],h=i[6],u=i[8],l=i[9],c=i[10],_=t._center.x,d=t._center.y,f=t._center.z,p=this._center.x=n*_+o*d+u*f+i[12],g=this._center.y=s*_+a*d+l*f+i[13],M=this._center.z=r*_+h*d+c*f+i[14];n<0&&(n=-n),s<0&&(s=-s),r<0&&(r=-r),o<0&&(o=-o),a<0&&(a=-a),h<0&&(h=-h),u<0&&(u=-u),l<0&&(l=-l),c<0&&(c=-c),_=t._halfExtentX,d=t._halfExtentY,f=t._halfExtentZ;var m=this._halfExtentX=n*_+o*d+u*f,A=this._halfExtentY=s*_+a*d+l*f,x=this._halfExtentZ=r*_+h*d+c*f;this._minimumX=p-m,this._minimumY=g-A,this._minimumZ=M-x,this._maximumX=p+m,this._maximumY=g+A,this._maximumZ=M+x,this._expanse=t._expanse}else this.clear(t._expanse)},$.prototype.intersectsConvexSolid=function(t,e){if(this._expanse===K.EXPANSE_INFINITE||this._expanse===K.EXPANSE_INHERIT)return!0;if(this._expanse===K.EXPANSE_EMPTY)return!1;for(var i=this._minimumX,n=this._minimumY,s=this._minimumZ,r=this._maximumX,o=this._maximumY,a=this._maximumZ,h=0;ht._minimumX&&this._minimumXt._minimumY&&this._minimumYt._minimumZ&&this._minimumZ>16&32768,n=e>>12&2047,s=e>>23&255;return s<103?i:142>114-s)+(n>>113-s&1):(i|=s-112<<10|n>>1,i+=1&n)}),encodeToFloat16Array:function(t){for(var e=At.encodeHalfFloat,i=[],n=0;nti.DEFAULT_TEXTURE_MAX_ANISOTROPY&&(t=ti.DEFAULT_TEXTURE_MAX_ANISOTROPY),this._maxAnisotropy=t,this.bind(),ti.EXT_TEXTURE_FILTER_ANISOTROPIC&&B.gl.texParameteri(this._glTarget,ti.EXT_TEXTURE_FILTER_ANISOTROPIC.TEXTURE_MAX_ANISOTROPY_EXT,t),e.bindTexture(this._glTarget,null)},get format(){return this._format},get dataType(){return this._dataType},isReady:function(){return this._isReady},bind:function(t){var e=B.gl;void 0!==t&&e.activeTexture(e.TEXTURE0+t),e.bindTexture(this._glTarget,this._texture)}};var Nt=0;function Dt(){Tt.call(this,B.gl.TEXTURE_2D),this.name="hx_texture2d_"+Nt++,this._default=Dt.DEFAULT,this._width=0,this._height=0,this.wrapMode=ii.DEFAULT}Dt._initDefault=function(){var t=new Uint8Array([255,0,255,255]);(Dt.DEFAULT=new Dt).uploadData(t,1,1,!0),Dt.DEFAULT.filter=ei.NEAREST_NOMIP},(Dt.prototype=Object.create(Tt.prototype,{numMips:{get:function(){return Math.floor(yt.log2(Math.max(this._width,this._height)))}},wrapMode:{get:function(){return this._wrapMode},set:function(t){var e=B.gl;this._wrapMode=t,this.bind(),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,t.s),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,t.t),e.bindTexture(e.TEXTURE_2D,null)}},width:{get:function(){return this._width}},height:{get:function(){return this._height}}})).initEmpty=function(t,e,i,n){this._data=null;var s=B.gl;this._format=i=i||li.RGBA,this._dataType=n=n||ci.UNSIGNED_BYTE,this.bind(),this._width=t,this._height=e;var r=li.getDefaultInternalFormat(i,n);s.texImage2D(s.TEXTURE_2D,0,r,t,e,0,i,n,null),this._isReady=!0,s.bindTexture(s.TEXTURE_2D,null)},Dt.prototype.uploadData=function(t,e,i,n,s,r,o){var a=B.gl;!ti.EXT_HALF_FLOAT_TEXTURES||r!==ci.HALF_FLOAT||t instanceof Uint16Array||(t=At.encodeToFloat16Array(t)),o||(this._width=e,this._height=i,this._format=s||li.RGBA,this._dataType=r||ci.UNSIGNED_BYTE),s=this._format,r=this._dataType,n=void 0!==n&&n,this.bind();var h=li.getDefaultInternalFormat(s,r);a.texImage2D(a.TEXTURE_2D,o||0,h,e,i,0,s,r,t),n&&a.generateMipmap(a.TEXTURE_2D),this._isReady=!0,a.bindTexture(a.TEXTURE_2D,null)},Dt.prototype.uploadImage=function(t,e,i,n,s,r,o){var a=B.gl;o||(this._width=e,this._height=i,this._format=s||li.RGBA,this._dataType=r||ci.UNSIGNED_BYTE),s=this._format,r=this._dataType,n=void 0===n||n,yt.isPowerOfTwo(e)&&yt.isPowerOfTwo(i)||(n=!1,this.filter===ei.NEAREST?this.filter=ei.NEAREST_NOMIP:this.filter===ei.BILINEAR?this.filter=ei.BILINEAR_NOMIP:this.filter!==ei.TRILINEAR&&this.filter!==ei.TRILINEAR_ANISOTROPIC||(this.filter=ei.BILINEAR_NOMIP),this.wrapMode=ii.CLAMP),this.bind();var h=li.getDefaultInternalFormat(s,r);a.texImage2D(a.TEXTURE_2D,o||0,h,s,r,t),n&&a.generateMipmap(a.TEXTURE_2D),this._isReady=!0,a.bindTexture(a.TEXTURE_2D,null)},Dt.prototype.uploadCompressedData=function(t,e,i,n,s,r){var o=B.gl;r||(this._width=e,this._height=i,this._format=li.RGBA,this._dataType=ci.UNSIGNED_BYTE),this.bind(),o.compressedTexImage2D(o.TEXTURE_2D,r||0,s,e,i,0,t),n&&o.generateMipmap(o.TEXTURE_2D),this._isReady=!0,o.bindTexture(o.TEXTURE_2D,null)},Dt.prototype.toString=function(){return"[Texture2D(name="+this.name+")]"};var Et,wt,Lt,It={getSettersPerPass:function(t){return void 0===It._passTable&&It._init(),It._findSetters(t,It._passTable)},getSettersPerInstance:function(t){return void 0===It._instanceTable&&It._init(),It._findSetters(t,It._instanceTable)},_findSetters:function(t,e){var i=[];for(var n in e)if(e.hasOwnProperty(n)){var s=t.getUniformBufferIndex(n);if(-1!==s){var r=new e[n];i.push(r),r.slot=s,r.pass=t}}return i},_init:function(){It._passTable={},It._instanceTable={},It._passTable.hx_lights=vt,It._passTable.hx_lightingCells=St}};function vt(){}function St(){}function Ot(t,e){this.x=t||0,this.y=e||0}function Ct(t,e,i,n){this.points=null,this.decayFactor=i||.99,this.initialDistance=e||1,this.maxTests=n||2e4,this.mode=void 0===t?Ct.CIRCULAR:t,this._currentDistance=0,this.reset()}function jt(t,e,i,n){this.points=null,this.mode=void 0===t?jt.SPHERICAL:t,this.initialDistance=e||1,this.decayFactor=i||.99,this.maxTests=n||2e4,this._currentDistance=0,this.reset()}function Pt(t,e,i,n){this.x=t||0,this.y=e||0,this.z=i||0,this.w=void 0===n?1:n}function bt(){this.enabled=!0,this.onChange=new r,this._targets=[]}function zt(){this._position=new q(0,0,0,1),this._rotation=new Pt,this._euler=new q(0,0,0,0),this._scale=new q(1,1,1,1),this._matrix=new Rt,this._eulerInvalid=!0,this._eulerChangeListener=new bt,this._eulerChangeListener.add(this._euler,"x"),this._eulerChangeListener.add(this._euler,"y"),this._eulerChangeListener.add(this._euler,"z"),this._eulerChangeListener.onChange.bind(this._onEulerChanged,this),this._changeListener=new bt,this._changeListener.add(this._position,"x"),this._changeListener.add(this._position,"y"),this._changeListener.add(this._position,"z"),this._changeListener.add(this._scale,"x"),this._changeListener.add(this._scale,"y"),this._changeListener.add(this._scale,"z"),this._changeListener.onChange.bind(this._invalidateMatrix,this),this._rotationChangeListener=new bt,this._rotationChangeListener.add(this._rotation,"x"),this._rotationChangeListener.add(this._rotation,"y"),this._rotationChangeListener.add(this._rotation,"z"),this._rotationChangeListener.add(this._rotation,"w"),this._rotationChangeListener.onChange.bind(this._onRotationChanged,this)}function Rt(t,e,i,n,s,r,o,a,h,u,l,c,_,d,f,p){this.set(t,e,i,n,s,r,o,a,h,u,l,c,_,d,f,p)}vt.prototype.execute=function(t){this.pass.setUniformBufferByIndex(this.slot,t._lightingUniformBuffer)},St.prototype.execute=function(t){this.pass.setUniformBufferByIndex(this.slot,t._lightingCellsUniformBuffer)},Ot.add=function(t,e,i){return(i=i||new Ot).x=t.x+e.x,i.y=t.y+e.y,i},Ot.subtract=function(t,e,i){return(i=i||new Ot).x=t.x-e.x,i.y=t.y-e.y,i},Ot.scale=function(t,e,i){return(i=i||new Ot).x=t.x*e,i.y=t.y*e,i},Ot.prototype={set:function(t,e){this.x=t,this.y=e},dot:function(t){return t.x*this.x+t.y*this.y},get lengthSqr(){return this.x*this.x+this.y*this.y},get length(){return Math.sqrt(this.x*this.x+this.y*this.y)},normalize:function(){var t=1/this.length;this.x*=t,this.y*=t},clone:function(){return new Ot(this.x,this.y)},add:function(t){this.x+=t.x,this.y+=t.y},addScaled:function(t,e){this.x+=t.x*e,this.y+=t.y*e},subtract:function(t){this.x-=t.x,this.y-=t.y},subtractScaled:function(t,e){return this.x-=t.x*e,this.y-=t.y*e,this},scale:function(t){this.x*=t,this.y*=t},negate:function(){this.x=-this.x,this.y=-this.y},negativeOf:function(t){this.x=-t.x,this.y=-t.y},abs:function(){this.x=Math.abs(this.x),this.y=Math.abs(this.y)},fromPolarCoordinates:function(t,e){this.x=t*Math.cos(e),this.y=t*Math.sin(e)},copyFrom:function(t){this.x=t.x,this.y=t.y},distanceTo:function(t){var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},squareDistanceTo:function(t){var e=t.x-this.x,i=t.y-this.y;return e*e+i*i},lerp:function(t,e,i){var n=t.x,s=t.y;this.x=n+(e.x-n)*i,this.y=s+(e.y-s)*i},maximize:function(t){t.x>this.x&&(this.x=t.x),t.y>this.y&&(this.y=t.y)},minimize:function(t){t.x>2);return i},getAdjugate:function(t,e,i){for(var n=(i=i||new Rt)._m,s=0;s<16;++s)n[s]=this.cofactor(s>>2,3&s);return i},determinant:function(){var t=this._m;return t[0]*this.determinant3x3(0,0)-t[4]*this.determinant3x3(0,1)+t[8]*this.determinant3x3(0,2)-t[12]*this.determinant3x3(0,3)},inverseOf:function(t){var e=t.determinant();if(0===e)return null;var i=1/e,n=i*t.cofactor(0,0),s=i*t.cofactor(0,1),r=i*t.cofactor(0,2),o=i*t.cofactor(0,3),a=i*t.cofactor(1,0),h=i*t.cofactor(1,1),u=i*t.cofactor(1,2),l=i*t.cofactor(1,3),c=i*t.cofactor(2,0),_=i*t.cofactor(2,1),d=i*t.cofactor(2,2),f=i*t.cofactor(2,3),p=i*t.cofactor(3,0),g=i*t.cofactor(3,1),M=i*t.cofactor(3,2),m=i*t.cofactor(3,3),A=this._m;return A[0]=n,A[1]=s,A[2]=r,A[3]=o,A[4]=a,A[5]=h,A[6]=u,A[7]=l,A[8]=c,A[9]=_,A[10]=d,A[11]=f,A[12]=p,A[13]=g,A[14]=M,A[15]=m,this},inverseAffineOf:function(t){var e=t._m,i=e[0],n=e[1],s=e[2],r=e[4],o=e[5],a=e[6],h=e[8],u=e[9],l=e[10],c=e[12],_=e[13],d=e[14],f=i*(o*l-u*a)-r*(n*l-u*s)+h*(n*a-o*s);if(0===f)return null;var p=1/f,g=(o*l-u*a)*p,M=(u*s-n*l)*p,m=(n*a-o*s)*p,A=(h*a-r*l)*p,x=(i*l-h*s)*p,y=(r*s-i*a)*p,T=(r*u-h*o)*p,N=(h*n-i*u)*p,D=(i*o-r*n)*p,E=this._m;return E[0]=g,E[1]=M,E[2]=m,E[3]=0,E[4]=A,E[5]=x,E[6]=y,E[7]=0,E[8]=T,E[9]=N,E[10]=D,E[11]=0,E[12]=-g*c-A*_-T*d,E[13]=-M*c-x*_-N*d,E[14]=-m*c-y*_-D*d,E[15]=1,this},writeNormalMatrix:function(t,e){e=e||0;var i=this._m,n=i[0],s=i[1],r=i[2],o=i[4],a=i[5],h=i[6],u=i[8],l=i[9],c=i[10],_=1/(n*(a*c-l*h)-o*(s*c-l*r)+u*(s*h-a*r));t[e]=(a*c-l*h)*_,t[e+1]=(u*h-o*c)*_,t[e+2]=(o*l-u*a)*_,t[e+3]=(l*r-s*c)*_,t[e+4]=(n*c-u*r)*_,t[e+5]=(u*s-n*l)*_,t[e+6]=(s*h-a*r)*_,t[e+7]=(o*r-n*h)*_,t[e+8]=(n*a-o*s)*_},writeData:function(t,e){e=e||0;for(var i=this._m,n=0;n<16;++n)t[e+n]=i[n]},writeData4x3:function(t,e){var i=this._m;t[e=e||0]=i[0],t[e+1]=i[4],t[e+2]=i[8],t[e+3]=i[12],t[e+4]=i[1],t[e+5]=i[5],t[e+6]=i[9],t[e+7]=i[13],t[e+8]=i[2],t[e+9]=i[6],t[e+10]=i[10],t[e+11]=i[14]},invert:function(){return this.inverseOf(this)},invertAffine:function(){return this.inverseAffineOf(this)},append:function(t){return this.multiply(t,this)},prepend:function(t){return this.multiply(this,t)},appendAffine:function(t){return this.multiplyAffine(t,this)},prependAffine:function(t){return this.multiplyAffine(this,t)},add:function(t){var e=this._m,i=t._m;return e[0]+=i[0],e[1]+=i[1],e[2]+=i[2],e[3]+=i[3],e[4]+=i[4],e[5]+=i[5],e[6]+=i[6],e[7]+=i[7],e[8]+=i[8],e[9]+=i[9],e[10]+=i[10],e[11]+=i[11],e[12]+=i[12],e[13]+=i[13],e[14]+=i[14],e[15]+=i[15],this},addAffine:function(t){var e=this._m,i=t._m;return e[0]+=i[0],e[1]+=i[1],e[2]+=i[2],e[4]+=i[4],e[5]+=i[5],e[6]+=i[6],e[8]+=i[8],e[9]+=i[9],e[10]+=i[10],this},subtract:function(t){var e=this._m,i=t._m;return e[0]-=i[0],e[1]-=i[1],e[2]-=i[2],e[3]-=i[3],e[4]-=i[4],e[5]-=i[5],e[6]-=i[6],e[7]-=i[7],e[8]-=i[8],e[9]-=i[9],e[10]-=i[10],e[11]-=i[11],e[12]-=i[12],e[13]-=i[13],e[14]-=i[14],e[15]-=i[15],this},subtractAffine:function(t){var e=this._m,i=t._m;return e[0]-=i[0],e[1]-=i[1],e[2]-=i[2],e[4]-=i[4],e[5]-=i[5],e[6]-=i[6],e[8]-=i[8],e[9]-=i[9],e[10]-=i[10],this},appendScale:function(t,e,i){t instanceof q?(e=t.y,i=t.z,t=t.x):void 0===e&&(e=i=t);var n=this._m;return n[0]*=t,n[1]*=e,n[2]*=i,n[4]*=t,n[5]*=e,n[6]*=i,n[8]*=t,n[9]*=e,n[10]*=i,n[12]*=t,n[13]*=e,n[14]*=i,this},prependScale:function(t,e,i){t instanceof q?(e=t.y,i=t.z,t=t.x):void 0===e&&(e=i=t);var n=this._m;return n[0]*=t,n[1]*=t,n[2]*=t,n[3]*=t,n[4]*=e,n[5]*=e,n[6]*=e,n[7]*=e,n[8]*=i,n[9]*=i,n[10]*=i,n[11]*=i,this},appendTranslation:function(t,e,i){void 0===e&&(e=t.y,i=t.z,t=t.x);var n=this._m;return n[12]+=t,n[13]+=e,n[14]+=i,this},prependTranslation:function(t,e,i){void 0===e&&(e=t.y,i=t.z,t=t.x);var n=this._m;return n[12]+=n[0]*t+n[4]*e+n[8]*i,n[13]+=n[1]*t+n[5]*e+n[9]*i,n[14]+=n[2]*t+n[6]*e+n[10]*i,n[15]+=n[3]*t+n[7]*e+n[11]*i,this},appendQuaternion:function(t){var e=this._m,i=t.x,n=t.y,s=t.z,r=t.w,o=1-2*(n*n+s*s),a=2*(i*n+r*s),h=2*(i*s-r*n),u=2*(i*n-r*s),l=1-2*(i*i+s*s),c=2*(n*s+r*i),_=2*(i*s+r*n),d=2*(n*s-r*i),f=1-2*(i*i+n*n),p=e[0],g=e[1],M=e[2],m=e[4],A=e[5],x=e[6],y=e[8],T=e[9],N=e[10],D=e[12],E=e[13],w=e[14];return e[0]=o*p+u*g+_*M,e[1]=a*p+l*g+d*M,e[2]=h*p+c*g+f*M,e[4]=o*m+u*A+_*x,e[5]=a*m+l*A+d*x,e[6]=h*m+c*A+f*x,e[8]=o*y+u*T+_*N,e[9]=a*y+l*T+d*N,e[10]=h*y+c*T+f*N,e[12]=o*D+u*E+_*w,e[13]=a*D+l*E+d*w,e[14]=h*D+c*E+f*w,this},prependQuaternion:function(t){var e=this._m,i=t.x,n=t.y,s=t.z,r=t.w,o=e[0],a=e[1],h=e[2],u=e[4],l=e[5],c=e[6],_=e[8],d=e[9],f=e[10],p=1-2*(n*n+s*s),g=2*(i*n+r*s),M=2*(i*s-r*n),m=2*(i*n-r*s),A=1-2*(i*i+s*s),x=2*(n*s+r*i),y=2*(i*s+r*n),T=2*(n*s-r*i),N=1-2*(i*i+n*n);return e[0]=o*p+u*g+_*M,e[1]=a*p+l*g+d*M,e[2]=h*p+c*g+f*M,e[4]=o*m+u*A+_*x,e[5]=a*m+l*A+d*x,e[6]=h*m+c*A+f*x,e[8]=o*y+u*T+_*N,e[9]=a*y+l*T+d*N,e[10]=h*y+c*T+f*N,this},appendRotationAxisAngle:function(t,e){var i=this._m,n=Math.cos(e),s=Math.sin(e),r=1/t.length,o=t.x*r,a=t.y*r,h=t.z*r,u=1-n,l=u*o*o+n,c=u*o*a+s*h,_=u*o*h-s*a,d=u*o*a-s*h,f=u*a*a+n,p=u*a*h+s*o,g=u*o*h+s*a,M=u*a*h-s*o,m=u*h*h+n,A=i[0],x=i[1],y=i[2],T=i[4],N=i[5],D=i[6],E=i[8],w=i[9],L=i[10],I=i[12],v=i[13],S=i[14];return i[0]=l*A+d*x+g*y,i[1]=c*A+f*x+M*y,i[2]=_*A+p*x+m*y,i[4]=l*T+d*N+g*D,i[5]=c*T+f*N+M*D,i[6]=_*T+p*N+m*D,i[8]=l*E+d*w+g*L,i[9]=c*E+f*w+M*L,i[10]=_*E+p*w+m*L,i[12]=l*I+d*v+g*S,i[13]=c*I+f*v+M*S,i[14]=_*I+p*v+m*S,this},prependRotationAxisAngle:function(t,e){var i=this._m,n=Math.cos(e),s=Math.sin(e),r=1/t.length,o=t.x*r,a=t.y*r,h=t.z*r,u=1-n,l=i[0],c=i[1],_=i[2],d=i[4],f=i[5],p=i[6],g=i[8],M=i[9],m=i[10],A=u*o*o+n,x=u*o*a+s*h,y=u*o*h-s*a,T=u*o*a-s*h,N=u*a*a+n,D=u*a*h+s*o,E=u*o*h+s*a,w=u*a*h-s*o,L=u*h*h+n;return i[0]=l*A+d*x+g*y,i[1]=c*A+f*x+M*y,i[2]=_*A+p*x+m*y,i[4]=l*T+d*N+g*D,i[5]=c*T+f*N+M*D,i[6]=_*T+p*N+m*D,i[8]=l*E+d*w+g*L,i[9]=c*E+f*w+M*L,i[10]=_*E+p*w+m*L,this},getRow:function(t,e){var i=this._m;return(e=e||new q).x=i[t],e.y=i[4|t],e.z=i[8|t],e.w=i[12|t],e},setRow:function(t,e){var i=this._m;return i[t]=e.x,i[4|t]=e.y,i[8|t]=e.z,i[12|t]=e.w,this},getElement:function(t,e){return this._m[t|e<<2]},setElement:function(t,e,i){return this._m[t|e<<2]=i,this},getColumn:function(t,e){var i=this._m;return t<<=2,(e=e||new q).x=i[t],e.y=i[1|t],e.z=i[2|t],e.w=i[3|t],e},setColumn:function(t,e){var i=this._m;return i[t<<=2]=e.x,i[1|t]=e.y,i[2|t]=e.z,i[3|t]=e.w,this},copyColumn:function(t,e){var i=this._m,n=e._m;return i[t<<=2]=n[t],i[1|t]=n[1|t],i[2|t]=n[2|t],i[3|t]=n[3|t],this},lookAt:(Et=new q,wt=new q,Lt=new q,function(t,e,i){if(i=i||q.Z_AXIS,q.subtract(t,e,wt),wt.normalize(),q.cross(wt,i,Et),Math.abs(Et.lengthSqr)<1e-4){var n=new q(i.x,i.z,i.y,0);q.cross(wt,n,Et),Math.abs(Et.lengthSqr)<=1e-4&&(n.set(i.z,i.y,i.z,0),q.cross(wt,n,Et))}Et.normalize(),q.cross(Et,wt,Lt);var s=this._m;return s[0]=Et.x,s[1]=Et.y,s[2]=Et.z,s[3]=0,s[4]=wt.x,s[5]=wt.y,s[6]=wt.z,s[7]=0,s[8]=Lt.x,s[9]=Lt.y,s[10]=Lt.z,s[11]=0,s[12]=e.x,s[13]=e.y,s[14]=e.z,s[15]=1,this}),compose:function(t,e,i){var n=e?t:t.position;return e=e||t.rotation,(i=i||t.scale)?this.fromScale(i):this.copyFrom(Rt.IDENTITY),this.appendQuaternion(e),this.appendTranslation(n),this},decompose:function(t,e,i){var n;t=t||new zt,void 0===e?(e=t.rotation,i=t.scale,n=t.position):n=t;var s=this._m,r=s[0],o=s[1],a=s[2],h=s[4],u=s[5],l=s[6],c=s[8],_=s[9],d=s[10],f=o*l-a*u,p=a*h-r*l,g=r*u-o*h,M=yt.sign(f*c+p*_+g*d);i.x=M*Math.sqrt(r*r+o*o+a*a),i.y=M*Math.sqrt(h*h+u*u+l*l),i.z=M*Math.sqrt(c*c+_*_+d*d),.999>5;return t&=~(e<<5),this._hash[e]&1<>5;t&=~(i<<5),e[i]=(e[i]||0)|1<>5;t&=~(i<<5),e[i]=(e[i]||0)&~(1<=this._morphWeights.length||(this._morphPositions[t]=e,i&&this._morphNormals&&(this._morphNormals[t]=i),this._morphWeights[t]=e?n:0)},Wi.prototype._updateBounds=function(){this._bounds=this._mesh.bounds},Wi.prototype._initMorphData=function(){if(this._morphPositions=null,this._morphNormals=null,this._morphWeights=null,this._mesh.hasMorphData){this._morphPositions=[];var t=8;this._mesh.hasMorphNormals&&(this._morphNormals=[],t=4),this._morphWeights=new Float32Array(t);for(var e=0;es&&(s=t._maximumX),t._maximumY>r&&(r=t._maximumY),t._maximumZ>o&&(o=t._maximumZ),t._minimumXthis.duration&&(this.duration=t.time)},_updateFrames:function(){this._keyFrames.sort(function(t,e){return t.time-e.time});var t=this._keyFrames[0],e=this._keyFrames[this._keyFrames.length-1];0o?(this._time=o,this._isPlaying=!1):this._time<0&&(this._time=0,this._isPlaying=!1)),0<=t){for(;this.looping&&this._time>=o;)this._currentFrameIndex=0,this._time-=o,++a;for(;++this._currentFrameIndex===s&&(this._currentFrameIndex=0),(i=n.getKeyFrame(this._currentFrameIndex)).timethis._time;);}return this.wraps=a,this.frame1=e,this.frame2=i,this.ratio=(this._time-e.time)/(i.time-e.time),!0}},$n.prototype={getWeight:function(t){return this._weights[t]},getMorphTargetName:function(t){return this._knownTargets[t]},setWeight:function(t,e){var i=this._weights[t];i!==e&&(void 0===i&&this._knownTargets.push(t),this._stateInvalid=!0,this._weights[t]=e)},update:function(){this._stateInvalid&&(this._knownTargets.sort(this._sortMorphs),this._stateInvalid=!1,this.onChange.dispatch())},clone:function(){var t=new $n;for(var e in this._weights)t.setWeight(e,this._weights[e]);return t},_sortMorphs:function(t,e){return this._weights[e.name]-this._weights[t.name]}};var ts=0;function es(t){Qi.call(this),this.name="hx_morphanimation_"+ts++,this._morphPose=t||new $n}(es.prototype=Object.create(Qi.prototype,{morphPose:{get:function(){return this._morphPose},set:function(t){this._morphPose=t,this._assignMorphPose(t)}}})).setWeight=function(t,e){this._morphPose.setWeight(t,e)},es.prototype.onAdded=function(){this.entity.morphPose=this._morphPose},es.prototype.onRemoved=function(){this.entity.morphPose=null},es.prototype.onUpdate=function(t){this._morphPose.update()},es.prototype.clone=function(){var t=new es(this._morphPose.clone());return t.name=this.name,t},Qi.register("morphAnimation",es);var is=0;function ns(){Qi.call(this),this.name="hx_layeredanimation_"+is++,this.playbackRate=1,this._layers=[],this._time=0,this._looping=!0}(ns.prototype=Object.create(Qi.prototype,{time:{get:function(){return this._time},set:function(t){this._time=t;for(var e=0;e>15,i=t>>10&31,n=1023&t;return 31===i?n?Number.NaN:e?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY:i?Math.pow(2,i-15)*(1+n/1024):n/1024*6103515625e-14},getFloat32:function(){var t=this._dataView.getFloat32(this.offset,this.endian);return this.offset+=4,t},getFloat64:function(){var t=this._dataView.getFloat64(this.offset,this.endian);return this.offset+=8,t},skipAlign:function(t){for(;this.offset%t;)++this.offset},getUint8Array:function(t){return this._readArray(t,Uint8Array,1,this.getUint8)},getUint16Array:function(t){return this._readArray(t,Uint16Array,2,this.getUint16)},getUint32Array:function(t){return this._readArray(t,Uint32Array,4,this.getUint32)},getInt8Array:function(t){return this._readArray(t,Int8Array,1,this.getInt8)},getInt16Array:function(t){return this._readArray(t,Int16Array,2,this.getInt16)},getInt32Array:function(t){return this._readArray(t,Int32Array,4,this.getInt32)},getInt64AsFloat64Array:function(t){for(var e=new Float64Array(t),i=0;i>8&255),e+=String.fromCharCode(t>>16&255),e+=String.fromCharCode(t>>24&255)){case"DXT1":return this._blockSize=8,void(this._format=ti.EXT_COMPRESSED_TEXTURE_S3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT);case"DXT3":return this._blockSize=16,void(this._format=ti.EXT_COMPRESSED_TEXTURE_S3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT);case"DXT5":return this._blockSize=16,void(this._format=ti.EXT_COMPRESSED_TEXTURE_S3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT);case"DX10":return this._blockSize=16,void this._parseDX10Header()}switch(t){case 111:return this._blockSize=1,this._format=li.RED||li.RGBA,void(this._dataType=ci.HALF_FLOAT||"Float16");case 112:return this._blockSize=2,this._format=li.RG||li.RGBA,void(this._dataType=ci.HALF_FLOAT||"Float16");case 113:return this._blockSize=4,this._format=li.RGBA,void(this._dataType=ci.HALF_FLOAT||"Float16");case 114:return this._blockSize=1,this._format=li.RED||li.RGBA,void(this._dataType=ci.FLOAT);case 112:return this._blockSize=2,this._format=li.RG||li.RGBA,void(this._dataType=ci.FLOAT);case 116:return this._blockSize=4,this._format=li.RGBA,void(this._dataType=ci.FLOAT);default:return void this._notifyFailure("Unsupported texture format!")}},xr.prototype._parseData=function(){for(var t=this._type===je?6:1,e=[],i=0;i>2)*Math.max(1,s+3>>2)*this._blockSize;r=this._stream.getUint8Array(a)}e[o][i]=r,0===(n>>=1)&&(n=1),0===(s>>=1)&&(s=1)}this._uploadData(e)},xr.prototype._uploadData=function(t){for(var e=1===this._mipLevels,i=this._width,n=this._height,s="Float16"===this._dataType?ci.FLOAT:this._dataType,r=0;r>=1)&&(i=1),0===(n>>=1)&&(n=1)}},xr.prototype._parseUncompressedMipData=function(t,e){var i=t*e*this._blockSize;return this._blockSize<4&&!ti.WEBGL_2?this._parseUnsupportedFormat(i):this._parseStraightDataBlock(i)},xr.prototype._parseUnsupportedFormat=function(t){var e,i;switch(t=t/this._blockSize*4,this._dataType){case ci.FLOAT:e=new Float32Array(t),i=this._stream.getFloat32.bind(this._stream);break;case ci.HALF_FLOAT:e=new Uint16Array(t),i=this._stream.getUint16.bind(this._stream);break;case"Float16":e=new Float32Array(t),i=this._stream.getFloat16.bind(this._stream)}for(var n=0,s=0;s>1;(n=n||new Dt).initEmpty(e,s,t.format,Dr(t.dataType)),fr||(fr=new we(f.get("equirectangular_from_cube_fragment.glsl")));var r=B.getCurrentRenderTarget(),o=new gt(n);return o.init(),B.setRenderTarget(o),B.clear(),fr.execute(t),B.setRenderTarget(r),i&&n.generateMipmap(),n}};function Dr(t){return t!==ci.HALF_FLOAT||ti.EXT_COLOR_BUFFER_HALF_FLOAT?t!==ci.FLOAT||ti.EXT_COLOR_BUFFER_FLOAT||(t=ti.EXT_COLOR_BUFFER_HALF_FLOAT?ci.HALF_FLOAT:ci.UNSIGNED_BYTE):t=ti.EXT_COLOR_BUFFER_FLOAT?ci.FLOAT:ci.UNSIGNED_BYTE,t}function Er(){ar.call(this,or.DATA_BINARY)}(Er.prototype=Object.create(ar.prototype)).parse=function(t,e){var i;this.options.equiToCube?(i=new Dt,e=e||new je):(e=e||new Dt,i=this.options.heightMap?new Dt:e),this._stream=new zs(t),this._stream.endian=js,this._texture=i,this._generateMips=void 0===this.options.generateMipmaps||this.options.generateMipmaps,this._flipY=!1,this._gamma=1,this._exposure=Math.pow(2,this.options.exposure||0),this._colorCorr=new T(1,1,1),this._parseHeader(),this._parseData(),this.options.equiToCube&&Nr.toCube(i,this.options.cubeSize,this._generateMips,e),this._notifyComplete(e)},Er.prototype._parseHeader=function(){var t=this._readLine();for(console.assert("#?RADIANCE"===t||"#?RGBE"===t,"Incorrect file format!");""!==t;){var e=(t=this._readLine()).split("=");switch(e[0]){case"GAMMA":this._gamma=parseFloat(e[1]);break;case"FORMAT":console.assert("32-bit_rle_rgbe"===e[1]||"32-bit_rle_xyze"===e[1],"Incorrect format!");break;case"EXPOSURE":this._exposure*=parseFloat(e[1]);break;case"COLORCORR":var i=e[1].replace(/^\s+|\s+$/g,"").split(" ");this._colorCorr.set(i[0],i[1],i[2])}}e=(t=this._readLine()).split(" "),this._parseSize(e[0],parseInt(e[1])),this._parseSize(e[2],parseInt(e[3]))},Er.prototype._parseSize=function(t,e){switch(t){case"+X":this._width=e;break;case"-X":this._width=e,console.warn("Flipping horizontal orientation not currently supported");break;case"-Y":this._height=e;break;case"+Y":this._height=e,console.warn("Flipping vertical orientation not currently supported")}},Er.prototype._readLine=function(){for(var t,e="";"\n"!==(t=this._stream.getChar());)e+=t;return e},Er.prototype._parseData=function(){var t,e=this._stream.getUint16();if(this._stream.offset-=2,514===e){t=this._parseNewRLE();var i=ti.HDR_DATA_TYPE;i!==ci.HALF_FLOAT||ti.CAN_UPLOAD_HALF_FLOAT||(i=ci.FLOAT),this._texture.uploadData(t,this._width,this._height,this._generateMips,li.RGB,i)}else this._notifyFailure("Obsolete HDR file version!")},Er.prototype._parseNewRLE=function(){for(var t=!this.options.ldr&&ti.HDR_DATA_TYPE!==ci.UNSIGNED_BYTE,e=this._width*this._height,i=this._width,n=new(t?Float32Array:Uint8Array)(3*e),s=0,r=0;r=E._lodRangeStartSqr&&m=_._lodRangeStartSqr&&u<_._lodRangeEndSqr&&0!==_.numInstances&&this.visitMeshInstance(_,n,i,u)}}},_h.prototype.visitMeshInstance=function(t,e,i,n){for(var s=t.skeleton,r=t.skeletonMatrices,o=De.DIR_LIGHT_SHADOW_MAP_PASS,a=He.OPTIONS.numShadowCascades,h=0;h=_._lodRangeStartSqr&&u<_._lodRangeEndSqr&&0!==_.numInstances&&this.visitMeshInstance(_,n,i,u)}},yh.prototype.visitMeshInstance=function(t,e,i,n){var s=this._octantPlanes,r=i.classifyAgainstPlane(s[0]),o=i.classifyAgainstPlane(s[1]),a=i.classifyAgainstPlane(s[2]),h=i.classifyAgainstPlane(s[3]),u=i.classifyAgainstPlane(s[4]),l=i.classifyAgainstPlane(s[5]);0<=o&&a<=0&&0<=u&&l<=0&&this._addTo(t,0,i,e,n),o<=0&&0<=a&&u<=0&&0<=l&&this._addTo(t,1,i,e,n),0<=r&&h<=0&&0<=u&&0<=l&&this._addTo(t,2,i,e,n),r<=0&&0<=h&&u<=0&&l<=0&&this._addTo(t,3,i,e,n),r<=0&&o<=0&&a<=0&&h<=0&&this._addTo(t,4,i,e,n),0<=r&&0<=o&&0<=a&&0<=h&&this._addTo(t,5,i,e,n)},yh.prototype._addTo=function(t,e,i,n,s){var r=t.skeleton,o=t.skeletonMatrices,a=this._renderItemPool,h=this._renderLists[e],u=t.material,l=a.getItem();l.material=u,l.meshInstance=t,l.skeleton=r,l.skeletonMatrices=o,l.renderOrderHint=s,l.worldBounds=i,h.push(l)},yh.prototype.qualifiesBounds=function(t){return t.intersectsBound(this._lightBounds)},yh.prototype.qualifies=function(t,e){return t.hierarchyVisible&&(e||t.worldBounds.intersectsBound(this._lightBounds))},Th.prototype={render:(dh=new q,function(t,e,i,n){var s=t.entity;s.worldMatrix.getColumn(3,dh),this._cubeCamera.farDistance=t._radius,this._cubeCamera.position=dh,this._casterCollector.setLightBounds(s.worldBounds),this._casterCollector.collect(this._cubeCamera,n,i),B.setInvertCulling(!0);for(var r=1/e.size,o=0;o<6;++o){var a=e.getNextRect(),h=this._cubeCamera.getFaceCamera(o);B.setViewport(a);var u=a.width*r,l=a.height*r,c=a.x*r,_=a.y*r;t._shadowTiles[o].set(.5*u,.5*l,.5*u+c,.5*l+_),hh(this,h,De.POINT_LIGHT_SHADOW_MAP_PASS,this._casterCollector.getRenderList(o),t)}B.setInvertCulling(!1),B.setColorMask(!0)})},(Nh.prototype=Object.create(jn.prototype)).getRenderList=function(){return this._renderList},Nh.prototype.collect=function(t,e,i){this.reset(),this._camera=t,this._renderList=[],i.worldMatrix.getColumn(3,this._viewCameraPos),t.worldMatrix.getColumn(1,this._cameraYAxis),this._frustumPlanes=t.frustum.planes,this._renderItemPool.reset(),e.acceptVisitor(this),this._renderList.sort(nh)},Nh.prototype.visitEntity=function(t){var e=t.components.meshInstance;if(e)for(var i=0,n=e.length;i=s._lodRangeStartSqr&&_n.t*n.t)break;r.transformFrom(s,a.objectMatrix),this._testMesh(r,a.meshInstance.mesh,n)&&(t=a.worldMatrix,n.entity=a.meshInstance.entity,n.component=a.meshInstance)}return n.entity&&(t.transformPoint(n.point,n.point),t.transformNormal(n.faceNormal,n.faceNormal)),n},Gh.prototype._testMesh=function(t,e,i){for(var n=t.direction,s=t.origin,r=s.x,o=s.y,a=s.z,h=n.x,u=n.y,l=n.z,c=e.getVertexAttributeByName("hx_position"),_=e.getVertexData(c.streamIndex),d=e.getIndexData(),f=e.getVertexStride(c.streamIndex),p=d.length,g=c.offset,M=!1,m=0;m=i.t)){var z=b*h+r,R=b*u+o,U=b*l+a,B=z-T,F=R-N,k=U-D,Y=E*E+w*w+L*L,Q=I*I+v*v+S*S,G=E*I+w*v+L*S,V=Y*Q-G*G;if(0!==V){var X=B*E+F*w+k*L,H=B*I+F*v+k*S,W=1/V,Z=(Q*X-G*H)*W,q=(Y*H-G*X)*W,K=1-Z-q;0<=K&&K<=1&&0<=Z&&Z<=1&&0<=q&&q<=1&&(i.faceNormal.set(O,C,j,0),i.point.set(z,R,U,1),i.barycentric.set(K,Z,q,0),i.mesh=e,i.t=b,i.faceIndex=m,M=!0)}}}}return i.faceNormal.normalize(),M},Gh.prototype._sortPotentialFunc=function(t,e){return t.closestDistanceSqr-e.closestDistanceSqr},Hh.prototype={update:function(t){this._currentFPS=1e3/t,this._runningSum-=this._frames[this._index],this._runningSum+=this._currentFPS,this._averageFPS=this._runningSum/this._numFrames,this._frames[this._index++]=this._currentFPS,this._index===this._numFrames&&(this._index=0),(void 0===this._maxFPS||this._currentFPS>this._maxFPS)&&(this._maxFPS=this._currentFPS),(void 0===this._minFPS||this._currentFPS Helix example: Temporal Anti-Aliasing - + diff --git a/examples/taa/script.js b/examples/taa/script.js index 809ed529..39cf943f 100644 --- a/examples/taa/script.js +++ b/examples/taa/script.js @@ -65,6 +65,7 @@ function initCamera(camera) camera.addComponent(controller); taa = new HX.TAA(); + taa.alpha = 0.01; fxaa = new HX.FXAA(); camera.addComponent(taa); camera.addComponent(fxaa); @@ -90,7 +91,7 @@ function initScene(scene, camera, assetLibrary) var material = new HX.BasicMaterial(); material.cullMode = HX.CullMode.NONE; material.metallicness = 1.0; - material.roughness = .01; + material.roughness = .1; replaceMaterials(model, material, floorMaterial); scene.startSystem(new HX.FixedLightsSystem()); @@ -123,5 +124,5 @@ function initGui() var taaFolder = gui.addFolder("TAA"); taaFolder.add(taa, "alpha").min(0).max(1).step(.001); - taaFolder.add(taa, "gamma").min(0).max(1).step(.001); + taaFolder.add(taa, "gamma").min(0).max(2).step(.001); } \ No newline at end of file diff --git a/src/helix-core/effect/TAA.js b/src/helix-core/effect/TAA.js index 0a8867bb..aa69ed45 100644 --- a/src/helix-core/effect/TAA.js +++ b/src/helix-core/effect/TAA.js @@ -42,7 +42,7 @@ function TAA() ShaderLibrary.get("taa_fragment.glsl") ); this._pass.setTexture("historyBuffer", this._historyTexture); - this.alpha = .01; + this.alpha = .1; this.gamma = 1.0; } diff --git a/src/helix-core/glsl/post-processing/taa_fragment.glsl b/src/helix-core/glsl/post-processing/taa_fragment.glsl index 4d47fff1..0d4dc09c 100644 --- a/src/helix-core/glsl/post-processing/taa_fragment.glsl +++ b/src/helix-core/glsl/post-processing/taa_fragment.glsl @@ -16,8 +16,8 @@ void main() float amount = alpha; // out of bounds: take new value completely - if (oldUV.x < 0.0 || oldUV.x > 1.0 || oldUV.y < 0.0 || oldUV.y > 1.0) - amount = 1.0; +// if (oldUV.x < 0.0 || oldUV.x > 1.0 || oldUV.y < 0.0 || oldUV.y > 1.0) +// amount = 1.0; // neighbourhood clamping: the old colour is only considered valid if it's within the bounds of the current neighbours // https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf [Karis2014] @@ -29,42 +29,34 @@ void main() vec3 maxBound = max(max(max(max(l, r), t), b), c); // just treat rgb space as a regular 3D space - if (any(lessThan(old, minBound)) || any(greaterThan(old, maxBound))) { - // variance clipping - // http://developer.download.nvidia.com/gameworks/events/GDC2016/msalvi_temporal_supersampling.pdf - // moments - vec3 m1 = l + r + t + b + c; - vec3 m2 = l * l + r * r + t * t + b * b + c * c; - // variance - vec3 mu = m1 / 5.0; - vec3 sigma = sqrt(m2 / 5.0 - mu * mu); - - vec3 d = c - old; - - // find relevant AABB planes (those closest to the ray, know this from ray direction) - vec3 planes = mu - sign(d) * gamma * sigma; - - // clip to old AABB to make sure it's never bigger - planes = max(planes, minBound); - planes = min(planes, maxBound); - - - // clip segment [old -> C] against new AABB - // C is always inside AABB - vec3 tm = (planes - old) / d; - vec3 absD = abs(d); - - float t = 0.0; - - if (absD.x > 0.0003) - t = max(tm.x, t); - if (absD.y > 0.0003) - t = max(tm.y, t); - if (absD.z > 0.0003) - t = max(tm.z, t); - - old += t * d; - } + // variance clipping + // http://developer.download.nvidia.com/gameworks/events/GDC2016/msalvi_temporal_supersampling.pdf + // moments + vec3 m1 = l + r + t + b + c; + vec3 m2 = l * l + r * r + t * t + b * b + c * c; + // variance + vec3 mu = m1 / 5.0; + vec3 sigma = sqrt(m2 / 5.0 - mu * mu); + + vec3 d = c - old; + + // find relevant AABB planes (those closest to the ray, know this from ray direction) + vec3 planes = mu - sign(d) * gamma * sigma; + + // clip to old AABB to make sure it's never bigger + planes = max(planes, minBound); + planes = min(planes, maxBound); + + // clip segment [old -> C] against new AABB + // C is always inside AABB + vec3 tm = (planes - old) / d; + vec3 absD = abs(d); + + float tf = (max(tm.x, tm.y), tm.z); + + // if already inside the box, or somehow overshooting target (?) + if (tf >= -0.001 && tf <= 1.001) + old += tf * d; hx_FragColor.xyz = mix(old, c, amount); hx_FragColor.w = col.w; diff --git a/src/helix-core/math/Matrix4x4.js b/src/helix-core/math/Matrix4x4.js index 91803179..ebf02d50 100644 --- a/src/helix-core/math/Matrix4x4.js +++ b/src/helix-core/math/Matrix4x4.js @@ -1528,7 +1528,7 @@ Matrix4x4.prototype = cm[10] *= rcpZ; quat.fromMatrix(clone); - this.getColumn(3, pos) + this.getColumn(3, pos); return targetOrPos; },