从0开始的技美实战(八)

本篇主要用于记录自己的实战操作,以及一些碎碎念(观后感),如果有什么好想法或者本篇出现什么错误,请多指教~

本篇的内容参考视频:庄懂的技术美术入门课(美术向)
使用软件:Unity 2019 3.6f1 ,ShaderForge

本篇内容主要包括:拆解菲涅尔,Matcap,Cubemap,oldSchoolPro;


一.菲涅尔

在这里插入图片描述
1.菲涅尔现象:如果你站在湖边,低头看脚下的水,你会发现水是透明的,反射不是特别强烈;如果你看远处的湖面,你会发现水并不是透明的,但反射非常强烈。这就是“菲涅尔效应”。自然界中的都有菲涅尔效应,金属也是,只不过影响很小罢了(此为修正具体参考PBR的讲解,原文为在真实世界中,除了金属之外,其它物质均有不同程度的“菲涅尔效应”。

2.连连看拆解菲涅尔
用法线向量点乘视向量,再用1减去后,使用Power控制效果得到最后的菲涅尔;
在这里插入图片描述


二.Matcap

在这里插入图片描述
1.Matcap

1.Matcap被称为材质捕获,效果如上图所示,具体的了解可以参考这篇,我们一般使用Matcap可以做环境的镜面反射,商城界面,展示界面之类的;

2.Matcap连连看

在这里插入图片描述

如上图,比起上篇使用code节点自己编写通过TBN矩阵转换法线贴图中的法线信息,这里使用Transform节点对法线信息进行转换,之后对其取R和G通道,分别对应在屏幕空间下的从左到右,从上到下的位置关系,在Remap之后该关系如下:

法线朝向取值
R=1
R=0
G=1
G=0
指向屏幕前的自己R=0.5,G=0.5

R和G通道取值范围刚好是构成一个圆,所以Matcap一般就是图片里一个圆;

3.Matcap代码

Shader "Unlit/co9-matcap-VS"
{
    Properties
    {
        _NormalMap ("法线贴图",2D) = "bump" {}
		_Matcap("Matcap",2D)="white"{}
		_fresnelexp("菲涅尔次幂",range(0,5))=2
		_Envcontrol("环境光强度",range(0,1))=1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
		    Tags { "LightMode"="ForwardBase" }
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

			uniform sampler2D _NormalMap;
			uniform sampler2D _Matcap;
			uniform float _fresnelexp;
			uniform float _Envcontrol;

            struct appdata
            {
                float4 vertex : POSITION;
				float3 normal  :NORMAL;
				float4 tangent : TANGENT;
                float2 uv0 : TEXCOORD0;
                float2 uv1 : TEXCOORD1;
            };

            struct v2f
            {
                float2 uv0 : TEXCOORD0;
				float3 posWS  : TEXCOORD1;
                float4 pos : SV_POSITION;
				float3 nDirWS : TEXCOORD2;
				float3 tDirWS : TEXCOORD3;
				float3 bDirWS : TEXCOORD4;
            };


            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
				o.posWS = mul(unity_ObjectToWorld,v.vertex);
                o.uv0 = v.uv0;
				o.nDirWS=UnityObjectToWorldNormal(v.normal);
				o.tDirWS = normalize(mul(unity_ObjectToWorld,float4(v.tangent.xyz,0.0)));
				o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS)*v.tangent.w);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 nDirTS=UnpackNormal(tex2D(_NormalMap,i.uv0));
				float3x3 TBN=float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
				float3 nDirWS=normalize(mul(nDirTS,TBN));
				float3 nDirVS=mul(UNITY_MATRIX_V,float4(nDirWS,0.0));
				float3 vDirWS=normalize(_WorldSpaceCameraPos.xyz-i.posWS);

				float2 matcapUV=nDirVS.rg*0.5+0.5;
				float ndotv=dot(nDirWS,vDirWS);

				float3 matcap=tex2D(_Matcap,matcapUV);
				float fresnel=pow(1-ndotv,_fresnelexp);
				float3 envSpecLighting=matcap*fresnel*_Envcontrol;

                return float4(envSpecLighting,1.0);
            }
            ENDCG
        }
    }
}

三.CubeMap

在这里插入图片描述

1.早期存在六张图里,现在一般存储在一张图里,如图中的彩图那般处理后得到;

2.连连看,图里的Mipmap就是纹理里讲的那个,我们这里是利用Mipmap表现不同粗糙度的反射;

在这里插入图片描述

3.全景图处理:

  • 首先我们在PS里打开一张exr格式的全景图,选择作为Alpha通道打开;
    在这里插入图片描述
  • 然后我们把图像修改成符合项目标准的方形;

在这里插入图片描述

  • 由于原图还是HDR高动态光照渲染的图,我们将其转换为低动态的将原本不在0-1的部分映射到0-1;

在这里插入图片描述

  • 然后以tga格式导入到Unity中,Textureshape修改为cube,Mapping那里默认auto识别会出错要手动改为Latitude,convolution type默认None手动改为Specular,这里跟Mipmap挂钩,在None的情况下,会突显一个个格子,不如Specular好使,Fixup edge seams(修正接缝)勾选;

在这里插入图片描述

4.Cubemap连连看

在这里插入图片描述

5.cubeMap代码

Shader "Unlit/co9-cubemap-VS"
{
    Properties
    {
        _NormalMap ("法线贴图",2D) = "bump" {}
		_CubeMap   ("CubeMap",Cube)="_Skybox"{}
		_Mipmap    ("Mipmap",range(0,7))=0
		_fresnelexp("菲涅尔次幂",range(0,5))=0.2
		_Envcontrol("环境光强度",range(0,5))=1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
		    Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

			uniform sampler2D _NormalMap;
			uniform samplerCUBE _CubeMap;
			uniform float _Mipmap;
			uniform float _fresnelexp;
			uniform float _Envcontrol;

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				float3 normal:NORMAL;
				float4 tangent:TANGENT;
				
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
				float3 nDirWS:TEXCOORD1;
				float3 bDirWS:TEXCOORD2;
				float3 tDirWS:TEXCOORD3;
                float4 pos : SV_POSITION;
				float3 posWS:TEXCOORD4;
            };


            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
				o.posWS=mul(unity_ObjectToWorld,v.vertex);
                o.uv = v.uv;
				o.nDirWS = UnityObjectToWorldNormal(v.normal);
				o.tDirWS = normalize(mul(unity_ObjectToWorld,float4(v.tangent.xyz,0.0)));
				o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS)*v.tangent.w);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 vDirWS=normalize(_WorldSpaceCameraPos-i.posWS);
				float3 nDirTS=UnpackNormal(tex2D(_NormalMap,i.uv));
				float3x3 TBN =float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
				float3 nDirWS=normalize(mul(nDirTS,TBN));
				float3 vrDir=reflect(-vDirWS,nDirWS);

				float ndotv=dot(nDirWS,vDirWS);
				float fresnel=pow(1-ndotv,_fresnelexp);
				float3 cubemap=texCUBElod(_CubeMap,float4(vrDir,_Mipmap));

				float3 final=cubemap*fresnel*_Envcontrol;

                return float4(final,1.0);
            }
            ENDCG
        }
    }
}


四.OldSchoolPro

1.SF连连看
在这里插入图片描述

看着复杂其实就是将之前学过的东西都耦合在一起

2.加强版代码

分类管理可调参数,使用lerp对高光和Cubemap进行灵活柔和处理;

Shader "Unlit/co9-oldschoolpro+VS"
{
    Properties
    {
	[Header(Texture)]
        _MainTex       ("RGB:基础颜色,A:环境遮罩", 2D)     = "white"   {}//这里将AO贴图与颜色贴图整合到了一张图里
		_NormalTex     ("RGB:法线贴图",2D)                 = "bump"    {}
		_SpecTex       ("RGB:高光颜色,A:高光次幂",2D)      = "gray"    {}
		_EmitTex       ("RGB:自发光贴图",2d)                 = "black"   {}
		_Cubemap       ("RGB:环境贴图Cubemap",Cube)        = "_Skybox" {}
	[Header(Diffuse)]
	    _BaseColor     ("基础颜色",color)                  = (1.0,1.0,1.0,1.0)
		_EnvUpColor    ("环境天顶颜色",color)              = (1.0,1.0,1.0,1.0)
		_EnvMidColor   ("环境侧部颜色",color)              = (1.0,1.0,1.0,1.0)
	    _EnvDowColor   ("环境底部颜色",color)              = (1.0,1.0,1.0,1.0)
		_EnvDiffuse    ("环境漫反射强度",range(0,1))       =  0.2
    [Header(Specular)]
	    _SpecularPow   ("高光次幂",range(1,90))            =  25
		_EnvSpecInt    ("高光强度",range(0,5))             =  1
		_FresenlPow    ("菲涅尔次幂",range(0,10))          =  3
		_CubemapMip    ("环境球Mip",range(0,7))            =  0
    [Header(Emission)]
	    _Emitint       ("自发光强度",range(1,10))          =  5 
   
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
		    Tags {"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdbase

            #include "UnityCG.cginc"
			#include "Lighting.cginc"
			#include "AutoLight.cginc"

			uniform sampler2D _MainTex;
			uniform sampler2D _NormalTex;
			uniform sampler2D _SpecTex;
			uniform sampler2D _EmitTex;
			uniform samplerCUBE _Cubemap;

			uniform float3 _BaseColor;
			uniform float3 _EnvUpColor;
			uniform float3 _EnvMidColor;
			uniform float3 _EnvDowColor;
			uniform float3 _EnvDiffuse;

			uniform float _SpecularPow;
			uniform float _EnvSpecInt;
			uniform float _FresenlPow;
			uniform float _CubemapMip;
			uniform float _Emitint;


            struct appdata
            {
                float4 vertex : POSITION;
				float4 normal : NORMAL;
				float4 tangent:TANGENT;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv       : TEXCOORD0;
                float4 pos      : SV_POSITION;
				float3 posWS    : TEXCOORD1;
				float3 nDirWS   : TEXCOORD2;
				float3 bDirWS   : TEXCOORD3;
				float3 tDirWS   : TEXCOORD4;
				LIGHTING_COORDS(5,6)
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.uv     = v.uv;
                o.pos    = UnityObjectToClipPos(v.vertex);
				o.posWS  = mul(unity_ObjectToWorld,v.vertex);
				o.nDirWS = UnityObjectToWorldNormal(v.normal);
				o.tDirWS = normalize(mul(unity_ObjectToWorld,float4(v.tangent.xyz,1.0)));
				o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS));
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
			   float3   nDirTS      = UnpackNormal(tex2D(_NormalTex,i.uv));
               float3x3 TBN         = float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
			   float3   nDirWS      = normalize(mul(nDirTS,TBN));
			   float3   lDir        = _WorldSpaceLightPos0;
			   float3   vDir        = normalize(_WorldSpaceCameraPos-i.posWS.xyz);
			   float3   vrDir       = reflect(-vDir,nDirWS);
			   float3   lrDir       = reflect(-lDir,nDirWS);

			   float3   ndotl       = dot(nDirWS,lDir); //兰伯特
			   float3   ndotv       = dot(nDirWS,vDir); //菲涅尔
			   float3   vdotlr      = dot(vDir,lrDir);  //Phong

			   float4   var_MainTex = tex2D(_MainTex,i.uv);
			   float4   var_SpecTex = tex2D(_SpecTex,i.uv);
			   float3   var_EmitTex = tex2D(_EmitTex,i.uv);
			   float3   var_Cubemap = texCUBElod(_Cubemap,float4(vrDir,lerp(_CubemapMip,1.0,var_SpecTex.a)));//lerp用来表现越光滑反射越清晰

			   float    Lambert     =  max(ndotl,0);
			   float    spect       =  lerp(1,_SpecularPow,var_SpecTex.a);//用lerp做插值
			   float    Phong       =  pow(max(0,vdotlr),spect);
			   float    shadow      =  LIGHT_ATTENUATION(i);
               float3   dirtLight   =  (Lambert*_BaseColor*var_MainTex.rgb + Phong*var_SpecTex.rgb)*shadow*_LightColor0;

			   float    topmask     =  max(nDirWS.g,0.0);
			   float    dowmask     =  max(-nDirWS.g,0.0);
			   float    midmask     =  1.0-topmask-dowmask;
			   float3   col3        =  topmask*_EnvUpColor+midmask*_EnvMidColor+dowmask*_EnvDowColor;

			   float   fresnel      = pow(max(1-ndotv,0.0),_FresenlPow);
			   float   occluision   = var_MainTex.a;
			   float   Envlighting  = (_BaseColor*var_MainTex.rgb*col3*_EnvDiffuse+var_Cubemap*fresnel*_EnvSpecInt)*occluision;
			   float3  emission     = var_EmitTex*_Emitint;
			    
			   float3  final        = dirtLight+Envlighting+emission;

			   return float4(final,1.0);
            }
            ENDCG
        }
    }
}

效果图 (老师的包里没自发光贴图,PS里随手画的,确实不好看)

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值