如果着色器从不改变,有没有办法缓存慢速 WebGL 着色器编译? [英] Is there a way to cache slow WebGL shader compilation if the shader never changes?

查看:47
本文介绍了如果着色器从不改变,有没有办法缓存慢速 WebGL 着色器编译?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 WebGL 着色器,当我有这个时,它会立即编译(Windows 7 上的 Chrome):

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;
}

但是编译这个需要很长时间(~10 秒):

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;
}

有没有办法将 WebGL 编译的结果缓存为二进制文件并加载它,或者这没有帮助?我假设长时间的延迟与将着色器从 OpenGL 转换为 DirectX 相关.

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.

(这是一个活生生的例子.)

推荐答案

我不知道有什么方法可以为 WebGL 预编译着色器;提供这样的功能可能会有很多便携性和安全性问题.

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.

antialias_level 是用户选择的对整个场景保持不变的参数吗?您最好为当前选择的级别而不是所有可能的级别编译着色器;这可能在运行时效率更高,编译速度更快.

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.

自定义着色器同时仍将着色器源与 JS 代码分开的一种简单方法是在编译之前添加 "#define ANTIALIAS_LEVEL " + level,并在着色器源中使用 #如果 选择合适的案例.但是,由于您的 main() 代码非常系统,因此仅通过算法生成它可能是值得的.

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.

这篇关于如果着色器从不改变,有没有办法缓存慢速 WebGL 着色器编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆