cocos2d-x 强大的shader系列:【OpenGL】Shader实例分析(一)-Wave

cocos2d-x 强大的shader系列:【OpenGL】Shader实例分析(一)-Wave,第1张

概述转发请保持地址:http://www.voidcn.com/article/p-bzdgsshf-bap.html 这篇文章主要分析一个Shader,从而感受shader的魅力,并学习相关shader的函数的用法。 先看Shader运行的效果(随着时间移动的波浪,具体效果请参考 https://www.shadertoy.com/view/4dsGzH): 下面是代码:   Shader "sha

转发请保持地址:http://www.jb51.cc/article/p-bzdgsshf-bap.html

这篇文章主要分析一个Shader,从而感受shader的魅力,并学习相关shader的函数的用法。

先看Shader运行的效果(随着时间移动的波浪,具体效果请参考https://www.shadertoy.com/view/4dsGzH):

下面是代码:

Shader"shadertoy/Waves"{//seehttps://www.shadertoy.com/vIEw/4dsGzH CGINCLUDE #include"UnityCG.cginc" #pragmatarget3.0 structvertOut{ float4pos:SV_position; float4srcPos; }; vertOutvert(appdata_basev){ vertOuto; o.pos=mul(UNITY_MATRIX_MVP,v.vertex); o.srcPos=ComputeScreenPos(o.pos); returno; } fixed4frag(vertOuti):color0{ fixed3color1=fixed3(0.0,0.0,0.3); fixed3color2=fixed3(0.5,0.0); floatBLOCK_WIDTH=0.03; float2uv=(i.srcPos.xy/i.srcPos.w); //TocreatetheBGpattern fixed3final_color=fixed3(1.0); fixed3bg_color=fixed3(0.0); fixed3wave_color=fixed3(0.0); floatc1=fmod(uv.x,2.0*BLOCK_WIDTH); c1=step(BLOCK_WIDTH,c1); floatc2=fmod(uv.y,108); color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> c2=step(BLOCK_WIDTH,c2); bg_color=lerp(uv.x*color1,uv.y*color2,c1*c2); //TOcreatethewaves floatwave_wIDth=0.01; uv=-1.0+2.0*uv; uv.y+=0.1; for(floati=0.0;i<10.0;i++){ uv.y+=(0.07*sin(uv.x+i/7.0+_Time.y)); wave_wIDth=abs(1.0/(150.0*uv.y)); wave_color+=fixed3(wave_wIDth*1.9,wave_wIDth,wave_wIDth*1.5); } final_color=bg_color+wave_color; returnfixed4(final_color,1.0); ENDCG SubShader{ Pass{ CGPROGRAM #pragmavertexvert #pragmafragmentfrag #pragmafragmentoptionARB_precision_hint_fastest FallBackOff }

下面进行分析:

1.ComputeScreenPos的解析:

用于把三维的坐标转化为屏幕上的点。有两种方式,请参考官方例子

ComputeScreenPos在UnityCG.cginc文件中定义如下:

//Projectedscreenpositionhelpers #defineV2F_SCREEN_TYPEfloat4 inlinefloat4ComputeScreenPos(float4pos){ float4o=pos*0.5f; #ifdefined(UNITY_HALF_TEXEL_OFFSET) o.xy=float2(o.x,o.y*_ProjectionParams.x)+o.w*_ScreenParams.zw; #else #endif #ifdefined(SHADER_API_FLASH) o.xy*=unity_NPOTScale.xy; o.zw=pos.zw; 原理解析(待续)

2. 背景的绘制

2.1)fmod用于求余数,比如fmod(1.5,1.0) 返回0.5;

2.2) step用于大小的比较,step(a,x) : 0 if x<a; 1 if x>=a; 比如: step(1,1.2),返回1; step(1,0.8) 返回0;

2.3) 结合fmod和step可以得到一个虚线的效果。 比如要得到虚线段长度为1的代码如下:

c1 = fmod(x,2*wIDth); c1=step(wIDth,c1); //其中wIDth为1

那么如果x的范围是[0,1),c1的值为0;范围为[1,2),c1的值为1;2为一个周期;

那么fmod起到了制作周期的作用,step计算周期内的0和1;

2.4)把2.3中的知识运用到2维,就可以计算出方块。

lerp函数的用法:lerp(a,b,f), f为百分数(取值范围[0,1]);如果f为0,则lerp返回a,f为1,则返回b。f为0到1之间,就返回a到b之间的值。

代码中的 lerp(uv.x*color1,c1*c2); 其中c1和c2的取值不是为1,就是为0,所以就可以变成网格的情况。 背景绘制如下:

3. 波纹的绘制

3.1 ) 坐标的转化

uv = -1.0 + 2.0*uv; // 把uv的x和y轴压缩到原来的0.5倍后,向右上角移动1个单位。

3.2 ) 画一条直线:

由于上面把y轴移动到屏幕的中心,所以屏幕的上半部分为正的,下半部分为负的,代码如下:

wave_wIDth=abs(1.0/(50.0*uv.y)); wave_color=fixed3(wave_wIDth*1.9,wave_wIDth*1.5);

其中50.0是用来控制线的宽度的(数值越大,线越细),效果如下:

3.3)把直线变为曲线,并使其动起来:

uv.y+=(0.07*sin(uv.x*10+_Time.y)); wave_wIDth=abs(1.0/(50.0*uv.y)); wave_color=fixed3(wave_wIDth*1.9,255)">效果如下:

3.4)多画几条曲线,形成波浪:

for(floati=0.0;i<10.0;i++){ uv.y+=(0.07*sin(uv.x+i/7.0+_Time.y)); wave_wIDth=abs(1.0/(150.0*uv.y)); wave_color+=fixed3(wave_wIDth*1.9,wave_wIDth*1.5); 最终效果请见文章开头。

其实写shader,很多时候都是要通过不断地效果叠加并调试来达到效果。

总结

以上是内存溢出为你收集整理的cocos2d-x 强大的shader系列:【OpenGL】Shader实例分析(一)-Wave全部内容,希望文章能够帮你解决cocos2d-x 强大的shader系列:【OpenGL】Shader实例分析(一)-Wave所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1032468.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存