Unity中Shader的GI的直接光实现
文章目录
- 前言
- 一、在上一篇文章中,得到GI相关数据后,需要对其进行Lambert光照模型计算
- 二、在准备好上面步骤后,我们需要准备缺少的数据
- 1、准备上图中的 s.Normal
- 2、准备上图中的 s.Albedo
前言
Unity中Shader的GI的直接光实现,基于上一篇准备好的数据的基础上,继续实现GI的直接光效果
- Unity中Shader的烘培分支的判断
一、在上一篇文章中,得到GI相关数据后,需要对其进行Lambert光照模型计算
这是上一篇文章中得到 GI 数据的方法
LightingLambert_GI1(o,giInput,gi);
得到了之后,我们直接使用Unity自带的计算 Lambert 模型的函数计算即可,当然也可自己按照之前的文章实现 Lambert 光照模型
- Unity中Shader的Lambert光照的实现
这是在 Lighting.cginc 中Unity实现Lambert光照的方法
我们把它移植到我们自己的 cginc 中,方便管理修改(记着修改一下函数名,防止函数名冲突)
二、在准备好上面步骤后,我们需要准备缺少的数据
1、准备上图中的 s.Normal
这在之前的文章中,已经定义过很多次了,具体步骤如下
1.在appdata中,接受 half3 normal : NORMAL;
half3 normal : NORMAL;
2.在 v2f 中定义一个 half3 worldNormal :TEXCOORD;用于存放顶点法线数据
half3 worldNormal : TEXCOORD2;
3.在顶点着色器中,把 appdata 传入的数据转化到世界坐标下,存入 v2f 的worldNormal中
o.worldNormal = UnityObjectToWorldNormal(v.normal);
4.在片元着色器中,把 worldNormal 赋值给 SurfaceOutput 变量的 Normal
//1、准备 SurfaceOutput 的数据
SurfaceOutput o;
//目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0
UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)
o.Normal = i.worldNormal;
然后,我们在UnityLambertLight1中,返回一下diff,看看结果
在片元着色器,返回计算结果
fixed4 c = LightingLambert1(o,gi);
return c;
这是烘培前的效果:
这是烘培后的效果:(我们可以看见已经有基本的光照效果了)
2、准备上图中的 s.Albedo
这个 Albedo 一般是用模型的贴图主纹理采样得到的,在这里我们没有使用,则一般给他赋值为1(不能为0,不然会导致输出的结果为黑色)
以下是修改后的完整代码:
//在这里里面使用 自定义的 cginc 来实现全局GI
//GI数据的准备
//烘培分支的判断
//GI的直接光实现
//GI的间接光实现
Shader "MyShader/P1_8_6"
{SubShader{Tags { "RenderType"="Opaque" }Pass{Tags{"LightMode"="ForwardBase"}CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile DYNAMICLIGHTMAP_ON#pragma multi_compile LIGHTMAP_ON#include "UnityCG.cginc"#include "AutoLight.cginc"#include "Lighting.cginc"#include "CGIncludes/MyGlobalIllumination.cginc"struct appdata{float4 vertex : POSITION;//定义第二套 UV ,appdata 对应的固定语义为 TEXCOORD1#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)float4 lightmapUV : TEXCOORD1;#endifhalf3 normal : NORMAL;};struct v2f{float4 vertex : SV_POSITION;float4 worldPos : TEXCOORD0;//定义第二套UV#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)float4 lightmapUV : TEXCOORD1;#endifhalf3 worldNormal : TEXCOORD2;};v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.worldPos = mul(unity_ObjectToWorld,v.vertex);//对第二套UV进行纹理采样#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)o.lightmapUV.xy = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;#endifo.worldNormal = UnityObjectToWorldNormal(v.normal);return o;}fixed4 frag (v2f i) : SV_Target{//1、准备 SurfaceOutput 的数据SurfaceOutput o;//目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)o.Albedo = 1;o.Normal = i.worldNormal;//2、准备 UnityGIInput 的数据UnityGIInput giInput;//初始化UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput);//修改用到的数据giInput.light.color = _LightColor0;giInput.light.dir = _WorldSpaceLightPos0;giInput.worldPos = i.worldPos;giInput.worldViewDir = normalize(_WorldSpaceCameraPos - i.worldPos);giInput.atten = 1;giInput.ambient = 0;#if defined(DYNAMICLIGHTMAP_ON) || defined(LIGHTMAP_ON)giInput.lightmapUV = i.lightmapUV;#endif//3、准备 UnityGI 的数据UnityGI gi;//直接光照数据(主平行光)gi.light.color = _LightColor0;gi.light.dir = _WorldSpaceLightPos0;//间接光照数据(目前先给0)gi.indirect.diffuse = 0;gi.indirect.specular = 0;LightingLambert_GI1(o,giInput,gi);//我们在得到GI的数据后,对其进行Lambert光照模型计算,即可得到结果fixed4 c = LightingLambert1(o,gi);return c;//return fixed4(gi.indirect.diffuse,1);//return 1;}ENDCG}}
}
这是修改后的效果:
相关文章:

Unity中Shader的GI的直接光实现
文章目录 前言一、在上一篇文章中,得到GI相关数据后,需要对其进行Lambert光照模型计算二、在准备好上面步骤后,我们需要准备缺少的数据1、准备上图中的 s.Normal2、准备上图中的 s.Albedo 前言 Unity中Shader的GI的直接光实现,基…...

JAVA进程和线程
哈喽~大家好呀,这篇来看看JAVA进程和线程。 🥇个人主页:个人主页 🥈 系列专栏:【日常学习上的分享】 🥉与这篇相关的文章: Redis快速入…...
JS自定义深浅度克隆
function deepClone(obj, cache new WeakMap()) {if (typeof obj ! object) return obj //普通类型,直接返回if (obj null) return objif (cache.get(obj)) return cache.get(obj)//防止循环引用,程序进入死循环if (obj instanceof Date) return new D…...

MySQL之表的约束
目录 表的约束1.空属性2.默认值3.列描述4.zerofill5.主键6.自增长7.唯一键8.外键 表的约束 真正约束字段的是数据类型,数据类型规定了数据的用法、范围…假如我们没有按照其规定的约束,那么数据将插入不成功但是数据类型约束很单一,需要有一…...
Go基础——接口、并发
1、接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。接口可以让不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计。Go 语言中的接口是隐式实现…...

zookeeper本地部署和集群搭建
zookeeper(动物园管理员)是一个广泛应用于分布式服务提供协调服务Apache的开源框架 Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它 负责存储和管理大家都关心的数据 ,然 后 接受观察…...
优橙内推甘肃专场——5G网络优化(中高级)工程师
内推公司1:上海井胜通讯技术有限公司 内推公司2:西安长河通讯有限责任公司 内推公司3:沈阳电信工程局 上海井胜通讯技术有限公司 公司成立于2002年,是一家专业移动通信技术服务公司。2008年之前是香港一家大型流动通讯运营公司…...

crontab 定时任务
1.查看 crond 是否开启 systemctl status crond 2.设置 crontab 定时任务 基本语法 #基本语法 crontab [选项] 查看定时任务 #查看定时任务 crontab -l 编辑定时任务 #编辑定时任务 crontab -e 案例实操 */1 * * * * echo "hello,world" >> /root/hel…...

【入门Flink】- 03Flink部署
集群角色 Flik提交作业和执行任务,需要几个关键组件: 客户端(Client):代码由客户端获取并做转换,之后提交给JobManger JobManager:就是Fink集群里的“管事人”,对作业进行中央调度管理;而它获…...

DockerFile常用保留字指令及知识点合集
目录 DockerFile加深理解: DockerFile常用保留字指令 保留字: RUN:容器构建时需要运行的命令 COPY:类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 …...

怎么批量删除文件名中的空格?
怎么批量删除文件名中的空格?当我们整理文件的时候发现文件名里面有一些空格,如果空格较多,可能会造成文件名特别的长,我们一般会随手对文件进行重命名,然后将文件名中的空格删除掉,这项操作非常的简单方便…...

回顾十大数据恢复软件,帮助用于恢复丢失的文件!
您是否因丢失计算机上的重要文件而感到恐慌?你不是一个人!数据丢失是许多人面临的严重问题,但幸运的是,有许多解决方案可以恢复数据。 在本文中,我将回顾十大数据恢复软件,以帮助您恢复丢失的文件…...

【Linux】多路IO复用技术②——poll详解如何使用poll模型实现简易的一对多服务器(附图解与代码实现)
在阅读本篇博客之前,建议大家先去看一下我之前写的这篇博客,否则你很可能会一头雾水 【Linux】多路IO复用技术①——select详解&如何使用select模型在本地主机实现简易的一对多服务器(附图解与代码实现)http://t.csdnimg.cn/…...

CSS 滚动捕获 Scroll Snap
CSS 滚动捕获 Scroll Snap CSS 滚动捕获允许开发者通过声明一些位置(或叫作捕获位置)来创建精准控制的滚动体验. 通常来说轮播图就是这种体验的例子, 在轮播图中, 用户只能停在图 A 或者图 B, 而不能停在 A 和 B 的中间. 比如平时用淘宝或小红书, 当你上滑到下一个推荐内容时…...
【带头学C++】----- 三、指针章 ---- 3.9 数组作为函数的参数
当数组作为函数参数时,有几种常见的方式可以传递数组给函数: 数组作为指针传递: 数组名在函数调用时会自动转换为指向数组第一个元素的指针。通过指针可以访问数组元素,但无法获取数组的大小。在函数中修改指针指向的值会影响原始…...

完美处理 Android App 的 apk 输出路径与文件名
实现代码 buildTypes {// ...applicationVariants.all {variant ->variant.outputs.all {Calendar calendar Calendar.getInstance(Locale.CHINA);def buildDate String.format(Locale.CHINA, "%04d%02d%02d", calendar.get(Calendar.YEAR), calendar.get(Cale…...

【技术干货】开源库 Com.Gitusme.Net.Extensiones.Core 的使用
目录 1、项目介绍 2、为项目添加依赖 3、代码中导入命名空间 4、代码中使用 示例 1:string转换 示例 2:object转换 1、项目介绍 Com.Gitusme.Net.Extensiones.Core是一个.Net扩展库。当前最新版本1.0.4,提供了常见类型转换,…...

大厂面试题-b树和b+树的理解
为了更清晰的解答这个问题,从三个方面来回答: a.了解二叉树、AVL树、B树的概念 b.B树和B树的应用场景 1.B树是一种多路平衡查找树,为了更形象的理解,我们来看这张图。 二叉树,每个节点支持两个分支的树结构ÿ…...

NeRF-SLAM部署运行(3060Ti)
记录在部署运行期间遇到的一些问题,分享给大家~ 一、环境 RTX 3060 Ti、8G显存、Ubuntu18.04 二、部署 1. 下载代码 git clone https://github.com/jrpowers/NeRF-SLAM.git --recurse-submodules git submodule update --init --recursive cd thirdparty/insta…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...