Unity中Shader光照探针的支持

news2024/11/26 12:32:03

文章目录

  • 前言
  • 一、光照探针用在哪怎么用
    • 1、光照探针的应用场景
    • 2、我们按照以上条件,在Unity中搭建一个相同的环境
    • 3、创建光照探针
  • 二、在我们自己的Shader中,实现支持光照探针
    • 1、使用常用的 cginc
    • 2、在 v2f 中,准备如下变量
    • 3、在顶点着色器中,进行顶点和法线世界空间的转化后,使用如下代码
    • 4、在片元着色器中,使用如下代码计算
    • 最终代码


前言

主要写全局照明中,光照探针的支持


一、光照探针用在哪怎么用

1、光照探针的应用场景

在一个只有 Backed 模式灯光的场景中,有一个非静态的物体
即该物体在烘焙时,不会被烘焙,不会受到烘焙灯光的影响。

但是,我们此时不能修改灯光的模式 也不能修改该物体为静态物体
却需要给该动态物体受到烘焙灯光的影响
此时就需要使用光照探针了

2、我们按照以上条件,在Unity中搭建一个相同的环境

在这里插入图片描述
我们会发现,小球在烘焙后是不受烘焙光的影响的
请添加图片描述

3、创建光照探针

可以直接在一个空物体添加 Light Probe Group,也按下图直接添加光照探针
在这里插入图片描述

添加后,把光照探针的范围设置到,要让动态小球接收到烘焙光影响的范围
在光照探针中,黄色小点点在空间内越密集越多,动态物体接收到的烘焙光越精致细腻
在这里插入图片描述

然后,我们烘焙后就可以看见小球能接收烘焙光的效果了
请添加图片描述


二、在我们自己的Shader中,实现支持光照探针

我们继续使用之前的文章作为测试

  • Unity中Shader再议ATTENUATION

我们会发现我们的 Shader在使用后是全黑的
因为我们关闭了主平行光,两个点光源又是Backed类
在这里插入图片描述

1、使用常用的 cginc

#include “AutoLight.cginc”
#include “Lighting.cginc”

2、在 v2f 中,准备如下变量

float4 worldPos : TEXCOORD;
half3 worldNormal : NORMAL;
half3 sh : TEXCOORD2;

3、在顶点着色器中,进行顶点和法线世界空间的转化后,使用如下代码

//实现 球谐 或者 环境色 和 顶点照明 的计算
//SH/ambient and vertex lights
#ifndef LIGHTMAP_ON //当此对象没有开启静态烘焙时
#if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
     o.sh = 0;
     //近似模拟非重要级别的点光在逐顶点上的光照效果
     #ifdef VERTEXLIGHT_ON
			o.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);
    #endif
    o.sh = ShadeSHPerVertex(o.worldNormal,o.sh);
#endif
#endif

4、在片元着色器中,使用如下代码计算

#if UNITY_SHOULD_SAMPLE_SH && !UNITY_SAMPLE_FULL_SH_PER_PIXEL
	giInput.ambient = i.sh;
#else
	giInput.ambient = 0.0;
#endif

然后,我们就可以看见我们的Shader也有光照探针的效果了

请添加图片描述

同时,也有了逐顶点光照的效果
请添加图片描述

最终代码

//在这里里面使用 自定义的 cginc 来实现全局GI
//GI数据的准备
//烘培分支的判断
//GI的直接光实现
//GI的间接光实现
//再议ATTENUATION
//光照探针的支持
Shader "MyShader/P1_8_8"
{
    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;
                #endif
                half3 normal : NORMAL;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                
                float4 worldPos : TEXCOORD;
                //定义第二套UV
                #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                float4 lightmapUV : TEXCOORD1;
                #endif
                half3 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_PIXEL
                    o.sh = 0;
                    //近似模拟非重要级别的点光在逐顶点上的光照效果
                    #ifdef VERTEXLIGHT_ON
                        o.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);
                    #endif
                    o.sh = ShadeSHPerVertex(o.worldNormal,o.sh);
                #endif
                #endif
                
                
                //2、使用 阴影采样 和 光照衰减的方案的 第二步
                UNITY_TRANSFER_LIGHTING(o,v.texcoord1.xy)
                //TRANSFER_SHADOW(o)
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //1、准备 SurfaceOutput 的数据
                SurfaceOutput o;
                //目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0
                UNITY_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_PIXEL
                    giInput.ambient = i.sh;
                #else
                    giInput.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_GI1
                gi = 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
        }
    }
}

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

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

相关文章

2023年【安全员-B证】新版试题及安全员-B证免费试题

题库来源:安全生产模拟考试一点通公众号小程序 安全员-B证新版试题参考答案及安全员-B证考试试题解析是安全生产模拟考试一点通题库老师及安全员-B证操作证已考过的学员汇总,相对有效帮助安全员-B证免费试题学员顺利通过考试。 1、【多选题】下列哪些属…

云表:“智、数”结合,低代码赋能制造业,入局者赢

在数智时代,智能制造正崭露头角,它借助先进的信息技术和数据分析工具,将制造业与人工智能紧密结合,推动生产过程的智能化和自动化。通过大数据、云计算、物联网等前沿技术,智能制造实现了生产线的高效、灵活、可定制的…

文件加密软件怎么用(附2种解密破解工具)

有时候出差或者有些商务场合,需要对一些敏感文件做一下简单的加密,这样在分享内容的时候,可以起到初步的保护作用。 当然了,如果文件非常重要,涉及到一些商业机密,这个时候你需要使用专业的加密工具&#x…

陳烨(本烨)老师受聘為香港國學發展研究院客座教授

香港國學發展研究院有幸宣布,中華傳統文化學者陳烨女士已正式受聘為學院的客座教授。陳烨女士是一位備受尊敬的學者,在中華傳統道學文化領域擁有廣泛的知識和卓越的學術成就。   陳烨女士是中華傳統道學文化領域的知名專家。她不僅在教學方面積累了豐富…

挑战100天 AI In LeetCode Day07(热题+面试经典150题)

挑战100天 AI In LeetCode Day07(热题面试经典150题) 一、LeetCode介绍二、LeetCode 热题 HOT 100-92.1 题目2.2 题解 三、面试经典 150 题-93.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站,提供各种算法和数据结构的题目&am…

2023禁用谷歌浏览器自动更新最好的解决方式

🧁介绍 对于一些用户来说,Chrome 浏览器的自动更新功能可能会带来一些不便或者不必要的麻烦。 本文将介绍如何使用批处理脚本来停止和禁用 Chrome 的自动更新功能,确保不再进行后台网络操作。文章将详细说明代码的编写和执行步骤。 &#…

FastReport 2023.1.3 基于源码原版本升级 Delphi 12 c++ builder 12

复制 RAD Studio 10.4 为RAD Studio 12 dpk 文本打开 28 改成 29 Build -> install就可以了

福州等保测评机构有几家?正规吗?在哪里?

最近看到不少福州小伙伴在问,福州等保测评机构有几家?正规吗?在哪里?这里小编就给大家来详细解答一下,仅供参考哦! 福州等保测评机构有几家?正规吗?在哪里? 【回答】&…

windows系统自动更新中断电导致系统无法开启

windows系统自动更新中断电导致系统无法开启 现象原因解决进入bios拆机更新系统重新安装内存条 现象 前一天晚上电脑出现合上之后风扇继续转的现象,拔掉电源后,第二天开不了机。现象为按压电源键,电源键和充电指示灯亮一次后熄灭&#xff0c…

docker 构建并运行 python项目

此处不重述docker安装及基本命令,可参考另一篇文章centos7 安装 docker_centos7 docker network rm-CSDN博客文章浏览阅读111次。1、 1.1 docker 官网 Empowering App Development for Developers | DockerLearn how Docker helps developers bring their ideas to …

SSM 线上知识竞赛系统-计算机毕设 附源码 27170

SSM线上知识竞赛系统 摘 要 科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。在现实运用中&#…

从哪些方面做好电商系统的网站建设?

电子商务的迅猛发展,建设一款成功的电商系统网站成为企业取得竞争优势的重要一环。下面将从用户体验、网站设计、安全性和性能优化等方面,介绍如何打造一款优秀的电商系统网站。 一、用户体验 一款成功的电商系统网站必须注重用户体验,确保用…

Note1: 算法的时间复杂度和空间复杂度

目录 ---前言 1.算法效率 1.1 算法的复杂度 2.时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.3常见时间复杂度计算举例 2.3.1 示例1 2.3.2 示例2 2.3.3 示例3 2.3.4 示例4 2.3.5 示例5 2.3.6 示例6 2.3.7 示例7 2.3.8 示例8 3.空间复杂度 3.1 示例1 …

安装软件时msvcp140.dll丢失的解决方法,快速解决dll问题

在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是“msvcp140.dll丢失”。msvcp140.dll是微软Visual C 2015运行库中的一个组件,它包含了许多用于支持C编程语言的函数和类。当我们在使用某些需要依赖这个运行库的程序时&#xff0…

打卡系统有什么用?如何通过日常管理系统提高企业员工的效率?

在当今快速发展的时代,职工的行动管理已成为机构单位工作中至关重要的一环。如何更好地了解和掌握职工的日程安排和行动轨迹,成为了一个值得探讨的问题。为了解决这一难题,“的修”打卡系统应运而生,它为我们提供了一个全面而高效…

跨境卖家必备的自养号测评技巧:提升商品评论数量和销量

无论是亚马逊还是拼多多Temu、shopee、Lazada、wish、速卖通、煤炉、敦煌、独立站、雅虎、eBay、TikTok、Newegg、Allegro、乐天、美客多、阿里国际、沃尔玛、OZON、Joom、Facebook、daraz、Cdiscount、Kaufland、DARTY、MANO、Shein、Jumia、eMAG、Fnac、Onbuy、Fruugo、等跨境…

在线判断代理是否生效

在线网站 http://www.zhizhi365.com/ 数据

日料西餐厅餐品预约小程序的作用是什么

日料店西餐厅客源也不少,对经营者来说,高市场需求度的同时也面临一些痛点: 1、品牌宣传拓客难 日料/西餐厅虽然已经存在多年,但依然有大量用户并没有消费过,因此这需要商家不断拓展品牌实力及餐品呈现吸引客户前往&a…

微信管理系统:让企业更轻松地管理客户和员工资源

在日常工作中,我们经常遇到以下问题: ①由于微信号众多,需要频繁地在不同设备之间切换,这严重影响了工作效率。 ②尽管我一直努力回复客户的消息,但有时还是无法做到即时回复,这给客户带来了一些不便。 …

浙大软院2024届推免录取名单及分析

名单 分析 浙大软院共录取电子信息专业推免生219人,机械专业推免生20人 小Tips:浙大软院夏令营考核时间比较长,并且不发offer,但是如果夏令营能拿到优营能够直入预推免哦,以浙大为梦校并且背景不是特别好的同学可以多…