Search Unity

shader compilation issue for WebGL

Discussion in 'Shaders' started by Epic_Cube, Aug 3, 2018.

  1. Epic_Cube

    Epic_Cube

    Joined:
    Jul 3, 2012
    Posts:
    100
    Hi all,
    I have written a post effect shader that works right for a number of platforms. Now I'm trying to make it work for WebGL too. I need to compile it for WebGL 1.0, becouse most of browsers out there don't support 2.0 yet. I In my shader, I have this piece of code:
    Code (CSharp):
    1. for (half k = 1; k <= _Thickness; k++)
    2. {
    3.     lerpVal = 1 - ((k+1) / _Thickness);
    4.     //lerpVal *= lerpVal;
    5.     silhouettesColor = getNeighborsSumHV( _SecondTex, _SecondTex_TexelSize, uv, k);
    6.     silhouettesColor /= silhouettesColor.a;
    7.    
    8.     [... some other stuff ...]
    9. }
    When I run this shader in my WebGL project, I get the following error:

    Note: Creation of internal variant of shader 'Outliner/Post Outline' failed. UnityLoader.js (4,10703)
    ERROR: 0:37: 'while' : This type of loop is not allowed UnityLoader.js (4,10703)


    I've checked the compiled version of my shader and I found where the problem is: when compiled and converted to GLES, the for loop is translated to a WHILE LOOP, that is not supported.
    Code (CSharp):
    1.     k_5 = 1.0;
    2.     while (true) {
    3.       if ((k_5 > 20.0)) {
    4.         break;
    5.       };
    6.       if ((k_5 > _Thickness)) {
    7.         break;
    8.       };
    9.       mediump vec4 tmpvar_6;
    10.       mediump float deltaX_7;
    11.       deltaX_7 = _MainTex_TexelSize.x;
    12.  
    13. [... more stuff ...]
    14.  
    15.       k_5 += 1.0;
    16.     };
    17.  
    How I can fix it? Is there any way to force compilation to use for loop instead of - unsupported - while?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The error is somewhat misleading. It makes it seem like the while loop is uniquely unsupported, but the reality is any kind of dynamic loop is unsupported by WebGL.

    The number of iterations in a loop must be a constant value defined in the shader itself and cannot be a material property for it to work correctly for WebGL 1.0. It might be possible to add [unroll(#)] before the loop, where # is the most iterations you want to allow, but Im not 100% sure that translates into the webGL shader as that's an HLSL thing. Be warned that with that line your shader will effectively being paying the cost of doing the max number of iterations all of the time regardless of the value you set on the material. If you want to support WebGL you may want to setup a couple of fixed iteration count options chosen via different passes or keywords.