首页 > 其他分享 >Shader随笔02

Shader随笔02

时间:2024-01-11 11:25:39浏览次数:27  
标签:02 defined Shader unity cginc endif 随笔 data gi

Global Bake

这里是简化Lighting.cginc的UnityGI_Base函数

以及AutoLight.cginc的LightingLambert

来实现bake贴图采样(没开灯光)

其中,Mixed是重点
Directional Mode是重点

Light组件的Mode需要调成Mixed

完成以上内容可以在使用unity标准Shader的情况下看的bake情况

自定义cginc文件

直接看pass

Baked光照贴图采样技术
Pass
{
    Tags {"LightMode"="ForwardBase"}
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    //需要使用这两个宏定义
    #pragma multi_compile DIRLIGHTMAP_COMBINED
    #pragma multi_compile LIGHTMAP_ON

    #include "UnityCG.cginc"
    #include "CGINC/MyCGInc.cginc"

    struct appdata
    {
        float4 vertex : POSITION;
        #if defined(LIGHTMAP_ON)
            float4 texcoord1 : TEXCOORD1;
        #endif
        float3 normal : NORMAL;
    };

    struct v2f
    {
        float4 pos : SV_POSITION;
        float3 worldNormal : NORMAL;
        float3 worldPos : TEXCOORD0;
        #if defined(LIGHTMAP_ON)
            fixed4 lightmapUV : TEXCOORD1;
        #endif
    };

    v2f vert (appdata v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.worldNormal = mul(unity_ObjectToWorld, v.normal);
        o.worldPos = mul(unity_ObjectToWorld, v.vertex);
        
        #if defined(LIGHTMAP_ON)
            o.lightmapUV.xy = v.texcoord1 * unity_LightmapST.xy + unity_LightmapST.zw;
        #endif

        return o;
    }

    fixed4 frag (v2f i) : SV_Target
    {
        SurfaceOutput o;
        UNITY_INITIALIZE_OUTPUT(SurfaceOutput, o);
        o.Albedo = 1;
        o.Normal = i.worldNormal;

        UnityGI gi;
        UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
        gi.light.color = _LightColor0;
        gi.light.dir = _WorldSpaceLightPos0;

        UnityGIInput giInput;
        UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
        giInput.light = gi.light;
        giInput.worldPos = i.worldPos;
        giInput.worldViewDir = normalize(_WorldSpaceCameraPos - i.worldPos);
        giInput.atten = 0.5;//先默认给一个,后续需要计算光照衰减

        #if defined(LIGHTMAP_ON)
            giInput.lightmapUV = i.lightmapUV;
        #endif

        //对烘焙贴图进行采样
        UnityGI_Base(giInput,1.0h,i.worldNormal, gi);
        //计算一个简单的Lambert光照模型
        return LightingLambert(o, gi);
    }
    ENDCG
}

这些gi啊giInput啊什么什么的,都来根据Unity内部实现使用的

来自于Lighting.cginc

同时,自定义的cginc文件也是改编自Lighting.cginc

1.SurfaceOutput是Lighting.cginc定义的struct,我们可以在自定义cginc中也定义一个

这里我定义了一个简略版,就是把需要的数据留着,不用的就删了

2.UnityGI和UnityGIInput也都是struct,由于东西太多,我这使用的#include "UnityLightingCommon.cginc"

这样,该cginc和该pass就可以使用这两个struct了

3.LightingLambert来自于Lighting.cginc,是实现一个简单的Lambert光照模型

4.UnityGI_Base来自于Lighting.cginc引入的UnityGlobalIllumination.cginc 

这里使用的是改编版,只留下了一个宏定义

UnityGI_Base原版
inline UnityGI UnityGI_Base(UnityGIInput data, half occlusion, half3 normalWorld)
{
    UnityGI o_gi;
    ResetUnityGI(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;
}

我看着就是一个简单的bake贴图采样,不过和法线有关

MyCGInc.cginc
 #ifndef MYCGINC_CGINCLUDE
#define MYCGINC_CGINCLUDE

#include "UnityLightingCommon.cginc"

struct SurfaceOutput {
    fixed3 Albedo;
    fixed3 Normal;
};

inline fixed4 LightingLambert (SurfaceOutput s, UnityGI gi)
{
    fixed4 c;
    fixed diff = max (0, dot (s.Normal, gi.light.dir));
    c.rgb = s.Albedo *  gi.light.color * diff;

    #if defined(LIGHTMAP_ON)
        c.rgb += s.Albedo * gi.indirect.diffuse;
    #endif

    return c;
}

inline void UnityGI_Base(UnityGIInput data, half occlusion, half3 normalWorld, inout UnityGI gi)
{
    #if defined(LIGHTMAP_ON)
        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);
            gi.indirect.diffuse += DecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);
        #endif
    #endif

    //将衰减应用于灯光颜色在
    gi.light.color *= data.atten;

    //环境光遮蔽
    gi.indirect.diffuse *= occlusion;
}

#endif

Global Bake之Non-Directional

近距离采用实时阴影,远距离采用Baked阴影  的技术

1.Light组件的Mode需要调成Mixed

2.Bake设置的LightingMode要调成Shadowmask

3.Bake设置的Directional Mode要调成Non-Directional

4.ProjectSettings-Quality-Shadows-Shadowmask Mode要调成Distance Shadowmask

5.ProjectSettings-Quality-Shadows-ShadowDistance调成你想要的值,这里是 5

效果:Bake的光照PosY是30,实时的光照PosY调了个46

距离小于ShadowDistance就用的实时阴影,大于就用bake阴影


此时上面是实时,下面是bake

继续远离

代码部分:

原先的自定义cginc没有实现该技术

该技术来自于UnityGlobalIllumination.cginc的HANDLE_SHADOWS_BLENDING_IN_GI宏定义,

就是将自定义cginc,修改成了使用Lighting.cginc的Bake阴影技术和AutoLight.cginc的实时阴影技术

代码部分

主pass
Pass
{
    Tags {"LightMode"="ForwardBase"}
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    
    #pragma multi_compile_fwdbase

    #include "UnityCG.cginc"
    #include "Lighting.cginc"
    #include "AutoLight.cginc"

    struct appdata
    {
        float4 vertex : POSITION;
        #if defined(LIGHTMAP_ON)
            float4 texcoord1 : TEXCOORD1;
        #endif
        float3 normal : NORMAL;
    };

    struct v2f
    {
        float4 pos : SV_POSITION;
        float3 worldNormal : NORMAL;
        float3 worldPos : TEXCOORD0;
        #if defined(LIGHTMAP_ON)
            fixed4 lightmapUV : TEXCOORD1;
        #endif
        UNITY_LIGHTING_COORDS(2,3)
    };

    v2f vert (appdata v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.worldNormal = mul(unity_ObjectToWorld, v.normal);
        o.worldPos = mul(unity_ObjectToWorld, v.vertex);
        
        #if defined(LIGHTMAP_ON)
            o.lightmapUV.xy = v.texcoord1 * unity_LightmapST.xy + unity_LightmapST.zw;
        #endif
        UNITY_TRANSFER_LIGHTING(o, v.texcoord1.xy);

        return o;
    }

    fixed4 frag (v2f i) : SV_Target
    {
        SurfaceOutput o;
        UNITY_INITIALIZE_OUTPUT(SurfaceOutput, o);
        o.Albedo = 1;
        o.Normal = i.worldNormal;

        UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

        UnityGI gi;
        UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
        gi.light.color = _LightColor0;
        gi.light.dir = _WorldSpaceLightPos0;

        UnityGIInput giInput;
        UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
        giInput.light = gi.light;
        giInput.worldPos = i.worldPos;
        giInput.worldViewDir = normalize(_WorldSpaceCameraPos - i.worldPos);
        giInput.atten = atten;

        #if defined(LIGHTMAP_ON) || defined(DYNAMACLIGHTMAP_ON)
            giInput.lightmapUV = i.lightmapUV;
        #endif

        //对烘焙贴图进行采样
        LightingLambert_GI(o,giInput,gi);
        //计算一个简单的Lambert光照模型
        return LightingLambert(o, gi);
    }
    ENDCG
}
阴影Pass
pass
{
    Tags{ "LightMode"="ShadowCaster" }
    CGPROGRAM
    
    #pragma vertex vert
    #pragma fragment frag
    #pragma multi_compile_shadowcaster
    #include "UnityCG.cginc"

    struct a2v
    {
        float4 vertex: POSITION;
        half3 normal: NORMAL;
    };

    struct v2f
    {
        V2F_SHADOW_CASTER;
    };

    v2f vert(a2v v)
    {
        v2f o;
        TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
        return o;
    }

    fixed4 frag(v2f i) : SV_Target
    {
        SHADOW_CASTER_FRAGMENT(i);
    }

    ENDCG
}

标签:02,defined,Shader,unity,cginc,endif,随笔,data,gi
From: https://www.cnblogs.com/LateUpdate/p/17957012

相关文章

  • 2023-2024年最佳人工智能工具(1)
    ​随着人工智能领域的迅猛发展,越来越多的新奇且意想不到的应用程序正在被开发出来。无论是商业领域还是个人领域,这些应用程序的范围都非常广泛。然而,我们使用这些人工智能工具的原因可以归结为一个共同点:人工智能已经发展到可以帮助人类完成繁重的重复性任务,并减少人为错误,从而节......
  • 创新工具:2024年开发者必备的一款表格控件
    前言在现代工作环境中,信息的处理和管理是至关重要的。表格是一种常见的数据呈现和整理工具,被广泛应用于各行各业。然而,随着技术的不断发展,市场对表格控件的需求也越来越高。随着工作效率的重要性日益凸显,一款高效的表格控件成为了开发者们的首选,因此本文小编将从葡萄城公司的纯前......
  • 【愚公系列】2024年01月 WPF控件专题 ListBox控件详解
    ......
  • 新火种AI|2024乍到,会成为小模型的当打之年吗?
    作者:小岩编辑:美美乘着ChatGPT爆火的东风,2023年成为了当之无愧的“大模型爆发之年”。跟随ChatGPT的脚步,诸多大厂和知名企业推出了自己的AI大模型。也正因此,大模型赛道的竞争变得异常激烈,烧钱的势头也变得异常凶猛。不过,这样的趋势很可能在2024年产生变化。每个事物的发展都要经历“......
  • 2024-01-10:用go语言,给你一个下标从 0 开始的二维整数数组 pairs 其中 pairs[i] = [sta
    2024-01-10:用go语言,给你一个下标从0开始的二维整数数组pairs其中pairs[i]=[starti,endi]如果pairs的一个重新排列满足对每一个下标i(1<=i<pairs.length)都有endi-1==starti,那么我们就认为这个重新排列是pairs的一个合法重新排列。请你返回任意一个pairs的......
  • 2023年山东省职业院校技能大赛高职组信息安全管理与评估 理论题
    2023年山东省职业院校技能大赛高职组信息安全管理与评估理论题理论技能与职业素养(100分)2023年山东省职业院校技能大赛高职组信息安全管理与评估理论题【注意事项】Geek极安云科专注技能竞赛技术提升,基于各大赛项提供全面的系统性培训,拥有完整的培训体系。团队拥有曾获国奖......
  • 2023年山东省职业院校技能大赛高职组信息安全管理与评估 模块一
    2023年山东省职业院校技能大赛高职组信息安全管理与评估模块一模块一竞赛项目试题根据信息安全管理与评估技术文件要求,模块一为网络平台搭建与网络安全防护。本文件为信息安全管理与评估项目竞赛-模块一试题。所需的设备、机械、装置和材料:所有测试项目都可以由参赛选手根据......
  • 从嘉手札<2024-1-10>
    冬月初零 年岁缭绕秋月无影倏尔迢迢暗章难牧纵使再怎么保有年少飞扬的内心时光仍带去了我二十六年的光阴出乎意料的收到了很多人的祝福可喜的是仍有不少人记挂着我于我而言无疑是莫大的荣幸和欣喜正如十九年前我第一次收到发小两毛钱的生日蛋糕倘若说完全没有内心......
  • SOLIDWORKS 2024新功能之SOLIDWORKS PDM篇
    SOLIDWORKS2024新功能PDM篇目录概述•装配体直观•在Web2中下载文件的特定版本•文件类型图标•“更改状态”命令中的签出选项•复制树对话框•查看检出事件详细信息•系统变量•查看许可证使用•数据安全增强功能•SOLIDWORKSPDM性能改进1、装配体直观可以在SOL......
  • OpenHarmony社区运营报告(2023年12月)
     • 截至2023年12月22日,OpenAtom OpenHarmony(简称“OpenHarmony")社区累计超过6700名贡献者,产生26.9万多个PR,2.4万多个Star,6.7万多个Fork,59个SIG。• 2023年12月16日,以“技术创新,照见未来”为主题的首届开放原子开发者大会OpenHarmony分论坛在无锡隆重举行。作为开放原子......