视频链接:Decryption card 解密卡 因为用到的基本上都是前八周的学习内容,不作赘述,逐一简单说说要求对应的画面呈现吧
1.有山有水有角色 2.有静有动有交互 3.顶点片段不能少(Lighting Surf不做强制要求) 4.抓屏后期(至少)选一路
山、水、角色
山
山体网格本身使用的是商城雪山资源,但是整体画面风格偏向卡通,贴图过于写实,需要经过处理。在红白场景中分别采用了不同的方法: 红色场景的山主要还是使用了卡通着色器,之前的笔记有提到:Shader攻占笔记(四)卡通着色器(“顶点与法线之间做抉择”部分)。 贴图部分进行了马赛克处理,即采样时对uv进行了一个floor操作,动态控制,方便调试。
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);
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);
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 = lerp(stepCol2, stepCol, stepCol.a);
col = lerp(col, stepCol, saturate(stepCol.a - col.a));
float cond = step(abs(i.uv.x - 0.5), 0.499) * step(abs(i.uv.y - 0.5), 0.499);
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));
float4 stepNormalCol = tex2D(_StepBump, (i.worldPos.xz - _PlayerPos.xz) * 0.015 + 0.5);
float3 stepNormal = stepNormalCol.rgb * 2 - 1;
stepNormal.rg *= 2 *_BumpScale;
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
角色
和红色场景的山体使用了同一套卡通材质,加了一点高光效果
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移动。
视频制作的问题
插入的视频有清晰度被削减的问题,通过两个方法可以有微弱提高效果:
- 增加RenderTexture文件本身的分辨率
- 增加原视频的清晰度
前者可以在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方法来控制纹理范围,使得雪和血在水面之上截止。很简单就不贴了。
|