It looks like this is a web page, not a feed. I looked for a feed associated with this page, but couldn't find one. Please enter the address of your feed to validate.

Source: https://www.shadertoy.com/user/StephanUgli654/

  1.  
  2. <!DOCTYPE HTML>
  3. <html lang="en">
  4. <head>
  5.    
  6. <script async src="https://www.googletagmanager.com/gtag/js?id=G-7SYLWGZYJ2"></script>
  7. <script>
  8.  window.dataLayer = window.dataLayer || [];
  9.  function gtag(){dataLayer.push(arguments);}
  10.  gtag('js', new Date());
  11.  
  12.  gtag('config', 'G-7SYLWGZYJ2');
  13. </script>
  14.  
  15. <title>StephanUgli654 - Shadertoy BETA</title>
  16. <meta charset="utf-8" />
  17. <meta name="Keywords" content="shadertoy, shader toy, quilez, inigo, jeremias, pol, fractals, demoscene, computer graphics, mathematics, rendering, demo, 3D, realtime, shader, raytracing, raymarching, webgl, glsl" />
  18. <meta name="Description" content="Build shaders, share them, and learn from the best community." />
  19. <meta name="Author" content="Beautypi" />
  20. <meta name="apple-mobile-web-app-capable" content="yes" />
  21. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  22.  
  23. <link rel="image_src" href="https://www.shadertoy.com/img/logo.png" />
  24. <link rel="apple-touch-icon" href="/img/launch_icon_57.png"/>
  25. <link rel="apple-touch-icon" sizes="72x72" href="/img/launch_icon_72.png"/>
  26. <link rel="apple-touch-icon" sizes="114x114" href="/img/launch_icon_114.png"/>
  27. <link rel="shortcut icon" href="/img/favicon.ico"/>
  28.  
  29. <style>*
  30. {
  31.    box-sizing: border-box;
  32. }
  33.  
  34. ::-webkit-scrollbar {
  35.    height: 8px;
  36.    width: 8px;
  37.    background: #404040;
  38. }
  39.  
  40. ::-webkit-scrollbar-thumb
  41. {
  42.    background: #909090;
  43.    border-radius: 0ex;
  44. }
  45.  
  46. ::-webkit-scrollbar-corner
  47. {
  48.    background: #000;
  49. }
  50.  
  51. ::-webkit-input-placeholder
  52. {
  53. font-style:italic;
  54. }
  55. input:-moz-placeholder, textarea:-moz-placeholder
  56. {
  57. font-style:italic;
  58. }
  59. input.placeholder-text, textarea.placeholder-text
  60. {
  61. font-style:italic;
  62. }
  63.  
  64. pre
  65. {
  66.    white-space: pre-wrap;
  67.    white-space: -moz-pre-wrap;
  68.    white-space: -pre-wrap;
  69.    white-space: -o-pre-wrap;
  70.    word-wrap: break-word;
  71. }
  72.  
  73. @font-face
  74. {
  75.    font-family: Lobster;
  76.    src: url("/img/lobster.otf") format("opentype");
  77. }
  78.  
  79. div#centerScreen
  80. {
  81.    left: 50%;
  82.    top: 50%;
  83.    position: absolute;
  84. }
  85.  
  86. a.headerLinks:hover
  87. {
  88.    background-color:#505050;
  89.    color : #ff8020;
  90. }
  91.  
  92. body
  93. {
  94.    color: #000000;
  95.    font-size:12px;
  96.    font-style:normal;
  97.    font-family:Tahoma,Arial;
  98.    background-repeat: no-repeat;
  99.    //background-attachment: fixed;
  100.    padding:0px;
  101.    margin:0px;
  102.    text-align: left;
  103.    background-color: #d0d0d0;
  104.    background-repeat: repeat;
  105.    user-select: text;
  106. }
  107.  
  108. a,
  109. a:hover,
  110. a:visited
  111. {
  112.  color : inherit;
  113. }
  114.  
  115. div#content {
  116.    width: 95%;
  117.    overflow: hidden;
  118.    margin: auto;
  119.    padding: 0px;
  120.    min-height: calc(100vh - 80px);
  121. }
  122.  
  123.  
  124. .notificationCount
  125. {
  126. background-color:#ff0000;
  127. padding-left:3px;
  128. padding-right:1px;
  129. padding-top:1px;
  130. padding-bottom:1px;
  131. }
  132.  
  133. div#header
  134. {
  135.    background-color: #404040;
  136.    top: 0px;
  137.    left: 0px;
  138.    width: 100%;
  139.    padding: 0;
  140.    margin: 0;
  141.    color: #ffffff;
  142.    display: flex;
  143.    flex-direction:row;
  144. }
  145.  
  146. #headerBlock1
  147. {
  148.    width: 50%;
  149.    display:flex;
  150.    align-items:center;
  151. }
  152.  
  153. a#headerTitle
  154. {
  155.    font-size: 2.25em;
  156.    font-family: Lobster,Tahoma,Arial;
  157.    text-decoration: none;
  158.    padding-left:32px;
  159.    padding-right:32px;
  160. }
  161.  
  162. #headerSearch
  163. {
  164.    display: inline-block;
  165.    color: #000000;
  166.    width: 300px;
  167. }
  168.  
  169. input[type=search]#mySearch
  170. {
  171.    width: 100%;
  172.    border-radius: 6px;
  173.    border: 1px solid black;
  174.    padding:12px;
  175. }
  176.  
  177. #headerBlock2
  178. {
  179.    width: 50%;
  180.    margin-left: auto;
  181.    display: flex;
  182.    justify-content: flex-end;
  183. }
  184.  
  185.  
  186. a#headerTitle:hover
  187. {
  188.    color : #ff8020;
  189. }
  190.  
  191. a.headerLinks
  192. {
  193.    font-weight: bold;
  194.    padding-top: 14px;
  195.    padding-bottom: 14px;
  196.    padding-left: 14px;
  197.    padding-right: 14px;
  198.    margin:0px;
  199.    text-decoration: none;
  200.    transition: background-color 0.15s linear, color 0.15s linear;
  201. }
  202.  
  203. #footer
  204. {
  205.    background-color: rgba(64,64,64,0.25);
  206.    color: #000000;
  207.    padding: 0px;
  208.    margin: 0px;
  209.    width: 100%;
  210.    display: flex;
  211.    justify-content: space-between;
  212.    flex-wrap: wrap;
  213. }
  214.  
  215. #footer div
  216. {
  217.    padding-top:10px;
  218.    padding-bottom:0px;
  219.    padding-left:16px;
  220.    padding-right:16px;
  221. }
  222.  
  223. #footer div ul
  224. {
  225.    margin-left:0px;
  226.    padding-left:16px;
  227. }
  228.  
  229. #footer div ul li
  230. {
  231.    padding-top:6px;
  232. }
  233.  
  234. a.regular
  235. {
  236.    font-weight:bold;
  237.    text-decoration:none
  238. }
  239.  
  240. a.regular:hover
  241. {
  242.  color : #ff8020;
  243. }
  244.  
  245. a.user
  246. {
  247.    font-weight:bold;
  248.    text-decoration:none;
  249. }
  250.  
  251. a.user:hover
  252. {
  253.  color : #ff8020;
  254.  text-decoration: underline;
  255. }
  256.  
  257. .uiButton
  258. {
  259.    border: none;
  260.    outline: none;
  261.    margin: 0px;
  262.    padding: 0px;
  263.    width: 22px;
  264.    height: 22px;
  265.    cursor: pointer;
  266.    border-radius: 4px;
  267. }
  268.  
  269. .uiButton:hover
  270. {
  271.    box-shadow: inset 0px 0px 1px 1px #808080, 0px 0px 1px 1px #808080;
  272. }
  273.  
  274. .uiDivBUtton
  275. {
  276.    cursor:pointer;
  277. }
  278.  
  279. .uiDivBUtton:hover
  280. {
  281.    color: #ffffff;
  282. }
  283.  
  284.  
  285. .dialog
  286. {
  287.    display: block;
  288.    background-color: #e0e0e0;
  289.    color: #000000;
  290.    border:1px solid #000;
  291.    padding:0px;
  292.    margin:0px;
  293.    text-align:left;
  294.    border-radius: 4px;
  295.    box-shadow:4px 4px 6px 0px rgba(0,0,0,0.5);
  296.    overflow: hidden;
  297.    z-index:1000;
  298.    visibility: hidden;
  299.    opacity:0;
  300.    -moz-transition: opacity 0.25s linear,visibility 0.25s linear;
  301.    -webkit-transition: opacity 0.25s linear,visibility 0.25s linear;
  302.    transition: opacity 0.25s linear,visibility 0.25s linear;
  303. }
  304.  
  305. .dialogHeader
  306. {
  307.    left:0px;
  308.    top: 0px;
  309.    width:100%;
  310.    height:32px;
  311.    position: absolute;
  312.    background-color: #808080;
  313.    cursor:move;
  314. }
  315.  
  316. .dialogTitle
  317. {
  318.    left: 12px;
  319.    top: 4px;
  320.    position: absolute;
  321.    padding: 0px;
  322.    margin: 0px;
  323.    color:#000000;
  324.    font-size:1.5em;
  325.    text-align: left;
  326.    user-select: none;
  327.    -moz-user-select: -moz-none;
  328.    -webkit-user-select: none;
  329. }
  330.  
  331. .dialogOverlay
  332. {
  333.    z-index:1000;
  334.  
  335.    visibility: hidden;
  336.    opacity:0;
  337.    -moz-transition: opacity 0.25s linear,visibility 0.25s linear;
  338.    -webkit-transition: opacity 0.25s linear,visibility 0.25s linear;
  339.    transition: opacity 0.25s linear,visibility 0.25s linear;
  340.  
  341.    left:0px;
  342.    top:0px;
  343.    padding:0px;
  344.    margin:0px;
  345.    width:100%;
  346.    height:100%;
  347.    position:absolute;
  348.  
  349.    background-color:rgba(0,0,0,.4);
  350. }
  351.  
  352. .viewsIcon, .likesIcon
  353. {
  354.    border: none;
  355.    outline: none;
  356.    display:inline-block;
  357.    background-repeat:no-repeat;
  358.    top:0px;
  359.    left:0px;
  360.    padding:0px;
  361.    padding-right: 2px;
  362.    margin:0px;
  363.    position:relative;
  364. }
  365.  
  366. .userPictureSmall
  367. {
  368.    background-color:#808080;
  369.    border: 1px solid #000000;
  370.    width:32px;
  371.    height:32px;
  372. }
  373.  
  374. .dialogCloseButton
  375. {
  376.    right:8px;
  377.    top: 4px;
  378.    width:22px;
  379.    height:22px;
  380.    position: absolute;
  381.    background-image: url("/img/close.png");
  382.    cursor: pointer;
  383.    border-radius: 4px;
  384. }
  385.  
  386. .dialogCloseButton:hover
  387. {
  388.    box-shadow: inset 0px 0px 4px 2px #ffffff, 0px 0px 4px 2px #ffffff;
  389. }
  390.  
  391. .dialogContentButtons
  392. {
  393.     padding:0;
  394.     border:0;
  395.     text-align: justify;
  396.     left: 24px;
  397.     bottom:40px;
  398.     position:absolute;
  399. }
  400.  
  401. .dialogButton
  402. {
  403.    text-align: center;
  404.    vertical-align: middle;
  405.    display: inline-block;
  406.    border-radius: 4px;
  407.    font-weight: bold;
  408.    cursor: pointer;
  409.    padding-bottom:5px;
  410.    padding-top:4px;
  411.    padding-left: 8px;
  412.    padding-right: 8px;
  413.    margin-left:4px;
  414.    margin-right:4px;
  415.    text-decoration: none;
  416.    color:#000000;
  417.    width: 80px;
  418.    -moz-transition:    background-color 0.15s linear, color 0.15s linear;
  419.    -webkit-transition: background-color 0.15s linear, color 0.15s linear;
  420.    transition:         background-color 0.15s linear, color 0.15s linear;
  421. }
  422.  
  423. .dialogButton:hover
  424. {
  425.  background-color:#808080;
  426.  color : #ff8020;
  427. }
  428.  
  429. .dialogCloseButton:hover
  430. {
  431.    box-shadow: inset 0px 0px 4px 2px #ffffff, 0px 0px 4px 2px #ffffff;
  432. }
  433.  
  434. .dialogContent
  435. {
  436.    color: inherit;
  437.    overflow: auto;
  438.    width:100%;
  439.    height:100%;
  440.    left: 0px;
  441.    top: 32px;
  442.    position:absolute
  443. }
  444.  
  445. .dialogContentBody
  446. {
  447.    color: inherit;
  448.    width:100%;
  449.    height:auto;
  450.    padding-top:24px;
  451.    padding-bottom:24px;
  452.    padding-left:24px;
  453.    padding-right:24px;
  454.    text-align: left;
  455. }
  456.  
  457. .formButton
  458. {
  459.    font-weight:bold;
  460. color:#ffffff;
  461. border:none;
  462.    text-align:center;
  463. background-color:#808080;
  464.    border-radius: 4px;
  465. padding-left:8px;
  466. padding-right:8px;
  467. padding-top:4px;
  468. padding-bottom:4px;
  469.    cursor:pointer;
  470.    min-width:80px;
  471. }
  472. .formInput {
  473.    border-radius: 6px;
  474.    border: 1px solid black;
  475.    padding: 4px;
  476.    border: none;
  477. }
  478. .formButton:hover {
  479.    background-color: #e0e0e0;
  480. }
  481. .formButton:disabled
  482. {
  483. color:#b0b0b0;
  484. background-color:#808080;
  485. }
  486.  
  487. .formButtonSmall
  488. {
  489.    color:#ffffff;
  490.    border:none;
  491.    text-align:center;
  492.    background-color:#808080;
  493.    border-radius: 4px;
  494.    padding-left:2px;
  495.    padding-right:2px;
  496.    padding-top:2px;
  497.    padding-bottom:2px;
  498.    cursor:pointer;
  499.    min-width:40px;
  500. }
  501.  
  502. .formButtonSmall:hover
  503. {
  504.    background-color: #e0e0e0;
  505. }
  506.  
  507. .formButtonSmall:disabled
  508. {
  509.    color:#b0b0b0;
  510.    background-color:#808080;
  511. }
  512.  
  513. .formButtonSmall.disabled2,
  514. .formButton.disabled2 { color:#b0b0b0; background-color:#808080; pointer-events: none; }
  515.  
  516. .inputForm
  517. {
  518.    padding-left:2%;
  519.    padding-right:2%;
  520.    resize: none;
  521.    text-align: left;
  522.    background-color:#e0e0e0;
  523.    outline: none;
  524.    border-radius: 4px;
  525.    border: 1px solid #808080;
  526.    color:inherit;
  527. }
  528.  
  529. .inputForm:focus
  530. {
  531.    border: 1px solid #AFCDD8;
  532.    background-color: #EBF2F4;
  533. }
  534.  
  535. .transparentPannel
  536. {
  537.    background-color:rgba(64,64,64,0.1);
  538.    padding:16px;
  539. }
  540.  
  541. .comment, .commentSelf, .commentNew
  542. {
  543.    border-radius: 4px;
  544.    width: 100%;
  545.    margin-left: 0px;
  546.    margin-right: 0px;
  547.    margin-top: 0px;
  548.    margin-bottom: 6px;
  549.  
  550.    padding: 14px;
  551.    display: grid;
  552.    grid-template-columns: 32px auto 8px;
  553.    grid-template-rows: 1fr;
  554.    grid-gap:8px;
  555. }
  556.  
  557. .comment:nth-child(even)
  558. {
  559.    background-color: rgba(64,64,64,0.1);
  560. }
  561.  
  562. .comment:nth-child(odd)
  563. {
  564.    background-color: rgba(128,128,128,0.1);
  565. }
  566.  
  567. .commentSelf
  568. {
  569.    background-color: rgba(240,160,64,0.1);
  570. }
  571.  
  572. .commentNew
  573. {
  574.    padding-right: 0px;
  575.    grid-template-columns: 40px auto;
  576. }
  577.  
  578. .commentContent
  579. {
  580.    vertical-align: top;
  581.    text-align: left;
  582.    word-break: break-all;
  583.    word-break: break-word;
  584.    white-space: pre-wrap;
  585.    white-space: -moz-pre-wrap;
  586. }
  587.  
  588.  
  589. /* ----------------------- media resolutions ------------------------ */
  590.  
  591. @media screen and (max-width:799px)
  592. {
  593.    div#header {flex-direction:column; }
  594.    #headerBlock1 { width:100%; }
  595.    #headerBlock2 { width:100%; justify-content: space-around;}
  596.    div#headerSearch {width:200px;}
  597.    input#mySearch { width:200px; left:21px; height:22px; border-radius:6px; padding-left:8px; padding-right:8px; }
  598.    .previewText { width:130px; }
  599.    .transparentPannel { padding:10px; }
  600. }
  601.  
  602. @media screen and (min-width:800px) and (max-width:1279px)
  603. {
  604.    body { font-size: 9px; }
  605.    div#headerSearch {width: 250px;}
  606.    input#mySearch { width:250px; left:21px; height:22px; border-radius:6px; padding-left:8px; padding-right:8px; }
  607.    .previewText { width:130px; }
  608.    .transparentPannel { padding:11px; }
  609. }
  610.  
  611. @media screen and (min-width:1280px) and (max-width:1439px)
  612. {
  613.    body { font-size: 10px; }
  614.    div#headerSearch {width: 300px;}
  615.    input#mySearch { width:300px; left:21px; height:22px; border-radius:6px; padding-left:8px; padding-right:8px; }
  616.    .dialogHeader { height:28px; }
  617.    .previewText { width:180px; }
  618.    .transparentPannel { padding:12px; }
  619. }
  620.  
  621. @media screen and (min-width:1440px) and (max-width:1919px)
  622. {
  623.    div#headerSearch {width: 300px;}
  624.    input#mySearch { width:300px; left:21px; height:22px; border-radius:6px; padding-left:8px; padding-right:8px; }
  625.    .dialogHeader { height:28px; }
  626.    .previewText { width:180px; }
  627.    .transparentPannel { padding:12px; }
  628. }
  629.  
  630. @media screen and (min-width:1920px) and (max-width:2559px)
  631. {
  632.    div#headerSearch {width: 300px;}
  633.    input#mySearch { width:300px; left:21px; height:22px; border-radius:6px; padding-left:8px; padding-right:8px; }
  634.    .dialogHeader { height:32px; }
  635.    .previewText { width:220px; }
  636.    .transparentPannel { padding:16px; }
  637. }
  638.  
  639. @media screen and (min-width:2560px)
  640. {
  641.    div#headerSearch {width: 300px;}
  642.    input#mySearch { width:300px; left:21px; height:22px; border-radius:6px; padding-left:8px; padding-right:8px; }
  643.    .dialogHeader { height:32px; }
  644.    .previewText { width:220px; }
  645.    .transparentPannel { padding:16px; }
  646. }
  647. body
  648. {
  649.    background-image: url("/img/themes/classic/background.jpg");
  650. }
  651. </style>
  652.    <script>"use strict"
  653.  
  654. //==============================================================================
  655. //
  656. // piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  657. //
  658. // piCamera
  659. //
  660. //==============================================================================
  661.  
  662. function piCamera()
  663. {
  664.    var mMatrix = setIdentity();
  665.    var mMatrixInv = setIdentity();
  666.  
  667.    var mPosition = [0.0,0.0,0.0];
  668.    var mXRotation = 0.0;
  669.    var mYRotation = 0.0;
  670.  
  671.    var mPositionTarget = [0.0,0.0,0.0];
  672.    var mXRotationTarget = 0.0;
  673.    var mYRotationTarget = 0.0;
  674.  
  675.    var me = {};
  676. /*
  677.    me.Set = function( pos, dir, roll)
  678.             {
  679.                 mMatrix    = setLookat( pos, add(pos,dir), [Math.sin(roll),Math.cos(roll),Math.sin(roll)] );
  680.                 mMatrixInv = invertFast( mMatrix );
  681.             };
  682. */
  683.    me.SetPos = function(pos)
  684.                {
  685.                    mPosition = pos;
  686.                    //mMatrix[ 3] = -(mMatrix[0] * pos[0] + mMatrix[1] * pos[1] + mMatrix[ 2] * pos[2]);
  687.                    //mMatrix[ 7] = -(mMatrix[4] * pos[0] + mMatrix[5] * pos[1] + mMatrix[ 6] * pos[2]);
  688.                    //mMatrix[11] = -(mMatrix[8] * pos[0] + mMatrix[9] * pos[1] + mMatrix[10] * pos[2]);
  689.                };
  690. /*
  691.    me.GlobalMove = function(pos)
  692.                    {
  693.                        mMatrix[ 3] -= (mMatrix[0] * pos[0] + mMatrix[1] * pos[1] + mMatrix[ 2] * pos[2]);
  694.                        mMatrix[ 7] -= (mMatrix[4] * pos[0] + mMatrix[5] * pos[1] + mMatrix[ 6] * pos[2]);
  695.                        mMatrix[11] -= (mMatrix[8] * pos[0] + mMatrix[9] * pos[1] + mMatrix[10] * pos[2]);
  696.                        mMatrixInv = invertFast(mMatrix);
  697.                    };
  698. */
  699.    me.LocalMove = function( dis )
  700.                    {
  701.                        dis = matMulvec( setRotationY(-mYRotation), dis);
  702.                        mPositionTarget = sub(mPositionTarget,dis)
  703.                    };
  704.  
  705.    me.RotateXY = function( x, y)
  706.                  {
  707.                    mXRotationTarget -= x;
  708.                    mYRotationTarget -= y;
  709.                    mXRotationTarget = Math.min( Math.max( mXRotationTarget, -Math.PI/2), Math.PI/2 );
  710.                  };
  711.  
  712.  
  713.    me.CameraExectue = function( dt )
  714.    {
  715.        // smooth position
  716.        mXRotation += (mXRotationTarget-mXRotation) * 12.0*dt;
  717.        mYRotation += (mYRotationTarget-mYRotation) * 12.0*dt;
  718.        mPosition = add(mPosition, mul( sub(mPositionTarget, mPosition), 12.0*dt));
  719.  
  720.        // Make Camera matrix
  721.        mMatrix = matMul( matMul(setRotationX(mXRotation),
  722.                                 setRotationY(mYRotation)),  
  723.                                 setTranslation(mPosition));
  724.        mMatrixInv = invertFast(mMatrix);
  725.  
  726.    }
  727.  
  728.    me.GetMatrix = function() { return mMatrix; };
  729.    me.GetMatrixInverse = function() { return mMatrixInv; };
  730.    me.SetMatrix = function( mat )
  731.                    {
  732.                        mMatrix = mat;
  733.                        mMatrixInv = invertFast(mMatrix);
  734.  
  735.                        mPosition = getXYZ(matMulpoint(mat, [0.0,0.0,0.0]));
  736.                        mPositionTarget = mPosition;
  737.                    };
  738.  
  739.    me.GetPos = function() { return getXYZ(matMulpoint(mMatrixInv, [0.0,0.0,0.0])); }
  740.    me.GetDir = function() { return getXYZ(normalize(matMulvec(mMatrixInv, [0.0,0.0,-1.0]))); }
  741.  
  742.    return me;
  743. }
  744. //==============================================================================
  745. //
  746. // piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  747. //
  748. // piFile
  749. //
  750. //==============================================================================
  751.  
  752. function piFile( binaryDataArrayBuffer )
  753. {
  754.    // private
  755.    //var mDataView = new DataView( binaryDataArrayBuffer, 0 );
  756.    var mDataView = binaryDataArrayBuffer;
  757.    var mOffset = 0;
  758.  
  759.    // public members
  760.    var me = {};
  761.    me.mDummy = 0;
  762. /*
  763.    // public functions
  764.    me.Seek = function( off ) { mOffset = off - 3; };
  765.    me.ReadUInt16 = function()  { var res = mDataView.getUint16( mOffset ); mOffset+=2; return res; };
  766.    me.ReadUInt32 = function()  { var res = mDataView.getUint32( mOffset ); mOffset+=4; return res; };
  767.    me.ReadUInt64 = function()  { return me.ReadUInt32() + (me.ReadUInt32()<<32); };
  768.    me.ReadFloat32 = function() { var res = mDataView.getFloat32( mOffset ); mOffset+=4; return res; };
  769. */
  770.  
  771.    me.Seek = function( off ) { mOffset = off; };
  772.    me.ReadUInt8  = function()  { var res = (new Uint8Array(mDataView,mOffset))[0]; mOffset+=1; return res; };
  773.    me.ReadUInt16 = function()  { var res = (new Uint16Array(mDataView,mOffset))[0]; mOffset+=2; return res; };
  774.    me.ReadUInt32 = function()  { var res = (new Uint32Array(mDataView,mOffset))[0]; mOffset+=4; return res; };
  775.    me.ReadUInt64 = function()  { return me.ReadUInt32() + (me.ReadUInt32()<<32); };
  776.    me.ReadFloat32 = function() { var res = (new Float32Array(mDataView,mOffset))[0]; mOffset+=4; return res; };
  777.    me.ReadFloat32Array = function(n)
  778.                          {
  779.                              var src = new Float32Array(mDataView, mOffset);
  780.                              var res = [];  for( var i=0; i<n; i++ ) { res[i] = src[i]; }
  781.                              mOffset += 4*n;
  782.                              return res;
  783.                          };
  784.    me.ReadFloat32ArrayNative = function(n) { var src = new Float32Array(mDataView, mOffset); mOffset += 4*n; return src; };
  785.    return me;
  786. }
  787. //==============================================================================
  788. //
  789. // piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  790. //
  791. // piMesh
  792. //
  793. //==============================================================================
  794.  
  795. function piMesh()
  796. {
  797.    this.mChunks = [];
  798.    this.mPrimitiveType = 0;
  799.    this.mVertexFormat = null;
  800. }
  801.  
  802. /*
  803. piMesh.prototype.normalize = function( ppos, npos )
  804. {
  805.    var numv = this.mVertexData.length;
  806.    var numt = this.mIndices.length;
  807.  
  808.    for( var i=0; i<numv; i++ )
  809.    {
  810.        //float *v = (float*)piMesh_GetVertexData( me, i, npos );
  811.        //v[0] = 0.0f;
  812.        //v[1] = 0.0f;
  813.        //v[2] = 0.0f;
  814.        this.mVerts[8 * i + 3] = 0.0;
  815.        this.mVerts[8 * i + 4] = 0.0;
  816.        this.mVerts[8 * i + 5] = 0.0;
  817.    }
  818.  
  819.    for( var i=0; i<numt; i++ )
  820.    {
  821.        piMeshFace *face = me->mFaceData.mIndexArray[0].mBuffer + i;
  822.  
  823.        const int ft = face->mNum;
  824.        
  825.        vec3 nor = vec3( 0.0f, 0.0f, 0.0f );
  826.        for( int j=0; j<ft; j++ )
  827.        {
  828.            const vec3 va = *((vec3*)piMesh_GetVertexData( me, face->mIndex[ j      ], ppos ));
  829.            const vec3 vb = *((vec3*)piMesh_GetVertexData( me, face->mIndex[(j+1)%ft], ppos ));
  830.  
  831.            nor += cross( va, vb );
  832.        }
  833.  
  834.        for( int j=0; j<ft; j++ )
  835.        {
  836.            vec3 *n = (vec3*)piMesh_GetVertexData( me, face->mIndex[j], npos );
  837.            n->x += nor.x;
  838.            n->y += nor.y;
  839.            n->z += nor.z;
  840.        }
  841.    }
  842.  
  843.    for( var i=0; i<numv; i++ )
  844.    {
  845.        vec3 *v = (vec3*)piMesh_GetVertexData( me, i, npos );
  846.        *v = normalize( *v );
  847.    }
  848. }
  849. */
  850.  
  851. piMesh.prototype.createCube = function(renderer)
  852. {
  853.    this.mPrimitiveType = 0;
  854.  
  855.    this.mChunks[0] = { mVerts : new Float32Array([ -1.0, -1.0, -1.0,
  856.                                       1.0, -1.0, -1.0,
  857.                                      -1.0,  1.0, -1.0,
  858.                                       1.0,  1.0, -1.0,
  859.                                      -1.0, -1.0,  1.0,
  860.                                       1.0, -1.0,  1.0,
  861.                                      -1.0,  1.0,  1.0,
  862.                                       1.0,  1.0,  1.0 ]),
  863.  
  864.                        mIndices : new Uint16Array([ 0, 2, 1,   1, 2, 3,   5, 1, 3,   5, 3, 7,   4, 5, 7,   4, 7, 6,   4, 6, 2,   4, 2, 0,   6, 7, 3,   6, 3, 2,   4, 0, 1,   4, 1, 5 ]),
  865.                        mNumVertices : 8,
  866.                        mNumFaces : 12,
  867.                        mTransform : setIdentity(),
  868.                        mVBO : null,
  869.                        mIBO : null };
  870.  
  871.    this.mVertexFormat = { mStride:12, mChannels:[ { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false } ] };
  872.  
  873.    return true;
  874. }
  875.  
  876. piMesh.prototype.createCubeSharp = function (renderer)
  877. {
  878.    this.mPrimitiveType = 0;
  879.  
  880.    this.mChunks[0] = { mVerts : new Float32Array([-1.0, 1.0,-1.0,   0.0, 1.0, 0.0,   0.0, 0.0,
  881.                                    -1.0, 1.0, 1.0,   0.0, 1.0, 0.0,   0.0, 1.0,
  882.                                     1.0, 1.0, 1.0,   0.0, 1.0, 0.0,   1.0, 1.0,
  883.                                     1.0, 1.0,-1.0,   0.0, 1.0, 0.0,   1.0, 0.0,
  884.  
  885.                                    -1.0,-1.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0,
  886.                                     1.0,-1.0, 1.0,   0.0, 0.0, 1.0,   0.0, 1.0,
  887.                                     1.0, 1.0, 1.0,   0.0, 0.0, 1.0,   1.0, 1.0,
  888.                                    -1.0, 1.0, 1.0,   0.0, 0.0, 1.0,   1.0, 0.0,
  889.  
  890.                                     1.0, 1.0, 1.0,   1.0, 0.0, 0.0,   0.0, 0.0,
  891.                                     1.0,-1.0, 1.0,   1.0, 0.0, 0.0,   0.0, 1.0,
  892.                                     1.0,-1.0,-1.0,   1.0, 0.0, 0.0,   1.0, 1.0,
  893.                                     1.0, 1.0,-1.0,   1.0, 0.0, 0.0,   1.0, 0.0,
  894.  
  895.                                     1.0,-1.0,-1.0,   0.0, 0.0,-1.0,   0.0, 0.0,
  896.                                    -1.0,-1.0,-1.0,   0.0, 0.0,-1.0,   0.0, 1.0,
  897.                                    -1.0, 1.0,-1.0,   0.0, 0.0,-1.0,   1.0, 1.0,
  898.                                     1.0, 1.0,-1.0,   0.0, 0.0,-1.0,   1.0, 0.0,
  899.  
  900.                                    -1.0,-1.0, 1.0,   0.0,-1.0, 0.0,   0.0, 0.0,
  901.                                    -1.0,-1.0,-1.0,   0.0,-1.0, 0.0,   0.0, 1.0,
  902.                                     1.0,-1.0,-1.0,   0.0,-1.0, 0.0,   1.0, 1.0,
  903.                                     1.0,-1.0, 1.0,   0.0,-1.0, 0.0,   1.0, 0.0,
  904.  
  905.                                    -1.0, 1.0, 1.0,  -1.0, 0.0, 0.0,   0.0, 0.0,
  906.                                    -1.0, 1.0,-1.0,  -1.0, 0.0, 0.0,   0.0, 1.0,
  907.                                    -1.0,-1.0,-1.0,  -1.0, 0.0, 0.0,   1.0, 1.0,
  908.                                    -1.0,-1.0, 1.0,  -1.0, 0.0, 0.0,   1.0, 0.0 ]),
  909.  
  910.                        mIndices : new Uint16Array([0,1,2, 0,2,3,   4,5,6, 4,6,7,    8,9,10,8,10,11,   12,13,14,12,14,15,   16,17,18,16,18,19,   20,21,22,20,22,23]),
  911.                        mNumVertices : 24,
  912.                        mNumFaces : 12,
  913.                        mTransform : setIdentity(),
  914.                        mVBO : null,
  915.                        mIBO : null };
  916.  
  917.  
  918.    this.mVertexFormat = { mStride:32, mChannels:[ { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false },
  919.                                                   { mNumComponents:3, mType: renderer.TYPE.FLOAT32, mNormalize: false },
  920.                                                   { mNumComponents:2, mType: renderer.TYPE.FLOAT32, mNormalize: false } ] };
  921.  
  922.    return true;
  923. }
  924.  
  925.  
  926. piMesh.prototype.createUnitQuad = function (renderer)
  927. {
  928.    this.mPrimitiveType = 0;
  929.    this.mVertexFormat = { mStride:8, mChannels: [ {mNumComponents:2, mType: renderer.TYPE.FLOAT32, mNormalize: false} ] };
  930.  
  931.    this.mChunks[0] = { mVerts : new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0,  1.0, 1.0,  1.0]),
  932.                        mIndices : new Uint16Array([0, 2, 1, 1, 2, 3]),
  933.                        mNumVertices : 4,
  934.                        mNumFaces : 2,
  935.                        mTransform : setIdentity(),
  936.                        mVBO : null,
  937.                        mIBO : null };
  938.    return true;
  939. }
  940.  
  941.  
  942.  
  943.  
  944. piMesh.prototype.destroy = function()
  945. {
  946.    //delete this.mVerts;   this.mVerts = null;
  947.    //delete this.mIndices; this.mIndices = null;
  948. }
  949.  
  950. piMesh.prototype.scale = function (x, y, z)
  951. {
  952.    var stride = this.mVertexFormat.mStride/4;
  953.    for( var j=0; j<this.mChunks.length; j++ )
  954.    {
  955.        var nv = this.mChunks[j].mNumVertices;
  956.        for (var i = 0; i < nv; i++)
  957.        {
  958.            this.mChunks[j].mVerts[stride * i + 0] *= x;
  959.            this.mChunks[j].mVerts[stride * i + 1] *= y;
  960.            this.mChunks[j].mVerts[stride * i + 2] *= z;
  961.        }
  962.    }
  963. }
  964.  
  965. piMesh.prototype.translate = function (x, y, z)
  966. {
  967.    var stride = this.mVertexFormat.mStride/4;
  968.    for( var j=0; j<this.mChunks.length; j++ )
  969.    {
  970.        var nv = this.mChunks[j].mNumVertices;
  971.        for (var i = 0; i < nv; i++)
  972.        {
  973.            this.mChunks[j].mVerts[stride * i + 0] += x;
  974.            this.mChunks[j].mVerts[stride * i + 1] += y;
  975.            this.mChunks[j].mVerts[stride * i + 2] += z;
  976.        }
  977.    }
  978. }
  979.  
  980. piMesh.prototype.GPULoad = function (renderer)
  981. {
  982.    for( var i=0; i<this.mChunks.length; i++ )
  983.    {
  984.        var vbo = renderer.CreateVertexArray(this.mChunks[i].mVerts, renderer.BUFTYPE.STATIC );
  985.        if (vbo == null)
  986.            return false;
  987.  
  988.        var ibo = renderer.CreateIndexArray(this.mChunks[i].mIndices, renderer.BUFTYPE.STATIC);
  989.        if (ibo == null)
  990.            return false;
  991.  
  992.        this.mChunks[i].mVBO = vbo;
  993.        this.mChunks[i].mIBO = ibo;
  994.    }
  995.    return true;
  996. }
  997.  
  998. piMesh.prototype.GPURender = function (renderer, positions )//, matPrj, matCam )
  999. {
  1000.    //renderer.SetShaderConstantMat4F("unMPrj", matPrj, false );
  1001.  
  1002.    var num = this.mChunks.length;
  1003.    for( var i=0; i<num; i++ )
  1004.    {
  1005.        //var mat =  matMul( matCam, this.mChunks[i].mTransform );
  1006.        //renderer.SetShaderConstantMat4F("unMMod", mat, false);
  1007.  
  1008.        renderer.AttachVertexArray(this.mChunks[i].mVBO, this.mVertexFormat, positions );
  1009.        renderer.AttachIndexArray(this.mChunks[i].mIBO );
  1010.        renderer.DrawPrimitive(renderer.PRIMTYPE.TRIANGLES, this.mChunks[i].mNumFaces * 3, true, 1);
  1011.        renderer.DetachIndexArray(this.mChunks[i].mIBO);
  1012.        renderer.DetachVertexArray(this.mChunks[i].mVBO, this.mVertexFormat );
  1013.    }
  1014. }
  1015. //==============================================================================
  1016. //
  1017. // piLibs 2014-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  1018. //
  1019. // piRenderer
  1020. //
  1021. //==============================================================================
  1022.  
  1023. function piRenderer()
  1024. {
  1025.    // private members
  1026.  
  1027.    var mGL = null;
  1028.    var mBindedShader = null;
  1029.    var mIs20 = false;
  1030.    var mFloat32Textures;
  1031.    var mFloat32Filter;
  1032.    var mFloat16Textures;
  1033.    var mDrawBuffers;
  1034.    var mDepthTextures;
  1035.    var mDerivatives;
  1036.    var mFloat16Filter;
  1037.    var mShaderTextureLOD;
  1038.    var mAnisotropic;
  1039.    var mRenderToFloat32F;
  1040.    var mDebugShader;
  1041.    var mAsynchCompile;
  1042.  
  1043.    var mVBO_Quad = null;
  1044.    var mVBO_Tri = null;
  1045.    var mVBO_CubePosNor = null;
  1046.    var mVBO_CubePos = null;
  1047.    var mShaderHeader = ["",""];
  1048.    var mShaderHeaderLines = [0,0];
  1049.  
  1050.    // public members
  1051.    var me = {};
  1052.  
  1053.    me.CLEAR      = { Color: 1, Zbuffer : 2, Stencil : 4 };
  1054.    me.TEXFMT     = { C4I8 : 0, C1I8 : 1, C1F16 : 2, C4F16 : 3, C1F32 : 4, C4F32 : 5, Z16 : 6, Z24 : 7, Z32 : 8, C3F32:9 };
  1055.    me.TEXWRP     = { CLAMP : 0, REPEAT : 1 };
  1056.    me.BUFTYPE    = { STATIC : 0, DYNAMIC : 1 };
  1057.    me.PRIMTYPE   = { POINTS : 0, LINES : 1, LINE_LOOP : 2, LINE_STRIP : 3, TRIANGLES : 4, TRIANGLE_STRIP : 5 };
  1058.    me.RENDSTGATE = { WIREFRAME : 0, FRONT_FACE : 1, CULL_FACE : 2, DEPTH_TEST : 3, ALPHA_TO_COVERAGE : 4 };
  1059.    me.TEXTYPE    = { T2D : 0, T3D : 1, CUBEMAP : 2 };
  1060.    me.FILTER     = { NONE : 0, LINEAR : 1, MIPMAP : 2, NONE_MIPMAP : 3 };
  1061.    me.TYPE       = { UINT8 : 0, UINT16 : 1, UINT32 : 2, FLOAT16: 3, FLOAT32 : 4, FLOAT64: 5 };
  1062.  
  1063.    // private functions
  1064.  
  1065.    var iFormatPI2GL = function( format )
  1066.    {
  1067.        if( mIs20 )
  1068.        {
  1069.             if (format === me.TEXFMT.C4I8)  return { mGLFormat: mGL.RGBA8,           mGLExternal: mGL.RGBA,             mGLType: mGL.UNSIGNED_BYTE }
  1070.        else if (format === me.TEXFMT.C1I8)  return { mGLFormat: mGL.R8,              mGLExternal: mGL.RED,              mGLType: mGL.UNSIGNED_BYTE }
  1071.        else if (format === me.TEXFMT.C1F16) return { mGLFormat: mGL.R16F,            mGLExternal: mGL.RED,              mGLType: mGL.FLOAT }
  1072.        else if (format === me.TEXFMT.C4F16) return { mGLFormat: mGL.RGBA16F,         mGLExternal: mGL.RGBA,             mGLType: mGL.FLOAT }
  1073.        else if (format === me.TEXFMT.C1F32) return { mGLFormat: mGL.R32F,            mGLExternal: mGL.RED,              mGLType: mGL.FLOAT }
  1074.        else if (format === me.TEXFMT.C4F32) return { mGLFormat: mGL.RGBA32F,         mGLExternal: mGL.RGBA,             mGLType: mGL.FLOAT }
  1075.        else if (format === me.TEXFMT.C3F32) return { mGLFormat: mGL.RGB32F,          mGLExternal: mGL.RGB,              mGLType: mGL.FLOAT }
  1076.        else if (format === me.TEXFMT.Z16)   return { mGLFormat: mGL.DEPTH_COMPONENT16, mGLExternal: mGL.DEPTH_COMPONENT,  mGLType: mGL.UNSIGNED_SHORT }
  1077.        else if (format === me.TEXFMT.Z24)   return { mGLFormat: mGL.DEPTH_COMPONENT24, mGLExternal: mGL.DEPTH_COMPONENT,  mGLType: mGL.UNSIGNED_SHORT }
  1078.        else if (format === me.TEXFMT.Z32)   return { mGLFormat: mGL.DEPTH_COMPONENT32F, mGLExternal: mGL.DEPTH_COMPONENT,  mGLType: mGL.UNSIGNED_SHORT }
  1079.        }
  1080.        else
  1081.        {
  1082.             if (format === me.TEXFMT.C4I8)  return { mGLFormat: mGL.RGBA,            mGLExternal: mGL.RGBA,            mGLType: mGL.UNSIGNED_BYTE }
  1083.        else if (format === me.TEXFMT.C1I8)  return { mGLFormat: mGL.LUMINANCE,       mGLExternal: mGL.LUMINANCE,       mGLType: mGL.UNSIGNED_BYTE }
  1084.        else if (format === me.TEXFMT.C1F16) return { mGLFormat: mGL.LUMINANCE,       mGLExternal: mGL.LUMINANCE,       mGLType: mGL.FLOAT }
  1085.        else if (format === me.TEXFMT.C4F16) return { mGLFormat: mGL.RGBA,            mGLExternal: mGL.RGBA,            mGLType: mGL.FLOAT }
  1086.        else if (format === me.TEXFMT.C1F32) return { mGLFormat: mGL.LUMINANCE,       mGLExternal: mGL.RED,             mGLType: mGL.FLOAT }
  1087.        else if (format === me.TEXFMT.C4F32) return { mGLFormat: mGL.RGBA,            mGLExternal: mGL.RGBA,            mGLType: mGL.FLOAT }
  1088.        else if (format === me.TEXFMT.Z16)   return { mGLFormat: mGL.DEPTH_COMPONENT, mGLExternal: mGL.DEPTH_COMPONENT, mGLType: mGL.UNSIGNED_SHORT }
  1089.        }
  1090.  
  1091.        return null;
  1092.     }
  1093.  
  1094.    // public functions
  1095.  
  1096.    me.Initialize = function( gl )
  1097.                    {
  1098.                        mGL = gl;
  1099.  
  1100.                        mIs20 = !(gl instanceof WebGLRenderingContext);
  1101.  
  1102.                        if( mIs20 )
  1103.                        {
  1104.                            mFloat32Textures  = true;
  1105.                            mFloat32Filter    = mGL.getExtension( 'OES_texture_float_linear');
  1106.                            mFloat16Textures  = true;
  1107.                            mFloat16Filter    = mGL.getExtension( 'OES_texture_half_float_linear' );
  1108.                            mDerivatives      = true;
  1109.                            mDrawBuffers      = true;
  1110.                            mDepthTextures    = true;
  1111.                            mShaderTextureLOD = true;
  1112.                            mAnisotropic = mGL.getExtension( 'EXT_texture_filter_anisotropic' );
  1113.                            mRenderToFloat32F = mGL.getExtension( 'EXT_color_buffer_float');
  1114.                            mDebugShader = mGL.getExtension('WEBGL_debug_shaders');
  1115.                            mAsynchCompile = mGL.getExtension('KHR_parallel_shader_compile');
  1116.  
  1117. mGL.hint( mGL.FRAGMENT_SHADER_DERIVATIVE_HINT, mGL.NICEST);
  1118.                        }
  1119.                        else
  1120.                        {
  1121.                            mFloat32Textures  = mGL.getExtension( 'OES_texture_float' );
  1122.                            mFloat32Filter    = mGL.getExtension( 'OES_texture_float_linear');
  1123.                            mFloat16Textures  = mGL.getExtension( 'OES_texture_half_float' );
  1124.                            mFloat16Filter    = mGL.getExtension( 'OES_texture_half_float_linear' );
  1125.                            mDerivatives      = mGL.getExtension( 'OES_standard_derivatives' );
  1126.                            mDrawBuffers      = mGL.getExtension( 'WEBGL_draw_buffers' );
  1127.                            mDepthTextures    = mGL.getExtension( 'WEBGL_depth_texture' );
  1128.                            mShaderTextureLOD = mGL.getExtension( 'EXT_shader_texture_lod' );
  1129.                            mAnisotropic      = mGL.getExtension( 'EXT_texture_filter_anisotropic' );
  1130.                            mRenderToFloat32F = mFloat32Textures;
  1131.                            mDebugShader      = null;
  1132.                            mAsynchCompile    = null;
  1133. if( mDerivatives !== null) mGL.hint( mDerivatives.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, mGL.NICEST);
  1134.                        }
  1135.                        
  1136.                        
  1137.                        var maxTexSize = mGL.getParameter( mGL.MAX_TEXTURE_SIZE );
  1138.                        var maxCubeSize = mGL.getParameter( mGL.MAX_CUBE_MAP_TEXTURE_SIZE );
  1139.                        var maxRenderbufferSize = mGL.getParameter( mGL.MAX_RENDERBUFFER_SIZE );
  1140.                        var extensions = mGL.getSupportedExtensions();
  1141.                        var textureUnits = mGL.getParameter( mGL.MAX_TEXTURE_IMAGE_UNITS );
  1142.                        console.log("WebGL (2.0=" + mIs20 + "):" +
  1143.                                    " Asynch Compile: "  + ((mAsynchCompile !==null) ? "yes" : "no") +
  1144.                                    ", Textures: F32 ["   + ((mFloat32Textures !==null) ? "yes" : "no") +
  1145.                                    "], F16 ["   + ((mFloat16Textures !==null) ? "yes" : "no") +
  1146.                                    "], Depth [" + ((mDepthTextures   !==null) ? "yes" : "no") +
  1147.                                    "], LOD ["    + ((mShaderTextureLOD!==null) ? "yes" : "no") +
  1148.                                    "], Aniso ["   + ((mAnisotropic     !==null) ? "yes" : "no") +
  1149.                                    "], Units [" + textureUnits +
  1150.                                    "], Max Size [" + maxTexSize +
  1151.                                    "], Cube Max Size [" + maxCubeSize +
  1152.                                    "], Targets: MRT ["            + ((mDrawBuffers     !==null) ? "yes" : "no") +
  1153.                                    "], F32 ["     + ((mRenderToFloat32F!==null) ? "yes" : "no") +
  1154.                                    "], Max Size [" + maxRenderbufferSize + "]");
  1155.  
  1156.                        // create a 2D quad Vertex Buffer
  1157.                        var vertices = new Float32Array( [ -1.0, -1.0,   1.0, -1.0,    -1.0,  1.0,     1.0, -1.0,    1.0,  1.0,    -1.0,  1.0] );
  1158.                        mVBO_Quad = mGL.createBuffer();
  1159.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Quad );
  1160.                        mGL.bufferData( mGL.ARRAY_BUFFER, vertices, mGL.STATIC_DRAW );
  1161.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  1162.  
  1163.                        // create a 2D triangle Vertex Buffer
  1164.                        mVBO_Tri = mGL.createBuffer();
  1165.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Tri );
  1166.                        mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0,   3.0, -1.0,    -1.0,  3.0] ), mGL.STATIC_DRAW );
  1167.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  1168.  
  1169.                        // create a 3D cube Vertex Buffer
  1170.                        mVBO_CubePosNor = mGL.createBuffer();
  1171.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePosNor );
  1172.                        mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, -1.0,  -1.0,  0.0,  0.0,
  1173.                                                                              -1.0, -1.0,  1.0,  -1.0,  0.0,  0.0,
  1174.                                                                              -1.0,  1.0, -1.0,  -1.0,  0.0,  0.0,
  1175.                                                                              -1.0,  1.0,  1.0,  -1.0,  0.0,  0.0,
  1176.                                                                               1.0,  1.0, -1.0,   1.0,  0.0,  0.0,
  1177.                                                                               1.0,  1.0,  1.0,   1.0,  0.0,  0.0,
  1178.                                                                               1.0, -1.0, -1.0,   1.0,  0.0,  0.0,
  1179.                                                                               1.0, -1.0,  1.0,   1.0,  0.0,  0.0,
  1180.                                                                               1.0,  1.0,  1.0,   0.0,  1.0,  0.0,
  1181.                                                                               1.0,  1.0, -1.0,   0.0,  1.0,  0.0,
  1182.                                                                              -1.0,  1.0,  1.0,   0.0,  1.0,  0.0,
  1183.                                                                              -1.0,  1.0, -1.0,   0.0,  1.0,  0.0,
  1184.                                                                               1.0, -1.0, -1.0,   0.0, -1.0,  0.0,
  1185.                                                                               1.0, -1.0,  1.0,   0.0, -1.0,  0.0,
  1186.                                                                              -1.0, -1.0, -1.0,   0.0, -1.0,  0.0,
  1187.                                                                              -1.0, -1.0,  1.0,   0.0, -1.0,  0.0,
  1188.                                                                              -1.0,  1.0,  1.0,   0.0,  0.0,  1.0,
  1189.                                                                              -1.0, -1.0,  1.0,   0.0,  0.0,  1.0,
  1190.                                                                               1.0,  1.0,  1.0,   0.0,  0.0,  1.0,
  1191.                                                                               1.0, -1.0,  1.0,   0.0,  0.0,  1.0,
  1192.                                                                              -1.0, -1.0, -1.0,   0.0,  0.0, -1.0,
  1193.                                                                              -1.0,  1.0, -1.0,   0.0,  0.0, -1.0,
  1194.                                                                               1.0, -1.0, -1.0,   0.0,  0.0, -1.0,
  1195.                                                                               1.0,  1.0, -1.0,   0.0,  0.0, -1.0 ] ), mGL.STATIC_DRAW );
  1196.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  1197.  
  1198.                        // create a 3D cube Vertex Buffer
  1199.                        mVBO_CubePos = mGL.createBuffer();
  1200.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePos );
  1201.                        mGL.bufferData( mGL.ARRAY_BUFFER, new Float32Array( [ -1.0, -1.0, -1.0,
  1202.                                                                              -1.0, -1.0,  1.0,
  1203.                                                                              -1.0,  1.0, -1.0,
  1204.                                                                              -1.0,  1.0,  1.0,
  1205.                                                                               1.0,  1.0, -1.0,
  1206.                                                                               1.0,  1.0,  1.0,
  1207.                                                                               1.0, -1.0, -1.0,
  1208.                                                                               1.0, -1.0,  1.0,
  1209.                                                                               1.0,  1.0,  1.0,
  1210.                                                                               1.0,  1.0, -1.0,
  1211.                                                                              -1.0,  1.0,  1.0,
  1212.                                                                              -1.0,  1.0, -1.0,
  1213.                                                                               1.0, -1.0, -1.0,
  1214.                                                                               1.0, -1.0,  1.0,
  1215.                                                                              -1.0, -1.0, -1.0,
  1216.                                                                              -1.0, -1.0,  1.0,
  1217.                                                                              -1.0,  1.0,  1.0,
  1218.                                                                              -1.0, -1.0,  1.0,
  1219.                                                                               1.0,  1.0,  1.0,
  1220.                                                                               1.0, -1.0,  1.0,
  1221.                                                                              -1.0, -1.0, -1.0,
  1222.                                                                              -1.0,  1.0, -1.0,
  1223.                                                                               1.0, -1.0, -1.0,
  1224.                                                                               1.0,  1.0, -1.0 ] ), mGL.STATIC_DRAW );
  1225.                        mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  1226.  
  1227.                        //-------------------------------------------------------------------
  1228.  
  1229.                        mShaderHeader[0] = "";
  1230.                        mShaderHeaderLines[0] = 0;
  1231.                        if( mIs20 )
  1232.                        {
  1233.                            mShaderHeader[0] += "#version 300 es\n" +
  1234.                                                "#ifdef GL_ES\n"+
  1235.                                                "precision highp float;\n" +
  1236.                                                "precision highp int;\n"+
  1237.                                                "precision mediump sampler3D;\n"+
  1238.                                                "#endif\n";
  1239.                            mShaderHeaderLines[0] += 6;
  1240.                        }
  1241.                        else
  1242.                        {
  1243.                            mShaderHeader[0] += "#ifdef GL_ES\n"+
  1244.                                                "precision highp float;\n" +
  1245.                                                "precision highp int;\n"+
  1246.                                                "#endif\n"+
  1247.                                                "float round( float x ) { return floor(x+0.5); }\n"+
  1248.                                                "vec2 round(vec2 x) { return floor(x + 0.5); }\n"+
  1249.                                                "vec3 round(vec3 x) { return floor(x + 0.5); }\n"+
  1250.                                                "vec4 round(vec4 x) { return floor(x + 0.5); }\n"+
  1251.                                                "float trunc( float x, float n ) { return floor(x*n)/n; }\n"+
  1252.                                                "mat3 transpose(mat3 m) { return mat3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); }\n"+
  1253.                                                "float determinant( in mat2 m ) { return m[0][0]*m[1][1] - m[0][1]*m[1][0]; }\n"+
  1254.                                                "float determinant( mat4 m ) { float b00 = m[0][0] * m[1][1] - m[0][1] * m[1][0], b01 = m[0][0] * m[1][2] - m[0][2] * m[1][0], b02 = m[0][0] * m[1][3] - m[0][3] * m[1][0], b03 = m[0][1] * m[1][2] - m[0][2] * m[1][1], b04 = m[0][1] * m[1][3] - m[0][3] * m[1][1], b05 = m[0][2] * m[1][3] - m[0][3] * m[1][2], b06 = m[2][0] * m[3][1] - m[2][1] * m[3][0], b07 = m[2][0] * m[3][2] - m[2][2] * m[3][0], b08 = m[2][0] * m[3][3] - m[2][3] * m[3][0], b09 = m[2][1] * m[3][2] - m[2][2] * m[3][1], b10 = m[2][1] * m[3][3] - m[2][3] * m[3][1], b11 = m[2][2] * m[3][3] - m[2][3] * m[3][2];  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;}\n"+
  1255.                                                "mat2 inverse(mat2 m) { float det = determinant(m); return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / det; }\n"+
  1256.                                                "mat4 inverse(mat4 m ) { float inv0 = m[1].y*m[2].z*m[3].w - m[1].y*m[2].w*m[3].z - m[2].y*m[1].z*m[3].w + m[2].y*m[1].w*m[3].z + m[3].y*m[1].z*m[2].w - m[3].y*m[1].w*m[2].z; float inv4 = -m[1].x*m[2].z*m[3].w + m[1].x*m[2].w*m[3].z + m[2].x*m[1].z*m[3].w - m[2].x*m[1].w*m[3].z - m[3].x*m[1].z*m[2].w + m[3].x*m[1].w*m[2].z; float inv8 = m[1].x*m[2].y*m[3].w - m[1].x*m[2].w*m[3].y - m[2].x  * m[1].y * m[3].w + m[2].x  * m[1].w * m[3].y + m[3].x * m[1].y * m[2].w - m[3].x * m[1].w * m[2].y; float inv12 = -m[1].x  * m[2].y * m[3].z + m[1].x  * m[2].z * m[3].y +m[2].x  * m[1].y * m[3].z - m[2].x  * m[1].z * m[3].y - m[3].x * m[1].y * m[2].z + m[3].x * m[1].z * m[2].y; float inv1 = -m[0].y*m[2].z * m[3].w + m[0].y*m[2].w * m[3].z + m[2].y  * m[0].z * m[3].w - m[2].y  * m[0].w * m[3].z - m[3].y * m[0].z * m[2].w + m[3].y * m[0].w * m[2].z; float inv5 = m[0].x  * m[2].z * m[3].w - m[0].x  * m[2].w * m[3].z - m[2].x  * m[0].z * m[3].w + m[2].x  * m[0].w * m[3].z + m[3].x * m[0].z * m[2].w - m[3].x * m[0].w * m[2].z; float inv9 = -m[0].x  * m[2].y * m[3].w +  m[0].x  * m[2].w * m[3].y + m[2].x  * m[0].y * m[3].w - m[2].x  * m[0].w * m[3].y - m[3].x * m[0].y * m[2].w + m[3].x * m[0].w * m[2].y; float inv13 = m[0].x  * m[2].y * m[3].z - m[0].x  * m[2].z * m[3].y - m[2].x  * m[0].y * m[3].z + m[2].x  * m[0].z * m[3].y + m[3].x * m[0].y * m[2].z - m[3].x * m[0].z * m[2].y; float inv2 = m[0].y  * m[1].z * m[3].w - m[0].y  * m[1].w * m[3].z - m[1].y  * m[0].z * m[3].w + m[1].y  * m[0].w * m[3].z + m[3].y * m[0].z * m[1].w - m[3].y * m[0].w * m[1].z; float inv6 = -m[0].x  * m[1].z * m[3].w + m[0].x  * m[1].w * m[3].z + m[1].x  * m[0].z * m[3].w - m[1].x  * m[0].w * m[3].z - m[3].x * m[0].z * m[1].w + m[3].x * m[0].w * m[1].z; float inv10 = m[0].x  * m[1].y * m[3].w - m[0].x  * m[1].w * m[3].y - m[1].x  * m[0].y * m[3].w + m[1].x  * m[0].w * m[3].y + m[3].x * m[0].y * m[1].w - m[3].x * m[0].w * m[1].y; float inv14 = -m[0].x  * m[1].y * m[3].z + m[0].x  * m[1].z * m[3].y + m[1].x  * m[0].y * m[3].z - m[1].x  * m[0].z * m[3].y - m[3].x * m[0].y * m[1].z + m[3].x * m[0].z * m[1].y; float inv3 = -m[0].y * m[1].z * m[2].w + m[0].y * m[1].w * m[2].z + m[1].y * m[0].z * m[2].w - m[1].y * m[0].w * m[2].z - m[2].y * m[0].z * m[1].w + m[2].y * m[0].w * m[1].z; float inv7 = m[0].x * m[1].z * m[2].w - m[0].x * m[1].w * m[2].z - m[1].x * m[0].z * m[2].w + m[1].x * m[0].w * m[2].z + m[2].x * m[0].z * m[1].w - m[2].x * m[0].w * m[1].z; float inv11 = -m[0].x * m[1].y * m[2].w + m[0].x * m[1].w * m[2].y + m[1].x * m[0].y * m[2].w - m[1].x * m[0].w * m[2].y - m[2].x * m[0].y * m[1].w + m[2].x * m[0].w * m[1].y; float inv15 = m[0].x * m[1].y * m[2].z - m[0].x * m[1].z * m[2].y - m[1].x * m[0].y * m[2].z + m[1].x * m[0].z * m[2].y + m[2].x * m[0].y * m[1].z - m[2].x * m[0].z * m[1].y; float det = m[0].x * inv0 + m[0].y * inv4 + m[0].z * inv8 + m[0].w * inv12; det = 1.0 / det; return det*mat4( inv0, inv1, inv2, inv3,inv4, inv5, inv6, inv7,inv8, inv9, inv10, inv11,inv12, inv13, inv14, inv15);}\n"+                                                
  1257.                                                "float sinh(float x)  { return (exp(x)-exp(-x))/2.; }\n"+
  1258.                                                "float cosh(float x)  { return (exp(x)+exp(-x))/2.; }\n"+
  1259.                                                "float tanh(float x)  { return sinh(x)/cosh(x); }\n"+
  1260.                                                "float coth(float x)  { return cosh(x)/sinh(x); }\n"+
  1261.                                                "float sech(float x)  { return 1./cosh(x); }\n"+
  1262.                                                "float csch(float x)  { return 1./sinh(x); }\n"+
  1263.                                                "float asinh(float x) { return    log(x+sqrt(x*x+1.)); }\n"+
  1264.                                                "float acosh(float x) { return    log(x+sqrt(x*x-1.)); }\n"+
  1265.                                                "float atanh(float x) { return .5*log((1.+x)/(1.-x)); }\n"+
  1266.                                                "float acoth(float x) { return .5*log((x+1.)/(x-1.)); }\n"+
  1267.                                                "float asech(float x) { return    log((1.+sqrt(1.-x*x))/x); }\n"+
  1268.                                                "float acsch(float x) { return    log((1.+sqrt(1.+x*x))/x); }\n";
  1269.                            mShaderHeaderLines[0] += 26;
  1270.                        }
  1271.  
  1272.                        //-------------------------------------------------------
  1273.  
  1274.                        mShaderHeader[1] = "";
  1275.                        mShaderHeaderLines[1] = 0;
  1276.                        if( mIs20 )
  1277.                        {
  1278.                            mShaderHeader[1] += "#version 300 es\n"+
  1279.                                                "#ifdef GL_ES\n"+
  1280.                                                "precision highp float;\n"+
  1281.                                                "precision highp int;\n"+
  1282.                                                "precision mediump sampler3D;\n"+
  1283.                                                "#endif\n";
  1284.                            mShaderHeaderLines[1] += 6;
  1285.                        }
  1286.                        else
  1287.                        {
  1288.                            if( mDerivatives ) { mShaderHeader[1] += "#ifdef GL_OES_standard_derivatives\n#extension GL_OES_standard_derivatives : enable\n#endif\n"; mShaderHeaderLines[1]+=3; }
  1289.                            if( mShaderTextureLOD  ) { mShaderHeader[1] += "#extension GL_EXT_shader_texture_lod : enable\n"; mShaderHeaderLines[1]++; }
  1290.                            mShaderHeader[1] += "#ifdef GL_ES\n"+
  1291.                                                "precision highp float;\n"+
  1292.                                                "precision highp int;\n"+
  1293.                                                "#endif\n"+
  1294.                                                "vec4 texture(     sampler2D   s, vec2 c)                   { return texture2D(s,c); }\n"+
  1295.                                                "vec4 texture(     sampler2D   s, vec2 c, float b)          { return texture2D(s,c,b); }\n"+
  1296.                                                "vec4 texture(     samplerCube s, vec3 c )                  { return textureCube(s,c); }\n"+
  1297.                                                "vec4 texture(     samplerCube s, vec3 c, float b)          { return textureCube(s,c,b); }\n"+
  1298.                                                "float round( float x ) { return floor(x+0.5); }\n"+
  1299.                                                "vec2 round(vec2 x) { return floor(x + 0.5); }\n"+
  1300.                                                "vec3 round(vec3 x) { return floor(x + 0.5); }\n"+
  1301.                                                "vec4 round(vec4 x) { return floor(x + 0.5); }\n"+
  1302.                                                "float trunc( float x, float n ) { return floor(x*n)/n; }\n"+
  1303.                                                "mat3 transpose(mat3 m) { return mat3(m[0].x, m[1].x, m[2].x, m[0].y, m[1].y, m[2].y, m[0].z, m[1].z, m[2].z); }\n"+
  1304.                                                "float determinant( in mat2 m ) { return m[0][0]*m[1][1] - m[0][1]*m[1][0]; }\n"+
  1305.                                                "float determinant( mat4 m ) { float b00 = m[0][0] * m[1][1] - m[0][1] * m[1][0], b01 = m[0][0] * m[1][2] - m[0][2] * m[1][0], b02 = m[0][0] * m[1][3] - m[0][3] * m[1][0], b03 = m[0][1] * m[1][2] - m[0][2] * m[1][1], b04 = m[0][1] * m[1][3] - m[0][3] * m[1][1], b05 = m[0][2] * m[1][3] - m[0][3] * m[1][2], b06 = m[2][0] * m[3][1] - m[2][1] * m[3][0], b07 = m[2][0] * m[3][2] - m[2][2] * m[3][0], b08 = m[2][0] * m[3][3] - m[2][3] * m[3][0], b09 = m[2][1] * m[3][2] - m[2][2] * m[3][1], b10 = m[2][1] * m[3][3] - m[2][3] * m[3][1], b11 = m[2][2] * m[3][3] - m[2][3] * m[3][2];  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;}\n"+
  1306.                                                "mat2 inverse(mat2 m) { float det = determinant(m); return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / det; }\n"+
  1307.                                                "mat4 inverse(mat4 m ) { float inv0 = m[1].y*m[2].z*m[3].w - m[1].y*m[2].w*m[3].z - m[2].y*m[1].z*m[3].w + m[2].y*m[1].w*m[3].z + m[3].y*m[1].z*m[2].w - m[3].y*m[1].w*m[2].z; float inv4 = -m[1].x*m[2].z*m[3].w + m[1].x*m[2].w*m[3].z + m[2].x*m[1].z*m[3].w - m[2].x*m[1].w*m[3].z - m[3].x*m[1].z*m[2].w + m[3].x*m[1].w*m[2].z; float inv8 = m[1].x*m[2].y*m[3].w - m[1].x*m[2].w*m[3].y - m[2].x  * m[1].y * m[3].w + m[2].x  * m[1].w * m[3].y + m[3].x * m[1].y * m[2].w - m[3].x * m[1].w * m[2].y; float inv12 = -m[1].x  * m[2].y * m[3].z + m[1].x  * m[2].z * m[3].y +m[2].x  * m[1].y * m[3].z - m[2].x  * m[1].z * m[3].y - m[3].x * m[1].y * m[2].z + m[3].x * m[1].z * m[2].y; float inv1 = -m[0].y*m[2].z * m[3].w + m[0].y*m[2].w * m[3].z + m[2].y  * m[0].z * m[3].w - m[2].y  * m[0].w * m[3].z - m[3].y * m[0].z * m[2].w + m[3].y * m[0].w * m[2].z; float inv5 = m[0].x  * m[2].z * m[3].w - m[0].x  * m[2].w * m[3].z - m[2].x  * m[0].z * m[3].w + m[2].x  * m[0].w * m[3].z + m[3].x * m[0].z * m[2].w - m[3].x * m[0].w * m[2].z; float inv9 = -m[0].x  * m[2].y * m[3].w +  m[0].x  * m[2].w * m[3].y + m[2].x  * m[0].y * m[3].w - m[2].x  * m[0].w * m[3].y - m[3].x * m[0].y * m[2].w + m[3].x * m[0].w * m[2].y; float inv13 = m[0].x  * m[2].y * m[3].z - m[0].x  * m[2].z * m[3].y - m[2].x  * m[0].y * m[3].z + m[2].x  * m[0].z * m[3].y + m[3].x * m[0].y * m[2].z - m[3].x * m[0].z * m[2].y; float inv2 = m[0].y  * m[1].z * m[3].w - m[0].y  * m[1].w * m[3].z - m[1].y  * m[0].z * m[3].w + m[1].y  * m[0].w * m[3].z + m[3].y * m[0].z * m[1].w - m[3].y * m[0].w * m[1].z; float inv6 = -m[0].x  * m[1].z * m[3].w + m[0].x  * m[1].w * m[3].z + m[1].x  * m[0].z * m[3].w - m[1].x  * m[0].w * m[3].z - m[3].x * m[0].z * m[1].w + m[3].x * m[0].w * m[1].z; float inv10 = m[0].x  * m[1].y * m[3].w - m[0].x  * m[1].w * m[3].y - m[1].x  * m[0].y * m[3].w + m[1].x  * m[0].w * m[3].y + m[3].x * m[0].y * m[1].w - m[3].x * m[0].w * m[1].y; float inv14 = -m[0].x  * m[1].y * m[3].z + m[0].x  * m[1].z * m[3].y + m[1].x  * m[0].y * m[3].z - m[1].x  * m[0].z * m[3].y - m[3].x * m[0].y * m[1].z + m[3].x * m[0].z * m[1].y; float inv3 = -m[0].y * m[1].z * m[2].w + m[0].y * m[1].w * m[2].z + m[1].y * m[0].z * m[2].w - m[1].y * m[0].w * m[2].z - m[2].y * m[0].z * m[1].w + m[2].y * m[0].w * m[1].z; float inv7 = m[0].x * m[1].z * m[2].w - m[0].x * m[1].w * m[2].z - m[1].x * m[0].z * m[2].w + m[1].x * m[0].w * m[2].z + m[2].x * m[0].z * m[1].w - m[2].x * m[0].w * m[1].z; float inv11 = -m[0].x * m[1].y * m[2].w + m[0].x * m[1].w * m[2].y + m[1].x * m[0].y * m[2].w - m[1].x * m[0].w * m[2].y - m[2].x * m[0].y * m[1].w + m[2].x * m[0].w * m[1].y; float inv15 = m[0].x * m[1].y * m[2].z - m[0].x * m[1].z * m[2].y - m[1].x * m[0].y * m[2].z + m[1].x * m[0].z * m[2].y + m[2].x * m[0].y * m[1].z - m[2].x * m[0].z * m[1].y; float det = m[0].x * inv0 + m[0].y * inv4 + m[0].z * inv8 + m[0].w * inv12; det = 1.0 / det; return det*mat4( inv0, inv1, inv2, inv3,inv4, inv5, inv6, inv7,inv8, inv9, inv10, inv11,inv12, inv13, inv14, inv15);}\n"+
  1308.                                                "float sinh(float x)  { return (exp(x)-exp(-x))/2.; }\n"+
  1309.                                                "float cosh(float x)  { return (exp(x)+exp(-x))/2.; }\n"+
  1310.                                                "float tanh(float x)  { return sinh(x)/cosh(x); }\n"+
  1311.                                                "float coth(float x)  { return cosh(x)/sinh(x); }\n"+
  1312.                                                "float sech(float x)  { return 1./cosh(x); }\n"+
  1313.                                                "float csch(float x)  { return 1./sinh(x); }\n"+
  1314.                                                "float asinh(float x) { return    log(x+sqrt(x*x+1.)); }\n"+
  1315.                                                "float acosh(float x) { return    log(x+sqrt(x*x-1.)); }\n"+
  1316.                                                "float atanh(float x) { return .5*log((1.+x)/(1.-x)); }\n"+
  1317.                                                "float acoth(float x) { return .5*log((x+1.)/(x-1.)); }\n"+
  1318.                                                "float asech(float x) { return    log((1.+sqrt(1.-x*x))/x); }\n"+
  1319.                                                "float acsch(float x) { return    log((1.+sqrt(1.+x*x))/x); }\n";
  1320.                            mShaderHeaderLines[1] += 30;
  1321.                            if( mShaderTextureLOD )
  1322.                            {
  1323.                            mShaderHeader[1] += "vec4 textureLod(  sampler2D   s, vec2 c, float b)          { return texture2DLodEXT(s,c,b); }\n";
  1324.                            mShaderHeader[1] += "vec4 textureGrad( sampler2D   s, vec2 c, vec2 dx, vec2 dy) { return texture2DGradEXT(s,c,dx,dy); }\n";
  1325.                            mShaderHeaderLines[1] += 2;
  1326.  
  1327.                            //mShaderHeader[1] += "vec4 texelFetch( sampler2D s, ivec2 c, int l) { return texture2DLodEXT(s,(vec2(c)+0.5)/vec2(800,450),float(l)); }\n";
  1328.                            //mShaderHeaderLines[1] += 1;
  1329.                            }
  1330.                        }
  1331.  
  1332.                        return true;
  1333.                    };
  1334.  
  1335.        me.GetCaps =    function ()
  1336.                        {  
  1337.                            return { mIsGL20 : mIs20,
  1338.                                     mFloat32Textures: mFloat32Textures != null,
  1339.                                     mFloat16Textures: mFloat16Textures != null,
  1340.                                     mDrawBuffers: mDrawBuffers != null,
  1341.                                     mDepthTextures: mDepthTextures != null,
  1342.                                     mDerivatives: mDerivatives != null,
  1343.                                     mShaderTextureLOD: mShaderTextureLOD != null };
  1344.                        };
  1345.  
  1346.        me.GetShaderHeaderLines = function (shaderType)
  1347.                        {  
  1348.                            return mShaderHeaderLines[shaderType];
  1349.                        };
  1350.  
  1351.        me.CheckErrors = function()
  1352.                         {
  1353.                                var error = mGL.getError();
  1354.                                if( error != mGL.NO_ERROR )
  1355.                                {
  1356.                                    for( var prop in mGL )
  1357.                                    {
  1358.                                        if( typeof mGL[prop] == 'number' )
  1359.                                        {
  1360.                                            if( mGL[prop] == error )
  1361.                                            {
  1362.                                                console.log( "GL Error " + error + ": " + prop );
  1363.                                                break;
  1364.                                            }
  1365.                                        }
  1366.                                    }
  1367.                                }
  1368.                         };
  1369.  
  1370.        me.Clear =  function( flags, ccolor, cdepth, cstencil )
  1371.                    {
  1372.                        var mode = 0;
  1373.                        if( flags & 1 ) { mode |= mGL.COLOR_BUFFER_BIT;   mGL.clearColor( ccolor[0], ccolor[1], ccolor[2], ccolor[3] ); }
  1374.                        if( flags & 2 ) { mode |= mGL.DEPTH_BUFFER_BIT;   mGL.clearDepth( cdepth ); }
  1375.                        if( flags & 4 ) { mode |= mGL.STENCIL_BUFFER_BIT; mGL.clearStencil( cstencil ); }
  1376.                        mGL.clear( mode );
  1377.                    };
  1378.  
  1379.  
  1380.        me.CreateTexture = function ( type, xres, yres, format, filter, wrap, buffer)
  1381.                           {
  1382.                                if( mGL===null ) return null;
  1383.  
  1384.                                var id = mGL.createTexture();
  1385.  
  1386.                                var glFoTy = iFormatPI2GL( format );
  1387.                                var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
  1388.  
  1389.                                if( type===me.TEXTYPE.T2D )
  1390.                                {
  1391.                                    mGL.bindTexture( mGL.TEXTURE_2D, id );
  1392. //if( buffer==null )
  1393.    //mGL.texStorage2D(mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, xres, yres);
  1394. //else
  1395.                                    mGL.texImage2D( mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1396.                                    mGL.texParameteri( mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap );
  1397.                                    mGL.texParameteri( mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap );
  1398.  
  1399.                                    if (filter === me.FILTER.NONE)
  1400.                                    {
  1401.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1402.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1403.                                    }
  1404.                                    else if (filter === me.FILTER.LINEAR)
  1405.                                    {
  1406.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1407.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
  1408.                                    }
  1409.                                    else if (filter === me.FILTER.MIPMAP)
  1410.                                    {
  1411.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1412.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1413.                                        mGL.generateMipmap(mGL.TEXTURE_2D);
  1414.                                    }
  1415.                                    else
  1416.                                    {
  1417.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1418.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
  1419.                                        mGL.generateMipmap(mGL.TEXTURE_2D);
  1420.                                    }
  1421.  
  1422.                                    mGL.bindTexture( mGL.TEXTURE_2D, null );
  1423.                                }
  1424.                                else if( type===me.TEXTYPE.T3D )
  1425.                                {
  1426.                                    if( mIs20 )
  1427.                                    {
  1428.                                        mGL.bindTexture( mGL.TEXTURE_3D, id );
  1429.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_BASE_LEVEL, 0);
  1430.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAX_LEVEL, Math.log2(xres));
  1431.                                        if (filter === me.FILTER.NONE)
  1432.                                        {
  1433.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1434.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1435.                                        }
  1436.                                        else if (filter === me.FILTER.LINEAR)
  1437.                                        {
  1438.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1439.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
  1440.                                        }
  1441.                                        else if (filter === me.FILTER.MIPMAP)
  1442.                                        {
  1443.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1444.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1445.                                        }
  1446.                                        else
  1447.                                        {
  1448.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1449.                                            mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
  1450.                                            mGL.generateMipmap(mGL.TEXTURE_3D);
  1451.                                        }
  1452.                                        mGL.texImage3D( mGL.TEXTURE_3D, 0, glFoTy.mGLFormat, xres, yres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1453.  
  1454.                                        mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_R, glWrap );
  1455.                                        mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_S, glWrap );
  1456.                                        mGL.texParameteri( mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_T, glWrap );
  1457.  
  1458.                                        if (filter === me.FILTER.MIPMAP)
  1459.                                            mGL.generateMipmap( mGL.TEXTURE_3D );
  1460.                                        mGL.bindTexture( mGL.TEXTURE_3D, null );
  1461.                                    }
  1462.                                    else
  1463.                                    {
  1464.                                        return null;
  1465.                                    }
  1466.                                }
  1467.                                else
  1468.                                {
  1469.                                    mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
  1470.  
  1471.                                    // this works great if we know the number of required mipmaps in advance (1, or other)
  1472.                                   //mGL.texStorage2D( mGL.TEXTURE_CUBE_MAP, 1, glFoTy.mGLFormat, xres, yres );
  1473.  
  1474.                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1475.                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1476.                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1477.                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1478.                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1479.                                    mGL.texImage2D( mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, xres, yres, 0, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1480.  
  1481.                                    if( filter === me.FILTER.NONE)
  1482.                                    {
  1483.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1484.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1485.                                    }
  1486.                                    else if (filter === me.FILTER.LINEAR)
  1487.                                    {
  1488.                                        mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR );
  1489.                                        mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR );
  1490.                                    }
  1491.                                    else if (filter === me.FILTER.MIPMAP)
  1492.                                    {
  1493.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1494.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1495.                                    }
  1496.  
  1497.                                    if (filter === me.FILTER.MIPMAP)
  1498.                                        mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
  1499.  
  1500.                                    mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
  1501.                                }
  1502.                        return { mObjectID: id, mXres: xres, mYres: yres, mFormat: format, mType: type, mFilter: filter, mWrap: wrap, mVFlip:false };
  1503.                        };
  1504.  
  1505.        me.CreateTextureFromImage = function ( type, image, format, filter, wrap, flipY)
  1506.                                {
  1507.                                    if( mGL===null ) return null;
  1508.  
  1509.                                    var id = mGL.createTexture();
  1510.  
  1511.                                    var glFoTy = iFormatPI2GL( format );
  1512.  
  1513.                                    var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
  1514.  
  1515.                                    if( type===me.TEXTYPE.T2D )
  1516.                                    {
  1517.                                        mGL.bindTexture(mGL.TEXTURE_2D, id);
  1518.  
  1519.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, flipY);
  1520.                                        mGL.pixelStorei(mGL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
  1521.                                        if( mIs20 ) mGL.pixelStorei(mGL.UNPACK_COLORSPACE_CONVERSION_WEBGL, mGL.NONE );
  1522.  
  1523.                                        mGL.texImage2D(mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image);
  1524.  
  1525.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap);
  1526.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap);
  1527.  
  1528.                                        if (filter === me.FILTER.NONE)
  1529.                                        {
  1530.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1531.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1532.                                        }
  1533.                                        else if (filter === me.FILTER.LINEAR)
  1534.                                        {
  1535.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1536.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
  1537.                                        }
  1538.                                        else if( filter === me.FILTER.MIPMAP)
  1539.                                        {
  1540.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1541.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1542.                                            mGL.generateMipmap(mGL.TEXTURE_2D);
  1543.                                        }
  1544.                                        else
  1545.                                        {
  1546.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1547.                                            mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
  1548.                                            mGL.generateMipmap(mGL.TEXTURE_2D);
  1549.                                        }
  1550.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
  1551.                                        mGL.bindTexture(mGL.TEXTURE_2D, null);
  1552.                                    }
  1553.                                    else if( type===me.TEXTYPE.T3D )
  1554.                                    {
  1555.                                        return null;
  1556.                                    }
  1557.                                    else
  1558.                                    {
  1559.                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
  1560.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, flipY);
  1561.                                        mGL.activeTexture( mGL.TEXTURE0 );
  1562.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[0] );
  1563.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[1] );
  1564.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (flipY ? image[3] : image[2]) );
  1565.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (flipY ? image[2] : image[3]) );
  1566.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[4] );
  1567.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[5] );
  1568.  
  1569.                                        if( filter === me.FILTER.NONE)
  1570.                                        {
  1571.                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1572.                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1573.                                        }
  1574.                                        else if (filter === me.FILTER.LINEAR)
  1575.                                        {
  1576.                                            mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR );
  1577.                                            mGL.texParameteri( mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR );
  1578.                                        }
  1579.                                        else if (filter === me.FILTER.MIPMAP)
  1580.                                        {
  1581.                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1582.                                            mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1583.                                            mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
  1584.                                        }
  1585.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
  1586.                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
  1587.                                    }
  1588.                                    return { mObjectID: id, mXres: image.width, mYres: image.height, mFormat: format, mType: type, mFilter: filter, mWrap:wrap, mVFlip:flipY };
  1589.                                };
  1590.  
  1591.        me.SetSamplerFilter = function (te, filter, doGenerateMipsIfNeeded)
  1592.                            {
  1593.                                if (te.mFilter === filter) return;
  1594.  
  1595.                                if (te.mType === me.TEXTYPE.T2D)
  1596.                                {
  1597.                                    mGL.bindTexture(mGL.TEXTURE_2D, te.mObjectID);
  1598.  
  1599.                                    if (filter === me.FILTER.NONE)
  1600.                                    {
  1601.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1602.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1603.                                    }
  1604.                                    else if (filter === me.FILTER.LINEAR)
  1605.                                    {
  1606.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1607.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
  1608.                                    }
  1609.                                    else if (filter === me.FILTER.MIPMAP)
  1610.                                    {
  1611.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1612.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1613.                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_2D);
  1614.                                    }
  1615.                                    else
  1616.                                    {
  1617.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1618.                                        mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
  1619.                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_2D);
  1620.                                    }
  1621.  
  1622.                                    mGL.bindTexture(mGL.TEXTURE_2D, null);
  1623.  
  1624.                                }
  1625.                                else if (te.mType === me.TEXTYPE.T3D)
  1626.                                {
  1627.                                    mGL.bindTexture(mGL.TEXTURE_3D, te.mObjectID);
  1628.  
  1629.                                    if (filter === me.FILTER.NONE)
  1630.                                    {
  1631.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1632.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1633.                                    }
  1634.                                    else if (filter === me.FILTER.LINEAR)
  1635.                                    {
  1636.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1637.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
  1638.                                    }
  1639.                                    else if (filter === me.FILTER.MIPMAP)
  1640.                                    {
  1641.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1642.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1643.                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_3D);
  1644.                                    }
  1645.                                    else
  1646.                                    {
  1647.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1648.                                        mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
  1649.                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_3D);
  1650.                                    }
  1651.  
  1652.                                    mGL.bindTexture(mGL.TEXTURE_3D, null);
  1653.  
  1654.                                }
  1655.                                else
  1656.                                {
  1657.                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, te.mObjectID);
  1658.  
  1659.                                    if (filter === me.FILTER.NONE)
  1660.                                    {
  1661.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1662.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST);
  1663.                                    }
  1664.                                    else if (filter === me.FILTER.LINEAR)
  1665.                                    {
  1666.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1667.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR);
  1668.                                    }
  1669.                                    else if (filter === me.FILTER.MIPMAP)
  1670.                                    {
  1671.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.LINEAR);
  1672.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.LINEAR_MIPMAP_LINEAR);
  1673.                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_CUBE_MAP);
  1674.                                    }
  1675.                                    else
  1676.                                    {
  1677.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MAG_FILTER, mGL.NEAREST);
  1678.                                        mGL.texParameteri(mGL.TEXTURE_CUBE_MAP, mGL.TEXTURE_MIN_FILTER, mGL.NEAREST_MIPMAP_LINEAR);
  1679.                                        if( doGenerateMipsIfNeeded ) mGL.generateMipmap(mGL.TEXTURE_CUBE_MAP);
  1680.                                    }
  1681.  
  1682.                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
  1683.                                }
  1684.  
  1685.  
  1686.                                te.mFilter = filter;
  1687.                            };
  1688.  
  1689.        me.SetSamplerWrap = function (te, wrap)
  1690.                            {
  1691.                                if (te.mWrap === wrap) return;
  1692.  
  1693.                                var glWrap = mGL.REPEAT; if (wrap === me.TEXWRP.CLAMP) glWrap = mGL.CLAMP_TO_EDGE;
  1694.  
  1695.                                var id = te.mObjectID;
  1696.  
  1697.                                if (te.mType === me.TEXTYPE.T2D)
  1698.                                {
  1699.                                    mGL.bindTexture(mGL.TEXTURE_2D, id);
  1700.                                    mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_S, glWrap);
  1701.                                    mGL.texParameteri(mGL.TEXTURE_2D, mGL.TEXTURE_WRAP_T, glWrap);
  1702.                                    mGL.bindTexture(mGL.TEXTURE_2D, null);
  1703.  
  1704.                                }
  1705.                                else if (te.mType === me.TEXTYPE.T3D)
  1706.                                {
  1707.                                    mGL.bindTexture(mGL.TEXTURE_3D, id);
  1708.                                    mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_R, glWrap);
  1709.                                    mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_S, glWrap);
  1710.                                    mGL.texParameteri(mGL.TEXTURE_3D, mGL.TEXTURE_WRAP_T, glWrap);
  1711.                                    mGL.bindTexture(mGL.TEXTURE_3D, null);
  1712.                                }
  1713.  
  1714.                                te.mWrap = wrap;
  1715.                            };
  1716.  
  1717.        me.SetSamplerVFlip = function (te, vflip, image)
  1718.                            {
  1719.                                if (te.mVFlip === vflip) return;
  1720.  
  1721.                                var id = te.mObjectID;
  1722.  
  1723.                                if (te.mType === me.TEXTYPE.T2D)
  1724.                                {
  1725.                                    if( image != null)
  1726.                                    {
  1727.                                        mGL.activeTexture( mGL.TEXTURE0 );
  1728.                                        mGL.bindTexture(mGL.TEXTURE_2D, id);
  1729.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, vflip);
  1730.                                        var glFoTy = iFormatPI2GL( te.mFormat );
  1731.                                        mGL.texImage2D(mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image);
  1732.                                        mGL.bindTexture(mGL.TEXTURE_2D, null);
  1733.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
  1734.                                    }
  1735.                                }
  1736.                                else if (te.mType === me.TEXTYPE.CUBEMAP)
  1737.                                {
  1738.                                    if( image != null)
  1739.                                    {
  1740.                                        var glFoTy = iFormatPI2GL( te.mFormat );
  1741.                                        mGL.activeTexture( mGL.TEXTURE0 );
  1742.                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, id );
  1743.                                        mGL.pixelStorei( mGL.UNPACK_FLIP_Y_WEBGL, vflip);
  1744.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[0] );
  1745.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[1] );
  1746.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (vflip ? image[3] : image[2]) );
  1747.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, (vflip ? image[2] : image[3]) );
  1748.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[4] );
  1749.                                        mGL.texImage2D(  mGL.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image[5] );
  1750.                                        mGL.bindTexture( mGL.TEXTURE_CUBE_MAP, null );
  1751.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
  1752.                                    }
  1753.        
  1754.                                }
  1755.  
  1756.                                te.mVFlip = vflip;
  1757.                            };
  1758.  
  1759.        me.CreateMipmaps =  function (te)
  1760.                            {
  1761.                                if( te.mType===me.TEXTYPE.T2D )
  1762.                                {
  1763.                                    mGL.activeTexture(mGL.TEXTURE0);
  1764.                                    mGL.bindTexture(mGL.TEXTURE_2D, te.mObjectID);
  1765.                                    mGL.generateMipmap(mGL.TEXTURE_2D);
  1766.                                    mGL.bindTexture(mGL.TEXTURE_2D, null);
  1767.                                }
  1768.                                else if( te.mType===me.TEXTYPE.CUBEMAP )
  1769.                                {
  1770.                                    mGL.activeTexture(mGL.TEXTURE0);
  1771.                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, te.mObjectID);
  1772.                                    mGL.generateMipmap( mGL.TEXTURE_CUBE_MAP );
  1773.                                    mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
  1774.                                }
  1775.                            };
  1776.  
  1777.        me.UpdateTexture =  function( tex, x0, y0, xres, yres, buffer )
  1778.                            {
  1779.                                var glFoTy = iFormatPI2GL( tex.mFormat );
  1780.                                if( tex.mType===me.TEXTYPE.T2D )
  1781.                                {
  1782.                                    mGL.activeTexture( mGL.TEXTURE0);
  1783.                                    mGL.bindTexture( mGL.TEXTURE_2D, tex.mObjectID );
  1784.                                    mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, tex.mVFlip );
  1785.                                    mGL.texSubImage2D( mGL.TEXTURE_2D, 0, x0, y0, xres, yres, glFoTy.mGLExternal, glFoTy.mGLType, buffer );
  1786.                                    mGL.bindTexture( mGL.TEXTURE_2D, null );
  1787.                                    mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
  1788.                                }
  1789.                            };
  1790.  
  1791.        me.UpdateTextureFromImage = function( tex, image )
  1792.                                {
  1793.                                    var glFoTy = iFormatPI2GL( tex.mFormat );
  1794.                                    if( tex.mType===me.TEXTYPE.T2D )
  1795.                                    {
  1796.                                        mGL.activeTexture( mGL.TEXTURE0 );
  1797.                                        mGL.bindTexture( mGL.TEXTURE_2D, tex.mObjectID );
  1798.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, tex.mVFlip );
  1799.                                        mGL.texImage2D(  mGL.TEXTURE_2D, 0, glFoTy.mGLFormat, glFoTy.mGLExternal, glFoTy.mGLType, image );
  1800.                                        mGL.bindTexture( mGL.TEXTURE_2D, null );
  1801.                                        mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, false);
  1802.                                    }
  1803.                                };
  1804.  
  1805.        me.DestroyTexture = function( te )
  1806.                            {
  1807.                                 mGL.deleteTexture( te.mObjectID );
  1808.                            };
  1809.  
  1810.        me.AttachTextures = function (num, t0, t1, t2, t3)
  1811.                            {
  1812.                                if (num > 0 && t0 != null)
  1813.                                {
  1814.                                    mGL.activeTexture(mGL.TEXTURE0);
  1815.                                         if (t0.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t0.mObjectID);
  1816.                                    else if (t0.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t0.mObjectID);
  1817.                                    else if (t0.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t0.mObjectID);
  1818.                                }
  1819.  
  1820.                                if (num > 1 && t1 != null)
  1821.                                {
  1822.                                    mGL.activeTexture(mGL.TEXTURE1);
  1823.                                         if (t1.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t1.mObjectID);
  1824.                                    else if (t1.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t1.mObjectID);
  1825.                                    else if (t1.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t1.mObjectID);
  1826.                                }
  1827.  
  1828.                                if (num > 2 && t2 != null)
  1829.                                {
  1830.                                    mGL.activeTexture(mGL.TEXTURE2);
  1831.                                         if (t2.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t2.mObjectID);
  1832.                                    else if (t2.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t2.mObjectID);
  1833.                                    else if (t2.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t2.mObjectID);
  1834.                                }
  1835.  
  1836.                                if (num > 3 && t3 != null)
  1837.                                {
  1838.                                    mGL.activeTexture(mGL.TEXTURE3);
  1839.                                         if (t3.mType === me.TEXTYPE.T2D) mGL.bindTexture(mGL.TEXTURE_2D, t3.mObjectID);
  1840.                                    else if (t3.mType === me.TEXTYPE.T3D) mGL.bindTexture(mGL.TEXTURE_3D, t3.mObjectID);
  1841.                                    else if (t3.mType === me.TEXTYPE.CUBEMAP) mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, t3.mObjectID);
  1842.                                }
  1843.                            };
  1844.  
  1845.        me.DettachTextures = function()
  1846.                             {
  1847.                                mGL.activeTexture(mGL.TEXTURE0);
  1848.                                mGL.bindTexture(mGL.TEXTURE_2D, null);
  1849.                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
  1850.  
  1851.                                mGL.activeTexture(mGL.TEXTURE1);
  1852.                                mGL.bindTexture(mGL.TEXTURE_2D, null);
  1853.                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
  1854.  
  1855.                                mGL.activeTexture(mGL.TEXTURE2);
  1856.                                mGL.bindTexture(mGL.TEXTURE_2D, null);
  1857.                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
  1858.  
  1859.                                mGL.activeTexture(mGL.TEXTURE3);
  1860.                                mGL.bindTexture(mGL.TEXTURE_2D, null);
  1861.                                mGL.bindTexture(mGL.TEXTURE_CUBE_MAP, null);
  1862.                             };
  1863.  
  1864.        me.CreateRenderTarget = function ( color0, color1, color2, color3, depth, wantZbuffer )
  1865.                                {
  1866.                                    var id =  mGL.createFramebuffer();
  1867.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
  1868.  
  1869.                                    if (depth === null)
  1870.                                    {
  1871.                                        if( wantZbuffer===true )
  1872.                                        {
  1873.                                            var zb = mGL.createRenderbuffer();
  1874.                                            mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
  1875.                                            mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, color0.mXres, color0.mYres);
  1876.  
  1877.                                            mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
  1878.                                        }
  1879.                                    }
  1880.                                    else
  1881.                                    {
  1882.                                        mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.TEXTURE_2D, depth.mObjectID, 0);
  1883.                                    }
  1884.  
  1885.                                    if( color0 !=null ) mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_2D, color0.mObjectID, 0);
  1886.  
  1887.                                    if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
  1888.                                        return null;
  1889.  
  1890.                                    mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
  1891.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
  1892.                                    return { mObjectID: id, mTex0: color0 };
  1893.                                };
  1894.  
  1895.        me.DestroyRenderTarget = function ( tex )
  1896.                                 {
  1897.                                     mGL.deleteFramebuffer(tex.mObjectID);
  1898.                                 };
  1899.  
  1900.        me.SetRenderTarget = function (tex)
  1901.                             {
  1902.                                if( tex===null )
  1903.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
  1904.                                else
  1905.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, tex.mObjectID);
  1906.  
  1907.                                //mGL.drawBuffers([mGL.COLOR_ATTACHMENT0, mGL.COLOR_ATTACHMENT1]);
  1908.                             };
  1909.  
  1910.        me.CreateRenderTargetNew = function ( wantColor0, wantZbuffer, xres, yres, samples )
  1911.                                {
  1912.                                    var id =  mGL.createFramebuffer();
  1913.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
  1914.  
  1915.                                    if( wantZbuffer===true )
  1916.                                    {
  1917.                                        var zb = mGL.createRenderbuffer();
  1918.                                        mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
  1919.  
  1920.                                        if( samples==1 )
  1921.                                        mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, xres, yres);
  1922.                                        else
  1923.                                        mGL.renderbufferStorageMultisample(mGL.RENDERBUFFER, samples, mGL.DEPTH_COMPONENT16, xres, yres);
  1924.                                        mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
  1925.                                    }
  1926.  
  1927.                                    if( wantColor0 )
  1928.                                    {
  1929.                                        var cb = mGL.createRenderbuffer();
  1930.                                        mGL.bindRenderbuffer(mGL.RENDERBUFFER, cb);
  1931.                                        if( samples==1 )
  1932.                                        mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.RGBA8, xres, yres);
  1933.                                        else
  1934.                                        mGL.renderbufferStorageMultisample(mGL.RENDERBUFFER, samples, mGL.RGBA8, xres, yres);
  1935.                                        mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.RENDERBUFFER, cb);
  1936.                                    }
  1937.  
  1938.                                    if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
  1939.                                    {
  1940.                                        return null;
  1941.                                    }
  1942.                                    mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
  1943.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
  1944.                                    return { mObjectID: id, mXres: xres, mYres:yres, mTex0: color0 };
  1945.                                };
  1946.  
  1947.        me.CreateRenderTargetCubeMap = function ( color0, depth, wantZbuffer )
  1948.                                {
  1949.                                    var id =  mGL.createFramebuffer();
  1950.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, id);
  1951.  
  1952.                                    if (depth === null)
  1953.                                    {
  1954.                                        if( wantZbuffer===true )
  1955.                                        {
  1956.                                            var zb = mGL.createRenderbuffer();
  1957.                                            mGL.bindRenderbuffer(mGL.RENDERBUFFER, zb);
  1958.                                            mGL.renderbufferStorage(mGL.RENDERBUFFER, mGL.DEPTH_COMPONENT16, color0.mXres, color0.mYres);
  1959.                                            mGL.framebufferRenderbuffer(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.RENDERBUFFER, zb);
  1960.                                        }
  1961.                                    }
  1962.                                    else
  1963.                                    {
  1964.                                        mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.DEPTH_ATTACHMENT, mGL.TEXTURE_2D, depth.mObjectID, 0);
  1965.                                    }
  1966.  
  1967.                                    if( color0 !=null ) mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_CUBE_MAP_POSITIVE_X, color0.mObjectID, 0);
  1968.  
  1969.                                    if (mGL.checkFramebufferStatus(mGL.FRAMEBUFFER) != mGL.FRAMEBUFFER_COMPLETE)
  1970.                                        return null;
  1971.  
  1972.                                    mGL.bindRenderbuffer(mGL.RENDERBUFFER, null);
  1973.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
  1974.                                    return { mObjectID: id, mTex0: color0 };
  1975.                                };
  1976.  
  1977.        me.SetRenderTargetCubeMap = function (fbo, face)
  1978.                             {
  1979.                                if( fbo===null )
  1980.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
  1981.                                else
  1982.                                {
  1983.                                    mGL.bindFramebuffer(mGL.FRAMEBUFFER, fbo.mObjectID);
  1984.                                    mGL.framebufferTexture2D(mGL.FRAMEBUFFER, mGL.COLOR_ATTACHMENT0, mGL.TEXTURE_CUBE_MAP_POSITIVE_X+face, fbo.mTex0.mObjectID, 0);
  1985.                                }
  1986.                             };
  1987.  
  1988.  
  1989.        me.BlitRenderTarget = function( dst, src )
  1990.                                {
  1991.                                    mGL.bindFramebuffer(mGL.READ_FRAMEBUFFER, src.mObjectID);
  1992.                                    mGL.bindFramebuffer(mGL.DRAW_FRAMEBUFFER, dst.mObjectID);
  1993.                                    mGL.clearBufferfv(mGL.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
  1994.                                    mGL.blitFramebuffer( 0, 0, src.mXres, src.mYres,
  1995.                                                         0, 0, src.mXres, src.mYres,
  1996.                                                         mGL.COLOR_BUFFER_BIT, mGL.LINEAR
  1997.                                    );
  1998.                                };
  1999.  
  2000.        me.SetViewport = function( vp )
  2001.                         {
  2002.                              mGL.viewport( vp[0], vp[1], vp[2], vp[3] );
  2003.                         };
  2004.  
  2005.        me.SetWriteMask = function( c0, c1, c2, c3, z )
  2006.                          {
  2007.                              mGL.depthMask(z);
  2008.                              mGL.colorMask(c0,c0,c0,c0);
  2009.                          };
  2010.  
  2011.        me.SetState = function( stateName, stateValue )
  2012.                      {
  2013.                            if (stateName === me.RENDSTGATE.WIREFRAME)
  2014.                            {
  2015.                                if( stateValue ) mGL.polygonMode( mGL.FRONT_AND_BACK, mGL.LINE );
  2016.                                else             mGL.polygonMode( mGL.FRONT_AND_BACK, mGL.FILL );
  2017.                            }
  2018.                            else if (stateName === me.RENDSTGATE.FRONT_FACE)
  2019.                            {
  2020.                                if( stateValue ) mGL.cullFace( mGL.BACK );
  2021.                                else             mGL.cullFace( mGL.FRONT );
  2022.                            }
  2023.                            else if (stateName === me.RENDSTGATE.CULL_FACE)
  2024.                            {
  2025.                                if( stateValue ) mGL.enable( mGL.CULL_FACE );
  2026.                                else             mGL.disable( mGL.CULL_FACE );
  2027.                            }
  2028.                            else if (stateName === me.RENDSTGATE.DEPTH_TEST)
  2029.                            {
  2030.                                if( stateValue ) mGL.enable( mGL.DEPTH_TEST );
  2031.                                else             mGL.disable( mGL.DEPTH_TEST );
  2032.                            }
  2033.                            else if (stateName === me.RENDSTGATE.ALPHA_TO_COVERAGE)
  2034.                            {
  2035.                                if( stateValue ) { mGL.enable(  mGL.SAMPLE_ALPHA_TO_COVERAGE ); }
  2036.                                else             { mGL.disable( mGL.SAMPLE_ALPHA_TO_COVERAGE ); }
  2037.                            }
  2038.                      };
  2039.  
  2040.        me.SetMultisample = function( v)
  2041.                    {
  2042.                        if( v===true )
  2043.                        {
  2044.                            mGL.enable(mGL.SAMPLE_COVERAGE);
  2045.                            mGL.sampleCoverage(1.0, false);
  2046.                        }
  2047.                        else
  2048.                        {
  2049.                            mGL.disable(mGL.SAMPLE_COVERAGE);
  2050.                        }
  2051.                    };
  2052.  
  2053.        me.GetTranslatedShaderSource = function (shader)
  2054.                          {
  2055.                            if( mGL===null ) return null;
  2056.                            if( mDebugShader===null ) return null;
  2057.                            let vfs = mGL.getAttachedShaders(shader.mProgram);
  2058.                            let str = mDebugShader.getTranslatedShaderSource(vfs[1]);
  2059.                            let parts = str.split("GLSL END"); str = (parts.length<2) ? str : parts[1];
  2060.                            return str;
  2061.                          };
  2062.  
  2063.        me.CreateShader = function (vsSource, fsSource, preventCache, forceSynch, onResolve)
  2064.                          {
  2065.                            if( mGL===null ) return;
  2066.  
  2067.                            var vs = mGL.createShader( mGL.VERTEX_SHADER   );
  2068.                            var fs = mGL.createShader( mGL.FRAGMENT_SHADER );
  2069.  
  2070.                            vsSource = mShaderHeader[0] + vsSource;
  2071.                            fsSource = mShaderHeader[1] + fsSource;
  2072.  
  2073.                            if( preventCache )
  2074.                            {
  2075.                                let vran = Math.random().toString(36).substring(7);
  2076.                                let fran = Math.random().toString(36).substring(7);
  2077.                                vsSource += "\n#define K" + vran + "\n";
  2078.                                fsSource += "\n#define K" + fran + "\n";
  2079.                            }
  2080.  
  2081.                            var timeStart = getRealTime();
  2082.  
  2083.                            mGL.shaderSource(vs, vsSource);
  2084.                            mGL.shaderSource(fs, fsSource);
  2085.                            mGL.compileShader(vs);
  2086.                            mGL.compileShader(fs);
  2087.  
  2088.                            var pr = mGL.createProgram();
  2089.                            mGL.attachShader(pr, vs);
  2090.                            mGL.attachShader(pr, fs);
  2091.                            mGL.linkProgram(pr);
  2092.  
  2093.                            //-------------
  2094.                            let checkErrors = function()
  2095.                            {
  2096.                                if (!mGL.getProgramParameter(pr, mGL.LINK_STATUS))
  2097.                                {
  2098.                                    // vs error
  2099.                                    if (!mGL.getShaderParameter(vs, mGL.COMPILE_STATUS))
  2100.                                    {
  2101.                                        let vsLog = mGL.getShaderInfoLog(vs);
  2102.                                        onResolve(false, { mErrorType: 0, mErrorStr: vsLog });
  2103.                                        mGL.deleteProgram(pr);
  2104.                                    }
  2105.                                    // fs error
  2106.                                    else if (!mGL.getShaderParameter(fs, mGL.COMPILE_STATUS))
  2107.                                    {
  2108.                                        let fsLog = mGL.getShaderInfoLog(fs);
  2109.                                        onResolve(false, { mErrorType: 1, mErrorStr: fsLog });
  2110.                                        mGL.deleteProgram(pr);
  2111.                                    }
  2112.                                    // link error
  2113.                                    else
  2114.                                    {
  2115.                                        let infoLog = mGL.getProgramInfoLog(pr);
  2116.                                        onResolve(false, { mErrorType: 2, mErrorStr: infoLog });
  2117.                                        mGL.deleteProgram(pr);
  2118.                                    }
  2119.                                }
  2120.                                // no errors
  2121.                                else
  2122.                                {
  2123.                                    let compilationTime = getRealTime() - timeStart;
  2124.                                    onResolve(true, { mProgram: pr, mTime: compilationTime });
  2125.                                }
  2126.                            };
  2127.  
  2128.                            // check compilation
  2129.                            if (mAsynchCompile === null || forceSynch===true )
  2130.                            {
  2131.                                checkErrors();
  2132.                            }
  2133.                            else
  2134.                            {
  2135.                                let loopCheckCompletion = function ()
  2136.                                {
  2137.                                    if( mGL.getProgramParameter(pr, mAsynchCompile.COMPLETION_STATUS_KHR) === true )
  2138.                                        checkErrors();
  2139.                                    else
  2140.                                        setTimeout(loopCheckCompletion, 10);
  2141.                                };
  2142.                                setTimeout(loopCheckCompletion, 10);
  2143.                            }
  2144.                        };
  2145.  
  2146.        me.AttachShader = function( shader )
  2147.                          {
  2148.                                if( shader===null )
  2149.                                {
  2150.                                    mBindedShader = null;
  2151.                                    mGL.useProgram( null );
  2152.                                }
  2153.                                else
  2154.                                {
  2155.                                    mBindedShader = shader;
  2156.                                    mGL.useProgram(shader.mProgram);
  2157.                                }
  2158.                          };
  2159.  
  2160.        me.DetachShader = function ()
  2161.                        {
  2162.                            mGL.useProgram(null);
  2163.                        };
  2164.  
  2165.        me.DestroyShader = function( tex )
  2166.                        {
  2167.                            mGL.deleteProgram(tex.mProgram);
  2168.                        };
  2169.  
  2170.        me.GetAttribLocation = function (shader, name)
  2171.                        {
  2172.                            return mGL.getAttribLocation(shader.mProgram, name);
  2173.                        };
  2174.  
  2175.        me.SetShaderConstantLocation = function (shader, name)
  2176.                        {
  2177.                            return mGL.getUniformLocation(shader.mProgram, name);
  2178.                        };
  2179.  
  2180.        me.SetShaderConstantMat4F = function( uname, params, istranspose )
  2181.                        {
  2182.                            var program = mBindedShader;
  2183.  
  2184.                            let pos = mGL.getUniformLocation( program.mProgram, uname );
  2185.                            if( pos===null )
  2186.                                return false;
  2187.  
  2188.                            if( istranspose===false )
  2189.                            {
  2190.                                var tmp = new Float32Array( [ params[0], params[4], params[ 8], params[12],
  2191.                                                              params[1], params[5], params[ 9], params[13],
  2192.                                                              params[2], params[6], params[10], params[14],
  2193.                                                              params[3], params[7], params[11], params[15] ] );
  2194.                            mGL.uniformMatrix4fv(pos,false,tmp);
  2195.                            }
  2196.                            else
  2197.                                mGL.uniformMatrix4fv(pos,false,new Float32Array(params) );
  2198.                            return true;
  2199.                        };
  2200.  
  2201.        me.SetShaderConstant1F_Pos = function(pos, x)
  2202.                        {
  2203.                            mGL.uniform1f(pos, x);
  2204.                            return true;
  2205.                        };
  2206.  
  2207.        me.SetShaderConstant1FV_Pos = function(pos, x)
  2208.                        {
  2209.                            mGL.uniform1fv(pos, x);
  2210.                            return true;
  2211.                        };
  2212.  
  2213.        me.SetShaderConstant1F = function( uname, x )
  2214.                        {
  2215.                            var pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
  2216.                            if (pos === null)
  2217.                                return false;
  2218.                            mGL.uniform1f(pos, x);
  2219.                            return true;
  2220.                        };
  2221.  
  2222.        me.SetShaderConstant1I = function(uname, x)
  2223.                        {
  2224.                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
  2225.                            if (pos === null)
  2226.                                return false;
  2227.                            mGL.uniform1i(pos, x);
  2228.                            return true;
  2229.                        };
  2230.        me.SetShaderConstant1I_Pos = function(pos, x)
  2231.                        {
  2232.                            mGL.uniform1i(pos, x);
  2233.                            return true;
  2234.                        };
  2235.  
  2236.  
  2237.        me.SetShaderConstant2F = function(uname, x)
  2238.                        {
  2239.                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
  2240.                            if (pos === null)
  2241.                                return false;
  2242.                            mGL.uniform2fv(pos, x);
  2243.                            return true;
  2244.                        };
  2245.  
  2246.        me.SetShaderConstant3F = function(uname, x, y, z)
  2247.                        {
  2248.                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
  2249.                            if (pos === null)
  2250.                                return false;
  2251.                            mGL.uniform3f(pos, x, y, z);
  2252.                            return true;
  2253.                        };
  2254.  
  2255.        me.SetShaderConstant1FV = function(uname, x)
  2256.                        {
  2257.                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
  2258.                            if (pos === null)
  2259.                                return false;
  2260.                            mGL.uniform1fv(pos, new Float32Array(x));
  2261.                            return true;
  2262.                        };
  2263.  
  2264.        me.SetShaderConstant3FV = function(uname, x)
  2265.                        {
  2266.                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
  2267.                            if (pos === null) return false;
  2268.                            mGL.uniform3fv(pos, new Float32Array(x) );
  2269.                            return true;
  2270.                        };
  2271.  
  2272.        me.SetShaderConstant4FV = function(uname, x)
  2273.                        {
  2274.                            let pos = mGL.getUniformLocation(mBindedShader.mProgram, uname);
  2275.                            if (pos === null) return false;
  2276.                            mGL.uniform4fv(pos, new Float32Array(x) );
  2277.                            return true;
  2278.                        };
  2279.  
  2280.        me.SetShaderTextureUnit = function( uname, unit )
  2281.                        {
  2282.                            var program = mBindedShader;
  2283.                            let pos = mGL.getUniformLocation(program.mProgram, uname);
  2284.                            if (pos === null) return false;
  2285.                            mGL.uniform1i(pos, unit);
  2286.                            return true;
  2287.                        };
  2288.  
  2289.        me.CreateVertexArray = function( data, mode )
  2290.                        {
  2291.                            let id = mGL.createBuffer();
  2292.                            mGL.bindBuffer(mGL.ARRAY_BUFFER, id);
  2293.                            if (mode === me.BUFTYPE.STATIC)
  2294.                                mGL.bufferData(mGL.ARRAY_BUFFER, data, mGL.STATIC_DRAW);
  2295.                            else
  2296.                                mGL.bufferData(mGL.ARRAY_BUFFER, data, mGL.DYNAMIC_DRAW);
  2297.                            return { mObject: id };
  2298.                        };
  2299.  
  2300.        me.CreateIndexArray = function( data, mode )
  2301.                        {
  2302.                            let id = mGL.createBuffer();
  2303.                            mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, id );
  2304.                            if (mode === me.BUFTYPE.STATIC)
  2305.                                mGL.bufferData(mGL.ELEMENT_ARRAY_BUFFER, data, mGL.STATIC_DRAW);
  2306.                            else
  2307.                                mGL.bufferData(mGL.ELEMENT_ARRAY_BUFFER, data, mGL.DYNAMIC_DRAW);
  2308.                            return { mObject: id };
  2309.                        };
  2310.  
  2311.        me.DestroyArray = function( tex )
  2312.                        {
  2313.                            mGL.destroyBuffer(tex.mObject);
  2314.                        };
  2315.  
  2316.        me.AttachVertexArray = function( tex, attribs, pos )
  2317.                        {
  2318.                            let shader = mBindedShader;
  2319.  
  2320.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, tex.mObject);
  2321.  
  2322.                            var num = attribs.mChannels.length;
  2323.                            var stride = attribs.mStride;
  2324.  
  2325.                            var offset = 0;
  2326.                            for (var i = 0; i < num; i++)
  2327.                            {
  2328.                                var id = pos[i];
  2329.                                mGL.enableVertexAttribArray(id);
  2330.                                var dtype = mGL.FLOAT;
  2331.                                var dsize = 4;
  2332.                                     if( attribs.mChannels[i].mType === me.TYPE.UINT8   ) { dtype = mGL.UNSIGNED_BYTE;  dsize = 1; }
  2333.                                else if( attribs.mChannels[i].mType === me.TYPE.UINT16  ) { dtype = mGL.UNSIGNED_SHORT; dsize = 2; }
  2334.                                else if( attribs.mChannels[i].mType === me.TYPE.FLOAT32 ) { dtype = mGL.FLOAT;          dsize = 4; }
  2335.                                mGL.vertexAttribPointer(id, attribs.mChannels[i].mNumComponents, dtype, attribs.mChannels[i].mNormalize, stride, offset);
  2336.                                offset += attribs.mChannels[i].mNumComponents * dsize;
  2337.                            }
  2338.                        };
  2339.  
  2340.        me.AttachIndexArray = function( tex )
  2341.                        {
  2342.                            mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, tex.mObject);
  2343.                        };
  2344.  
  2345.        me.DetachVertexArray = function (tex, attribs)
  2346.                        {
  2347.                            let num = attribs.mChannels.length;
  2348.                            for (let i = 0; i < num; i++)
  2349.                                mGL.disableVertexAttribArray(i);
  2350.                            mGL.bindBuffer(mGL.ARRAY_BUFFER, null);
  2351.                        };
  2352.  
  2353.        me.DetachIndexArray = function( tex )
  2354.                        {
  2355.                            mGL.bindBuffer(mGL.ELEMENT_ARRAY_BUFFER, null);
  2356.                        };
  2357.  
  2358.        me.DrawPrimitive = function( typeOfPrimitive, num, useIndexArray, numInstances )
  2359.                        {
  2360.                            let glType = mGL.POINTS;
  2361.                            if( typeOfPrimitive===me.PRIMTYPE.POINTS ) glType = mGL.POINTS;
  2362.                            if( typeOfPrimitive===me.PRIMTYPE.LINES ) glType = mGL.LINES;
  2363.                            if( typeOfPrimitive===me.PRIMTYPE.LINE_LOOP ) glType = mGL.LINE_LOOP;
  2364.                            if( typeOfPrimitive===me.PRIMTYPE.LINE_STRIP ) glType = mGL.LINE_STRIP;
  2365.                            if( typeOfPrimitive===me.PRIMTYPE.TRIANGLES ) glType = mGL.TRIANGLES;
  2366.                            if( typeOfPrimitive===me.PRIMTYPE.TRIANGLE_STRIP ) glType = mGL.TRIANGLE_STRIP;
  2367.  
  2368.                            if( numInstances<=1 )
  2369.                            {
  2370.                              if( useIndexArray ) mGL.drawElements( glType, num, mGL.UNSIGNED_SHORT, 0 );
  2371.                            else                mGL.drawArrays( glType, 0, num );
  2372.                            }
  2373.                            else
  2374.                            {
  2375.                                mGL.drawArraysInstanced(glType, 0, num, numInstances);
  2376.                                mGL.drawElementsInstanced( glType, num, mGL.UNSIGNED_SHORT, 0, numInstances);
  2377.                            }
  2378.                        };
  2379.  
  2380.  
  2381.        me.DrawFullScreenTriangle_XY = function( vpos )
  2382.                        {
  2383.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Tri );
  2384.                            mGL.vertexAttribPointer( vpos, 2, mGL.FLOAT, false, 0, 0 );
  2385.                            mGL.enableVertexAttribArray( vpos );
  2386.                            mGL.drawArrays( mGL.TRIANGLES, 0, 3 );
  2387.                            mGL.disableVertexAttribArray( vpos );
  2388.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  2389.                        };
  2390.  
  2391.  
  2392.        me.DrawUnitQuad_XY = function( vpos )
  2393.                        {
  2394.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_Quad );
  2395.                            mGL.vertexAttribPointer( vpos, 2, mGL.FLOAT, false, 0, 0 );
  2396.                            mGL.enableVertexAttribArray( vpos );
  2397.                            mGL.drawArrays( mGL.TRIANGLES, 0, 6 );
  2398.                            mGL.disableVertexAttribArray( vpos );
  2399.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  2400.                        };
  2401.  
  2402.        me.DrawUnitCube_XYZ_NOR = function( vpos )
  2403.                        {
  2404.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePosNor );
  2405.                            mGL.vertexAttribPointer( vpos[0], 3, mGL.FLOAT, false, 0, 0 );
  2406.                            mGL.vertexAttribPointer( vpos[1], 3, mGL.FLOAT, false, 0, 0 );
  2407.                            mGL.enableVertexAttribArray( vpos[0] );
  2408.                            mGL.enableVertexAttribArray( vpos[1] );
  2409.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 0, 4);
  2410.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 4, 4);
  2411.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 8, 4);
  2412.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 12, 4);
  2413.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 16, 4);
  2414.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 20, 4);
  2415.                            mGL.disableVertexAttribArray( vpos[0] );
  2416.                            mGL.disableVertexAttribArray( vpos[1] );
  2417.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  2418.                        }
  2419.  
  2420.        me.DrawUnitCube_XYZ = function( vpos )
  2421.                        {
  2422.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, mVBO_CubePos );
  2423.                            mGL.vertexAttribPointer( vpos, 3, mGL.FLOAT, false, 0, 0 );
  2424.                            mGL.enableVertexAttribArray( vpos );
  2425.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 0, 4);
  2426.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 4, 4);
  2427.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 8, 4);
  2428.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 12, 4);
  2429.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 16, 4);
  2430.                            mGL.drawArrays(mGL.TRIANGLE_STRIP, 20, 4);
  2431.                            mGL.disableVertexAttribArray( vpos );
  2432.                            mGL.bindBuffer( mGL.ARRAY_BUFFER, null );
  2433.                        }
  2434.  
  2435.        me.SetBlend = function( enabled )
  2436.                    {
  2437.                        if( enabled )
  2438.                        {
  2439.                            mGL.enable( mGL.BLEND );
  2440.                            mGL.blendEquationSeparate( mGL.FUNC_ADD, mGL.FUNC_ADD );
  2441.                            mGL.blendFuncSeparate( mGL.SRC_ALPHA, mGL.ONE_MINUS_SRC_ALPHA, mGL.ONE, mGL.ONE_MINUS_SRC_ALPHA );
  2442.                        }
  2443.                        else
  2444.                        {
  2445.                            mGL.disable( mGL.BLEND );
  2446.                        }
  2447.                    };
  2448.  
  2449.        me.GetPixelData = function( data, offset, xres, yres )
  2450.                        {
  2451.                            mGL.readPixels(0, 0, xres, yres, mGL.RGBA, mGL.UNSIGNED_BYTE, data, offset);
  2452.                        };
  2453.  
  2454.        me.GetPixelDataRenderTarget = function( obj, data, xres, yres )
  2455.                        {
  2456.                            mGL.bindFramebuffer(mGL.FRAMEBUFFER, obj.mObjectID);
  2457.                            mGL.readBuffer(mGL.COLOR_ATTACHMENT0);
  2458.                            mGL.readPixels(0, 0, xres, yres, mGL.RGBA, mGL.FLOAT, data, 0);
  2459.                            mGL.bindFramebuffer(mGL.FRAMEBUFFER, null);
  2460.                        };
  2461.    return me;
  2462. }
  2463. //==============================================================================
  2464. //
  2465. // piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  2466. //
  2467. // piShading
  2468. //
  2469. //==============================================================================
  2470.  
  2471. function smoothstep(a, b, x)
  2472. {
  2473.    x = (x - a) / (b - a);
  2474.    if (x < 0) x = 0; else if (x > 1) x = 1;
  2475.    return x * x * (3.0 - 2.0 * x);
  2476. }
  2477.  
  2478. function clamp01(x)
  2479. {
  2480.    if( x < 0.0 ) x = 0.0;
  2481.    if( x > 1.0 ) x = 1.0;
  2482.    return x;
  2483. }
  2484.  
  2485. function clamp(x, a, b)
  2486. {
  2487.    if( x < a ) x = a;
  2488.    if( x > b ) x = b;
  2489.    return x;
  2490. }
  2491.  
  2492. function screen(a, b)
  2493. {
  2494.    return 1.0 - (1.0 - a) * (1.0 - b);
  2495. }
  2496.  
  2497. function parabola(x)
  2498. {
  2499.    return 4.0 * x * (1.0 - x);
  2500. }
  2501.  
  2502. function min(a, b)
  2503. {
  2504.    return (a < b) ? a : b;
  2505. }
  2506.  
  2507. function max(a, b)
  2508. {
  2509.    return (a > b) ? a : b;
  2510. }
  2511.  
  2512. function noise( x )
  2513. {
  2514.    function grad(i, j, x, y)
  2515.    {
  2516.        var h = 7 * i + 131 * j;
  2517.        h = (h << 13) ^ h;
  2518.        h = (h * (h * h * 15731 + 789221) + 1376312589);
  2519.  
  2520.        var rx = (h & 0x20000000) ? x : -x;
  2521.        var ry = (h & 0x10000000) ? y : -y;
  2522.  
  2523.        return rx + ry;
  2524.    }
  2525.  
  2526.    var i = [ Math.floor(x[0]), Math.floor(x[1]) ];
  2527.    var f = [ x[0] - i[0], x[1] - i[1] ];
  2528.    var w = [ f[0]*f[0]*(3.0-2.0*f[0]), f[1]*f[1]*(3.0-2.0*f[1]) ];
  2529.  
  2530.    var a = grad( i[0]+0, i[1]+0, f[0]+0.0, f[1]+0.0 );
  2531.    var b = grad( i[0]+1, i[1]+0, f[0]-1.0, f[1]+0.0 );
  2532.    var c = grad( i[0]+0, i[1]+1, f[0]+0.0, f[1]-1.0 );
  2533.    var d = grad( i[0]+1, i[1]+1, f[0]-1.0, f[1]-1.0 );
  2534.  
  2535.    return a + (b-a)*w[0] + (c-a)*w[1] + (a-b-c+d)*w[0]*w[1];
  2536. }//==============================================================================
  2537. //
  2538. // piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  2539. //
  2540. // piVecTypes
  2541. //
  2542. //==============================================================================
  2543.  
  2544.  
  2545. function vec3( a, b, c )
  2546. {
  2547.    return [ a, b, c ];
  2548. }
  2549.  
  2550. function add( a, b )
  2551. {
  2552.    return [ a[0]+b[0], a[1]+b[1], a[2]+b[2] ];
  2553. }
  2554.  
  2555. function sub( a, b )
  2556. {
  2557.    return [ a[0]-b[0], a[1]-b[1], a[2]-b[2] ];
  2558. }
  2559.  
  2560. function mul( a, s )
  2561. {
  2562.    return [ a[0]*s, a[1]*s, a[2]*s ];
  2563. }
  2564.  
  2565. function cross( a, b )
  2566. {
  2567.    return [ a[1]*b[2] - a[2]*b[1],
  2568.             a[2]*b[0] - a[0]*b[2],
  2569.             a[0]*b[1] - a[1]*b[0] ];
  2570. }
  2571.  
  2572. function dot( a, b )
  2573. {
  2574.    return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
  2575. }
  2576.  
  2577. function normalize( v )
  2578. {
  2579.    var is = 1.0 / Math.sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
  2580.    return [ v[0]*is, v[1]*is, v[2]*is ];
  2581. }
  2582.  
  2583. function createCirclePoint( cen, uuu, vvv, rad, s, t )
  2584. {
  2585.    return [ cen[0] + rad*(uuu[0]*s + vvv[0]*t),
  2586.             cen[1] + rad*(uuu[1]*s + vvv[1]*t),
  2587.             cen[2] + rad*(uuu[2]*s + vvv[2]*t) ];
  2588. }
  2589.  
  2590. function createTangent( a, b, c )
  2591. {
  2592.    var cb = normalize( [ c[0]-b[0], c[1]-b[1], c[2]-b[2] ] );
  2593.    var ba = normalize( [ b[0]-a[0], b[1]-a[1], b[2]-a[2] ] );
  2594.    return normalize( [ ba[0]+cb[0], ba[1]+cb[1], ba[2]+cb[2] ] );
  2595.  
  2596. }
  2597.  
  2598. //===================================
  2599.  
  2600. function vec4( a, b, c, d )
  2601. {
  2602.    return [ a, b, c, d ];
  2603. }
  2604.  
  2605. function getXYZ( v )
  2606. {
  2607.    return [ v[0], v[1], v[2] ];
  2608. }
  2609.  
  2610. //===================================
  2611.  
  2612. function setIdentity()
  2613. {
  2614.    return [ 1.0, 0.0, 0.0, 0.0,
  2615.             0.0, 1.0, 0.0, 0.0,
  2616.             0.0, 0.0, 1.0, 0.0,
  2617.             0.0, 0.0, 0.0, 1.0 ];
  2618. }
  2619.  
  2620. function setRotationX( t )
  2621. {
  2622.    var sint = Math.sin(t);
  2623.    var cost = Math.cos(t);
  2624.  
  2625.    return [ 1.0,   0.0,   0.0, 0.0,
  2626.             0.0,  cost, -sint, 0.0,
  2627.             0.0,  sint,  cost, 0.0,
  2628.             0.0,   0.0,   0.0, 1.0 ];
  2629. }
  2630.  
  2631. function setRotationY( t )
  2632. {
  2633.    var sint = Math.sin(t);
  2634.    var cost = Math.cos(t);
  2635.  
  2636.    return [ cost, 0.0, -sint, 0.0,
  2637.              0.0, 1.0,   0.0, 0.0,
  2638.             sint, 0.0,  cost, 0.0,
  2639.              0.0, 0.0,   0.0, 1.0 ];
  2640. }
  2641.  
  2642. function extractRotationEuler( m)
  2643. {
  2644.    var res = [];
  2645.    if (m[0] == 1.0)
  2646.    {
  2647.        res[0] = Math.atan2(m[2], m[11]);
  2648.        res[1] = 0.0;
  2649.        res[2] = 0.0;
  2650.  
  2651.    }
  2652.    else if (m[0] == -1.0)
  2653.    {
  2654.        res[0] = Math.atan2( m[2], m[11]);
  2655.        res[1] = 0.0;
  2656.        res[2] = 0.0;
  2657.    }
  2658.    else
  2659.    {
  2660.        res[0] = Math.atan2( -m[9], m[10]);
  2661.        res[1] = Math.atan2( m[8], Math.sqrt(m[9]*m[9] + m[10]*m[10]));
  2662.        res[2] = Math.atan2( m[4], m[0]);
  2663.    }
  2664.    return res;
  2665. }
  2666.  
  2667. function setFromQuaternion( q )
  2668. {
  2669.    var ww = q[3]*q[3];
  2670.    var xx = q[0]*q[0];
  2671.    var yy = q[1]*q[1];
  2672.    var zz = q[2]*q[2];
  2673.  
  2674.    return [ ww+xx-yy-zz,                   2.0*(q[0]*q[1] - q[3]*q[2]), 2.0*(q[0]*q[2] + q[3]*q[1]), 0.0,
  2675.               2.0*(q[0]*q[1] + q[3]*q[2]),   ww-xx+yy-zz,                 2.0*(q[1]*q[2] - q[3]*q[0]), 0.0,
  2676.               2.0*(q[0]*q[2] - q[3]*q[1]),   2.0*(q[1]*q[2] + q[3]*q[0]), ww-xx-yy+zz,                 0.0,
  2677.               0.0,                           0.0,                         0.0,                         1.0 ];
  2678. }
  2679.  
  2680. function setPerspective( fovy, aspect, znear, zfar )
  2681. {
  2682.    var tan = Math.tan(fovy * Math.PI/180.0);
  2683.    var x = 1.0 / (tan*aspect);
  2684.    var y = 1.0 / (tan);
  2685.    var c = -(zfar + znear) / ( zfar - znear);
  2686.    var d = -(2.0 * zfar * znear) / (zfar - znear);
  2687.  
  2688.    return [ x,    0.0,  0.0,  0.0,
  2689.             0.0,  y,    0.0,  0.0,
  2690.             0.0,  0.0,  c,     d,
  2691.             0.0,  0.0, -1.0,  0.0 ];
  2692. }
  2693.  
  2694. function setLookAt( eye, tar, up )
  2695. {
  2696.    var dir = [ -tar[0]+eye[0], -tar[1]+eye[1], -tar[2]+eye[2] ];
  2697.  
  2698. var m00 = dir[2]*up[1] - dir[1]*up[2];
  2699.    var m01 = dir[0]*up[2] - dir[2]*up[0];
  2700.    var m02 = dir[1]*up[0] - dir[0]*up[1];
  2701.    var im = 1.0/Math.sqrt( m00*m00 + m01*m01 + m02*m02 );
  2702.    m00 *= im;
  2703.    m01 *= im;
  2704.    m02 *= im;
  2705.  
  2706. var m04 = m02*dir[1] - m01*dir[2];
  2707.    var m05 = m00*dir[2] - m02*dir[0];
  2708.    var m06 = m01*dir[0] - m00*dir[1];
  2709.    im = 1.0/Math.sqrt( m04*m04 + m05*m05 + m06*m06 );
  2710.    m04 *= im;
  2711.    m05 *= im;
  2712.    m06 *= im;
  2713.  
  2714. var m08 = dir[0];
  2715. var m09 = dir[1];
  2716. var m10 = dir[2];
  2717.    im = 1.0/Math.sqrt( m08*m08 + m09*m09 + m10*m10 );
  2718.    m08 *= im;
  2719.    m09 *= im;
  2720.    m10 *= im;
  2721.  
  2722. var m03 = -(m00*eye[0] + m01*eye[1] + m02*eye[2] );
  2723. var m07 = -(m04*eye[0] + m05*eye[1] + m06*eye[2] );
  2724. var m11 = -(m08*eye[0] + m09*eye[1] + m10*eye[2] );
  2725.  
  2726.    return [ m00, m01, m02, m03,
  2727.             m04, m05, m06, m07,
  2728.             m08, m09, m10, m11,
  2729.             0.0, 0.0, 0.0, 1.0 ];
  2730. }
  2731.  
  2732.  
  2733. function setOrtho( left, right, bottom, top, znear, zfar )
  2734. {
  2735.   var x = 2.0 / (right - left);
  2736.   var y = 2.0 / (top - bottom);
  2737.   var a = (right + left) / (right - left);
  2738.   var b = (top + bottom) / (top - bottom);
  2739.   var c = -2.0 / (zfar - znear);
  2740.   var d = -(zfar + znear) / ( zfar - znear);
  2741.  
  2742.   return [  x, 0.0, 0.0,   a,
  2743.           0.0,   y, 0.0,   b,
  2744.           0.0, 0.0,   c,   d,
  2745.           0.0, 0.0, 0.0, 1.0 ];
  2746. }
  2747.  
  2748. function setTranslation( p )
  2749. {
  2750.    return [ 1.0, 0.0, 0.0, p[0],
  2751.             0.0, 1.0, 0.0, p[1],
  2752.             0.0, 0.0, 1.0, p[2],
  2753.             0.0, 0.0, 0.0, 1.0 ];
  2754. }
  2755.  
  2756. function setScale( s )
  2757. {
  2758.    return [ s[0], 0.0,  0.0,  0.0,
  2759.             0.0,  s[1], 0.0,  0.0,
  2760.             0.0,  0.0,  s[2], 0.0,
  2761.             0.0,  0.0,  0.0,  1.0];
  2762. }
  2763.  
  2764. function setProjection( fov, znear, zfar )
  2765. {
  2766.    var x = 2.0 / (fov[3]+fov[2]);
  2767.    var y = 2.0 / (fov[0]+fov[1]);
  2768.    var a = (fov[3]-fov[2]) / (fov[3]+fov[2]);
  2769.    var b = (fov[0]-fov[1]) / (fov[0]+fov[1]);
  2770.    var c = -(zfar + znear) / ( zfar - znear);
  2771.    var d = -(2.0*zfar*znear) / (zfar - znear);
  2772.    return [   x, 0.0,    a, 0.0,
  2773.             0.0,   y,    b, 0.0,
  2774.             0.0, 0.0,    c,   d,
  2775.             0.0, 0.0, -1.0, 0.0 ];
  2776.   // inverse is:
  2777.   //return mat4x4( 1.0/x, 0.0f,  0.0f,   a/x,
  2778.   //               0.0f,  1.0/y, 0.0f,   b/x,
  2779.   //               0.0f,  0.0f,  0.0f,   -1.0,
  2780.   //               0.0f,  0.0f,  1.0f/d, c/d );
  2781. }
  2782.  
  2783.  
  2784. function invertFast( m )
  2785. {
  2786.    var inv = [
  2787.  
  2788.             m[5]  * m[10] * m[15] -
  2789.             m[5]  * m[11] * m[14] -
  2790.             m[9]  * m[6]  * m[15] +
  2791.             m[9]  * m[7]  * m[14] +
  2792.             m[13] * m[6]  * m[11] -
  2793.             m[13] * m[7]  * m[10],
  2794.  
  2795.             -m[1]  * m[10] * m[15] +
  2796.              m[1]  * m[11] * m[14] +
  2797.              m[9]  * m[2] * m[15] -
  2798.              m[9]  * m[3] * m[14] -
  2799.              m[13] * m[2] * m[11] +
  2800.              m[13] * m[3] * m[10],
  2801.  
  2802.             m[1]  * m[6] * m[15] -
  2803.             m[1]  * m[7] * m[14] -
  2804.             m[5]  * m[2] * m[15] +
  2805.             m[5]  * m[3] * m[14] +
  2806.             m[13] * m[2] * m[7] -
  2807.             m[13] * m[3] * m[6],
  2808.  
  2809.             -m[1] * m[6] * m[11] +
  2810.              m[1] * m[7] * m[10] +
  2811.              m[5] * m[2] * m[11] -
  2812.              m[5] * m[3] * m[10] -
  2813.              m[9] * m[2] * m[7] +
  2814.              m[9] * m[3] * m[6],
  2815.  
  2816.             -m[4]  * m[10] * m[15] +
  2817.              m[4]  * m[11] * m[14] +
  2818.              m[8]  * m[6]  * m[15] -
  2819.              m[8]  * m[7]  * m[14] -
  2820.              m[12] * m[6]  * m[11] +
  2821.              m[12] * m[7]  * m[10],
  2822.  
  2823.             m[0]  * m[10] * m[15] -
  2824.             m[0]  * m[11] * m[14] -
  2825.             m[8]  * m[2] * m[15] +
  2826.             m[8]  * m[3] * m[14] +
  2827.             m[12] * m[2] * m[11] -
  2828.             m[12] * m[3] * m[10],
  2829.  
  2830.             -m[0]  * m[6] * m[15] +
  2831.              m[0]  * m[7] * m[14] +
  2832.              m[4]  * m[2] * m[15] -
  2833.              m[4]  * m[3] * m[14] -
  2834.              m[12] * m[2] * m[7] +
  2835.              m[12] * m[3] * m[6],
  2836.  
  2837.  
  2838.             m[0] * m[6] * m[11] -
  2839.             m[0] * m[7] * m[10] -
  2840.             m[4] * m[2] * m[11] +
  2841.             m[4] * m[3] * m[10] +
  2842.             m[8] * m[2] * m[7] -
  2843.             m[8] * m[3] * m[6],
  2844.  
  2845.  
  2846.             m[4]  * m[9] * m[15] -
  2847.             m[4]  * m[11] * m[13] -
  2848.             m[8]  * m[5] * m[15] +
  2849.             m[8]  * m[7] * m[13] +
  2850.             m[12] * m[5] * m[11] -
  2851.             m[12] * m[7] * m[9],
  2852.  
  2853.  
  2854.  
  2855.             -m[0]  * m[9] * m[15] +
  2856.              m[0]  * m[11] * m[13] +
  2857.              m[8]  * m[1] * m[15] -
  2858.              m[8]  * m[3] * m[13] -
  2859.              m[12] * m[1] * m[11] +
  2860.              m[12] * m[3] * m[9],
  2861.  
  2862.              m[0]  * m[5] * m[15] -
  2863.              m[0]  * m[7] * m[13] -
  2864.              m[4]  * m[1] * m[15] +
  2865.              m[4]  * m[3] * m[13] +
  2866.              m[12] * m[1] * m[7] -
  2867.              m[12] * m[3] * m[5],
  2868.  
  2869.              -m[0] * m[5] * m[11] +
  2870.               m[0] * m[7] * m[9] +
  2871.               m[4] * m[1] * m[11] -
  2872.               m[4] * m[3] * m[9] -
  2873.               m[8] * m[1] * m[7] +
  2874.               m[8] * m[3] * m[5],
  2875.  
  2876.              -m[4]  * m[9] * m[14] +
  2877.               m[4]  * m[10] * m[13] +
  2878.               m[8]  * m[5] * m[14] -
  2879.               m[8]  * m[6] * m[13] -
  2880.               m[12] * m[5] * m[10] +
  2881.               m[12] * m[6] * m[9],
  2882.  
  2883.              m[0]  * m[9] * m[14] -
  2884.              m[0]  * m[10] * m[13] -
  2885.              m[8]  * m[1] * m[14] +
  2886.              m[8]  * m[2] * m[13] +
  2887.              m[12] * m[1] * m[10] -
  2888.              m[12] * m[2] * m[9],
  2889.  
  2890.              -m[0]  * m[5] * m[14] +
  2891.               m[0]  * m[6] * m[13] +
  2892.               m[4]  * m[1] * m[14] -
  2893.               m[4]  * m[2] * m[13] -
  2894.               m[12] * m[1] * m[6] +
  2895.               m[12] * m[2] * m[5],
  2896.  
  2897.              m[0] * m[5] * m[10] -
  2898.              m[0] * m[6] * m[9] -
  2899.              m[4] * m[1] * m[10] +
  2900.              m[4] * m[2] * m[9] +
  2901.              m[8] * m[1] * m[6] -
  2902.              m[8] * m[2] * m[5] ];
  2903.  
  2904.    var det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
  2905.  
  2906.    det = 1.0/det;
  2907.  
  2908.    for( var i = 0; i<16; i++ ) inv[i] = inv[i] * det;
  2909.  
  2910.    return inv;
  2911. }
  2912.  
  2913. function matMul( a, b )
  2914. {
  2915.    var res = [];
  2916.    for( var i=0; i<4; i++ )
  2917.    {
  2918.        var x = a[4*i+0];
  2919.        var y = a[4*i+1];
  2920.        var z = a[4*i+2];
  2921.        var w = a[4*i+3];
  2922.  
  2923.        res[4*i+0] = x * b[ 0] + y * b[ 4] + z * b[ 8] + w * b[12];
  2924.        res[4*i+1] = x * b[ 1] + y * b[ 5] + z * b[ 9] + w * b[13];
  2925.        res[4*i+2] = x * b[ 2] + y * b[ 6] + z * b[10] + w * b[14];
  2926.        res[4*i+3] = x * b[ 3] + y * b[ 7] + z * b[11] + w * b[15];
  2927.    }
  2928.  
  2929.    return res;
  2930. }
  2931.  
  2932. function matMulpoint( m, v )
  2933. {
  2934.    return [ m[0]*v[0] + m[1]*v[1] + m[ 2]*v[2] + m[ 3],
  2935.             m[4]*v[0] + m[5]*v[1] + m[ 6]*v[2] + m[ 7],
  2936.             m[8]*v[0] + m[9]*v[1] + m[10]*v[2] + m[11] ];
  2937. }
  2938.  
  2939. function matMulvec( m, v )
  2940. {
  2941.    return [ m[0]*v[0] + m[1]*v[1] + m[ 2]*v[2],
  2942.             m[4]*v[0] + m[5]*v[1] + m[ 6]*v[2],
  2943.             m[8]*v[0] + m[9]*v[1] + m[10]*v[2] ];
  2944. }
  2945.  
  2946.  
  2947. function bound3( infi )
  2948. {
  2949.    return [ infi, -infi, infi, -infi, infi, -infi ];
  2950. }
  2951.  
  2952. function bound3_include( a, p )
  2953. {
  2954.    return [
  2955.        (p[0]<a[0]) ? p[0] : a[0],
  2956.        (p[0]>a[1]) ? p[0] : a[1],
  2957.        (p[1]<a[2]) ? p[1] : a[2],
  2958.        (p[1]>a[3]) ? p[1] : a[3],
  2959.        (p[2]<a[4]) ? p[2] : a[4],
  2960.        (p[2]>a[5]) ? p[2] : a[5] ];
  2961. }
  2962.  
  2963. function bound3_center( b )
  2964. {
  2965.    return [ 0.5*(b[0]+b[1]),
  2966.             0.5*(b[2]+b[3]),
  2967.             0.5*(b[4]+b[5]) ];
  2968. }
  2969.  
  2970. function bound3_radius( b )
  2971. {
  2972.    return [ 0.5*(b[1]-b[0]),
  2973.             0.5*(b[3]-b[2]),
  2974.             0.5*(b[5]-b[4]) ];
  2975. }
  2976. //==============================================================================
  2977. //
  2978. // piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  2979. //
  2980. // piWebVR
  2981. //
  2982. //==============================================================================
  2983.  
  2984. function WebVR( isVREnabledCallback, canvasElement )
  2985. {
  2986.    isVREnabledCallback(false);
  2987.    /*
  2988.  
  2989.  
  2990.    this.mSupportVR = false;
  2991.    this.mHMD = null;
  2992.  
  2993.    var me = this;
  2994.    var listVRDisplays = function (vrdevs) {
  2995.        for (var i = 0; i < vrdevs.length; i++)
  2996.        {
  2997.            if (vrdevs[i] instanceof VRDisplay)
  2998.            {
  2999.                me.mHMD = vrdevs[i];
  3000.                console.log("WebVR is available.");
  3001.                console.log(me.mHMD);
  3002.                break;
  3003.            }
  3004.        }
  3005.  
  3006.        isVREnabledCallback(true);
  3007.        me.mSupportVR = true;
  3008.    }
  3009.  
  3010.    if (navigator.getVRDisplays)
  3011.    {
  3012.        navigator.getVRDisplays().then(listVRDisplays);
  3013.    }
  3014.  
  3015.    isVREnabledCallback(false);
  3016.    this.mCanvas = canvasElement;
  3017.    */
  3018. }
  3019.  
  3020. WebVR.prototype.IsSupported = function()
  3021. {
  3022.    return false;
  3023.    //return this.mSupportVR;
  3024. }
  3025.  
  3026. WebVR.prototype.GetData = function( id )
  3027. {
  3028.    return {};
  3029.    /*
  3030.    var frameData = new VRFrameData();
  3031.    var s = this.mHMD.getFrameData(frameData);
  3032.    var ss = frameData.pose;
  3033.    
  3034.    var fovL = this.mHMD.getEyeParameters("left");
  3035.    var fovR = this.mHMD.getEyeParameters( "right" );
  3036.  
  3037.    // camera info
  3038.    var cPos = vec3(0.0, 0.0, 0.0);
  3039.    if (ss.position)
  3040.        cPos = vec3(-ss.position[0], -ss.position[1], -ss.position[2]);
  3041.    var rot = vec4(0.0, 0.0, 0.0, 0.0);
  3042.    if (ss.orientation)
  3043.        rot = vec4(ss.orientation[0], ss.orientation[1], ss.orientation[2], ss.orientation[3]);
  3044.    var cRot = setFromQuaternion(rot);
  3045.    var cTra = setTranslation(cPos);
  3046.    var cMat = matMul(invertFast(cRot), cTra);
  3047.    
  3048.    // per eye info
  3049.    var lTra = setTranslation( vec3(-fovL.offset[0], -fovL.offset[1], -fovL.offset[2]) );
  3050.    var lMat = matMul(lTra, cMat);
  3051.    var lPrj = [ Math.tan( fovL.fieldOfView.upDegrees * Math.PI/180.0),
  3052.                 Math.tan(fovL.fieldOfView.downDegrees * Math.PI / 180.0),
  3053.                 Math.tan(fovL.fieldOfView.leftDegrees * Math.PI / 180.0),
  3054.                 Math.tan(fovL.fieldOfView.rightDegrees * Math.PI / 180.0)];
  3055.  
  3056.    var rTra = setTranslation(vec3(-fovR.offset[0], -fovR.offset[1], -fovR.offset[2]));
  3057.    var rMat = matMul(rTra, cMat);
  3058.    var rPrj = [Math.tan(fovR.fieldOfView.upDegrees * Math.PI / 180.0),
  3059.                 Math.tan(fovR.fieldOfView.downDegrees * Math.PI / 180.0),
  3060.                 Math.tan(fovR.fieldOfView.leftDegrees * Math.PI / 180.0),
  3061.                 Math.tan(fovR.fieldOfView.rightDegrees * Math.PI / 180.0)];
  3062.  
  3063.    return {
  3064.        mCamera   : { mCamera: cMat },
  3065.        mLeftEye  : { mVP:[0,0,fovL.renderWidth,fovL.renderHeight], mProjection:lPrj, mCamera:lMat },
  3066.        mRightEye : { mVP:[fovR.renderWidth/2,0,fovR.renderWidth,fovR.renderHeight], mProjection:rPrj, mCamera:rMat }
  3067.           };
  3068.    */
  3069. }
  3070.  
  3071. WebVR.prototype.Enable = function( id )
  3072. {
  3073.    /*
  3074.    this.mHMD.requestPresent([{ source: this.mCanvas }]).then(
  3075.        function ()
  3076.        {
  3077.        },
  3078.        function (err)
  3079.        {
  3080.            console.log("webVR : requestPresent failed.");
  3081.        }
  3082.    );
  3083.    */
  3084. }
  3085.  
  3086. WebVR.prototype.Disable = function( id )
  3087. {
  3088.    /*
  3089.    if (!this.mHMD.isPresenting)
  3090.    {
  3091.        return;
  3092.    }
  3093.  
  3094.    this.mHMD.exitPresent().then(
  3095.        function ()
  3096.        {
  3097.        },
  3098.        function (err)
  3099.        {
  3100.            console.log("webVR : exitPresent failed.");
  3101.        }
  3102.    );
  3103.    */
  3104. }
  3105.  
  3106. WebVR.prototype.RequestAnimationFrame = function (id)
  3107. {
  3108.    //this.mHMD.requestAnimationFrame(id);
  3109. }
  3110.  
  3111. WebVR.prototype.IsPresenting = function (id)
  3112. {
  3113.    /*
  3114.    if (this.mHMD.isPresenting)
  3115.    {
  3116.        return true;
  3117.    }
  3118.    */
  3119.    return false;
  3120. }
  3121.  
  3122. WebVR.prototype.Finish = function (id)
  3123. {
  3124.    /*
  3125.    if (this.mHMD.isPresenting)
  3126.    {
  3127.        this.mHMD.submitFrame();
  3128.    }
  3129.    */
  3130. }
  3131.  
  3132. //==============================================================================
  3133. //
  3134. // piLibs 2015-2017 - http://www.iquilezles.org/www/material/piLibs/piLibs.htm
  3135. //
  3136. // piWebUtils
  3137. //
  3138. //==============================================================================
  3139.  
  3140.  
  3141. // RequestAnimationFrame
  3142. window.requestAnimFrame = ( function () { return window.requestAnimationFrame    || window.webkitRequestAnimationFrame ||
  3143.                                                 window.mozRequestAnimationFrame || window.oRequestAnimationFrame ||
  3144.                                                 window.msRequestAnimationFrame  || function( cb ) { window.setTimeout(cb,1000/60); };
  3145.                                        } )();
  3146.  
  3147. // performance.now
  3148. window.getRealTime = ( function() { if ("performance" in window ) return function() { return window.performance.now(); }
  3149.                                                                  return function() { return (new Date()).getTime(); }
  3150.                                  } )();
  3151.  
  3152. window.URL = window.URL || window.webkitURL;
  3153.  
  3154. navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
  3155.  
  3156. function htmlEntities(str)
  3157. {
  3158.    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g,'&apos;');
  3159. }
  3160.  
  3161. function piDisableTouch()
  3162. {
  3163.    document.body.addEventListener('touchstart', function(e){ e.preventDefault(); });
  3164. }
  3165.  
  3166. var piGetTime = function ( timestamp )
  3167. {
  3168.    if (timestamp == 0)
  3169.        return "";
  3170.    return new Date(timestamp * 1000).toISOString().substr(0, 10);
  3171. }
  3172.  
  3173. function piGetCoords( obj )
  3174. {
  3175.    var x = 0;
  3176.    var y = 0;
  3177.    do
  3178.    {
  3179.         x += obj.offsetLeft;
  3180.         y += obj.offsetTop;
  3181.    }while( obj = obj.offsetParent );
  3182.  
  3183.    return { mX:x, mY:y };
  3184. }
  3185.  
  3186. function piGetMouseCoords( ev, canvasElement )
  3187. {
  3188.    var pos = piGetCoords(canvasElement );
  3189.    var mcx =                        (ev.pageX - pos.mX) * canvasElement.width / canvasElement.offsetWidth;
  3190.    var mcy = canvasElement.height - (ev.pageY - pos.mY) * canvasElement.height / canvasElement.offsetHeight;
  3191.  
  3192.    return { mX: mcx, mY: mcy };
  3193.  
  3194. }
  3195.  
  3196. function piGetSourceElement( e )
  3197. {
  3198.    var ele = null;
  3199.    if( e.target )     ele = e.target;
  3200.    if( e.srcElement ) ele = e.srcElement;
  3201.    return ele;
  3202. }
  3203.  
  3204. function piRequestFullScreen( ele )
  3205. {
  3206.    if( ele==null ) ele =   document.documentElement;
  3207.         if( ele.requestFullscreen       ) ele.requestFullscreen();
  3208.    else if( ele.msRequestFullscreen     ) ele.msRequestFullscreen();
  3209.    else if( ele.mozRequestFullScreen    ) ele.mozRequestFullScreen();
  3210.    else if( ele.webkitRequestFullscreen ) ele.webkitRequestFullscreen( Element.ALLOW_KEYBOARD_INPUT );
  3211. }
  3212.  
  3213. function piIsFullScreen()
  3214. {
  3215.    return document.fullscreen || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement || false;
  3216. }
  3217.  
  3218. function piExitFullScreen()
  3219. {
  3220.       if( document.exitFullscreen       ) document.exitFullscreen();
  3221.  else if( document.msExitFullscreen     ) document.msExitFullscreen();
  3222.  else if( document.mozCancelFullScreen  ) document.mozCancelFullScreen();
  3223.  else if( document.webkitExitFullscreen ) document.webkitExitFullscreen();
  3224. }
  3225.  
  3226. function piIsMobile()
  3227. {
  3228.    return (navigator.userAgent.match(/Android/i) ||
  3229.            navigator.userAgent.match(/webOS/i) ||
  3230.            navigator.userAgent.match(/iPhone/i) ||
  3231.            navigator.userAgent.match(/iPad/i) ||
  3232.            navigator.userAgent.match(/iPod/i) ||
  3233.            navigator.userAgent.match(/BlackBerry/i) ||
  3234.            navigator.userAgent.match(/Windows Phone/i)) ? true : false;
  3235. }
  3236.  
  3237. function piCreateGlContext( cv, useAlpha, useDepth, usePreserveBuffer, useSupersampling )
  3238. {
  3239.    var opts = { alpha: useAlpha,
  3240.                 depth: useDepth,
  3241.                 stencil: false,
  3242.                 premultipliedAlpha: false,
  3243.                 antialias: useSupersampling,
  3244.                 preserveDrawingBuffer: usePreserveBuffer,
  3245.                 powerPreference: "high-performance" }; // "low_power", "high_performance", "default"
  3246.  
  3247.    var gl = null;
  3248.    if( gl === null) gl = cv.getContext( "webgl2", opts );
  3249.    if( gl === null) gl = cv.getContext( "experimental-webgl2", opts );
  3250.    if( gl === null) gl = cv.getContext( "webgl", opts );
  3251.    if( gl === null) gl = cv.getContext( "experimental-webgl", opts );
  3252.  
  3253.    return gl;
  3254. }
  3255.  
  3256. function piCreateAudioContext()
  3257. {
  3258.    var res = null;
  3259.    try
  3260.    {
  3261.        if( window.AudioContext ) res = new AudioContext();
  3262.        if( res==null && window.webkitAudioContext ) res = new webkitAudioContext();
  3263.    }
  3264.    catch( e )
  3265.    {
  3266.        res = null;
  3267.    }
  3268.    return res;
  3269. }
  3270.  
  3271. function piHexColorToRGB(str) // "#ff3041"
  3272. {
  3273.    var rgb = parseInt(str.slice(1), 16);
  3274.    var r = (rgb >> 16) & 255;
  3275.    var g = (rgb >> 8) & 255;
  3276.    var b = (rgb >> 0) & 255;
  3277.    return [r, g, b];
  3278. }
  3279.  
  3280. function piCreateFPSCounter()
  3281. {
  3282.    var mFrame;
  3283.    var mTo;
  3284.    var mFPS;
  3285.  
  3286.    var iReset = function( time )
  3287.    {
  3288.        mFrame = 0;
  3289.        mTo = time;
  3290.        mFPS = 60.0;
  3291.    }
  3292.  
  3293.    var iCount = function( time )
  3294.    {
  3295.        mFrame++;
  3296.  
  3297.        if( (time-mTo)>500.0 )
  3298.        {
  3299.            mFPS = 1000.0*mFrame/(time-mTo);
  3300.            mFrame = 0;
  3301.            mTo = time;
  3302.            return true;
  3303.        }
  3304.        return false;
  3305.    }
  3306.  
  3307.    var iGetFPS = function()
  3308.    {
  3309.        return mFPS;
  3310.    }
  3311.    
  3312.    return { Reset : iReset, Count : iCount, GetFPS : iGetFPS };
  3313. }
  3314.  
  3315. function piCanMediaRecorded(canvas)
  3316. {
  3317.    if (typeof window.MediaRecorder !== 'function' || typeof canvas.captureStream !== 'function') {
  3318.        return false;
  3319.    }
  3320.    return true;
  3321. }
  3322.  
  3323. function piCreateMediaRecorder(isRecordingCallback, canvas)
  3324. {
  3325.    if (piCanMediaRecorded(canvas) == false)
  3326.    {
  3327.        return null;
  3328.    }
  3329.    
  3330.    var options = { audioBitsPerSecond : 0, videoBitsPerSecond : 8000000 };
  3331.     if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) options.mimeType = 'video/webm;codecs=h264';
  3332.    else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9' )) options.mimeType = 'video/webm;codecs=vp9';
  3333.    else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8' )) options.mimeType = 'video/webm;codecs=vp8';
  3334.    else                                                              options.mimeType = 'video/webm;';
  3335.  
  3336.    var mediaRecorder = new MediaRecorder(canvas.captureStream(), options);
  3337.    var chunks = [];
  3338.    
  3339.    mediaRecorder.ondataavailable = function(e)
  3340.    {
  3341.        if (e.data.size > 0)
  3342.        {
  3343.            chunks.push(e.data);
  3344.        }
  3345.    };
  3346.    mediaRecorder.onstart = function(){
  3347.        isRecordingCallback( true );
  3348.    };
  3349.    
  3350.    mediaRecorder.onstop = function()
  3351.    {
  3352.         isRecordingCallback( false );
  3353.         let blob     = new Blob(chunks, {type: "video/webm"});
  3354.         chunks       = [];
  3355.         let videoURL = window.URL.createObjectURL(blob);
  3356.         let url      = window.URL.createObjectURL(blob);
  3357.         let a        = document.createElement("a");
  3358.         document.body.appendChild(a);
  3359.         a.style      = "display: none";
  3360.         a.href       = url;
  3361.         a.download   = "capture.webm";
  3362.         a.click();
  3363.         window.URL.revokeObjectURL(url);
  3364.     };
  3365.    
  3366.    return mediaRecorder;
  3367. }
  3368.  
  3369. function piExportToEXR(width, height, numComponents, type, bytes)
  3370. {
  3371.    var bytesPerComponent = 0;
  3372.    if      (type=="Uint")   bytesPerComponent = 4;
  3373.    else if (type=="Half")   bytesPerComponent = 2;
  3374.    else if (type=="Float")  bytesPerComponent = 4;
  3375.  
  3376.    var tHeader = 258 + (18 * numComponents + 1);
  3377.    var tTable = 8 * height;
  3378.    var tScanlines = height * (4 + 4 + (numComponents * bytesPerComponent * width));
  3379.    var tTotal = tHeader + tTable + tScanlines;
  3380.  
  3381.    //console.log("    header size = " + tHeader);
  3382.    //console.log("    table size = " + tTable);
  3383.    //console.log("    scanlines size = " + tScanlines);
  3384.    //console.log("    total = " + tTotal);
  3385.  
  3386.    var buffer = new ArrayBuffer(tTotal);
  3387.    var data = new DataView(buffer);
  3388.  
  3389.    // Header
  3390.    {
  3391.        // Header : 4 bytes -> 0x76, 0x2f, 0x31, 0x01
  3392.        var c = 0;
  3393.        data.setUint8 (c++, 0x76);
  3394.        data.setUint8 (c++, 0x2f);
  3395.        data.setUint8 (c++, 0x31);
  3396.        data.setUint8 (c++, 0x01);
  3397.  
  3398.        // Version : 4 bytes -> 2, 0, 0, 0
  3399.        data.setUint8 (c++, 0x02);
  3400.        data.setUint8 (c++, 0x0);
  3401.        data.setUint8 (c++, 0x0);
  3402.        data.setUint8 (c++, 0x0);
  3403.        
  3404.        // Write channel info
  3405.        // Write attribute name : "channels"
  3406.            data.setUint8 (c++, 0x63);
  3407.            data.setUint8 (c++, 0x68);
  3408.            data.setUint8 (c++, 0x61);
  3409.            data.setUint8 (c++, 0x6e);
  3410.            data.setUint8 (c++, 0x6e);
  3411.            data.setUint8 (c++, 0x65);
  3412.            data.setUint8 (c++, 0x6c);
  3413.            data.setUint8 (c++, 0x73);
  3414.            data.setUint8 (c++, 0x0);
  3415.  
  3416.            // Write attribute type : "chlist"
  3417.            data.setUint8 (c++, 0x63);
  3418.            data.setUint8 (c++, 0x68);
  3419.            data.setUint8 (c++, 0x6c);
  3420.            data.setUint8 (c++, 0x69);
  3421.            data.setUint8 (c++, 0x73);
  3422.            data.setUint8 (c++, 0x74);
  3423.            data.setUint8 (c++, 0x00);
  3424.  
  3425.            // Write attribute size : 18 x 3 + 1 = 55
  3426.            var attribSize = 18 * numComponents + 1;
  3427.            data.setUint8 (c++, attribSize);
  3428.            data.setUint8 (c++, 0x00);
  3429.            data.setUint8 (c++, 0x00);
  3430.            data.setUint8 (c++, 0x00);
  3431.  
  3432.            var i;
  3433.            for (i = 0; i < numComponents; i++)
  3434.            {
  3435.                // Attribute : "B" (42) "G" (47) "R" (52)
  3436.                if (i==0)       data.setUint8 (c++, 0x42);
  3437.                else if (i==1)  data.setUint8 (c++, 0x47);
  3438.                else if (i==2)  data.setUint8 (c++, 0x52);
  3439.                data.setUint8 (c++, 0x00);
  3440.                
  3441.                // Value : Float (2), Half (1), Uint (0)
  3442.                if      (type=="Uint")   data.setUint8 (c++, 0x00);
  3443.                else if (type=="Half")   data.setUint8 (c++, 0x01);
  3444.                else if (type=="Float")  data.setUint8 (c++, 0x02);
  3445.                data.setUint8 (c++, 0x00);
  3446.                data.setUint8 (c++, 0x00);
  3447.                data.setUint8 (c++, 0x00);
  3448.  
  3449.                // Plinear
  3450.                data.setUint8 (c++, 0x01);
  3451.  
  3452.                // Reserved
  3453.                data.setUint8 (c++, 0x00);
  3454.                data.setUint8 (c++, 0x00);
  3455.                data.setUint8 (c++, 0x00);
  3456.  
  3457.                // X sampling
  3458.                data.setUint8 (c++, 0x01);
  3459.                data.setUint8 (c++, 0x00);
  3460.                data.setUint8 (c++, 0x00);
  3461.                data.setUint8 (c++, 0x00);
  3462.                
  3463.                // Y sampling
  3464.                data.setUint8 (c++, 0x01);
  3465.                data.setUint8 (c++, 0x00);
  3466.                data.setUint8 (c++, 0x00);
  3467.                data.setUint8 (c++, 0x00);
  3468.            }
  3469.            // End attribute
  3470.            data.setUint8 (c++, 0x00);
  3471.    
  3472.        // Write attribute name : "compression"
  3473.            data.setUint8 (c++, 0x63);
  3474.            data.setUint8 (c++, 0x6f);
  3475.            data.setUint8 (c++, 0x6d);
  3476.            data.setUint8 (c++, 0x70);
  3477.            data.setUint8 (c++, 0x72);
  3478.            data.setUint8 (c++, 0x65);
  3479.            data.setUint8 (c++, 0x73);
  3480.            data.setUint8 (c++, 0x73);
  3481.            data.setUint8 (c++, 0x69);
  3482.            data.setUint8 (c++, 0x6f);
  3483.            data.setUint8 (c++, 0x6e);
  3484.            data.setUint8 (c++, 0x00);
  3485.  
  3486.            // Write attribute type : "compression"
  3487.            data.setUint8 (c++, 0x63);
  3488.            data.setUint8 (c++, 0x6f);
  3489.            data.setUint8 (c++, 0x6d);
  3490.            data.setUint8 (c++, 0x70);
  3491.            data.setUint8 (c++, 0x72);
  3492.            data.setUint8 (c++, 0x65);
  3493.            data.setUint8 (c++, 0x73);
  3494.            data.setUint8 (c++, 0x73);
  3495.            data.setUint8 (c++, 0x69);
  3496.            data.setUint8 (c++, 0x6f);
  3497.            data.setUint8 (c++, 0x6e);
  3498.            data.setUint8 (c++, 0x00);
  3499.  
  3500.            // Write attribute size : "1"
  3501.            data.setUint8 (c++, 0x01);
  3502.            data.setUint8 (c++, 0x00);
  3503.            data.setUint8 (c++, 0x00);
  3504.            data.setUint8 (c++, 0x00);
  3505.  
  3506.            // Write attribute value : "0" (None)
  3507.            data.setUint8 (c++, 0x00);
  3508.  
  3509.        // datawindow
  3510.            data.setUint8 (c++, 0x64);
  3511.            data.setUint8 (c++, 0x61);
  3512.            data.setUint8 (c++, 0x74);
  3513.            data.setUint8 (c++, 0x61);
  3514.            data.setUint8 (c++, 0x57);
  3515.            data.setUint8 (c++, 0x69);
  3516.            data.setUint8 (c++, 0x6e);
  3517.            data.setUint8 (c++, 0x64);
  3518.            data.setUint8 (c++, 0x6f);
  3519.            data.setUint8 (c++, 0x77);
  3520.            data.setUint8 (c++, 0x00);
  3521.  
  3522.            // box2i
  3523.            data.setUint8 (c++, 0x62);
  3524.            data.setUint8 (c++, 0x6f);
  3525.            data.setUint8 (c++, 0x78);
  3526.            data.setUint8 (c++, 0x32);
  3527.            data.setUint8 (c++, 0x69);
  3528.            data.setUint8 (c++, 0x00);
  3529.  
  3530.            // size 16
  3531.            data.setUint8 (c++, 0x10);
  3532.            data.setUint8 (c++, 0x00);
  3533.            data.setUint8 (c++, 0x00);
  3534.            data.setUint8 (c++, 0x00);
  3535.  
  3536.            // value 0 0 3 2
  3537.            data.setUint8 (c++, 0x00);
  3538.            data.setUint8 (c++, 0x00);
  3539.            data.setUint8 (c++, 0x00);
  3540.            data.setUint8 (c++, 0x00);
  3541.  
  3542.            data.setUint8 (c++, 0x00);
  3543.            data.setUint8 (c++, 0x00);
  3544.            data.setUint8 (c++, 0x00);
  3545.            data.setUint8 (c++, 0x00);
  3546.            
  3547.            data.setUint32 (c, width-1, true);
  3548.            c += 4;
  3549.            
  3550.            data.setUint32 (c, height-1, true);
  3551.            c += 4;
  3552.  
  3553.        // displayWindow
  3554.            data.setUint8 (c++, 0x64);
  3555.            data.setUint8 (c++, 0x69);
  3556.            data.setUint8 (c++, 0x73);
  3557.            data.setUint8 (c++, 0x70);
  3558.            data.setUint8 (c++, 0x6c);
  3559.            data.setUint8 (c++, 0x61);
  3560.            data.setUint8 (c++, 0x79);
  3561.            data.setUint8 (c++, 0x57);
  3562.            data.setUint8 (c++, 0x69);
  3563.            data.setUint8 (c++, 0x6e);
  3564.            data.setUint8 (c++, 0x64);
  3565.            data.setUint8 (c++, 0x6f);
  3566.            data.setUint8 (c++, 0x77);
  3567.            data.setUint8 (c++, 0x00);
  3568.  
  3569.            // box2i
  3570.            data.setUint8 (c++, 0x62);
  3571.            data.setUint8 (c++, 0x6f);
  3572.            data.setUint8 (c++, 0x78);
  3573.            data.setUint8 (c++, 0x32);
  3574.            data.setUint8 (c++, 0x69);
  3575.            data.setUint8 (c++, 0x00);
  3576.  
  3577.            // size 16
  3578.            data.setUint8 (c++, 0x10);
  3579.            data.setUint8 (c++, 0x00);
  3580.            data.setUint8 (c++, 0x00);
  3581.            data.setUint8 (c++, 0x00);
  3582.  
  3583.            // value 0 0 3 2
  3584.            data.setUint8 (c++, 0x00);
  3585.            data.setUint8 (c++, 0x00);
  3586.            data.setUint8 (c++, 0x00);
  3587.            data.setUint8 (c++, 0x00);
  3588.            
  3589.            data.setUint8 (c++, 0x00);
  3590.            data.setUint8 (c++, 0x00);
  3591.            data.setUint8 (c++, 0x00);
  3592.            data.setUint8 (c++, 0x00);
  3593.            
  3594.            data.setUint32 (c, width-1, true);
  3595.            c += 4;
  3596.            
  3597.            data.setUint32 (c, height-1, true);
  3598.            c += 4;
  3599.  
  3600.        // lineOrder
  3601.            data.setUint8 (c++, 0x6c);
  3602.            data.setUint8 (c++, 0x69);
  3603.            data.setUint8 (c++, 0x6e);
  3604.            data.setUint8 (c++, 0x65);
  3605.            data.setUint8 (c++, 0x4f);
  3606.            data.setUint8 (c++, 0x72);
  3607.            data.setUint8 (c++, 0x64);
  3608.            data.setUint8 (c++, 0x65);
  3609.            data.setUint8 (c++, 0x72);
  3610.            data.setUint8 (c++, 0x00);
  3611.            
  3612.            // lineOrder
  3613.            data.setUint8 (c++, 0x6c);
  3614.            data.setUint8 (c++, 0x69);
  3615.            data.setUint8 (c++, 0x6e);
  3616.            data.setUint8 (c++, 0x65);
  3617.            data.setUint8 (c++, 0x4f);
  3618.            data.setUint8 (c++, 0x72);
  3619.            data.setUint8 (c++, 0x64);
  3620.            data.setUint8 (c++, 0x65);
  3621.            data.setUint8 (c++, 0x72);
  3622.            data.setUint8 (c++, 0x00);
  3623.            
  3624.            // size
  3625.            data.setUint8 (c++, 0x01);
  3626.            data.setUint8 (c++, 0x00);
  3627.            data.setUint8 (c++, 0x00);
  3628.            data.setUint8 (c++, 0x00);
  3629.            
  3630.            // value
  3631.            data.setUint8 (c++, 0x00);
  3632.  
  3633.        // PixelAspectRatio
  3634.            data.setUint8 (c++, 0x70);
  3635.            data.setUint8 (c++, 0x69);
  3636.            data.setUint8 (c++, 0x78);
  3637.            data.setUint8 (c++, 0x65);
  3638.            data.setUint8 (c++, 0x6c);
  3639.            data.setUint8 (c++, 0x41);
  3640.            data.setUint8 (c++, 0x73);
  3641.            data.setUint8 (c++, 0x70);
  3642.            data.setUint8 (c++, 0x65);
  3643.            data.setUint8 (c++, 0x63);
  3644.            data.setUint8 (c++, 0x74);
  3645.            data.setUint8 (c++, 0x52);
  3646.            data.setUint8 (c++, 0x61);
  3647.            data.setUint8 (c++, 0x74);
  3648.            data.setUint8 (c++, 0x69);
  3649.            data.setUint8 (c++, 0x6f);
  3650.            data.setUint8 (c++, 0x00);
  3651.  
  3652.            // float
  3653.            data.setUint8 (c++, 0x66);
  3654.            data.setUint8 (c++, 0x6c);
  3655.            data.setUint8 (c++, 0x6f);
  3656.            data.setUint8 (c++, 0x61);
  3657.            data.setUint8 (c++, 0x74);
  3658.            data.setUint8 (c++, 0x00);
  3659.        
  3660.            // size 4
  3661.            data.setUint8 (c++, 0x04);
  3662.            data.setUint8 (c++, 0x00);
  3663.            data.setUint8 (c++, 0x00);
  3664.            data.setUint8 (c++, 0x00);
  3665.  
  3666.            // value 1.0
  3667.            data.setUint8 (c++, 0x00);
  3668.            data.setUint8 (c++, 0x00);
  3669.            data.setUint8 (c++, 0x80);
  3670.            data.setUint8 (c++, 0x3f);
  3671.        
  3672.        // screenWindowCenter
  3673.            data.setUint8 (c++, 0x73);
  3674.            data.setUint8 (c++, 0x63);
  3675.            data.setUint8 (c++, 0x72);
  3676.            data.setUint8 (c++, 0x65);
  3677.            data.setUint8 (c++, 0x65);
  3678.            data.setUint8 (c++, 0x6e);
  3679.            data.setUint8 (c++, 0x57);
  3680.            data.setUint8 (c++, 0x69);
  3681.            data.setUint8 (c++, 0x6e);
  3682.            data.setUint8 (c++, 0x64);
  3683.            data.setUint8 (c++, 0x6f);
  3684.            data.setUint8 (c++, 0x77);
  3685.            data.setUint8 (c++, 0x43);
  3686.            data.setUint8 (c++, 0x65);
  3687.            data.setUint8 (c++, 0x6e);
  3688.            data.setUint8 (c++, 0x74);
  3689.            data.setUint8 (c++, 0x65);
  3690.            data.setUint8 (c++, 0x72);
  3691.            data.setUint8 (c++, 0x00);
  3692.  
  3693.            // v2f
  3694.            data.setUint8 (c++, 0x76);
  3695.            data.setUint8 (c++, 0x32);
  3696.            data.setUint8 (c++, 0x66);
  3697.            data.setUint8 (c++, 0x00);
  3698.  
  3699.            // size 8
  3700.            data.setUint8 (c++, 0x08);
  3701.            data.setUint8 (c++, 0x00);
  3702.            data.setUint8 (c++, 0x00);
  3703.            data.setUint8 (c++, 0x00);
  3704.  
  3705.            // value 0 0
  3706.            data.setUint8 (c++, 0x00);
  3707.            data.setUint8 (c++, 0x00);
  3708.            data.setUint8 (c++, 0x00);
  3709.            data.setUint8 (c++, 0x00);
  3710.            
  3711.            data.setUint8 (c++, 0x00);
  3712.            data.setUint8 (c++, 0x00);
  3713.            data.setUint8 (c++, 0x00);
  3714.            data.setUint8 (c++, 0x00);
  3715.  
  3716.        // screenWindowWidth
  3717.            data.setUint8 (c++, 0x73);
  3718.            data.setUint8 (c++, 0x63);
  3719.            data.setUint8 (c++, 0x72);
  3720.            data.setUint8 (c++, 0x65);
  3721.            data.setUint8 (c++, 0x65);
  3722.            data.setUint8 (c++, 0x6e);
  3723.            data.setUint8 (c++, 0x57);
  3724.            data.setUint8 (c++, 0x69);
  3725.            data.setUint8 (c++, 0x6e);
  3726.            data.setUint8 (c++, 0x64);
  3727.            data.setUint8 (c++, 0x6f);
  3728.            data.setUint8 (c++, 0x77);
  3729.            data.setUint8 (c++, 0x57);
  3730.            data.setUint8 (c++, 0x69);
  3731.            data.setUint8 (c++, 0x64);
  3732.            data.setUint8 (c++, 0x74);
  3733.            data.setUint8 (c++, 0x68);
  3734.            data.setUint8 (c++, 0x00);
  3735.            
  3736.            // float
  3737.            data.setUint8 (c++, 0x66);
  3738.            data.setUint8 (c++, 0x6c);
  3739.            data.setUint8 (c++, 0x6f);
  3740.            data.setUint8 (c++, 0x61);
  3741.            data.setUint8 (c++, 0x74);
  3742.            data.setUint8 (c++, 0x00);
  3743.  
  3744.            // size
  3745.            data.setUint8 (c++, 0x04);
  3746.            data.setUint8 (c++, 0x00);
  3747.            data.setUint8 (c++, 0x00);
  3748.            data.setUint8 (c++, 0x00);
  3749.  
  3750.            // value
  3751.            data.setUint8 (c++, 0x00);
  3752.            data.setUint8 (c++, 0x00);
  3753.            data.setUint8 (c++, 0x80);
  3754.            data.setUint8 (c++, 0x3f);
  3755.  
  3756.        // End of header
  3757.        data.setUint8 (c++, 0x00);
  3758.    }
  3759.    //console.log("header size = " + c);
  3760.  
  3761.    // Scanline table
  3762.    var initc = c + height * 8;
  3763.    for (var scanline = 0 ; scanline < height ; scanline ++)
  3764.    {
  3765.        var jump = initc + scanline * (8 + width * bytesPerComponent * numComponents);
  3766.        data.setUint32 (c, jump, true);
  3767.        c += 4;
  3768.  
  3769.        data.setUint32 (c, 0x00, true);
  3770.        c += 4;
  3771.    }
  3772.    //console.log("header + scanlines table size = " + c);
  3773.  
  3774.    // Scanlines
  3775.    for (var scanline = 0 ; scanline < height ; scanline ++)
  3776.    {
  3777.        // Scanline
  3778.        data.setUint32(c, scanline, true);
  3779.        c += 4;
  3780.  
  3781.        // size 24
  3782.        var size = width * numComponents * bytesPerComponent;
  3783.        data.setUint32(c, size, true);
  3784.        c += 4;
  3785.  
  3786.        var numComponentsSource = 4; // number of components in the SOURCE image
  3787.        for (var component = 0; component < numComponents ; component ++)
  3788.        {
  3789.            for (var pixel = 0 ; pixel < width ; pixel ++)
  3790.            {
  3791.                // flip vertical, so we read OpenGL buffers without JS image flipping
  3792.                var v = bytes[(height-1-scanline) * width *numComponentsSource + pixel * numComponentsSource + (2-component)];
  3793.                if      (type=="Float") data.setFloat32(c, v, true);
  3794.                else if (type=="Half")  data.setUint16(c, v, true);
  3795.  
  3796.                c += bytesPerComponent;
  3797.            }
  3798.        }
  3799.    }
  3800.    //console.log("total size = " + c);
  3801.    return new Blob([buffer], {type: 'application/octet-stream'});
  3802. }
  3803.  
  3804.  
  3805. function piExportToWAV(numSamples, rate, bits, numChannels, words)
  3806. {
  3807.    let numBytes = numSamples * numChannels * bits/8;
  3808.  
  3809.    let buffer = new ArrayBuffer(44 + numBytes);
  3810.    let data = new DataView(buffer);
  3811.  
  3812.    {
  3813.        data.setUint32( 0, 0x46464952, true );  // RIFF
  3814.        data.setUint32( 4, numBytes + 36, true);
  3815.        {
  3816.            data.setUint32( 8, 0x45564157, true );  // WAV_WAVE
  3817.            data.setUint32( 12, 0x20746D66, true );  // WAV_FMT
  3818.            {
  3819.                data.setUint32( 16, 16, true);
  3820.                data.setUint16( 20, 1, true ); // WAV_FORMAT_PCM
  3821.                data.setUint16( 22, numChannels, true);
  3822.                data.setUint32( 24, rate, true);
  3823.                data.setUint32( 28, rate*numChannels*bits / 8, true);
  3824.                data.setUint16( 32, numChannels*bits / 8, true);
  3825.                data.setUint16( 34, bits, true);
  3826.            }
  3827.  
  3828.            data.setUint32( 36, 0x61746164, true);  // WAV_DATA
  3829.            {
  3830.                data.setUint32( 40, numBytes, true);
  3831.                let numWords = numSamples * numChannels;
  3832.                for(let i=0; i<numWords; i++ )
  3833.                {
  3834.                    data.setInt16( 44 + i*2, words[i], true );
  3835.                }
  3836.            }
  3837.        }
  3838.    }
  3839.  
  3840.  
  3841.    //console.log("total size = " + c);
  3842.    return new Blob([buffer], {type: 'application/octet-stream'});
  3843. }
  3844.  
  3845. function piTriggerDownload(name, blob)
  3846. {
  3847.    let url = URL.createObjectURL(blob);
  3848.    let aElement = document.createElement("a");
  3849.    aElement.href     = url;
  3850.    aElement.target   = "_self";
  3851.    aElement.download = name;
  3852.    document.body.appendChild(aElement);
  3853.    aElement.click();
  3854.    document.body.removeChild(aElement);
  3855. }</script>
  3856.    <script>"use strict"
  3857.  
  3858. function bufferID_to_assetID( id )
  3859. {
  3860.    if( id===0 ) return '4dXGR8';
  3861.    if( id===1 ) return 'XsXGR8';
  3862.    if( id===2 ) return '4sXGR8';
  3863.    if( id===3 ) return 'XdfGR8';
  3864.    return 'none';
  3865. }
  3866. function assetID_to_bufferID( id )
  3867. {
  3868.    if( id==='4dXGR8' ) return 0;
  3869.    if( id==='XsXGR8' ) return 1;
  3870.    if( id==='4sXGR8' ) return 2;
  3871.    if( id==='XdfGR8' ) return 3;
  3872.    return -1;
  3873. }
  3874.  
  3875. function assetID_to_cubemapBuferID( id )
  3876. {
  3877.    if( id==='4dX3Rr' ) return 0;
  3878.    return -1;
  3879. }
  3880. function cubamepBufferID_to_assetID( id )
  3881. {
  3882.    if( id===0 ) return '4dX3Rr';
  3883.    return 'none';
  3884. }
  3885.  
  3886. function EffectPass( renderer, is20, isLowEnd, hasShaderTextureLOD, callback, obj, forceMuted, forcePaused, outputGainNode, copyProgram, id, effect  )
  3887. {
  3888.    this.mID = id;
  3889.    this.mInputs  = [null, null, null, null ];
  3890.    this.mOutputs = [null, null, null, null ];
  3891.    this.mSource = null;
  3892.  
  3893.    this.mGainNode = outputGainNode;
  3894.    this.mSoundShaderCompiled = false;
  3895.  
  3896.    this.mEffect = effect;
  3897.    this.mRenderer = renderer;
  3898.    this.mProgramCopy = copyProgram;
  3899.    this.mCompilationTime = 0;
  3900.  
  3901.    this.mType = "none";
  3902.    this.mName = "none";
  3903.    this.mFrame = 0;
  3904.  
  3905.    this.mShaderTextureLOD = hasShaderTextureLOD;
  3906.    this.mIs20 = is20;
  3907.    this.mIsLowEnd = isLowEnd;
  3908.    this.mTextureCallbackFun = callback;
  3909.    this.mTextureCallbackObj = obj;
  3910.    this.mForceMuted = forceMuted;
  3911.    this.mForcePaused = forcePaused;
  3912. }
  3913.  
  3914. EffectPass.prototype.MakeHeader_Image = function()
  3915. {
  3916.    let header = "";
  3917.  
  3918.    header += "#define HW_PERFORMANCE " + ((this.mIsLowEnd===true)?"0":"1") + "\n";
  3919.  
  3920.    header += "uniform vec3      iResolution;\n" +
  3921.              "uniform float     iTime;\n" +
  3922.              "uniform float     iChannelTime[4];\n" +
  3923.              "uniform vec4      iMouse;\n" +
  3924.              "uniform vec4      iDate;\n" +
  3925.              "uniform float     iSampleRate;\n" +
  3926.              "uniform vec3      iChannelResolution[4];\n" +
  3927.              "uniform int       iFrame;\n" +
  3928.              "uniform float     iTimeDelta;\n" +
  3929.              "uniform float     iFrameRate;\n";
  3930.  
  3931.    for( let i=0; i<this.mInputs.length; i++ )
  3932.    {
  3933.        let inp = this.mInputs[i];
  3934.  
  3935.        // old API
  3936.             if( inp===null )                  header += "uniform sampler2D iChannel" + i + ";\n";
  3937.        else if( inp.mInfo.mType==="cubemap" ) header += "uniform samplerCube iChannel" + i + ";\n";
  3938.        else if( inp.mInfo.mType==="volume"  ) header += "uniform sampler3D iChannel" + i + ";\n";
  3939.        else                                   header += "uniform sampler2D iChannel" + i + ";\n";
  3940.  
  3941.        // new API (see shadertoy.com/view/wtdGW8)
  3942.        header += "uniform struct {\n";
  3943.             if( inp===null )                  header += "  sampler2D";
  3944.        else if( inp.mInfo.mType==="cubemap" ) header += "  samplerCube";
  3945.        else if( inp.mInfo.mType==="volume"  ) header += "  sampler3D";
  3946.        else                                  header += "  sampler2D";
  3947.        header +=        " sampler;\n";
  3948.        header += "  vec3  size;\n";
  3949.        header += "  float time;\n";
  3950.        header += "  int   loaded;\n";
  3951.        header += "}iCh" + i + ";\n";
  3952.    }
  3953. header += "void mainImage( out vec4 c, in vec2 f );\n";
  3954.    header += "void st_assert( bool cond );\n";
  3955.    header += "void st_assert( bool cond, int v );\n";
  3956.  
  3957.    if( this.mIs20 )
  3958.    {
  3959.        header += "\nout vec4 shadertoy_out_color;\n" +
  3960.        "void st_assert( bool cond, int v ) {if(!cond){if(v==0)shadertoy_out_color.x=-1.0;else if(v==1)shadertoy_out_color.y=-1.0;else if(v==2)shadertoy_out_color.z=-1.0;else shadertoy_out_color.w=-1.0;}}\n" +
  3961.        "void st_assert( bool cond        ) {if(!cond)shadertoy_out_color.x=-1.0;}\n" +
  3962.        "void main( void )" +
  3963.        "{" +
  3964.            "shadertoy_out_color = vec4(1.0,1.0,1.0,1.0);" +
  3965.            "vec4 color = vec4(1e20);" +
  3966.            "mainImage( color, gl_FragCoord.xy );" +
  3967.            "if(shadertoy_out_color.x<0.0) color=vec4(1.0,0.0,0.0,1.0);" +
  3968.            "if(shadertoy_out_color.y<0.0) color=vec4(0.0,1.0,0.0,1.0);" +
  3969.            "if(shadertoy_out_color.z<0.0) color=vec4(0.0,0.0,1.0,1.0);" +
  3970.            "if(shadertoy_out_color.w<0.0) color=vec4(1.0,1.0,0.0,1.0);" +
  3971.            "shadertoy_out_color = vec4(color.xyz,1.0);" +
  3972.        "}";
  3973.    }
  3974.    else
  3975.    {
  3976.        header += "" +
  3977.        "void st_assert( bool cond, int v ) {if(!cond){if(v==0)gl_FragColor.x=-1.0;else if(v==1)gl_FragColor.y=-1.0;else if(v==2)gl_FragColor.z=-1.0;else gl_FragColor.w=-1.0;}}\n" +
  3978.        "void st_assert( bool cond        ) {if(!cond)gl_FragColor.x=-1.0;}\n" +
  3979.        "void main( void )" +
  3980.        "{" +
  3981.            "gl_FragColor = vec4(0.0,0.0,0.0,1.0);" +
  3982.            "vec4 color = vec4(1e20);" +
  3983.            "mainImage( color, gl_FragCoord.xy );" +
  3984.            "color.w = 1.0;" +
  3985.            "if(gl_FragColor.w<0.0) color=vec4(1.0,0.0,0.0,1.0);" +
  3986.            "if(gl_FragColor.x<0.0) color=vec4(1.0,0.0,0.0,1.0);" +
  3987.            "if(gl_FragColor.y<0.0) color=vec4(0.0,1.0,0.0,1.0);" +
  3988.            "if(gl_FragColor.z<0.0) color=vec4(0.0,0.0,1.0,1.0);" +
  3989.            "if(gl_FragColor.w<0.0) color=vec4(1.0,1.0,0.0,1.0);" +
  3990.            "gl_FragColor = vec4(color.xyz,1.0);"+
  3991.        "}";
  3992.    }
  3993.    header += "\n";
  3994.  
  3995.    /*
  3996.    this.mImagePassFooterVR = "\n" +
  3997.    "uniform vec4 unViewport;\n" +
  3998.    "uniform vec3 unCorners[5];\n";
  3999.    if( this.mIs20 )
  4000.        this.mImagePassFooterVR += "\nout vec4 outColor;\n";
  4001.    this.mImagePassFooterVR += "void main( void )" +
  4002.    "{" +
  4003.        "vec4 color = vec4(1e20);" +
  4004.  
  4005.        "vec3 ro = unCorners[4];" +
  4006.        "vec2 uv = (gl_FragCoord.xy - unViewport.xy)/unViewport.zw;" +
  4007.        "vec3 rd = normalize( mix( mix( unCorners[0], unCorners[1], uv.x )," +
  4008.                                  "mix( unCorners[3], unCorners[2], uv.x ), uv.y ) - ro);" +
  4009.  
  4010.        "mainVR( color, gl_FragCoord.xy-unViewport.xy, ro, rd );" +
  4011.        "color.w = 1.0;"
  4012.    if( this.mIs20 )
  4013.        this.mImagePassFooterVR +=  "outColor = color;}";
  4014.    else
  4015.        this.mImagePassFooterVR +=  "gl_FragColor = color;}";
  4016.    */
  4017.    this.mHeader = header;
  4018.    this.mHeaderLength = 0;
  4019. }
  4020.  
  4021. EffectPass.prototype.MakeHeader_Buffer = function()
  4022. {
  4023.    let header = "";
  4024.    
  4025.    header += "#define HW_PERFORMANCE " + ((this.mIsLowEnd===true)?"0":"1") + "\n";
  4026.  
  4027.    header += "uniform vec3      iResolution;\n" +
  4028.              "uniform float     iTime;\n" +
  4029.              "uniform float     iChannelTime[4];\n" +
  4030.              "uniform vec4      iMouse;\n" +
  4031.              "uniform vec4      iDate;\n" +
  4032.              "uniform float     iSampleRate;\n" +
  4033.              "uniform vec3      iChannelResolution[4];\n" +
  4034.              "uniform int       iFrame;\n" +
  4035.              "uniform float     iTimeDelta;\n" +
  4036.              "uniform float     iFrameRate;\n";
  4037.  
  4038.    for (let i = 0; i < this.mInputs.length; i++)
  4039.    {
  4040.        let inp = this.mInputs[i];
  4041.             if( inp===null )                  header += "uniform sampler2D iChannel" + i + ";\n";
  4042.        else if( inp.mInfo.mType==="cubemap" ) header += "uniform samplerCube iChannel" + i + ";\n";
  4043.        else if( inp.mInfo.mType==="volume"  ) header += "uniform sampler3D iChannel" + i + ";\n";
  4044.        else                                  header += "uniform sampler2D iChannel" + i + ";\n";
  4045.    }
  4046.  
  4047. header += "void mainImage( out vec4 c,  in vec2 f );\n"
  4048.  
  4049.    if( this.mIs20 )
  4050.        header += "\nout vec4 outColor;\n";
  4051.    header += "\nvoid main( void )\n" +
  4052.    "{" +
  4053.        "vec4 color = vec4(1e20);" +
  4054.        "mainImage( color, gl_FragCoord.xy );";
  4055.    if( this.mIs20 )
  4056.        header +="outColor = color; }";
  4057.    else
  4058.        header +="gl_FragColor = color; }";
  4059.    header += "\n";
  4060.  
  4061.    /*
  4062.    this.mImagePassFooterVR = "\n" +
  4063.    "uniform vec4 unViewport;\n" +
  4064.    "uniform vec3 unCorners[5];\n";
  4065.    if( this.mIs20 )
  4066.    this.mImagePassFooterVR += "\nout vec4 outColor;\n";
  4067.    this.mImagePassFooterVR += "\nvoid main( void )\n" +
  4068.    "{" +
  4069.        "vec4 color = vec4(1e20);" +
  4070.  
  4071.        "vec3 ro = unCorners[4];" +
  4072.        "vec2 uv = (gl_FragCoord.xy - unViewport.xy)/unViewport.zw;" +
  4073.        "vec3 rd = normalize( mix( mix( unCorners[0], unCorners[1], uv.x )," +
  4074.                                  "mix( unCorners[3], unCorners[2], uv.x ), uv.y ) - ro);" +
  4075.  
  4076.        "mainVR( color, gl_FragCoord.xy-unViewport.xy, ro, rd );";
  4077.    if( this.mIs20 )
  4078.        this.mImagePassFooterVR +="outColor = color; }";
  4079.    else
  4080.        this.mImagePassFooterVR +="gl_FragColor = color; }";
  4081.    */
  4082.    this.mHeader = header;
  4083.    this.mHeaderLength = 0;
  4084. }
  4085.  
  4086. EffectPass.prototype.MakeHeader_Cubemap = function()
  4087. {
  4088.    let header = "";
  4089.    
  4090.    header += "#define HW_PERFORMANCE " + ((this.mIsLowEnd===true)?"0":"1") + "\n";
  4091.  
  4092.    header += "uniform vec3      iResolution;\n" +
  4093.              "uniform float     iTime;\n" +
  4094.              "uniform float     iChannelTime[4];\n" +
  4095.              "uniform vec4      iMouse;\n" +
  4096.              "uniform vec4      iDate;\n" +
  4097.              "uniform float     iSampleRate;\n" +
  4098.              "uniform vec3      iChannelResolution[4];\n" +
  4099.              "uniform int       iFrame;\n" +
  4100.              "uniform float     iTimeDelta;\n" +
  4101.              "uniform float     iFrameRate;\n";
  4102.  
  4103.    for (let i = 0; i < this.mInputs.length; i++)
  4104.    {
  4105.        let inp = this.mInputs[i];
  4106.             if( inp===null )                  header += "uniform sampler2D iChannel" + i + ";\n";
  4107.        else if( inp.mInfo.mType==="cubemap" ) header += "uniform samplerCube iChannel" + i + ";\n";
  4108.        else if( inp.mInfo.mType==="volume"  ) header += "uniform sampler3D iChannel" + i + ";\n";
  4109.        else                                   header += "uniform sampler2D iChannel" + i + ";\n";
  4110.    }
  4111.  
  4112. header += "void mainCubemap( out vec4 c, in vec2 f, in vec3 ro, in vec3 rd );\n"
  4113.  
  4114.    header += "\n" +
  4115.    "uniform vec4 unViewport;\n" +
  4116.    "uniform vec3 unCorners[5];\n";
  4117.    if( this.mIs20 )
  4118.        header += "\nout vec4 outColor;\n";
  4119.    header += "\nvoid main( void )\n" +
  4120.    "{" +
  4121.        "vec4 color = vec4(1e20);" +
  4122.  
  4123.        "vec3 ro = unCorners[4];" +
  4124.        "vec2 uv = (gl_FragCoord.xy - unViewport.xy)/unViewport.zw;" +
  4125.        "vec3 rd = normalize( mix( mix( unCorners[0], unCorners[1], uv.x )," +
  4126.                                  "mix( unCorners[3], unCorners[2], uv.x ), uv.y ) - ro);" +
  4127.  
  4128.        "mainCubemap( color, gl_FragCoord.xy-unViewport.xy, ro, rd );";
  4129.    if( this.mIs20 )
  4130.        header +="outColor = color; }";
  4131.    else
  4132.        header +="gl_FragColor = color; }";
  4133.    header += "\n";
  4134.  
  4135.    this.mHeader = header;
  4136.    this.mHeaderLength = 0;
  4137. }
  4138.  
  4139. EffectPass.prototype.MakeHeader_Sound = function()
  4140. {
  4141.    let header = "";
  4142.  
  4143.    header += "#define HW_PERFORMANCE " + ((this.mIsLowEnd===true)?"0":"1") + "\n";
  4144.  
  4145.    header += "uniform float     iChannelTime[4];\n" +
  4146.              "uniform float     iTimeOffset;\n" +
  4147.              "uniform int       iSampleOffset;\n" +
  4148.              "uniform vec4      iDate;\n" +
  4149.              "uniform float     iSampleRate;\n" +
  4150.              "uniform vec3      iChannelResolution[4];\n";
  4151.  
  4152.    for (let i=0; i<this.mInputs.length; i++ )
  4153.    {
  4154.        let inp = this.mInputs[i];
  4155.  
  4156.        if( inp!==null && inp.mInfo.mType==="cubemap" )
  4157.            header += "uniform samplerCube iChannel" + i + ";\n";
  4158.        else
  4159.            header += "uniform sampler2D iChannel" + i + ";\n";
  4160.    }
  4161.    header += "\n";
  4162.    header += "vec2 mainSound( in int samp, float time );\n";
  4163.  
  4164.    if( this.mIs20 )
  4165.    {
  4166.        header += "out vec4 outColor; void main()" +
  4167.            "{" +
  4168.            "float t = iTimeOffset + ((gl_FragCoord.x-0.5) + (gl_FragCoord.y-0.5)*512.0)/iSampleRate;" +
  4169.            "int   s = iSampleOffset + int(gl_FragCoord.y-0.2)*512 + int(gl_FragCoord.x-0.2);" +
  4170.            "vec2 y = mainSound( s, t );" +
  4171.            "vec2 v  = floor((0.5+0.5*y)*65536.0);" +
  4172.            "vec2 vl =   mod(v,256.0)/255.0;" +
  4173.            "vec2 vh = floor(v/256.0)/255.0;" +
  4174.            "outColor = vec4(vl.x,vh.x,vl.y,vh.y);" +
  4175.            "}";
  4176.    }
  4177.    else
  4178.    {
  4179.        header += "void main()" +
  4180.            "{" +
  4181.            "float t = iTimeOffset + ((gl_FragCoord.x-0.5) + (gl_FragCoord.y-0.5)*512.0)/iSampleRate;" +
  4182.            "vec2 y = mainSound( 0, t );" +
  4183.            "vec2 v  = floor((0.5+0.5*y)*65536.0);" +
  4184.            "vec2 vl =   mod(v,256.0)/255.0;" +
  4185.            "vec2 vh = floor(v/256.0)/255.0;" +
  4186.            "gl_FragColor = vec4(vl.x,vh.x,vl.y,vh.y);" +
  4187.            "}";
  4188.    }
  4189.    header += "\n";
  4190.    this.mHeader = header;
  4191.    this.mHeaderLength = 0;
  4192. }
  4193.  
  4194.  
  4195. EffectPass.prototype.MakeHeader_Common = function ()
  4196. {
  4197.    let header = "";
  4198.    let headerlength = 0;
  4199.  
  4200.    header += "uniform vec4      iDate;\n" +
  4201.              "uniform float     iSampleRate;\n";
  4202.    headerlength += 2;
  4203.  
  4204.    if (this.mIs20)
  4205.    {
  4206.        header += "out vec4 outColor;\n";
  4207.        headerlength += 1;
  4208.    }
  4209.    header += "void main( void )\n";
  4210.    headerlength += 1;
  4211.  
  4212.    if (this.mIs20)
  4213.        header += "{ outColor = vec4(0.0); }";
  4214.    else
  4215.        header += "{ gl_FragColor = vec4(0.0); }";
  4216.    headerlength += 1;
  4217.    header += "\n";
  4218.    headerlength += 1;
  4219.  
  4220.    this.mHeader = header;
  4221.    this.mHeaderLength = headerlength;
  4222. }
  4223.  
  4224. EffectPass.prototype.MakeHeader = function()
  4225. {
  4226.         if( this.mType==="image" ) this.MakeHeader_Image();
  4227.    else if( this.mType==="sound" ) this.MakeHeader_Sound();
  4228.    else if( this.mType==="buffer") this.MakeHeader_Buffer();
  4229.    else if( this.mType==="common") this.MakeHeader_Common();
  4230.    else if( this.mType==="cubemap") this.MakeHeader_Cubemap();
  4231.    else console.log("ERROR 4");
  4232. }
  4233.  
  4234. EffectPass.prototype.Create_Image = function( wa )
  4235. {
  4236.    this.MakeHeader();
  4237.    this.mSampleRate = 44100;
  4238.    this.mSupportsVR = false;
  4239.    this.mProgram = null;
  4240.    this.mError = false;
  4241.    this.mErrorStr = "";
  4242.    this.mTranslatedSource = null;
  4243.    //this.mProgramVR = null;
  4244. }
  4245. EffectPass.prototype.Destroy_Image = function( wa )
  4246. {
  4247. }
  4248.  
  4249. EffectPass.prototype.Create_Buffer = function( wa )
  4250. {
  4251.    this.MakeHeader();
  4252.    this.mSampleRate = 44100;
  4253.    this.mSupportsVR = false;
  4254.    this.mProgram = null;
  4255.    this.mError = false;
  4256.    this.mErrorStr = "";
  4257.    this.mTranslatedSource = null;
  4258.    //this.mProgramVR = null;
  4259. }
  4260.  
  4261. EffectPass.prototype.Destroy_Buffer = function( wa )
  4262. {
  4263. }
  4264.  
  4265. EffectPass.prototype.Create_Cubemap = function( wa )
  4266. {
  4267.    this.MakeHeader();
  4268.    this.mSampleRate = 44100;
  4269.    this.mProgram = null;
  4270.    this.mError = false;
  4271.    this.mErrorStr = "";
  4272.    this.mTranslatedSource = null;
  4273. }
  4274.  
  4275. EffectPass.prototype.Destroy_Cubemap = function( wa )
  4276. {
  4277. }
  4278.  
  4279. EffectPass.prototype.Create_Common = function( wa )
  4280. {
  4281.    this.mProgram = null;
  4282.    this.mError = false;
  4283.    this.mErrorStr = "";
  4284.    this.MakeHeader();
  4285. }
  4286. EffectPass.prototype.Destroy_Common = function( wa )
  4287. {
  4288. }
  4289.  
  4290. EffectPass.prototype.Create_Sound = function (wa)
  4291. {
  4292.    this.MakeHeader();
  4293.  
  4294.    this.mProgram = null;
  4295.    this.mError = false;
  4296.    this.mErrorStr = "";
  4297.    this.mTranslatedSource = null;
  4298.    this.mSampleRate = 44100;
  4299.    this.mPlayTime = 60*3;
  4300.    this.mPlaySamples = this.mPlayTime*this.mSampleRate;
  4301.    this.mBuffer = wa.createBuffer( 2, this.mPlaySamples, this.mSampleRate );
  4302.  
  4303.    //-------------------
  4304.    this.mTextureDimensions = 512;
  4305.    this.mRenderTexture = this.mRenderer.CreateTexture(this.mRenderer.TEXTYPE.T2D,
  4306.                                                       this.mTextureDimensions, this.mTextureDimensions,
  4307.                                                       this.mRenderer.TEXFMT.C4I8,
  4308.                                                       this.mRenderer.FILTER.NONE,
  4309.                                                       this.mRenderer.TEXWRP.CLAMP, null);
  4310.    this.mRenderFBO = this.mRenderer.CreateRenderTarget(this.mRenderTexture, null, null, null, null, false);
  4311.  
  4312.    //-----------------------------
  4313.  
  4314.    // ArrayBufferView pixels;
  4315.    this.mTmpBufferSamples = this.mTextureDimensions*this.mTextureDimensions;
  4316.    this.mData = new Uint8Array( this.mTmpBufferSamples*4 );
  4317.  
  4318.    this.mPlaying = false;
  4319. }
  4320.  
  4321. EffectPass.prototype.Destroy_Sound = function( wa )
  4322. {
  4323.    if( this.mPlayNode!==null ) this.mPlayNode.stop();
  4324.    this.mPlayNode = null;
  4325.    this.mBuffer = null;
  4326.    this.mData = null;
  4327.  
  4328.    this.mRenderer.DestroyRenderTarget(this.mRenderFBO);
  4329.    this.mRenderer.DestroyTexture(this.mRenderTexture);
  4330. }
  4331.  
  4332. EffectPass.prototype.Create = function( passType, wa )
  4333. {
  4334.    this.mType = passType;
  4335.    this.mSource = null;
  4336.  
  4337.         if( passType==="image" ) this.Create_Image( wa );
  4338.    else if( passType==="sound" ) this.Create_Sound( wa );
  4339.    else if( passType==="buffer") this.Create_Buffer( wa );
  4340.    else if( passType==="common") this.Create_Common( wa );
  4341.    else if( passType==="cubemap") this.Create_Cubemap( wa );
  4342.    else alert("ERROR 1");
  4343. }
  4344.  
  4345. EffectPass.prototype.SetName = function (passName)
  4346. {
  4347.    this.mName = passName;
  4348. }
  4349.  
  4350. EffectPass.prototype.SetCode = function (src)
  4351. {
  4352.    this.mSource = src;
  4353. }
  4354.  
  4355. EffectPass.prototype.Destroy = function( wa )
  4356. {
  4357.    this.mSource = null;
  4358.         if( this.mType==="image" ) this.Destroy_Image( wa );
  4359.    else if( this.mType==="sound" ) this.Destroy_Sound( wa );
  4360.    else if( this.mType==="buffer") this.Destroy_Buffer( wa );
  4361.    else if( this.mType==="common") this.Destroy_Common( wa );
  4362.    else if( this.mType==="cubemap") this.Destroy_Cubemap( wa );
  4363.    else alert("ERROR 2");
  4364. }
  4365.  
  4366. EffectPass.prototype.NewShader_Sound = function( shaderCode, commonShaderCodes)
  4367. {
  4368.    let vsSource = null;
  4369.  
  4370.    if( this.mIs20 )
  4371.        vsSource = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4372.    else
  4373.        vsSource = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4374.  
  4375.    let fsSource = this.mHeader;
  4376.    for( let i=0; i<commonShaderCodes.length; i++ )
  4377.    {
  4378.        fsSource += commonShaderCodes[i]+'\n';
  4379.    }
  4380.    this.mHeaderLength = fsSource.split(/\r\n|\r|\n/).length;
  4381.    fsSource += shaderCode;
  4382.  
  4383.    this.mSoundShaderCompiled = false;
  4384.  
  4385.    return [vsSource, fsSource];
  4386. }
  4387.  
  4388. EffectPass.prototype.NewShader_Image = function ( shaderCode, commonShaderCodes )
  4389. {
  4390.    this.mSupportsVR = false;
  4391.  
  4392.    let vsSource = null;
  4393.    if( this.mIs20 )
  4394.        vsSource = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4395.    else
  4396.        vsSource = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4397.  
  4398.    let fsSource = this.mHeader;
  4399.    for (let i = 0; i < commonShaderCodes.length; i++)
  4400.    {
  4401.        fsSource += commonShaderCodes[i]+'\n';
  4402.    }
  4403.    this.mHeaderLength = fsSource.split(/\r\n|\r|\n/).length;
  4404.    fsSource += shaderCode;
  4405.  
  4406.    return [vsSource, fsSource];
  4407.  
  4408.  
  4409.    /*
  4410.    let n1 = shaderCode.indexOf("mainVR(");
  4411.    let n2 = shaderCode.indexOf("mainVR (");
  4412.    let n3 = shaderCode.indexOf("mainVR  (");
  4413.    if( n1>0 || n2>0 || n3>0 )
  4414.    {
  4415.        let vsSourceVR;
  4416.        if( this.mIs20 )
  4417.            vsSourceVR = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4418.        else
  4419.            vsSourceVR = "attribute in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4420.  
  4421.        let fsSourceVR = this.mHeader;
  4422.        for (let i = 0; i < commonShaderCodes.length; i++) {
  4423.            fsSourceVR += commonShaderCodes[i];
  4424.        }
  4425.        fsSourceVR += shaderCode;
  4426.        fsSourceVR += this.mImagePassFooterVR;
  4427.  
  4428.        let res = this.mRenderer.CreateShader(vsSource, fsSourceVR, preventCache);
  4429.        if( res.mResult == false )
  4430.        {
  4431.            return res.mInfo;
  4432.        }
  4433.        if( this.mProgramVR != null )
  4434.            this.mRenderer.DestroyShader( this.mProgramVR );
  4435.  
  4436.        this.mSupportsVR = true;
  4437.        this.mProgramVR = res;
  4438.    }
  4439.    */
  4440. }
  4441.  
  4442. EffectPass.prototype.NewShader_Cubemap = function( shaderCode, commonShaderCodes )
  4443. {
  4444.    let vsSource = null;
  4445.    if( this.mIs20 )
  4446.        vsSource = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4447.    else
  4448.        vsSource = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4449.  
  4450.    let fsSource = this.mHeader;
  4451.    for (let i = 0; i < commonShaderCodes.length; i++)
  4452.    {
  4453.        fsSource += commonShaderCodes[i]+'\n';
  4454.    }
  4455.  
  4456.    this.mHeaderLength = fsSource.split(/\r\n|\r|\n/).length;
  4457.  
  4458.    fsSource += shaderCode;
  4459.  
  4460.    return [vsSource, fsSource];
  4461. }
  4462.  
  4463. EffectPass.prototype.NewShader_Common = function (shaderCode )
  4464. {
  4465.    let vsSource = null;
  4466.    if (this.mIs20)
  4467.        vsSource = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4468.    else
  4469.        vsSource = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  4470.  
  4471.    let fsSource = this.mHeader + shaderCode;
  4472.  
  4473.    return [vsSource, fsSource];
  4474. }
  4475.  
  4476. EffectPass.prototype.NewShader = function ( commonSourceCodes, preventCache, onResolve)
  4477. {
  4478.    if( this.mRenderer===null ) return;
  4479.  
  4480.    let vs_fs = null;
  4481.  
  4482.         if( this.mType==="sound"  ) vs_fs = this.NewShader_Sound(   this.mSource, commonSourceCodes );
  4483.    else if( this.mType==="image"  ) vs_fs = this.NewShader_Image(   this.mSource, commonSourceCodes );
  4484.    else if( this.mType==="buffer" ) vs_fs = this.NewShader_Image(   this.mSource, commonSourceCodes );
  4485.    else if( this.mType==="common" ) vs_fs = this.NewShader_Common(  this.mSource,                   );
  4486.    else if( this.mType==="cubemap") vs_fs = this.NewShader_Cubemap( this.mSource, commonSourceCodes );
  4487.    else { console.log("ERROR 3: \"" + this.mType + "\""); return; }
  4488.  
  4489.    let me = this;
  4490.    this.mRenderer.CreateShader(vs_fs[0], vs_fs[1], preventCache, false,
  4491.        function (worked, info)
  4492.        {
  4493.            if (worked === true)
  4494.            {
  4495.                if (me.mType === "sound")
  4496.                {
  4497.                    me.mSoundShaderCompiled = true;
  4498.                }
  4499.  
  4500.                me.mCompilationTime = info.mTime;
  4501.                me.mError = false;
  4502.                me.mErrorStr = "No Errors";
  4503.                if (me.mProgram !== null)
  4504.                    me.mRenderer.DestroyShader(me.mProgram);
  4505.                me.mTranslatedSource = me.mRenderer.GetTranslatedShaderSource(info);
  4506.                me.mProgram = info;
  4507.            }
  4508.            else
  4509.            {
  4510.                me.mError = true;
  4511.                me.mErrorStr = info.mErrorStr;
  4512.            }
  4513.            onResolve();
  4514.        });
  4515. }
  4516.  
  4517. EffectPass.prototype.DestroyInput = function( id )
  4518. {
  4519.    if( this.mInputs[id]===null ) return;
  4520.  
  4521.    if( this.mInputs[id].mInfo.mType==="texture" )
  4522.    {
  4523.        if( this.mInputs[id].globject !== null )
  4524.            this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4525.    }
  4526.    if( this.mInputs[id].mInfo.mType==="volume" )
  4527.    {
  4528.        if( this.mInputs[id].globject !== null )
  4529.            this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4530.    }
  4531.    else if( this.mInputs[id].mInfo.mType==="webcam" )
  4532.    {
  4533.        this.mInputs[id].video.pause();
  4534.        this.mInputs[id].video.src = "";
  4535.  
  4536.        if( this.mInputs[id].video.srcObject!==null )
  4537.        {
  4538.        let tracks = this.mInputs[id].video.srcObject.getVideoTracks();
  4539.        if( tracks ) tracks[0].stop();
  4540.        }
  4541.        this.mInputs[id].video = null;
  4542.        if( this.mInputs[id].globject !== null )
  4543.            this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4544.    }
  4545.    else if( this.mInputs[id].mInfo.mType==="video" )
  4546.    {
  4547.        this.mInputs[id].video.pause();
  4548.        this.mInputs[id].video = null;
  4549.        if( this.mInputs[id].globject !== null )
  4550.            this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4551.    }
  4552.    else if( this.mInputs[id].mInfo.mType==="music" || this.mInputs[id].mInfo.mType==="musicstream")
  4553.    {
  4554.        this.mInputs[id].audio.pause();
  4555.        this.mInputs[id].audio.mSound.mFreqData = null;
  4556.        this.mInputs[id].audio.mSound.mWaveData = null;
  4557.        this.mInputs[id].audio = null;
  4558.        if( this.mInputs[id].globject !== null )
  4559.            this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4560.    }
  4561.    else if( this.mInputs[id].mInfo.mType==="cubemap" )
  4562.    {
  4563.        if( this.mInputs[id].globject !== null )
  4564.            this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4565.    }
  4566.    else if( this.mInputs[id].mInfo.mType==="keyboard" )
  4567.    {
  4568.        //if( this.mInputs[id].globject != null )
  4569.          //  this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4570.    }
  4571.    else if( this.mInputs[id].mInfo.mType==="mic" )
  4572.    {
  4573.        this.mInputs[id].mic = null;
  4574.        if( this.mInputs[id].globject !== null )
  4575.            this.mRenderer.DestroyTexture(this.mInputs[id].globject);
  4576.    }
  4577.  
  4578.    this.mInputs[id] = null;
  4579. }
  4580.  
  4581. EffectPass.prototype.TooglePauseInput = function( wa, id )
  4582. {
  4583.    var me = this;
  4584.    let inp = this.mInputs[id];
  4585.  
  4586.    if( inp===null )
  4587.    {
  4588.    }
  4589.    else if( inp.mInfo.mType==="texture" )
  4590.    {
  4591.    }
  4592.    else if( inp.mInfo.mType==="volume" )
  4593.    {
  4594.    }
  4595.    else if( inp.mInfo.mType==="video" )
  4596.    {
  4597.        if( inp.video.mPaused )
  4598.        {
  4599.            inp.video.play();
  4600.            inp.video.mPaused = false;
  4601.        }
  4602.        else
  4603.        {
  4604.            inp.video.pause();
  4605.            inp.video.mPaused = true;
  4606.        }
  4607.        return inp.video.mPaused;
  4608.    }
  4609.    else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream")
  4610.    {
  4611.        wa.resume()
  4612.        if( inp.audio.mPaused )
  4613.        {
  4614.            if( inp.loaded )
  4615.            {
  4616.                inp.audio.play();
  4617.            }
  4618.            inp.audio.mPaused = false;
  4619.        }
  4620.        else
  4621.        {
  4622.            inp.audio.pause();
  4623.            inp.audio.mPaused = true;
  4624.        }
  4625.        return inp.audio.mPaused;
  4626.    }
  4627.  
  4628.    return null;
  4629. }
  4630.  
  4631. EffectPass.prototype.StopInput = function( id )
  4632. {
  4633.    let inp = this.mInputs[id];
  4634.  
  4635.    if( inp===null )
  4636.    {
  4637.    }
  4638.    else if( inp.mInfo.mType==="texture" )
  4639.    {
  4640.    }
  4641.    else if( inp.mInfo.mType==="volume" )
  4642.    {
  4643.    }
  4644.    else if( inp.mInfo.mType==="video" )
  4645.    {
  4646.        if( inp.video.mPaused === false )
  4647.        {
  4648.            inp.video.pause();
  4649.            inp.video.mPaused = true;
  4650.        }
  4651.        return inp.video.mPaused;
  4652.    }
  4653.    else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream" )
  4654.    {
  4655.        if( inp.audio.mPaused === false )
  4656.        {
  4657.            inp.audio.pause();
  4658.            inp.audio.mPaused = true;
  4659.        }
  4660.        return inp.audio.mPaused;
  4661.    }
  4662.    return null;
  4663. }
  4664.  
  4665. EffectPass.prototype.ResumeInput = function( id )
  4666. {
  4667.    let inp = this.mInputs[id];
  4668.  
  4669.    if( inp===null )
  4670.    {
  4671.    }
  4672.    else if( inp.mInfo.mType==="texture" )
  4673.    {
  4674.    }
  4675.    else if( inp.mInfo.mType==="volume" )
  4676.    {
  4677.    }
  4678.    else if( inp.mInfo.mType==="video" )
  4679.    {
  4680.        if( inp.video.mPaused )
  4681.        {
  4682.            inp.video.play();
  4683.            inp.video.mPaused = false;
  4684.        }
  4685.        return inp.video.mPaused;
  4686.    }
  4687.    else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream" )
  4688.    {
  4689.        if( inp.audio.mPaused )
  4690.        {
  4691.            inp.audio.play();
  4692.            inp.audio.mPaused = false;
  4693.        }
  4694.        return inp.audio.mPaused;
  4695.    }
  4696.    return null;
  4697. }
  4698.  
  4699. EffectPass.prototype.RewindInput = function( wa, id )
  4700. {
  4701.    var me = this;
  4702.    let inp = this.mInputs[id];
  4703.  
  4704.    if( inp==null )
  4705.    {
  4706.    }
  4707.    else if( inp.mInfo.mType==="texture" )
  4708.    {
  4709.    }
  4710.    else if( inp.mInfo.mType==="volume" )
  4711.    {
  4712.    }
  4713.    else if( inp.mInfo.mType==="video" )
  4714.    {
  4715.        if( inp.loaded )
  4716.        {
  4717.            inp.video.currentTime = 0;
  4718.        }
  4719.    }
  4720.    else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream")
  4721.    {
  4722.        wa.resume()
  4723.        if( inp.loaded )
  4724.        {
  4725.            inp.audio.currentTime = 0;
  4726.        }
  4727.    }
  4728. }
  4729.  
  4730. EffectPass.prototype.MuteInput = function( wa, id )
  4731. {
  4732.    let inp = this.mInputs[id];
  4733.    if( inp===null ) return;
  4734.  
  4735.    if( inp.mInfo.mType==="video" )
  4736.    {
  4737.        inp.video.muted = true;
  4738.        inp.video.mMuted = true;
  4739.    }
  4740.    else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream")
  4741.    {
  4742.        if (wa !== null) inp.audio.mSound.mGain.gain.value = 0.0;
  4743.        inp.audio.mMuted = true;
  4744.    }
  4745. }
  4746.  
  4747. EffectPass.prototype.UnMuteInput = function( wa, id )
  4748. {
  4749.    let inp = this.mInputs[id];
  4750.    if( inp===null ) return;
  4751.  
  4752.    if( inp.mInfo.mType==="video" )
  4753.    {
  4754.        inp.video.muted = false;
  4755.        inp.video.mMuted = false;
  4756.    }
  4757.    else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream")
  4758.    {
  4759.        if (wa !== null) inp.audio.mSound.mGain.gain.value = 1.0;
  4760.        inp.audio.mMuted = false;
  4761.    }
  4762. }
  4763.  
  4764. EffectPass.prototype.ToggleMuteInput = function( wa, id )
  4765. {
  4766.    var me = this;
  4767.    let inp = this.mInputs[id];
  4768.    if( inp===null ) return null;
  4769.  
  4770.    if( inp.mInfo.mType==="video" )
  4771.    {
  4772.        if( inp.video.mMuted ) this.UnMuteInput(wa,id);
  4773.        else                   this.MuteInput(wa,id);
  4774.        return inp.video.mMuted;
  4775.    }
  4776.    else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream")
  4777.    {
  4778.        if( inp.audio.mMuted ) this.UnMuteInput(wa,id);
  4779.        else                   this.MuteInput(wa,id);
  4780.        return inp.audio.mMuted;
  4781.    }
  4782.  
  4783.    return null;
  4784. }
  4785.  
  4786. EffectPass.prototype.UpdateInputs = function( wa, forceUpdate, keyboard )
  4787. {
  4788.   for (let i=0; i<this.mInputs.length; i++ )
  4789.   {
  4790.        let inp = this.mInputs[i];
  4791.  
  4792.        if( inp===null )
  4793.        {
  4794.            if( forceUpdate )
  4795.            {
  4796.              if( this.mTextureCallbackFun!==null )
  4797.                  this.mTextureCallbackFun( this.mTextureCallbackObj, i, null, false, 0, 0, -1.0, this.mID );
  4798.            }
  4799.        }
  4800.        else if( inp.mInfo.mType==="texture" )
  4801.        {
  4802.            if( inp.loaded && forceUpdate )
  4803.            {
  4804.              if( this.mTextureCallbackFun!==null )
  4805.                  this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.image, true, 1, 1, -1.0, this.mID );
  4806.            }
  4807.        }
  4808.        else if( inp.mInfo.mType==="volume" )
  4809.        {
  4810.            if( inp.loaded && forceUpdate )
  4811.            {
  4812.              if( this.mTextureCallbackFun!==null )
  4813.                  this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.mPreview, true, 1, 1, -1.0, this.mID );
  4814.            }
  4815.        }
  4816.        else if( inp.mInfo.mType==="cubemap" )
  4817.        {
  4818.            if( inp.loaded && forceUpdate )
  4819.            {
  4820.                if( this.mTextureCallbackFun!==null )
  4821.                {
  4822.                    let img = (assetID_to_cubemapBuferID(inp.mInfo.mID)===-1) ? inp.image[0] : inp.mImage;
  4823.                    this.mTextureCallbackFun( this.mTextureCallbackObj, i, img, true, 2, 1, -1.0, this.mID );
  4824.                }
  4825.            }
  4826.        }
  4827.        else if( inp.mInfo.mType==="keyboard" )
  4828.        {
  4829.            if( this.mTextureCallbackFun!==null )
  4830.                this.mTextureCallbackFun( this.mTextureCallbackObj, i, {mImage:keyboard.mIcon,mData:keyboard.mData}, false, 6, 0, -1.0, this.mID );
  4831.        }
  4832.        else if( inp.mInfo.mType==="video" )
  4833.        {
  4834.            if( inp.video.readyState === inp.video.HAVE_ENOUGH_DATA )
  4835.            {
  4836.                if( this.mTextureCallbackFun!==null )
  4837.                    this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.video, false, 3, 1, -1, this.mID );
  4838.            }
  4839.        }
  4840.        else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream" )
  4841.        {
  4842.              if( inp.loaded && inp.audio.mPaused === false && inp.audio.mForceMuted === false )
  4843.              {
  4844.                  if( wa !== null )
  4845.                  {
  4846.                      inp.audio.mSound.mAnalyser.getByteFrequencyData(  inp.audio.mSound.mFreqData );
  4847.                      inp.audio.mSound.mAnalyser.getByteTimeDomainData( inp.audio.mSound.mWaveData );
  4848.                  }
  4849.  
  4850.                  if (this.mTextureCallbackFun!==null)
  4851.                  {
  4852.                           if (inp.mInfo.mType === "music")       this.mTextureCallbackFun(this.mTextureCallbackObj, i, {wave:(wa==null)?null:inp.audio.mSound.mFreqData}, false, 4, 1, inp.audio.currentTime, this.mID);
  4853.                      else if (inp.mInfo.mType === "musicstream") this.mTextureCallbackFun(this.mTextureCallbackObj, i, {wave:(wa==null)?null:inp.audio.mSound.mFreqData, info: inp.audio.soundcloudInfo}, false, 8, 1, inp.audio.currentTime, this.mID);
  4854.                  }
  4855.              }
  4856.              else if( inp.loaded===false )
  4857.              {
  4858.                  if (this.mTextureCallbackFun!==null)
  4859.                      this.mTextureCallbackFun(this.mTextureCallbackObj, i, {wave:null}, false, 4, 0, -1.0, this.mID);
  4860.              }
  4861.        }
  4862.        else if( inp.mInfo.mType==="mic" )
  4863.        {
  4864.              if( inp.loaded && inp.mForceMuted === false )
  4865.              {
  4866.                  if( wa !== null )
  4867.                  {
  4868.                      inp.mAnalyser.getByteFrequencyData(  inp.mFreqData );
  4869.                      inp.mAnalyser.getByteTimeDomainData( inp.mWaveData );
  4870.                  }
  4871.                  if( this.mTextureCallbackFun!==null )
  4872.                      this.mTextureCallbackFun( this.mTextureCallbackObj, i, {wave: ((wa==null)?null:inp.mFreqData) }, false, 5, 1, 0, this.mID );
  4873.              }
  4874.        }
  4875.        else if( inp.mInfo.mType==="buffer" )
  4876.        {
  4877.            if( inp.loaded && forceUpdate )
  4878.            {
  4879.              if( this.mTextureCallbackFun!==null )
  4880.                  this.mTextureCallbackFun( this.mTextureCallbackObj, i, {texture:inp.image, data:null}, true, 9, 1, -1.0, this.mID );
  4881.            }
  4882.        }
  4883.    }
  4884. }
  4885.  
  4886. EffectPass.prototype.Sampler2Renderer = function (sampler)
  4887. {
  4888.    let filter = this.mRenderer.FILTER.NONE;
  4889.    if (sampler.filter === "linear") filter = this.mRenderer.FILTER.LINEAR;
  4890.    if (sampler.filter === "mipmap") filter = this.mRenderer.FILTER.MIPMAP;
  4891.    let wrap = this.mRenderer.TEXWRP.REPEAT;
  4892.    if (sampler.wrap === "clamp") wrap = this.mRenderer.TEXWRP.CLAMP;
  4893.    let vflip = false;
  4894.    if (sampler.vflip === "true") vflip = true;
  4895.  
  4896.    return { mFilter: filter, mWrap: wrap, mVFlip: vflip };
  4897. }
  4898.  
  4899. EffectPass.prototype.GetSamplerVFlip = function (id)
  4900. {
  4901.    let inp = this.mInputs[id];
  4902.    return inp.mInfo.mSampler.vflip;
  4903. }
  4904.  
  4905. EffectPass.prototype.GetTranslatedShaderSource = function ()
  4906. {
  4907.    return this.mTranslatedSource;
  4908. }
  4909.  
  4910. EffectPass.prototype.SetSamplerVFlip = function (id, str)
  4911. {
  4912.    var me = this;
  4913.    var renderer = this.mRenderer;
  4914.    let inp = this.mInputs[id];
  4915.  
  4916.    let filter = false;
  4917.    if (str === "true") filter = true;
  4918.  
  4919.    if (inp === null)
  4920.    {
  4921.    }
  4922.    else if (inp.mInfo.mType === "texture")
  4923.    {
  4924.        if (inp.loaded)
  4925.        {
  4926.            renderer.SetSamplerVFlip(inp.globject, filter, inp.image);
  4927.            inp.mInfo.mSampler.vflip = str;
  4928.        }
  4929.    }
  4930.    else if (inp.mInfo.mType === "volume")
  4931.    {
  4932.    }
  4933.    else if (inp.mInfo.mType === "video")
  4934.    {
  4935.        if (inp.loaded)
  4936.        {
  4937.            renderer.SetSamplerVFlip(inp.globject, filter, inp.image);
  4938.            inp.mInfo.mSampler.vflip = str;
  4939.        }
  4940.    }
  4941.    else if (inp.mInfo.mType === "cubemap")
  4942.    {
  4943.        if (inp.loaded)
  4944.        {
  4945.            renderer.SetSamplerVFlip(inp.globject, filter, inp.image);
  4946.            inp.mInfo.mSampler.vflip = str;
  4947.        }
  4948.    }
  4949.    else if (inp.mInfo.mType === "webcam")
  4950.    {
  4951.        if (inp.loaded)
  4952.        {
  4953.            renderer.SetSamplerVFlip(inp.globject, filter, null);
  4954.            inp.mInfo.mSampler.vflip = str;
  4955.        }
  4956.    }
  4957. }
  4958.  
  4959. EffectPass.prototype.GetAcceptsVFlip = function (id)
  4960. {
  4961.    let inp = this.mInputs[id];
  4962.  
  4963.    if (inp === null) return false;
  4964.    if (inp.mInfo.mType === "texture") return true;
  4965.    if (inp.mInfo.mType === "volume") return false;
  4966.    if (inp.mInfo.mType === "video")  return true;
  4967.    if (inp.mInfo.mType === "cubemap") return true;
  4968.    if (inp.mInfo.mType === "webcam")  return true;
  4969.    if (inp.mInfo.mType === "music")  return false;
  4970.    if (inp.mInfo.mType === "musicstream") return false;
  4971.    if (inp.mInfo.mType === "mic")  return false;
  4972.    if (inp.mInfo.mType === "keyboard")  return false;
  4973.    if (inp.mInfo.mType === "buffer") return false;
  4974.    return true;
  4975. }
  4976.  
  4977. EffectPass.prototype.GetSamplerFilter = function (id)
  4978. {
  4979.    let inp = this.mInputs[id];
  4980.    if( inp===null) return;
  4981.    return inp.mInfo.mSampler.filter;
  4982. }
  4983.  
  4984. EffectPass.prototype.SetSamplerFilter = function (id, str, buffers, cubeBuffers)
  4985. {
  4986.    var me = this;
  4987.    var renderer = this.mRenderer;
  4988.    let inp = this.mInputs[id];
  4989.  
  4990.    let filter = renderer.FILTER.NONE;
  4991.    if (str === "linear") filter = renderer.FILTER.LINEAR;
  4992.    if (str === "mipmap") filter = renderer.FILTER.MIPMAP;
  4993.  
  4994.    if (inp === null)
  4995.    {
  4996.    }
  4997.    else if (inp.mInfo.mType === "texture")
  4998.    {
  4999.        if (inp.loaded)
  5000.        {
  5001.            renderer.SetSamplerFilter(inp.globject, filter, true);
  5002.            inp.mInfo.mSampler.filter = str;
  5003.        }
  5004.    }
  5005.    else if (inp.mInfo.mType === "volume")
  5006.    {
  5007.        if (inp.loaded)
  5008.        {
  5009.            renderer.SetSamplerFilter(inp.globject, filter, true);
  5010.            inp.mInfo.mSampler.filter = str;
  5011.        }
  5012.    }
  5013.    else if (inp.mInfo.mType === "video")
  5014.    {
  5015.        if (inp.loaded)
  5016.        {
  5017.            renderer.SetSamplerFilter(inp.globject, filter, true);
  5018.            inp.mInfo.mSampler.filter = str;
  5019.        }
  5020.    }
  5021.    else if (inp.mInfo.mType === "cubemap")
  5022.    {
  5023.        if (inp.loaded)
  5024.        {
  5025.            if( assetID_to_cubemapBuferID(inp.mInfo.mID)===0)
  5026.            {
  5027.                renderer.SetSamplerFilter(cubeBuffers[0].mTexture[0], filter, true);
  5028.                renderer.SetSamplerFilter(cubeBuffers[0].mTexture[1], filter, true);
  5029.                inp.mInfo.mSampler.filter = str;
  5030.            }
  5031.            else
  5032.            {
  5033.                renderer.SetSamplerFilter(inp.globject, filter, true);
  5034.                inp.mInfo.mSampler.filter = str;
  5035.            }
  5036.        }
  5037.    }
  5038.    else if (inp.mInfo.mType === "webcam")
  5039.    {
  5040.        if (inp.loaded)
  5041.        {
  5042.            renderer.SetSamplerFilter(inp.globject, filter, true);
  5043.            inp.mInfo.mSampler.filter = str;
  5044.        }
  5045.    }
  5046.    else if (inp.mInfo.mType === "buffer")
  5047.    {
  5048.        renderer.SetSamplerFilter(buffers[inp.id].mTexture[0], filter, true);
  5049.        renderer.SetSamplerFilter(buffers[inp.id].mTexture[1], filter, true);
  5050.        inp.mInfo.mSampler.filter = str;
  5051.    }
  5052.    else if (inp.mInfo.mType === "keyboard")
  5053.    {
  5054.        inp.mInfo.mSampler.filter = str;
  5055.    }
  5056. }
  5057.  
  5058. EffectPass.prototype.GetAcceptsMipmapping = function (id)
  5059. {
  5060.    let inp = this.mInputs[id];
  5061.  
  5062.    if (inp === null) return false;
  5063.    if (inp.mInfo.mType === "texture") return true;
  5064.    if (inp.mInfo.mType === "volume") return true;
  5065.    if (inp.mInfo.mType === "video")  return this.mIs20;
  5066.    if (inp.mInfo.mType === "cubemap") return true;
  5067.    if (inp.mInfo.mType === "webcam")  return this.mIs20;
  5068.    if (inp.mInfo.mType === "music")  return false;
  5069.    if (inp.mInfo.mType === "musicstream") return false;
  5070.    if (inp.mInfo.mType === "mic")  return false;
  5071.    if (inp.mInfo.mType === "keyboard")  return false;
  5072.    if (inp.mInfo.mType === "buffer") return this.mIs20;
  5073.    return false;
  5074. }
  5075.  
  5076. EffectPass.prototype.GetAcceptsLinear = function (id)
  5077. {
  5078.    let inp = this.mInputs[id];
  5079.  
  5080.    if (inp === null) return false;
  5081.    if (inp.mInfo.mType === "texture") return true;
  5082.    if (inp.mInfo.mType === "volume") return true;
  5083.    if (inp.mInfo.mType === "video")  return true;
  5084.    if (inp.mInfo.mType === "cubemap") return true;
  5085.    if (inp.mInfo.mType === "webcam")  return true;
  5086.    if (inp.mInfo.mType === "music")  return true;
  5087.    if (inp.mInfo.mType === "musicstream") return true;
  5088.    if (inp.mInfo.mType === "mic")  return true;
  5089.    if (inp.mInfo.mType === "keyboard")  return false;
  5090.    if (inp.mInfo.mType === "buffer") return true;
  5091.    return false;
  5092. }
  5093.  
  5094. EffectPass.prototype.GetAcceptsWrapRepeat = function (id)
  5095. {
  5096.    let inp = this.mInputs[id];
  5097.  
  5098.    if (inp === null) return false;
  5099.    if (inp.mInfo.mType === "texture") return true;
  5100.    if (inp.mInfo.mType === "volume") return true;
  5101.    if (inp.mInfo.mType === "video")  return this.mIs20;
  5102.    if (inp.mInfo.mType === "cubemap") return false;
  5103.    if (inp.mInfo.mType === "webcam")  return this.mIs20;
  5104.    if (inp.mInfo.mType === "music")  return false;
  5105.    if (inp.mInfo.mType === "musicstream") return false;
  5106.    if (inp.mInfo.mType === "mic")  return false;
  5107.    if (inp.mInfo.mType === "keyboard")  return false;
  5108.    if (inp.mInfo.mType === "buffer") return this.mIs20;
  5109.    return false;
  5110. }
  5111.  
  5112. EffectPass.prototype.GetSamplerWrap = function (id)
  5113. {
  5114.    return this.mInputs[id].mInfo.mSampler.wrap;
  5115. }
  5116.  
  5117. EffectPass.prototype.SetSamplerWrap = function (id, str, buffers)
  5118. {
  5119.    var me = this;
  5120.    var renderer = this.mRenderer;
  5121.    let inp = this.mInputs[id];
  5122.  
  5123.    let restr = renderer.TEXWRP.REPEAT;
  5124.    if (str === "clamp") restr = renderer.TEXWRP.CLAMP;
  5125.  
  5126.    if (inp === null)
  5127.    {
  5128.    }
  5129.    else if (inp.mInfo.mType === "texture")
  5130.    {
  5131.        if (inp.loaded)
  5132.        {
  5133.            renderer.SetSamplerWrap(inp.globject, restr);
  5134.            inp.mInfo.mSampler.wrap = str;
  5135.        }
  5136.    }
  5137.    else if (inp.mInfo.mType === "volume")
  5138.    {
  5139.        if (inp.loaded)
  5140.        {
  5141.            renderer.SetSamplerWrap(inp.globject, restr);
  5142.            inp.mInfo.mSampler.wrap = str;
  5143.        }
  5144.    }
  5145.    else if (inp.mInfo.mType === "video")
  5146.    {
  5147.        if (inp.loaded)
  5148.        {
  5149.            renderer.SetSamplerWrap(inp.globject, restr);
  5150.            inp.mInfo.mSampler.wrap = str;
  5151.        }
  5152.    }
  5153.    else if (inp.mInfo.mType === "cubemap")
  5154.    {
  5155.        if (inp.loaded)
  5156.        {
  5157.            renderer.SetSamplerWrap(inp.globject, restr);
  5158.            inp.mInfo.mSampler.wrap = str;
  5159.        }
  5160.    }
  5161.    else if (inp.mInfo.mType === "webcam")
  5162.    {
  5163.        if (inp.loaded)
  5164.        {
  5165.            renderer.SetSamplerWrap(inp.globject, restr);
  5166.            inp.mInfo.mSampler.wrap = str;
  5167.        }
  5168.    }
  5169.    else if (inp.mInfo.mType === "buffer")
  5170.    {
  5171.        renderer.SetSamplerWrap(buffers[inp.id].mTexture[0], restr);
  5172.        renderer.SetSamplerWrap(buffers[inp.id].mTexture[1], restr);
  5173.        inp.mInfo.mSampler.wrap = str;
  5174.    }
  5175. }
  5176.  
  5177.  
  5178. EffectPass.prototype.GetTexture = function( slot )
  5179. {
  5180.    let inp = this.mInputs[slot];
  5181.    if( inp===null ) return null;
  5182.    return inp.mInfo;
  5183. }
  5184.  
  5185. EffectPass.prototype.SetOutputs = function( slot, id )
  5186. {
  5187.    this.mOutputs[slot] = id;
  5188. }
  5189.  
  5190. EffectPass.prototype.SetOutputsByBufferID = function( slot, id )
  5191. {
  5192.    if( this.mType==="buffer" )
  5193.    {
  5194.        this.mOutputs[slot] = bufferID_to_assetID( id );
  5195.  
  5196.        this.mEffect.ResizeBuffer( id, this.mEffect.mXres, this.mEffect.mYres, false );
  5197.    }
  5198.    else if( this.mType==="cubemap" )
  5199.    {
  5200.        this.mOutputs[slot] = cubamepBufferID_to_assetID( id );
  5201.        this.mEffect.ResizeCubemapBuffer(id, 1024, 1024 );
  5202.    }
  5203. }
  5204.  
  5205. EffectPass.prototype.NewTexture = function( wa, slot, url, buffers, cubeBuffers, keyboard )
  5206. {
  5207.    var me = this;
  5208.    var renderer = this.mRenderer;
  5209.  
  5210.    if( renderer===null ) return;
  5211.  
  5212.    let texture = null;
  5213.  
  5214.    if( url===null || url.mType===null )
  5215.    {
  5216.        if( me.mTextureCallbackFun!==null )
  5217.            me.mTextureCallbackFun( this.mTextureCallbackObj, slot, null, true, 0, 0, -1.0, me.mID );
  5218.        me.DestroyInput( slot );
  5219.        me.mInputs[slot] = null;
  5220.        me.MakeHeader();
  5221.        return { mFailed:false, mNeedsShaderCompile:false };
  5222.    }
  5223.    else if( url.mType==="texture" )
  5224.    {
  5225.        texture = {};
  5226.        texture.mInfo = url;
  5227.        texture.globject = null;
  5228.        texture.loaded = false;
  5229.        texture.image = new Image();
  5230.        texture.image.crossOrigin = '';
  5231.        texture.image.onload = function()
  5232.        {
  5233.            let rti = me.Sampler2Renderer(url.mSampler);
  5234.  
  5235.            // O.M.G. FIX THIS
  5236.            let channels = renderer.TEXFMT.C4I8;
  5237.            if (url.mID === "Xdf3zn" || url.mID === "4sf3Rn" || url.mID === "4dXGzn" || url.mID === "4sf3Rr")
  5238.                channels = renderer.TEXFMT.C1I8;
  5239.            
  5240.            texture.globject = renderer.CreateTextureFromImage(renderer.TEXTYPE.T2D, texture.image, channels, rti.mFilter, rti.mWrap, rti.mVFlip);
  5241.  
  5242.            texture.loaded = true;
  5243.            if( me.mTextureCallbackFun!==null )
  5244.                me.mTextureCallbackFun( me.mTextureCallbackObj, slot, texture.image, true, 1, 1, -1.0, me.mID );
  5245.        }
  5246.        texture.image.src = url.mSrc;
  5247.  
  5248.  
  5249.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5250.                                                                (this.mInputs[slot].mInfo.mType!=="texture") &&
  5251.                                                                (this.mInputs[slot].mInfo.mType!=="webcam") &&
  5252.                                                                (this.mInputs[slot].mInfo.mType!=="mic") &&
  5253.                                                                (this.mInputs[slot].mInfo.mType!=="music") &&
  5254.                                                                (this.mInputs[slot].mInfo.mType!=="musicstream") &&
  5255.                                                                (this.mInputs[slot].mInfo.mType!=="keyboard") &&
  5256.                                                                (this.mInputs[slot].mInfo.mType!=="video")) };
  5257.        this.DestroyInput( slot );
  5258.        this.mInputs[slot] = texture;
  5259.        this.MakeHeader();
  5260.        return returnValue;
  5261.    }
  5262.    else if( url.mType==="volume" )
  5263.    {
  5264.        texture = {};
  5265.        texture.mInfo = url;
  5266.        texture.globject = null;
  5267.        texture.loaded = false;
  5268.        texture.mImage = { mData:null, mXres:1, mYres:0, mZres:0 };
  5269.        texture.mPreview = new Image();
  5270.        texture.mPreview.crossOrigin = '';
  5271.  
  5272.    var xmlHttp = new XMLHttpRequest();
  5273.        if( xmlHttp===null ) return { mFailed:true };
  5274.  
  5275.        xmlHttp.open('GET', url.mSrc, true);
  5276.        xmlHttp.responseType = "arraybuffer";
  5277.        xmlHttp.onerror = function()
  5278.        {
  5279.            console.log( "Error 1 loading Volume" );
  5280.        }
  5281.        xmlHttp.onload = function()
  5282.        {
  5283.            let data = xmlHttp.response;
  5284.            if (!data ) { console.log( "Error 2 loading Volume" ); return; }
  5285.  
  5286.            let file = piFile(data);
  5287.  
  5288.            let signature = file.ReadUInt32();
  5289.            texture.mImage.mXres = file.ReadUInt32();
  5290.            texture.mImage.mYres = file.ReadUInt32();
  5291.            texture.mImage.mZres = file.ReadUInt32();
  5292.            let binNumChannels = file.ReadUInt8();
  5293.            let binLayout = file.ReadUInt8();
  5294.            let binFormat = file.ReadUInt16();
  5295.            let format = renderer.TEXFMT.C1I8;
  5296.                 if( binNumChannels===1 && binFormat===0 )  format = renderer.TEXFMT.C1I8;
  5297.            else if( binNumChannels===2 && binFormat===0 )  format = renderer.TEXFMT.C2I8;
  5298.            else if( binNumChannels===3 && binFormat===0 )  format = renderer.TEXFMT.C3I8;
  5299.            else if( binNumChannels===4 && binFormat===0 )  format = renderer.TEXFMT.C4I8;
  5300.            else if( binNumChannels===1 && binFormat===10 ) format = renderer.TEXFMT.C1F32;
  5301.            else if( binNumChannels===2 && binFormat===10 ) format = renderer.TEXFMT.C2F32;
  5302.            else if( binNumChannels===3 && binFormat===10 ) format = renderer.TEXFMT.C3F32;
  5303.            else if( binNumChannels===4 && binFormat===10 ) format = renderer.TEXFMT.C4F32;
  5304.            else return;
  5305.  
  5306.            let buffer = new Uint8Array(data, 20); // skip 16 bytes (header of .bin)
  5307.  
  5308.            let rti = me.Sampler2Renderer(url.mSampler);
  5309.  
  5310.            texture.globject = renderer.CreateTexture(renderer.TEXTYPE.T3D, texture.mImage.mXres, texture.mImage.mYres, format, rti.mFilter, rti.mWrap, buffer);
  5311.  
  5312.            if( texture.globject===null )
  5313.            {
  5314.                console.log( "Error 4: loading Volume" );
  5315.                return { mFailed:true };
  5316.            }
  5317.  
  5318.            if (me.mTextureCallbackFun !== null)
  5319.            {
  5320.                me.mTextureCallbackFun( me.mTextureCallbackObj, slot, texture.mPreview, true, 1, 1, -1.0, me.mID );
  5321.            }
  5322.  
  5323.            texture.loaded = true;
  5324.  
  5325.            // load icon for it
  5326.            texture.mPreview.onload = function()
  5327.            {
  5328.                if( me.mTextureCallbackFun!==null )
  5329.                    me.mTextureCallbackFun( me.mTextureCallbackObj, slot, texture.mPreview, true, 1, 1, -1.0, me.mID );
  5330.            }
  5331.            texture.mPreview.src = url.mPreviewSrc;
  5332.        }
  5333.        xmlHttp.send("");
  5334.  
  5335.  
  5336.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5337.                                                                (this.mInputs[slot].mInfo.mType!=="volume")) };
  5338.        this.DestroyInput( slot );
  5339.        this.mInputs[slot] = texture;
  5340.        this.MakeHeader();
  5341.        return returnValue;
  5342.    }
  5343.    else if( url.mType==="cubemap" )
  5344.    {
  5345.        texture = {};
  5346.        texture.mInfo = url;
  5347.        texture.globject = null;
  5348.        texture.loaded = false;
  5349.  
  5350.        let rti = me.Sampler2Renderer(url.mSampler);
  5351.  
  5352.        if( assetID_to_cubemapBuferID(url.mID)!==-1 )
  5353.        {
  5354.            texture.mImage = new Image();
  5355.            texture.mImage.onload = function()
  5356.            {
  5357.                texture.loaded = true;
  5358.                if( me.mTextureCallbackFun!==null )
  5359.                    me.mTextureCallbackFun( me.mTextureCallbackObj, slot, texture.mImage, true, 2, 1, -1.0, me.mID );
  5360.            }
  5361.            texture.mImage.src = "/media/previz/cubemap00.png";
  5362.  
  5363.            this.mEffect.ResizeCubemapBuffer(0, 1024, 1024 );
  5364.  
  5365.        }
  5366.        else
  5367.        {
  5368.            texture.image = [ new Image(), new Image(), new Image(), new Image(), new Image(), new Image() ];
  5369.  
  5370.            let numLoaded = 0;
  5371.            for (var i=0; i<6; i++ )
  5372.            {
  5373.                texture.image[i].mId = i;
  5374.                texture.image[i].crossOrigin = '';
  5375.                texture.image[i].onload = function()
  5376.                {
  5377.                    var id = this.mId;
  5378.                    numLoaded++;
  5379.                    if( numLoaded===6 )
  5380.                    {
  5381.                        texture.globject = renderer.CreateTextureFromImage(renderer.TEXTYPE.CUBEMAP, texture.image, renderer.TEXFMT.C4I8, rti.mFilter, rti.mWrap, rti.mVFlip);
  5382.                        texture.loaded = true;
  5383.                        if (me.mTextureCallbackFun !== null)
  5384.                            me.mTextureCallbackFun(me.mTextureCallbackObj, slot, texture.image[0], true, 2, 1, -1.0, me.mID);
  5385.                    }
  5386.                }
  5387.  
  5388.                if( i === 0)
  5389.                {
  5390.                    texture.image[i].src = url.mSrc;
  5391.                }
  5392.                else
  5393.                {
  5394.                    let n = url.mSrc.lastIndexOf(".");
  5395.                    texture.image[i].src = url.mSrc.substring(0, n) + "_" + i + url.mSrc.substring(n, url.mSrc.length);
  5396.                }
  5397.            }
  5398.        }
  5399.  
  5400.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5401.                                                                (this.mInputs[slot].mInfo.mType!=="cubemap")) };
  5402.  
  5403.        this.DestroyInput( slot );
  5404.        this.mInputs[slot] = texture;
  5405.        this.MakeHeader();
  5406.        return returnValue;
  5407.    }
  5408.    else if( url.mType==="webcam" )
  5409.    {
  5410.        texture = {};
  5411.        texture.mInfo = url;
  5412.        texture.globject = null;
  5413.        texture.loaded = false;
  5414.  
  5415.        texture.video = document.createElement('video');
  5416.     texture.video.width = 320;
  5417.     texture.video.height = 240;
  5418.     texture.video.autoplay = true;
  5419.     texture.video.loop = true;
  5420.        texture.mForceMuted = this.mForceMuted;
  5421.        texture.mImage = null;
  5422.  
  5423.        let rti = me.Sampler2Renderer(url.mSampler);
  5424.  
  5425.        var loadImageInsteadOfWebCam = function()
  5426.        {
  5427.            texture.mImage = new Image();
  5428.            texture.mImage.onload = function()
  5429.            {
  5430.                texture.loaded = true;
  5431.                texture.globject = renderer.CreateTextureFromImage(renderer.TEXTYPE.T2D, texture.mImage, renderer.TEXFMT.C4I8, rti.mFilter, rti.mWrap, rti.mVFlip);
  5432.                if( me.mTextureCallbackFun!==null )
  5433.                    me.mTextureCallbackFun( me.mTextureCallbackObj, slot, texture.mImage, true, 7, 1, -1.0, me.mID );
  5434.            }
  5435.            texture.mImage.src = "/media/previz/webcam.png";
  5436.        }
  5437.        
  5438.        loadImageInsteadOfWebCam();
  5439.  
  5440.        if( typeof navigator.getUserMedia !== "undefined"  && texture.mForceMuted===false )
  5441.        {
  5442.            texture.video.addEventListener("canplay", function (e)
  5443.            {
  5444. try
  5445. {
  5446.                    texture.mImage = null;
  5447.                    if( texture.globject != null )
  5448.                        renderer.DestroyTexture( texture.globject );
  5449. texture.globject = renderer.CreateTextureFromImage(renderer.TEXTYPE.T2D, texture.video, renderer.TEXFMT.C4I8, rti.mFilter, rti.mWrap, rti.mVFlip);
  5450. texture.loaded = true;
  5451.                }
  5452.                catch(e)
  5453.                {
  5454.                    loadImageInsteadOfWebCam();
  5455.                alert( 'Your browser can not transfer webcam data to the GPU.');
  5456.                }
  5457.            } );
  5458.  
  5459.            navigator.mediaDevices.getUserMedia(
  5460.                                { "video": { width: 1280, height: 720 }, "audio": false } )
  5461.                                .then( function(stream)
  5462.                                       {
  5463.                                            texture.video.srcObject = stream;
  5464.                                   } )
  5465.                                .catch( function(error)
  5466.                                        {
  5467.                                            loadImageInsteadOfWebCam();
  5468.                                    alert( 'Unable to capture WebCam. Please reload the page.' );
  5469.                                    } );
  5470.        }
  5471.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5472.                                                                (this.mInputs[slot].mInfo.mType!=="texture") &&
  5473.                                                                (this.mInputs[slot].mInfo.mType!=="webcam") &&
  5474.                                                                (this.mInputs[slot].mInfo.mType!=="mic") &&
  5475.                                                                (this.mInputs[slot].mInfo.mType!=="music") &&
  5476.                                                                (this.mInputs[slot].mInfo.mType!=="musicstream") &&
  5477.                                                                (this.mInputs[slot].mInfo.mType!=="keyboard") &&
  5478.                                                                (this.mInputs[slot].mInfo.mType!=="video")) };
  5479.        this.DestroyInput( slot );
  5480.        this.mInputs[slot] = texture;
  5481.        this.MakeHeader();
  5482.        return returnValue;
  5483.    }
  5484.    else if( url.mType==="mic" )
  5485.    {
  5486.        texture = {};
  5487.        texture.mInfo = url;
  5488.        texture.globject = null;
  5489.        texture.loaded = false;
  5490.        texture.mForceMuted = this.mForceMuted;
  5491.        texture.mAnalyser = null;
  5492.        let num = 512;
  5493.        texture.mFreqData = new Uint8Array( num );
  5494.        texture.mWaveData = new Uint8Array( num );
  5495.  
  5496.        if( wa === null || typeof navigator.getUserMedia === "undefined" )
  5497.        {
  5498.            if( !texture.mForceMuted ) alert( "Shadertoy: Web Audio not implement in this browser" );
  5499.            texture.mForceMuted = true;
  5500.        }
  5501.  
  5502.        if( texture.mForceMuted )
  5503.        {
  5504.            texture.globject = renderer.CreateTexture(renderer.TEXTYPE.T2D, num, 2, renderer.TEXFMT.C1I8, renderer.FILTER.LINEAR, renderer.TEXWRP.CLAMP, null)
  5505.            texture.loaded = true;
  5506.        }
  5507.        else
  5508.        {
  5509.        navigator.getUserMedia( { "audio": true },
  5510.                                function(stream)
  5511.                                {
  5512.                                  texture.globject = renderer.CreateTexture(renderer.TEXTYPE.T2D, 512, 2, renderer.TEXFMT.C1I8, renderer.FILTER.LINEAR, null)
  5513.                                  texture.mic = wa.createMediaStreamSource(stream);
  5514.                                  texture.mAnalyser = wa.createAnalyser();
  5515.                                  texture.mic.connect( texture.mAnalyser );
  5516.                                  texture.loaded = true;
  5517.                            },
  5518.                                function(error)
  5519.                                {
  5520.                            alert( 'Unable open Mic. Please reload the page.' );
  5521.                            } );
  5522.        }
  5523.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5524.                                                                (this.mInputs[slot].mInfo.mType!=="texture") &&
  5525.                                                                (this.mInputs[slot].mInfo.mType!=="webcam") &&
  5526.                                                                (this.mInputs[slot].mInfo.mType!=="mic") &&
  5527.                                                                (this.mInputs[slot].mInfo.mType!=="music") &&
  5528.                                                                (this.mInputs[slot].mInfo.mType!=="musicstream") &&
  5529.                                                                (this.mInputs[slot].mInfo.mType!=="keyboard") &&
  5530.                                                                (this.mInputs[slot].mInfo.mType!=="video")) };
  5531.        this.DestroyInput( slot );
  5532.        this.mInputs[slot] = texture;
  5533.        this.MakeHeader();
  5534.        return returnValue;
  5535.    }
  5536.    else if( url.mType==="video" )
  5537.    {
  5538.     texture = {};
  5539.        texture.mInfo = url;
  5540.        texture.globject = null;
  5541.        texture.loaded = false;
  5542.        texture.video = document.createElement('video');
  5543.     texture.video.loop = true;
  5544.        texture.video.preload = "auto";
  5545.        texture.video.mPaused = this.mForcePaused;
  5546.        texture.video.mMuted = true;//this.mForceMuted;
  5547.     texture.video.muted  = true;//this.mForceMuted;
  5548.        if( this.mForceMuted===true )
  5549.            texture.video.volume = 0;
  5550.     texture.video.autoplay = false;
  5551.        texture.video.hasFalled = false;
  5552.        
  5553.        let rti = me.Sampler2Renderer(url.mSampler);
  5554.  
  5555.        texture.video.addEventListener("canplay", function (e)
  5556.        {
  5557.            texture.video.play().then( function()
  5558.                                       {
  5559.                                           texture.video.mPaused = false;
  5560.  
  5561.                                           texture.globject = renderer.CreateTextureFromImage(renderer.TEXTYPE.T2D, texture.video, renderer.TEXFMT.C4I8, rti.mFilter, rti.mWrap, rti.mVFlip);
  5562.                                           texture.loaded = true;
  5563.            
  5564.                                           if( me.mTextureCallbackFun!=null )
  5565.                                               me.mTextureCallbackFun( me.mTextureCallbackObj, slot, texture.video, true, 3, 1, -1.0, me.mID );
  5566.                                        } )
  5567.                               .catch( function(error)
  5568.                                       {
  5569.                                           console.log( error );
  5570.                                       }
  5571.                                );
  5572.        } );
  5573.  
  5574.        texture.video.addEventListener( "error", function(e)
  5575.        {
  5576.               if( texture.video.hasFalled===true ) { alert("Error: cannot load video" ); return; }
  5577.               let str = texture.video.src;
  5578.               str = str.substr(0,str.lastIndexOf('.') ) + ".mp4";
  5579.               texture.video.src = str;
  5580.               texture.video.hasFalled = true;
  5581.        } );
  5582.  
  5583.        texture.video.src = url.mSrc;
  5584.  
  5585.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5586.                                                                (this.mInputs[slot].mInfo.mType!=="texture") &&
  5587.                                                                (this.mInputs[slot].mInfo.mType!=="webcam") &&
  5588.                                                                (this.mInputs[slot].mInfo.mType!=="mic") &&
  5589.                                                                (this.mInputs[slot].mInfo.mType!=="music") &&
  5590.                                                                (this.mInputs[slot].mInfo.mType!=="musicstream") &&
  5591.                                                                (this.mInputs[slot].mInfo.mType!=="keyboard") &&
  5592.                                                                (this.mInputs[slot].mInfo.mType!=="video")) };
  5593.        this.DestroyInput( slot );
  5594.        this.mInputs[slot] = texture;
  5595.        this.MakeHeader();
  5596.        return returnValue;
  5597.    }
  5598.    else if( url.mType==="music" || url.mType==="musicstream" )
  5599.    {
  5600.     texture = {};
  5601.        texture.mInfo = url;
  5602.        texture.globject = null;
  5603.        texture.loaded = false;
  5604.        texture.audio = document.createElement('audio');
  5605.     texture.audio.loop = true;
  5606.        texture.audio.mMuted = this.mForceMuted;
  5607.        texture.audio.mForceMuted = this.mForceMuted;
  5608.        texture.audio.muted = this.mForceMuted;
  5609.        if( this.mForceMuted===true )
  5610.            texture.audio.volume = 0;
  5611.        texture.audio.autoplay = false;
  5612.        texture.audio.hasFalled = false;
  5613.        texture.audio.mPaused = false;
  5614.        texture.audio.mSound = {};
  5615.  
  5616.        if( this.mForceMuted===false )
  5617.        {
  5618.            if(url.mType==="musicstream" && SC === null)
  5619.            {
  5620.                alert( "Shadertoy: Soundcloud could not be reached" );
  5621.                texture.audio.mForceMuted = true;
  5622.            }
  5623.            }
  5624.  
  5625.        if( wa === null && this.mForceMuted===false )
  5626.        {
  5627.            alert( "Shadertoy: Web Audio not implement in this browser" );
  5628.            texture.audio.mForceMuted = true;
  5629.        }
  5630.  
  5631.        if( texture.audio.mForceMuted )
  5632.        {
  5633.            texture.globject = renderer.CreateTexture(renderer.TEXTYPE.T2D, 512, 2, renderer.TEXFMT.C1I8, renderer.FILTER.LINEAR, renderer.TEXWRP.CLAMP, null);
  5634.            let num = 512;
  5635.            texture.audio.mSound.mFreqData = new Uint8Array( num );
  5636.            texture.audio.mSound.mWaveData = new Uint8Array( num );
  5637.            texture.loaded = true;
  5638.        }
  5639.  
  5640.        texture.audio.addEventListener( "canplay", function()
  5641.        {
  5642.            if( texture===null || texture.audio===null ) return;
  5643.            if( this.mForceMuted  ) return;
  5644.            if( texture.loaded === true ) return;
  5645.  
  5646.            texture.globject = renderer.CreateTexture(renderer.TEXTYPE.T2D, 512, 2, renderer.TEXFMT.C1I8, renderer.FILTER.LINEAR, renderer.TEXWRP.CLAMP, null)
  5647.  
  5648.            texture.audio.mSound.mSource   = wa.createMediaElementSource( texture.audio );
  5649.            texture.audio.mSound.mAnalyser = wa.createAnalyser();
  5650.            texture.audio.mSound.mGain     = wa.createGain();
  5651.  
  5652.            texture.audio.mSound.mSource.connect(   texture.audio.mSound.mAnalyser );
  5653.            texture.audio.mSound.mAnalyser.connect( texture.audio.mSound.mGain );
  5654.            texture.audio.mSound.mGain.connect(me.mGainNode);
  5655.  
  5656.            texture.audio.mSound.mFreqData = new Uint8Array( texture.audio.mSound.mAnalyser.frequencyBinCount );
  5657.            texture.audio.mSound.mWaveData = new Uint8Array( texture.audio.mSound.mAnalyser.frequencyBinCount );
  5658.  
  5659.            if( texture.audio.mPaused )
  5660.            {
  5661.                texture.audio.pause();
  5662.            }
  5663.            else
  5664.            {
  5665.                texture.audio.play().then( function() {} ).catch( function(e){console.log("error " + e);} );
  5666.            }
  5667.            texture.loaded = true;
  5668.        } );
  5669.  
  5670.        texture.audio.addEventListener( "error", function(e)
  5671.        {
  5672.               if( this.mForceMuted  ) return;
  5673.  
  5674.               if( texture.audio.hasFalled===true ) { return; }
  5675.               let str = texture.audio.src;
  5676.               str = str.substr(0,str.lastIndexOf('.') ) + ".ogg";
  5677.               texture.audio.src = str;
  5678.               texture.audio.hasFalled = true;
  5679.        } );
  5680.  
  5681.        if( !texture.audio.mForceMuted )
  5682.        {
  5683.            if(url.mType==="musicstream")
  5684.            {
  5685.                SC.resolve(url.mSrc,
  5686.                    function(song)
  5687.                    {
  5688.                        if( song.streamable===true )
  5689.                        {
  5690.                            texture.audio.crossOrigin = 'anonymous';
  5691.                            texture.audio.src = song.stream_url;
  5692.                            texture.audio.soundcloudInfo = song;
  5693.                        }
  5694.                        else
  5695.                        {
  5696.                            alert('Shadertoy: Soundcloud 3 - This track cannot be streamed' );
  5697.                        }
  5698.                    },
  5699.                    function(error)
  5700.                    {
  5701.                        if (me.mTextureCallbackFun!==null)
  5702.                        {
  5703.                            me.mTextureCallbackFun(me.mTextureCallbackObj, slot, {wave:null}, false, 4, 0, -1.0, me.mID);
  5704.                        }
  5705.                    } );
  5706.            }
  5707.            else
  5708.            {
  5709.                texture.audio.src = url.mSrc;
  5710.            }
  5711.        }
  5712.  
  5713.        if (me.mTextureCallbackFun!==null)
  5714.        {
  5715.            if (url.mType === "music")            me.mTextureCallbackFun(me.mTextureCallbackObj, slot, {wave:null}, false, 4, 0, -1.0, me.mID);
  5716.            else if (url.mType === "musicstream") me.mTextureCallbackFun(me.mTextureCallbackObj, slot, {wave:null, info: texture.audio.soundcloudInfo}, false, 8, 0, -1.0, me.mID);
  5717.        }
  5718.  
  5719.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5720.                                                                (this.mInputs[slot].mInfo.mType!=="texture") &&
  5721.                                                                (this.mInputs[slot].mInfo.mType!=="webcam") &&
  5722.                                                                (this.mInputs[slot].mInfo.mType!=="mic") &&
  5723.                                                                (this.mInputs[slot].mInfo.mType!=="music") &&
  5724.                                                                (this.mInputs[slot].mInfo.mType!=="musicstream") &&
  5725.                                                                (this.mInputs[slot].mInfo.mType!=="keyboard") &&
  5726.                                                                (this.mInputs[slot].mInfo.mType!=="video")) };
  5727.        this.DestroyInput( slot );
  5728.        this.mInputs[slot] = texture;
  5729.        this.MakeHeader();
  5730.        return returnValue;
  5731.    }
  5732.    else if( url.mType==="keyboard" )
  5733.    {
  5734.     texture = {};
  5735.        texture.mInfo = url;
  5736.        texture.globject = null;
  5737.        texture.loaded = true;
  5738.  
  5739.        texture.keyboard = {};
  5740.  
  5741.        if( me.mTextureCallbackFun!==null )
  5742.            me.mTextureCallbackFun( me.mTextureCallbackObj, slot, {mImage: keyboard.mIcon, mData: keyboard.mData}, false, 6, 1, -1.0, me.mID );
  5743.  
  5744.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5745.                                                                (this.mInputs[slot].mInfo.mType!="texture") &&
  5746.                                                                (this.mInputs[slot].mInfo.mType!="webcam") &&
  5747.                                                                (this.mInputs[slot].mInfo.mType!="mic") &&
  5748.                                                                (this.mInputs[slot].mInfo.mType!="music") &&
  5749.                                                                (this.mInputs[slot].mInfo.mType!="musicstream") &&
  5750.                                                                (this.mInputs[slot].mInfo.mType!="keyboard") &&
  5751.                                                                (this.mInputs[slot].mInfo.mType!="video")) };
  5752.        this.DestroyInput( slot );
  5753.        this.mInputs[slot] = texture;
  5754.        this.MakeHeader();
  5755.        return returnValue;
  5756.    }
  5757.    else if( url.mType==="buffer" )
  5758.    {
  5759.        texture = {};
  5760.        texture.mInfo = url;
  5761.  
  5762.        texture.image = new Image();
  5763.        texture.image.onload = function()
  5764.        {
  5765.            if( me.mTextureCallbackFun!==null )
  5766.                me.mTextureCallbackFun( me.mTextureCallbackObj, slot, {texture: texture.image, data:null}, true, 9, 1, -1.0, me.mID );
  5767.        }
  5768.        texture.image.src = url.mSrc;
  5769.        texture.id = assetID_to_bufferID( url.mID );
  5770.        texture.loaded = true;
  5771.  
  5772.        let returnValue = { mFailed:false, mNeedsShaderCompile: (this.mInputs[slot]===null ) || (
  5773.                                                                (this.mInputs[slot].mInfo.mType!=="texture") &&
  5774.                                                                (this.mInputs[slot].mInfo.mType!=="webcam") &&
  5775.                                                                (this.mInputs[slot].mInfo.mType!=="mic") &&
  5776.                                                                (this.mInputs[slot].mInfo.mType!=="music") &&
  5777.                                                                (this.mInputs[slot].mInfo.mType!=="musicstream") &&
  5778.                                                                (this.mInputs[slot].mInfo.mType!=="keyboard") &&
  5779.                                                                (this.mInputs[slot].mInfo.mType!=="video")) };
  5780.  
  5781.        this.DestroyInput( slot );
  5782.        this.mInputs[slot] = texture;
  5783.  
  5784.        this.mEffect.ResizeBuffer(texture.id, this.mEffect.mXres, this.mEffect.mYres, false );
  5785.  
  5786.        this.SetSamplerFilter(slot, url.mSampler.filter, buffers, cubeBuffers, true);
  5787.        this.SetSamplerVFlip(slot, url.mSampler.vflip);
  5788.        this.SetSamplerWrap(slot, url.mSampler.wrap, buffers);
  5789.  
  5790.        this.MakeHeader();
  5791.        return returnValue;
  5792.    }
  5793.    else
  5794.    {
  5795.        alert( "input type error" );
  5796.        return { mFailed: true };
  5797.    }
  5798.  
  5799.    return { mFailed: true };
  5800. }
  5801.  
  5802. EffectPass.prototype.Paint_Image = function( vrData, wa, d, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard )
  5803. {
  5804.    let times = [ 0.0, 0.0, 0.0, 0.0 ];
  5805.  
  5806.    let dates = [ d.getFullYear(), // the year (four digits)
  5807.                  d.getMonth(),   // the month (from 0-11)
  5808.                  d.getDate(),     // the day of the month (from 1-31)
  5809.                  d.getHours()*60.0*60 + d.getMinutes()*60 + d.getSeconds()  + d.getMilliseconds()/1000.0 ];
  5810.  
  5811.    let mouse = [  mousePosX, mousePosY, mouseOriX, mouseOriY ];
  5812.  
  5813.    //------------------------
  5814.    
  5815.    let resos = [ 0.0,0.0,0.0, 0.0,0.0,0.0, 0.0,0.0,0.0, 0.0,0.0,0.0 ];
  5816.    let texIsLoaded = [0, 0, 0, 0 ];
  5817.    let texID = [ null, null, null, null];
  5818.  
  5819.    for (let i=0; i<this.mInputs.length; i++ )
  5820.    {
  5821.        let inp = this.mInputs[i];
  5822.  
  5823.        if( inp===null )
  5824.        {
  5825.        }
  5826.        else if( inp.mInfo.mType==="texture" )
  5827.        {
  5828.            if( inp.loaded===true  )
  5829.            {
  5830.                texID[i] = inp.globject;
  5831.                texIsLoaded[i] = 1;
  5832.                resos[3*i+0] = inp.image.width;
  5833.                resos[3*i+1] = inp.image.height;
  5834.                resos[3*i+2] = 1;
  5835.            }
  5836.        }
  5837.        else if( inp.mInfo.mType==="volume" )
  5838.        {
  5839.            if( inp.loaded===true  )
  5840.            {
  5841.                texID[i] = inp.globject;
  5842.                texIsLoaded[i] = 1;
  5843.                resos[3*i+0] = inp.mImage.mXres;
  5844.                resos[3*i+1] = inp.mImage.mYres;
  5845.                resos[3*i+2] = inp.mImage.mZres;
  5846.            }
  5847.        }
  5848.        else if( inp.mInfo.mType==="keyboard" )
  5849.        {
  5850.            texID[i] = keyboard.mTexture;
  5851.            texIsLoaded[i] = 1;
  5852.            resos[3*i+0] = 256;
  5853.            resos[3*i+1] = 3;
  5854.            resos[3*i+2] = 1;
  5855.        }
  5856.        else if( inp.mInfo.mType==="cubemap" )
  5857.        {
  5858.            if (inp.loaded === true)
  5859.            {
  5860.                let id = assetID_to_cubemapBuferID(inp.mInfo.mID);
  5861.                if( id!==-1 )
  5862.                {
  5863.                    texID[i] = cubeBuffers[id].mTexture[ cubeBuffers[id].mLastRenderDone ];
  5864.                    resos[3*i+0] = cubeBuffers[id].mResolution[0];
  5865.                    resos[3*i+1] = cubeBuffers[id].mResolution[1];
  5866.                    resos[3*i+2] = 1;
  5867.                    texIsLoaded[i] = 1;
  5868.  
  5869.                    // hack. in webgl2.0 we have samplers, so we don't need this crap here
  5870.                    let filter = this.mRenderer.FILTER.NONE;
  5871.                         if (inp.mInfo.mSampler.filter === "linear") filter = this.mRenderer.FILTER.LINEAR;
  5872.                    else if (inp.mInfo.mSampler.filter === "mipmap") filter = this.mRenderer.FILTER.MIPMAP;
  5873.                    this.mRenderer.SetSamplerFilter( texID[i], filter, false);
  5874.                }
  5875.                else
  5876.                {
  5877.                    texID[i] = inp.globject;
  5878.                    texIsLoaded[i] = 1;
  5879.                }
  5880.            }
  5881.        }
  5882.        else if( inp.mInfo.mType==="webcam" )
  5883.        {
  5884.            if( inp.loaded===true )
  5885.            {
  5886.                if( inp.mImage !== null )
  5887.                {
  5888.                    if( this.mTextureCallbackFun!==null )
  5889.                        this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.mImage, false, 7, 1, -1, this.mID );
  5890.  
  5891.                    texID[i] = inp.globject;
  5892.                    texIsLoaded[i] = 1;
  5893.                    resos[3*i+0] = inp.mImage.width;
  5894.                    resos[3*i+1] = inp.mImage.height;
  5895.                    resos[3*i+2] = 1;
  5896.                }
  5897.                else  if( inp.video.readyState === inp.video.HAVE_ENOUGH_DATA )
  5898.                {
  5899.  
  5900.                    if( this.mTextureCallbackFun!==null )
  5901.                        this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.video, false, 7, 1, -1, this.mID );
  5902.  
  5903.                    texID[i] = inp.globject;
  5904.                    this.mRenderer.UpdateTextureFromImage(inp.globject, inp.video);
  5905.                    if( inp.mInfo.mSampler.filter === "mipmap" )
  5906.                        this.mRenderer.CreateMipmaps(inp.globject);
  5907.                    resos[3*i+0] = inp.video.videoWidth;
  5908.                    resos[3*i+1] = inp.video.videoHeight;
  5909.                    resos[3*i+2] = 1;
  5910.                    texIsLoaded[i] = 1;
  5911.                }
  5912.            }
  5913.            else
  5914.            {
  5915.                texID[i] = null;
  5916.                texIsLoaded[i] = 0;
  5917.                resos[3*i+0] = inp.video.width;
  5918.                resos[3*i+1] = inp.video.height;
  5919.                resos[3*i+2] = 1;
  5920.            }
  5921.        }
  5922.        else if( inp.mInfo.mType==="video" )
  5923.        {
  5924.            if( inp.video.mPaused === false )
  5925.            {
  5926.                if( this.mTextureCallbackFun!==null )
  5927.                    this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.video, false, 3, 1, inp.video.currentTime, this.mID );
  5928.            }
  5929.  
  5930.            if( inp.loaded===true )
  5931.            {
  5932.                times[i] = inp.video.currentTime;
  5933.                texID[i] = inp.globject;
  5934.                texIsLoaded[i] = 1;
  5935.  
  5936.              if( inp.video.mPaused === false )
  5937.              {
  5938.                  this.mRenderer.UpdateTextureFromImage(inp.globject, inp.video);
  5939.                    if( inp.mInfo.mSampler.filter === "mipmap" )
  5940.                        this.mRenderer.CreateMipmaps(inp.globject);
  5941.                }
  5942.                resos[3*i+0] = inp.video.videoWidth;
  5943.                resos[3*i+1] = inp.video.videoHeight;
  5944.                resos[3*i+2] = 1;
  5945.            }
  5946.        }
  5947.        else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream" )
  5948.        {
  5949.            if( inp.audio.mPaused === false && inp.audio.mForceMuted === false && inp.loaded===true )
  5950.            {
  5951.                if( wa !== null )
  5952.                {
  5953.                    inp.audio.mSound.mAnalyser.getByteFrequencyData(  inp.audio.mSound.mFreqData );
  5954.                    inp.audio.mSound.mAnalyser.getByteTimeDomainData( inp.audio.mSound.mWaveData );
  5955.                }
  5956.  
  5957.                if( this.mTextureCallbackFun!==null )
  5958.                {
  5959.                         if( inp.mInfo.mType==="music")       this.mTextureCallbackFun(this.mTextureCallbackObj, i, (wa === null) ? null : { wave : inp.audio.mSound.mFreqData }, false, 4, 1, inp.audio.currentTime, this.mID);
  5960.                    else if( inp.mInfo.mType==="musicstream") this.mTextureCallbackFun(this.mTextureCallbackObj, i, (wa === null) ? null : { wave : inp.audio.mSound.mFreqData, info : inp.audio.soundcloudInfo}, false, 8, 1, inp.audio.currentTime, this.mID);
  5961.                }
  5962.            }
  5963.  
  5964.            if( inp.loaded===true )
  5965.            {
  5966.                times[i] = inp.audio.currentTime;
  5967.                texID[i] = inp.globject;
  5968.                texIsLoaded[i] = 1;
  5969.  
  5970.                if( inp.audio.mForceMuted === true )
  5971.                {
  5972.                    times[i] = 10.0 + time;
  5973.                    let num = inp.audio.mSound.mFreqData.length;
  5974.                    for (let j=0; j<num; j++ )
  5975.                    {
  5976.                        let x = j / num;
  5977.                        let f =  (0.75 + 0.25*Math.sin( 10.0*j + 13.0*time )) * Math.exp( -3.0*x );
  5978.  
  5979.                        if( j<3 )
  5980.                            f =  Math.pow( 0.50 + 0.5*Math.sin( 6.2831*time ), 4.0 ) * (1.0-j/3.0);
  5981.  
  5982.                        inp.audio.mSound.mFreqData[j] = Math.floor(255.0*f) | 0;
  5983.                    }
  5984.  
  5985.                  //let num = inp.audio.mSound.mFreqData.length;
  5986.                    for (let j=0; j<num; j++ )
  5987.                    {
  5988.                        let f = 0.5 + 0.15*Math.sin( 17.0*time + 10.0*6.2831*j/num ) * Math.sin( 23.0*time + 1.9*j/num );
  5989.                        inp.audio.mSound.mWaveData[j] = Math.floor(255.0*f) | 0;
  5990.                    }
  5991.  
  5992.                }
  5993.  
  5994.              if( inp.audio.mPaused === false )
  5995.                {
  5996.                  let waveLen = Math.min(inp.audio.mSound.mWaveData.length, 512);
  5997.                  this.mRenderer.UpdateTexture(inp.globject, 0, 0, 512, 1, inp.audio.mSound.mFreqData);
  5998.                  this.mRenderer.UpdateTexture(inp.globject, 0, 1, 512, 1, inp.audio.mSound.mWaveData);
  5999.                }
  6000.  
  6001.                resos[3*i+0] = 512;
  6002.                resos[3*i+1] = 2;
  6003.                resos[3*i+2] = 1;
  6004.            }
  6005.        }
  6006.        else if( inp.mInfo.mType==="mic" )
  6007.        {
  6008.            if( inp.loaded===false || inp.mForceMuted || wa === null || inp.mAnalyser == null )
  6009.            {
  6010.                    times[i] = 10.0 + time;
  6011.                    let num = inp.mFreqData.length;
  6012.                    for( let j=0; j<num; j++ )
  6013.                    {
  6014.                        let x = j / num;
  6015.                        let f =  (0.75 + 0.25*Math.sin( 10.0*j + 13.0*time )) * Math.exp( -3.0*x );
  6016.  
  6017.                        if( j<3 )
  6018.                            f =  Math.pow( 0.50 + 0.5*Math.sin( 6.2831*time ), 4.0 ) * (1.0-j/3.0);
  6019.  
  6020.                        inp.mFreqData[j] = Math.floor(255.0*f) | 0;
  6021.                    }
  6022.  
  6023.                    for( let j=0; j<num; j++ )
  6024.                    {
  6025.                        let f = 0.5 + 0.15*Math.sin( 17.0*time + 10.0*6.2831*j/num ) * Math.sin( 23.0*time + 1.9*j/num );
  6026.                        inp.mWaveData[j] = Math.floor(255.0*f) | 0;
  6027.                    }
  6028.            }
  6029.            else
  6030.            {
  6031.                inp.mAnalyser.getByteFrequencyData(  inp.mFreqData );
  6032.                inp.mAnalyser.getByteTimeDomainData( inp.mWaveData );
  6033.            }
  6034.  
  6035.            if( this.mTextureCallbackFun!==null )
  6036.                this.mTextureCallbackFun( this.mTextureCallbackObj, i, {wave:inp.mFreqData}, false, 5, 1, -1, this.mID );
  6037.  
  6038.            if( inp.loaded===true )
  6039.            {
  6040.                texID[i] = inp.globject;
  6041.                texIsLoaded[i] = 1;
  6042.                let waveLen = Math.min( inp.mWaveData.length, 512 );
  6043.                this.mRenderer.UpdateTexture(inp.globject, 0, 0, 512,     1, inp.mFreqData);
  6044.                this.mRenderer.UpdateTexture(inp.globject, 0, 1, waveLen, 1, inp.mWaveData);
  6045.                resos[3*i+0] = 512;
  6046.                resos[3*i+1] = 2;
  6047.                resos[3*i+2] = 1;
  6048.            }
  6049.        }
  6050.        else if( inp.mInfo.mType==="buffer" )
  6051.        {
  6052.            let id = inp.id;
  6053.            if( inp.loaded===true  )
  6054.            {
  6055.                texID[i] = buffers[id].mTexture[ buffers[id].mLastRenderDone ];
  6056.                texIsLoaded[i] = 1;
  6057.                resos[3*i+0] = xres;
  6058.                resos[3*i+1] = yres;
  6059.                resos[3*i+2] = 1;
  6060.                // hack. in webgl2.0 we have samplers, so we don't need this crap here
  6061.                let filter = this.mRenderer.FILTER.NONE;
  6062.                     if (inp.mInfo.mSampler.filter === "linear") filter = this.mRenderer.FILTER.LINEAR;
  6063.                else if (inp.mInfo.mSampler.filter === "mipmap") filter = this.mRenderer.FILTER.MIPMAP;
  6064.                this.mRenderer.SetSamplerFilter( texID[i], filter, false);
  6065.            }
  6066.  
  6067.            if( this.mTextureCallbackFun!==null )
  6068.            {
  6069.                this.mTextureCallbackFun( this.mTextureCallbackObj, i, {texture:inp.image, data:buffers[id].mThumbnailBuffer}, false, 9, 1, -1, this.mID );
  6070.            }
  6071.        }
  6072.    }
  6073.  
  6074.    this.mRenderer.AttachTextures( 4, texID[0], texID[1], texID[2], texID[3] );
  6075.  
  6076.    //-----------------------------------
  6077.  
  6078.    let prog = this.mProgram;
  6079.  
  6080.    //if( vrData!=null && this.mSupportsVR ) prog = this.mProgramVR;
  6081.  
  6082.    this.mRenderer.AttachShader(prog);
  6083.  
  6084.    this.mRenderer.SetShaderConstant1F(  "iTime", time);
  6085.    this.mRenderer.SetShaderConstant3F(  "iResolution", xres, yres, 1.0);
  6086.    this.mRenderer.SetShaderConstant4FV( "iMouse", mouse);
  6087.    this.mRenderer.SetShaderConstant1FV( "iChannelTime", times );              // OBSOLETE
  6088.    this.mRenderer.SetShaderConstant4FV( "iDate", dates );
  6089.    this.mRenderer.SetShaderConstant3FV( "iChannelResolution", resos );        // OBSOLETE
  6090.    this.mRenderer.SetShaderConstant1F(  "iSampleRate", this.mSampleRate);
  6091.    this.mRenderer.SetShaderTextureUnit( "iChannel0", 0 );
  6092.    this.mRenderer.SetShaderTextureUnit( "iChannel1", 1 );
  6093.    this.mRenderer.SetShaderTextureUnit( "iChannel2", 2 );
  6094.    this.mRenderer.SetShaderTextureUnit( "iChannel3", 3 );
  6095.    this.mRenderer.SetShaderConstant1I(  "iFrame", this.mFrame );
  6096.    this.mRenderer.SetShaderConstant1F(  "iTimeDelta", dtime);
  6097.    this.mRenderer.SetShaderConstant1F("iFrameRate", fps);
  6098.  
  6099.    this.mRenderer.SetShaderConstant1F(  "iCh0.time", times[0] );
  6100.    this.mRenderer.SetShaderConstant1F(  "iCh1.time", times[1] );
  6101.    this.mRenderer.SetShaderConstant1F(  "iCh2.time", times[2] );
  6102.    this.mRenderer.SetShaderConstant1F(  "iCh3.time", times[3] );
  6103.    this.mRenderer.SetShaderConstant3F(  "iCh0.size", resos[0], resos[ 1], resos[ 2] );
  6104.    this.mRenderer.SetShaderConstant3F(  "iCh1.size", resos[3], resos[ 4], resos[ 5] );
  6105.    this.mRenderer.SetShaderConstant3F(  "iCh2.size", resos[6], resos[ 7], resos[ 8] );
  6106.    this.mRenderer.SetShaderConstant3F(  "iCh3.size", resos[9], resos[10], resos[11] );
  6107.    this.mRenderer.SetShaderConstant1I(  "iCh0.loaded", texIsLoaded[0] );
  6108.    this.mRenderer.SetShaderConstant1I(  "iCh1.loaded", texIsLoaded[1] );
  6109.    this.mRenderer.SetShaderConstant1I(  "iCh2.loaded", texIsLoaded[2] );
  6110.    this.mRenderer.SetShaderConstant1I(  "iCh3.loaded", texIsLoaded[3] );
  6111.  
  6112.    let l1 = this.mRenderer.GetAttribLocation(this.mProgram, "pos");
  6113.  
  6114.    if( (vrData !== null) && this.mSupportsVR )
  6115.    {
  6116.        for (let i=0; i<2; i++ )
  6117.        {
  6118.            let ei = (i===0) ? vrData.mLeftEye : vrData.mRightEye;
  6119.  
  6120.            let vp = [i * xres / 2, 0, xres / 2, yres];
  6121.  
  6122.            this.mRenderer.SetViewport(vp);
  6123.  
  6124.            let fov = ei.mProjection;
  6125.            let corA = [ -fov[2], -fov[1], -1.0 ];
  6126.            let corB = [  fov[3], -fov[1], -1.0 ];
  6127.            let corC = [  fov[3],  fov[0], -1.0 ];
  6128.            let corD = [ -fov[2],  fov[0], -1.0 ];
  6129.            let apex = [ 0.0, 0.0, 0.0 ];
  6130.  
  6131.            let ma = invertFast( ei.mCamera );
  6132.            corA = matMulpoint( ma, corA );
  6133.            corB = matMulpoint( ma, corB );
  6134.            corC = matMulpoint( ma, corC );
  6135.            corD = matMulpoint( ma, corD );
  6136.            apex = matMulpoint( ma, apex );
  6137.  
  6138.            let corners = [ corA[0], corA[1], corA[2],
  6139.                            corB[0], corB[1], corB[2],
  6140.                            corC[0], corC[1], corC[2],
  6141.                            corD[0], corD[1], corD[2],
  6142.                            apex[0], apex[1], apex[2]];
  6143.  
  6144.            this.mRenderer.SetShaderConstant3FV("unCorners", corners);
  6145.            this.mRenderer.SetShaderConstant4FV("unViewport", vp);
  6146.  
  6147.            this.mRenderer.DrawUnitQuad_XY(l1);
  6148.        }
  6149.    }
  6150.    else
  6151.    {
  6152.        this.mRenderer.SetViewport([0, 0, xres, yres]);
  6153.        this.mRenderer.DrawFullScreenTriangle_XY( l1 );
  6154.    }
  6155.  
  6156.    this.mRenderer.DettachTextures();
  6157. }
  6158.  
  6159. EffectPass.prototype.iRenderSound = function(d, callback )
  6160. {
  6161.    let dates = [ d.getFullYear(), // the year (four digits)
  6162.                  d.getMonth(),   // the month (from 0-11)
  6163.                  d.getDate(),     // the day of the month (from 1-31)
  6164.                  d.getHours()*60.0*60 + d.getMinutes()*60 + d.getSeconds() ];
  6165.  
  6166.    let resos = [ 0.0,0.0,0.0, 0.0,0.0,0.0, 0.0,0.0,0.0, 0.0,0.0,0.0 ];
  6167.  
  6168.    this.mRenderer.SetRenderTarget(this.mRenderFBO);
  6169.  
  6170.    this.mRenderer.SetViewport([0, 0, this.mTextureDimensions, this.mTextureDimensions]);
  6171.    this.mRenderer.AttachShader(this.mProgram);
  6172.    this.mRenderer.SetBlend( false );
  6173.  
  6174.    let texID = [null, null, null, null];
  6175.    for (let i = 0; i < this.mInputs.length; i++)
  6176.    {
  6177.        let inp = this.mInputs[i];
  6178.  
  6179.        if( inp===null )
  6180.        {
  6181.        }
  6182.        else if( inp.mInfo.mType==="texture" )
  6183.        {
  6184.            if( inp.loaded===true  )
  6185.            {
  6186.                texID[i] = inp.globject;
  6187.                resos[3*i+0] = inp.image.width;
  6188.                resos[3*i+1] = inp.image.height;
  6189.                resos[3*i+2] = 1;
  6190.            }
  6191.        }
  6192.        else if( inp.mInfo.mType==="volume" )
  6193.        {
  6194.            if( inp.loaded===true  )
  6195.            {
  6196.                texID[i] = inp.globject;
  6197.                resos[3*i+0] = inp.mImage.mXres;
  6198.                resos[3*i+1] = inp.mImage.mYres;
  6199.                resos[3*i+2] = inp.mImage.mZres;
  6200.            }
  6201.        }
  6202.    }
  6203.  
  6204.    this.mRenderer.AttachTextures(4, texID[0], texID[1], texID[2], texID[3]);
  6205.  
  6206.    let l2 = this.mRenderer.SetShaderConstantLocation(this.mProgram, "iTimeOffset");
  6207.    let l3 = this.mRenderer.SetShaderConstantLocation(this.mProgram, "iSampleOffset");
  6208.    this.mRenderer.SetShaderConstant4FV("iDate", dates);
  6209.    this.mRenderer.SetShaderConstant3FV("iChannelResolution", resos);
  6210.    this.mRenderer.SetShaderConstant1F("iSampleRate", this.mSampleRate);
  6211.    this.mRenderer.SetShaderTextureUnit("iChannel0", 0);
  6212.    this.mRenderer.SetShaderTextureUnit("iChannel1", 1);
  6213.    this.mRenderer.SetShaderTextureUnit("iChannel2", 2);
  6214.    this.mRenderer.SetShaderTextureUnit("iChannel3", 3);
  6215.  
  6216.    let l1 = this.mRenderer.GetAttribLocation(this.mProgram, "pos");
  6217.  
  6218.    //--------------------------------
  6219.    let numSamples = this.mTmpBufferSamples;
  6220.    let numBlocks = this.mPlaySamples / numSamples;
  6221.    for (let j=0; j<numBlocks; j++ )
  6222.    {
  6223.        let off = j*numSamples;
  6224.        
  6225.        this.mRenderer.SetShaderConstant1F_Pos(l2, off / this.mSampleRate);
  6226.        this.mRenderer.SetShaderConstant1I_Pos(l3, off );
  6227.        this.mRenderer.DrawUnitQuad_XY(l1);
  6228.  
  6229.        this.mRenderer.GetPixelData(this.mData, 0, this.mTextureDimensions, this.mTextureDimensions);
  6230.  
  6231.        callback( off, this.mData, numSamples );
  6232.    }
  6233.  
  6234.    this.mRenderer.DetachShader();
  6235.    this.mRenderer.DettachTextures();
  6236.    this.mRenderer.SetRenderTarget(null);
  6237. }
  6238.  
  6239. EffectPass.prototype.Paint_Sound = function( wa, d )
  6240. {
  6241.    let bufL = this.mBuffer.getChannelData(0); // Float32Array
  6242.    let bufR = this.mBuffer.getChannelData(1); // Float32Array
  6243.  
  6244.    this.iRenderSound( d, function(off, data, numSamples)
  6245.                         {
  6246.                            for( let i=0; i<numSamples; i++ )
  6247.                            {
  6248.                                bufL[off+i] = -1.0 + 2.0*(data[4*i+0]+256.0*data[4*i+1])/65535.0;
  6249.                                bufR[off+i] = -1.0 + 2.0*(data[4*i+2]+256.0*data[4*i+3])/65535.0;
  6250.                            }
  6251.                         }
  6252.                     );
  6253. }
  6254.  
  6255. EffectPass.prototype.SetUniforms = function(vrData, wa, d, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard )
  6256. {
  6257.    let times = [ 0.0, 0.0, 0.0, 0.0 ];
  6258.  
  6259.    let dates = [ d.getFullYear(), // the year (four digits)
  6260.                  d.getMonth(),   // the month (from 0-11)
  6261.                  d.getDate(),     // the day of the month (from 1-31)
  6262.                  d.getHours()*60.0*60 + d.getMinutes()*60 + d.getSeconds()  + d.getMilliseconds()/1000.0 ];
  6263.  
  6264.    let mouse = [  mousePosX, mousePosY, mouseOriX, mouseOriY ];
  6265.  
  6266.    let resos = [ 0.0,0.0,0.0, 0.0,0.0,0.0, 0.0,0.0,0.0, 0.0,0.0,0.0 ];
  6267.  
  6268.    //------------------------
  6269.    
  6270.    let texID = [ null, null, null, null];
  6271.  
  6272.    for( let i=0; i<this.mInputs.length; i++ )
  6273.    {
  6274.        let inp = this.mInputs[i];
  6275.  
  6276.        if( inp===null )
  6277.        {
  6278.        }
  6279.        else if( inp.mInfo.mType==="texture" )
  6280.        {
  6281.            if( inp.loaded===true  )
  6282.            {
  6283.                texID[i] = inp.globject;
  6284.                resos[3*i+0] = inp.image.width;
  6285.                resos[3*i+1] = inp.image.height;
  6286.                resos[3*i+2] = 1;
  6287.            }
  6288.        }
  6289.        else if( inp.mInfo.mType==="volume" )
  6290.        {
  6291.            if( inp.loaded===true  )
  6292.            {
  6293.                texID[i] = inp.globject;
  6294.                resos[3*i+0] = inp.mImage.mXres;
  6295.                resos[3*i+1] = inp.mImage.mYres;
  6296.                resos[3*i+2] = inp.mImage.mZres;
  6297.            }
  6298.        }
  6299.        else if( inp.mInfo.mType==="keyboard" )
  6300.        {
  6301.            texID[i] = keyboard.mTexture;
  6302.        }
  6303.        else if( inp.mInfo.mType=="cubemap" )
  6304.        {
  6305.            if (inp.loaded === true)
  6306.            {
  6307.                let id = assetID_to_cubemapBuferID(inp.mInfo.mID);
  6308.                if( id!==-1 )
  6309.                {
  6310.                    texID[i] = cubeBuffers[id].mTexture[ cubeBuffers[id].mLastRenderDone ];
  6311.                    resos[3*i+0] = cubeBuffers[id].mResolution[0];
  6312.                    resos[3*i+1] = cubeBuffers[id].mResolution[1];
  6313.                    resos[3*i+2] = 1;
  6314.    
  6315.                    // hack. in webgl2.0 we have samplers, so we don't need this crap here
  6316.                    let filter = this.mRenderer.FILTER.NONE;
  6317.                         if (inp.mInfo.mSampler.filter === "linear") filter = this.mRenderer.FILTER.LINEAR;
  6318.                    else if (inp.mInfo.mSampler.filter === "mipmap") filter = this.mRenderer.FILTER.MIPMAP;
  6319.                    this.mRenderer.SetSamplerFilter( texID[i], filter, false);
  6320.                }
  6321.                else
  6322.                {
  6323.                    texID[i] = inp.globject;
  6324.                }
  6325.            }
  6326.  
  6327.        }
  6328.        else if( inp.mInfo.mType==="webcam" )
  6329.        {
  6330.            if( inp.loaded===true )
  6331.            {
  6332.                if( inp.mImage !== null )
  6333.                {
  6334.                    texID[i] = inp.globject;
  6335.                    resos[3*i+0] = inp.mImage.width;
  6336.                    resos[3*i+1] = inp.mImage.height;
  6337.                    resos[3*i+2] = 1;
  6338.                }
  6339.                else  if( inp.video.readyState === inp.video.HAVE_ENOUGH_DATA )
  6340.                {
  6341.                    texID[i] = inp.globject;
  6342.                    resos[3*i+0] = inp.video.videoWidth;
  6343.                    resos[3*i+1] = inp.video.videoHeight;
  6344.                    resos[3*i+2] = 1;
  6345.                }
  6346.            }
  6347.            else
  6348.            {
  6349.                texID[i] = null;
  6350.                resos[3*i+0] = inp.video.width;
  6351.                resos[3*i+1] = inp.video.height;
  6352.                resos[3*i+2] = 1;
  6353.            }
  6354.        }
  6355.        else if( inp.mInfo.mType==="video" )
  6356.        {
  6357.           if( inp.loaded===true )
  6358.           {
  6359.                times[i] = inp.video.currentTime;
  6360.                texID[i] = inp.globject;
  6361.                resos[3*i+0] = inp.video.videoWidth;
  6362.                resos[3*i+1] = inp.video.videoHeight;
  6363.                resos[3*i+2] = 1;
  6364.            }
  6365.        }
  6366.        else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream" )
  6367.        {
  6368.            if( inp.loaded===true )
  6369.            {
  6370.                times[i] = inp.audio.currentTime;
  6371.                texID[i] = inp.globject;
  6372.  
  6373.                if( inp.audio.mForceMuted === true )
  6374.                {
  6375.                    times[i] = 10.0 + time;
  6376.                }
  6377.  
  6378.                resos[3*i+0] = 512;
  6379.                resos[3*i+1] = 2;
  6380.                resos[3*i+2] = 1;
  6381.            }
  6382.        }
  6383.        else if( inp.mInfo.mType==="mic" )
  6384.        {
  6385.            if( inp.loaded===false || inp.mForceMuted || wa === null || inp.mAnalyser == null )
  6386.            {
  6387.                times[i] = 10.0 + time;
  6388.            }
  6389.  
  6390.            if( inp.loaded===true )
  6391.            {
  6392.                texID[i] = inp.globject;
  6393.                resos[3*i+0] = 512;
  6394.                resos[3*i+1] = 2;
  6395.                resos[3*i+2] = 1;
  6396.            }
  6397.        }
  6398.        else if( inp.mInfo.mType==="buffer" )
  6399.        {
  6400.            if( inp.loaded===true  )
  6401.            {
  6402.                texID[i] = buffers[inp.id].mTexture[ buffers[inp.id].mLastRenderDone ];
  6403.                resos[3*i+0] = buffers[inp.id].mResolution[0];
  6404.                resos[3*i+1] = buffers[inp.id].mResolution[1];
  6405.                resos[3*i+2] = 1;
  6406.            }
  6407.        }
  6408.    }
  6409.  
  6410.    this.mRenderer.AttachTextures( 4, texID[0], texID[1], texID[2], texID[3] );
  6411.  
  6412.    //-----------------------------------
  6413.  
  6414.    this.mRenderer.AttachShader(this.mProgram);
  6415.  
  6416.    this.mRenderer.SetShaderConstant1F(  "iTime", time);
  6417.    this.mRenderer.SetShaderConstant3F(  "iResolution", xres, yres, 1.0);
  6418.    this.mRenderer.SetShaderConstant4FV( "iMouse", mouse);
  6419.    this.mRenderer.SetShaderConstant1FV( "iChannelTime", times );              // OBSOLETE
  6420.    this.mRenderer.SetShaderConstant4FV( "iDate", dates );
  6421.    this.mRenderer.SetShaderConstant3FV( "iChannelResolution", resos );        // OBSOLETE
  6422.    this.mRenderer.SetShaderConstant1F(  "iSampleRate", this.mSampleRate);
  6423.    this.mRenderer.SetShaderTextureUnit( "iChannel0", 0 );
  6424.    this.mRenderer.SetShaderTextureUnit( "iChannel1", 1 );
  6425.    this.mRenderer.SetShaderTextureUnit( "iChannel2", 2 );
  6426.    this.mRenderer.SetShaderTextureUnit( "iChannel3", 3 );
  6427.    this.mRenderer.SetShaderConstant1I(  "iFrame", this.mFrame );
  6428.    this.mRenderer.SetShaderConstant1F(  "iTimeDelta", dtime);
  6429.    this.mRenderer.SetShaderConstant1F(  "iFrameRate", fps );
  6430.  
  6431.    this.mRenderer.SetShaderConstant1F(  "iChannel[0].time",       times[0] );
  6432.    this.mRenderer.SetShaderConstant1F(  "iChannel[1].time",       times[1] );
  6433.    this.mRenderer.SetShaderConstant1F(  "iChannel[2].time",       times[2] );
  6434.    this.mRenderer.SetShaderConstant1F(  "iChannel[3].time",       times[3] );
  6435.    this.mRenderer.SetShaderConstant3F(  "iChannel[0].resolution", resos[0], resos[ 1], resos[ 2] );
  6436.    this.mRenderer.SetShaderConstant3F(  "iChannel[1].resolution", resos[3], resos[ 4], resos[ 5] );
  6437.    this.mRenderer.SetShaderConstant3F(  "iChannel[2].resolution", resos[6], resos[ 7], resos[ 8] );
  6438.    this.mRenderer.SetShaderConstant3F(  "iChannel[3].resolution", resos[9], resos[10], resos[11] );
  6439. }
  6440.  
  6441. EffectPass.prototype.ProcessInputs = function(vrData, wa, d, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard )
  6442. {
  6443.    for (let i=0; i<this.mInputs.length; i++ )
  6444.    {
  6445.        let inp = this.mInputs[i];
  6446.  
  6447.        if( inp===null )
  6448.        {
  6449.        }
  6450.        else if( inp.mInfo.mType==="texture" )
  6451.        {
  6452.        }
  6453.        else if( inp.mInfo.mType==="volume" )
  6454.        {
  6455.        }
  6456.        else if( inp.mInfo.mType==="keyboard" )
  6457.        {
  6458.        }
  6459.        else if( inp.mInfo.mType==="cubemap" )
  6460.        {
  6461.        }
  6462.        else if( inp.mInfo.mType==="webcam" )
  6463.        {
  6464.            if( inp.loaded===true )
  6465.            {
  6466.                if( inp.mImage !== null )
  6467.                {
  6468.                    if( this.mTextureCallbackFun!==null )
  6469.                        this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.mImage, false, 7, 1, -1, this.mID );
  6470.                }
  6471.                else if( inp.video.readyState === inp.video.HAVE_ENOUGH_DATA )
  6472.                {
  6473.                    if( this.mTextureCallbackFun!==null )
  6474.                        this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.video, false, 7, 1, -1, this.mID );
  6475.  
  6476.                    this.mRenderer.UpdateTextureFromImage(inp.globject, inp.video);
  6477.                    if( inp.mInfo.mSampler.filter === "mipmap" )
  6478.                        this.mRenderer.CreateMipmaps(inp.globject);
  6479.                }
  6480.            }
  6481.        }
  6482.        else if( inp.mInfo.mType==="video" )
  6483.        {
  6484.            if( inp.video.mPaused === false )
  6485.            {
  6486.                if( this.mTextureCallbackFun!==null )
  6487.                    this.mTextureCallbackFun( this.mTextureCallbackObj, i, inp.video, false, 3, 1, inp.video.currentTime, this.mID );
  6488.            }
  6489.  
  6490.            if( inp.loaded===true )
  6491.            {
  6492.              if( inp.video.mPaused === false )
  6493.              {
  6494.                  this.mRenderer.UpdateTextureFromImage(inp.globject, inp.video);
  6495.                    if( inp.mInfo.mSampler.filter === "mipmap" )
  6496.                        this.mRenderer.CreateMipmaps(inp.globject);
  6497.                }
  6498.            }
  6499.        }
  6500.        else if( inp.mInfo.mType==="music" || inp.mInfo.mType==="musicstream" )
  6501.        {
  6502.            if( inp.audio.mPaused === false && inp.audio.mForceMuted === false && inp.loaded===true )
  6503.            {
  6504.                if( wa !== null )
  6505.                {
  6506.                    inp.audio.mSound.mAnalyser.getByteFrequencyData(  inp.audio.mSound.mFreqData );
  6507.                    inp.audio.mSound.mAnalyser.getByteTimeDomainData( inp.audio.mSound.mWaveData );
  6508.                }
  6509.  
  6510.                if( this.mTextureCallbackFun!==null )
  6511.                {
  6512.                         if( inp.mInfo.mType==="music")       this.mTextureCallbackFun(this.mTextureCallbackObj, i, (wa == null) ? null : { wave : inp.audio.mSound.mFreqData }, false, 4, 1, inp.audio.currentTime, this.mID);
  6513.                    else if( inp.mInfo.mType==="musicstream") this.mTextureCallbackFun(this.mTextureCallbackObj, i, (wa == null) ? null : { wave : inp.audio.mSound.mFreqData, info : inp.audio.soundcloudInfo}, false, 8, 1, inp.audio.currentTime, this.mID);
  6514.                }
  6515.            }
  6516.  
  6517.            if( inp.loaded===true )
  6518.            {
  6519.                if( inp.audio.mForceMuted === true )
  6520.                {
  6521.                    let num = inp.audio.mSound.mFreqData.length;
  6522.                    for (let j=0; j<num; j++ )
  6523.                    {
  6524.                        let x = j / num;
  6525.                        let f =  (0.75 + 0.25*Math.sin( 10.0*j + 13.0*time )) * Math.exp( -3.0*x );
  6526.  
  6527.                        if( j<3 )
  6528.                            f =  Math.pow( 0.50 + 0.5*Math.sin( 6.2831*time ), 4.0 ) * (1.0-j/3.0);
  6529.  
  6530.                        inp.audio.mSound.mFreqData[j] = Math.floor(255.0*f) | 0;
  6531.                    }
  6532.  
  6533.                  //let num = inp.audio.mSound.mFreqData.length;
  6534.                    for (let j=0; j<num; j++ )
  6535.                    {
  6536.                        let f = 0.5 + 0.15*Math.sin( 17.0*time + 10.0*6.2831*j/num ) * Math.sin( 23.0*time + 1.9*j/num );
  6537.                        inp.audio.mSound.mWaveData[j] = Math.floor(255.0*f) | 0;
  6538.                    }
  6539.  
  6540.                }
  6541.  
  6542.              if( inp.audio.mPaused === false )
  6543.                {
  6544.                  let waveLen = Math.min(inp.audio.mSound.mWaveData.length, 512);
  6545.                  this.mRenderer.UpdateTexture(inp.globject, 0, 0, 512, 1, inp.audio.mSound.mFreqData);
  6546.                  this.mRenderer.UpdateTexture(inp.globject, 0, 1, 512, 1, inp.audio.mSound.mWaveData);
  6547.                }
  6548.            }
  6549.        }
  6550.        else if( inp.mInfo.mType==="mic" )
  6551.        {
  6552.            if( inp.loaded===false || inp.mForceMuted || wa === null || inp.mAnalyser == null )
  6553.            {
  6554.                    let num = inp.mFreqData.length;
  6555.                    for( let j=0; j<num; j++ )
  6556.                    {
  6557.                        let x = j / num;
  6558.                        let f =  (0.75 + 0.25*Math.sin( 10.0*j + 13.0*time )) * Math.exp( -3.0*x );
  6559.  
  6560.                        if( j<3 )
  6561.                            f =  Math.pow( 0.50 + 0.5*Math.sin( 6.2831*time ), 4.0 ) * (1.0-j/3.0);
  6562.  
  6563.                        inp.mFreqData[j] = Math.floor(255.0*f) | 0;
  6564.                    }
  6565.  
  6566.                    for( let j=0; j<num; j++ )
  6567.                    {
  6568.                        let f = 0.5 + 0.15*Math.sin( 17.0*time + 10.0*6.2831*j/num ) * Math.sin( 23.0*time + 1.9*j/num );
  6569.                        inp.mWaveData[j] = Math.floor(255.0*f) | 0;
  6570.                    }
  6571.            }
  6572.            else
  6573.            {
  6574.                inp.mAnalyser.getByteFrequencyData(  inp.mFreqData );
  6575.                inp.mAnalyser.getByteTimeDomainData( inp.mWaveData );
  6576.            }
  6577.  
  6578.            if( this.mTextureCallbackFun!==null )
  6579.                this.mTextureCallbackFun( this.mTextureCallbackObj, i, {wave:inp.mFreqData}, false, 5, 1, -1, this.mID );
  6580.  
  6581.            if( inp.loaded===true )
  6582.            {
  6583.                let waveLen = Math.min( inp.mWaveData.length, 512 );
  6584.                this.mRenderer.UpdateTexture(inp.globject, 0, 0, 512,     1, inp.mFreqData);
  6585.                this.mRenderer.UpdateTexture(inp.globject, 0, 1, waveLen, 1, inp.mWaveData);
  6586.            }
  6587.        }
  6588.        else if( inp.mInfo.mType==="buffer" )
  6589.        {
  6590.            if( inp.loaded===true  )
  6591.            {
  6592.                let id = inp.id;
  6593.                let texID = buffers[id].mTexture[ buffers[id].mLastRenderDone ];
  6594.  
  6595.                // hack. in webgl2.0 we have samplers, so we don't need this crap here
  6596.                let filter = this.mRenderer.FILTER.NONE;
  6597.                     if (inp.mInfo.mSampler.filter === "linear") filter = this.mRenderer.FILTER.LINEAR;
  6598.                else if (inp.mInfo.mSampler.filter === "mipmap") filter = this.mRenderer.FILTER.MIPMAP;
  6599.                this.mRenderer.SetSamplerFilter( texID, filter, false);
  6600.            }
  6601.  
  6602.            if( this.mTextureCallbackFun!==null )
  6603.            {
  6604. let id = inp.id;
  6605.                this.mTextureCallbackFun( this.mTextureCallbackObj, i, {texture:inp.image, data:buffers[id].mThumbnailBuffer}, false, 9, 1, -1, this.mID );
  6606.            }
  6607.        }
  6608.    }
  6609. }
  6610.  
  6611. EffectPass.prototype.Paint_Cubemap = function( vrData, wa, d, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard, face )
  6612. {
  6613.    this.ProcessInputs(vrData, wa, d, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard, face );
  6614.    this.SetUniforms(vrData, wa, d, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard );
  6615.  
  6616.    let l1 = this.mRenderer.GetAttribLocation(this.mProgram, "pos");
  6617.  
  6618.    let vp = [0, 0, xres, yres];
  6619.  
  6620.    this.mRenderer.SetViewport(vp);
  6621.  
  6622.    let corA = [-1.0, -1.0, -1.0];
  6623.    let corB = [ 1.0, -1.0, -1.0];
  6624.    let corC = [ 1.0,  1.0, -1.0];
  6625.    let corD = [-1.0,  1.0, -1.0];
  6626.    let apex = [ 0.0,  0.0,  0.0];
  6627.  
  6628.         if( face===0 ) { corA=[ 1.0,  1.0,  1.0]; corB=[ 1.0,  1.0, -1.0]; corC=[ 1.0, -1.0, -1.0]; corD=[ 1.0, -1.0,  1.0]; }
  6629.    else if( face===1 ) { corA=[-1.0,  1.0, -1.0]; corB=[-1.0,  1.0,  1.0]; corC=[-1.0, -1.0,  1.0]; corD=[-1.0, -1.0, -1.0]; }
  6630.    else if( face===2 ) { corA=[-1.0,  1.0, -1.0]; corB=[ 1.0,  1.0, -1.0]; corC=[ 1.0,  1.0,  1.0]; corD=[-1.0,  1.0,  1.0]; }
  6631.    else if( face===3 ) { corA=[-1.0, -1.0,  1.0]; corB=[ 1.0, -1.0,  1.0]; corC=[ 1.0, -1.0, -1.0]; corD=[-1.0, -1.0, -1.0]; }
  6632.    else if( face===4 ) { corA=[-1.0,  1.0,  1.0]; corB=[ 1.0,  1.0,  1.0]; corC=[ 1.0, -1.0,  1.0]; corD=[-1.0, -1.0,  1.0]; }
  6633.    else if( face===5 ) { corA=[ 1.0,  1.0, -1.0]; corB=[-1.0,  1.0, -1.0]; corC=[-1.0, -1.0, -1.0]; corD=[ 1.0, -1.0, -1.0]; }
  6634.  
  6635.    let corners = [ corA[0], corA[1], corA[2],
  6636.                    corB[0], corB[1], corB[2],
  6637.                    corC[0], corC[1], corC[2],
  6638.                    corD[0], corD[1], corD[2],
  6639.                    apex[0], apex[1], apex[2]];
  6640.  
  6641.    this.mRenderer.SetShaderConstant3FV("unCorners", corners);
  6642.    this.mRenderer.SetShaderConstant4FV("unViewport", vp);
  6643.  
  6644.    this.mRenderer.DrawUnitQuad_XY(l1);
  6645.  
  6646.    this.mRenderer.DettachTextures();
  6647. }
  6648.  
  6649. EffectPass.prototype.Paint = function( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, isPaused, bufferID, bufferNeedsMimaps, buffers, cubeBuffers, keyboard, effect )
  6650. {
  6651.    if( this.mType==="sound" )
  6652.    {
  6653.        if (this.mSoundShaderCompiled === true)
  6654.        {
  6655.            // make sure all textures are loaded
  6656.            for (let i=0; i<this.mInputs.length; i++ )
  6657.            {
  6658.                let inp = this.mInputs[i];
  6659.                if (inp === null) continue;
  6660.  
  6661.                if (inp.mInfo.mType === "texture" && !inp.loaded) return;
  6662.                if (inp.mInfo.mType === "cubemap" && !inp.loaded) return;
  6663.            }
  6664.  
  6665.            this.Paint_Sound(wa, da);
  6666.            this.mSoundShaderCompiled = false;
  6667.        }
  6668.        if (this.mFrame === 0)
  6669.        {
  6670.            if (this.mPlaying===true)
  6671.            {
  6672.                this.mPlayNode.disconnect();
  6673.                this.mPlayNode.stop();
  6674.                this.mPlayNode = null;
  6675.            }
  6676.            this.mPlaying = true;
  6677.  
  6678.            this.mPlayNode = wa.createBufferSource();
  6679.            this.mPlayNode.buffer = this.mBuffer;
  6680.            this.mPlayNode.connect(this.mGainNode);
  6681.            this.mPlayNode.start(0);
  6682.        }
  6683.        this.mFrame++;
  6684.    }
  6685.    else if( this.mType==="image" )
  6686.    {
  6687.        this.mRenderer.SetRenderTarget( null );
  6688.        this.Paint_Image( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard );
  6689.        this.mFrame++;
  6690.    }
  6691.    else if( this.mType==="common" )
  6692.    {
  6693.    }
  6694.    else if( this.mType==="buffer" )
  6695.    {
  6696.        this.mEffect.ResizeBuffer(bufferID, this.mEffect.mXres, this.mEffect.mYres, false );
  6697.  
  6698.        let buffer = buffers[bufferID];
  6699.  
  6700.        let dstID = 1 - buffer.mLastRenderDone;
  6701.  
  6702.        this.mRenderer.SetRenderTarget( buffer.mTarget[dstID] );
  6703.        this.Paint_Image( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard );
  6704.  
  6705.        // compute mipmaps if needd
  6706.        if( bufferNeedsMimaps )
  6707.        {
  6708.            this.mRenderer.CreateMipmaps( buffer.mTexture[dstID]);
  6709.        }
  6710.  
  6711.        // make thumbnail
  6712.        //if( this.mTextureCallbackFun != null )
  6713.        /*
  6714.        {
  6715.            this.mRenderer.SetRenderTarget( buffer.mThumbnailRenderTarget );
  6716.            let v = [0, 0, buffer.mThumbnailRes[0], buffer.mThumbnailRes[1]];
  6717.            this.mRenderer.SetBlend(false);
  6718.            this.mRenderer.SetViewport(v);
  6719.            this.mRenderer.AttachShader(this.mProgramCopy);
  6720.            let l1 = this.mRenderer.GetAttribLocation(this.mProgramCopy, "pos");
  6721.            this.mRenderer.SetShaderConstant4FV("v", v);
  6722.            this.mRenderer.AttachTextures(1, buffer.mTexture[dstID], null, null, null);
  6723.            this.mRenderer.DrawUnitQuad_XY(l1);
  6724.            this.mRenderer.DettachTextures();
  6725.            this.mRenderer.DetachShader();
  6726.            this.mRenderer.GetPixelData( new Uint8Array(buffer.mThumbnailBuffer.data.buffer), buffer.mThumbnailRes[0], buffer.mThumbnailRes[1] );
  6727.            this.mRenderer.SetRenderTarget(null);
  6728.        }
  6729.        */
  6730.        buffers[bufferID].mLastRenderDone = 1 - buffers[bufferID].mLastRenderDone;
  6731.        this.mFrame++;
  6732.    }
  6733.    else if( this.mType==="cubemap" )
  6734.    {
  6735.        this.mEffect.ResizeCubemapBuffer(bufferID, 1024, 1024, false );
  6736.  
  6737.        let buffer = cubeBuffers[bufferID];
  6738.  
  6739.        xres = buffer.mResolution[0];
  6740.        yres = buffer.mResolution[1];
  6741.        let dstID = 1 - buffer.mLastRenderDone;
  6742.        for( let face=0; face<6; face++ )
  6743.        {
  6744.            this.mRenderer.SetRenderTargetCubeMap( buffer.mTarget[dstID], face );
  6745.            this.Paint_Cubemap( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, buffers, cubeBuffers, keyboard, face );
  6746.        }
  6747.        this.mRenderer.SetRenderTargetCubeMap( null, 0 );
  6748.  
  6749.        // compute mipmaps if needd
  6750.        if( bufferNeedsMimaps )
  6751.        {
  6752.            this.mRenderer.CreateMipmaps( buffer.mTexture[dstID]);
  6753.        }
  6754.        cubeBuffers[bufferID].mLastRenderDone = 1 - cubeBuffers[bufferID].mLastRenderDone;
  6755.  
  6756.        this.mFrame++;
  6757.    }
  6758. }
  6759.  
  6760. EffectPass.prototype.StopOutput_Sound = function( wa )
  6761. {
  6762.    if( this.mPlayNode===null ) return;
  6763.    this.mPlayNode.disconnect();
  6764. }
  6765.  
  6766. EffectPass.prototype.ResumeOutput_Sound = function( wa )
  6767. {
  6768.    if( this.mPlayNode===null ) return;
  6769.  
  6770.    wa.resume()
  6771.    this.mPlayNode.connect( this.mGainNode );
  6772. }
  6773.  
  6774. EffectPass.prototype.StopOutput_Image = function( wa )
  6775. {
  6776. }
  6777.  
  6778. EffectPass.prototype.ResumeOutput_Image = function( wa )
  6779. {
  6780. }
  6781.  
  6782. EffectPass.prototype.StopOutput = function( wa )
  6783. {
  6784.    for (let j=0; j<this.mInputs.length; j++ )
  6785.        this.StopInput(j);
  6786.  
  6787.    if( this.mType==="sound" )
  6788.         this.StopOutput_Sound( wa );
  6789.    else
  6790.         this.StopOutput_Image( wa );
  6791. }
  6792.  
  6793. EffectPass.prototype.ResumeOutput = function( wa )
  6794. {
  6795.    for (let j=0; j<this.mInputs.length; j++ )
  6796.        this.ResumeInput(j);
  6797.  
  6798.    if( this.mType==="sound" )
  6799.         this.ResumeOutput_Sound( wa );
  6800.    else
  6801.         this.ResumeOutput_Image( wa );
  6802. }
  6803.  
  6804. EffectPass.prototype.GetCompilationTime = function()
  6805. {
  6806.    return this.mCompilationTime;
  6807. }
  6808.  
  6809. //============================================================================================================
  6810. function Screenshots()
  6811. {
  6812.    // private
  6813.    let mTexture = null;
  6814.    let mTarget = null;
  6815.    let mXres = 0;
  6816.    let mYres = 0;
  6817.    let mCubemapToEquirectProgram;
  6818.    let mRenderer = null;
  6819.  
  6820.    // public
  6821.    var me = {};
  6822.  
  6823.    me.Initialize = function(renderer)
  6824.    {
  6825.        mRenderer = renderer;
  6826.        let caps = mRenderer.GetCaps();
  6827.        let is20 = caps.mIsGL20;
  6828.  
  6829.        let vsSourceC, fsSourceC;
  6830.        if( is20 )
  6831.        {
  6832.            vsSourceC = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  6833.            fsSourceC = "uniform samplerCube t; out vec4 outColor; void main() { vec2 px = gl_FragCoord.xy/vec2(4096.0,2048.0); vec2 an = 3.1415926535898 * (px*vec2(2.0, 1.0) - vec2(0.0,0.5)); vec3 rd = vec3(-cos(an.y) * sin(an.x), sin(an.y), cos(an.y) * cos(an.x)); outColor = texture(t, rd); }";
  6834.        }
  6835.        else
  6836.        {
  6837.            vsSourceC = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  6838.            fsSourceC = "uniform samplerCube t; void main() { vec2 px = gl_FragCoord.xy/vec2(4096.0,2048.0); vec2 an = 3.1415926535898 * (px*vec2(2.0, 1.0) - vec2(0.0,0.5)); vec3 rd = vec3(-cos(an.y) * sin(an.x), sin(an.y), cos(an.y) * cos(an.x)); gl_FragColor = texture(t, rd); }";
  6839.        }
  6840.  
  6841.        let compileShader = function (worked, info)
  6842.        {
  6843.            if (worked === false)
  6844.            {
  6845.                console.log("Failed to compile cubemap resample shader (" + errorType + "): " + log);
  6846.            }
  6847.            else
  6848.            {
  6849.                mCubemapToEquirectProgram = info;
  6850.            }
  6851.        }
  6852.        mRenderer.CreateShader(vsSourceC, fsSourceC, false, true, compileShader);
  6853.  
  6854.        return true;
  6855.    };
  6856.  
  6857.    me.Allocate = function( xres, yres )
  6858.    {
  6859.        if( xres>mXres || yres>mYres )
  6860.        {
  6861.            let texture = mRenderer.CreateTexture(mRenderer.TEXTYPE.T2D, xres, yres, mRenderer.TEXFMT.C4F32, mRenderer.FILTER.NONE, mRenderer.TEXWRP.CLAMP, null);
  6862.            let target = mRenderer.CreateRenderTarget( texture, null, null, null, null, false);
  6863.  
  6864.            if( mXres!==0 )
  6865.            {
  6866.                mRenderer.DestroyTexture(mTexture);
  6867.                mRenderer.DestroyRenderTarget(mTarget);
  6868.            }
  6869.  
  6870.            mTexture = texture;
  6871.            mTarget = target;
  6872.            mXres = xres;
  6873.            mYres = yres;
  6874.        }
  6875.    };
  6876.  
  6877.    me.GetProgram = function()
  6878.    {
  6879.        return mCubemapToEquirectProgram;
  6880.    };
  6881.    me.GetTarget = function()
  6882.    {
  6883.        return mTarget;
  6884.    };
  6885.  
  6886.    return me;
  6887. };
  6888.  
  6889. //============================================================================================================
  6890.  
  6891. function Effect(vr, ac, canvas, callback, obj, forceMuted, forcePaused, resizeCallback, crashCallback )
  6892. {
  6893.    let xres = canvas.width;
  6894.    let yres = canvas.height;
  6895.  
  6896.    let me = this;
  6897.    this.mCanvas = canvas;
  6898.    this.mCreated = false;
  6899.    this.mRenderer = null;
  6900.    this.mAudioContext = ac;
  6901.    this.mGLContext = null;
  6902.    this.mWebVR = vr;
  6903.    this.mRenderingStereo = false;
  6904.    this.mXres = xres;
  6905.    this.mYres = yres;
  6906.    this.mForceMuted = forceMuted;
  6907.    if( ac===null ) this.mForceMuted = true;
  6908.    this.mForcePaused = forcePaused;
  6909.    this.mGainNode = null;
  6910.    this.mPasses = [];
  6911.    this.mFrame = 0;
  6912.    this.mTextureCallbackFun = callback;
  6913.    this.mTextureCallbackObj = obj;
  6914.    this.mMaxBuffers = 4;
  6915.    this.mMaxCubeBuffers = 1;
  6916.    this.mMaxPasses = this.mMaxBuffers + 1 + 1 + 1 + 1; // some day decouple passes from buffers (4 buffers + common + Imagen + sound + cubemap)
  6917.    this.mBuffers = [];
  6918.    this.mCubeBuffers = [];
  6919.    this.mScreenshotSytem = null;
  6920.    this.mCompilationTime = 0;
  6921.    this.mIsLowEnd = piIsMobile();
  6922.  
  6923.    this.mGLContext = piCreateGlContext(canvas, false, false, true, false); // need preserve-buffe to true in order to capture screenshots
  6924.    if (this.mGLContext === null)
  6925.    {
  6926.        return;
  6927.    }
  6928.  
  6929.    canvas.addEventListener("webglcontextlost", function (event)
  6930.        {
  6931.            event.preventDefault();
  6932.            crashCallback();
  6933.        }, false);
  6934.  
  6935.    this.mRenderer = piRenderer();
  6936.    if (!this.mRenderer.Initialize(this.mGLContext))
  6937.        return;
  6938.  
  6939.    this.mScreenshotSytem = Screenshots();
  6940.    if (!this.mScreenshotSytem.Initialize(this.mRenderer))
  6941.        return;
  6942.  
  6943.    var caps = this.mRenderer.GetCaps();
  6944.    this.mIs20 = caps.mIsGL20;
  6945.    this.mShaderTextureLOD = caps.mShaderTextureLOD;
  6946.    //-------------
  6947.    if( ac!==null )
  6948.    {  
  6949.        this.mGainNode = ac.createGain();
  6950.        if( !forceMuted )
  6951.        {
  6952.            this.mGainNode.connect( ac.destination);
  6953.        }
  6954.        if (this.mForceMuted )
  6955.            this.mGainNode.gain.value = 0.0;
  6956.        else
  6957.            this.mGainNode.gain.value = 1.0;
  6958.    }
  6959.  
  6960.    //-------------
  6961.    let vsSourceC, fsSourceC;
  6962.    if( this.mIs20 )
  6963.    {
  6964.        vsSourceC = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  6965.        fsSourceC = "uniform vec4 v; uniform sampler2D t; out vec4 outColor; void main() { outColor = textureLod(t, gl_FragCoord.xy / v.zw, 0.0); }";
  6966.    }
  6967.    else
  6968.    {
  6969.        vsSourceC = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  6970.        fsSourceC = "uniform vec4 v; uniform sampler2D t; void main() { gl_FragColor = texture2D(t, gl_FragCoord.xy / v.zw, -100.0); }";
  6971.    }
  6972.  
  6973.    this.mRenderer.CreateShader(vsSourceC, fsSourceC, false, true, function(worked, info)
  6974.        {
  6975.            if (worked === false) console.log("Failed to compile shader to copy buffers : " + info.mErrorStr);
  6976.            else me.mProgramCopy = info;
  6977.        });
  6978.  
  6979.    let vsSourceD, fsSourceD;
  6980.    if( this.mIs20 )
  6981.    {
  6982.        vsSourceD = "layout(location = 0) in vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  6983.        fsSourceD = "uniform vec4 v; uniform sampler2D t; out vec4 outColor; void main() { vec2 uv = gl_FragCoord.xy / v.zw; outColor = texture(t, vec2(uv.x,1.0-uv.y)); }";
  6984.    }
  6985.    else
  6986.    {
  6987.        vsSourceD = "attribute vec2 pos; void main() { gl_Position = vec4(pos.xy,0.0,1.0); }";
  6988.        fsSourceD = "uniform vec4 v; uniform sampler2D t; void main() { vec2 uv = gl_FragCoord.xy / v.zw; gl_FragColor = texture2D(t, vec2(uv.x,1.0-uv.y)); }";
  6989.    }
  6990.  
  6991.    this.mRenderer.CreateShader(vsSourceD, fsSourceD, false, true, function (worked, info)
  6992.        {
  6993.            if (worked === false) console.log("Failed to compile shader to downscale buffers : " + info.mErrorStr);
  6994.            else me.mProgramDownscale = info;
  6995.        });
  6996.  
  6997.  
  6998.    // set all buffers and cubemaps to null
  6999.    for( let i=0; i<this.mMaxBuffers; i++ )
  7000.    {
  7001.        this.mBuffers[i] = { mTexture: [null, null],
  7002.                             mTarget:  [null, null],
  7003.                             mResolution: [0, 0],
  7004.                             mLastRenderDone: 0,
  7005.                             mThumbnailRenderTarget: null,
  7006.                             mThumbnailTexture: null,
  7007.                             mThumbnailBuffer:  null,
  7008.                             mThumbnailRes: [0, 0] };
  7009.    }
  7010.  
  7011.    for( let i=0; i<this.mMaxCubeBuffers; i++ )
  7012.    {
  7013.        this.mCubeBuffers[i] = { mTexture: [null, null],
  7014.                                mTarget:  [null, null],
  7015.                                mResolution: [0, 0],
  7016.                                mLastRenderDone: 0,
  7017.                                mThumbnailRenderTarget: null,
  7018.                                mThumbnailTexture: null,
  7019.                                mThumbnailBuffer:  null,
  7020.                                mThumbnailRes: [0, 0] };
  7021.    }
  7022.  
  7023.    //-------
  7024.  
  7025.    let keyboardData = new Uint8Array( 256*3 );
  7026.    for (let j=0; j<(256*3); j++ ) { keyboardData[j] = 0; }
  7027.    let kayboardTexture = this.mRenderer.CreateTexture( this.mRenderer.TEXTYPE.T2D, 256, 3, this.mRenderer.TEXFMT.C1I8, this.mRenderer.FILTER.NONE, this.mRenderer.TEXWRP.CLAMP, null);
  7028.    let keyboardImage = new Image();
  7029.    if( callback!==null )
  7030.        keyboardImage.src = "/img/keyboard.png"; // don't load PNG if no UI
  7031.    this.mKeyboard = { mData: keyboardData, mTexture: kayboardTexture, mIcon: keyboardImage };
  7032.  
  7033.    let iResize = function( xres, yres )
  7034.    {
  7035.        me.mCanvas.width = xres;
  7036.        me.mCanvas.height = yres;
  7037.        me.mXres = xres;
  7038.        me.mYres = yres;
  7039.        me.ResizeBuffers(xres, yres);
  7040.        resizeCallback(xres, yres);
  7041.    };
  7042.  
  7043.    let bestAttemptFallback = function()
  7044.    {
  7045.        let devicePixelRatio = window.devicePixelRatio || 1;
  7046.        let xres = Math.round(me.mCanvas.offsetWidth  * devicePixelRatio) | 0;
  7047.        let yres = Math.round(me.mCanvas.offsetHeight * devicePixelRatio) | 0;
  7048.        iResize(xres, yres);
  7049.    };
  7050.  
  7051.    if(!window.ResizeObserver)
  7052.    {
  7053.        console.log("WARNING: This browser doesn't support ResizeObserver.");
  7054.        bestAttemptFallback();
  7055.        window.addEventListener("resize", bestAttemptFallback);
  7056.    }
  7057.    else
  7058.    {
  7059.        this.mRO = new ResizeObserver( function(entries, observer)
  7060.        {
  7061.            var entry = entries[0];
  7062.            if (!entry['devicePixelContentBoxSize'])
  7063.            {
  7064.                observer.unobserve(me.mCanvas);
  7065.                console.log("WARNING: This browser doesn't support ResizeObserver + device-pixel-content-box (2)");
  7066.                bestAttemptFallback();
  7067.                window.addEventListener("resize", bestAttemptFallback);
  7068.            }
  7069.            else
  7070.            {
  7071.                let box = entry.devicePixelContentBoxSize[0];
  7072.                let xres = box.inlineSize;
  7073.                let yres = box.blockSize;
  7074.                iResize(xres, yres);
  7075.            }
  7076.        });
  7077.        try
  7078.        {
  7079.            this.mRO.observe(this.mCanvas, { box: ["device-pixel-content-box"] });
  7080.            //this.mRO.observe(this.mCanvas);
  7081.        }
  7082.        catch (e)
  7083.        {
  7084.            console.log("WARNING: This browser doesn't support ResizeObserver + device-pixel-content-box (1)");
  7085.            bestAttemptFallback();
  7086.            window.addEventListener("resize", bestAttemptFallback);
  7087.        }
  7088.    }
  7089.  
  7090.    this.mCreated = true;
  7091. }
  7092.  
  7093. Effect.prototype.ResizeCubemapBuffer = function(i, xres, yres )
  7094. {
  7095.    let oldXres = this.mCubeBuffers[i].mResolution[0];
  7096.    let oldYres = this.mCubeBuffers[i].mResolution[1];
  7097.  
  7098.    if( this.mCubeBuffers[i].mTexture[0]===null || oldXres !== xres || oldYres !== yres )
  7099.    {
  7100.        let texture1 = this.mRenderer.CreateTexture(this.mRenderer.TEXTYPE.CUBEMAP,
  7101.            xres, yres,
  7102.            this.mRenderer.TEXFMT.C4F16,
  7103.            this.mRenderer.FILTER.LINEAR,
  7104.            this.mRenderer.TEXWRP.CLAMP,
  7105.            null);
  7106.        let target1 = this.mRenderer.CreateRenderTargetCubeMap( texture1, null, false);
  7107.  
  7108.        let texture2 = this.mRenderer.CreateTexture(this.mRenderer.TEXTYPE.CUBEMAP,
  7109.            xres, yres,
  7110.            this.mRenderer.TEXFMT.C4F16,
  7111.            this.mRenderer.FILTER.LINEAR,
  7112.            this.mRenderer.TEXWRP.CLAMP,
  7113.            null);
  7114.  
  7115.        let target2 = this.mRenderer.CreateRenderTargetCubeMap( texture2, null, false);
  7116.  
  7117.        // Store new buffers
  7118.        this.mCubeBuffers[i].mTexture = [texture1,texture2],
  7119.        this.mCubeBuffers[i].mTarget =  [target1, target2 ],
  7120.        this.mCubeBuffers[i].mLastRenderDone = 0;
  7121.        this.mCubeBuffers[i].mResolution[0] = xres;
  7122.        this.mCubeBuffers[i].mResolution[1] = yres;
  7123.    }
  7124. }
  7125.  
  7126. Effect.prototype.ResizeBuffer = function( i, xres, yres, skipIfNotExists )
  7127. {
  7128.    if( skipIfNotExists && this.mBuffers[i].mTexture[0]===null ) return;
  7129.  
  7130.    let oldXres = this.mBuffers[i].mResolution[0];
  7131.    let oldYres = this.mBuffers[i].mResolution[1];
  7132.  
  7133.    if( oldXres !== xres || oldYres !== yres )
  7134.    {
  7135.        let needCopy = (this.mBuffers[i].mTexture[0]!==null);
  7136.  
  7137.        let texture1 = this.mRenderer.CreateTexture(this.mRenderer.TEXTYPE.T2D,
  7138.            xres, yres,
  7139.            this.mRenderer.TEXFMT.C4F32,
  7140.            (needCopy) ? this.mBuffers[i].mTexture[0].mFilter : this.mRenderer.FILTER.NONE,
  7141.            (needCopy) ? this.mBuffers[i].mTexture[0].mWrap   : this.mRenderer.TEXWRP.CLAMP,
  7142.            null);
  7143.  
  7144.        let texture2 = this.mRenderer.CreateTexture(this.mRenderer.TEXTYPE.T2D,
  7145.            xres, yres,
  7146.            this.mRenderer.TEXFMT.C4F32,
  7147.            (needCopy) ? this.mBuffers[i].mTexture[1].mFilter : this.mRenderer.FILTER.NONE,
  7148.            (needCopy) ? this.mBuffers[i].mTexture[1].mWrap   : this.mRenderer.TEXWRP.CLAMP,
  7149.            null);
  7150.  
  7151.        let target1 = this.mRenderer.CreateRenderTarget( texture1, null, null, null, null, false);
  7152.        let target2 = this.mRenderer.CreateRenderTarget( texture2, null, null, null, null, false);
  7153.  
  7154.        if( needCopy )
  7155.        {
  7156.            let v = [0, 0, Math.min(xres, oldXres), Math.min(yres, oldYres)];
  7157.            this.mRenderer.SetBlend(false);
  7158.            this.mRenderer.SetViewport(v);
  7159.            this.mRenderer.AttachShader(this.mProgramCopy);
  7160.            let l1 = this.mRenderer.GetAttribLocation(this.mProgramCopy, "pos");
  7161.            let vOld = [0, 0, oldXres, oldYres];
  7162.            this.mRenderer.SetShaderConstant4FV("v", vOld);
  7163.  
  7164.            // Copy old buffers 1 to new buffer
  7165.            this.mRenderer.SetRenderTarget(target1);
  7166.            this.mRenderer.AttachTextures(1, this.mBuffers[i].mTexture[0], null, null, null);
  7167.            this.mRenderer.DrawUnitQuad_XY(l1);
  7168.  
  7169.            // Copy old buffers 2 to new buffer
  7170.            this.mRenderer.SetRenderTarget(target2);
  7171.            this.mRenderer.AttachTextures(1, this.mBuffers[i].mTexture[1], null, null, null);
  7172.            this.mRenderer.DrawUnitQuad_XY(l1);
  7173.  
  7174.            // Deallocate old memory
  7175.            this.mRenderer.DestroyTexture(this.mBuffers[i].mTexture[0]);
  7176.            this.mRenderer.DestroyRenderTarget(this.mBuffers[i].mTarget[0]);
  7177.            this.mRenderer.DestroyTexture(this.mBuffers[i].mTexture[1]);
  7178.            this.mRenderer.DestroyRenderTarget(this.mBuffers[i].mTarget[1]);
  7179.            //this.mRenderer.DestroyTexture(this.mBuffers[i].thumbnailTexture);
  7180.        }
  7181.  
  7182.        // Store new buffers
  7183.        this.mBuffers[i].mTexture = [texture1,texture2],
  7184.        this.mBuffers[i].mTarget =  [target1, target2 ],
  7185.        this.mBuffers[i].mLastRenderDone = 0;
  7186.        this.mBuffers[i].mResolution[0] = xres;
  7187.        this.mBuffers[i].mResolution[1] = yres;
  7188.    }
  7189. }
  7190.  
  7191. Effect.prototype.saveScreenshot = function(passid)
  7192. {
  7193.    let pass = this.mPasses[passid];
  7194.  
  7195.    if( pass.mType === "buffer" )
  7196.    {
  7197.        let bufferID = assetID_to_bufferID( this.mPasses[passid].mOutputs[0] );
  7198.  
  7199.        let texture = this.mBuffers[bufferID].mTarget[ this.mBuffers[bufferID].mLastRenderDone ];
  7200.  
  7201.        let numComponents = 3;
  7202.        let width = texture.mTex0.mXres;
  7203.        let height = texture.mTex0.mYres;
  7204.        let type = "Float"; // Other options Float, Half, Uint
  7205.        let bytes = new Float32Array(width * height * 4 );//numComponents);
  7206.        this.mRenderer.GetPixelDataRenderTarget( texture, bytes, width, height );
  7207.        let blob = piExportToEXR(width, height, numComponents, type, bytes);
  7208.  
  7209.        // Offer download automatically to the user
  7210.        piTriggerDownload("image.exr", blob);
  7211.    }
  7212.    else if( pass.mType === "cubemap" )
  7213.    {
  7214.        let xres = 4096;
  7215.        let yres = 2048;
  7216.        this.mScreenshotSytem.Allocate( xres, yres );
  7217.  
  7218.        let cubeBuffer = this.mCubeBuffers[0];
  7219.  
  7220.        let target = this.mScreenshotSytem.GetTarget();
  7221.        this.mRenderer.SetRenderTarget( target );
  7222.  
  7223.        let program = this.mScreenshotSytem.GetProgram();
  7224.  
  7225.        this.mRenderer.AttachShader(program);
  7226.        let l1 = this.mRenderer.GetAttribLocation(program, "pos");
  7227.        this.mRenderer.SetViewport( [0, 0, xres, yres] );
  7228.        this.mRenderer.AttachTextures(1, cubeBuffer.mTexture[ cubeBuffer.mLastRenderDone ], null, null, null);
  7229.        this.mRenderer.DrawUnitQuad_XY(l1);
  7230.        this.mRenderer.DettachTextures();
  7231.        this.mRenderer.SetRenderTarget( null );
  7232.  
  7233.        let data = new Float32Array(xres*yres*4);
  7234.        this.mRenderer.GetPixelDataRenderTarget( target, data, xres, yres );
  7235.  
  7236.        let blob = piExportToEXR(xres, yres, 3, "Float", data );
  7237.        piTriggerDownload("image.exr", blob);
  7238.    }
  7239.    else if( pass.mType === "sound" )
  7240.    {
  7241.        let offset = 0;
  7242.        const bits = 16;
  7243.        const numChannels = 2;
  7244.        let words = new Int16Array(60*pass.mSampleRate*numChannels );
  7245.  
  7246.        pass.iRenderSound( new Date(), function(off, data, numSamples)
  7247.                                         {
  7248.                                            for( let i=0; i<numSamples; i++ )
  7249.                                            {
  7250.                                                words[offset++] = (data[4*i+0]+256.0*data[4*i+1]) - 32767;
  7251.                                                words[offset++] = (data[4*i+2]+256.0*data[4*i+3]) - 32767;
  7252.                                            }
  7253.                                         }
  7254.                                     );
  7255.  
  7256.        let blob = piExportToWAV( 60*pass.mSampleRate, pass.mSampleRate, bits, numChannels, words);
  7257.  
  7258.        piTriggerDownload("sound.wav", blob);
  7259.    }    
  7260. }
  7261.  
  7262. Effect.prototype.ResizeBuffers = function(xres, yres)
  7263. {
  7264.    for (let i=0; i<this.mMaxBuffers; i++ )
  7265.    {
  7266.        this.ResizeBuffer(i, xres, yres, true);
  7267.    }
  7268. }
  7269.  
  7270. Effect.prototype.IsEnabledVR = function ()
  7271. {
  7272.    if (this.mRenderingStereo) return true;
  7273.    return false;
  7274. }
  7275.  
  7276. Effect.prototype.EnableVR = function()
  7277. {
  7278.    if( !this.mWebVR.IsSupported() ) return;
  7279.    if( this.mRenderingStereo ) return;
  7280.  
  7281.    this.mRenderingStereo = true;
  7282.    this.mWebVR.Enable();
  7283. }
  7284.  
  7285. Effect.prototype.DisableVR = function()
  7286. {
  7287.    if( !this.mWebVR.IsSupported() ) return;
  7288.    if( !this.mRenderingStereo ) return;
  7289.  
  7290.    this.mRenderingStereo = false;
  7291.    this.mWebVR.Disable();
  7292. }
  7293.  
  7294. Effect.prototype.GetTexture = function( passid, slot ) { return this.mPasses[passid].GetTexture( slot ); }
  7295. Effect.prototype.NewTexture = function (passid, slot, url) { return this.mPasses[passid].NewTexture( this.mAudioContext, slot, url, this.mBuffers, this.mCubeBuffers, this.mKeyboard ); }
  7296. Effect.prototype.SetOutputs = function( passid, slot, url ) { this.mPasses[passid].SetOutputs( slot, url ); }
  7297. Effect.prototype.SetOutputsByBufferID = function( passid, slot, id ) { this.mPasses[passid].SetOutputsByBufferID( slot, id ); }
  7298. Effect.prototype.GetAcceptsLinear = function (passid, slot) { return this.mPasses[passid].GetAcceptsLinear(slot); }
  7299. Effect.prototype.GetAcceptsMipmapping = function (passid, slot) { return this.mPasses[passid].GetAcceptsMipmapping(slot); }
  7300. Effect.prototype.GetAcceptsWrapRepeat = function (passid, slot) { return this.mPasses[passid].GetAcceptsWrapRepeat(slot); }
  7301. Effect.prototype.GetAcceptsVFlip = function (passid, slot) { return this.mPasses[passid].GetAcceptsVFlip(slot); }
  7302. Effect.prototype.SetSamplerFilter = function (passid, slot, str) { this.mPasses[passid].SetSamplerFilter(slot, str, this.mBuffers, this.mCubeBuffers); }
  7303. Effect.prototype.GetTranslatedShaderSource = function (passid) { return this.mPasses[passid].GetTranslatedShaderSource(); }
  7304. Effect.prototype.GetSamplerFilter = function (passid, slot) { return this.mPasses[passid].GetSamplerFilter(slot); }
  7305. Effect.prototype.SetSamplerWrap = function (passid, slot, str) { this.mPasses[passid].SetSamplerWrap(slot, str, this.mBuffers); }
  7306. Effect.prototype.GetSamplerWrap = function (passid, slot) { return this.mPasses[passid].GetSamplerWrap(slot); }
  7307. Effect.prototype.SetSamplerVFlip = function (passid, slot, str) { this.mPasses[passid].SetSamplerVFlip(slot, str); }
  7308. Effect.prototype.GetSamplerVFlip = function (passid, slot) { return this.mPasses[passid].GetSamplerVFlip(slot); }
  7309.  
  7310. Effect.prototype.GetHeaderSize = function (passid)
  7311. {
  7312.    return this.mPasses[passid].mHeaderLength +
  7313.           this.mRenderer.GetShaderHeaderLines(1);
  7314. }
  7315.  
  7316. Effect.prototype.ToggleVolume = function()
  7317. {
  7318.    this.mForceMuted = !this.mForceMuted;
  7319.  
  7320.    // outp
  7321.    if (this.mForceMuted)
  7322.        this.mGainNode.gain.value = 0.0;
  7323.    else
  7324.        this.mGainNode.gain.value = 1.0;
  7325.  
  7326.    // inp
  7327.    let num = this.mPasses.length;
  7328.    for( let j=0; j<num; j++ )
  7329.    {
  7330.        for( let i=0; i<this.mPasses[j].mInputs.length; i++ )
  7331.        {
  7332.            if( this.mForceMuted )
  7333.                this.mPasses[j].MuteInput( this.mAudioContext, i );
  7334.            else
  7335.                this.mPasses[j].UnMuteInput( this.mAudioContext, i );
  7336.        }
  7337.    }
  7338.  
  7339.    return this.mForceMuted;
  7340. }
  7341.  
  7342. Effect.prototype.SetKeyDown = function( passid, k )
  7343. {
  7344.    if( this.mKeyboard.mData[ k + 0*256 ] == 255 ) return;
  7345.  
  7346.    this.mKeyboard.mData[ k + 0*256 ] = 255;
  7347.    this.mKeyboard.mData[ k + 1*256 ] = 255;
  7348.    this.mKeyboard.mData[ k + 2*256 ] = 255 - this.mKeyboard.mData[ k + 2*256 ];
  7349.    this.mRenderer.UpdateTexture( this.mKeyboard.mTexture, 0, 0, 256, 3, this.mKeyboard.mData );
  7350.  
  7351.    let num = this.mPasses.length;
  7352.    for (let j=0; j<num; j++ )
  7353.    {
  7354.        for (let i=0; i<this.mPasses[j].mInputs.length; i++ )
  7355.        {
  7356.            let inp = this.mPasses[j].mInputs[i];
  7357.            if( inp!==null && inp.mInfo.mType==="keyboard" )
  7358.            {
  7359.                if( this.mTextureCallbackFun!==null )
  7360.                    this.mTextureCallbackFun( this.mTextureCallbackObj, i, {mImage:this.mKeyboard.mIcon, mData: this.mKeyboard.mData}, false, 6, 1, -1.0, this.mPasses[j].mID );
  7361.            }
  7362.        }
  7363.    }
  7364. }
  7365.  
  7366. Effect.prototype.SetKeyUp = function( passid, k )
  7367. {
  7368.    this.mKeyboard.mData[ k + 0*256 ] = 0;
  7369.    this.mKeyboard.mData[ k + 1*256 ] = 0;
  7370.    this.mRenderer.UpdateTexture( this.mKeyboard.mTexture, 0, 0, 256, 3, this.mKeyboard.mData );
  7371.  
  7372.    let num = this.mPasses.length;
  7373.    for (let j=0; j<num; j++ )
  7374.    {
  7375.        for (let i=0; i<this.mPasses[j].mInputs.length; i++ )
  7376.        {
  7377.            let inp = this.mPasses[j].mInputs[i];
  7378.            if( inp!==null && inp.mInfo.mType==="keyboard" )
  7379.            {
  7380.                if( this.mTextureCallbackFun!==null )
  7381.                    this.mTextureCallbackFun( this.mTextureCallbackObj, i, {mImage:this.mKeyboard.mIcon, mData: this.mKeyboard.mData}, false, 6, 1, -1.0, this.mPasses[j].mID );
  7382.            }
  7383.        }
  7384.    }
  7385. }
  7386.  
  7387. Effect.prototype.StopOutputs = function()
  7388. {
  7389.    let wa = this.mAudioContext;
  7390.  
  7391.    let num = this.mPasses.length;
  7392.    for (let i=0; i<num; i++ )
  7393.    {
  7394.        this.mPasses[i].StopOutput( wa );
  7395.    }
  7396. }
  7397.  
  7398. Effect.prototype.ResumeOutputs = function()
  7399. {
  7400.    let wa = this.mAudioContext;
  7401.  
  7402.    let num = this.mPasses.length;
  7403.    for (let i=0; i<num; i++ )
  7404.    {
  7405.        this.mPasses[i].ResumeOutput( wa );
  7406.    }
  7407. }
  7408.  
  7409. Effect.prototype.PauseInput = function( passid, id )
  7410. {
  7411.    return this.mPasses[passid].TooglePauseInput( this.mAudioContext, id );
  7412. }
  7413.  
  7414. Effect.prototype.ToggleMuteInput = function( passid, id )
  7415. {
  7416.    return this.mPasses[passid].ToggleMuteInput( this.mAudioContext, id );
  7417. }
  7418.  
  7419. Effect.prototype.RewindInput = function( passid, id )
  7420. {
  7421.    this.mPasses[passid].RewindInput( this.mAudioContext, id );
  7422. }
  7423.  
  7424. Effect.prototype.UpdateInputs = function( passid, forceUpdate )
  7425. {
  7426.   this.mPasses[passid].UpdateInputs( this.mAudioContext, forceUpdate, this.mKeyboard );
  7427. }
  7428.  
  7429. Effect.prototype.ResetTime = function()
  7430. {
  7431.    this.mFrame = 0;
  7432.    this.mAudioContext.resume()
  7433.  
  7434.    let num = this.mPasses.length;
  7435.    for( let i=0; i<num; i++ )
  7436.    {
  7437.        this.mPasses[i].mFrame = 0;
  7438.        for( let j=0; j<this.mPasses[i].mInputs.length; j++ )
  7439.            this.mPasses[i].RewindInput(this.mAudioContext, j)
  7440.    }
  7441. }
  7442.  
  7443. Effect.prototype.RequestAnimationFrame = function (id)
  7444. {
  7445.    if (this.mRenderingStereo && this.mWebVR.IsPresenting())
  7446.    {
  7447.        this.mWebVR.RequestAnimationFrame(id);
  7448.    }
  7449.    else
  7450.    {
  7451.        requestAnimFrame(id);
  7452.    }
  7453. }
  7454.  
  7455. Effect.prototype.Paint = function(time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, isPaused)
  7456. {
  7457.    let wa = this.mAudioContext;
  7458.    let da = new Date();
  7459.    let vrData = null; if (this.mRenderingStereo) vrData = this.mWebVR.GetData();
  7460.    let xres = this.mXres / 1;
  7461.    let yres = this.mYres / 1;
  7462.  
  7463.    if( this.mFrame===0 )
  7464.    {
  7465.        for( let i=0; i<this.mMaxBuffers; i++ )
  7466.        {
  7467.            if( this.mBuffers[i].mTexture[0]!==null )
  7468.            {
  7469.                this.mRenderer.SetRenderTarget( this.mBuffers[i].mTarget[0] );
  7470.                this.mRenderer.Clear( this.mRenderer.CLEAR.Color, [0.0,0.0,0.0,0.0], 1.0, 0   );
  7471.                this.mRenderer.SetRenderTarget( this.mBuffers[i].mTarget[1] );
  7472.                this.mRenderer.Clear( this.mRenderer.CLEAR.Color, [0.0,0.0,0.0,0.0], 1.0, 0   );
  7473. this.mRenderer.CreateMipmaps( this.mBuffers[i].mTexture[0] );
  7474. this.mRenderer.CreateMipmaps( this.mBuffers[i].mTexture[1] );
  7475.            }
  7476.        }
  7477.        for( let i=0; i<this.mMaxCubeBuffers; i++ )
  7478.        {
  7479.            if( this.mCubeBuffers[i].mTexture[0]!==null )
  7480.            {
  7481.                for( let face=0; face<6; face++ )
  7482.                {
  7483.                    this.mRenderer.SetRenderTargetCubeMap( this.mCubeBuffers[i].mTarget[0], face );
  7484.                    this.mRenderer.Clear( this.mRenderer.CLEAR.Color, [0.0,0.0,0.0,0.0], 1.0, 0   );
  7485.                    this.mRenderer.SetRenderTargetCubeMap( this.mCubeBuffers[i].mTarget[1], face );
  7486.                    this.mRenderer.Clear( this.mRenderer.CLEAR.Color, [0.0,0.0,0.0,0.0], 1.0, 0   );
  7487. this.mRenderer.CreateMipmaps( this.mCubeBuffers[i].mTexture[0] );
  7488.    this.mRenderer.CreateMipmaps( this.mCubeBuffers[i].mTexture[1] );
  7489.                }
  7490.            }
  7491.        }
  7492.    }
  7493.  
  7494.    let num = this.mPasses.length;
  7495.  
  7496.    // render sound first
  7497.    for( let i=0; i<num; i++ )
  7498.    {
  7499.        if( this.mPasses[i].mType !== "sound" ) continue;
  7500.        if( this.mPasses[i].mProgram===null ) continue;
  7501.        this.mPasses[i].Paint( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, isPaused, null, false, this.mBuffers, this.mCubeBuffers, this.mKeyboard, this );
  7502.    }
  7503.  
  7504.    // render buffers second
  7505.    for( let i=0; i<num; i++ )
  7506.    {
  7507.        if( this.mPasses[i].mType !== "buffer" ) continue;
  7508.        if( this.mPasses[i].mProgram===null ) continue;
  7509.        let bufferID = assetID_to_bufferID( this.mPasses[i].mOutputs[0] );
  7510.  
  7511.        // check if any downstream pass needs mipmaps when reading from this buffer
  7512.        let needMipMaps = false;
  7513.        for (let j=0; j<num; j++ )
  7514.        {
  7515.            for (let k=0; k<this.mPasses[j].mInputs.length; k++ )
  7516.            {
  7517.                let inp = this.mPasses[j].mInputs[k];
  7518.                if( inp!==null && inp.mInfo.mType==="buffer" && inp.id === bufferID && inp.mInfo.mSampler.filter === "mipmap")
  7519.                {
  7520.                    needMipMaps = true;
  7521.                    break;
  7522.                }
  7523.            }
  7524.        }
  7525.  
  7526.        this.mPasses[i].Paint( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, isPaused, bufferID, needMipMaps, this.mBuffers, this.mCubeBuffers, this.mKeyboard, this );
  7527.    }
  7528.  
  7529.    // render cubemap buffers second
  7530.    for( let i=0; i<num; i++ )
  7531.    {
  7532.        if( this.mPasses[i].mType !== "cubemap" ) continue;
  7533.        if( this.mPasses[i].mProgram===null ) continue;
  7534.        let bufferID = 0;//assetID_to_bufferID( this.mPasses[i].mOutputs[0] );
  7535.  
  7536.        // check if any downstream pass needs mipmaps when reading from this buffer
  7537.        let needMipMaps = false;
  7538.  
  7539.        for (let j=0; j<num; j++ )
  7540.        {
  7541.            for (let k=0; k<this.mPasses[j].mInputs.length; k++ )
  7542.            {
  7543.                let inp = this.mPasses[j].mInputs[k];
  7544.                if( inp!==null && inp.mInfo.mType==="cubemap" )
  7545.                {
  7546.                    if( assetID_to_cubemapBuferID(inp.mInfo.mID)===0 && inp.mInfo.mSampler.filter === "mipmap" )
  7547.                    {
  7548.                        needMipMaps = true;
  7549.                        break;
  7550.                    }
  7551.                }
  7552.            }
  7553.        }
  7554.  
  7555.        this.mPasses[i].Paint( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, isPaused, bufferID, needMipMaps, this.mBuffers, this.mCubeBuffers, this.mKeyboard, this );
  7556.    }
  7557.  
  7558.    // render image last
  7559.    for( let i=0; i<num; i++ )
  7560.    {
  7561.        if( this.mPasses[i].mType !== "image" ) continue;
  7562.        if( this.mPasses[i].mProgram===null ) continue;
  7563.        this.mPasses[i].Paint( vrData, wa, da, time, dtime, fps, mouseOriX, mouseOriY, mousePosX, mousePosY, xres, yres, isPaused, null, false, this.mBuffers, this.mCubeBuffers, this.mKeyboard, this );
  7564.    }  
  7565.  
  7566.    // erase keypresses
  7567.    for (let k=0; k<256; k++ )
  7568.    {
  7569.       this.mKeyboard.mData[ k + 1*256 ] = 0;
  7570.    }
  7571.    this.mRenderer.UpdateTexture( this.mKeyboard.mTexture, 0, 0, 256, 3, this.mKeyboard.mData );
  7572.  
  7573.    if( this.mRenderingStereo ) this.mWebVR.Finish();
  7574.  
  7575.    this.mFrame++;
  7576. }
  7577.  
  7578. Effect.prototype.NewShader = function( passid, preventCache, onResolve )
  7579. {
  7580.    let commonSourceCodes = [];
  7581.    for (let i=0; i<this.mPasses.length; i++ )
  7582.    {
  7583.        if( this.mPasses[i].mType==="common")
  7584.        {
  7585.            commonSourceCodes.push(this.mPasses[i].mSource);
  7586.        }
  7587.    }
  7588.  
  7589.    this.mPasses[passid].NewShader(commonSourceCodes, preventCache, onResolve );
  7590. }
  7591.  
  7592. Effect.prototype.GetNumPasses = function()
  7593. {
  7594.    return this.mPasses.length;
  7595. }
  7596.  
  7597. Effect.prototype.GetNumOfType = function(passtype)
  7598. {
  7599.    let id = 0;
  7600.    for (let j=0; j<this.mPasses.length; j++ )
  7601.    {
  7602.        if( this.mPasses[j].mType===passtype )
  7603.        {
  7604.            id++;
  7605.        }
  7606.    }
  7607.    return id;
  7608. }
  7609.  
  7610. Effect.prototype.GetPassType = function( id ) { return this.mPasses[id].mType; }
  7611. Effect.prototype.GetPassName = function( id ) { return this.mPasses[id].mName; }
  7612. Effect.prototype.GetCode = function( id ) { return this.mPasses[id].mSource; }
  7613. Effect.prototype.SetCode = function( id, source ) { this.mPasses[id].SetCode(source); }
  7614. Effect.prototype.GetError = function (id) { return this.mPasses[id].mError; }
  7615. Effect.prototype.GetErrorStr = function (id) { return this.mPasses[id].mErrorStr; }
  7616. Effect.prototype.GetErrorGlobal = function()
  7617. {
  7618.    for (let i = 0; i < this.mPasses.length; i++)
  7619.    {
  7620.        if (this.mPasses[i].mError)
  7621.        {
  7622.            return true;
  7623.        }
  7624.    }
  7625.    return false;
  7626. }
  7627.  
  7628. Effect.prototype.Load = function (jobj )
  7629. {
  7630.    if (jobj.ver !== "0.1")
  7631.    {
  7632.        console.log("Wrong Format");
  7633.        return false;
  7634.    }
  7635.  
  7636.    let numPasses = jobj.renderpass.length;
  7637.  
  7638.    if( numPasses<1 || numPasses>this.mMaxPasses )
  7639.    {
  7640.        console.log("Corrupted Shader - " + numPasses);
  7641.        return false;
  7642.    }
  7643.  
  7644.    this.mPasses = [];
  7645.    for (let j = 0; j < numPasses; j++)
  7646.    {
  7647.        let rpass = jobj.renderpass[j];
  7648.  
  7649.        // skip sound passes if in thumbnail mode
  7650.        if( this.mForceMuted && rpass.type === "sound" ) continue;
  7651.  
  7652.        let wpass = new EffectPass(this.mRenderer, this.mIs20, this.mIsLowEnd, this.mShaderTextureLOD,
  7653.                                   this.mTextureCallbackFun, this.mTextureCallbackObj, this.mForceMuted, this.mForcePaused, this.mGainNode,
  7654.                                   this.mProgramDownscale, j, this);
  7655.  
  7656.        wpass.Create(rpass.type, this.mAudioContext);
  7657.  
  7658.        let numInputs = rpass.inputs.length;
  7659.  
  7660.        for (let i = 0; i < 4; i++)
  7661.        {
  7662.            wpass.NewTexture(this.mAudioContext, i, null, null, null);
  7663.        }
  7664.        for (let i = 0; i < numInputs; i++)
  7665.        {
  7666.            let lid  = rpass.inputs[i].channel;
  7667.            let styp = rpass.inputs[i].type;
  7668.            let sid  = rpass.inputs[i].id;
  7669.            let ssrc = rpass.inputs[i].filepath;
  7670.            let psrc = rpass.inputs[i].previewfilepath;
  7671.            let samp = rpass.inputs[i].sampler;
  7672.  
  7673.            wpass.NewTexture(this.mAudioContext, lid, { mType: styp, mID: sid, mSrc: ssrc, mSampler: samp, mPreviewSrc: psrc }, this.mBuffers, this.mCubeBuffers, this.mKeyboard);
  7674.        }
  7675.  
  7676.        for (let i = 0; i < 4; i++)
  7677.        {
  7678.            wpass.SetOutputs(i, null);
  7679.        }
  7680.  
  7681.        let numOutputs = rpass.outputs.length;
  7682.        for (let i = 0; i < numOutputs; i++)
  7683.        {
  7684.            let outputID = rpass.outputs[i].id;
  7685.            let outputCH = rpass.outputs[i].channel;
  7686.            wpass.SetOutputs(outputCH, outputID);
  7687.        }
  7688.  
  7689.        // create some hardcoded names. This should come from the DB
  7690.        let rpassName = "";
  7691.        if (rpass.type === "common" ) rpassName = "Common";
  7692.        if (rpass.type === "sound"  ) rpassName = "Sound";
  7693.        if (rpass.type === "image"  ) rpassName = "Image";
  7694.        if (rpass.type === "buffer") rpassName = "Buffer " + String.fromCharCode(65 + assetID_to_bufferID(wpass.mOutputs[0]));
  7695.        if (rpass.type === "cubemap") rpassName = "Cube A";// " + String.fromCharCode(65 + assetID_to_bufferID(this.mPasses[j].mOutputs[0]));
  7696.        wpass.SetName(rpassName);
  7697.        wpass.SetCode(rpass.code);
  7698.  
  7699.        this.mPasses.push(wpass);
  7700.    }
  7701.    return true;
  7702. }
  7703.  
  7704. Effect.prototype.CompileSome = function ( passes, preventCache, onResolve )
  7705. {
  7706.    let me = this;
  7707.  
  7708.    let to = getRealTime();
  7709.    let allPromisses = [];
  7710.    for (let j = 0; j < passes.length; j++)
  7711.    {
  7712.        allPromisses.push(new Promise(function (resolve, reject)
  7713.        {
  7714.            me.NewShader(passes[j], preventCache, function () { resolve(1); });
  7715.        }));
  7716.    }
  7717.  
  7718.    // aggregated callback when all passes have been compiled
  7719.    Promise.all(allPromisses).then(function (values)
  7720.    {
  7721.        let totalError = false;
  7722.        for (let j = 0; j < me.mPasses.length; j++)
  7723.        {
  7724.            if (me.mPasses[j].mError)
  7725.            {
  7726.                totalError = true;
  7727.                break;
  7728.            }
  7729.        }
  7730.        me.mCompilationTime = getRealTime() - to;
  7731.        onResolve(!totalError);
  7732.    }).catch(console.log);
  7733. }
  7734.  
  7735. Effect.prototype.Compile = function (preventCache, onResolve )
  7736. {
  7737.    let me = this;
  7738.  
  7739.    let to = getRealTime();
  7740.    let allPromisses = [];
  7741.    let numPasses = this.mPasses.length;
  7742.    for (let j = 0; j < numPasses; j++)
  7743.    {
  7744.        allPromisses.push(new Promise(function (resolve, reject)
  7745.        {
  7746.            me.NewShader(j, preventCache, function () { resolve(1); });
  7747.        }));
  7748.    }
  7749.  
  7750.    // aggregated callback when all passes have been compiled
  7751.    Promise.all(allPromisses).then(function (values)
  7752.    {
  7753.        let totalError = false;
  7754.        for (let j = 0; j < numPasses; j++)
  7755.        {
  7756.            if (me.mPasses[j].mError)
  7757.            {
  7758.                totalError = true;
  7759.                break;
  7760.            }
  7761.        }
  7762.        me.mCompilationTime = getRealTime() - to;
  7763.        onResolve(!totalError);
  7764.    }).catch(console.log);
  7765. }
  7766.  
  7767. Effect.prototype.GetCompilationTime = function( id )
  7768. {
  7769.    return this.mPasses[id].GetCompilationTime()/1000.0;
  7770. }
  7771. Effect.prototype.GetTotalCompilationTime = function()
  7772. {
  7773.    return this.mCompilationTime/1000.0;
  7774. }
  7775.  
  7776. Effect.prototype.DestroyPass = function( id )
  7777. {
  7778.   this.mPasses[id].Destroy( this.mAudioContext );
  7779.   this.mPasses.splice(id, 1);
  7780. }
  7781.  
  7782. Effect.prototype.AddPass = function( passType, passName, onResolve )
  7783. {
  7784.    let shaderStr = null;
  7785.  
  7786.    if( passType==="sound"   ) shaderStr = "vec2 mainSound( int samp, float time )\n{\n    // A 440 Hz wave that attenuates quickly overt time\n    return vec2( sin(6.2831*440.0*time)*exp(-3.0*time) );\n}";
  7787.    if( passType==="buffer"  ) shaderStr = "void mainImage( out vec4 fragColor, in vec2 fragCoord )\n{\n    fragColor = vec4(0.0,0.0,1.0,1.0);\n}";
  7788.    if( passType==="common"  ) shaderStr = "vec4 someFunction( vec4 a, float b )\n{\n    return a+b;\n}";
  7789.    if( passType==="cubemap" ) shaderStr = "void mainCubemap( out vec4 fragColor, in vec2 fragCoord, in vec3 rayOri, in vec3 rayDir )\n{\n    // Ray direction as color\n    vec3 col = 0.5 + 0.5*rayDir;\n\n    // Output to cubemap\n    fragColor = vec4(col,1.0);\n}";
  7790.  
  7791.    let id = this.GetNumPasses();
  7792.    this.mPasses[id] = new EffectPass( this.mRenderer, this.mIs20, this.mIsLowEnd, this.mShaderTextureLOD,
  7793.                                       this.mTextureCallbackFun, this.mTextureCallbackObj, this.mForceMuted, this.mForcePaused, this.mGainNode,
  7794.                                       this.mProgramDownscale, id, this );
  7795.  
  7796.    this.mPasses[id].Create( passType, this.mAudioContext );
  7797.    this.mPasses[id].SetName( passName );
  7798.    this.mPasses[id].SetCode( shaderStr );
  7799.    this.NewShader(id, false, function ()
  7800.    {
  7801.        onResolve();
  7802.    });
  7803.  
  7804.    return { mId : id, mShader : shaderStr };
  7805. }
  7806.  
  7807. // this should be removed once we have MultiPass 2.0 and passes render to arbitrary buffers
  7808. Effect.prototype.IsBufferPassUsed = function( bufferID )
  7809. {
  7810.    for (let j=0; j<this.mPasses.length; j++ )
  7811.    {
  7812.        if( this.mPasses[j].mType !== "buffer" ) continue;
  7813.        if( this.mPasses[j].mOutputs[0] === bufferID_to_assetID(bufferID) ) return true;
  7814.    }
  7815.    return false;
  7816. }
  7817.  
  7818. Effect.prototype.Save = function()
  7819. {
  7820.    var result = {};
  7821.  
  7822.    result.ver = "0.1";
  7823.  
  7824.    result.renderpass = [];
  7825.  
  7826.    let numPasses = this.mPasses.length;
  7827.    for (let j=0; j<numPasses; j++ )
  7828.    {
  7829.        result.renderpass[j] = {};
  7830.  
  7831.        result.renderpass[j].outputs = new Array();
  7832.        for (let i = 0; i<4; i++ )
  7833.        {
  7834.            let outputID = this.mPasses[j].mOutputs[i];
  7835.            if( outputID===null ) continue;
  7836.            result.renderpass[j].outputs.push( { channel: i, id: outputID } );
  7837.        }
  7838.        result.renderpass[j].inputs = new Array();
  7839.        for (let i = 0; i<4; i++ )
  7840.        {
  7841.            if( this.mPasses[j].mInputs[i]===null ) continue;
  7842.            result.renderpass[j].inputs.push( {channel: i,
  7843.                                               type    : this.mPasses[j].mInputs[i].mInfo.mType,
  7844.                                               id      : this.mPasses[j].mInputs[i].mInfo.mID,
  7845.                                               filepath: this.mPasses[j].mInputs[i].mInfo.mSrc,
  7846.                                               sampler : this.mPasses[j].mInputs[i].mInfo.mSampler });
  7847.        }
  7848.  
  7849.        result.renderpass[j].code = this.mPasses[j].mSource;
  7850.        result.renderpass[j].name = this.mPasses[j].mName
  7851.        result.renderpass[j].description = "";
  7852.        result.renderpass[j].type = this.mPasses[j].mType;
  7853.    }
  7854.  
  7855.    result.flags = this.calcFlags();
  7856.  
  7857.    return result;
  7858. }
  7859.  
  7860. Effect.prototype.calcFlags = function ()
  7861. {
  7862.    let flagVR = false;
  7863.    let flagWebcam = false;
  7864.    let flagSoundInput = false;
  7865.    let flagSoundOutput = false;
  7866.    let flagKeyboard = false;
  7867.    let flagMultipass = false;
  7868.    let flagMusicStream = false;
  7869.  
  7870.    let numPasses = this.mPasses.length;
  7871.    for (let j = 0; j < numPasses; j++)
  7872.    {
  7873.        let pass = this.mPasses[j];
  7874.  
  7875.        if (pass.mType === "sound") flagSoundOutput = true;
  7876.        if (pass.mType === "buffer") flagMultipass = true;
  7877.  
  7878.        for (let i = 0; i < 4; i++)
  7879.        {
  7880.            if (pass.mInputs[i] === null) continue;
  7881.  
  7882.            if (pass.mInputs[i].mInfo.mType === "webcam") flagWebcam = true;
  7883.            else if (pass.mInputs[i].mInfo.mType === "keyboard") flagKeyboard = true;
  7884.            else if (pass.mInputs[i].mInfo.mType === "mic") flagSoundInput = true;
  7885.            else if (pass.mInputs[i].mInfo.mType === "musicstream") flagMusicStream = true;
  7886.        }
  7887.  
  7888.        let n1 = pass.mSource.indexOf("mainVR(");
  7889.        let n2 = pass.mSource.indexOf("mainVR (");
  7890.        if (n1 > 0 || n2 > 0) flagVR = true;
  7891.    }
  7892.  
  7893.    return {
  7894.        mFlagVR: flagVR,
  7895.        mFlagWebcam: flagWebcam,
  7896.        mFlagSoundInput: flagSoundInput,
  7897.        mFlagSoundOutput: flagSoundOutput,
  7898.        mFlagKeyboard: flagKeyboard,
  7899.        mFlagMultipass: flagMultipass,
  7900.        mFlagMusicStream: flagMusicStream
  7901.    };
  7902. }</script>
  7903.    <script>"use strict"
  7904.  
  7905. const kMaxCompileTime = 10.0;
  7906.  
  7907. function iReportCrash(shaderID)
  7908. {
  7909.    let req = new XMLHttpRequest();
  7910.    req.onload = function ()
  7911.    {
  7912.        let jsn = req.response;
  7913.        if (jsn === null) return;
  7914.        if (jsn.result === 0)
  7915.        {
  7916.            // yep
  7917.        }
  7918.    };
  7919.    req.open("POST", "/shadertoy", true);
  7920.    req.responseType = "json";
  7921.    req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  7922.    req.send( "s=" + shaderID + "&r=2" );
  7923. }
  7924. </script>
  7925.    <script>"use strict"
  7926.  
  7927. var gActive = -1;
  7928. var mShaders = [];
  7929. var gNumCanvases = 0;
  7930.  
  7931. function myrefresh( id, slot, img, forceFrame, gui, guiID, renderID, time )
  7932. {
  7933.    if( mShaders[id].mReady===false ) return;
  7934.    if( forceFrame )
  7935.    {
  7936.        if (mShaders[id].mScreenshot === false)
  7937.        {
  7938.            mShaders[id].gEffect.Paint(mShaders[id].mTime / 1000.0, 1.0 / 60.0, 60.0, 0, 0, 0, 0, false);
  7939.        }
  7940.    }
  7941. }
  7942.  
  7943. function startRendering()
  7944. {
  7945.    if( gActive<0 ) return;
  7946.    if( mShaders[gActive].mReady===false ) return;
  7947.    if( mShaders[gActive].mScreenshot===true ) return;
  7948.  
  7949.    let time = getRealTime();
  7950.  
  7951.    mShaders[gActive].mFPS.Count( time );
  7952.    mShaders[gActive].mTime = mShaders[gActive].mTime0 + (time - mShaders[gActive].mTo);
  7953.    let dtime = 1000.0/60.0;
  7954.    mShaders[gActive].gEffect.Paint( mShaders[gActive].mTime/1000.0, dtime/1000.0, mShaders[gActive].mFPS.GetFPS(), 0,0,0,0, false);
  7955.  
  7956.    requestAnimFrame( startRendering );
  7957. }
  7958.  
  7959. function iLoadAndCompile(jsn, i )
  7960. {
  7961.    var shaderObj = jsn[i];
  7962.    if (shaderObj === null) return;
  7963.  
  7964.    var resizeCB = function (xres, yres) { myrefresh(i, 0, null, true, false, 0, -1.0) };
  7965.    var crashCB = function () { alert('crash');/*iReportCrash(gShaderIDs[i])*/ };
  7966.    mShaders[i].gEffect = new Effect(null, null, mShaders[i].mPreview.mCanvas, myrefresh, i, true, true, resizeCB, crashCB);
  7967.  
  7968.    if (!mShaders[i].gEffect.Load(shaderObj)) return;
  7969.  
  7970.    mShaders[i].gEffect.Compile(false, function (worked)
  7971.    {
  7972.        if (worked === true)
  7973.        {
  7974.            previewShowRender(mShaders[i].mPreview);
  7975.  
  7976.            mShaders[i].mScreenshot = false;
  7977.            mShaders[i].mReady = true;
  7978.            mShaders[i].mTime = 10.0 * 1000.0;
  7979.            mShaders[i].mTime0 = 0.0;
  7980.            mShaders[i].mTo = 0.0;
  7981.            mShaders[i].mFPS = piCreateFPSCounter();
  7982.            mShaders[i].mPreview.mCanvas.addEventListener("mouseout", function (ev) { gActive = -1; }, true);
  7983.            mShaders[i].mPreview.mBase.addEventListener("mouseover", function (ev) { if (mShaders[i].mPreview.mUI !== null) mShaders[i].mPreview.mUI.classList.add('isVisible'); }, true);
  7984.            mShaders[i].mPreview.mBase.addEventListener("mouseout", function (ev) { if (mShaders[i].mPreview.mUI !== null) mShaders[i].mPreview.mUI.classList.remove('isVisible'); }, true);
  7985.            mShaders[i].mPreview.mCanvas.addEventListener("mouseover", function (ev)
  7986.            {
  7987.                let ele = piGetSourceElement(ev);
  7988.                if (ele.mId === undefined) return;
  7989.  
  7990.                gActive = ele.mId;
  7991.                if (!mShaders[gActive].mReady) return;
  7992.                let time = getRealTime();
  7993.                mShaders[gActive].mTo = time;
  7994.                mShaders[gActive].mTime0 = mShaders[gActive].mTime;
  7995.                mShaders[gActive].mFPS.Reset(time);
  7996.  
  7997.                startRendering();
  7998.            }, true);
  7999.  
  8000.  
  8001.            /*
  8002.            let compilationTime = mShaders[i].gEffect.GetTotalCompilationTime();
  8003.            if (compilationTime > kMaxCompileTime)
  8004.            {
  8005.                iReportCrash(mShaders[i].mShaderID);
  8006.            }*/
  8007.  
  8008.            myrefresh(i, null, null, true, false, 0, -1.0);
  8009.        }
  8010.        else
  8011.        {
  8012.            mShaders[i].mReady = false;
  8013.            previewShowError(mShaders[i].mPreview);
  8014.        }
  8015.    });
  8016. };
  8017.  
  8018.  
  8019. function iProcessShader( jsn, i )
  8020. {
  8021.    var shaderObj = jsn[i];
  8022.    if( shaderObj===null ) return;
  8023.  
  8024.    if ((shaderObj.info.usePreview === 0 && !gUseScreenshots) || (mShaders[i].mPreviewReady !== 1))
  8025.    {
  8026.        iLoadAndCompile(jsn, i);
  8027.    }
  8028.    else
  8029.    {
  8030.        mShaders[i].mScreenshot = true;
  8031.        if( shaderObj.info.usePreview === 1 )
  8032.            previewShowScreenshot(mShaders[i].mPreview, 1); // comp
  8033.        else if (gUseScreenshots)
  8034.            previewShowScreenshot(mShaders[i].mPreview, 2); // sett
  8035.    }
  8036.  
  8037.    if( i<(jsn.length-1) ) setTimeout( function(){iProcessShader(jsn,i+1);}, 10 );
  8038. }
  8039.  
  8040. function iInitUI(numCanvases, uiCallback, windowTitle)
  8041. {
  8042.    gNumCanvases = numCanvases;
  8043.    document.getElementById("mySearch").focus();
  8044.  
  8045.    //-----------------------------------------------------------------
  8046.    // window
  8047.    //-----------------------------------------------------------------
  8048.    if (windowTitle !== null) {
  8049.        document.title = windowTitle;
  8050.    }
  8051.  
  8052.    //-----------------------------------------------------------------
  8053.    // ui
  8054.    //-----------------------------------------------------------------
  8055.    var num = Math.min(gShaders.length, gNumCanvases);
  8056.  
  8057.    //var base = document.getElementsByClassName( "searchResult" );
  8058.  
  8059.    for (let i = 0; i < gNumCanvases; i++)
  8060.    {
  8061.        let pv = createPreview(i);
  8062.  
  8063.        if (i >= num) {
  8064.            previewHide(pv);
  8065.            continue;
  8066.        }
  8067.  
  8068.        let shaderID = gShaders[i].info.id;
  8069.        
  8070.        if (pv.mUI !== null && uiCallback !== null) {
  8071.            pv.mUI.addEventListener('click', function (ev) {
  8072.                uiCallback(shaderID);
  8073.                ev.preventDefault();
  8074.            }, false);
  8075.        }
  8076.        
  8077.        previewShowLoading(pv);
  8078.        
  8079.        mShaders[i] = {};
  8080.        mShaders[i].mShaderID = shaderID;
  8081.        mShaders[i].mPreview = pv;
  8082.        mShaders[i].mScreenshot = false;
  8083.        mShaders[i].mPreview.mLink.href = "/view/" + shaderID;
  8084.        mShaders[i].mPreviewReady = 0;
  8085.        mShaders[i].mReady = false;
  8086.        mShaders[i].gEffect = null;
  8087.  
  8088.        previewLoadScreenshot(mShaders[i].mPreview,
  8089.            function () { mShaders[i].mPreviewReady = 1; if (mShaders[i].mReady === false) previewShowScreenshot(mShaders[i].mPreview, 0); },
  8090.            function () { mShaders[i].mPreviewReady = 2; },
  8091.            shaderID);
  8092.    }
  8093.  
  8094.    if (num <= 0) {
  8095.        return;
  8096.    }
  8097. }
  8098.  
  8099. function iInitShaders(jsn)
  8100. {
  8101.    for (let i = 0; i < jsn.length; i++)
  8102.    {
  8103.        let shaderObj = jsn[i];
  8104.        if (shaderObj === null) continue;
  8105.        let inf = shaderObj.info;
  8106.        mShaders[i].mPreview.mTextA.textContent = inf.name;
  8107.        mShaders[i].mPreview.mTextB.innerHTML = "<a class='user' href='/user/" + htmlEntities(inf.username) + "'>" + htmlEntities(inf.username) + "</a>";
  8108.        mShaders[i].mPreview.mTextC.innerHTML = "<img src='/img/themes/" + gThemeName + "/views.png' class='viewsIcon'></img>" + inf.viewed + "    &nbsp;&nbsp;  <img src='/img/themes/" + gThemeName + "/likes.png' class='likesIcon'></img>" + inf.likes;
  8109.    }
  8110.  
  8111.    setTimeout(function () { iProcessShader(jsn, 0); }, 10);
  8112. }
  8113.  
  8114. function resultsInitStatic(numCanvases, uiCallback, windowTitle)
  8115. {
  8116.    iInitUI(numCanvases, uiCallback, windowTitle);
  8117.  
  8118.    iInitShaders(gShaders);
  8119. }
  8120.  
  8121. function resultsInit(numCanvases, uiCallback, windowTitle)
  8122. {
  8123.    iInitUI(numCanvases, uiCallback, windowTitle);
  8124.  
  8125.    var num = Math.min(gShaderIDs.length, gNumCanvases);
  8126.  
  8127.    var mHttpReq = new XMLHttpRequest();
  8128.  
  8129.    mHttpReq.abort();
  8130.  
  8131.    var str = "{ \"shaders\" : [";
  8132.    for( let i=0; i<num; i++ )
  8133.    {
  8134.         str += "\"" + gShaderIDs[i] + "\"";
  8135.         if( i!==(num-1) ) str += ", ";
  8136.    }
  8137.    str += "] }";
  8138.  
  8139.    str = "s=" + encodeURIComponent( str ) + "&nt=0&nl=0&np=0";
  8140.  
  8141.    mHttpReq.open( "POST", "/shadertoy", true );
  8142.    mHttpReq.responseType = "json";
  8143.    mHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  8144.    mHttpReq.onload = function ()
  8145.    {
  8146.        let jsn = this.response;
  8147.        if( jsn===null )
  8148.        {
  8149.            console.log( "Could not load shaders" );
  8150.            return;
  8151.        }
  8152.  
  8153.        iInitShaders(jsn);
  8154.    }
  8155.    mHttpReq.send( str );
  8156. }</script>
  8157.    <style>
  8158.    .shaderPreview
  8159.    {
  8160.    display: block;
  8161.    background-color: #000000;
  8162.    background-image: url("/img/loading.gif");
  8163.    background-repeat: no-repeat;
  8164.    background-position: center;
  8165.    padding: 0px;
  8166.    margin: 0px;
  8167.    border: 0px solid #000000;
  8168.    border-radius: 8px;
  8169.    width:100%;
  8170.    height:100%;
  8171.    position: absolute;
  8172.    overflow:hidden;
  8173.    }
  8174.  
  8175.    .previewInfo
  8176.    {
  8177.    width: 100%;
  8178.    left: 0px;
  8179.    top: 2px;
  8180.    position: relative;
  8181.    visibility: hidden;
  8182.    }
  8183.  
  8184.    .previewCanvas
  8185.    {
  8186.    left: 0px;
  8187.    top: 0px;
  8188.    padding: 0px;
  8189.    margin: 0px;
  8190.    position: absolute;
  8191.    cursor: pointer;
  8192.    width:100%;
  8193.    height:100%;
  8194.    border-radius: 8px;
  8195.    border: 0px solid #000000;
  8196.    backgroundColor: transparent;
  8197. visibility: hidden;
  8198. opacity:0;
  8199. transition: opacity 1.0s ease;
  8200.    }
  8201.  
  8202.    .previewText
  8203.    {
  8204.        text-overflow: ellipsis;
  8205.    white-space: nowrap;
  8206.    padding-right: 1px;
  8207.    }
  8208.  
  8209.    .previewTextUser
  8210.    {
  8211.    text-overflow: ellipsis;
  8212.    white-space: nowrap;
  8213.    padding-left: 3px;
  8214.    }
  8215.  
  8216.    .previewStats
  8217.    {
  8218.    padding-right: 1px;
  8219.    right: 0px;
  8220.    top: 0px;
  8221.    position: absolute;
  8222.    }
  8223.  
  8224.    .previewErrorContainer
  8225.    {
  8226.    left:0px;
  8227.    top:0px;
  8228.    width:100%;
  8229.    height:100%;
  8230.    padding:0px;
  8231.    margin:0px;
  8232.    background-color:#000000;
  8233.    border-radius:8px;
  8234.    cursor:pointer;
  8235.    visibility:hidden;
  8236.    }
  8237.  
  8238.    .previewErrorMessage
  8239.    {
  8240.    top:50%;
  8241.    position:absolute;
  8242.    width:100%;
  8243.    text-align:center;
  8244.    padding:0;
  8245.    margin:auto;
  8246.    color:#ff0000;
  8247.    font-size:2em;
  8248.    font-style:italic;
  8249.    }
  8250.  
  8251.    .previewNoGLContainter
  8252.    {
  8253.    left:0px;
  8254.    top:0px;
  8255.    width:100%;
  8256.    height:100%;
  8257.    padding:0px;
  8258.    margin:0px;
  8259.    position:absolute;
  8260.    background-color:#000000;
  8261.    border-radius:8px;
  8262.    cursor:pointer;
  8263.    pointer-events:none;
  8264.    visibility:hidden;
  8265.    font-size:2em;
  8266.    }
  8267.  
  8268.    .previewNoGLMessage
  8269.    {
  8270.    width:86%;
  8271.    height:90%;
  8272.    padding-left:7%;
  8273.    padding-right:7%;
  8274.    padding-top:10%;
  8275.    padding-bottom:0px;
  8276.    color:#ff0000;
  8277.    position:absolute;
  8278.    visibility:hidden;
  8279.    }
  8280.  
  8281.    .previewThumbnailContainer
  8282.    {
  8283.    width:100%;
  8284.    height:100%;
  8285.    left:0px;
  8286.    top:0px;
  8287.    padding:0px;
  8288.    margin:0px;
  8289.    position:absolute;
  8290.    cursor:pointer;
  8291.    visibility:hidden;
  8292.    border-radius:8px;
  8293.    border:0px solid #000000;
  8294.    }
  8295.  
  8296.    .previewThumbnailImage
  8297.    {
  8298.    width:100%;
  8299.    height:100%;
  8300.    left:0px;
  8301.    top:0px;
  8302.    padding:0px;
  8303.    margin:0px;
  8304.    position:absolute;
  8305.    cursor:pointer;
  8306.    border-radius:8px;
  8307.    border:0px solid #000000;
  8308. opacity: 0.0;
  8309. transition: opacity 1.0s ease;
  8310.    }
  8311.  
  8312.    .previewThumbnailIcon
  8313.    {
  8314.    width:64px;
  8315.    height:32px;
  8316.    left:0px;
  8317.    top:0px;
  8318.    padding:0px;
  8319.    padding-top:12px;
  8320.    margin:0px;
  8321.    position:absolute;
  8322.    color:#ffffff;
  8323.    background-color:#ff8020;
  8324.    font-weight:bold;
  8325.    border-radius:0px 0px 8px 0px;
  8326.    text-align:center;
  8327.    //visibility:hidden;
  8328.    }
  8329.  
  8330.  
  8331.    .previewUIContainter
  8332.    {
  8333.    display: block;
  8334.    right:0px;
  8335.    top:0px;
  8336.    padding:0px;
  8337.    margin:0px;
  8338.    position:absolute;
  8339.    //cursor:pointer;
  8340.    //pointer-events:none;
  8341.    //visibility:hidden;
  8342.    }
  8343. </style>
  8344.  
  8345. <script>
  8346.    function previewHide(me)
  8347.    {
  8348.    me.mBase.style.visibility = "hidden";
  8349.    me.mCanvas.style.visibility = "hidden";
  8350.    me.mCanvas2D.style.visibility = "hidden";
  8351.    me.mNoWebGL.style.visibility = "hidden";
  8352.    me.mError.style.visibility = "hidden";
  8353.    me.mCont.style.visibility = "hidden";
  8354.    }
  8355.  
  8356.    function previewShowRender(me)
  8357.    {
  8358.    me.mBase.style.visibility = "visible";
  8359.    me.mCanvas.style.visibility = "visible";
  8360. me.mCanvas.style.opacity = 1.0;
  8361.    me.mCanvas.style.borderRadius ="8px;";
  8362. //  me.mCanvas2D.style.visibility = "hidden";
  8363.    me.mNoWebGL.style.visibility = "hidden";
  8364.    me.mError.style.visibility = "hidden";
  8365.    me.mCont.style.visibility = "visible";
  8366.    }
  8367.  
  8368.    function previewShowScreenshot(me, message)
  8369.    {
  8370.    me.mBase.style.visibility = "visible";
  8371.    me.mCanvas.style.visibility = "hidden";
  8372.    me.mCanvas2D.style.visibility = "visible";
  8373. me.mThumbnailImg.style.opacity = 1.0;
  8374.    me.mNoWebGL.style.visibility = "hidden";
  8375.    me.mError.style.visibility = "hidden";
  8376.    me.mCont.style.visibility = "visible";
  8377.    me.mThumbnailWar1.style.visibility = (message===1)?"visible":"hidden";
  8378.    me.mThumbnailWar2.style.visibility = (message===2)?"visible":"hidden";
  8379.    }
  8380.  
  8381.    function previewShowLoading(me)
  8382.    {
  8383.    me.mBase.style.visibility = "visible";
  8384.    me.mCanvas.style.visibility = "hidden";
  8385.    me.mCanvas2D.style.visibility = "hidden";
  8386.    me.mNoWebGL.style.visibility = "hidden";
  8387.    me.mError.style.visibility = "hidden";
  8388.    me.mCont.style.visibility = "hidden";
  8389.  
  8390.    me.mLink.style.visibility = "visible";
  8391.    me.mBase.style.backgroundColor = "#ff0000;"
  8392.    me.mCont.style.visibility = "visible";
  8393.    }
  8394.  
  8395.    function previewShowNoWebGL(me, shaderID)
  8396.    {
  8397.    me.mBase.style.visibility = "visible";
  8398.    me.mCanvas.style.visibility = "hidden";
  8399.    me.mCanvas2D.style.visibility = "hidden";
  8400.    me.mNoWebGL.style.visibility = "visible";
  8401.    me.mError.style.visibility = "visible";
  8402.    me.mThumbnailImgNoWebGL.onerror = function(ev)
  8403.                                      {
  8404.                                            me.mThumbnailImgNoWebGL.style.visibility="hidden";
  8405.                                            me.mMessageNoWebGL.style.visibility="visible";
  8406.                                      };
  8407.    me.mThumbnailImgNoWebGL.src = "/media/shaders/" + shaderID + ".jpg";
  8408.    }
  8409.  
  8410.    function previewShowError(me)
  8411.    {
  8412.    me.mBase.style.visibility = "visible";
  8413.    me.mCanvas.style.visibility = "hidden";
  8414.    me.mCanvas2D.style.visibility = "hidden";
  8415.    me.mNoWebGL.style.visibility = "hidden";
  8416.    me.mError.style.visibility = "visible";
  8417.    me.mCont.style.visibility = "visible";
  8418.    }
  8419.  
  8420.    function previewLoadScreenshot( me, cbSuccess, cbError, shaderID )
  8421.    {
  8422.    var url = "/media/shaders/" + shaderID + ".jpg";
  8423.    me.mThumbnailImg.onload = cbSuccess;
  8424.    me.mThumbnailImg.onerror = function(ev) { cbError(); };
  8425.    me.mThumbnailImg.src = url;
  8426.    }
  8427.        
  8428.    function createPreview(id)
  8429.    {
  8430.        var bar = document.getElementById( "Preview_"+id+"_Canvas" );
  8431.        bar.width = bar.offsetWidth;
  8432.        bar.height = bar.offsetHeight;
  8433.        bar.mId = id;
  8434.  
  8435.        return { mBase: document.getElementById( "Preview_"+id+"_Container" ),
  8436.        mLink: document.getElementById( "Preview_"+id+"_Link" ),
  8437.        mCanvas: bar,
  8438.        mCont: document.getElementById( "Preview_"+id+"_Info" ),
  8439.        mTextA: document.getElementById( "Preview_"+id+"_Text" ),
  8440.        mTextB: document.getElementById( "Preview_"+id+"_TextUser" ),
  8441.        mTextC: document.getElementById( "Preview_"+id+"_Stats" ),
  8442.        mNoWebGL: document.getElementById( "Preview_"+id+"_NoWebGL" ),
  8443.        mError: document.getElementById( "Preview_"+id+"_Error" ),
  8444.        mCanvas2D: document.getElementById( "Preview_"+id+"_Thumnail" ),
  8445.        mThumbnailImg: document.getElementById( "Preview_"+id+"_ThumnailImage" ),
  8446.        mThumbnailWar1: document.getElementById( "Preview_"+id+"_ThumnailWarning1" ),
  8447.        mThumbnailWar2: document.getElementById( "Preview_"+id+"_ThumnailWarning2" ),
  8448.        mThumbnailImgNoWebGL: document.getElementById( "Preview_"+id+"_ThumnailImageNoWebGL" ),
  8449.        mMessageNoWebGL: document.getElementById( "Preview_"+id+"_MessageNoWebGL"),
  8450.        mUI: document.getElementById( "Preview_"+id+"_UI" )
  8451.        };
  8452.    }
  8453. </script>
  8454.  
  8455.    <style>
  8456.  
  8457.    #content
  8458.    {
  8459.        user-select: text;
  8460.        -moz-user-select: -moz-text;
  8461.        -webkit-user-select: text;
  8462.        padding:0px;
  8463.        margin:0px;
  8464.        position:relative;
  8465.    }
  8466.  
  8467.    #divUser
  8468.    {
  8469.        padding:0px;
  8470.        padding-top:24px;
  8471.        padding-bottom:16px;
  8472.        width:100%;
  8473.    }
  8474.  
  8475.    div#controls
  8476.    {
  8477.        width:100%;
  8478.        padding-top:16px;
  8479.        padding-bottom:16px;
  8480.        display:flex;
  8481.        justify-content:space-between;
  8482.        flex-wrap:wrap;
  8483.    }
  8484.  
  8485.    div#controls > div
  8486.    {
  8487.        display:inline-flex;
  8488.    }
  8489.  
  8490.    .controlOptions
  8491.    {
  8492.        display:inline-block;
  8493.    }
  8494.  
  8495.    div#shaderGrid
  8496.    {
  8497.        width:100%;
  8498.        padding:0px;
  8499.        margin:0px;
  8500.        display: grid;
  8501.        grid-template-columns: repeat(4, 1fr);
  8502.        grid-template-rows: repeat(2, 1fr);
  8503.        grid-column-gap: 64px;
  8504.        grid-row-gap: 16px;
  8505.    }
  8506.  
  8507.    .searchResult
  8508.    {
  8509.        margin: 0px;
  8510.        padding: 0px;
  8511.        width: 100%;
  8512.    }
  8513.    .searchResultContainer
  8514.    {
  8515.        width: 100%;
  8516.        padding-bottom:56.25%;
  8517.        height: 0;
  8518.        position: relative;
  8519.    }
  8520.  
  8521.    div#navigation
  8522.    {
  8523.        text-align: center;
  8524.        width: 100%;
  8525.    }
  8526.  
  8527.  
  8528.    #userPicture
  8529.    {
  8530.        background-color:#808080;
  8531.        border: 1px solid #000000;
  8532.        padding:0px;
  8533.        left:0px;
  8534.        top:0px;
  8535.        width:128px;
  8536.        height:128px;
  8537.    }
  8538.  
  8539.    a.pageButtons, .pageButtonsCurrent
  8540.    {
  8541.        
  8542.        //background-color: #303030;
  8543.        border-style: solid;
  8544.        border-width: 1px;
  8545.        border-color: #808080;
  8546.        text-align: center;
  8547.        vertical-align: middle;
  8548.        margin-left: 12px;
  8549.        display: inline-block;
  8550.        border-radius: 4px;
  8551. font-weight:bold;
  8552.        cursor: pointer;
  8553.        padding-bottom:5px;
  8554.        padding-top:4px;
  8555.        padding-left: 8px;
  8556.        padding-right: 8px;
  8557.        margin:8px;
  8558.    }
  8559.  
  8560.    a.pageButtons
  8561.    {
  8562.        text-decoration: none;
  8563.        -moz-transition:    background-color 0.15s linear, color 0.15s linear;
  8564.        -webkit-transition: background-color 0.15s linear, color 0.15s linear;
  8565.        transition:         background-color 0.15s linear, color 0.15s linear;
  8566.    }
  8567.  
  8568.    a.pageButtons:hover
  8569.    {
  8570.      background-color:#808080;
  8571.      color : #ff8020;
  8572.    }
  8573.  
  8574.    .pageButtonsCurrent
  8575.    {
  8576.        background-color: #808080;
  8577.        color:#000000;
  8578.    }
  8579.  
  8580.    /* ----------------------- media resolutions ------------------------ */
  8581.  
  8582.    @media screen and (max-width:799px)
  8583.    {
  8584.        div#shaderGrid  { grid-template-columns: 1fr; grid-template-rows: repeat(8, 1fr); grid-column-gap: 0px; grid-row-gap: 16px; padding-bottom:16px; }
  8585.  
  8586.        div#controls
  8587.        {
  8588.            width:100%;
  8589.            display:flex;
  8590.            justify-content:flex-start;
  8591.            flex-wrap:wrap;
  8592.        }
  8593.  
  8594.        div#controls > div
  8595.        {
  8596.            display:inline-flex;
  8597.            width:100%;
  8598.            margin-left: 0px;
  8599.            margin-right: 0px;
  8600.            padding-bottom:16px;
  8601.        }
  8602.    }
  8603.    </style>
  8604.  
  8605.    <script>
  8606.  
  8607.    var gShaders=[];var gFollow = -1;
  8608.    var gUseScreenshots = piIsMobile();
  8609.    var gThemeName = "classic";
  8610.    </script>
  8611.  
  8612. </head>
  8613.  
  8614. <body onload="resultsInitStatic(8,null,null)">
  8615.  
  8616. <!-- header =================================================================================== -->
  8617.  
  8618.  
  8619. <div id="header">
  8620.  
  8621.    <div id="headerBlock1">
  8622.        <a href="/" id="headerTitle">Shadertoy</a>
  8623.        <form name="formSearch" action="/results" method="get" style="display:inline-block;">
  8624.        <div  id="headerSearch">
  8625.            <input type="search" id="mySearch" name="query" placeholder="Search..." value=""/>
  8626.        </div>
  8627.        </form>
  8628.    </div>
  8629.  
  8630.    <div id="headerBlock2">
  8631.            <a class="headerLinks" href="/browse">Browse</a>
  8632.        <a class="headerLinks" href="/new">New</a>
  8633.        <a class="headerLinks" href="/signin">Sign In</a>
  8634.        </div>
  8635. </div>
  8636. <!-- content ================================================================================== -->
  8637.  
  8638. <div id="content">
  8639.  
  8640.    
  8641.    <script>
  8642.    function follow()
  8643.    {
  8644.        if (gFollow < 0) return;
  8645.        try
  8646.        {
  8647.            var req = new XMLHttpRequest();
  8648.            req.onload = function()
  8649.            {
  8650.                var jsn = req.response;
  8651.                if( jsn==null ) return;
  8652.                let btnFollow = document.getElementById( "btnFollow");
  8653.                if (gFollow == 1) {
  8654.                    gFollow = 0;
  8655.                    btnFollow.value="Follow";
  8656.                } else if (gFollow == 0) {
  8657.                    gFollow = 1;
  8658.                    btnFollow.value="Unfollow";
  8659.                }
  8660.            }
  8661.            req.open( "POST", "/shadertoy", true );
  8662.            req.responseType = "json";
  8663.            req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  8664.            if (gFollow == 1) {
  8665.                var str = "fu=1&uid=StephanUgli654";
  8666.            } else if (gFollow == 0) {
  8667.                var str = "fs=1&uid=StephanUgli654";
  8668.            }
  8669.            req.send( str );
  8670.        }
  8671.        catch(e)
  8672.        {
  8673.            alert( "exception: " + e );
  8674.        }
  8675.    }
  8676.    </script>
  8677.  
  8678.    <!-- ---------------------------------- -->
  8679.  
  8680.    <div id="divUser">
  8681.        <table style="border:0px;border-spacing:0px;border-collapse:collapse;"><tr>
  8682.        <td style="vertical-align:top;">
  8683.        <img id="userPicture" src="/img/profile.jpg"></img>        </td>
  8684.        <td style="vertical-align:top;padding-left:16px;">
  8685.        <b>Name</b>: StephanUgli654 <br/><b>Joined</b>: February 27, 2024 <br/> <br/><b>Shaders</b>: 0<br/><b>Playlists</b>: 0<br/><b>Comments</b>: 0<br/> <br/><b>Following</b>: 0<br/><b>Followers</b>: 0<br/>        </td>
  8686.        <td style="vertical-align:top;padding-left:32px;">
  8687.        <b>About</b><br><br>I'd highly recommend checking out <a href="https://1xbet-ar.biz/"  class="regular" target="_blank">https://1xbet-ar.biz/</a> . Not only does it offer a seamless online chess experience, but it also provides a plethora of other gaming options for those seeking variety.        </td>
  8688.        <td style="vertical-align:top;padding-left:32px;">
  8689.                    </td>
  8690.        </tr></table>
  8691.    </div>
  8692.  
  8693. <!-- --------------------------- -->
  8694.  
  8695.  <div id="controls">
  8696.  
  8697.    <div>
  8698.      <div style="text-align: center; vertical-align: middle; display: inline-block; padding-bottom:5px; padding-top:4px; margin-right:8px; margin-bottom:8px; margin-top:8px;">
  8699.      Sort:      </div>
  8700.      <div class="controlOptions"><div class="pageButtonsCurrent" href="/user/StephanUgli654/sort=popular">Popular</div><a class="pageButtons" href="/user/StephanUgli654/sort=newest">Newest</a><a class="pageButtons" href="/user/StephanUgli654/sort=love">Love</a></div>
  8701.    </div>
  8702.  
  8703.    <div id="controlFilter">
  8704.      <div style="display:flex;margin-right:8px;align-items:center;">Filter:</div>
  8705.      <div class="controlOptions"> <a class="pageButtons" href="/user/StephanUgli654&sort=popular&filter=multipass">Multipass</a><a class="pageButtons" href="/user/StephanUgli654&sort=popular&filter=soundoutput">GPU Sound</a><a class="pageButtons" href="/user/StephanUgli654&sort=popular&filter=vr">VR</a><a class="pageButtons" href="/user/StephanUgli654&sort=popular&filter=soundinput">Microphone</a><a class="pageButtons" href="/user/StephanUgli654&sort=popular&filter=musicstream">Soundcloud</a><a class="pageButtons" href="/user/StephanUgli654&sort=popular&filter=webcam">Webcam</a></div>
  8706.    </div>
  8707.  
  8708.    <div>
  8709.        <div style="text-align: center; vertical-align: middle; display: inline-block; padding-bottom:5px; padding-top:4px; margin-right:8px; margin-bottom:8px; margin-top:8px;">
  8710.        Results (0):        </div>
  8711.  
  8712.        <div class="controlOptions">
  8713.                      </div>
  8714.    </div>
  8715.  </div>
  8716.  
  8717.  
  8718.  <div id="shaderGrid">
  8719.    <div class='searchResult'><div class='searchResultContainer' id='Preview_0_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_0_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_0_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_0_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_0_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_0_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_0_Thumnail'>        <img class='previewThumbnailImage' id='Preview_0_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_0_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8720. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_0_ThumnailWarning2' title='You are using static shader previews.
  8721. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_0_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_0_Info'>  <span class='previewText'  id='Preview_0_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_0_TextUser'></span>  <span class='previewStats' id='Preview_0_Stats'></span></div></div><div class='searchResult'><div class='searchResultContainer' id='Preview_1_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_1_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_1_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_1_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_1_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_1_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_1_Thumnail'>        <img class='previewThumbnailImage' id='Preview_1_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_1_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8722. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_1_ThumnailWarning2' title='You are using static shader previews.
  8723. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_1_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_1_Info'>  <span class='previewText'  id='Preview_1_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_1_TextUser'></span>  <span class='previewStats' id='Preview_1_Stats'></span></div></div><div class='searchResult'><div class='searchResultContainer' id='Preview_2_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_2_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_2_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_2_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_2_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_2_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_2_Thumnail'>        <img class='previewThumbnailImage' id='Preview_2_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_2_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8724. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_2_ThumnailWarning2' title='You are using static shader previews.
  8725. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_2_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_2_Info'>  <span class='previewText'  id='Preview_2_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_2_TextUser'></span>  <span class='previewStats' id='Preview_2_Stats'></span></div></div><div class='searchResult'><div class='searchResultContainer' id='Preview_3_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_3_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_3_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_3_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_3_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_3_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_3_Thumnail'>        <img class='previewThumbnailImage' id='Preview_3_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_3_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8726. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_3_ThumnailWarning2' title='You are using static shader previews.
  8727. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_3_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_3_Info'>  <span class='previewText'  id='Preview_3_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_3_TextUser'></span>  <span class='previewStats' id='Preview_3_Stats'></span></div></div><div class='searchResult'><div class='searchResultContainer' id='Preview_4_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_4_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_4_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_4_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_4_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_4_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_4_Thumnail'>        <img class='previewThumbnailImage' id='Preview_4_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_4_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8728. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_4_ThumnailWarning2' title='You are using static shader previews.
  8729. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_4_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_4_Info'>  <span class='previewText'  id='Preview_4_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_4_TextUser'></span>  <span class='previewStats' id='Preview_4_Stats'></span></div></div><div class='searchResult'><div class='searchResultContainer' id='Preview_5_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_5_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_5_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_5_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_5_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_5_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_5_Thumnail'>        <img class='previewThumbnailImage' id='Preview_5_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_5_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8730. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_5_ThumnailWarning2' title='You are using static shader previews.
  8731. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_5_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_5_Info'>  <span class='previewText'  id='Preview_5_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_5_TextUser'></span>  <span class='previewStats' id='Preview_5_Stats'></span></div></div><div class='searchResult'><div class='searchResultContainer' id='Preview_6_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_6_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_6_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_6_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_6_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_6_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_6_Thumnail'>        <img class='previewThumbnailImage' id='Preview_6_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_6_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8732. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_6_ThumnailWarning2' title='You are using static shader previews.
  8733. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_6_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_6_Info'>  <span class='previewText'  id='Preview_6_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_6_TextUser'></span>  <span class='previewStats' id='Preview_6_Stats'></span></div></div><div class='searchResult'><div class='searchResultContainer' id='Preview_7_Container'>  <a class='shaderPreview searchResultCanvas' id='Preview_7_Link'>    <div class='previewNoGLContainter searchResultCanvas' id='Preview_7_NoWebGL'>        <img class='previewThumbnailImage' id='Preview_7_ThumnailImageNoWebGL'></img>        <div class='previewNoGLMessage' id='Preview_7_MessageNoWebGL'>No Screenshot Availabe</div>    </div>    <div class='previewErrorContainer searchResultCanvas' id='Preview_7_Error'>        <div class='previewErrorMessage'>Shader Error</div>    </div>    <div class='previewThumbnailContainer searchResultCanvas' id='Preview_7_Thumnail'>        <img class='previewThumbnailImage' id='Preview_7_ThumnailImage'></img>        <div class='previewThumbnailIcon' id='Preview_7_ThumnailWarning1' title='This shader takes too long to compile, a preview image is shown instead to improve browsing.
  8734. Click on the shader to see it in real-time.'>Warning</div>        <div class='previewThumbnailIcon' id='Preview_7_ThumnailWarning2' title='You are using static shader previews.
  8735. Click on the shader to see it in real-time.'>Preview</div>    </div>    <canvas class='previewCanvas searchResultCanvas' id='Preview_7_Canvas'></canvas>  </a></div><div class='previewInfo' id='Preview_7_Info'>  <span class='previewText'  id='Preview_7_Text'></span>  <span>by</span>  <span class='previewTextUser'  id='Preview_7_TextUser'></span>  <span class='previewStats' id='Preview_7_Stats'></span></div></div>  </div>
  8736. </div>
  8737.  
  8738. <!-- footer ================================================================================== -->
  8739.  
  8740. <div id="footer">
  8741.    
  8742.    <div><span style="color:#ffffff;">Community Forums</span>
  8743.      <ul>
  8744.      <li><a class="regular" href="/events">Official Events</a></li>
  8745.      <li><a class="regular" href="https://www.facebook.com/groups/147749602472741">In Facebook (english)</a></li>
  8746.      <li><a class="regular" href="https://www.facebook.com/groups/1339783682699494">In Facebook (korean)</a></li>
  8747.      <li><a class="regular" href="https://discord.gg/XtmMN6E">In Discord</a> (<a class="regular" href="https://discordapp.com/channels/578696555612209173/579531723348639754">direct link</a>)</li>
  8748.      </ul>
  8749.    </div>
  8750.  
  8751.    <div><span style="color:#ffffff;">Feedback and Support</span>
  8752.      <ul>
  8753.      <li><a class="regular" href="https://www.facebook.com/Shadertoy">Facebook</a></li>
  8754.      <li><a class="regular" href="https://twitter.com/shadertoy">Twitter</a></li>
  8755.      <li><a class="regular" href="https://www.patreon.com/shadertoy">Patreon</a></li>
  8756.      <li><a class="regular" href="https://trello.com/b/5hM0CjId">Roadmap</a></li>
  8757.  
  8758.      
  8759.      </ul>
  8760.    </div>
  8761.  
  8762.    <div><span style="color:#ffffff;">Shadertoy</span>
  8763.      <ul>
  8764.      <li><a class="regular" href="/store">Store</a></li>
  8765.      <li><a class="regular" href="/howto">Documentation</a></li>
  8766.      <li><a class="regular" href="/terms">Terms & Privacy</a></li>
  8767.      <li><a class="regular" href="/about">About</a></li>
  8768.      </ul>
  8769.    </div>
  8770.  
  8771.    <div><span style="color:#ffffff;">Apps and Plugins</span>
  8772.      <ul>
  8773.      <li><a class="regular" href="https://itunes.apple.com/us/app/shadertoy/id717961814">Official iPhone App</a> by <a class="user" href="/user/reinder">Reinder</a></li>
  8774.      <li><a class="regular" href="https://steamcommunity.com/sharedfiles/filedetails/?id=1726697188">Screensaver</a> by <a class="user" href="/user/kosro">Kosro</a></li>
  8775.      <li><a class="regular" href="https://chrome.google.com/webstore/detail/shadertoy-unofficial-plug/ohicbclhdmkhoabobgppffepcopomhgl">Shadertoy plugin</a> by <a class="user" href="/user/patu">Patu</a></li>
  8776.      </ul>
  8777.    </div>
  8778.  
  8779.    <div><span style="color:#ffffff;">Tutorials</span>
  8780.      <ul>
  8781.      <li><a class="regular" href="https://www.youtube.com/watch?v=0ifChJ0nJfM">Shader coding intro</a> by <a class="user" href="/user/iq">iq</a></li>
  8782.      <li><a class="regular" href="https://shadertoyunofficial.wordpress.com/">Shadertoy Unofficial</a> by <a class="user" href="/user/FabriceNeyret2">FabriceNeyret2</a></li>
  8783.      </ul>
  8784.    </div>
  8785.  
  8786. </div>
  8787.  
  8788. <div id="compliance" style="padding-bottom:6px;visibility:hidden;left:0;top:0px;width:100%;background-color:rgb(200,120,20,0.93);position:absolute;color:#FFFFFF">
  8789.    <div style="text-align: center; margin-top:8px">
  8790.        We use cookies to give you the best experience on our website. If you continue using Shadertoy, we'll assume that you are happy to receive all cookies on this website.
  8791.        For more information, please review our <a class="regular" href="/terms">Terms & Privacy</a>.
  8792.    </div>
  8793.    <div style="text-align: center;margin-top:6px">
  8794.        <button type="button" style="width:100px;font-size:inherit" onclick="acceptCompliance()">Accept</button>
  8795.    </div>
  8796. </div>
  8797.  
  8798. <script>
  8799. (function runCompliance()
  8800. {
  8801.    let showCompliance = 1;
  8802.    let allcookies = document.cookie;
  8803.    let cookiearray = allcookies.split(';');
  8804.    for (var i=0; i<cookiearray.length; i++)
  8805.    {
  8806.        let name  = cookiearray[i].split('=')[0];
  8807.        let value = cookiearray[i].split('=')[1];
  8808.        if (name.trim() == "scmp")
  8809.        {
  8810.            showCompliance = value;
  8811.            break;
  8812.        }
  8813.    }
  8814.  
  8815.    if (showCompliance === 1)
  8816.    {
  8817.        var ve = document.getElementById("compliance");
  8818.        ve.style.visibility="visible";
  8819.    }
  8820. })();
  8821.  
  8822. function acceptCompliance()
  8823. {
  8824.    let now = new Date();
  8825.    now.setTime( now.getTime() + (5*365*24*60*60*1000) );
  8826.    document.cookie="scmp=0;expires=" + now.toUTCString() + ";";
  8827.  
  8828.    var ve = document.getElementById("compliance");
  8829.    ve.style.visibility="hidden";
  8830. }
  8831. </script>
  8832.  
  8833.  
  8834. </body>
  8835. </html>
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda