Unity Shader 入门精要阅读笔记_基础光照


前言

从初级篇开始


一、开始学习Unity Shader

1.1 Unity Shader的基本结构:

在这里插入图片描述

1.2 一些介绍

很烦,一上来就是bug,一模一样得代码,我的球就是红色的,初步怀疑是target的问题:在这里插入图片描述

这个bug的原因是frag()函数的输出不是fix而是fixed4
当时刚刚学大约是打错了

//shader名称
Shader "Custom/SimpleShader"{
	SubShader{
		pass{
			CGPROGRAM
			//定义顶点着色器和片元着色器函数
			#pragma vertex vert
			#pragma fragment frag
			
			//输入:POSITION,定义为v, 输出到SV_POSITION 中
			float4 vert(float4 v : POSITION): SV_POSITION{
				return UnityObjectToClipPos(v);
			}
			// SV_TARGET,渲染目标,储存到一个帧缓存器中
			fixed4 frag() : SV_Target{
				return fixed4(1.0 , 1.0 ,1.0 , 1.0);
			}
			ENDCG
		}
	}
}

struct结构体
定义一个结构
在这里插入图片描述在这里插入图片描述
综合使用

Shader "Unity Shaders Book/Chapter 5/Simple Shader" {
	Properties {
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
	}
	SubShader {
        Pass {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            
            uniform fixed4 _Color;

			struct a2v {
                float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
            };
            
            struct v2f {
                float4 pos : SV_POSITION;
                fixed3 color : COLOR0;
            };
            
            v2f vert(a2v v) {
            	v2f o;
            	o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
            	o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
            	fixed3 c = i.color;
            	c *= _Color.rgb;
                return fixed4(c, 1.0);
            }

            ENDCG
        }
    }
}

1.3 总结:Unity内置变量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、基础光照

2.1 视觉原理基础

  • 光线从光源中传播出来
  • 光线被物体吸收,并且由物体发出散射到其他各个方向
  • 摄像机接收到光纤,产生图像

几个名词:

  • 辐照度(irradiance):量化光,光源方向和v表面法线n之间的夹角的余弦值来得到
  • 高光反射:物体表面是如何反射光线的
  • 漫反射:有多少光线会被折射吸收和散射
  • 出射度:出射光线的数量和方向
  • BRDF:双向散射分布模型,后续会有提到

2.2 标准光照模型

只关注直接光照

他把进入到摄像机内的光线分为四个部分

  • 自发光,描述一个给定方向上的一个表面本身会向该方向发射多少辐射量
  • 高光反射
  • 漫反射
  • 环境光,描述其他的所有间接光照

接下来是一些计算公式

  • 环境光通常是一个全局变量,所有的物体都会使用它,用来模拟间接光照
  • 自发光,直接使用该材质的自发光颜色
  • 在这里插入图片描述
  • 高光反射是经验模型
    在这里插入图片描述

2.3 漫反射光照模型

逐顶点版本

Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex-Level" {
	Properties {
	// 定义漫反射颜色,初始值白色
		_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
	}
	SubShader {
		Pass { 
		// 指定该pass的光照模式,定义该pass在unity的光照流水线中的角色
			Tags { "LightMode"="ForwardBase" }
		
			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			//为了使用内置变量引入库
			#include "Lighting.cginc"
			// 使用properties的变量
			fixed4 _Diffuse;
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				fixed3 color : COLOR;
			};
			
			v2f vert(a2v v) {
				v2f o;
				// Transform the vertex from object space to projection space
				o.pos = UnityObjectToClipPos(v.vertex);
				
				// Get ambient term
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				
				// Transform the normal from object space to world space
				fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
				// Get the light direction in world space
				fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
				// Compute diffuse term
				//内置变量lightcolor0 访问该pass处理的光源的颜色和强度信息
				//光源方向可以由_WorldSpaceLightPos0
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
				
				o.color = ambient + diffuse;
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
				return fixed4(i.color, 1.0);
			}
			
			ENDCG
		}
	}
	FallBack "Diffuse"
}

在逐像素版本中,顶点着色器将传递世界法线和裁切空间的位置信息,在片元着色器中完成fixed4 color的计算

2.4 半兰伯特模型

上面的模型有个问题
在这里插入图片描述
在光照无法到达的区域,模型是纯黑的,没有一点变化,看起来是个平面

半兰伯特光照模型的公式如下
在这里插入图片描述

  • 他把表面法线和入射光线的点积做了个映射,而不是取最大值,把负值部分完全抛掉
  • 一般 α = β = 0.5 \alpha = \beta = 0.5 α=β=0.5,映射到 [ 0 , 1 ] [0,1] [0,1]

效果长这样
在这里插入图片描述

2.5 高光反射光照模型

在这里插入图片描述

  • 入射光线的颜色和强度
  • 材质的高光反射系数
  • 视角方向
  • 反射方向
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 6/Specular Vertex-Level" {
	Properties {
		_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
	}
	SubShader {
		Pass { 
			Tags { "LightMode"="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;
				fixed3 color : COLOR;
			};
			
			v2f vert(a2v v) {
				v2f o;
				// Transform the vertex from object space to projection space
				o.pos = UnityObjectToClipPos(v.vertex);
				
				// Get ambient term
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
				
				// Transform the normal from object space to world space
				//注意左乘右乘
				fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
				// Get the light direction in world space
				fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
				
				// Compute diffuse term
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
				
				// 获得反射光线
				fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
				// 视角方向
				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz);
				
				// Compute specular term
				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.0);
			}
			
			ENDCG
		}
	} 
	FallBack "Specular"
}

效果如图
在这里插入图片描述

2.6 布林冯模型

半程向量的使用
在这里插入图片描述
在这里插入图片描述

2.7 帮助函数

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/woshi_wst/article/details/128528559