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

漫反射光照是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;

渲染效果如下:

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT控件QDialog结合QDialogButtonBox实现确认弹窗

项目需要二次确认开启,添加一个确认弹窗,采用QDialog并添加按钮控件。 QDialogButtonBox控件用于添加按钮组,初始化时可以增加标准按键,但是不能自定义按钮文字。 想要更改按键大小,但是没有提供设置组内按钮大小的函数…

创建型模式之单例

文章目录 概述定义场景小结 概述 设计模式包括创建型模式,结构型模式,行为型模式。 今天先看看创建型模式,而单例是创建型模式中的第一个而且是常用的,就从它开始吧。 定义 单例模式用来创建全局唯一的对象。一个类只允许创建一…

5.23 学习总结

一.项目优化(语音通话) 实现步骤: 1.用户发送通话申请,并处理通话请求,如果同意,为两个用户之间进行连接。 2.获取到电脑的麦克风和扬声器,将获取到的语音信息转换成以字节数组的形式传递。 …

小林coding笔记

MySQL执行流程 MySQL 的架构共分为两层:Server 层和存储引擎层。Server 层负责建立连接、分析和执行 SQL。存储引擎层负责数据的存储和提取。 Mysql执行 启动Mysql net start mysql登陆 mysql -u root -p输入密码

C++之单链表与双链表逆序实例(二百七十九)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

17款奔驰GLS450升级头等舱行政独立四座马鞍是什么样体验

五座版本:迈巴赫GLS480的五座版本通常指的是具有五个座位的配置,包括两个前排座椅和三个后排座椅。这种配置适合搭载更多乘客,后排座椅通常为三人座设计,乘坐人数较多。 四座版本:迈巴赫GLS480的四座版本通常指的是具…

正点原子LWIP学习笔记(二)MAC简介

MAC简介 一、MAC简介(了解)二级目录三级目录 二、ST的ETH框架(了解)三、SMI站管理接口(熟悉)四、介质接口MII、RMII(熟悉) 一、MAC简介(了解) STM32 的 MAC …

c++笔记3

优先队列 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。优先队列是一种按照优先级决定出队顺序的数据结构,优先队列中的每个元素被赋予级别,队首元素的优先级最高。 例如:4入队&#xff0c…

Python筑基之旅-MySQL数据库(一)

目录 一、MySQL数据库 1、简介 2、优点 2-1、开源和免费 2-2、高性能 2-3、可扩展性 2-4、易用性 2-5、灵活性 2-6、安全性和稳定性 2-7、丰富的功能 2-8、结合其他工具和服务 2-9、良好的兼容性和移植性 3、缺点 3-1、对大数据的支持有限 3-2、缺乏全文…

Windows系统安装OpenSSH使用VScode远程连接内网Linux服务器开发

文章目录 💡推荐 前言1、安装OpenSSH2、VS Code配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网…

threejs的基本属性

1.创建场景,摄像机,渲染器,几何体,材质,网格 网格 物体材质 场景.add(网格),网格加入场景中 场景.add(坐标辅助器) 渲染 场景摄像机 相机的轨道控制器是个单独的对象 import ./style.css import * as THREE from three import { OrbitControls } from three/examples/j…

【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针

前言 大家好,今天是【重学C】系列的第二讲,我们来聊聊C的智能指针。 为什么需要智能指针 在上一讲《01 C如何进行内存资源管理》中,提到了对于堆上的内存资源,需要我们手动分配和释放。管理这些资源是个技术活,一不…

新媒体运营十大能力,让品牌闻达天下!

" 现在新媒体蓬勃发展,很多品牌都有新媒体运营这个岗位。新媒体运营好的话,可以提高公司品牌曝光、影响力。那新媒体运营具备什么能力,才能让品牌知名度如虎添翼呢?" 信息收集能力 在移动互联网时代,信息的…

你应该用USB还是或耳机插孔连接你的电脑耳机?这里有详细解释

​如果你有一套有线耳机,可以通过USB连接或传统耳机插孔连接到电脑,你可能想知道使用这两个端口选项的实际区别。 使用耳机插孔 如果你使用传统的模拟电缆将耳机连接到计算机(或任何带耳机插孔的设备),则耳机的作用与…

英码科技算能系列边缘计算盒子再添新成员!搭载TPU处理器BM1688CV186AH,功耗更低、接口更丰富

在数据呈现指数级增长的今天,越来越多的领域和细分场景对实时、高效的数据处理和分析的需求日益增长,对智能算力的需求也不断增强。为应对新的市场趋势,英码科技凭借自身的硬件研发优势,携手算能相继推出了基于BM1684的边缘计算盒…

Google Earth Engine(GEE)深度学习入门教程-Python数据读入篇

Python数据读入篇 前置条件: GEE预处理影像导出保存为tfrecord的数据包,并下载到本地tensorflow的深度学习环境 本篇文章的目的主要是把Tfrecord格式的数据加载为tf可使用的数据集格式 设定超参数 首先需要设定导出时的波段名称和数据格式&#xff…

linux 排查java内存溢出(持续更新中)

场景 tone.jar 启动后内存溢出,假设pid 为48044 排查 1.确定java程序的pid(进程id) ps 或 jps 都可以 ps -ef | grep tone jps -l 2.查看堆栈信息 jmap -heap 48044 3.查看对象的实例数量显示前30 jmap -histo:live 48044 | head -n 30 4.查看线程状态 jstack 48044

于ThinkPHP开发的赛事报名小程序

基于ThinkPHP开发的赛事报名微信小程序 功能包括 1、参赛公告 2、会员中心(会员注册、登录、成绩查询、资料管理、参赛记录管理) 3、个人报名和企业报名 (身份证验证防止重复报名) 4、培训报名 5、查询是否在库人员,根…

深度学习之Pytorch框架垃圾分类智能识别系统

欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着城市化进程的加快和人们环保意识的提高,垃圾分类已成为城市管理的重要一环。然而&am…

git拉取项目前需要操作哪些?

1.输入 $ ssh-keygen -t rsa -C "秘钥说明" 按enter键 2.出现 ssh/id_rsa:(输入也可以不输入也可以) 然后按enter键 3.出现empty for no passphrase:(输入也可以不输入也可以) 然后按enter键 4.出现same passphrase again: (输入也可以不输入也…