着色器很重的主要原因:
1:这两个计算:v_texCoord + offset
and v_texCoord - offset
。由于 uv 坐标是在片段着色器中计算的,因此必须当场从内存加载纹理数据,从而导致缓存未命中。
什么是依赖纹理读取? https://stackoverflow.com/questions/1054096/what-is-a-dependent-texture-read
2: radius
太大了。
如何让它更快/更好:
1:在顶点着色器中尽可能多地计算。理想情况下,如果您在顶点着色器中计算所有 UV,GPU 可以在调用片段着色器之前移动缓存中的纹理内存,从而显着提高性能。
2:减少Radius
可以容纳8-16人texture2D
来电。这可能不会给您期望的结果,为了解决这个问题,您可以使用 2 个纹理,将纹理 A 模糊到 B 中,然后再次将 B 模糊到纹理 A 中,依此类推,根据需要进行模糊处理。这将给出非常好的结果,我记得 crisys 1 使用它进行运动模糊,但我找不到论文。
3:消除那 64 个制服,将所有数据硬编码在着色器中。我知道这不太好,但你会获得一些额外的性能。
4:如果仔细计算 UV 坐标,您可以充分利用纹理插值。基本上不会对中心的像素进行采样,总是在像素之间进行采样,硬件会执行此操作并取附近 4 个像素的平均值:
https://en.wikipedia.org/wiki/Bilinear_filtering https://en.wikipedia.org/wiki/Bilinear_filtering
5:这一行:precision mediump float;
一切都必须如此吗mediump
?我建议删除它并进行一些测试lowp
尽可能多地进行。
编辑:
对于您的着色器,这是您需要执行的操作的简化版本:
顶点着色器:
attribute highp vec4 Position;
attribute mediump vec2 texture0UV;
varying mediump vec2 v_texCoord0;
varying mediump vec2 v_texCoord1;
varying mediump vec2 v_texCoord2;
varying mediump vec2 v_texCoord3;
varying mediump vec2 v_texCoord5;
uniform mediump vec2 texture_size;
void main()
{
gl_Position = Position;
vec2 pixel_size = vec2(1.0) / texture_size;
vec2 offset;
v_texCoord0 = texture0UV;
v_texCoord1 = texture0UV + vec2(-1.0,0.0) / texture_size + pixel_size * 0.5;
v_texCoord2 = texture0UV + vec2(0.0,-1.0) / texture_size + pixel_size * 0.5;
v_texCoord3 = texture0UV + vec2(1.0,0.0) / texture_size - pixel_size * 0.5;
v_texCoord4 = texture0UV + vec2(0.0,1.0) / texture_size - pixel_size * 0.5;
}
最后一次操作pixel_size * 0.5
需要最大限度地利用线性插值。在此示例中,您选择的采样位置很简单,但有关如何选择采样位置的完整讨论超出了本问题的范围。
片段着色器:
varying mediump vec2 v_texCoord0;
varying mediump vec2 v_texCoord1;
varying mediump vec2 v_texCoord2;
varying mediump vec2 v_texCoord3;
varying mediump vec2 v_texCoord5;
uniform lowp sampler2D CC_Texture0;
void main()
{
mediump vec4 final_color = vec4(0.0);
final_color += texture2D(CC_Texture0,v_texCoord0);
final_color += texture2D(CC_Texture0,v_texCoord1);
final_color += texture2D(CC_Texture0,v_texCoord2);
final_color += texture2D(CC_Texture0,v_texCoord3);
final_color += texture2D(CC_Texture0,v_texCoord4);
gl_FragColor = final_color / 5.0;//weights have to go, use fixed values instead, in this case it's 1/5 for each sample
}
为了让效果看起来不错,您需要多次模糊纹理,即使您模糊纹理 2 次,您也应该看到明显的差异。