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

Unity3d Shader篇(六)— BlinnPhong高光反射着色器

文章目录

  • 前言
  • 一、BlinnPhong高光反射着色器是什么?
    • 1. BlinnPhong高光反射着色器的工作原理
    • 2. BlinnPhong高光反射着色器的优缺点
      • 优点
      • 缺点
    • 3. 公式
  • 二、使用步骤
    • 1. Shader 属性定义
    • 2. SubShader 设置
    • 3. 渲染 Pass
    • 4. 定义结构体和顶点着色器函数
    • 5. 片元着色器函数
  • 三、效果
  • 四、总结
    • Phong 顶点高光反射着色器的优劣势
    • Phong 片元高光反射着色器的优劣势
    • Blinn-Phong 高光反射着色器的优劣势


前言

在 Unity 中,Shader 可以用来实现各种视觉效果。本教程将详细介绍如何编写一个基于 BlinnPhong高光反射着色器,使物体的颜色根据光照和法线方向的变化而变化。


一、BlinnPhong高光反射着色器是什么?

1. BlinnPhong高光反射着色器的工作原理

Blinn-Phong 高光反射着色器是一种常用的光照模型,它可以模拟物体表面在不同光源和观察角度下的明暗变化,从而增强物体的立体感和真实感。它是由 Jim Blinn 和 Bui Tuong Phong 在 1970 年代提出的,是对 Phong 光照模型的改进和简化。

Blinn-Phong 高光反射着色器的基本思想是,物体表面的颜色由三个分量组成:环境光分量,漫反射分量和高光分量。环境光分量表示物体表面接收到的来自四面八方的间接光照,它是一个常量,与光源和观察者的位置无关。漫反射分量表示物体表面接收到的来自光源的直接光照,它与光源和物体表面的法线的夹角成正比,即 Lambert 定律。高光分量表示物体表面反射的光线进入观察者的眼睛,它与光源,物体表面的法线和观察者的位置有关,即 Blinn-Phong 反射模型。

2. BlinnPhong高光反射着色器的优缺点

优点

简单易实现,计算量相对较低,适合实时渲染。
可以调节物体表面的各种参数,例如颜色,亮度,高光系数等,来模拟不同的材质效果。
可以与纹理贴图,法线贴图等技术结合,进一步增强物体表面的细节和真实感。
产生的高光效果比 Phong 模型更加柔和和自然。

缺点

不符合物理规律,只是一种经验模型,无法模拟复杂的光照现象,例如阴影,折射,散射等。
对于一些高光敏感的材质,例如金属,玻璃等,可能无法产生理想的效果。
对于一些弯曲的物体,例如球体,圆柱体等,可能会出现高光断裂的现象,因为半向量的变化不够平滑

3. 公式

在这里插入图片描述

二、使用步骤

1. Shader 属性定义

// 定义属性
Properties
{_Diffuse("Diffuse",Color)=(1,1,1,1) // 漫反射颜色属性,默认白色_Specular("Specular",Color)=(1,1,1,1) // 高光颜色性,默认白色_Gloss("Gloss",Range(1,256))=5// 高光反射系数
}

这段代码定义了Shader的属性,其中:
_Diffuse: 表示漫反射颜色属性,使用RGBA格式表示颜色,默认为白色 (1, 1, 1, 1)。
_Specular: 表示高光颜色属性,同样使用RGBA格式表示颜色,默认为白色 (1, 1, 1, 1)。
_Gloss: 表示高光反射系数属性,使用Range声明范围为1到256,默认值为5。

2. SubShader 设置

SubShader
{Tags{"RenderType" = "Opaque" // 渲染类型为不透明}LOD 100 // 细节级别
}

SubShader 定义了一组渲染设置,包括标签和细节级别。在这里,我们将渲染类型标签设置为 “Opaque”,表示物体是不透明的。

3. 渲染 Pass

Pass
{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"
}

这里开始了渲染 Pass 部分。在这里,我们使用了 CGPROGRAM 指令来声明顶点着色器和片元着色器函数。#pragma vertex vert 和 #pragma fragment frag 分别指定了顶点着色器函数和片元着色器函数的名称。

然后,我们包含了 UnityCG.cginc 和 Lighting.cginc,它们提供了许多有用的函数和宏,用于简化编写 Shader。

4. 定义结构体和顶点着色器函数

// 定义结构体:从顶点到片元的数据传递
struct v2f
{float4 vertex : SV_POSITION; // 顶点位置fixed3 worldNormal : TEXCOORD0; // 世界空间法线fixed3 worldPos : TEXCOORD1; // 世界空间位置
};// 顶点着色器函数
v2f vert(appdata_base v)
{v2f o;o.vertex = UnityObjectToClipPos(v.vertex); // 顶点位置变换到裁剪空间fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); // 世界空间法线o.worldNormal = worldNormal;//unity_ObjectToWorld 是一个变换矩阵,用于将顶点从对象空间变换到世界空间。//v.vertex 是顶点的位置信息。//mul() 函数表示矩阵相乘操作,这里将对象空间中的顶点位置矩阵与对象到世界的变换矩阵相乘,得到世界空间中的顶点位置。o.worldPos=mul(unity_ObjectToWorld,v.vertex);return o;
}

顶点着色器的输入是一个结构体 appdata_base ,它包含了顶点的位置和法线信息。顶点着色器的输出是一个结构体 v2f ,它包含了顶点的裁剪空间位置和世界空间法线和位置信息。

顶点着色器的主要逻辑是:

  1. 使用 UnityObjectToClipPos 函数,将顶点的位置从对象空间变换到裁剪空间,这是渲染管线的必要步骤。

  2. 使用 UnityObjectToWorldNormal 函数,将顶点的法线从对象空间变换到世界空间,这是为了计算光照效果所需的方向向量。

  3. 使用 unity_ObjectToWorld 矩阵,将顶点的位置从对象空间变换到世界空间,这是为了计算光照效果所需的坐标系。

5. 片元着色器函数

// 片段着色器函数
fixed4 frag(v2f i) : SV_Target
{// 获取环境光fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;// 漫反射// 获取光源位置//fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);// 获取光源位置简化fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldLightDir, i.worldNormal));// 高光反射// 计算视角方向//fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.WorldPos);fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));// 计算半向量fixed3 halfDir = normalize(worldLightDir + viewDir);// 计算高光颜色fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(i.worldNormal, halfDir)), _Gloss);// 组合最终颜色fixed3 color = diffuse + ambient + specular;return fixed4(color, 1); // 输出颜色
}

片元着色器的输入是一个结构体 v2f ,它包含了顶点的裁剪空间位置和世界空间法线和位置信息。片元着色器的输出是一个 fixed4 类型的颜色值,它表示了片元的颜色。

片元着色器的主要逻辑是:

  1. 使用 UNITY_LIGHTMODEL_AMBIENT 宏,获取环境光的颜色,这是 Blinn-Phong 光照模型的第一个分量。

  2. 使用 UnityWorldSpaceLightDir 函数,获取光源的方向向量,这是为了计算漫反射和高光效果所需的角度。

  3. 使用 _LightColor0 和 _Diffuse 变量,获取光源的颜色和物体的漫反射颜色,然后使用 max 和 dot 函数,计算光源和法线的夹角的余弦值,这是 Blinn-Phong 光照模型的第二个分量。

  4. 使用 UnityWorldSpaceViewDir 函数,获取视线的方向向量,这是为了计算高光效果所需的角度。

  5. 使用 normalize 函数,计算视线方向和光源方向的半向量,这是为了简化高光效果的计算。

  6. 使用 _LightColor0 和 _Specular 变量,获取光源的颜色和物体的高光颜色,然后使用 max 和 dot 函数,计算法线和半向量的夹角的余弦值,然后使用 pow 函数,计算高光的强度,这是 Blinn-Phong 光照模型的第三个分量。

  7. 将环境光、漫反射和高光的颜色相加,得到最终的光照颜色,作为片元着色器的输出。

三、效果

左:Phong顶点高光反射着色器 中:Phong片元高光反射着色器 右:BlinnPhong高光反射着色器 (_Diffuse设置成了红色)

在这里插入图片描述

四、总结

Phong 片元高光反射着色器和 Phong 顶点高光反射着色器都是基于 Phong 光照模型的着色器,可以模拟物体表面的漫反射、环境光和高光效果,使物体看起来更加真实和立体。Blinn-Phong 高光反射着色器是对 Phong 高光反射着色器的改进和简化,主要区别在于计算高光反射时使用了半向量(half vector)代替镜面反射向量(reflection vector),从而减少了计算量和误差。

Phong 顶点高光反射着色器的优劣势

它的优势是:
在顶点着色器中计算光照颜色,减少了片元着色器的计算量,提高了性能和效率。

它的劣势是:会导致光照效果不够精细,尤其是在物体表面有弯曲或者高光区域时,会出现明显的锯齿或者平面化的现象。它不能处理复杂的光照情况,例如多光源、阴影、透明度、反射、折射等,需要使用更高级的着色器来实现。

使用场景:
当需要模拟物体表面的光照效果,但又不需要太高的精度和细节时,可以使用这种着色器。例如,一些简单的几何形状,或者一些远处的物体,或者一些不需要太多关注的物体,都可以使用这种着色器来提高性能和节省资源。

Phong 片元高光反射着色器的优劣势

它的优势是:
在片元着色器中计算光照颜色,提高了光照效果的精细度和真实度,尤其是在物体表面有弯曲或者高光区域时,可以避免出现锯齿或者平面化的现象。

它的劣势是:
会增加片元着色器的计算量,降低性能和效率,尤其是在物体的面数较多或者光源的数量较多时,会造成较大的开销。它不能处理复杂的光照情况,例如多光源、阴影、透明度、反射、折射等,需要使用更高级的着色器来实现。

使用场景:
当需要模拟物体表面的光照效果,且需要较高的精度和细节时,可以使用这种着色器。例如,一些复杂的几何形状,或者一些近处的物体,或者一些需要重点关注的物体,都可以使用这种着色器来提高视觉效果和真实感。

Blinn-Phong 高光反射着色器的优劣势

它的优势是:
简单易实现,计算量相对较低,适合实时渲染。
可以调节物体表面的高光反射系数和指数,来模拟不同的材质效果。
产生的高光效果比 Phong 模型更加柔和和自然,更接近真实的光照现象。

它的劣势是:
不符合物理规律,只是一种经验模型,无法模拟复杂的光照现象,例如阴影,折射,散射等。
对于一些高光敏感的材质,例如金属,玻璃等,可能无法产生理想的效果。
对于一些弯曲的物体,例如球体,圆柱体等,可能会出现高光断裂的现象,因为半向量的变化不够平滑。

使用场景:
当需要模拟物体表面的高光反射效果,且需要较好的效率和真实感时,可以使用这种着色器。例如,一些光滑的几何形状,或者一些中等距离的物体,或者一些需要突出高光的物体,都可以使用这种着色器来增强光照效果和立体感。

相关文章:

Unity3d Shader篇(六)— BlinnPhong高光反射着色器

文章目录 前言一、BlinnPhong高光反射着色器是什么?1. BlinnPhong高光反射着色器的工作原理2. BlinnPhong高光反射着色器的优缺点优点缺点 3. 公式 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数 三…...

Go-zero微服务个人探究之路(十二)定时任务的选择调研

前言 很多时候后台需要做定时任务的需求,笔者的项目采用go-zero框架微服务框架,需要做定时任务,于是做了如下方法调研,共有大概三种主要选择 方案 难度总体由容易到复杂 go的timer库 通过Go的标准库time中的Ticker和Tick功能…...

Java中,List、Map和Set的区别是什么?

在Java中,List、Map和Set是三种常用的集合类型,它们之间的主要区别如下: 1、List List是有序集合,它可以包含重复元素。 List中的元素是按照插入顺序排列的,可以通过索引访问每个元素。 Java中常见的List实现类有A…...

Google刚刚推出了图神经网络Tensorflow-GNN

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

链表基础知识汇总

链表 链表是一种基本的数据结构,是由一系列节点组成的集合。每个节点包含两个部分:值和指向下一个节点的指针。链表中的节点可以动态地添加、删除,其大小可以根据需要进行扩展或缩小。 链表通常用于处理不固定长度的数据结构,具有…...

Educational Codeforces Round 2(远古edu计划)

A. 恶心模拟。。 模拟一下分类即可 数字类&#xff0c;数字0&#xff0c;或者都是数字 字母类&#xff0c;字母空的也是字母&#xff0c;有字母就是字母 #include<bits/stdc.h> #define INF 1e9 using namespace std; typedef long long ll; const int N2e59; strin…...

【Tauri】(1):使用Tauri1.5版本,进行桌面应用开发,在windows,linux进行桌面GUI应用程序开发,可以打包成功,使用 vite 最方便

1&#xff0c;视频地址&#xff1a; https://www.bilibili.com/video/BV1Pz421d7s4/ 【Tauri】&#xff08;1&#xff09;&#xff1a;使用Tauri1.5版本&#xff0c;进行桌面应用开发&#xff0c;在windows&#xff0c;linux进行桌面GUI应用程序开发&#xff0c;可以打包成功&…...

「Linux」软件安装

MySQL5.7在CentOS安装 安装 配置yum仓库 更新密钥&#xff1a;rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022安装MySQL yum库&#xff1a;rpm -Uvh http://repo.mysql.com//mysql57-community-release-el7-7.noarch.rpm使用yum安装MySQL&#xff1a;yum -y in…...

Ubuntu Desktop - Terminal 输出全部选中 + 复制

Ubuntu Desktop - Terminal 输出全部选中 复制 1. Terminal2. Terminal 最大化3. Edit -> Select All4. Copy & PasteReferences 1. Terminal 2. Terminal 最大化 3. Edit -> Select All 4. Copy & Paste Edit -> Copy or Shift Ctrl C Edit -> Paste…...

Java 三大并大特性-可见性介绍(结合代码、分析源码)

目录 ​编辑 一、可见性概念 1.1 概念 二、可见性问题由来 2.1 由来分析 三、可见性代码例子 3.1 代码 3.2 执行结果 四、Java 中保证可见性的手段 4.1 volatile 4.1.1 优化代码 4.1.2 测试结果 4.1.3 volatile原理分析 4.1.3.1 查看字节码 4.1.3.2 hotspot 层面…...

【漏洞复现】狮子鱼CMS某SQL注入漏洞01

Nx01 产品简介 狮子鱼CMS&#xff08;Content Management System&#xff09;是一种网站管理系统&#xff0c;它旨在帮助用户更轻松地创建和管理网站。该系统拥有用户友好的界面和丰富的功能&#xff0c;包括页面管理、博客、新闻、产品展示等。通过简单直观的管理界面&#xf…...

《Java 简易速速上手小册》第6章:Java 并发编程(2024 最新版)

文章目录 6.1 线程的创建和管理 - 召唤你的士兵6.1.1 基础知识6.1.2 重点案例&#xff1a;实现一个简单的计数器6.1.3 拓展案例 1&#xff1a;定时器线程6.1.4 拓展案例 2&#xff1a;使用 Executor 框架管理线程 6.2 同步机制 - 维持军队的秩序6.2.1 基础知识6.2.2 重点案例&a…...

C++初阶:容器(Containers)list常用接口详解

介绍完了vector类的相关内容后&#xff0c;接下来进入新的篇章&#xff0c;容器list介绍&#xff1a; 文章目录 1.list的初步介绍2.list的定义&#xff08;constructor&#xff09;3.list迭代器&#xff08; iterator &#xff09;4.string的三种遍历4.1迭代器4.2范围for循环 5…...

HARRYPOTTER: FAWKES

攻击机 192.168.223.128 目标机192.168.223.143 主机发现 nmap -sP 192.168.223.0/24 端口扫描 nmap -sV -p- -A 192.168.223.143 开启了21 22 80 2222 9898 五个端口&#xff0c;其中21端口可以匿名FTP登录&#xff0c;好像有点说法,百度搜索一下发现可以用anonymous登录…...

嵌入式Qt 第一个Qt项目

一.创建Qt项目 打开Qt Creator 界面选择 New Project或者选择菜单栏 【文件】-【新建文件或项目】菜单项 弹出New Project对话框&#xff0c;选择Qt Widgets Application 选择【Choose】按钮&#xff0c;弹出如下对话框 设置项目名称和路径&#xff0c;按照向导进行下一步 选…...

【OpenHarmony硬件操作】风扇与温湿度模块

文章目录 前言一、串行通信是什么二、IC2.1 IC是什么2.2 IC涉及到的线2.3 IC的时序三、风扇的操作3.1 关于 pcf85743.2 风扇的接口函数IO拓展芯片的定义初始化PCF8574初始化 IO拓展版的引脚属性开启和关闭风扇读状态四、温湿度传感器的使用4.1 初始化温湿度传感器</...

Vue3.4+element-plus2.5 + Vite 搭建教程整理

一、 Vue3Vite 项目搭建 说明&#xff1a; Vue3 最新版本已经基于Vite构建&#xff0c;关于Vite简介&#xff1a;Vite 下一代的前端工具链&#xff0c;前端开发与构建工具-CSDN博客 1.安装 并 创建Vue3 应用 npm create vuelatest 创建过程可以一路 NO 目前推荐使用 Vue R…...

STM32Cubmax stm32f103zet6 SPI通讯

一、基本概念 SPI 是英语 Serial Peripheral interface 的缩写&#xff0c;顾名思义就是串行外围设备接口。是 Motorola 首先在其 MC68HCXX 系列处理器上定义的。 SPI 接口主要应用在 EEPROM&#xff0c; FLASH&#xff0c;实时时 钟&#xff0c; AD 转换器&#xff0c;还有数…...

每日OJ题_位运算⑤_力扣371. 两整数之和

目录 力扣371. 两整数之和 解析代码 力扣371. 两整数之和 371. 两整数之和 难度 简单 给你两个整数 a 和 b &#xff0c;不使用 运算符 和 - &#xff0c;计算并返回两整数之和。 示例 1&#xff1a; 输入&#xff1a;a 1, b 2 输出&#xff1a;3示例 2&#xff1a; …...

Mysql中索引优化和失效

什么是索引 要了解索引优化和索引失效的场景就要先了解什么是索引 索引是一种有序的存储结构&#xff0c;按照单个或者多个列的值进行排序&#xff0c;以提升搜索效率。 索引的类型 UNIQUE唯一索引 不可以出现相同的值&#xff0c;可以有NULL值。 INDEX普通索引 允许出现相同…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

高分辨率图像合成归一化流扩展

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 1 摘要 我们提出了STARFlow&#xff0c;一种基于归一化流的可扩展生成模型&#xff0c;它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流&#xff08;TARFlow&am…...