操作系统:Windows8.1
显卡:Nivida GTX965M
开发工具:GLSL | C
最近在看Cardboard实现,其中关于畸变的着色器代码中有加入 晕影Vignette 效果的实现,固在这里温习、总结一下。
直接上效果图:
使用Vignette滤镜效果图:
大概意思如图所示,增加了晕影效果后,使得边缘区域覆盖了厚重的颜色快,其目的是使得观看者更多的将目光聚焦在中心区域,该效果被大量运用到摄影、影视作品中。
比如:
How to implement
先给出全部代码具体解释说明,顶点着色器代码相对比较简单,仅仅是传递Mesh顶点数据及对应的UV数据。
static const char *vertex_shader_source = LINE("attribute vec4 aPosition;") LINE("attribute vec4 aTextureCoord;") LINE("varying highp vec2 vTextureCoord;") LINE("void main() {") LINE("gl_Position = aPosition;") LINE("vTextureCoord = aTextureCoord.xy;") LINE("}");
片段着色器代码:
static const char *fragment_shader_source = LINE("precision mediump float;") LINE("varying vec2 vTextureCoord;") LINE("uniform lowp sampler2D sTexture;") LINE("uniform lowp vec2 uVignetteCenter;") LINE("uniform lowp vec3 uVignetteColor;") LINE("uniform highp float uVignetteStart;") LINE("uniform highp float uVignetteEnd;") LINE("void main() {") LINE("lowp vec3 rgb = texture2D(sTexture, vTextureCoord).rgb;") LINE("lowp float d = distance(vTextureCoord, vec2(uVignetteCenter.x, uVignetteCenter.y));") LINE("lowp float percent = smoothstep(uVignetteStart, uVignetteEnd, d);") LINE("gl_FragColor = vec4(mix(rgb.x, uVignetteColor.x, percent), mix(rgb.y, uVignetteColor.y, percent), mix(rgb.z, uVignetteColor.z, percent), 1.0);") LINE("}");
该代码中设计带一些 uniform 系变量逐一说明:
- uVignetteCenter 二维分量,用于确定晕影效果的中心点,用于逐像素计算距离中心点距离使用。考虑着色器坐标需要归一化 [0.0 - 1.0 ],固在上面的示例中定义为默认 [0.5, 0.5]
- uVignetteColor 三维分量,用于确定晕影效果的颜色,一般情况下倾向于暗色调,在本例中为黑色 [1.0, 1.0, 1.0]
- uVignetteStart | uVigntteEnd 均为二维分量,与上面提到的中心点组合使用,可以简单理解通过 smoothstep 插值计算当前像素晕影强度,越靠近 uVignetteStart 晕影效果越轻淡,反之越靠近边缘晕影效果越浓重
以下为示例所使用的参数值:
filter->vignette_center_x = 0.5f; filter->vignette_center_y = 0.5f; filter->vignette_color[0] = 0.0f; filter->vignette_color[1] = 0.0f; filter->vignette_color[2] = 0.0f; filter->vignette_start = 0.2f; filter->vignette_end = 0.85f;
关于着色器中的 smoothstep 插值函数以参考 OpenGL Refpages 了解其实现原理,mix 混色函数参考 OpenGL Refpages。
Summery
效果实现相对比较简单,具体应用环境可通过 fragment shader 任意调整参数,包括影晕形状。