什么是Shader呢?简单的说,Shader(着色器)是一段能够针对3D对象进行操作、并被GPU所执行的程序。通过这些程序,程序员就能够获得绝大部分想要的3D图形效果。在一个3D场景中,一般包含多个Shader。这些Shader中有的负责对3D对象表面进行处理,有的负责对3D对象的纹理进行处理。早在微软发布DirectX 8时,Shader Model的概念就出现在其中了,并根据操作对象的不同被分为对顶点进行各种操作的Vertex Shader(顶点渲染引擎)和对像素进行各种操作的Pixel Shader(像素渲染引擎)。

Shader的意义在于,它可以利用GPU加速的方式,为OpenGL和OpenGLES中的纹理进行程序员设定的样式改变,从而实现用户需要的任意效果。

下文以cocos2d-x为例,介绍一下基本的使用模式(好吧,因为此文伪原创,所以用这货,等过一阵翻过手来写个libgdx和lgame(等改版,目前使用的GL 1.x不支持,下个版本换2.0)的,反正能直接照搬,又增加两篇原创

)

首先是一张效果图,左上的是原图,第二个是灰色效果,第三是彩色横条效果,第四是高亮,第五是边缘检测,第六是冰花效果,第七是卡通渲染,第八是石刻效果,第九是高斯模糊。

1.灰色效果

灰色效果是非常简单的一种Shader效果,对于这个效果更多的是用来测试基本的Shader效果能否实现。

灰色效果的设计理念就是使原图片的RGB的值按比例减少。我们都知道一般灰色是128,128,128.我们通过把RGB的值降低,可以明显的使图片色调变暗,从而实现变灰效果。

具体操作就是把原来图片的alpha通道保留,RBG点成一个比例。

Gray.fshvaryingvec4v_fragmentColor;

varyingvec2v_texCoord;

uniformsampler2DCC_Texture0;

voidmain()

{

vec4v_orColor=v_fragmentColor*texture2D(CC_Texture0,v_texCoord);

floatgray=dot(v_orColor.rgb,vec3(0.3,0.3,0.3));

gl_FragColor=vec4(gray,gray,gray,v_orColor.a);

}

一般来说,一个Shader效果可以有一个vertexshader一个fragmentshader.上面的Gray.fsh就是我们实现变灰的代码,而下面的Gray.vsh则决定了位置。由于变灰效果网上很多大牛都写过,所以不做过多讲解。有一点就是下面的关于变灰后图片的位置网上有个代码使用了CC_MVPMatrix导致图片位置不对。

Gray.vshattributevec4a_position;

attributevec2a_texCoord;

attributevec4a_color;

varyingvec4v_fragmentColor;

varyingvec2v_texCoord;

voidmain()

{

gl_Position=CC_PMatrix*a_position;

v_fragmentColor=a_color;

v_texCoord=a_texCoord;

}

这个vertexshader是我看到后来别人回复修改过后的,大家使用我的就没有问题了,后面我更多的会针对fragmentshader进行讲解,毕竟这是实现效果的主要部分。

2.彩色横条效果

彩色横条效果是Cocos2d-x-iPhone和Cocos2d-x3.0里面都自带的一个shader效果。这个效果是从McCollough效果上衍生而来的,对历史和理论感兴趣的可以下载下我的App具体学习。如果我没记错,McCollough好像是从人类视觉感知的一个现象衍生出来的一个效果。#ifdefGL_ES

precisionlowpfloat;

#endif

varyingvec2v_texCoord;

uniformsampler2DCC_Texture0;

vec4colors[8];

voidmain(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);

colors[5]=vec4(1,1,0,1);

colors[6]=vec4(1,1,1,1);

inty=int(mod(gl_FragCoord.y/3.0,7.0));

gl_FragColor=colors[y]*texture2D(CC_Texture0,v_texCoord);

}

这个效果的设计理念也是很清晰的。首先我们把原图的y轴色彩抽出,然后强制性的打上一些颜色,这样就会形成一个个的彩色横条。

然后我们把原图的材质给乘到打上横条以后的色彩上,就形成了彩色横条效果。

3.高亮效果

这个效果我暂时压后,因为这个效果里面涉及到了高斯模糊,所以在后面讲解会更加方便。

4.边缘检测

边缘检测的Shader效果也是Cocos2d-x里面本身就带有的一个Shader效果。

具体上的操作是使用了索贝尔算子,来计算出2D图形空间上梯度。在技术上,它是一种离散性差分算子,用来运算图像亮函数的梯度近似值。

当然,索贝尔算子仅仅是边缘检测一种方法之一,另外还有罗盘算子,Canny算子等等。

索贝尔算子包含了2组3*3的矩阵,分别为横向以及纵向,将它与图像做平面卷积,既可以亮度差分近似值。

假设A代表原始图形,上面的理论参考了wikipedia上的资料:http://en.wikipedia.org/wiki/Sobel_operator

然后我们来看具体实现,EdgeDetection.fsh.#ifdefGL_ES

precisionmediumpfloat;

#endif

varyingvec4v_fragmentColor;

varyingvec2v_texCoord;

vec2resolution;

uniformsampler2DCC_Texture0;

floatlookup(vec2p,floatdx,floatdy)

{

vec2uv=p.xy+vec2(dx,dy)/resolution.xy;

vec4c=texture2D(CC_Texture0,uv.xy);

return0.2126*c.r+0.7152*c.g+0.0722*c.b;

}

voidmain(void)

{

//simplesobeledgedetection

resolution=vec2(1024.0,768.0);

vec2p=v_texCoord.xy;

//Gxmatrixmultiplication

floatgx=0.0;

gx+=-1.0*lookup(p,-1.0,-1.0);

gx+=-2.0*lookup(p,-1.0,0.0);

gx+=-1.0*lookup(p,-1.0,1.0);

gx+=1.0*lookup(p,1.0,-1.0);

gx+=2.0*lookup(p,1.0,0.0);

gx+=1.0*lookup(p,1.0,1.0);

//Gymatrixmultiplication

floatgy=0.0;

gy+=-1.0*lookup(p,-1.0,-1.0);

gy+=-2.0*lookup(p,0.0,-1.0);

gy+=-1.0*lookup(p,1.0,-1.0);

gy+=1.0*lookup(p,-1.0,1.0);

gy+=2.0*lookup(p,0.0,1.0);

gy+=1.0*lookup(p,1.0,1.0);

floatg=gx*gx+gy*gy;

gl_FragColor.xyz=vec3(1.-g);

gl_FragColor.w=1.;

}

//Thisshaderisreferredtococos2d-xofficialengineshader.

//Checkhttp://www.cocos2d-x.org/fordetailedinformation.

仔细看下,gx,gy的值就是根据索贝尔算子矩阵所得,最后的每个像素的梯度近似值也与理论相符。这也是为什么这个着色效果可以做出边缘检测的原因。

5.冰花效果

冰花效果是个很有意思的模糊效果,这个效果源于一个很有爱的国际友人在10年博客上发表的一篇博文(查看文章)。

后来我在学习模糊效果的时候,一个国外论坛上有人引用了这个简单有有效的效果。

简单的说,这个着色效果模仿了冰花玻璃的效果,原理是根据一个伪随机的向量平移了像素的位置。

给张大点的效果图,可以更清晰的看出这个效果(效果图稍后补充)。

看上去是一个很有意思的效果,不过这个效果的实现却是惊人的简单。

FrostBlur.fsh#ifdefGL_ES

precisionmediumpfloat;

#endif

varyinglowpvec2v_texCoord;

uniformsampler2Du_texture;

floatrand(vec2co)

{

returnfract(sin(dot(co.xy,vec2(100,100)))+

cos(dot(co.xy,vec2(50,50)))*5.0);

}

voidmain()

{

vec2rnd=vec2(0.0);

rnd=vec2(rand(v_texCoord),rand(v_texCoord));

gl_FragColor=texture2D(u_texture,v_texCoord+rnd*0.02);

}

核心代码只有5行,其实就是平移了像素的位置,不过效果却不错。

6.卡通渲染

卡通渲染是一种去真实感的渲染方法,旨在使电脑生成的图像呈现出手绘的效果。渲染过程中一般会把常规光源的取值被逐一计算并投射到一小片独立的明暗区域上,产生卡通式的单调色彩。然后会有一个勾边的过程,用于突出物体。

当然,有些更精细的实现会得出更好效果。比如Unity就发表过一个卡通渲染的教程,中间包括采光,散光等一系列的处理(http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Toon_Shading)。

现在我们来看下Cocos2d-x的实现。

celShading.fsh

#ifdefGL_ES

precisionmediumpfloat;

#endif

varyingvec4v_fragmentColor;

varyingvec2v_texCoord;

vec2resolution;

uniformsampler2DCC_Texture0;

#defineFILTER_SIZE2

#defineCOLOR_LEVELS7.0

#defineEDGE_FILTER_SIZE2

#defineEDGE_THRESHOLD0.05

vec4edgeFilter(inintpx,inintpy)

{

vec4color=vec4(0.0);

for(inty=-EDGE_FILTER_SIZE;y<=EDGE_FILTER_SIZE;++y)

{

for(intx=-EDGE_FILTER_SIZE;x<=EDGE_FILTER_SIZE;++x)

{

color+=texture2D(CC_Texture0,v_texCoord+vec2(px+x,py+y)/resolution.xy);

}

}

color/=float((2*EDGE_FILTER_SIZE+1)*(2*EDGE_FILTER_SIZE+1));

returncolor;

}

voidmain(void)

{

//Shade

resolution=vec2(1024.0,768.0);

vec4color=vec4(0.0);

for(inty=-FILTER_SIZE;y<=FILTER_SIZE;++y)

{

for(intx=-FILTER_SIZE;x<=FILTER_SIZE;++x)

{

color+=texture2D(CC_Texture0,v_texCoord+vec2(x,y)/resolution.xy);

}

}

color/=float((2*FILTER_SIZE+1)*(2*FILTER_SIZE+1));

for(intc=0;c<3;++c)

{

color[c]=floor(COLOR_LEVELS*color[c])/COLOR_LEVELS;

}

//Highlightedges

vec4sum=abs(edgeFilter(0,1)-edgeFilter(0,-1));

sum+=abs(edgeFilter(1,0)-edgeFilter(-1,0));

sum/=2.0;

if(length(sum)>EDGE_THRESHOLD)

{

color.rgb=vec3(0.0);

}

gl_FragColor=color;

}

这里实现总共分为两个部分,一个是阴影(shade),一个是勾边(highlightedge)。

其实打阴影的过程,就是我们前面理论里的把常规光源投射到独立明暗区间的过程。这也是为什么卡通渲染会颜色有所加深,或者说,让有感觉一眼就不是真实图片。因为明暗间有平滑过渡的取值被明确的分开成了卡通式的单调色彩。

勾边的过程,也可使用上个效果中的索贝尔算子,也确实有不少应用和游戏中勾边过程使用了索贝尔算子。原中的边缘滤镜方法我并没有深究,有兴趣的朋友可以探索下。

我对这个效果的探索不是很深,其中主要原因就是这个效果渲染起来并不是很顺畅。甚至有些卡卡的,在iPadmini上都是这样,更不用说手机了。所以如果在实际应用中,肯定需要重新修改。不过阀值修改后,渲染速度会变快,不过卡通的质量也会有所下降。

7.石刻效果

石刻效果,是我个人非常喜欢的一个效果。这个效果理论上就是把像素变成高光或者阴影,换句话说就是明显的区分开来。

这个效果最早在Coco2d的开发中,就被开发者所发现了。代码简单,效果也很有特色。

我最早看到关于石刻效果的教程:《HowToCreateCoolEffectswithCustomShadersinOpenGLES2.0andCocos2d2.x》

这篇教程把时刻效果和反色放一起讲解了,还是很详细了。

不过想具体实现,用这个代码就已经足够了。#ifdefGL_ES

precisionmediumpfloat;

#endif

//Theshaderisinspiredandmodifiedfromcocos2dcustomshadertutorial

http://www.raywenderlich.com/10862/how-to-create-cool-effects-with-custom-shaders-in-opengl-es-2-0-and-cocos2d-2-x

varyingvec2v_texCoord;

uniformsampler2Du_texture;

voidmain()

{

//pixelsize

vec2onePixel=vec2(1.0/480.0,1.0/320.0);

//getv_texCoordate

vec2texCoord=v_texCoord;

//exactlystepfollowtheidea

vec4color;

color.rgb=vec3(0.5);

color-=texture2D(u_texture,texCoord-onePixel)*5.0;

color+=texture2D(u_texture,texCoord+onePixel)*5.0;

//grayscale

color.rgb=vec3((color.r+color.g+color.b)/3.0);

gl_FragColor=vec4(color.rgb,1);

}

核心代码其实就3行,我们想要让图片的像素看起来很明显不同,那我们需要个基本色,color.rgb=vec3(0.5);

然后基于这个基本色,把像素之间的色差给打开。

最后在利用我们之前的灰色效果,把整个图形变灰。

这样就能达成石刻效果了。

后来我在网上搜索,也有些算法是通过梯度计算边缘,然后也能达到同样的效果。不过光听都感觉,这个过程会有些繁复。

8.高斯模糊

最后个效果也就是高斯模糊,也叫高斯平滑。在计算机图像领域,是个很重的话题。通常用它来减少图像噪声以及降低细节层次。这种模糊技术生成的图像,其视觉效果就像是经过一个半透明屏幕在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同。

从数学角度来看,图像的高斯模糊效果就是图像与正态分布做卷积。由于正态分布又叫高斯分布,所以这个效果也叫高斯模糊。由于高斯函数的傅里叶变换是另一个高斯函数,所以高斯模糊对于图像来说是个低通滤波器。

这里对于高斯模糊的实现,有一些可以增加渲染速度的小技巧。

高斯模糊是一种图像模糊滤波器,它用正态分布计算图像中每个像素的变换。N维空间正态分布方程为:

但是在实际过程中,我们可以先对水平方向先做一次一维的模糊,再对垂直方向做一次一维模糊,同样可以达到使用二维矩阵变换得到的效果。

这是因为高斯模式线性可分,引用下GameRendering开发小组的例子。其实打开数学公式也可以证明线性可分。

另一个实现过程中的一个小技巧就是可以用预计算的方法。

我们可以通过高斯函数,预先计算出模糊的权重。

这张是我App里面的一个教学slides,解释的还是很清楚的。

所以最后的实现可以变成:

Gaussian_Blur.fsh#ifdefGL_ES

precisionmediumpfloat;

#endif

varyingvec4v_fragmentColor;

varyingvec2v_texCoord;

uniformsampler2DCC_Texture0;

vec2blurSize;

uniformvec4substract;

voidmain(){

blurSize=vec2((1.0/1024.0)*3.0,(1.0/768.0)*3.0);

vec4sum=vec4(0.0);

sum+=texture2D(CC_Texture0,v_texCoord-4.0*blurSize)*0.063327;

sum+=texture2D(CC_Texture0,v_texCoord-3.0*blurSize)*0.093095;

sum+=texture2D(CC_Texture0,v_texCoord-2.0*blurSize)*0.122589;

sum+=texture2D(CC_Texture0,v_texCoord-1.0*blurSize)*0.144599;

sum+=texture2D(CC_Texture0,v_texCoord)*0.152781;

sum+=texture2D(CC_Texture0,v_texCoord+1.0*blurSize)*0.144599;

sum+=texture2D(CC_Texture0,v_texCoord+2.0*blurSize)*0.122589;

sum+=texture2D(CC_Texture0,v_texCoord+3.0*blurSize)*0.093095;

sum+=texture2D(CC_Texture0,v_texCoord+4.0*blurSize)*0.063327;

gl_FragColor=sum*v_fragmentColor;

}

最后来张效果图:

前面跳过的高亮效果,是基于高斯模糊的一个变版。

那么具体实现就是如果我们把原来图形的直接应用高斯函数求出来的数值,那就是高斯模糊。如果我们在原值上加上高斯函数的值,那就是高亮+模糊。

JAVA瑞波币_关于Shader着色器的使用(这个是GL通用的,用什么开发设置都一样) | Java与Ripple怎么玩?...相关推荐

  1. 比特币、以太坊、瑞波币、万融链和区块链

      关于比特币 8 年,比特币创造一个神话--价格上涨近 300 万倍,国内价格一度突破 2 万元.在这场神话中,不同的人看到了不同的故事.投机者看到了赚钱的机会,技术极客看到了改变未来的技术,传统金 ...

  2. 【 Threejs 】- Shader 着色器实例渲染教程

    着色器在threejs中是一个难点,话不多说,先来看看着色器是什么? 如果您已经有使用计算机绘图的经验,您就会知道在这个过程中您先画一个圆,然后画一个矩形.一条线.一些三角形,直到您组成您想要的图像. ...

  3. Lesson3 Shader着色器

    2019独角兽企业重金招聘Python工程师标准>>> Shader(着色器): 它是图形硬件设备所执行的一类特殊函数,可以把它看作专为图形处理单元(GPU)编译的一种小型程序.Op ...

  4. Unity Shader着色器优化

    对游戏开发者而言,着色器长久以来就是游戏开发中的重要部分,在Unity中编写并实现着色器的过程直观且高效,优秀的着色器还可以创造非常精美的游戏画面,同时保证极高的性能.今天将由Unity的技术工程师张 ...

  5. UE4 Shader 着色器概述

    UE4 Shader 着色器概述 https://zhuanlan.zhihu.com/p/32628933 名词 FShaderType 用于序列化和反序列化,可以被实例化为具体的ShaderCla ...

  6. Opengl入门基础-shader着色器画方形并且填颜色

    文章目录 一.目的 二.结果 三.详细过程 下载 一.目的 opengl shader画方形并且填颜色 二.结果 成功画方形并用shader填充彩色 三.详细过程 https://blog.csdn. ...

  7. Shader着色器代码辅助工具

    借用二次元界一个传奇组合的话:"既然你诚心诚意地发问了,我们就大发慈悲地告诉你--"这次我为普罗开发者提供Shader代码辅助工具的安装指南,也是作为Unity着色器训练营第二期直 ...

  8. Unity3d基础知识之Texture纹理、Shader着色器、Material材质、Rendering Mode

    Unity3d基础知识之Texture纹理.Shader着色器.Material材质.Rendering Mode 一.纹理.着色器与材质 Texture(纹理):应用于网格表面上的标准位图图像.Un ...

  9. Shader学习_曲面细分着色器

    曲面细分 详细介绍 当然除了细分与简化之外,还有另外一种同属一类的操作叫做==曲面规则化(Mesh Regularization)==其所作的便是将三角面都变的尽可能相同,从而也达到提升模型效果的目的 ...

最新文章

  1. ubuntu下sudo命令不能使用问题
  2. anki模板_梁宝川:如何导入,导出anki笔记?
  3. Mongodb定时备份脚本和清除脚本
  4. Google IO 2015 Material Now
  5. DeepRacer 资源合集
  6. Dos/Linux/nc/Xscan/Xsniffer
  7. 微机原理笔记day01 计算机发展史,和计算机组成部分
  8. c语言 组合问题,排列组合问题 C语言
  9. c 语言 输入一个英文字母,判断该字母是大写还是小写,c语言从键盘输入一个字符,判断该字符是大写英文字母.小写英文字母还是数字....
  10. linux代码之atomic
  11. 有赞云支付php接口,有赞个人免签支付设置
  12. CTFHub 技能树web
  13. 快手本地生活可以入场吗
  14. PHP+TP框架实现微信公众号开发之发送模板消息
  15. 《PHP挖宝》1—再论框架
  16. 计算机设计大赛应用软件组,组一览表(计算机设计大赛).pdf
  17. keypad.h arduino按键操作显示
  18. 「伯克利大学」 的计算机入门教程
  19. C++ primer Plus(第六版)第十三章 类继承 章节编程练习答案
  20. jQuery的样式切换

热门文章

  1. 余承东:华为Mate 30 RS保时捷设计 9月19日发布
  2. 华为年度旗舰Mate 30 Pro真机现身,既惊喜又失望...
  3. 2019款iPhone XR新配色机模上手:就是这个味儿
  4. 推搡辱骂外卖小哥 美女主持人再发道歉视频:网友集体不买账
  5. 上海查处一批涉“樱桃直播”传播淫秽物品牟利案女主播 已有14人获刑
  6. 马斯克扎心了!猎鹰重型火箭核心助推器运输过程中坠海
  7. 苹果叫停经销商供货拼多多?官方回应:系谣言 所售新款iPhone均为正品
  8. java设计模式之创建型设计模式
  9. Python生成随机数的方法
  10. 揭开git的神秘面纱