着色器(Shader)应用与计算机图形学领域,指一组提供计算机图形资源在渲染时执行的指令。
随着手机应用以及移动端游戏这几年的发展,着色器设计凭借着自身的灵活性以及适应性,越来越多的被移动端开发者所接受。
本人在App Store上发布了一个原创免费开源无广告的关于着色器的教育型软件,以研究着色器在移动端的设计为目的。
可惜由于时间匆忙,并没有做中文的本地化。所以将写几篇博客,手把手的教一些希望学习着色器的新手移动开发者如何把着色器应用在自己的App上。
首先,跟我学着色这个软件是使用coco2d-x 3.0 + GLSL 编写而成的。如果有朋友想直接下载源码运行,请使用正确的coco2d-x的版本。
整个软件分为3个部分,1是主体的教育软件,中间带有一些正常应用的按钮和比较功能。2是着色器的程序。这些着色器的程序有部分是我原创的,有些是包含在coco2d-x 游戏引擎里的,还有部分是来自于国外开源shadertoy上。我自身也在shadertoy上发表了一些着色器的程序,上面的所有着色器程序都是免费开源的。第三就是读取着色器程序的一段程序。其实GLSL是可以支持在很多引擎上运行的,所以无论是Unity还是cocos2d-x或者一些其他主流的引擎,只要自己写段读取的代码,着色器程序都可以运行。
因为今天是入门篇,所以今天先介绍几个静态的着色器设计。
首先是一张效果图,左上的是原图,第二个是灰色效果,第三是彩色横条效果,第四是高亮,第五是边缘检测,第六是冰花效果,第七是卡通渲染,第八是石刻效果,第九是高斯模糊。
因为篇幅有限,接下来介绍每种效果的设计原理。具体想了解更多的朋友可以直接去下我的软件,或者直接开我底部的源码链接编译运行。里面每种效果都非常详细,总共有超过100张PPT。介绍了每种效果的历史,起源,物理学原理,设计理念,实现效果以及一些可以实际应用上的Tricky Solution.
1. 灰色效果:
灰色效果是非常简单的一种Shader效果,对于这个效果更多的是用来测试基本的Shader效果能否实现。
灰色效果的设计理念就是使原图片的RGB的值按比例减少。我们都知道一般灰色是128,128,128.我们通过把RGB的值降低,可以明显的使图片色调变暗,从而实现变灰效果。
具体操作就是把原来图片的alpha通道保留,RBG点成一个比例。
Gray.fsh
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform sampler2D CC_Texture0;
void main()
{
vec4 v_orColor = v_fragmentColor *texture2D(CC_Texture0, v_texCoord);
float gray =dot(v_orColor.rgb, vec3(0.3,0.3,0.3));
gl_FragColor =vec4(gray, gray, gray, v_orColor.a);
}
一般来说,一个Shader效果可以有一个vertex shader一个 fragment shader. 上面的Gray.fsh就是我们实现变灰的代码,而下面的Gray.vsh则决定了位置。由于变灰效果网上很多大牛都写过,所以不做过多讲解。有一点就是下面的关于变灰后图片的位置网上有个代码使用了CC_MVPMatrix导致图片位置不对。Gray.vsh
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
这个vertex shader是我看到后来别人回复修改过后的,大家使用我的就没有问题了,后面我更多的会针对fragment shader进行讲解,毕竟这是实现效果的主要部分。2. 彩色横条效果
彩色横条效果是cocos2d-iphone和cocos2d-x 3.0里面都自带的一个shader效果。这个效果是从McCollough效果上衍生而来的,对历史和理论感兴趣的可以下载下我的App具体学习。如果我没记错,McCollough好像是从人类视觉感知的一个现象衍生出来的一个效果。(原谅我McCollough这个词wikipedia上没有中文翻译)
//inspired and modified from http://www.cocos2d-iphone.org
#ifdef GL_ES
precision lowp float;
#endif
varying vec2 v_texCoord;
uniform sampler2D CC_Texture0;
vec4 colors[8];
void main(void)
{
colors[0] =vec4(1,0,0,1);
colors[1] =vec4(0,1,0,1);
colors[2] =vec4(0,0,1,1);
colors[3] =vec4(0,1,1,1);
colors[4] =vec4(1,0,1,1);