崩坏学园3里离摄像机近距离的头发透明效果在unity里的实现方法
2016-09-30 23:16
876 查看
最近国内崩坏3开始公测了,在看到宣传视频的时候我就对这个游戏画面很有兴趣了。然后第一时间就下来玩了。本人渣手机最低特效帧数都不稳定,好在今天更新了新版本,模拟器能正常运行了。立马就开了个模拟器最高画质来玩,效果棒棒的。网上搜了下,这个团队说是用了罪恶装备xrd的2d渲染技术,怪不得我当时看画面的时候立马就想到了罪恶装备xrd。而且这技术用得也非常到位,不管是动态的角色头发的卡通高光,还是那种动画里特有的自身阴影效果都非常到位。而现在不管是中国还是日本,大部分2d卡通渲染风格的游戏里,角色都是靠死的贴图来表现高光和阴影的。不然就是高光和阴影没有那种卡通风格的感觉。
崩坏3的这种动态效果一下就让整个角色的效果上了几个档次。
这里我注意到了在选择角色武器的时候,由于长发角色容易把武器遮住,制作组特别给头发做了半透明效果,这点细节好评。这里我就用unity自己实现了一下这个效果。先做个笔记吧。
效果如图
原理是在shader里比较摄像机距离和当前像素的距离,当这个距离小于某个值以后,就把某个范围内的一段像素的透明度按照一个线性的方式赋值。
这里画一个图比较好理解。
y轴代表透明度,x轴代表顶点离摄像机的距离。透明度程线性递增,透明度是1的时候则完全不透明,为0的时候则完全透明。我们高中学过直线方程为 y = a*x + b。
然后我们在模型顶点和摄像机距离小于 start的时候开始绘制线性递增的透明效果,距离大于end以外的像素透明度则都为大于等于1。
那么现在就变成了,已知直线方程为y = a*x + b,当x = start的时候 y=0,当x = end的时候,y = 1,求a b的值。
于是就有了一个方程组
a * start + b = 1;
a * end + b = 0;
的方程组了。
解这个方程组得出 a = 1/(start - end); b = -end/(start - end)
于是这个方程就变成了 y = x / (start - end) - end / (start - end) 了。
好了,解到这里我们已经知道了像素透明度和摄像机距离的关系了。接下来我们只要把这个公式写在shader里就可以了。
感谢群里的 LJL&PRC 大大的帮助
崩坏3的这种动态效果一下就让整个角色的效果上了几个档次。
这里我注意到了在选择角色武器的时候,由于长发角色容易把武器遮住,制作组特别给头发做了半透明效果,这点细节好评。这里我就用unity自己实现了一下这个效果。先做个笔记吧。
效果如图
原理是在shader里比较摄像机距离和当前像素的距离,当这个距离小于某个值以后,就把某个范围内的一段像素的透明度按照一个线性的方式赋值。
这里画一个图比较好理解。
y轴代表透明度,x轴代表顶点离摄像机的距离。透明度程线性递增,透明度是1的时候则完全不透明,为0的时候则完全透明。我们高中学过直线方程为 y = a*x + b。
然后我们在模型顶点和摄像机距离小于 start的时候开始绘制线性递增的透明效果,距离大于end以外的像素透明度则都为大于等于1。
那么现在就变成了,已知直线方程为y = a*x + b,当x = start的时候 y=0,当x = end的时候,y = 1,求a b的值。
于是就有了一个方程组
a * start + b = 1;
a * end + b = 0;
的方程组了。
解这个方程组得出 a = 1/(start - end); b = -end/(start - end)
于是这个方程就变成了 y = x / (start - end) - end / (start - end) 了。
好了,解到这里我们已经知道了像素透明度和摄像机距离的关系了。接下来我们只要把这个公式写在shader里就可以了。
Shader "Unlit/CutPixelByDistance" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" "Queue" = "Transparent" } LOD 100 Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; float lengthInCamera : TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); //计算顶点和camera之间的距离 o.lengthInCamera = length(_WorldSpaceCameraPos - v.vertex.xyz); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); col.a = 1; float Start = 3;//设定开始值 float End = 2.5;//设定结束值 //如果像素和camera直接的距离小于Start则给alpha赋值 if (i.lengthInCamera < Start) { col.a =i.lengthInCamera /(Start - End) - End /(Start - End) ; } return col; } ENDCG } } }在vert顶点函数里求出顶点和摄像机之间的距离以便在片段函数里调用。 然后片段函数frag里 当顶点和摄像机距离小于 start的时候就开始给alpha赋值, col.a就是公式里的y了,i.lengthInCamera就是公式里的x了,这样得出来的shader效果如下图。 这里我把 start和end写死了,如果把这两个值作为一个range放到shader的顶端,就可以在unity的shader面板上随意调整了。这个效果是不是很人性化呢。实现这个效果需要开启透明混合,需要多消耗一些性能了,不知道有没有其他更好的方法实现这种效果呢。
感谢群里的 LJL&PRC 大大的帮助
相关文章推荐
- 崩坏学园3里离摄像机近距离的头发透明效果在unity里的实现方法
- Activity透明/半透明效果的设置transparent(两种实现方法)【转】
- JS+CSS实现弹出全屏灰黑色透明遮罩效果的方法
- 互动大屏,unity透明视频的实现方法:
- 三个实现透明效果的方法(我还没有试过,不保证质量)
- Unity 对选中物体实现描边效果(方法3:结合方法1的外轮廓渲染、方法2的选择网格)
- CSS实现透明效果颜色的方法:RGBa
- 一种简单的方法在程序中实现透明效果(JAVA)(源代码)
- Activity透明/半透明效果的设置transparent(两种实现方法)
- unity 实现物体破碎效果的一些方法 - 细雨淅淅
- Activity透明/半透明效果的设置transparent(两种实现方法)
- 【Unity Shader】手游中高光效果的几种实现方法
- JS+CSS实现弹出全屏灰黑色透明遮罩效果的方法
- Unity 对选中物体实现描边效果(方法1:指定layer的外轮廓渲染)
- 在IE和VB中支持png图片透明效果的实现方法(vb源码打包)
- unity 实现物体破碎效果的一些方法
- 讲解如何在Unity的Inspector面板实现类似摄像机层次遮罩的多选效果
- Activity透明/半透明效果的设置transparent(两种实现方法)
- 在IE和VB中支持png图片透明效果的实现方法(vb源码打包)
- Unity 对选中物体实现描边效果(方法2:对物体网格顶点的外扩)