Shader攻占笔记(九)结课作业小记

在这里插入图片描述
在这里插入图片描述
视频链接:Decryption card 解密卡
因为用到的基本上都是前八周的学习内容,不作赘述,逐一简单说说要求对应的画面呈现吧

1.有山有水有角色
2.有静有动有交互
3.顶点片段不能少(Lighting Surf不做强制要求)
4.抓屏后期(至少)选一路

山、水、角色

山体网格本身使用的是商城雪山资源,但是整体画面风格偏向卡通,贴图过于写实,需要经过处理。在红白场景中分别采用了不同的方法:
在这里插入图片描述
红色场景的山主要还是使用了卡通着色器,之前的笔记有提到:Shader攻占笔记(四)卡通着色器(“顶点与法线之间做抉择”部分)。
贴图部分进行了马赛克处理,即采样时对uv进行了一个floor操作,动态控制,方便调试。

//_MainLayer变量控制马赛克分层的层数
fixed4 col = tex2D(_MainTex, float2(floor(i.uv * _MainTexLayer)/_MainTexLayer));

在此之上,最后计算完颜色,在表面较暗的部分使用了圆点遮罩。(追求更写实可以在diff或者NdotL部分进行 lerp 阴影添加)
在这里插入图片描述

c = _LightColor0 * diff * NdotL * col * _Color;
//------------------------[阴影]
//采样贴图,调整对比度
fixed bump = saturate(tex2D(_Bump, i.buv * 15).r  + 0.4f);
//和原来的颜色进行lerp上色
//_ShadowRange变量控制阴影范围
c = lerp(c * bump, c, step(_ShadowRange, c.r));
return c;

在这里插入图片描述
白色场景的山体比较简单,单纯地拉到PS里面做了晶格化的滤镜处理,效果还是不错的。
在这里插入图片描述
在这里插入图片描述

在水的制作过程中遇到了几个问题,简单说说

轨迹的问题

轨迹制作的灵感主要来源于一篇雪地沙地的shader文章:游戏中沙漠、雪地的轨迹、脚印实现。里面使用了一种保持人物停留在RT中心以节省资源的方式,觉得很妙,推荐读读。
但是实际场景展示中,发现水和沙地、雪地的轨迹还是有一定区别的,波纹和衰减的频率都不太一样(果然还是不能偷懒照搬);
其次,文章中是通过改变其alpha来使波纹逐渐回到原点的,在不透明的材质上效果还行,但是放在水面这种地方就比较复杂,它使一整片RT范围内的数值都改变,不能单纯地加到现有的波纹之上(会变得更亮),也不能单纯地使用step来删除掉某些信息,因为波峰和波谷都是制造波纹需要的内容;
再次,我的视角相对比较水平,其实波纹幅度较小的情况下还是不能看清,于是由于时间关系索性暂时不优化了。
即使没有大成功,学习的部分还是写了挺多注释,在此做个记录。

生成脚印的shader

fixed4 frag (v2f i) : SV_Target
{
	//角色的位移差作为输入偏移轨迹贴图
	fixed4 col = tex2D(_MainTex, i.uv + _DeltaPos.xz * 0.015);
	//uv倍数即为圆的tiling
	//缩放为原uv的1/n后,+0.5挪到中点
	fixed4 stepCol = tex2D(_StepBump, (i.uv - 0.5) * 26 + 0.5);		//残影部分
	fixed4 stepCol2 = tex2D(_StepBump, (i.uv - 0.5) * 39 + 0.5);	//本体圆环部分
	stepCol2.rg = 1 - stepCol2.rg; //本体圆环突出
	//残影随着stepCol的a通道的降低 从stepCol2逐渐减淡
	stepCol = lerp(stepCol2, stepCol, stepCol.a);
	
	col = lerp(col, stepCol, saturate(stepCol.a - col.a));
	//0.499 > abs(i.uv.x - 0.5)? 1:0
	float cond = step(abs(i.uv.x - 0.5), 0.499) * step(abs(i.uv.y - 0.5), 0.499);
	//col慢慢过渡到float4() a通道渐低 模拟痕迹逐渐消失
	col = lerp(float4(0.5,0.5,1,0), col, cond * 0.996);
	return col;
}

使用脚印的shader:

float3x3 tangentToWorld = float3x3(normalize(i.tangent), normalize(i.bitangent), normalize(i.normal));
 
//处理后的轨迹图 放RT
float4 stepNormalCol = tex2D(_StepBump, (i.worldPos.xz - _PlayerPos.xz) * 0.015 + 0.5);
float3 stepNormal = stepNormalCol.rgb * 2 - 1;
//float3 stepNormal = UnpackNormal(stepNormalCol);//test

//提高rg的值 加强轨迹颜色
//整体地形凹凸程度
stepNormal.rg *= 2 *_BumpScale;

//TBN矩阵将切线空间下的法线变换到物体空间下的法线
float3 normal = mul(normalize(stepNormal), tangentToWorld);

有关法线混合的内容,可以阅读:法线混合
有关TBN矩阵的内容,可以阅读:切线空间(TBN) ---- 聊聊图形学中的矩阵运算

折射的问题

在这里插入图片描述
之前写折射的时候和写玻璃差不多,垂直往下看的时候观感还凑合,但是一到水平角度就有问题了:没有在水里的部分也受到了折射影响。
可以在扰动之前,通过一个是否在水里检测来筛选出在水底的内容

//用深度信息比较判断是否在水里
float depth2 = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, float4(i.scrPos.x, i.scrPos.yzw));
depth2 = LinearEyeDepth(depth2);
fixed inWater = 1 - saturate(depth2 - i.scrPos.w * _Deepness);

最后的扰动构成:

fixed2 offset = bump2.xy *_Dist_refr        //噪声扰动乘程度
              * _GrabPass_TexelSize * 2000   //纹素大小 抵消比例影响
              * i.scrPos.z                  //越靠近水底的部分扰动程度越大
              * inWater;                    //是否是在水里的部分
fixed4 grabColor = tex2Dproj(_GrabPass, UNITY_PROJ_COORD(i.scrPos + offset.x));
                

Unlit与深度检测的问题

在我给人物放上卡通材质之后,我发现用深度写的边缘泡沫不见了,进而发现unity自带的所有Unlit材质都不能显现泡沫。这个时候大佬指了路,告诉我得在SubShader后加一个Fallback,加上之后果然成功了。
shader最后FallBack

角色

和红色场景的山体使用了同一套卡通材质,加了一点高光效果

//高光区域 使用_HighlightRange控制高光范围
//须在分层之前处理(占位较小
//但是调整时需要注意避免范围的时候和分层结果交叉
fixed highlight = smoothstep(_HighlightRange, 1, NdotL);
NdotL = max(0.3 * _MainTexLayer, floor(NdotL * _LightVal)/ _LightVal);//漫反射部分光照分层

把皮囊加工了一下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
鲸的处理和人差不多,不作赘述。

静、动、交互

说说“动”吧,这个大圆环请添加图片描述
和顶点那章笔记里头猴子瞪眼差不多:Shader攻占笔记(六)顶点涟漪与遮罩,外层Pass是普通的贴图,加入了朝法线方向浮动的方式(需要裂开的效果,所以不用顶点方向,具体效果参见笔记六中布丁部分),内层是自发光Pass。
使用blender的甜甜圈做基础,细分后再在上面刷了几刷。
在这里插入图片描述
小石头同样简单做了一下,作为粒子系统的第四层环绕在圆圈周围。

交互

在这里插入图片描述

思路

刚开始拿大赛模板做的,动画采用Timeline控制的方式,一共就只有五秒钟,不太方便做交互。于是才加入的轨迹波澜,算是角色和波纹的交互;但又觉得不太足够,因为还是没有用户和内容的交互,后期如果需要上交可交互的版本将会比较局促。
后来想到了冒险小虎队里的解密卡,于是就又搭建了一个场景(白色场景):在Unity内跨场景遮罩大概是不太可能的,想到内外基本同步,本身Timeline是没有交互,时长又相对较短,于是直接使用了插入视频的方式来增加微弱的游戏性。卡面自制,使用了Unity内部的Vedio Player遮罩组件,通过脚本控制遮罩层和视频层的UI移动。

视频制作的问题

插入的视频有清晰度被削减的问题,通过两个方法可以有微弱提高效果:

  1. 增加RenderTexture文件本身的分辨率
  2. 增加原视频的清晰度

前者可以在Unity中设置。本体的分辨率是1920 x 600,*我将RT的分辨率提高到了3200 x 1000;
后者可以参考这篇文章(【Unity开发】Unity引擎生成2K视频的方法 )提高分辨率,主要思路是在场景中使用内置提高的分辨率进行逐帧截图,存在电脑里,再通过其他软件合成视频。
原帖的评论区提到可以通过AE来合成视频,不需要下载软件合并了。

顶点片段、抓屏/后期

大部分自编着色器都是顶点片段着色器,用的表面着色器比较少。
抓屏在两个场景的水面部分,以及白色场景角色背上的玻璃人部分使用,主要思想和抓屏玻璃章节笔记里普通畸变玻璃类似,不作赘述。链接:shader攻占笔记(七)抓屏玻璃大杂烩 GrabPass{}
在这里插入图片描述

表面着色器

在场景中的雪地和染血地面是使用表面着色器来绘制的,上色思路和基础雪地相似。雪地场景地面纹理是经过ps彩块化的草地贴图;血液场景地面纹理是马赛克uv采样的山地贴图。
在这里插入图片描述
在这里插入图片描述
基础雪地shader

void surf (Input IN, inout SurfaceOutputStandard o)
{
    half4 c = tex2D(_MainTex, IN.uv_MainTex);//表面纹理
    o.Normal = UnpackNormal(tex2D(_Bump, IN.uv_Bump));//表面法线
    //雪地上色
    if(dot(WorldNormalVector(IN, o.Normal),
        _SnowDirection.xyz) >= _Snow)
        o.Albedo = _SnowColor.rgb;
    else
        o.Albedo = c.rgb * _MainColor;
        o.Alpha = 1;
}

此外,使用worldPos.y 的 step方法来控制纹理范围,使得雪和血在水面之上截止。很简单就不贴了。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值