Unity3D Shader(10)——Fragment Shader(漫反射、phong效果、blinnPhong效果、阴影、halfLambert、渐变纹理)

各种shader 小问题请咨询扣扣:2540,33230 


Fragment Shader的效果要好于vertex shader,前者基于面,然后逐像素处理对象,后者基于顶点来处理对象,缺点就是前者计算相对复杂,会多耗费一些资源。

首先对应着vertex shader(看之前的博客),来看一下Fragment的漫反射的效果。

Fragment Shader的主要计算在Frag方法里计算,Vert方法主要起传递数据的作用,而vertex shader主要在Vert方法里计算。

Shader "Custom/FragmentShader" {
	SubShader {
		PASS{
		tags{"LightMode"="ForwardBase"}		
		CGPROGRAM
		#pragma vertex vert  
        #pragma fragment frag
        #include "UnityCG.cginc"
        #include "Lighting.cginc"


        struct v2f{
        float4 pos:POSITION;
        float3 normal1:TEXCOORD0;
        float4 vertex1:TEXCOORD1;
        };  

        v2f vert(appdata_base v){
        v2f o;
        o.pos=UnityObjectToClipPos(v.vertex);
        o.normal1=v.normal;
        o.vertex1=v.vertex;   
        return o;
        }

        float4 frag(v2f IN):COLOR{

        float4 col= UNITY_LIGHTMODEL_AMBIENT;
        float3 N=UnityObjectToWorldNormal(IN.normal1);
        float3 L=normalize(WorldSpaceLightDir(IN.vertex1));
        float diffuseScale=saturate(dot(N,L));
        col+=_LightColor0*diffuseScale;
        return col;
        }
		ENDCG
		}
	}
	FallBack "Diffuse"

}

2、将上面代码稍微修改一下,即在frag方法里增加Phong的计算就可以得到Phong的效果,原理请看上篇博文。具体代码如下:

properties{
_SpecularColor("SpecularColor",color)=(1,1,1,1)
_Shininess("Shininess",range(1,8))=4

}
	SubShader {
		PASS{
		tags{"LightMode"="ForwardBase"}		
		CGPROGRAM
		#pragma vertex vert  
        #pragma fragment frag
        #include "UnityCG.cginc"
        #include "Lighting.cginc"

        float4 _SpecularColor;
        float _Shininess;


        struct v2f{
        float4 pos:POSITION;
        float3 normal1:TEXCOORD0;
        float4 vertex1:TEXCOORD1;
        };  

        v2f vert(appdata_base v){
        v2f o;
        o.pos=UnityObjectToClipPos(v.vertex);
        o.normal1=v.normal;
        o.vertex1=v.vertex;   
        return o;
        }

        float4 frag(v2f IN):COLOR{

        float4 col= UNITY_LIGHTMODEL_AMBIENT;
        float3 N=UnityObjectToWorldNormal(IN.normal1);
        float3 L=normalize(WorldSpaceLightDir(IN.vertex1));
        float diffuseScale=saturate(dot(N,L));
        col+=_LightColor0*diffuseScale;

        //Phong运算
        float3 V=normalize(WorldSpaceViewDir(IN.vertex1));
        float3 R=2*dot(N,L)*N-L;
        float specularScale=saturate(dot(R,V));
        col+=_SpecularColor*pow(specularScale,_Shininess);

        return col;
        }
		ENDCG
		}
	}
	FallBack "Diffuse"

}


3、同样的,在Phong效果的基础上,再修改一下,即可以得到BlinnPong的效果。

Shader "Custom/FragmentShader" {
properties{
_SpecularColor("SpecularColor",color)=(1,1,1,1)
_Shininess("Shininess",range(1,8))=4

}
	SubShader {
		PASS{
		tags{"LightMode"="ForwardBase"}		
		CGPROGRAM
		#pragma vertex vert  
        #pragma fragment frag
        #include "UnityCG.cginc"
        #include "Lighting.cginc"

        float4 _SpecularColor;
        float _Shininess;


        struct v2f{
        float4 pos:POSITION;
        float3 normal1:TEXCOORD0;
        float4 vertex1:TEXCOORD1;
        };  

        v2f vert(appdata_base v){
        v2f o;
        o.pos=UnityObjectToClipPos(v.vertex);
        o.normal1=v.normal;
        o.vertex1=v.vertex;   
        return o;
        }

        float4 frag(v2f IN):COLOR{

        float4 col= UNITY_LIGHTMODEL_AMBIENT;
        float3 N=UnityObjectToWorldNormal(IN.normal1);
        float3 L=normalize(WorldSpaceLightDir(IN.vertex1));
        float diffuseScale=saturate(dot(N,L));
        col+=_LightColor0*diffuseScale;

        //Phong运算
        //float3 V=normalize(WorldSpaceViewDir(IN.vertex1));
        //float3 R=2*dot(N,L)*N-L;
        //float specularScale=saturate(dot(R,V));
        //col+=_SpecularColor*pow(specularScale,_Shininess);

        //BlinnPhong运算
        float3 V=normalize(WorldSpaceViewDir(IN.vertex1));
        float3 H=normalize(V+L);
        float specularScale=saturate(dot(H,V));
        col+=_SpecularColor*pow(specularScale,_Shininess);


        return col;
        }
		ENDCG
		}
	}
	FallBack "Diffuse"

}


4、从上面的代码,可以看到,上面并没有阴影的描述,所以需要增加一个阴影,这个阴影用光照深度来描述(atten),将上面的代码再修改一下

Shader "Custom/FragmentShader" {
properties{
_SpecularColor("SpecularColor",color)=(1,1,1,1)
_Shininess("Shininess",range(1,8))=4

}
	SubShader {
		PASS{
		tags{"LightMode"="ForwardBase"}		
		CGPROGRAM
		#pragma vertex vert  
        #pragma fragment frag
        #pragma multi_compile_fwdbase
        #include "UnityCG.cginc"
        #include "Lighting.cginc"
        #include "AutoLight.cginc"

        float4 _SpecularColor;
        float _Shininess;


        struct v2f{
        float4 pos:POSITION;
        float3 normal1:TEXCOORD0;
        float4 vertex1:TEXCOORD1;
        LIGHTING_COORDS(2,3)
        };  

        v2f vert(appdata_base v){
        v2f o;
        o.pos=UnityObjectToClipPos(v.vertex);
        o.normal1=v.normal;
        o.vertex1=v.vertex;
        TRANSFER_VERTEX_TO_FRAGMENT(o)   
        return o;
        }

        float4 frag(v2f IN):COLOR{

        float4 col= UNITY_LIGHTMODEL_AMBIENT;
        float3 N=UnityObjectToWorldNormal(IN.normal1);
        float3 L=normalize(WorldSpaceLightDir(IN.vertex1));
        float diffuseScale=saturate(dot(N,L));
        col+=_LightColor0*diffuseScale;

        //Phong运算
        //float3 V=normalize(WorldSpaceViewDir(IN.vertex1));
        //float3 R=2*dot(N,L)*N-L;
        //float specularScale=saturate(dot(R,V));
        //col+=_SpecularColor*pow(specularScale,_Shininess);

        //BlinnPhong运算
        float3 V=normalize(WorldSpaceViewDir(IN.vertex1));
        float3 H=normalize(V+L);
        float specularScale=saturate(dot(H,V));
        col+=_SpecularColor*pow(specularScale,_Shininess);
        //增加阴影
        float atten=LIGHT_ATTENUATION(IN);
        col.rgb*=atten;
        return col;
        }
		ENDCG
		}
	}
	FallBack "Diffuse"

}
阴影效果如下:



从上面的效果可以看出,背面比较黑,如果想背面也显示不那么黑,就可以用Half Lambert光照模型

Shader "Custom/Shader" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)

	}
	SubShader {
	pass{
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		// Use shader model 3.0 target, to get nicer looking lighting
		#pragma target 3.0
		#pragma vertex vert
		#pragma fragment frag

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

		struct v2f {
			float4 pos:SV_POSITION;
			float3 V:Texcoord0;
			float3 N:Texcoord1; 
		};

		fixed4 _Color;

		v2f vert(appdata_base v){
		 v2f o;
		 o.pos=UnityObjectToClipPos(v.vertex);
		 o.N=v.normal;
		 o.V=WorldSpaceLightDir( v.vertex);
		 return o;
		}


		float frag(v2f IN):color {
		float4 col;
		float diff=dot(IN.N,IN.V)*0.5+0.5;
		col=_LightColor0*diff;
		return col; 			
		}
		ENDCG
	}
	}
	FallBack "Diffuse"
}


渐变纹理(摘自http://blog.csdn.net/u013354943/article/details/52788010)

Shader "LT/RampTexture"
{
    Properties
    {
        _Color("Color Tint",Color) = (1,1,1,1)
        _RampTex("Ramp Tex",2D) = "white" {}    //渐变纹理
        _Specular("Specular",Color) = (1,1,1,1)
        _Gloss("Gloss",Range(8.0,256)) = 20
    }
    SubShader
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }//定义该Pass在光照流水线中的角色光照模式注意要设置为Forward
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            fixed4 _Color;
            sampler2D _RampTex;
            fixed4 _Specular;
            float4 _RampTex_ST;
            float _Gloss;

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldNormal : TEXCOORD1;
                float3 worldPos : TEXCOORD2;
            };
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                o.uv = TRANSFORM_TEX(v.uv, _RampTex);   //内置的宏计算平铺和偏移位置
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 worldNormal =normalize(i.worldNormal);
                fixed3 worldLightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz ;
                
                //法线和方向和光照方向的点积做一次0.5倍的缩放和一个0.5大小的偏移来计算兰伯特部分halfLambert,得到结果在【0,1】之间
                fixed halfLambert = 0.5 *dot(worldNormal,worldLightDir) +0.5;
                //用halfLambert构建一个纹理坐标,并对这个纹理坐标对_RampTex进行采样。
                //由于_RampTex实际是一个一维纹理(纵轴方向上颜色不变),所以纹理坐标的UV方向我们都使用了halfLambert,
                fixed3 diffuseColor = tex2D(_RampTex, fixed2(halfLambert,halfLambert)).rgb * _Color.rgb;
                //漫反射颜色 = 渐变纹理采样得到的颜色 * 材质颜色
                fixed3 diffuse  = _LightColor0 * diffuseColor ;

                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                fixed3 halfDir = normalize(worldLightDir + viewDir);
            
                fixed3 specular = _LightColor0.rbg * _Specular.rgb *pow(max(0,dot                       (worldNormal,halfDir)),_Gloss);
                fixed4 col = fixed4( diffuse+  specular + ambient,1.0);
                return col;
            }
            ENDCG
        }
    }
    Fallback "Specular"
}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值