Something about shaders

When the shader starts to work, my project will get stuck for a few seconds. I want to hide this stuck by loading some models, pictures and other resources, but the effect is not ideal,still stuck for a few seconds.
Will other loading work be suspended when the shader is working?
Is there any conflict between the work of the shader and the model I load through the script?

var TransmitProgress = pc.createScript('transmitProgress');


TransmitProgress.attributes.add("tagName", {
    type: "string"
});
TransmitProgress.attributes.add("targetEntity", {
    type: "entity",
    array: true
});



// initialize code called once per entity
TransmitProgress.prototype.initialize = function () {
    this.loadAssets();
    // this.app.on("loadInteriorModels", this.loadAssets, this);
    // this.on("destroy", function () {
    //     this.app.off("loadInteriorModels", this.loadAssets, this);
    // }, this);
};

TransmitProgress.prototype.loadAssets = function (index) {
    console.log('start load');

    var self = this;

    var assets = this.app.assets.findByTag(self.tagName);
    var assetsLoaded = 0;
    var assestTotal = assets.length;

    // Callback function when an asset is loaded
    var onAssetReady = function () {
        assetsLoaded += 1;

        // Update the progress bar
        let percent = assetsLoaded / assestTotal;
        self.app.fire('loadedModeProgress', percent);

        // Once we have loaded all the assets
        if (assetsLoaded === assestTotal) {
            self.onAssetsLoaded(index);
            self.app.fire('loadedModeComplete');
        }
    };

    // Start loading all the assets
    for (var i = 0; i < assets.length; i++) {
        assets[i].ready(onAssetReady);
        this.app.assets.load(assets[i]);
    }

    if (!assets.length) {
        this.onAssetsLoaded();
    }
};

TransmitProgress.prototype.onAssetsLoaded = function (index) {
    var self = this;

    for (let i = 0; i < this.targetEntity.length; i++) {
        self.targetEntity[i].enabled = true;
    }

};


TransmitProgress.prototype.update = function (dt) {

};
pc.script.createLoadingScreen(function (app) {
  var isInDebug = location.href.includes("debug");

  var showSplash = function () {

    var wrapper = document.createElement("div");
    wrapper.id = "application-splash-wrapper";
    var innerHTML = `
      <div id="loading-box-wrap">
        <img
          id="loading-logo"
          src="https://h5.dongfeng-honda.com/vrh5/upload/oss_1/loading-logo.png"
        />
        
        <div id="loading-box">
          <div id="loading-car">0%</div>
          <div class="loading-bar" style="margin: auto">
            <div class="loading-bar" id="loading-bar"></div>
          </div>
          
        </div>
        <div id="sub-tips">
          
        </div>
      </div>`;


    wrapper.innerHTML = innerHTML;
    document.body.appendChild(wrapper);
  };
  showSplash();
  let loadingBox = document.getElementById("loading-box"),
    bar = document.getElementById("loading-bar"),
    car = document.getElementById("loading-car");

  var hideSplash = function () {
    var splash = document.getElementById("application-splash-wrapper");
    splash.parentElement.removeChild(splash);
  };


  var setProgress = function (value) {
    value = Math.min(0.8, Math.max(0, value * 0.8));
    bar.style.width = value * 100 + "%";
    car.innerText = Math.floor(value * 100) + "%";
  };
  var setProgress2 = function (value) {
    value = Math.min(1, Math.max(0.8, value * 0.2 + 0.8));
    bar.style.width = value * 100 + "%";
    console.log(value);
    car.innerText = Math.floor(value * 100) + "%";
  };

  var createCss = function () {
    var css = `
        #sub-tips {
          position: absolute;
          left: 0;
          right: 0;
          bottom: 4%;
          color: #606060;
          text-align: center;
          font-size: 0.8rem;
          transform: scale(0.8);
          z-index: 10;
          display: none;
        }
      #application-splash-wrapper {
        width: 100vw;
        height: 100vh;
        background-color: #000;
        display: flex;
        justify-content: center;
        position: absolute;
        z-index:9999;
      }
      #loading-box-wrap {
        width: 100%;
      }
      #loading-box {
        position: absolute;
        left: 0vw;
        right: 0;
        bottom: 12%;
        width: 45%;
        height: 20px;
        margin: auto;
        
      }
      #loading-logo {
        width: 100%;
        margin-top: 30%
      }
      #loading-box .loading-bar, #loading-car {
        display: none;
      }
      .loading-bar {
        width: 100%;
        height: 3px;
        border-radius: 40px;
        overflow: hidden;
        background: #000;
          no-repeat center/contain;
      }
      #loading-bar {
        width: 0;
        background:#fff;
        background-size: 65vw 6px;
      }
      #loading-car {
        width: 45px;
        height: 70px;
        text-align: center;
        padding-top: 31px;
        font-size: 0.65rem;
        color: #fff;
        position: absolute;
        left: 0;
        right: 0;
        top: -50px;
        margin: auto;
      }
      @media (min-width: 768px) {
        #loading-logo {
          margin-top: 0;
        }
      }
      @media (orientation: landscape){
        #loading-logo {
          width: auto;
          height: 85%;
        }
      #loading-box-wrap{
          display: flex;
          justify-content: center;
        }
      }
      `;

    var style = document.createElement("style");
    style.type = "text/css";
    if (style.styleSheet) {
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }

    document.head.appendChild(style);
  };

  createCss();



  $("#application-canvas").css('background-color', '#000');


  $("#loading-logo").fadeIn();
  setTimeout(function () {
    $("#loading-box .loading-bar, #loading-car").fadeIn(2000);
    $("#sub-tips").fadeIn(2000);
  }, 1000);


  app.on('preload:progress', setProgress);


  app.on('loadedModeProgress', setProgress2);
  app.once('loadedModeComplete', hideSplash);
});

Yes, compiling a shader locks the main thread of the browser

Not sure what you mean here?

Can I load the model while compiling a shader?Or I have to load the model and other resources after the shader compilation is completed?

AFAIK, the network request to download the data is asynchronous so not affected by the main thread being locked. But once it has finished downloading, it has to wait on the main thread to process and parse the downloaded data.

Can it do concurrent process the data loading & redenring when loading the game?

another question:while the main page displays some models, can it render some objects in the backstage, similar to multithreading?Instead of starting rendering after loading all.

Downloading of data is always asynchronous

Sorry, I don’t understand

Sorry, maybe I’m not clear. Can we load and render the model in the background at the same time when we can’t see it visually?

you can render it in the background (render it to a texture), so it won’t be visible. But this won’t help with the main thread slowing down as WebGL is single threaded, so all rendering takes place on the same thread.

Can playcanvas use web worker to render models and materials?

As I said, WebGL API is single threaded, and can only be used from a single thread. Off-screen canvas (OffscreenCanvas - Web APIs | MDN) allows it to be used from a worker thread, but then all rendering moves to that thread. It does not allow you to render from multiple threads in parallel.

So this typically helps if you use html webpage, and WebGL is rendering on separate thread, that can work without blocking the main webpage.

At the moment, Playcavas does not support this.

Ok, thank you for your help :grinning: