庄懂21课 塞博小人

https://space.bilibili.com/6373917?spm_id_from=333.788.b_765f7570696e666f.1https://space.bilibili.com/6373917?spm_id_from=333.788.b_765f7570696e666f.1

 前期准备

模型准备 

为了得到网格效果,专门渲染一张纯黑白的网格图,然后右边的图则是在Alpha通道里用于UV分块

 在SD中准备UV1:3D位置信息图

在SD中中制作UV2

R:网格线;

 G按模型灰度随机Bias透明度;

 B:坡度值(从边缘到中间坡度);

 A纯色(无信息)

编写Shading

 顶点动画的方法

前面都是基础操作遵循PPT即可,下面着重讲一下顶点动画的方法

追加小人顶点动画方法

//动画方法 noise:偏移噪声;mask:基座遮罩;normal:模型法线;vertex:模型顶点位置(inout) 返回effct相关遮罩
float4 CyberpunkAnim(float noise,float mask, float3 normal,inout float3 vertex)

 锯齿波mask

float baseMask = abs(frac(vertex.y*_EffParams.x-_Time.x*_EffParams.y)-0.5)*2.0;
               baseMask       = min(1.0,baseMask*2.0);
  1.  因为所需效果是从下到上所以取Y轴(vertex.y)
  2. 再用函数frac取小数部分,此时范围是(-1,1)
  3.   -0.5,此时范围是(-0.5,0.5)
  4.  加绝对值(0,0.5)
  5. *2 (0,1)
  6.  把Y轴(vertex.y)*_Time.x(时间)*_EffParams.y(波速度)*_EffParams.x(波密度)
  7. 把刚刚得到的结果*2(0,2)再把结果和1比较取较小的(使黑色时间比白色时间少,不透明时间更多,透明时间更少)

 

Noise偏移锯齿波

baseMask      += (noise-0.5)*_EffParams.z;

因为noise从纹理里采样所以值域是(0,1),做相加偏移只会加不会减,把值域-0.5(-0.5,0.5)有加有减这时候偏移才会合理错开,再*_EffParams.z(混乱度) 

smoothstep重映射波形平滑

float4 effectMask = float4(0,0,0,0)
effectMask.x   = smoothstep(0,0.9,baseMask);
effectMask.y   = smoothstep(0.2,0.7,baseMask);
effectMask.z   = smoothstep(0.4,0.5,baseMask);

 把RGB通道存在范围不同的三个通道里

 将顶点色遮罩存入EffectMask

effectMask.w   = mask;

把基座遮罩存到w分量 

计算顶点动画

 vertex.xz     += normal.xz*(1.0-effectMask.y)*_EffParams.w*mask;

只在xz轴偏移也就是平着散出去,如果是三维太乱了;

给每个顶点一个增量;我们需要的效果是让透明的地方膨胀带动着不透明的地方(黑色透明,白色不透明),也就是让半透的地方膨胀,也就是刚刚计算的EffectMask的反向,经测试y也就是棕色区域效果最好;

乘以_EffParams.w(消散强度)和基座的mask(顶点色)

顶点动画部分完整代码,老师PPT

像素Shader

采样EffMap02

float3 _Effmap01_var  = tex2D(_Effmap01,i.uv1).xyz;
float   meshMask      = _Effmap01_var.x;
float   faceRandomMask= _Effmap01_var.y;
float   facesSlopeMask= _Effmap01_var.z;

把图的各个通道信息给缓存起来 

获取EffectMask

float  smallMask     = i.effectMask.x;
float  midMask       = i.effectMask.y;
float  bigMask       = i.effectMask.z;
float  baseMask      = i.effectMask.w;
X:波形遮罩·小; Y:波形遮罩·中;  Z:波形遮罩·大;  W:基座遮罩;

 把顶点effect数据缓存

计算Opacity

float midOpacity     =saturate(floor(min(faceRandomMask,0.99999)+midMask));
float bigOpacity     =saturate(floor(min(facesSlopeMask,0.99999)+bigMask));
float Opacity        =lerp(1.0,min(bigOpacity,midOpacity),baseMask);

midOpacity 

方格随机灰度图(G通道),用min把值域从(0,1)限制到(0,0.99999);

加上Noise偏移锯齿波(midMask)把两个相加值域是(0,1.99999);

再使用函数floor二分处理,如果大于1就白色不透明,小于1就纯透明,没有半透明。

给一个值保护(0,1)之间

随机性+随机性结果,如左图

bigOpacity 

面坡度值(B通道),在单独一个面上有坡度变化,从面边缘慢慢消散到面中心。

 方法和上面一样不再赘述

Opacity(把两种混合)

midOpacity ,bigOpacity 混合取最小;

lerp基座mask,使基座永远是实的

叠加自发光

float meshEmitInt    =(bigMask-smallMask)*meshMask;
meshEmitInt         *=meshEmitInt;
emit                +=_Effcol*meshEmitInt*baseMask;

希望在半透明的地方产生自发光,用大范围减小范围,乘以网格线(meshMask);但是范围有点大,自然而然就想了Power但是太费了,我们就自己乘自己相当于Power 2得到了我们想要的效果;再把自发光强度*自发光颜色再*基座

返回结果

float3  final       = finalRGb+envLighting+emit;

最终效果以及代码

 

Shader "Unlit/cyber" {
    Properties {
    [Header(Texture)]
    _MainTex("基础贴图",2d)="white"{}
    _NormalTex("法线贴图",2d)="bump"{}
    _OcclusionTex("AO贴图",2d)="white"{}
    _EmitTex("自发光贴图",2d)="black"{}
    _CubeMap("环境贴图",cube)="skybox"{}
    _SpecTex("高光贴图",2d)="gery"{}
    [Header(Diffuse)]
    _MainCol    ("基础颜色",color)         =(0,0,0,0)
    _EnvUpCol   ("环境天顶颜色",color)     =(1,1,1,1)
    _EnvDownCol ("环境地表颜色",color)     =(0.5,0.5,0.5,1.0)
    _EnvSideCol ("环境水平颜色",color)     =(0,0,0,0)
    _EnvColInt  ("环境漫反射强度",Range(0,1))=0.5
    [Header(Specular)]
    _SpecPow ("高光次幂",Range(1,90)) =30
    _FransnalPow("菲涅尔次幂",Range(1,10))=3
    _EnvSpecInt("环境镜面反射强度",Range(0,10))=2
    _CubemapMip("环境球Mip",range(0,7))=1
    _EmitInt("自发光强度",Range(1,10))=1
    _threshold("抖动值",Range(0,1.01))=0.5
    [Header(Effect)]
    _Effmap01("特效纹理1",2D)="gray"{}
    _Effmap02("特效纹理2",2D)="gray"{}
[HDR]_Effcol("光效颜色",color)=(0,0,0,0)
    _EffParams("X:波密度 Y:波速度 Z:混乱度 W:消散强度",vector)=(0.03,3.0,0.3,2.5)
    }
    SubShader {
        Tags {
            "RenderType"="transparent" "Queue"="transparent"
        }
        LOD 100
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            Blend One OneMinusSrcAlpha
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            //包含文件
            #include "Lighting.cginc"
			#include "AutoLight.cginc"
            #include "../CG include/My cginc.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma target 3.0
            //Texture
            uniform sampler2D _MainTex;
            uniform sampler2D _NormalTex;
            uniform sampler2D _OcclusionTex;
            uniform sampler2D _EmitTex;
            uniform samplerCUBE _CubeMap;
            uniform samplerCUBE _SpecTex;
            //Diffuse
			uniform float3 _EnvDownCol;
			uniform float3 _EnvUpCol;
			uniform float3 _EnvSideCol;
            uniform float3 _MainCol;
            uniform float _EnvColInt;
            //Specular
            uniform float _SpecPow;
            uniform float _FransnalPow;
            uniform float _EnvSpecInt;
            uniform float _CubemapMip;
            uniform float _EmitInt;
            float _threshold;
            //Effect
            uniform sampler2D _Effmap01;
            uniform sampler2D _Effmap02;
            float3 _Effcol;
            float4 _EffParams;


            //输入结构
            struct VertexInput {
            float4 vertex : POSITION;
            float2 uv0    :TEXCOORD0;
            float2 uv1    :TEXCOORD1;
            float4 normal :NORMAL;
            float4 tangent:TANGENT;
            float4 color  :COLOR;
            };
            //输出结构
            struct VertexOutput {
            float4 pos:SV_POSITION;
            float2 uv0 :TEXCOORD0;
            float4 posWS:TEXCOORD1;
            float3 tDirWS:TEXCOORD2;
            float3 bDirWS:TEXCOORD3;
            float3 ndirWS:TEXCOORD4;
            float2 uv1:TEXCOORD5;
            float4 effectMask :TEXCOORD6;
            LIGHTING_COORDS(7,8)
            };

            //动画方法 noise:偏移噪声;mask:基座遮罩;normal:模型法线;vertex:模型顶点位置(inout) 返回effct相关遮罩
			float4 CyberpunkAnim(float noise,float mask, float3 normal,inout float3 vertex){
               //锯齿波mask
               float baseMask = abs(frac(vertex.y*_EffParams.x-_Time.x*_EffParams.y)-0.5)*2.0;
               baseMask       = min(1.0,baseMask*2.0);
               //Noise偏移锯齿波
			   baseMask      += (noise-0.5)*_EffParams.z;
               //smoothstep重映射波形平滑
               float4 effectMask = float4(0,0,0,0);
			   effectMask.x   = smoothstep(0,0.9,baseMask);
			   effectMask.y   = smoothstep(0.2,0.7,baseMask);
			   effectMask.z   = smoothstep(0.4,0.5,baseMask);
               //将顶点色遮罩存入EffectMask
			   effectMask.w   = mask;
               //计算顶点动画
			   vertex.xz     += normal.xz*(1.0-effectMask.y)*_EffParams.w*mask;
			   return effectMask; 
			}

            //输入结构>>>顶点Shader>>>输出结构
            VertexOutput vert (VertexInput v) {
                //采样纹理。tex2Dlod顶点着色器中采样纹理,也可采样Mipmap
                float noise =tex2Dlod(_Effmap02,float4(v.uv1,0.0,0.0)).r;
                //输出结构
                VertexOutput o = (VertexOutput)0;
                //计算顶点动画 同时获取EffectMask
                o.effectMask=CyberpunkAnim(noise,v.color.r,v.normal.xyz,v.vertex.xyz);
                o.pos=UnityObjectToClipPos(v.vertex);
                o.uv0=v.uv0;
                o.uv1=v.uv1;
                o.posWS=mul(unity_ObjectToWorld,v.vertex);
                o.ndirWS = UnityObjectToWorldNormal(v.normal);
                o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 1.0)).xyz);
                o.bDirWS = normalize(cross(o.ndirWS, o.tDirWS));
                TRANSFER_VERTEX_TO_FRAGMENT(o)//投影
                return o;
            }

            //输出结构>>>像素
            float4 frag(VertexOutput i) : COLOR {
            //向量准备
            float3 nDirTS =UnpackNormal(tex2D(_NormalTex,i.uv0)).rgb;
            float3x3 TBN  =float3x3(i.tDirWS,i.bDirWS,i.ndirWS);
            float3 ndirWS = normalize(mul(nDirTS, TBN));
            float3 lDirWS =_WorldSpaceLightPos0.xyz;
            float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);
            float3 vrDirWS = reflect(vDirWS,ndirWS);
           //中间量准备
           float vrdir=dot(vrDirWS,-lDirWS);
           float ndotv = dot(ndirWS,vDirWS);
           //纹理采样
           float4 var_MainTex=tex2D(_MainTex,i.uv0);
           //float4 var_SpecTex=tex2D(_SpecTex,i.uv0);
           float3 var_CubeMap= texCUBElod(_CubeMap,float4(vrDirWS,_CubemapMip));
           float3 var_OcclusionTex=tex2D(_OcclusionTex,i.uv0);
           float3 var_EmitTex=tex2D(_EmitTex,i.uv0);
           //光照模型
               //光源漫反射
            float3 basecol =var_MainTex*_MainCol;
            float lambert=max(0.0,dot(ndirWS,lDirWS));
               //光源镜面反射
            //float var_specPow=lerp(1,_SpecPow,var_SpecTex);
            float phone =pow(max(0,vrdir),_SpecPow);
              //光源混合
            float shadow = LIGHT_ATTENUATION(i);
            float3 dirLighting =(basecol*lambert)*_LightColor0*shadow;
              //环境漫反射
            float3 envCol = TriColAmbient(ndirWS,_EnvUpCol,_EnvDownCol,_EnvSideCol);
            float3 EnvDiff =_EnvColInt*envCol*basecol;
              //环境镜面反射
            float fresnel =pow(max(0,1-ndotv),_FransnalPow);
            float3 EnvSpec=var_CubeMap*fresnel*_EnvSpecInt;
              //环境反射混合
            float3 envLighting=(EnvSpec+EnvDiff)*var_OcclusionTex;
            //自发光
            float3 emit=_EmitInt*var_EmitTex;
            //输出
            float3 finalRGb=envLighting+dirLighting+emit;

            //特效部分
            //采样EffMap02
            float3 _Effmap01_var  = tex2D(_Effmap01,i.uv1).xyz;
			float   meshMask      = _Effmap01_var.x;
			float   faceRandomMask= _Effmap01_var.y;
			float   facesSlopeMask= _Effmap01_var.z;
            //获取EffectMask
			float  smallMask     = i.effectMask.x;
			float  midMask       = i.effectMask.y;
			float  bigMask       = i.effectMask.z;
			float  baseMask      = i.effectMask.w;
            //计算Opacity
			float midOpacity     =saturate(floor(min(faceRandomMask,0.99999)+midMask));
			float bigOpacity     =saturate(floor(min(facesSlopeMask,0.99999)+bigMask));
			float Opacity        =lerp(1.0,min(bigOpacity,midOpacity),baseMask);
            //叠加自发光
			float meshEmitInt   =saturate(bigMask-smallMask)*meshMask;
			meshEmitInt         =meshEmitInt*meshEmitInt;
			emit                =emit+_Effcol*meshEmitInt*baseMask;
            //返回结果
			float3  final       = finalRGb+envLighting+emit;
			return float4(final*Opacity,Opacity);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值