Unity Shader学习日志五:简单制作玉石材质


前言

本章简单制作玉石材质,感谢Kerry大佬的教学
在这里插入图片描述

玉石材质可以被光透过


一、添加漫反射

float diffuse_term=max(0.0,dot(normal_dir,light_dir));
float3 diffuse_color=diffuse_term*base_color*_LightColor0.xyz*_AddColor.xyz;

base_color为贴图颜色,由于这个模型没有贴图,则使用Color代替,_AddColor则为要设置的玉石材质颜色,我这里设置的为绿色
在这里插入图片描述

二、透射光

参考漫反射max(0.0,dot(view_dir,light_dir))我们可以获得被光照射到颜色,当我们将光的逆向max(0.0,dot(view_dir,-light_dir)),则可以获得背光
在这里插入图片描述

此时我们需要混合法线才可以看到模型纹理,_Distort为纹理强度

float3 back_dir=-(light_dir+normal_dir*_Distort);//混合可以看到纹理
float VdotB=max(0.0,dot(view_dir,back_dir));

接下来我们限制一小部分区域透光,而不是整个模型透光,_Power的作用和实现高光原理一样,就是让视角与光夹角很小时,透射光越强,_Scale为透射光强度

float backlight_term=max(0.0,pow(VdotB,_Power))*_Scale;
float3 backlight=backlight_term*_LightColor0.xyz;

在这里插入图片描述
接下来应用厚度图,可知模型不同部位厚度不一,厚度越高透光越弱
在这里插入图片描述
这是一张厚度图,越白数值越高表示越厚,透射光越弱,我们采取1-x的形式使得厚度数值越高时越容易透光

float thickness_color=1.0-tex2D(_ThicknessMap,uv).r;//只获取厚度图的灰度,代表模型厚度,越白越厚,反向操作
float3 backlight=backlight_term*_LightColor0.xyz*thickness_color;

在这里插入图片描述

三、添加光泽

玉石材质的光泽部分,我们采样环境贴图模拟

 //环境图旋转,_EnvRotate为旋转角度,这部分参考使用
 float theta=_EnvRotate*UNITY_PI/180.0;//转弧度
 float2x2 m_rot=float2x2(cos(theta),-sin(theta),
                             sin(theta),cos(theta));//构建旋转矩阵
 float2 dir_rota=mul(m_rot,reflect_dir.xz);//只旋转xz轴
 reflect_dir=float3(dir_rota.x,reflect_dir.y,dir_rota.y);

 //获取环境贴图
 float4 hdr_color=texCUBE(_CubeMap,reflect_dir);//采样环境贴图

//解码HDR,让多平台通用,_CubeMap_HDR为pass全局float4变量
 float3 env_color=DecodeHDR(hdr_color,_CubeMap_HDR);
return float4(env_color,1.0);

在这里插入图片描述
添加菲涅尔效应,让边缘更光滑,中心不那么光滑

//添加菲涅尔效果,让边缘更光滑,中心不那么光滑
float fresnel=1.0-max(0.0,dot(normal_dir,view_dir));//菲涅尔因子
float3 final_env=env_color*fresnel;

return float4(final_env,1.0);

在这里插入图片描述
形成最终效果

float3 final_color=diffuse_color+backlight+final_env;//混合背光,漫反射后的最终效果

在这里插入图片描述

完整代码

Shader "Unlit/Dragon1"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _DiffuseColor ("DiffuseColor", color) =(1,1,1,1)
        _AddColor ("AddColor", color) =(1,1,1,1)
        _Opacity("Opacity",float)=0

        _Distort("Distort",float)=0
        _Power("Power",float)=1.0
        _Scale("Scale",float)=1.0
        _ThicknessMap("ThicknessMap",2D)="white"{}
        
        _CubeMap("CubeMap",Cube)="white"{}
        _EnvRotate("EnvRotate",range(0,360))=0

        
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        //平行光
        Pass
        {

            Tags{"LightMode"="ForwardBase"}//光照标签
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            //光照标签
            #pragma multi_compile_fwdbase
            //光照头文件
            #include "AutoLight.cginc"

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                float3 normal:NORMAL;
                float4 tangent:TANGENT;//切线
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;     
                float3 normal_dir:TEXCOORD1;
                float4 pos : SV_POSITION;
                float3 pos_world:TEXCOORD2;
               

              

                
            };
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _DiffuseColor;
            float _Opacity;//天光色强度
            
            float4 _AddColor;//提高漫反射颜色
            float4 _LightColor0;//光源

            float _Distort;//衰减系数

            float _Power;//对比度
            float _Scale;//漫反射亮度
           
            sampler2D _ThicknessMap;

            samplerCUBE _CubeMap;
            float4 _CubeMap_HDR;
            float _EnvRotate;//环境贴图旋转值
         
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.pos_world=mul(unity_ObjectToWorld,v.vertex).xyz;//模型顶点坐标转世界空间坐标
                o.normal_dir=normalize(mul(float4(v.normal,0.0),unity_WorldToObject).xyz);//世界空间下的法线方向


                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                
                

                //线、方向与空间矩阵定义
                float3 normal_dir=normalize(i.normal_dir);
                float3 view_dir=normalize(_WorldSpaceCameraPos.xyz-i.pos_world);//求视角方向
                float3 light_dir=normalize(_WorldSpaceLightPos0.xyz);//光的方向         
                float3 reflect_dir=reflect(-view_dir,normal_dir);//获取反射光
                
                float2 uv=i.uv;
            
                
               

                //贴图
                float3 base_color = _DiffuseColor.xyz;
                float thickness_color=1.0-tex2D(_ThicknessMap,uv).r;//只获取厚度图的灰度,代表模型厚度,越白越厚,反向操作
                float4 hdr_color=texCUBE(_CubeMap,reflect_dir);//获取环境贴图

                
                //漫反射
                float diffuse_term=max(0.0,dot(normal_dir,light_dir));
                float3 diffuse_color=diffuse_term*base_color*_LightColor0.xyz;
               
               
                //天光计算,可加可不加
                float sky_light=(dot(normal_dir,float3(0,1,0))+1.0)*0.5;//把-1-1区间变成0-1
                float3 sky_lightcolor=sky_light*diffuse_color;

                diffuse_color=diffuse_color+sky_lightcolor*_Opacity+_AddColor.xyz;
                

                //透射光
                float3 back_dir=-(light_dir+normal_dir*_Distort);//混合可以看到纹理
                float VdotB=max(0.0,dot(view_dir,back_dir));//获取背光
                float backlight_term=max(0.0,pow(VdotB,_Power))*_Scale;//限制透光范围
                float3 backlight=backlight_term*_LightColor0.xyz*thickness_color;
               

                //光泽反射

                //环境图旋转
                float theta=_EnvRotate*UNITY_PI/180.0;//转弧度
                float2x2 m_rot=float2x2(cos(theta),-sin(theta),
                                            sin(theta),cos(theta));//构建旋转矩阵
                float2 dir_rota=mul(m_rot,reflect_dir.xz);//只旋转xz轴
                reflect_dir=float3(dir_rota.x,reflect_dir.y,dir_rota.y);

                //获取环境贴图
                hdr_color=texCUBE(_CubeMap,reflect_dir);//采样环境贴图

                float3 env_color=DecodeHDR(hdr_color,_CubeMap_HDR);

                //添加菲涅尔效果,让边缘更光滑,中心不那么光滑
                float fresnel=1.0-max(0.0,dot(normal_dir,view_dir));//菲涅尔因子
                float3 final_env=env_color*fresnel;

                float3 final_color=diffuse_color+backlight+final_env;//混合背光,漫反射后的最终效果

                return float4(final_color,1.0);
            }
            ENDCG
        }

       
        //点光
        Pass
        {

            Tags{"LightMode"="ForwardAdd"}//光照标签
            Blend One One
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            //光照标签
            #pragma multi_compile_fwdadd
            //光照头文件
            #include "AutoLight.cginc"

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
                float3 normal:NORMAL;
               
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;     
                float3 normal_dir:TEXCOORD1;
                float4 pos : SV_POSITION;
                float3 pos_world:TEXCOORD2;
               
               

              

                
            };
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _DiffuseColor;
            float _Opacity;//天光色强度
            
            float4 _AddColor;//提高漫反射颜色
            float4 _LightColor0;//光源

            float _Distort;//衰减系数

            float _Power;//对比度
            float _Scale;//漫反射亮度
           
            sampler2D _ThicknessMap;

            samplerCUBE _CubeMap;
            float4 _CubeMap_HDR;
            float _EnvRotate;//环境贴图旋转值
         
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.pos_world=mul(unity_ObjectToWorld,v.vertex).xyz;//模型顶点坐标转世界空间坐标
                o.normal_dir=normalize(mul(float4(v.normal,0.0),unity_WorldToObject).xyz);//世界空间下的法线方向
               


                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                
                
                

                //线、方向与空间矩阵定义
                float3 normal_dir=normalize(i.normal_dir);
                float3 view_dir=normalize(_WorldSpaceCameraPos.xyz-i.pos_world);//求视角方向
                float3 light_dir=normalize(_WorldSpaceLightPos0.xyz);//光的方向
                float3 light_dir_other=normalize(_WorldSpaceLightPos0.xyz-i.pos_world);
                float3 reflect_dir=reflect(-view_dir,normal_dir);//获取反射光
                
                float2 uv=i.uv;
            
                light_dir=lerp(light_dir,light_dir_other,_WorldSpaceLightPos0);//区分点光和平行光
               

                //贴图
                float3 base_color = _DiffuseColor.xyz;
                float thickness_color=1.0-tex2D(_ThicknessMap,uv).r;//只获取厚度图的灰度,代表模型厚度,越白越厚,反向操作
                float4 hdr_color=texCUBE(_CubeMap,reflect_dir);//获取环境贴图

                
               

                //透射光
                float3 back_dir=-(light_dir+normal_dir*_Distort);//混合发现可以看到纹理
                float VdotB=max(0.0,dot(view_dir,back_dir));//获取背光
                float backlight_term=max(0.0,pow(VdotB,_Power))*_Scale;//与高光原理一样,限制范围
                float3 backlight=backlight_term*_LightColor0.xyz*thickness_color;

               

                float3 final_color=backlight;

                return float4(final_color,1.0);
            }
            ENDCG
        }
    }
    Fallback "Diffuse"
}

参考文献

什么是菲涅尔效应( Fresnel)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值