[实例] Unity Shader 逐像素漫反射与半兰伯特光照

news2024/11/19 0:41:12

漫反射光照是Unity中最基本最简单的光照模型,本篇将会介绍在片元着色器中实现反射效果,并会采用半兰伯特光照技术对其进行改进。

1. 逐顶点光照与逐像素光照

在Unity Shader中,我们可以有两个地方可以用来计算光照:在顶点着色器中计算,被称为逐顶点光照(per-vertex lighting);在片元着色器中计算,被称为逐像素光照(per-pixel lighting)

在逐像素光照中,我们会以每个像素为基础,得到它的法线(可以是对顶点法线插值得到的,也可以是从法线纹理中采样得到的),然后进行光照模型的计算。而逐顶点光照会在每个顶点上计算光照,然后会在渲染图元内部进行线性插值,最后输出成像素颜色。由于顶点数目往往远小于像素数目,因此逐顶点光照的计算量往往要小于逐像素光照,性能较高;但由于逐顶点光照会在渲染图元内部对顶点颜色进行插值,这又会导致渲染图元内部的颜色总是暗于顶点处的最高颜色值,这在某些情况下会产生明显的棱角现象,使渲染效果下降。

2. 初始定义

为了控制材质的漫反射颜色,首先要在Shader的Properties语义块中声明一个Color类型的属性,并把它的初始值设为白色:

_Diffuse("Diffuse", Color) = (1, 1, 1, 1)

接下来在Pass语义块中,指定我们的光照模式:

Tags {
    "LightMode" = "ForwardBase" // 指定光照模式
}

为了使用Unity内置的一些变量,如_LightColor0,还需要包含Unity的内置文件Lighting.cginc:

#include "Lighting.cginc"

为了在Shader中使用Properties语义块中声明的属性,我们需要定义一个和该属性类型相匹配的变量:

fixed4 _Diffuse;

然后定义顶点着色器的输入和输出结构体:

// 顶点着色器输入 结构体
struct a2v
{
    float4 vertex: POSITION; // 顶点坐标
    float3 normal: NORMAL; // 法线方向
    float4 texcorrd: TEXCOORD0; // 模型的第一套纹理坐标
};

// 顶点着色器向片元着色器的输出 结构体
struct v2f
{
    float4 pos: POSITION; // 顶点在裁剪空间中的位置信息
    float3 worldNormal: TEXCOORD0; // 世界空间法线
};

3. 实现漫反射

首先我们要在顶点着色器函数中计算世界空间法线并输出到片元着色器:

// 将法线从模型空间转世界空间
outData.worldNormal = mul(appData.normal, (float3x3)unity_WorldToObject);

return outData;

然后在片元着色器中,通过法线和光源计算辐照度:

// 规范化世界空间法线
fixed3 worldNormal = normalize(inputData.worldNormal);
// 规范化世界空间光源
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// 计算辐照度
fixed E = saturate(dot(worldNormal, worldLightDir));

有了辐照度,再混合光照色和反射色计算出漫反射:

// 漫反射 = 光照色 * 反射色 * 辐照度
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * E;

最后加入环境光,计算出反射光:

// 获取环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// 环境光 + 漫反射
fixed3 color = ambient + diffuse;

return fixed4(color, 1);

渲染效果如下:

 

4. 使用半兰伯特模型对代码进行改进

我们发现该漫反射渲染有一个问题:在光照无法到达的区域,模型的表面呈现为全黑,没有任何明暗变化,这会使模型的背光区域看起来就像一个平面一样,失去了模型细节表现,因此我们需要引入半兰伯特光照技术对其进行改进。

我们在片元着色器代码中,将原先计算漫反射的部分,修改代码如下:

// 半兰伯特模型辐照度
fixed halfLambertE = E * 0.5 + 0.5;
// 漫反射 = 光照色 * 反射色 * 半兰伯特模型辐照度
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambertE;

渲染效果如下:

不过需要注意的是,半兰伯特是没有任何物理依据的,它仅仅是一个视觉加强技术。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1683614.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网创教程wordpress插件自动采集并发布

使用教程 出现404的请搞定自己网站的伪静态。一般都是伪静态问题。 需要定制可以联系我。 本次更新主要更新了。界面的设置。用户可以直接设置文章的分类。 设置文章发布的金额。 使插件更加的人性化。优化了采集更新发布的代码。 更新了网站的界面。 主要功能: w…

K8s Service 背后是怎么工作的?

kube-proxy 是 Kubernetes 集群中负责服务发现和负载均衡的组件之一。它是一个网络代理,运行在每个节点上, 用于 service 资源的负载均衡。它有两种模式:iptables 和 ipvs。 iptables iptables 是 Linux 系统中的一个用户空间实用程序,用于…

Ubuntu 20/22 安装 Jenkins

1. 使用 apt 命令安装 Java Jenkins 作为一个 Java 应用程序,要求 Java 8 及更高版本,检查系统上是否安装了 Java。 sudo apt install -y openjdk-17-jre-headless安装完成后,再次验证 Java 是否已安装 java --version2. 通过官方存储库安…

冯喜运:5.24现货黄金趋势解读,黄金原油行情分析及操作建议

【黄金消息面分析】:美国劳工部公布的最新数据显示,截至5月18日的一周内,首次申请失业救济人数下降至21.5万人,创下自去年9月以来的最大降幅。数据公布后,现货黄金短线下挫6美元,报2362.71美元/盎司。这表明…

泰迪智能科技分享:2024年职业院校中职组ZZ052大数据应用与服务赛项赛题第01套【子任务二:Hadoop 完全分布式安装配置】答案

Hadoop完全分布式安装配置 任务内容 本实训需要使用root用户完成相关配置,master、slave1、slave2三台节点都需要安装JDK与Hadoop,具体要求如下: 将JDK安装包解压到/root/software目录下;在“/etc/profile”文件中配置JDK环境变…

游戏联运的挑战与核心关键点

​游戏联运一个看似充满机遇与挑战的行业,吸引了很多创业者的加入。然而,真正踏入这个行业后,许多人会发现,手游代理并非想象中的那么简单。今天,溪谷软件就来和大家聊聊游戏联运是怎么做的,需要注意什么。…

使用RAG和文本转语音功能,我构建了一个 QA 问答机器人

节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

VC++学习(3)——认识MFC框架,新建项目,添加按钮

目录 引出第三讲 MFC框架新建项目Windows搜索【包含内容的搜索】如何加按钮添加成员变量添加成功 添加按钮2杂项 总结 引出 VC学习(3)——认识MFC框架,新建项目,添加按钮 MFC(Microsoft Foundation Classes),是微软公…

【Linux】关于获取进程退出状态中的core dump标志补充

通过 wait/waitpid 可以获取子进程的退出状态, 从而判断其退出结果. 记录退出状态的 int 变量 status 的使用情况如下图所示: 如果是收到信号终止的话, 低 7 位为收到的终止信号, 而低第 8 位为 core dump 标志, core dump 标志有什么用呢? core dump 标志只存 0/1, 表示是否…

leetcode以及牛客网单链表相关的题、移除链表元素、链表的中间节点、合并两个有序链表、反转链表、链表分割、倒数第k个节点等的介绍

文章目录 前言一、移除链表元素二、链表的中间节点三、合并两个有序链表四、反转链表五、链表分割六、倒数第k个节点总结 前言 leetcode以及牛客网单链表相关的题、移除链表元素、链表的中间节点、合并两个有序链表、反转链表、链表分割、倒数第k个节点等的介绍 一、移除链表元…

解决go install 网络问题

rootiZbp1hiqzlhh6w05gloffgZ:~# go install mvdan.cc/garblelatest go: mvdan.cc/garblelatest: module mvdan.cc/garble: Get "https://proxy.golang.org/mvdan.cc/garble/v/list": dial tcp 172.217.160.81:443: i/o timeout解决方法 更换阿里代理 rootiZbp1hiq…

js——数据操作——实现阶梯价格排序——基础积累

最近在写网络报价的时候,遇到一个需求,就是要根据采购数量,找到符合数量的阶梯区间,并找到最便宜的采购价格。 比如下面: let originViewList [{id:1,incrementalQuantity:10,priceList:[{minQuantity:1,price:20},…

加速短剧出海,优秀出海产品技术服务金帆奖颁布

当碎片化内容消费成为主流,短剧凭借其短小精悍、环环相扣、高频爆点等优势迅速拿捏大众喜好。作为泛娱乐市场又一个新兴的亮点,不止国内,伴随着碎片娱乐的海外移动观剧习惯持续培养,短剧供给量与消费规模不断上升,海外…

使用DockerFile 编写 指令来构建镜像

文章目录 前言使用DockerFile 编写 指令来构建镜像1. 构建2. 验证 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差,实在白嫖的话&#x…

【课后练习分享】Java用户注册界面设计和求三角形面积的图形界面程序

目录 java编程题(每日一练): 问题一的答案代码如下: 问题一的运行截图如下: 问题二的答案代码如下: 问题二的运行截图如下: java编程题(每日一练): 1.…

内存马实战(持续更新中)

注:这篇文章记录在我的语雀里面,语雀格式好看一点,地址: https://ganmaocai.yuque.com/ghgp8x/zoy1yn/faet35ae9gpxzn61 计划 复现以下框架的内存马注入: shiro: 普通内存马 冰蝎马 WebSocket马 xxl-job…

【Linux】-Elasticsearch安装部署[16]

目录 简介 安装 1、添加yum仓库 2、安装es 3、配置es 4、启动es 5、关闭防火墙 6、测试 简介 全文搜索属于最常见的要求,开源的Elasticsearch(以下简称es)是目前全文搜索引擎的首选。它可以快速的储存、搜索和分析海量数据。维基百科…

蓝牙模块七种工作模式——蓝牙Mesh组网工作模式

蓝牙Mesh组网模块技术在2017年得到SIG批准,这是一种独立的网络技术,兼容4及5系列蓝牙协议。它把蓝牙设备作为信号中继站,利用低功耗蓝牙广播的方式进行信息收发,蓝牙Mesh组网技术拓展了蓝牙的通讯关系,打破了以往蓝牙设…

Vue3 ts实现将assets中的图片转为file格式,实现本地图片选择上传功能

Vue3 ts实现将assets中的图片转为file格式,实现本地图片选择上传功能 1、需求描述2、关键代码3、img标签src使用变量打包后图片无法展示 1、需求描述 用户可以选项系统固定的几个图标,也可以自定义上传图片。系统固定图标存在 src\assets\images\app 路径…

6款网页表白代码6(附带源码)

6款网页表白代码6 前言效果图及部分源码1.爱心倒计时2.一起看星星3.爱心4.爱心(有鼠标移动特效)5.爱心(高级效果)6.爱心(3D效果) 领取源码下期更新预报 前言 大部分人都有喜欢的人,学会这些表白…