Reputation: 8354
I have a WebGL shader which compiles perceptually immediately (Chrome on Windows 7) when I have this:
void main(void) {
if (antialias_level == 1)
gl_FragColor = NewtonIteration((gl_FragCoord.xy + offset) / zoom);
else if (antialias_level == 2)
gl_FragColor = (NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.25, -0.25)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.25, 0.25)) / zoom)) * 0.5;
}
But it takes a very long time (~10 sec) to compile this:
void main(void) {
if (antialias_level == 1)
gl_FragColor = NewtonIteration((gl_FragCoord.xy + offset) / zoom);
else if (antialias_level == 2)
gl_FragColor = (NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.25, -0.25)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.25, 0.25)) / zoom)) * 0.5;
else if (antialias_level == 4)
gl_FragColor = (NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.25, -0.25)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.25, 0.25)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.25, -0.25)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.25, 0.25)) / zoom)) * 0.25;
else if (antialias_level == 9)\
gl_FragColor = (NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.33, -0.33)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.0, -0.33)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.33, -0.33)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.33, 0.0)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.0, 0.0)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.33, 0.0)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.33, 0.33)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.0, 0.33)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.33, 0.33)) / zoom)) * 0.111111111;
else if (antialias_level == 16)\
gl_FragColor = (NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.375, -0.375)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.125, -0.375)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.125, -0.375)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.375, -0.375)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.375, -0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.125, -0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.125, -0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.375, -0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.375, 0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.125, 0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.125, 0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.375, 0.125)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.375, 0.375)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(-0.125, 0.375)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.125, 0.375)) / zoom) + NewtonIteration((gl_FragCoord.xy + offset + vec2(0.375, 0.375)) / zoom)) * 0.0625;
}
Is there a way to cache the result of the WebGL compilation to binary and load that instead, or would that not help? I'm assuming the long delay has to do with translating the shader from OpenGL to DirectX.
Upvotes: 1
Views: 1499
Reputation:
No, there is no way to precompile a shader. It would be a huge security hole.
On the other hand, it is likely both browsers will start caching shaders in the future for you under the hood
Here's the issue for Chrome http://code.google.com/p/chromium/issues/detail?id=88572
I'm not sure if there is a similar one for Firefox or other browsers.
Upvotes: 2
Reputation: 43753
I am not aware of any way to precompile shaders for WebGL; there would probably be many portability and security issues with providing such a feature.
Is antialias_level
a user-chosen parameter that is constant for the entire scene? You would probably be better off compiling a shader for the current chosen level rather than all possible ones; this may be more efficient at runtime as well as compiling faster.
A simple way to customize a shader while still separating your shader source from your JS code is to prepend "#define ANTIALIAS_LEVEL " + level
before compiling, and in your shader source use #if
to choose the appropriate case. However, since your main()
code is very systematic, it might be worthwhile just generating it algorithmically.
Upvotes: 3