Unity Shader着色器学习(一)

发布时间:2023-01-20 10:00

Shader介绍

一个模型渲染所需的组成

1. Mesh Filter
存储一个Mesh(网格,模型的网格,就是模型由哪些三角面组成,组成一个什么样子的模型,三角面的一些顶点信息)
2. Mesh Renderer
根据Mesh的顶点信息,渲染一个模型的外观,就是样子,按照Mesh给它皮肤,给它颜色,通过Material(材质)控制模型渲染的样子
3. Material
渲染的样子,包括贴图和Shader,贴图可以没有,可以是一个单纯的颜色
4. Shader

相关资料推荐

书籍
unity shader 入门精要(乐乐程序猿)
unity 3d shaderlab开发实战详解(第二版)
unity 5.x shaders and effects cookbook(中文版 unity着色器和屏幕特效开发秘籍)

CG语言教程官网
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_frontmatter.html

一些网站
www.shadertoy.com
http://blog.csdn.net/poem_qianmo?viewmode=contents

数学函数在线演示
http://zh.numberempire.com/graphingcalculator.php

什么是光照模型

光照模型就是一个公式,使用这个公式来计算在某个点的光照效果

标准光照模型
在标准光照模型里面,我们把进入摄像机的光分为下面四个部分
1. 自发光(emissive)
这个部分用于描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。需要注意的是,如果没有使用全局光照(global illumination)技术,这些自发光的表面并不会真的照亮周围的物体,而是它本身看起来更亮了而已。
2. 高光反射(specular)
这个部分用于描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。(高光是指光源照射到物体反射到人的眼镜里时,物体上最亮的那个点就是高光)
3. 漫反射(diffuse)
这个部分用于描述当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。(漫反射是投射在粗糙表面上的光向各个方向反射的现象)
4. 环境光(ambient)
它用于描述其他所有的间接光照

逐顶点漫反射计算

漫反射光照模型

Diffuse = 直射光颜色 * max(0, cosθ)
注:θ为光和法线的夹角

cosθ怎么算
当矢量a与b的模都为1的时候,a与b的点乘结果即为cosθ,所以如果我们可以通过光的单位矢量与法线的单位矢量求得cosθ

定义LightMode
只有定义了正确的LightMode才能得到一些Unity的内置光照变量

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

包含Unity内置文件
包含unity的内置的Lighting.cginc文件,才可以使用unity内置的变量

shader	#include "Lighting.cginc"


逐顶点光照(加入环境光的影响)

Shader "Shader Learning Siki/Lighting/Diffuse PerVertex"
{
	Properties
	{
		_Diffuse("Diffuse Color", Color) = (1, 1, 1, 1)
	}
	SubShader
	{
		Pass
		{
			Tags{ "LightMode" = "ForwardBase"}
			
			CGPROGRAM
			
			//用于取得第一个直射光的颜色 _LightColor0
			//用于取得第一个直射光的位置 _WorldSpaceLightPos0
			#include "Lighting.cginc" 
			#pragma vertex vert
			#pragma fragment frag
			
			fixed4 _Diffuse;
			
			struct a2v
			{
				float4 vertex : POSITION;  //告诉Unity把模型空间下的顶点坐标填充给vertex
				float3 normal : NORMAL;
			};
			
			struct v2f
			{
				float4 position : SV_POSITION;
				fixed3 color : COLOR;
			};
			
			v2f vert(a2v v)
			{
				v2f f;
				f.position = mul(UNITY_MATRIX_MVP, v.vertex);
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;  //获取环境光
				
				fixed3 normalDir = normalize( mul(v.normal, (float3x3)_World2Object));
				
				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  //对于每个顶点来说 光源的位置就是光源的方向,因为光是平行光
				fixed3 diffuse = _LightColor0.rgb * max(dot( normalDir, lightDir), 0) * _Diffuse.rgb;  //取得漫反射的颜色
				f.color = diffuse + ambient;  //漫反射光部分和环境光两种光叠加,得到最终的光照结果
			
				return f;
			}
			
			fixed4 frag(v2f f) : SV_Target
			{
				return fixed(f.color, 1.0);
			}
			
			ENDCG
		}
	}
	
	Fallback "Diffuse"
}

注:
环境光在这里设置
Unity Shader着色器学习(一)_第1张图片

逐像素漫反射计算

逐像素光照可以得到更加平滑的光照效果
逐像素漫反射计算只需要将 在逐顶点漫反射计算中的部分计算挪到片元着色器中计算即可。

Shader "Shader Learning Siki/Lighting/Diffuse PerFragment"
{
	Properties
	{
		_Diffuse("Diffuse Color", Color) = (1, 1, 1, 1)
	}
	SubShader
	{
		Pass
		{
			Tags{ "LightMode" = "ForwardBase"}
			
			CGPROGRAM
			
			//用于取得第一个直射光的颜色 _LightColor0
			//用于取得第一个直射光的位置 _WorldSpaceLightPos0
			#include "Lighting.cginc" 
			#pragma vertex vert
			#pragma fragment frag
			
			fixed4 _Diffuse;
			
			struct a2v
			{
				float4 vertex : POSITION;  //告诉Unity把模型空间下的顶点坐标填充给vertex
				float3 normal : NORMAL;
			};
			
			struct v2f
			{
				float4 position : SV_POSITION;
				fixed3 worldNormalDir : COLOR0;
			};
			
			v2f vert(a2v v)
			{
				v2f f;
				f.position = mul(UNITY_MATRIX_MVP, v.vertex);
				f.worldNormalDir = mul(v.normal, (float3x3)_World2Object);
			
				return f;
			}
			
			fixed4 frag(v2f f) : SV_Target
			{
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;  //获取环境光
				
				fixed3 normalDir = normalize(f.worldNormalDir);
				
				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  //对于每个顶点来说 光源的位置就是光源的方向,因为光是平行光
				fixed3 diffuse = _LightColor0.rgb * max(dot( normalDir, lightDir), 0) * _Diffuse.rgb;  //取得漫反射的颜色
				fixed3 tempColor = diffuse + ambient;  //漫反射光部分和环境光两种光叠加,得到最终的光照结果
			
				return fixed(tempColor , 1.0);
			}
			
			ENDCG
		}
	}
}

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号