下面的片元着色器通过二维加权采样实现模糊,适合验证思路,不建议未经性能评估直接用于大面积实时渲染。
效果图

片元着色器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
#ifdef GL_ES precision mediump float; #endif
varying vec4 v_fragmentColor; varying vec2 v_texCoord;
uniform vec2 resolution;
uniform float blurRadius;
vec4 blur(vec2);
void main(void) { vec4 col = blur(v_texCoord); gl_FragColor = vec4(col) * v_fragmentColor; }
vec4 blur(vec2 p) { if (blurRadius <= 0.0) { return texture2D(CC_Texture0, p); }
vec4 col = vec4(0.0); float r = blurRadius;
vec2 unit = 1.0 / max(resolution.xy, vec2(1.0)); float step = r / 5.0; float allWeight = 0.0; for(float x = -r; x < r; x += step) { for(float y = -r; y < r; y += step) { float weight = (r - abs(x)) * (r - abs(y)); col += texture2D(CC_Texture0, p + vec2(x * unit.x, y * unit.y)) * weight; allWeight += weight; } } if (allWeight <= 0.0) { return texture2D(CC_Texture0, p); } return col / allWeight; }
|
使用限制
resolution 应传入纹理的像素宽高,blurRadius 必须大于 0。
- 双层循环每个片元会执行大量纹理采样,半径增大后 GPU 开销明显。
- 循环边界由 uniform 决定,部分 OpenGL ES 2.0 设备或驱动可能拒绝编译。需要覆盖旧设备时,建议改成固定循环上限,或采用横向、纵向两次采样的可分离模糊。
- 图片边缘的采样结果受纹理寻址方式影响;若出现边缘渗色,需要检查纹理的 wrap 和图集边距。
相关阅读