Unity中一个节点实现植物动态(Shader)

news2025/2/22 9:58:22

1 . 核心思路就操作顶点作往复运动;

核心代码:

half  stage1 = dot(positionOS, float3(0, 1, 0)) * _Strength;
half  stage2 = sin(dot(positionOS, float3(1, 0, 0)) * _Strength + _Time.y * _Speed);
half  stage3 = stage1 * stage2 * float3(0.001, 0, 0.001);

PositionVar  = stage3 + positionOS;

至于下面的贴图采样这些不重要,除非你需要特别指定顶点哪部分动,哪部分不需要动,你可以采样一个贴图和顶点作Mask操作;

以前在URP管线中也写过,一并发出来:

Shader "Common/Tree_Simple"
{
    Properties
    {   
        [MaterialEnum(Off,0,Front,1,Back,2)] _Cull("Cull", Int) = 2
        _BaseColor("Base Color",color) = (1,1,1,1)
        _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
        [Normal]_BumpMap("Normal Map", 2D) = "bump" {}
        _NormalScale("NormalPow", Range(0,2)) = 1.0

        _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
        _Roughness("Roughness", Range(0.0, 1.0)) = 0.0

        [Header(Mask)]
        [KeywordEnum(CLIP,ALPHA_TO_MASK)]ClipSwitch("Clip / AlphaToMask)",Float) = 0
        _Cutoff("Alpha Cutoff", Range(0,1)) = 0.333

        [Header(Y_Color)]       //对顶点进行X轴和Y轴上的偏移
        [KeywordEnum(YES,NO)]LEAF("是否树叶(渐变色开关)?",Float) = 1
        _Strength("摇摆幅度", Float) = 1
        _Speed("摇摆速度", Float) = 3
        _BaseColorMaskHeight("BaseColorMaskHeight",Range(0,1)) = 0.5 
        _BaseColorTop("BaseColorTop",Color) = (1,1,1,1)
        _BaseColorBottom("BaseColorBottom",Color) = (0,0,0,1)

        [Header(Shadow)]
        _ShadowMainColor("接受阴影颜色", color) = (0.25,0.25,0.25,1)

        [Toggle(_KALOS_G_FACTOR_ON)] _Kalos_G_Factor ("Optimize with Kalos G Factor", Int) = 1 

    }
 
    SubShader
    {
        Tags {"LightMode" = "UniversalForward" "RenderPipeline" = "UniversalPipeline" }
        LOD 100
        Cull [_Cull]
        AlphaToMask On
 
        Pass
        {
            Name "Unlit"
            HLSLPROGRAM
            // Required to compile gles 2.0 with standard srp library
            #pragma prefer_hlslcc gles
            #pragma exclude_renderers d3d11_9x
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #pragma shader_feature _ _KALOS_G_FACTOR_ON

            #pragma multi_compile CLIPSWITCH_CLIP CLIPSWITCH_ALPHA_TO_MASK
            #pragma multi_compile LEAF_YES LEAF_NO

            //光照贴图这一坨别丢了,不然移动端不显示
            #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            #pragma multi_compile _ SHADOWS_SHADOWMASK
            #pragma multi_compile _ DIRLIGHTMAP_COMBINED
            #pragma multi_compile _ LIGHTMAP_ON
            #pragma multi_compile _ DYNAMICLIGHTMAP_ON	

            // URP 软阴影
            #pragma multi_compile_fragment _ _SHADOWS_SOFT
            // URP 主光阴影、联机阴影、屏幕空间阴影//
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"

            #include "PBRMath.hlsl"

            CBUFFER_START(UnityPerMaterial)
            half4  _BaseColor; half _NormalScale , _Metallic,_Roughness;
            float4 _MainTex_ST,_BumpMap_ST;
            float  _bakedGIBlend,_bakedGIPow,_Cutoff;
            half4  _ShadowMainColor;     half4 _BaseColorBottom,_BaseColorTop;
            half  _BaseColorMaskHeight , _Speed , _Strength;
            CBUFFER_END
            TEXTURE2D (_MainTex);SAMPLER(sampler_MainTex);
            TEXTURE2D (_BumpMap);SAMPLER(sampler_BumpMap);
 
            struct VertexInput
            {
                float4 positionOS       : POSITION;
                float2 uv               : TEXCOORD0;
				float4 normalOS         : NORMAL;
				float4 tangentOS        : TANGENT;
                float2 uvLM             : TEXCOORD1;        //光照贴图三件套
                float4 color            : COLOR0;
            };
 
            struct VertexOutput
            {
                float4 position       : SV_POSITION;
                float4 uv               : TEXCOORD0;
				float3 positionWS       :  TEXCOORD1;
				float3 normalWS         : TEXCOORD2;
				float3 tangentWS        : TEXCOORD3;
				float3 bitangentWS      : TEXCOORD4;
                float  fogCoord         : TEXCOORD5;
                float2 uvLM             : TEXCOORD6;        //光照贴图三件套
                float3 vertexSH         : TEXCOORD7;        //光照贴图三件套
                float4 color            : TEXCOORD8;
            };
            
            half3 Saturation(half3 finalCol, half Saturation)
            {
                half   gray        = 0.2125 * finalCol.r + 0.7154 * finalCol.g + 0.0721 * finalCol.b;
                half3  grayColor   = half3(gray, gray, gray);
                return lerp(grayColor, finalCol, Saturation);
            }
 
            VertexOutput vert(VertexInput v)
            {
                VertexOutput o = (VertexOutput)0;

                //--------------树叶飘动------------------------
                half  stage1 = dot(v.positionOS.xyz, float3(0, 1, 0)) * _Strength;
                half  stage2 = sin(dot(v.positionOS.xyz, float3(1, 0, 0)) * _Strength + _Time.y * _Speed);
                half3 stage3 = stage1 * stage2 * float3(0.001, 0, 0.001) * v.color.a; 
                //------------------End---------------------------- 

				VertexPositionInputs positionInputs = GetVertexPositionInputs(v.positionOS.xyz + stage3);
                o.position = positionInputs.positionCS;
				o.positionWS = positionInputs.positionWS; 

				VertexNormalInputs normalInputs = GetVertexNormalInputs(v.normalOS.xyz,v.tangentOS);
				o.normalWS = normalInputs.normalWS;
				o.tangentWS = normalInputs.tangentWS;
				o.bitangentWS = normalInputs.bitangentWS;

                o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
                o.uv.zw = TRANSFORM_TEX(v.uv, _BumpMap);

                OUTPUT_LIGHTMAP_UV(v.uvLM, unity_LightmapST, o.uvLM);         //光照贴图三件套  
                //o.position = TransformObjectToHClip(v.positionOS.xyz);
                o.fogCoord = ComputeFogFactor(o.position.z);
 
                return o;
            }
 
            half4 frag(VertexOutput i) : SV_Target
            {
                //阴影
				float4 SHADOW_COORDS = TransformWorldToShadowCoord(i.positionWS.xyz);
				Light  lightDirectional     = GetMainLight(SHADOW_COORDS);
				half   shadow        = lightDirectional.shadowAttenuation;

                //贴图采样
                float4 MainTex      = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv.xy);
                half4  normalTXS    = SAMPLE_TEXTURE2D(_BumpMap,sampler_BumpMap,i.uv.xy);

                float3 normalMap    = UnpackNormalScale(normalTXS,_NormalScale);
                real3x3 TBN         = real3x3(i.tangentWS, i.bitangentWS, i.normalWS);    //追求高精度
                half3 normalWS      = TransformTangentToWorld(normalMap,TBN);

                //向量准备
                half3 N = normalWS;
                half3 L = normalize(lightDirectional.direction);
                half3 V = SafeNormalize(_WorldSpaceCameraPos - i.positionWS);
                half3 H = normalize(L + V);

                //点积
                half  HdotL = max(dot(H, L), 1e-5);
                half  NdotV = max(dot(N, V), 1e-5);         
                half  HdotN = max(dot(H, N), 1e-5);
                half  NdotL = dot(N,L);

                half3 R     = reflect( -L , N );
                half  VdotR = dot ( V , R );

                NdotL = lerp(NdotL*0.5+0.5,max(dot(N, L), 1e-5),0.75);  //这个是我个人喜好!

                //PBR参数准备 
                half3 Albedo        = MainTex.rgb; 
                half  occlusion     = MainTex.g;

                half  roughness     = normalTXS.a;
                half  smoothness    = (1 - roughness/_Roughness);      //计算待定

                half  metallic      = normalTXS.a * _Metallic;
                half3 F0            = Direct_F0_Function(Albedo, metallic);
                half3 Direct_F      = Direct_F_Function(HdotL, F0);

                //----// 直线光漫反射
                half3 KS = Direct_F;
                half3 KD = (1 - KS) * (1 - metallic);
                half3 DirectDiffColor = KD * Albedo * lightDirectional.color * NdotL;

                // 镜面反射
                half Direct_D = Direct_D_Function(HdotN, roughness);

                //----// BRDF
                #if defined(_KALOS_G_FACTOR_ON)
                        half Direct_G = Direct_G_Function_Kalos(HdotL, roughness);
                #else
                        half Direct_G = Direct_G_Function(NdotL, NdotV, roughness);
                #endif

                #if defined(_KALOS_G_FACTOR_ON)
                        half3 BRDFSpecSection = (Direct_D * Direct_G) * Direct_F / (4 * HdotL);
                #else
                        half3 BRDFSpecSection = (Direct_D * Direct_G) * Direct_F / (4 * NdotL * NdotV);
                #endif

                half3 DirectSpeColor = BRDFSpecSection * lightDirectional.color * (NdotL * PI * occlusion);

                // 第一部分(直线光照结果):实时或者烘焙
                //-------光照贴图-------------//
                #ifdef LIGHTMAP_ON
                half3 bakedGI = SAMPLE_GI(i.uvLM, i.vertexSH, N);        //光照贴图三件套
                      bakedGI = lerp(half3(1,1,1),pow( abs(bakedGI),_bakedGIPow),_bakedGIBlend);
                      half3 DirectColor = bakedGI*Albedo;
                #else
                half3 DirectColor = DirectDiffColor + DirectSpeColor;
                #endif
            
                // 第二部分:间接漫反射
                half3 shColor       = SH_IndirectionDiff(N) * occlusion;
                half3 Indirect_KS   = Indirect_F_Function(NdotV, F0, roughness);
                half3 Indirect_KD   = (1 - Indirect_KS) * (1 - metallic);
                half3 IndirectDiffColor = shColor * Indirect_KD * Albedo;
                
                // 间接反射
                //----// 反射探针的间接光
                half3 IndirectSpeCubeColor  = IndirectSpeCube(N, V, roughness, occlusion); 
                half3 IndirectSpeCubeFactor = IndirectSpeFactor(roughness, smoothness, BRDFSpecSection, F0, NdotV); 
                half3 IndirectSpeColor      = IndirectSpeCubeColor *IndirectSpeCubeFactor; 

                //----//间接漫反射 + 间接反射
                    //魔改金属表现
                    half  k = 1;  //探针强度
                    IndirectSpeColor = IndirectSpeColor * k; 
                    //-------//魔改金属表现
                    IndirectSpeColor.rgb = Saturation(IndirectSpeColor, k*metallic);
                    IndirectSpeColor.rgb = IndirectSpeColor.rgb + IndirectSpeColor.rgb*metallic*(k);
                half3 IndirectColor = IndirectDiffColor + IndirectSpeColor; 
                           

                //----//

                //----------------直接光漫射 + 间接光漫射(间接光反射) ------------------------------------
                half3 Col       = DirectColor + IndirectColor;      
                //-------------------------------------------------------------------------------------
                //--树叶Y方向颜色渐变(球形法线特性)--//LEAF_YES LEAF_NO
                #ifdef LEAF_YES
                float3 albedoMask = i.normalWS.y;
                albedoMask = albedoMask/2+0.5;
                albedoMask*=_BaseColorMaskHeight;
                albedoMask= smoothstep(0,1,albedoMask);
                half3 albedoMaskCol = lerp(_BaseColorBottom.rgb,_BaseColorTop.rgb,albedoMask);
                
                Col *= albedoMaskCol;
                #elif LEAF_NO

                #endif       

                      Col       = Col * _BaseColor.rgb;
                      Col       = MixFog(Col.rgb, i.fogCoord);

                      Col       = lerp(_ShadowMainColor.rgb * Col, Col, shadow); 

                #ifdef CLIPSWITCH_CLIP
                half  Alpha     = 1;
                clip(MainTex.a-_Cutoff);
                #elif  CLIPSWITCH_ALPHA_TO_MASK
                half  Alpha     = MainTex.a;
                #endif
                
                half4 finalCol  = half4(Col,Alpha);
                return finalCol;
            }
            ENDHLSL
        }

        UsePass "Universal Render Pipeline/Lit/ShadowCaster"

        UsePass "Universal Render Pipeline/Lit/Meta"

        UsePass "Universal Render Pipeline/Lit/DepthOnly" 
    }
}

静态图没这么丑..不知道咋压缩的..

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

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

相关文章

PrimeTime:工具简介

相关阅读 PrimeTimehttps://blog.csdn.net/weixin_45791458/category_12900271.html?spm1001.2014.3001.5482 PrimeTime是PrimeTime Suite中的一个工具,能够执行全芯片级、门级的静态时序分析,这是芯片设计和分析流程中的一个关键部分。该工具通过检查…

【拜读】Tensor Product Attention Is All You Need姚期智团队开源兼容RoPE位置编码

姚期智团队开源新型注意力:张量积注意力(Tensor Product Attention,TPA)。有点像一种「动态的LoRA」,核心思路在于利用张量分解来压缩注意力机制中的 Q、K、V 表示,同时保留上下文信息,减少内存…

Docker-技术架构演进之路

目录 一、概述 常见概念 二、架构演进 1.单机架构 2.应用数据分离架构 3.应用服务集群架构 4.读写分离 / 主从分离架构 5.引入缓存 —— 冷热分离架构 6.垂直分库 7.业务拆分 —— 微服务 8.容器化引入——容器编排架构 三、尾声 一、概述 在进行技术学习过程中&am…

用Chrome Recorder轻松完成自动化测试脚本录制

前言 入门自动化测试,录制回放通常是小白测试首先用到的功能。而录制回放工具也一直是各大Web自动化测试必然会着重提供的一块功能。 早期WinRunner、QTP这样的工具,自动化测试可以说是围绕录制回放开展的。近年像Selenium也提供有录制工具 Selenium IDE,Playwright也包含…

python中的异常-模块-包

文章目录 异常异常的定义异常捕获语法捕获常规异常捕获指定异常捕获多个异常捕获所有异常异常else异常finally 异常传递总结 模块概念导入自定义模块及导入main方法all变量 总结 包自定义包定义pycharm中建包的基本步骤导入方式 第三方包 异常 异常的定义 当检测到一个错误时…

【GPU驱动】OpenGLES图形管线渲染机制

OpenGLES图形管线渲染机制 OpenGL/ES 的渲染管线也是一个典型的图形流水线(Graphics Pipeline),包括多个阶段,每个阶段都负责对图形数据进行处理。管线的核心目标是将图形数据转换为最终的图像,这些图像可以显示在屏幕…

ssm-day06 ssm整合

从springMVC总结再回顾一下 60节 整合就是应用框架,并且把这个框架放到IOC容器中 web容器:装springMVC和controller相关的web组件 root容器:装业务和持久层相关的组件 子容器可以引用父容器中的组件,父容器不能调子容器 一个容器…

AI 编程助手 cursor的系统提示词 prompt

# Role 你是一名极其优秀具有10年经验的产品经理和精通java编程语言的架构师。与你交流的用户是不懂代码的初中生,不善于表达产品和代码需求。你的工作对用户来说非常重要,完成后将获得10000美元奖励。 # Goal 你的目标是帮助用户以他容易理解的…

ollama如何安全卸载,解决Ollama unins000.msg is missing

春节后在本地电脑安装了Ollama的客户端,每次开机自启,影响开机速度,而且本地的模型不如联网的回答效果好,果断选择了卸载,但是今天卸载发现提示下方的错误。根据此文章可以解决当前的问题。 根据此文章可以解决当前的…

网络安全设备防护原理 网络安全防护装置

🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 防火墙 简介 网络层的防护设备,依照特殊的规则允许或者限制传输的数据通过 是由软件和硬件设备组合而成,在内部网和外部网之间、专用网…

Python的那些事第二十八篇:数据分析与操作的利器Pandas

Pandas:数据分析与操作的利器 摘要 Pandas是基于Python的开源数据分析库,广泛应用于数据科学、机器学习和商业智能等领域。它提供了高效的数据结构和丰富的分析工具,能够处理结构化数据、时间序列数据以及复杂的数据转换任务。本文从Pandas的基础概念入手,深入探讨其核心…

学习threejs,使用MeshBasicMaterial基本网格材质

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.MeshBasicMaterial 二…

【git-hub项目:YOLOs-CPP】本地实现05:项目移植

ok,经过前3个博客,我们实现了项目的跑通。 但是,通常情况下,我们的项目都是需要在其他电脑上也跑通,才对。 然而,经过测试,目前出现了2 个bug。 项目一键下载【⬇️⬇️⬇️】: 精…

【python】协程(coroutine)

协程(coroutine)可以理解为一个可以中途暂停保存当前执行状态信息并可以从此处恢复执行的函数,多个协程共用一个线程执行,适合执行需要“等待”的任务。 所以严格意义上,多个协程同一时刻也只有一个在真正的执行&#…

【编译器】-LLVMIR

概述 LLVM 是一种基于静态单赋值 (SSA) 的表示形式,提供类型安全、低级操作、灵活性以及干净地表示“所有”高级语言的能力。 LLVM IR 是一门低级语言,语法类似于汇编任何高级编程语言(如C)都可以用LLVM IR表示基于LLVM IR可以很…

java面试场景问题

还在补充,这几天工作忙,闲了会把答案附上去,也欢迎各位大佬评论区讨论 1.不用分布式锁如何防重复提交 方法 1:基于唯一请求 ID(幂等 Token) 思路:前端生成 一个唯一的 requestId(…

python pandas下载

pandas pandas:就是一个可以处理数据的 python 库 核心功能: 数据的清洗:处理丢失值,重复值数据分析:计算和统计信息,或分组汇总数据可视化:结合 图标库(Matplotlib)完成数据可视化…

Python+Selenium+Pytest+POM自动化测试框架封装

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 1、测试框架简介 1)测试框架的优点 代码复用率高,如果不使用框架的话,代码会显得很冗余。可以组装日志、报告、邮件等一些高…

猿大师中间件:网页直接内嵌本机EXE、OCX控件、ActiveX控件或桌面应用程序神器

猿大师中间件自从2019年发布以来,迄今为止不断迭代升级,给第三方提供了将自己的桌面程序和OCX控件支持直接内嵌到浏览器网页运行的赋能SDK开发包。 目前针对不同需求发布了三个成熟且商用的产品: 猿大师播放器:浏览器中直接原生…

C++,设计模式,【工厂方法模式】

文章目录 如何用汽车生产线理解工厂方法模式?一、传统生产方式的困境二、工厂方法模式解决方案三、模式应用场景四、模式优势分析五、现实应用启示✅C++,设计模式,【目录篇】 如何用汽车生产线理解工厂方法模式? 某个早晨,某车企CEO看着会议室里堆积如面的新车订单皱起眉…