unityshader入门(三)什么是光照模型、(实现漫反射和环境光)

前言

本文所有内容来自
unity5shader着色器入门教程

什么是光照模型

光照模型是一个公式(算法),计算光照照射到某个点的显示效果。

标准光照模型:
进入摄像机的光分为这四个部分:
自发光
高光反射 specular =直射光*pow(cosθ,高光的参数) θ:是反射光方向和视野方向的夹角
高光参数一般是大于等于10的(就是反射光进入视野的时候这个高光反射的值比较大)
高光参数越大,高光越小

漫反射 diffuse=直射光颜色*max(0,cos(光和法线的夹角)) cosθ=光方向·法线方向
环境光

实现漫反射

逐顶点实现漫反射:因为顶点的数量是比像素的数量少的,所以不在顶点上的其他像素的颜色是通过插值得到的

只有定义了正确的LightMode才能得到一些Unity的内置光照变量。
Tags(“LightMode”=“ForwardBase”)
#include “Lighting.cginc”//这个里面包含了一些光照变量的定义
_WorldSpaceLightPos0 取得平行光的位置
_LightColor0取得平行光的颜色
UNITY_MATRIX_MVP 这个矩阵用来把一个坐标从模型空间转换到剪裁空间
在unity5.6以上版本中,shader中的UNITY_MATRIX_MVP将会被UnityObjectToClipPos替代
_World2Object 这个矩阵用来把一个方向从世界空间转换到模型空间 这是一个4x4的矩阵 而法线方向是3x3的 所以为了格式符合 需要把矩阵的第四行第四列略掉
mul(v.normal, (float3x3)_World2Object)
mul(_World2Object,v.normal)
上面一条反过来乘就是模型空间到世界空间mul(v.normal,_World2Object)

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/04DiffuseVertex"
{
    
    

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

		CGPROGRAM
		// Upgrade NOTE: excluded shader from DX11; has structs without semantics (struct v2f members temp)
#include "Lighting.cginc"
		#pragma vertex vert
		#pragma fragment frag

				//把参数定义成结构体以获取更多的输入
				struct a2v {
    
    //application to vertex
					float4 vertex:POSITION;
					float3 normal:NORMAL;
				};

				struct v2f {
    
    
					float4 position:SV_POSITION;
					fixed3 color : COLOR;
				};


				v2f  vert(a2v v) {
    
    //为顶点计算
					v2f f;
					f.position = UnityObjectToClipPos(v.vertex);
					fixed3 normalDir = normalize(mul(v.normal, (float3x3)unity_WorldToObject));//将顶点法线方向转换到世界空间
					fixed3 lightDir =normalize( _WorldSpaceLightPos0.xyz);//对于每个顶点来说,光的位置就是光的方向,因为光是平行光。normalize是取单位向量


					fixed3 diffuse = _LightColor0.rgb*max(0,dot(normalDir,lightDir));//取得第一个直射光的颜色(不包括透明度alpha) _LightColor0 这是在文件Lighting.cginc里面定义的
					f.color = diffuse;
					return f;
			}

				fixed4 frag(v2f f) : SV_Target {
    
    

					return fixed4(f.color,1);
			}

		ENDCG

		}

	}
		FallBack "Diffuse"
}


给物体添加漫反射颜色和环境光颜色控制

{
    
    
	Properties{
    
    
		_Diffuse("Diffuse Color",Color) = (1,1,1,1)
	}

			fixed4 _Diffuse;
//。。。


fixed3 diffuse = _LightColor0.rgb*max(0,dot(normalDir,lightDir))*_Diffuse.rgb;


环境光

UNITY_LIGHTMODEL_AMBIENT用来获取环境光

v2f  vert(a2v v) {
    
    //为顶点计算
					fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb;//环境光
					f.color = diffuse+ambient;
			}

环境光的来源
在这里插入图片描述

逐像素实现漫反射:

将计算颜色的内容放到frag函数里就行了

// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/04DiffuseVertex"
{
    
    
	Properties{
    
    
		_Diffuse("Diffuse Color",Color) = (0,1,1,1)
	}


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

		CGPROGRAM
		// Upgrade NOTE: excluded shader from DX11; has structs without semantics (struct v2f members temp)
#include "Lighting.cginc"
		#pragma vertex vert
		#pragma fragment frag
			fixed4 _Diffuse;

	//把参数定义成结构体以获取更多的输入
	struct a2v {
    
    //application to vertex
		float4 vertex:POSITION;
		float3 normal:NORMAL;
	};

	struct v2f {
    
    
		float4 position:SV_POSITION;
		fixed3 worldNormalDir : COLOR0;
	};


	v2f  vert(a2v v) {
    
    //为顶点计算
		v2f f;
		f.position = UnityObjectToClipPos(v.vertex);
		f.worldNormalDir = mul(v.normal, (float3x3)unity_WorldToObject);



		return f;
}

	fixed4 frag(v2f f) : SV_Target {
    
    
				
		fixed3 normalDir = normalize(f.worldNormalDir);//将顶点法线方向转换到世界空间
		fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说,光的位置就是光的方向,因为光是平行光。normalize是取单位向量

		fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//环境光
		fixed3 diffuse = _LightColor0.rgb*max(0,dot(normalDir,lightDir))*_Diffuse.rgb;//取得第一个直射光的颜色(不包括透明度alpha) _LightColor0 这是在文件Lighting.cginc里面定义的
		fixed3 tempColor = diffuse + ambient;

		return fixed4(tempColor,1);
}

ENDCG

}

	}
		FallBack "Diffuse"
}

半兰伯特光照模型

Diffuse=直射光颜色*(cosθ*0.5+0.5)
cos的值从-1到1。现在是直射光颜色乘以0到1的值。

内置方法reflect可以计算反射光的方向

猜你喜欢

转载自blog.csdn.net/weixin_42914662/article/details/116597012