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

news/2024/9/19 7:48:15/ 标签: unity, 游戏引擎

漫反射光照是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.ppmy.cn/news/1462730.html

相关文章

后端雪花算法主键ID传到前端变了

Mybatis Plus 的主键策略: /*** id*/TableId(type IdType.ASSIGN_ID)private Long id; 这个主键策略会用雪花算法生成一个 19位的ID,比如 1791006670084734978 现象 后端生成的 id 是正常的,通过 swagger 文档此时获取到的 id 也和数据库中…

GitHub的原理及应用详解(四)

本系列文章简介: GitHub是一个基于Git版本控制系统的代码托管平台,为开发者提供了一个方便的协作和版本管理的工具。它广泛应用于软件开发项目中,包括但不限于代码托管、协作开发、版本控制、错误追踪、持续集成等方面。 GitHub的原理可以简单…

RabbitMQ(二)七种工作模式

文章目录 概述:工作模式(七种)1. "Hello World!"2. Work Queues(工作队列模式)3. Publish/Subscribe(发布订阅模式)4. Routing5. Topics6. RPC7. Publisher Confirms 详细1. "Hello World!&…

哈醉咯最狠

3、通过命令行安装aptitude sudo apt-get install aptitude4、通过命令行利用aptitude 安装fcitx、qtsudo aptitude install fcitx-bin fcitx-table fcitx-config-gtk fcitx-config-gtk2 fcitx-frontend-allsudo aptitude install qt5-default qtcreator qml-module-qtquick-co…

Linux(centos)常用命令

Linux(Centos)常用命令使用说明文档 切换到/home目录下 使用cd命令切换目录,例如: cd /home列出/home目录下的所有文件 使用ls命令列出目录下的文件和子目录,例如: ls /home新建目录dir1 使用mkdir命…

Linux数组

目录 一.概念 (一)什么是数组? (二)数组的表现方式 (三)数组的数据类型 二.运用数组查看、修改、删除相关信息 (1)查看数组的元素列表 (2)查…

物联网应用开发--STM32与机智云通信(ESP8266 Wi-Fi+手机APP+LED+蜂鸣器+SHT20温湿度传感器)

实现目标 1、熟悉机智云平台,会下载APP 2、熟悉新云平台创建产品,项目虚拟调试 3、掌握云平台生成MCU代码,并移植。机智云透传固件的下载 4、具体目标:(1)注册机智云平台;(2&…

自动驾驶---Tesla的自动驾驶技术进化史(PerceptionPlanning)

1 前言 笔者在专栏《自动驾驶Planning模块》中已经详细讲解了传统自动驾驶Planning模块的内容:包括行车的Behavior Planning和Motion Planning,以及低速记忆泊车的Planning(最开始有15篇,目前逐渐更新到17篇)。读者对整…

【微信小程序开发】小程序前后端交互--发送网络请求实战解析

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

python写的五个小游戏___浔川python社

一: 猜词游戏 # 猜词游戏 import random words [apple, , orange, pear] word random.choice(words) mixed_word list(word) random.shuffle(mixed_word) mixed_word .join(mixed_word) print(猜词游戏开始!) print(打乱后的词是:, mixed_word) while True:gue…

Android 屏保开关

设置-显示-屏保, 打开关闭 设置代码在 ./packages/apps/Settings/src/com/android/settings/dream/DreamMainSwitchPreferenceController.java , Overridepublic boolean isChecked() {return mBackend.isEnabled();}Overridepublic boolean setChecke…

[Vulnhub] KVM3 (ht编辑器权限提升)

Vulnhub 报告 信息获取 系统 IP:192.168.8.100 服务枚举 Server IP AddressPorts Open192.168.8.100TCP 22,80 使用 Nmap 扫描: $ nmap -p- -sV -sC 192.168.8.100 --min-rate 1000 结果: Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-18 04:35 EDT Nmap sc…

Python | Leetcode Python题解之第110题平衡二叉树

题目: 题解: class Solution:def isBalanced(self, root: TreeNode) -> bool:def height(root: TreeNode) -> int:if not root:return 0leftHeight height(root.left)rightHeight height(root.right)if leftHeight -1 or rightHeight -1 or a…

Softing工业将亮相2024年阿赫玛展会——提供过程自动化的连接解决方案

您可于2024年6月10日至14日前往美因河畔法兰克福11.0号馆,Softing将在C25展位展出,欢迎莅临! 作为工业应用中数据交换领域公认的专家,Softing工业致力于帮助各行各业的客户部署网络自动化和优化生产流程。 使用Softing产品&…

JVM学习-堆空间(二)

年轻代与老年代 存储在JVM中的Java对象被划分为两类 一类是生命周期较短的瞬时对象,这类对象的创建和消亡都非常迅速一类对象的生命周期很长,在某些极端情况下还能够与JVM的生命周期保持一致 Java堆区进一步细分的话,分为年轻代(YoungGen)和…

hcip—VLAN实验

目录 实验拓扑: 实验目的: 实验思路: 实验步骤: 1.创建VLAN 2.将接口放进相应VLAN当中,并配置接口类型(hybrid口配置撕tag表) 3.配置路由器接口 4.配置DHCP服务 pc1 ping pc4的过程分析…

精准键位提示,键盘盲打轻松入门

在说明精准键位提示之前,我们先来看一张图: 这是一张标准的基准键位图,也就是打字时我们双手的8个手指放在基准键位上,在打不同的字母时,我们的手指以基准键位为中心,或上、或下、或左、或右,在…

Ubuntu上部署nginx RTMP直播服务

1 源代码下载 创建存放待编译源代码的目录: $ mkdir nginx-src 进入该目录,以获取相关代码: $ cd nginx-src 获取nginx源代码供编译: $ git clone https://github.com/nginx/nginx.git (也可通过wget或其它方式直…

bootstrap实现九宫格效果(猫捉老鼠游戏)

最近,孩子的幼儿园让家长体验“半日助教活动”,每个家长需要讲授15-20分钟的课程。作为一名程序员,实在没有能教的课程,只能做了一个小游戏,带着小朋友们熟悉数字。 效果大致是这样的。九宫格的左上角是一只小猫图片&…