(笔记)中级Shader教程01 2D海洋 2D太阳 2D云朵

原作者  FishMan的技术专栏

以下是代码以及自己学习笔记:

  1. sin波函数的理解和应用
  2. 极坐标+sin 对于波动圆环的实现
  3. 2D模拟3D中”分层”的概念

 

 

1.原理:

备注:sin波形在shader 是常用的波形 

sin函数是周期函数,对于无限重复的现象是一种很好的模拟 类似傅里叶变换一样,复杂的函数可以用简单的sin cos 组合进行比逼近 波浪这种效果是一种典型。

2.分析:

1.云的实现

  1. 形状:多个不同大小,偏移的圆,通过+=的方式合成云朵  实际上就是N个大小的圆
  2. 动态:简单的走UV

2.太阳的实现

  1. 形状:光的边缘是通过极坐标中的角度带入多个不同频率的sin函数中是实现
  2. 动态:不同频率的sin函数不同的相位偏移速度来实现

3. 海洋的实现

  1. 原理:观察海洋,海浪的变化是连续的,随机的,而且是相似的。 这几个特点是不是非常像前面文章提到过的Noise的感觉,局部是连续的,但整体的感觉又是随机的。 很类似对吧,后面我们实现山脉(FBM)和3D海洋(FFT)的时候,再回过头来看待这两种方式,会发现他们的合成形式是一样的,这里我们使用多个频率,振幅不同的Sin函数海实现对波浪的模拟。 我们通过”多层”的方式来模拟3D效果,同样需要考虑透视对于图像大小,范围,清晰度的影响
  2. 形态:分层实现,单层中叠加不同频率,振幅,偏移的方式sin函数
  3. 动态:不同的层不同的频率,同一层中,不同频率之间拥有不同的相位偏移速度

Shader "FishManShaderTutorial/2DCloudSea"{
	Properties{
	    _MainTex ("MainTex", 2D) = "white" {}
	}

	SubShader
	{
	    Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }

	    Pass
	    {
	        ZWrite Off
	        Blend SrcAlpha OneMinusSrcAlpha

	        CGPROGRAM
	        #pragma vertex vert
	        #pragma fragment frag
			#include "ShaderLibs/Framework2D.cginc"
	
			#define LAYER 20.0
			fixed Wave(float layer,fixed2 uv,fixed val){
				float amplitude =  layer*layer*0.00004;  //振幅
				float frequency = val*200*uv.x/layer;    //频率
				float phase = 9.*layer+ _Time.z/val;
				return amplitude*sin(frequency+phase); 
			}
			float Circle(fixed2 uv,fixed2 center,float size,float blur){
				uv = uv - center;
				uv /= size;
				float len = length(uv);
				return smoothstep(1.,1.-blur,len);
			}
			float AngleCircle(fixed2 uv,fixed2 center,float size,float blur){
				uv = uv - center;
				uv /= size;
				float deg = atan2(uv.y,uv.x) + _Time.y * -0.1;
				float len = length(uv);
				float offs =( sin(deg*9)*3.+sin(deg*11+sin(_Time.y*6)*.5))*0.05;
				return smoothstep(1.+offs,1.-blur+offs,len);
			}

			float DrawCloud(fixed2 uv,fixed2 center,float size){
				uv = uv - center;
				uv /= size;
				float col = Circle(uv,fixed2(0.,0.),0.2,0.05);
				col =col *  smoothstep(-0.1,-0.1+0.01,uv.y);
				 col += Circle(uv,fixed2(0.15,-0.05),0.1,0.05);
				 col += Circle(uv,fixed2(0.,-0.1),0.11,0.05);
				 col += Circle(uv,fixed2(-0.15,-0.1),0.1,0.05);
				 col += Circle(uv,fixed2(-0.3,-0.08),0.1,0.05);
				 col += Circle(uv,fixed2(-0.2,0.),0.15,0.05);
				return col;
			}
			float DrawClouds(fixed2 uv){
				uv.x += 0.03*_Time.y;
				uv.x = frac(uv.x+0.5) - 0.5;
				float col = DrawCloud( uv,fixed2(-0.4,0.3),0.2);
				col += DrawCloud( uv,fixed2(-0.2,0.42),0.2);
				col += DrawCloud( uv,fixed2(0.0,0.4),0.2);
				col += DrawCloud( uv,fixed2(0.15,0.3),0.2);
				col += DrawCloud( uv,fixed2(0.45,0.45),0.2);
				return col;
			}
			//----------------------------------------------------------------
			// #include "ShaderLibs/Framework2D.cginc"  里面写了ProcessFrag函数
			//float3 ProcessFrag(float2 uv);
			//float4 frag(v2f i) : SV_Target{
			//	return float4(ProcessFrag(i.uv),1.0);}
			//----------------------------------------------------------------
			float3 ProcessFrag(float2 uv)  {                
			    float3 col = float3(0.0,0.0,0.0);
			    float num = 0.;
			    for (float i=1.; i < LAYER; i++) {
			    	//float wave = 2.*Wave(i,uv,1.)+Wave(i,uv,1.8)+.5*Wave(i,uv,3.);
					float wave = 2.*Wave(i,uv,1.0);
			    	float layerVal = 0.7-0.02*i + wave;
			        if(uv.y >layerVal){
			            break;
			        }
					num = i;//计算所在层的ID
			    }
			    col = num*fixed3(0,.03,1);//计算每一层的基本颜色
			    col += (LAYER - num) * fixed3(.04,.04,.04);//颜色叠亮
				if(num ==0){
					//添加海平面泛光
					float ry = Remap(0.7,1.0,1.0,0.0,uv.y); 		 		//重映射  将值从一个范围重映射到另一个范围。
					col = lerp(fixed3(0.1,0.6,0.9),fixed3(0.1,0.7,0.9),ry); //float Remap(float oa,float ob,float na,float nb,float val){
					col += pow(ry,10.)*fixed3(0.9,0.2,0.1)*0.2;				//return (val-oa)/(ob-oa) * (nb-na) + na;}
				}
				//调整UV为(-0.5,-0.5,0.5,0.5)方便绘图
				uv = uv - fixed2(0.5,0.5);
				//添加太阳
				fixed2 sunPos = fixed2(0.3,0.35);
				fixed sun = Circle(uv,sunPos,0.06,0.05);
				fixed sunCircle = AngleCircle(uv,sunPos,0.08,0.05);
				col = lerp( col ,fixed3(0.9,0.6,0.15),sunCircle);
				col = lerp( col ,fixed3(0.98,0.9,0.1),sun);
				//云
				col += DrawClouds(uv);
				return col;
			}
	    ENDCG
	}//end pass
  }//end SubShader
}//end Shader

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值