当前位置: 首页 > news >正文

第七天 开始Unity Shader的学习之Unity中的基础光照之高光反射光照模型

Unity Shader的学习笔记

第七天 开始Unity Shader的学习之Unity中的基础光照之高光反射光照模型


文章目录

  • Unity Shader的学习笔记
  • 前言
  • 一、高光反射光照模型
    • 1.逐顶点光照
      • ① Properties
      • ② 顶点着色器中计算高光specular
      • ③ Fallback
      • 效果展示
    • 2.逐像素光照
      • ① 片元着色器输出结构体v2f
      • ②高光反射部分计算
      • 效果展示
  • 总结


前言

今天学习漫反射光照模型中的逐顶点光照和逐像素光照,其实今天的大部分代码之前学习过了,主要是对高光反射特有的公式这些进行一个讲解.


一、高光反射光照模型

相比于漫反射光照模型,高光反射的模型只是在器基础上增加了高光的部分,让我们接下来看下面这段代码:

1.逐顶点光照

// 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;
				o.pos = UnityObjectToClipPos(v.vertex);
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT;
				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 - mul(unity_ObjectToWorld, v.vertex).xyz);									
				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"}

① Properties

首先为了方便我们在材质面板中控制高光反射属性,于是相比于漫反射,我们声明了_Specular和_Gloss两个属性,分别用于控制高光反射的颜色和高光反射的区域大小.

② 顶点着色器中计算高光specular

fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));																
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz);									
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);

首先我们就需要先摆出来高光反射部分的计算公式了:
高光反射部分的计算公式反射方向的计算公式
因此除了我们已经有了的光照的颜色和高光反射的颜色之外,我们还需要计算视角方向和反射方向,反射方向的公式已经给出来了(Unity本身也提供了reflect来计算反射方向),视角方向可以通过世界空间下摄像机的位置 - 世界空间下的顶点位置来得到,这样每一个变量都有了,直接计算高光反射部分(pow的用法看清楚哈)
计算完成后,将o.color 加上高光反射的部分.

③ Fallback

由于我们是高光反射,因此将Unity Shader的回调Shader设置为Specular.

效果展示

使用逐顶点的方法得到的效果如下:
逐顶点高光反射光照效果
我们会法线这个效果其实是有很大问题的:高光反射部分明显不平滑,这是因为高光反射的部分计算是非线性的,而在顶点着色器中计算光照再插值的过程是线性的,破坏了原计算的非线性关系,就会产生较大的视觉问题,接下来的逐像素高光反射可以解决这个问题

2.逐像素光照

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// 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 Pixed-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;
				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 ambient = UNITY_LIGHTMODEL_AMBIENT;
				fixed3 worldNormal = normalize(i.worldNormal);
				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 - i.worldPos.xyz);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
				fixed3 color = ambient + diffuse + specular;
				return fixed4(color, 1.0);
			}

			ENDCG
		}
	}
	Fallback "Specular"
}

① 片元着色器输出结构体v2f

因为我们需要在片元着色器中计算高光反射部分,所以我们需要将顶点着色器中计算得到的世界空间下的法线方向和顶点坐标,并且把他们传递给片元着色器.

struct v2f
{
	float4 pos : SV_POSITION;
	float3 worldNormal : TEXCOORD0;
	float3 worldPos : TEXCOORD1;
};

②高光反射部分计算

fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
fixed3 color = ambient + diffuse + specular;

计算公式我们上面也给出了,唯一不同的是我们使用的顶点坐标和法线方向是顶点着色器传递过来的.

效果展示

逐像素的方式处理的高光反射光照模型
这样我们可以得到更加光滑的高光效果.


总结

经过这几天的学习,我们终于实现了一个完整的Phong光照模型.

相关文章:

  • S7-1200 PLC热电偶和热电阻模拟量模块
  • java基础-修饰符
  • Jakarta EE 11发布:云原生Java企业应用的新标准
  • Android Studio Narwhal | 2025.1.1新功能
  • Python3笔记之号称替代pip的uv包管理器
  • 01.02、判定是否互为字符重排
  • H3C的MSTP+VRRP高可靠性组网技术(MSTP单域)
  • Adam为什么能加速收敛和自适应学习率?
  • 2025.04.05-美团春招第四题
  • 【大数据生态】Hive的metadata服务未开启
  • 一种单脉冲雷达多通道解卷积前视成像方法【论文阅读】
  • DDoS防御与流量优化
  • 机器学习-线性回归模型
  • JdbcTemplate基本使用
  • [Bond的杂货铺] CKS 证书也到货咯
  • Python标准库json完全指南:高效处理JSON数据
  • 动态规划——两个数组的dp问题
  • [C++面试] 初始化相关面试点深究
  • macos下 ragflow二次开发环境搭建
  • PIXOR:基于LiDAR的3D检测模型解析
  • 中小微企业查询官网/温州seo外包公司
  • 外贸网站框架/站长之家app
  • 客服代运营/网站首页的优化
  • 做网站用的笔记本配置/韩国seocaso
  • 中国建设银行山西省分行网站/广州白云区疫情实时动态
  • 做的比较唯美的网站/新手做seo怎么做