在我最近的项目中,我以程序方式创建了如下所示的片段着色器(但可能更大),并使用WebGL进行显示:
precision mediump float;
uniform vec2 u_windowSize;
void main() {
float s = 2.0 / min(u_windowSize.x, u_windowSize.y);
vec2 pos0 = s * (gl_FragCoord.xy - 0.5 * u_windowSize);
if (length(pos0) > 1.0) { gl_FragColor = vec4(0,0,0,0); return; }
vec2 pos1 = pos0/0.8;
vec2 pos2 = ((1.0-length(pos1))/length(pos1)) * pos1;
vec3 col2 = vec3(1.0,1.0,1.0);
vec2 pos3 = pos2;
vec3 col3 = vec3(1.0,0.0,0.0);
vec2 tmp2 = 6.0*(1.0/sqrt(2.0)) * mat2(1.0,1.0,-1.0,1.0) * pos2;
vec3 col4;
if (mod(tmp2.x, 2.0) < 1.0 != mod(tmp2.y, 2.0) < 1.0) {
col4 = col2;
} else {
col4 = col3;
};
vec2 pos5 = pos0;
vec3 col5 = vec3(0.0,1.0,1.0);
vec3 col6;
if (length(pos0) < 0.8) {
col6 = col4;
} else {
col6 = col5;
};
gl_FragColor = vec4(col6, 1.0);
}
很显然这里有些冗余,您不会手工书写–例如,将pos2
复制到pos3
是没有意义的。但是,因为我生成了这段代码,所以很方便。
在我现在开始过早开始优化并使生成器产生希望更有效的代码之前,我想知道:
浏览器和/或图形驱动程序是否已经优化了此类功能(因此我不必这样做)?
答案 0 :(得分:1)
浏览器无需进行任何优化。您可以使用WEBGL_debug_shaders
扩展名查看浏览器向驱动程序发送的内容。
示例:
const gl = document.createElement('canvas').getContext('webgl');
const ext = gl.getExtension('WEBGL_debug_shaders');
const vs = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
float a = 1. + 2. * 3.; // does this get optimized to 7?
float b = a; // does this get discarded?
gl_Position = matrix * position * vec4(b, a, b, a);
}
`;
const s = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(s, vs);
gl.compileShader(s);
console.log(ext.getTranslatedShaderSource(s));
在我的机器/驱动程序/浏览器上返回此结果
#version 410
in vec4 webgl_74509a83309904df;
uniform mat4 webgl_5746d1f3d2c2394;
void main(){
(gl_Position = vec4(0.0, 0.0, 0.0, 0.0));
float webgl_2420662cd003acfa = 7.0;
float webgl_44a9acbe7629930d = webgl_2420662cd003acfa;
(gl_Position = ((webgl_5746d1f3d2c2394 * webgl_74509a83309904df) * vec4(webgl_44a9acbe7629930d, webgl_2420662cd003acfa, webgl_44a9acbe7629930d, webgl_2420662cd003acfa)));
}
在这种情况下,我们可以看到对简单常数数学进行了优化,但是a
和b
相同的事实却并非如此。也就是说,不能保证其他浏览器会进行此优化。
驱动程序是否优化取决于驱动程序。大多数驱动程序至少会做一点优化,但是完全优化需要时间。 DirectX可能需要5分钟以上的时间才能对单个复杂的着色器进行全面优化,因此优化可能应该是done offline。在DirectX情况下,您希望保存二进制着色器结果以避免下次需要着色器时花费5分钟,但是对于WebGL来说,这是不可能的,因为二进制着色器既不可移植又存在安全问题。而且让浏览器长时间冻结以等待编译也将是不可接受的,因此浏览器无法要求DirectX进行全面优化。就是说,某些浏览器在后台缓存了二进制着色器结果。