Unity中Shader的GI相关数据的准备

news2024/11/28 23:39:50

文章目录

  • 前言
  • 一、把 Unity 中用到的 GI 的函数移植到我们自定义的 cginc 文件中
  • 二、开始使用和 GI 相关的方法
    • 1、了解 UnityGI 结构体的内容,并且准备 UnityGI 的数据
    • 2、了解 SurfaceOutput 结构体,并且准备数据
    • 3、了解并准备 UnityGIInput 结构体,并且准备其相关数据
    • 这是目前准备完 GI 数据的代码


前言

Unity中Shader的GI相关数据的准备,这是基于上一篇文章中的自定义 cginc 文件的基础上续写的,主要是要把在 GI 中用到的 cginc 库,整合到自己的 cginc 文件中。

  • Unity中Shader自定义cginc文件

一、把 Unity 中用到的 GI 的函数移植到我们自定义的 cginc 文件中

在这里插入图片描述

我们复制过来后,可以发现缺少一些相关的函数 和 类型,我们需要依次找到后,复制在该函数上方,因为 CG 不像C#一样可以读取到后面定义的函数

在这里插入图片描述

下面是依次解决完没有引入方法、结构体后的 代码:(在方法后加1,是为了和Unity自带方法区别开)

#ifndef MYGLOBALILLUMINATION_INCLUDE
#define MYGLOBALILLUMINATION_INCLUDE


inline void ResetUnityLight1(out UnityLight outLight)
{
    outLight.color = half3(0, 0, 0);
    outLight.dir = half3(0, 1, 0); // Irrelevant direction, just not null
    outLight.ndotl = 0; // Not used
}

inline void ResetUnityGI1(out UnityGI outGI)
{
    ResetUnityLight1(outGI.light);
    outGI.indirect.diffuse = 0;
    outGI.indirect.specular = 0;
}

inline UnityGI UnityGI_Base1(UnityGIInput data, half occlusion, half3 normalWorld)
{
    UnityGI o_gi;
    ResetUnityGI1(o_gi);

    // Base pass with Lightmap support is responsible for handling ShadowMask / blending here for performance reason
    #if defined(HANDLE_SHADOWS_BLENDING_IN_GI)
        half bakedAtten = UnitySampleBakedOcclusion(data.lightmapUV.xy, data.worldPos);
        float zDist = dot(_WorldSpaceCameraPos - data.worldPos, UNITY_MATRIX_V[2].xyz);
        float fadeDist = UnityComputeShadowFadeDistance(data.worldPos, zDist);
        data.atten = UnityMixRealtimeAndBakedShadows(data.atten, bakedAtten, UnityComputeShadowFade(fadeDist));
    #endif

    o_gi.light = data.light;
    o_gi.light.color *= data.atten;

    #if UNITY_SHOULD_SAMPLE_SH
        o_gi.indirect.diffuse = ShadeSHPerPixel(normalWorld, data.ambient, data.worldPos);
    #endif

    #if defined(LIGHTMAP_ON)
        // Baked lightmaps
        half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
        half3 bakedColor = DecodeLightmap(bakedColorTex);

        #ifdef DIRLIGHTMAP_COMBINED
            fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER (unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);
            o_gi.indirect.diffuse += DecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);

            #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
                ResetUnityLight(o_gi.light);
                o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap (o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
            #endif

        #else // not directional lightmap
            o_gi.indirect.diffuse += bakedColor;

            #if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
                ResetUnityLight(o_gi.light);
                o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
            #endif

        #endif
    #endif

    #ifdef DYNAMICLIGHTMAP_ON
        // Dynamic lightmaps
        fixed4 realtimeColorTex = UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, data.lightmapUV.zw);
        half3 realtimeColor = DecodeRealtimeLightmap (realtimeColorTex);

        #ifdef DIRLIGHTMAP_COMBINED
            half4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, data.lightmapUV.zw);
            o_gi.indirect.diffuse += DecodeDirectionalLightmap (realtimeColor, realtimeDirTex, normalWorld);
        #else
            o_gi.indirect.diffuse += realtimeColor;
        #endif
    #endif

    o_gi.indirect.diffuse *= occlusion;
    return o_gi;
}

inline UnityGI UnityGlobalIllumination1 (UnityGIInput data, half occlusion, half3 normalWorld)
{
    return UnityGI_Base1(data, occlusion, normalWorld);
}

inline void LightingLambert_GI1 (SurfaceOutput s,UnityGIInput data,inout UnityGI gi)
{
    gi = UnityGlobalIllumination1 (data, 1.0, s.Normal);
}

#endif

二、开始使用和 GI 相关的方法

1、了解 UnityGI 结构体的内容,并且准备 UnityGI 的数据

因为 GI = 直接光照 + 间接光照,所以UnityGI中的内容是存储一些相关的信息

在这里插入图片描述

准备 UnityGI 的数据

	//3、准备 UnityGI 的数据
    UnityGI gi;
    //直接光照数据(主平行光)
    gi.light.color = _LightColor0;
    gi.light.dir = _WorldSpaceLightPos0;
    //间接光照数据(目前先给0)
    gi.indirect.diffuse = 0;
    gi.indirect.specular = 0;

2、了解 SurfaceOutput 结构体,并且准备数据

该结构体主要存储 和物体表面相关的主要信息

在这里插入图片描述

准备 SurfaceOutput 数据

	//1、准备 SurfaceOutput 的数据
    SurfaceOutput o;
    //目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0
    UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)

3、了解并准备 UnityGIInput 结构体,并且准备其相关数据

主要是用来计算 GI 的相关数据

在这里插入图片描述

准备UnityGIInput数据

	//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;
    //giInput.lightmapUV = ?

这是目前准备完 GI 数据的代码

//在这里里面使用 自定义的 cginc 来实现全局GI
Shader "MyShader/P1_8_2"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #include "CGIncludes/MyGlobalIllumination.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 worldPos : TEXCOORD0;
            };
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);
                
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //1、准备 SurfaceOutput 的数据
                SurfaceOutput o;
                //目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0
                UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)

                //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;
                //giInput.lightmapUV = ?

                
                //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);
                return 1;
            }
            ENDCG
        }
    }
}

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

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

相关文章

Flutter笔记:发布一个模块 scale_design - (移动端)设计师尺寸适配工具

Flutter笔记 发布一个模块scale_design设计师尺寸适配工具与常用组件库 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:https://blog.csdn.net/qq_28550263/a…

词向量模型Word2Vec

Word2Vec CBOW连续词袋模型例子CBOW模型的embeddings层CBOW模型的线性层 总结 skip-gram跳字模型例子Skip-Gram模型的结构 CBOW和skip-gram的目标都是迭代出词向量字典(嵌入矩阵)——embeddings CBOW连续词袋模型 根据上下文词汇预测目标词汇 例子 使…

【FastCAE源码阅读3】几何模型显示:从OCC对象到VTK对象

从几何到显示还是比较麻烦的,需要将几何对象转换成渲染对象,涉及几何建模、面的三角化、图形渲染等学科,阅读本文需了解一些基本的OCC、VTK编程 一、几何体显示基本流程 FastCAE几何内核使用的是OCC,显示渲染用的VTK,…

Leetcode—111.二叉树的最小深度【简单】

2023每日刷题(十八) Leetcode—111.二叉树的最小深度 DFS实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ int minDepth(struct TreeNode* root…

NCL颜色索引表---全平台可用

NCL颜色索引表—全平台可用

三维向量旋转

三维向量旋转 问题描述问题分析 v ⃗ ∣ ∣ \vec{v}_{||} v ∣∣​的旋转 v ⃗ ⊥ \vec{v}_{\bot} v ⊥​的旋转 v ⃗ \vec{v} v 的旋转结论致谢 问题描述 如图1所示,设一个向量 v ⃗ \vec{v} v 绕另一个向量 u ⃗ [ x , y , z ] T \vec{u}[x,y,z]^{T} u [x,y,z]T…

【电路笔记】-相位差和相移

相位差和相移 文章目录 相位差和相移1、概述2、相位差2.1 同频信号2.2 电流与电压信号2.3 相似频率的信号 3、干扰4、总结 当我们听歌曲时,我们将正弦声音波形感知为音乐。 它们的振幅告诉我们信号有多大,频率告诉我们声音是低音还是高音。 然而&#xf…

vue学习part01

02_Vue简介_哔哩哔哩_bilibili Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org) 1.简介 2.常用用法 新项目一般vue3,老项目vue2 3.vue两种风格:选项式api(vue2)和组合式api(vue3) 两种方式实现累…

JS异常处理——throw和try、catch以及debugger

让我为大家介绍一下异常处理吧! 异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行 throw 抛异常 第一种写法 function fun(x, y) {// undefined是false 但取反就是trueif (!x || !y) {// 第一种写…

实习记录--(海量数据如何判重?)--每天都要保持学习状态和专注的状态啊!!!---你的未来值得你去奋斗

海量数据如何判重? 判断一个值是否存在?解决方法: 1.使用哈希表: 可以将数据进行哈希操作,将数据存储在相应的桶中。 查询时,根据哈希值定位到对应的桶,然后在桶内进行查找。这种方法的时间复…

在线词典项目-项目介绍及框架搭建

项目介绍 通过代码实现词典的注册、登录、单词注释查询、历史查询、查询记录。 有道词典分析图 客户端流程图 注释:首先开始-->创建流式套接字-->连接服务器-->输入需要执行的命令代码-->创建循环,判断需要执行的函数(如果登录…

基于深度学习的行人重识别(person reid) 计算机竞赛

文章目录 0 前言1 技术背景2 技术介绍3 重识别技术实现3.1 数据集3.2 Person REID3.2.1 算法原理3.2.2 算法流程图 4 实现效果5 部分代码6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学习的行人重识别 该项目较为新颖,适合…

AIGC | 如何用“Flow”,轻松解决复杂业务问题

随着LLM(大语言模型)的爆火,不少企业都在寻找通过LLM解决企业业务问题的方法,以达到降本增效的效果。但是,当面对较为复杂的业务问题(如:背景资料多、问题分类多、条件判断复杂、涉及模块多等&a…

Java高级互联网架构师之路:垃圾回收器的介绍

本文重点 从本文开始我们将开启垃圾回收器的介绍了,我们知道垃圾回收算法是逻辑改变,而垃圾回收器是具体的实现。我们前面介绍的垃圾回收器有7个,本文将在添加三个,但是这三个目前来看不是很常用,我们只了解一下,我们主要还是讲解这7个垃圾回收器。 十个垃圾回收器 目…

天空卫士为集度智能汽车系上“安全带”

10月27日,集度汽车在北京正式发布了旗下首款量产车型——极越 01 SUV。极越 01 SUV 是一款集科技、智能、美学于一身的纯电动中大型SUV,号称全球首款“AI 汽车机器人”。作为集度的合作伙伴,天空卫士第一时间送上祝福,祝愿极越大卖…

鸿蒙应用开发取消标题栏

在config.json中的module下添加如下内容: "metaData": {"customizeData": [{"name": "hwc-theme","extra": "","value": "androidhwext:style/Theme.Emui.Light.NoTitleBar"}] }…

深度学习_4 数据训练之线性回归

训练数据 线性回归 基本原理 比如我们要买房,机器学习深度学习来预测房价。房价的影响因素有:卧室数量,卫生间数量,居住面积。此外,还需要加上偏差值来计算。我们要找到一个正确率高的计算方法来计算。 首先&#…

web3 React dapp中编写balance组件从redux取出并展示用户资产

好啊 上文WEB3 在 React搭建的Dapp中通过redux全局获取并存储用户ETH与自定义token与交易所存储数量中 我们拿到了用户的一个本身 和 交易所token数量 并放进了redux中做了一个全局管理 然后 我们继续 先 起来ganache的一个模拟环境 ganache -d然后 我们启动自己的项目 顺手发…

SaveToDisk属性

大家好,才是真的好。 Domino Designer的帮助文档里面充满了宝藏,最近就发现一个notesitem对象的SaveToDisk属性,你可以设置它为false,这样,虽然文档保存了,但这个字段本身可以不用保存,不仅可以…

激光雷达标定板如何提高激光雷达避免误判的精准度

激光雷达在提高自动驾驶的安全性方面具有重要作用。它通过高精度测量、避免误判、实时感知、适应不同环境和结合其他传感器等方式,为自动驾驶系统提供准确、可靠的感知数据,从而确保行驶的安全性和稳定性。 激光雷达可以通过以下方式避免误判&#xff1a…