您当前的位置: 首页 > 

幻世界

暂无认证

  • 5浏览

    0关注

    237博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Shader理论《六》高光反射光照模型

幻世界 发布时间:2020-06-28 16:47:07 ,浏览量:5

 欢迎加入Unity业内qq交流群:956187480

qq扫描二维码加群

 基本光照模型中高光反射部分的计算模型:C_{specular} = (C_{light}\cdot M_{specular})max(0,\hat{v}\cdot \hat{r})^{M_{gloss}}

计算高光反射我们需要知道四个参数:入射光线的颜色跟强度,材质的高光反射系数,视角方向v以及反射方向r。

其中反射方向r可以由表面法线n和光源方向l计算:\hat{r}=\hat{l}-2(\hat{n}\cdot\hat{l})\hat{n},此公式我们可以用函数reflect(i,n),i入射方向跟n法线方向

一.逐顶点高光反射,高光部分明显不平滑,因为高光反射部分的计算是非线性的,而顶点着色器计算光照再进行插值的过程是线性的,破坏了原计算的非线性关系就出现了视觉问题。
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'

Shader "a幻世界/SpecularVertex"
{
    Properties
	{ 
	  _Diffuse ("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
	  _Specular ("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
	  _Gloss ("Gloss", Range(8, 256)) = 20 //控制高光范围
	}
		SubShader
	  {
			Pass{
			Tags { "RenderType" = "ForwardBase" }
			CGPROGRAM 
            #pragma vertex vert
			#pragma fragment frag

			#include "Lighting.cginc"
		    fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

		    struct a2v {
			  float4 vertex : POSITION;
			  float3 normal : NORMAL;
            };
	  struct v2f {
		  float4 pos : SV_POSITION;
		  float3 color : COLOR;
	  };
	  v2f vert(a2v v) {
		  v2f o;
		  o.pos = UnityObjectToClipPos(v.vertex);//模型空间顶点转换到裁剪空间
		  fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//获取环境光
		  fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));//把模型空间的法线转换到世界坐标
		  fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);//获取世界空间的光方向
		  fixed3 diffuse = _LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal, worldLightDir));//计算漫反射
		  fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));//计算反射方向
		  fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz-UnityObjectToClipPos(v.vertex));//相机的世界坐标-顶点转换到世界空间=世界空间下的视角方向
		  
		  fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir,viewDir)), _Gloss);//代入公式计算高光
		  o.color = ambient + diffuse + specular;
		  return o;
	  }
	  fixed4 frag(v2f i):SV_Target {
		  return fixed4(i.color,1);
	  }
		  ENDCG
		}
	  }
    FallBack "Specular"
}
二.逐像素高光反射,按照逐像素处理我们就能得到更加平滑的高光效果
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "a幻世界/SpecularPixel"
{
	Properties
	{
	  _Diffuse("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
	  _Specular("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
	  _Gloss("Gloss", Range(8, 256)) = 20 //控制高光范围
	}
		SubShader
	{
		  Pass{
		  Tags { "RenderType" = "ForwardBase" }
		  CGPROGRAM
		  #pragma vertex vert
		  #pragma fragment frag

		  #include "Lighting.cginc"
		  fixed4 _Diffuse;
		  fixed4 _Specular;
		  float _Gloss;

		  struct a2v {
			float4 vertex : POSITION;
			float3 normal : NORMAL;
		  };
	struct v2f {
		float4 pos : SV_POSITION;
		float3 worldNormal : TEXCOORD0;
		float3 worldPos: TEXCOORD1;

	};
	v2f vert(a2v v) {
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);//模型空间顶点转换到裁剪空间
		o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
		o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		return o;
	}
	fixed4 frag(v2f i) :SV_Target {
		fixed3 ambienm = UNITY_LIGHTMODEL_AMBIENT.xyz;
	    fixed3 worldNormal = normalize(i.worldNormal);
		fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
		fixed3 diffuse = _LightColor0.rbg*_Diffuse.rgb*saturate(dot( worldLightDir, worldNormal ) );
		fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));
		fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
		fixed3 specular = _LightColor0.rgb*_Specular.rbg*pow(saturate(dot(reflectDir, viewDir ) ),_Gloss);
		return fixed4(ambienm+diffuse+specular,1);
	}
		ENDCG

	  }
	}
		FallBack "Specular"
}
三.Blinn-Phong光照模型,高光反射部分看起来更大更亮一些。而具体在实际渲染中选择哪一种我们要视情况而定
Shader "a幻世界/SpecularBlinnPhong"
{
	Properties
	{
	  _Diffuse("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
	  _Specular("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
	  _Gloss("Gloss", Range(8, 256)) = 20 //控制高光范围
	}
		SubShader
	{
		  Pass{
		  Tags { "RenderType" = "ForwardBase" }
		  CGPROGRAM
		  #pragma vertex vert
		  #pragma fragment frag

		  #include "Lighting.cginc"
		  fixed4 _Diffuse;
		  fixed4 _Specular;
		  float _Gloss;

		  struct a2v {
			float4 vertex : POSITION;
			float3 normal : NORMAL;
		  };
	struct v2f {
		float4 pos : SV_POSITION;
		float3 worldNormal : TEXCOORD0;
		float3 worldPos: TEXCOORD1;

	};
	v2f vert(a2v v) {
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);//模型空间顶点转换到裁剪空间
		o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
		o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		return o;
	}
	fixed4 frag(v2f i) :SV_Target {
		fixed3 ambienm = UNITY_LIGHTMODEL_AMBIENT.xyz;
		fixed3 worldNormal = normalize(i.worldNormal);
		fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
		fixed3 diffuse = _LightColor0.rbg*_Diffuse.rgb*saturate(dot(worldLightDir, worldNormal));
		fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));
		fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
		fixed3 halfDir = normalize(worldLightDir+viewDir);
		fixed3 specular = _LightColor0.rgb*_Specular.rbg*pow(max(0,dot(worldNormal, halfDir)),_Gloss);
		return fixed4(ambienm + diffuse + specular,1);
	}
		ENDCG
	  }
	}
		FallBack "Specular"
}

四.使用Unity内置函数来写shader以上面的模型为例

Shader "a幻世界/SpecularBlinnPhongUseBuildInunction"
{
	Properties
	{
	  _Diffuse("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
	  _Specular("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
	  _Gloss("Gloss", Range(8, 256)) = 20 //控制高光范围
	}
    SubShader
	{
		Pass{
		Tags { "RenderType" = "ForwardBase" }
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag

		#include "Lighting.cginc"
		fixed4 _Diffuse;
		fixed4 _Specular;
		float _Gloss;

		struct a2v {
			float4 vertex : POSITION;
			float3 normal : NORMAL;
		};

		struct v2f {
		float4 pos : SV_POSITION;
		float3 worldNormal : TEXCOORD0;
		float3 worldPos: TEXCOORD1;
		};
		v2f vert(a2v v) {
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);//模型空间顶点转换到裁剪空间
		o.worldNormal = UnityObjectToWorldNormal(v.normal);
		o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		return o;
	}
	fixed4 frag(v2f i) :SV_Target {
		fixed3 ambienm = UNITY_LIGHTMODEL_AMBIENT.xyz;
		fixed3 worldNormal = normalize(i.worldNormal);
		fixed3 worldLightDir = normalize( UnityWorldSpaceLightDir(i.worldPos));
		fixed3 diffuse = _LightColor0.rbg*_Diffuse.rgb*saturate(dot(worldLightDir, worldNormal));
		fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));
		fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
		fixed3 halfDir = normalize(worldLightDir + viewDir);
		fixed3 specular = _LightColor0.rgb*_Specular.rbg*pow(max(0,dot(worldNormal, halfDir)),_Gloss);
		return fixed4(ambienm + diffuse + specular,1);
	}
		ENDCG

	  }
	}
    FallBack "Diffuse"
}

 欢迎加入Unity业内qq交流群:956187480

qq扫描二维码加群

关注
打赏
1660704426
查看更多评论
立即登录/注册

微信扫码登录

0.0441s