Unity中Shader的间接光的产生Meta Pass

文章目录

  • 前言
    • Unity中Shader的间接光的产生Meta Pass,这也是属于全局光照 GI 的内容。主要实现像现实生活中,光线照到有颜色的物体后,该物体有反射出该颜色的光的效果。
  • 一、我们先使用Unity自带的Shader看看间接光效果
    • 1、先按照如下设置搭建一个场景
    • 2、然后,按下图设置,做一个材质球给小球
    • 3、最后,按下图设置GI,烘焙看一下效果
    • 烘焙前效果:
    • 烘焙后效果:(墙上已经有了间接光的效果)
    • 在这里插入图片描述
  • 二、在我们的Shader中实现间接光的效果
    • 1、在属性面板定义一个颜色属性
    • 2、在Unity自带的Shader中,把名叫 META 的Pass复制到我们的Shader中,该Pass实现了自发光功能
    • 3、因为该Pass一般是在烘焙时完成,所以不影响我们的实时渲染,我们可以不用修改它,我们看一下实现的功能
    • 4、上面在Shader最后加的那句话,我们还有其他方法可以实现同样的修改


前言

Unity中Shader的间接光的产生Meta Pass,这也是属于全局光照 GI 的内容。主要实现像现实生活中,光线照到有颜色的物体后,该物体有反射出该颜色的光的效果。

一、我们先使用Unity自带的Shader看看间接光效果

1、先按照如下设置搭建一个场景

在这里插入图片描述

2、然后,按下图设置,做一个材质球给小球

在这里插入图片描述

3、最后,按下图设置GI,烘焙看一下效果

在这里插入图片描述

烘焙前效果:

在这里插入图片描述

烘焙后效果:(墙上已经有了间接光的效果)

在这里插入图片描述

二、在我们的Shader中实现间接光的效果

继续完成上一篇文章 GI 中的间接光效果

  • Unity中Shader光照探针的支持

这是没有实现间接光前的烘焙效果

在这里插入图片描述

1、在属性面板定义一个颜色属性

Properties
{
_Color(“Color”,Color) = (1,1,1,1)
}

2、在Unity自带的Shader中,把名叫 META 的Pass复制到我们的Shader中,该Pass实现了自发光功能

在这里插入图片描述

//在正常的渲染时,是不会被使用的。一般用于烘焙时,计算间接光反弹// Extracts information for lightmapping, GI (emission, albedo, ...)// This pass it not used during regular rendering.Pass{Name "META"Tags{"LightMode" = "Meta"}CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 2.0#include "UnityCG.cginc"#include "UnityMetaPass.cginc"struct v2f{float4 pos : SV_POSITION;float2 uvMain : TEXCOORD0;float2 uvIllum : TEXCOORD1;#ifdef EDITOR_VISUALIZATIONfloat2 vizUV : TEXCOORD2;float4 lightCoord : TEXCOORD3;#endifUNITY_VERTEX_OUTPUT_STEREO};float4 _MainTex_ST;float4 _Illum_ST;v2f vert(appdata_full v){v2f o;UNITY_SETUP_INSTANCE_ID(v);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);o.pos = UnityMetaVertexPosition(v.vertex, v.texcoord1.xy, v.texcoord2.xy, unity_LightmapST,unity_DynamicLightmapST);o.uvMain = TRANSFORM_TEX(v.texcoord, _MainTex);o.uvIllum = TRANSFORM_TEX(v.texcoord, _Illum);#ifdef EDITOR_VISUALIZATIONo.vizUV = 0;o.lightCoord = 0;if (unity_VisualizationMode == EDITORVIZ_TEXTURE)o.vizUV = UnityMetaVizUV(unity_EditorViz_UVIndex, v.texcoord.xy, v.texcoord1.xy, v.texcoord2.xy, unity_EditorViz_Texture_ST);else if (unity_VisualizationMode == EDITORVIZ_SHOWLIGHTMASK){o.vizUV = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;o.lightCoord = mul(unity_EditorViz_WorldToLight, mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1)));}#endifreturn o;}sampler2D _MainTex;sampler2D _Illum;fixed4 _Color;fixed _Emission;half4 frag(v2f i) : SV_Target{UnityMetaInput metaIN;UNITY_INITIALIZE_OUTPUT(UnityMetaInput, metaIN);fixed4 tex = tex2D(_MainTex, i.uvMain);fixed4 c = tex * _Color;metaIN.Albedo = c.rgb;metaIN.Emission = c.rgb * tex2D(_Illum, i.uvIllum).a;#if defined(EDITOR_VISUALIZATION)metaIN.VizUV = i.vizUV;metaIN.LightCoord = i.lightCoord;#endifreturn UnityMetaFragment(metaIN);}ENDCG}

注意:如果此时没有显示出烘焙的间接光,则在该Shader最后加上这句话

CustomEditor “LegacyIlluminShaderGUI”

在这里插入图片描述

3、因为该Pass一般是在烘焙时完成,所以不影响我们的实时渲染,我们可以不用修改它,我们看一下实现的功能

1、这个是实现该功能的主要函数,一般不做修改因为不影响我们实时渲染
在这里插入图片描述

2、UnityMetaInput 中主要有的数据
间接光一般考虑:物体的反射率,物体的自发光,物体的高光色

在这里插入图片描述
3、删除一些不用的功能,按需求来

v2f保留:

struct v2f
{
float4 pos : SV_POSITION;
};

顶点着色器保留:

v2f vert(appdata_full v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f,o)
o.pos = UnityMetaVertexPosition(v.vertex, v.texcoord1.xy, v.texcoord2.xy, unity_LightmapST,
unity_DynamicLightmapST);
return o;
}

片元着色器保留:

half4 frag(v2f i) : SV_Target
{
UnityMetaInput metaIN;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, metaIN);
metaIN.Albedo = 1;
metaIN.Emission = _Color;
return UnityMetaFragment(metaIN);
}

4、上面在Shader最后加的那句话,我们还有其他方法可以实现同样的修改

CustomEditor “LegacyIlluminShaderGUI”

在这里插入图片描述

1、首先,把 Inspect 窗口修改为Debug模式

在这里插入图片描述

2、修改材质球的这个值,实现和上面那串代码同样的效果
在这里插入图片描述

最后,修改该值为2,就可以看见最后的效果了

在这里插入图片描述

最终代码:

//在这里里面使用 自定义的 cginc 来实现全局GI
//GI数据的准备
//烘培分支的判断
//GI的直接光实现
//GI的间接光实现
//再议ATTENUATION
//光照探针的支持
//间接光的产生Meta Pass
Shader "MyShader/P1_8_9"
{Properties{_Color("Color",Color) = (1,1,1,1)}SubShader{Tags{"RenderType"="Opaque"}Pass{Tags{"LightMode"="ForwardBase"}CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#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 texcoord1 : TEXCOORD1;#endifhalf3 normal : NORMAL;float4 texcoord2 : TEXCOORD2;};struct v2f{float4 pos : SV_POSITION;float4 worldPos : TEXCOORD;//定义第二套UV#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)float4 lightmapUV : TEXCOORD1;#endifhalf3 worldNormal : NORMAL;half3 sh : TEXCOORD2;//1、使用 阴影采样 和 光照衰减的方案的 第一步//同时定义灯光衰减以及实时阴影采样所需的插值器UNITY_LIGHTING_COORDS(3, 4)//UNITY_SHADOW_COORDS(2)};v2f vert(appdata v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.worldPos = mul(unity_ObjectToWorld, v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);//对第二套UV进行纹理采样#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)o.lightmapUV.xy = v.texcoord1 * unity_LightmapST.xy + unity_LightmapST.zw;#endif//实现 球谐 或者 环境色 和 顶点照明 的计算//SH/ambient and vertex lights#ifndef LIGHTMAP_ON //当此对象没有开启静态烘焙时#if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXELo.sh = 0;//近似模拟非重要级别的点光在逐顶点上的光照效果#ifdef VERTEXLIGHT_ONo.sh += Shade4PointLights(unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0,unity_LightColor[0].rgb,unity_LightColor[1].rgb,unity_LightColor[2].rgb,unity_LightColor[3].rgb,unity_4LightAtten0,o.worldPos,o.worldNormal);#endifo.sh = ShadeSHPerVertex(o.worldNormal,o.sh);#endif#endif//2、使用 阴影采样 和 光照衰减的方案的 第二步UNITY_TRANSFER_LIGHTING(o, v.texcoord2.xy)//TRANSFER_SHADOW(o)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;//1、代表灯光的衰减效果//2、实时阴影的采样UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);//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 = atten;giInput.ambient = 0;#if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXELgiInput.ambient = i.sh;#elsegiInput.ambient = 0.0;#endif#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;//GI的间接光照的计算 LightingLambert_GI1(o, giInput, gi);//查看Unity源码可知,计算间接光照最主要的函数就是//inline UnityGI UnityGI_Base1(UnityGIInput data, half occlusion, half3 normalWorld)//所以我们直接给 gi 赋值,可以不使用 LightingLambert_GI1gi = UnityGI_Base1(giInput, 1, o.Normal);//GI的直接光照的计算//我们在得到GI的数据后,对其进行Lambert光照模型计算,即可得到结果fixed4 c = LightingLambert1(o, gi);return c;//return fixed4(gi.indirect.diffuse,1);//return 1;}ENDCG}//阴影的投射Pass{//1、设置 "LightMode" = "ShadowCaster"Tags{"LightMode" = "ShadowCaster"}CGPROGRAM#pragma vertex vert#pragma fragment frag//需要添加一个 Unity变体#pragma multi_compile_shadowcaster#include "UnityCG.cginc"//声明消融使用的变量float _Clip;sampler2D _DissolveTex;float4 _DissolveTex_ST;//2、appdata中声明float4 vertex:POSITION;和half3 normal:NORMAL;这是生成阴影所需要的语义.//注意:在appdata部分,我们几乎不要去修改名字 和 对应的类型。//因为,在Unity中封装好的很多方法都是使用这些标准的名字struct appdata{float4 vertex:POSITION;half3 normal:NORMAL;float4 uv:TEXCOORD;};//3、v2f中添加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据.struct v2f{float4 uv : TEXCOORD;V2F_SHADOW_CASTER;};//4、在顶点着色器中添加TRANSFER_SHADOW_CASTER_NORMALOFFSET(o),主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象.v2f vert(appdata v){v2f o;o.uv.zw = TRANSFORM_TEX(v.uv, _DissolveTex);TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);return o;}//5、在片断着色器中添加SHADOW_CASTER_FRAGMENT(i)fixed4 frag(v2f i) : SV_Target{//外部获取的 纹理 ,使用前都需要采样fixed4 dissolveTex = tex2D(_DissolveTex, i.uv.zw);//片段的取舍clip(dissolveTex.r - _Clip);SHADOW_CASTER_FRAGMENT(i);}ENDCG}//在常规的渲染时,是不会被使用的。一般使用时,是在烘焙贴图// Extracts information for lightmapping, GI (emission, albedo, ...)// This pass it not used during regular rendering.Pass{Name "META"Tags{"LightMode" = "Meta"}CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 2.0#include "UnityCG.cginc"#include "UnityMetaPass.cginc"fixed4 _Color;struct v2f{float4 pos : SV_POSITION;};v2f vert(appdata_full v){v2f o;UNITY_INITIALIZE_OUTPUT(v2f,o)o.pos = UnityMetaVertexPosition(v.vertex, v.texcoord1.xy, v.texcoord2.xy, unity_LightmapST,unity_DynamicLightmapST);return o;}half4 frag(v2f i) : SV_Target{UnityMetaInput metaIN;UNITY_INITIALIZE_OUTPUT(UnityMetaInput, metaIN);metaIN.Albedo = 1;metaIN.Emission = _Color;return UnityMetaFragment(metaIN);}ENDCG}}CustomEditor "LegacyIlluminShaderGUI"
}

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

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

相关文章

8年经验之谈 —— 记一次接口压力测试与性能调优!

经验总结 1. 如果总的CPU占用率偏高,且基本都被业务线程占用时,CPU占用率过高的原因跟JVM参数大小没有直接关系,而跟具体的业务逻辑有关。 2. 当设置JVM堆内存偏小时,GC频繁会导致业务线程停顿增多,TPS下降&#xff…

基于SSM的考研图书电子商务平台的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

链动2+1模式系统开发之区域代理深度解析

区域代理的保护机制:在链动商城系统里设定的代理有唯一性,每个省只有一个省代,每个市只有一个市代,每个区县只有一个区县代。这样也是保护每个代理的收益权益。 区域代理包含的权益类别:购物奖励折扣;区域实…

Python实现猎人猎物优化算法(HPO)优化XGBoost回归模型(XGBRegressor算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的…

Marin说PCB之 PCB封装和原理图封装的藕断丝连

最近天气开始降温了,小编我不得不拿出珍藏多年的秋裤穿上了,就是走路不太方便,有点紧啊,可能是当时衣服尺码买小了吧,不可能是我吃胖了,这个绝对不可能。 话说小编我今年属实有点走霉运啊,下班和…

计网自顶向下(Web服务器+UDPping+邮件客户端)

目录 🐖前言 🌼Web服务器(作业1) 🌳过程 🌳解释 🔥代码 🌼UDPping程序(作业2) 🌳过程 🌳解释 Client Server 整体逻辑 🔥代码 🌼邮件客户端(作业…

ChineseChess.2023.11.13.01

中国象棋残局模拟器ChineseChess.2023.11.13.01

正交矩阵的定义

对于n阶矩阵A,如果,其中为单位矩阵,为A的转置矩阵,那么就称A为正交矩阵。 对于正交矩阵, 对于正交矩阵,其列向量都是单位向量,行向量都是单位向量

【matlab】KMeans KMeans++实现手写数字聚类

目录 matlab代码kmeans matlab代码kmeans MNIST DATABASE下载网址: http://yann.lecun.com/exdb/mnist/ 聚类 将物理或抽象对象的集合分成由类似特征组成的多个类的过程称为聚类(clustering)。 对于给定N个n维向量x1,…,xN∈Rn,聚类的目标…

亚马逊云科技Zero ETL集成全面可用,可运行近乎实时的分析和机器学习

亚马逊云科技数据库、数据分析和机器学习全球副总裁Swami Sivasubramanian曾指出:“数据是应用、流程和商业决策的核心。”如今,客户常用的数据传输模式是建立从Amazon Aurora到Amazon Redshift的数据管道。这些解决方案能够帮助客户获得新的见解&#x…

通讯协议学习之路(实践部分):SPI开发实践

通讯协议之路主要分为两部分,第一部分从理论上面讲解各类协议的通讯原理以及通讯格式,第二部分从具体运用上讲解各类通讯协议的具体应用方法。 后续文章会同时发表在个人博客(jason1016.club)、CSDN;视频会发布在bilibili(UID:399951374) 本文…

Spring的Redis客户端

如何在Spring中操作redis 在创建springboot项目的时候引入redis的依赖. 在配置文件里指定redis主机的地址和端口,此处我们配置了ssh隧道,所以连接的就是本机的8888端口. 创建一个controller类,注入操作redis的对象. 前面使用jedis,是通过jedis对象里的各种方法来操作redis的,此…

Ionic组件 ion-list ion-list-header

1 ion-list 列表由多行项目组成,这些项目可以包含 text, buttons, toggles, icons, thumbnails等。列表通常包含具有类似数据内容的项目,如 images and text。 列表支持多种交互,包括滑动项目以显示选项、拖动以重新排列列表中的项目以及删除…

MySQL表的增删改查(进阶)

目录 数据库约束 约束的定义 约束类型 null约束 unique:唯一约束 default:默认值约束 primary key:主键约束(重要) foreign key:外键约束(描述两个表之间的关联) 表的设计 一般思路 三大范式 一对一 一对多 ​编辑 多对多 ​编辑 新增 查询 聚合查询 聚合函…

Ridgeline plot / 远山图 / 山脊图 怎么画?怎么优化?

工具 Origin 2022 当然,用Matlab、Python也是可以的。 颜色配置 色卡调整

GEE:将鼠标变成十字指针,点击获取影像值,显示值到UI中

作者:CSDN _养乐多_ 本文记录了在 Google Earth Engine(GEE)开发中,将鼠标变成十字指针,点击获取影像值,显示值到UI中的代码片段。这段代码复制过去修改变量名就可以用了。 效果如下图所示, …

Transformer详解一:transformer的由来和先导知识

目录 参考资料前言一、预训练二、神经网络语言模型(NNLM):预测下一个词one-hot编码的缺陷词向量(word embedding) 三、Word2Vec模型:得到词向量CBOWSkip-gramWord2Vec和NNLM的区别Word2Vec的缺陷 四、ELMO模…

Python---练习:把8名讲师随机分配到3个教室

案例:把8名讲师随机分配到3个教室 列表嵌套:有3个教室[[],[],[]],8名讲师[A,B,C,D,E,F,G,H],将8名讲师随机分配到3个教室中。 分析: 一步步来解决。 首先, 要求有3个教室,第一间教室、第二间…

微信小程序真机调试连接状态一直在正常和未链接之间反复横跳?

背景:小程序真机调试的时候,发现真机的network不显示接口调用情况,控制台也没有输出内容。具体如下所示; 解决方法: 1、确保手机端连接的网络和微信开发者工具网络一致,比如用同一个WiFi 2、真机自动调试…

Ubuntu 22.04源码安装cmake 3.27.7

安装参考博客是《ubuntu安装cmake》和《Ubuntu 安装CMake》。 https://cmake.org/download是cmake官网下载的网址。 sudo wget -c https://github.com/Kitware/CMake/releases/download/v3.27.7/cmake-3.27.7.tar.gz可以下载源码,最后显示‘cmake-3.27.7.tar.gz’…