unity URP 利用particle system制作简单的shader交互

news/2025/3/26 18:32:39/

首先这里制作了一个简单交互,使用shader grapgh,根据计算距离和变化数值的差实现交互后的扩散,同时计算消散遮罩让它逐渐谈去。

将他赋予材质物体,根据脚本传入位置和逐渐变化的大小后,呈现这样的效果。

但是,shader graph这样的工具,在做这种效果非常快的同时,也存在不少缺点,比如这里我希望我传入的位置和大小变化都是数组,使用shader graph就不太好办了。

这时候就需要把它翻译成代码,根据连线图的逻辑翻译即可,此外把传入的位置和size值替换为数组。

Shader "yourname"
{Properties{_MainTex ("Texture", 2D) = "white" {}_HitPos("HitPos", Vector) = (0, 0, 0, 0)_HitSize("HitSize", Float) = 0.001_HitSpread("HitSpread", Range(0, 10)) = 1_HitSizeMax("HitSizeMax", Float) = 0_DisappearSpread("DisappearSpread", Float) = 1_HitSpreadNoiseMulti("HitSpreadNoiseMulti", Range(0.01, 10)) = 1_HitSpreadNoiseScale("HitSpreadNoiseScale", Range(1, 200)) = 20[HideInInspector]_QueueOffset("_QueueOffset", Float) = 0[HideInInspector]_QueueControl("_QueueControl", Float) = -1[HideInInspector][NoScaleOffset]unity_Lightmaps("unity_Lightmaps", 2DArray) = "" {}[HideInInspector][NoScaleOffset]unity_LightmapsInd("unity_LightmapsInd", 2DArray) = "" {}[HideInInspector][NoScaleOffset]unity_ShadowMasks("unity_ShadowMasks", 2DArray) = "" {}}SubShader{Tags{"RenderPipeline"="UniversalPipeline""RenderType"="Opaque"//"UniversalMaterialType" = "Lit""Queue"="Geometry""DisableBatching"="False"}Pass{Name "Universal Forward"Tags{"LightMode" = "UniversalForward"}Cull BackBlend One ZeroZTest LEqualZWrite OnHLSLPROGRAM#pragma enable_d3d11_debug_symbols  //  debug信息#pragma multi_compile_instancing#pragma target 4.0  // 默认2.5 target的详细信息 https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html#pragma vertex vert#pragma fragment frag//https://github.com/Unity-Technologies/Graphics/tree/master/Packages/com.unity.render-pipelines.universal/ShaderLibrary#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.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.universal/ShaderLibrary/Input.hlsl"#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl"#include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl"#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Hashes.hlsl"float Unity_SimpleNoise_ValueNoise_Deterministic_float (float2 uv){float2 i = floor(uv);float2 f = frac(uv);f = f * f * (3.0 - 2.0 * f);uv = abs(frac(uv) - 0.5);float2 c0 = i + float2(0.0, 0.0);float2 c1 = i + float2(1.0, 0.0);float2 c2 = i + float2(0.0, 1.0);float2 c3 = i + float2(1.0, 1.0);float r0; Hash_Tchou_2_1_float(c0, r0);float r1; Hash_Tchou_2_1_float(c1, r1);float r2; Hash_Tchou_2_1_float(c2, r2);float r3; Hash_Tchou_2_1_float(c3, r3);float bottomOfGrid = lerp(r0, r1, f.x);float topOfGrid = lerp(r2, r3, f.x);float t = lerp(bottomOfGrid, topOfGrid, f.y);return t;}void Unity_SimpleNoise_Deterministic_float(float2 UV, float Scale, out float Out){float freq, amp;Out = 0.0f;freq = pow(2.0, float(0));amp = pow(0.5, float(3-0));Out += Unity_SimpleNoise_ValueNoise_Deterministic_float(float2(UV.xy*(Scale/freq)))*amp;freq = pow(2.0, float(1));amp = pow(0.5, float(3-1));Out += Unity_SimpleNoise_ValueNoise_Deterministic_float(float2(UV.xy*(Scale/freq)))*amp;freq = pow(2.0, float(2));amp = pow(0.5, float(3-2));Out += Unity_SimpleNoise_ValueNoise_Deterministic_float(float2(UV.xy*(Scale/freq)))*amp;}void Unity_SampleGradientV1_float(Gradient Gradient, float Time, out float4 Out){float3 color = Gradient.colors[0].rgb;[unroll]for (int c = 1; c < Gradient.colorsLength; c++){float colorPos = saturate((Time - Gradient.colors[c - 1].w) / (Gradient.colors[c].w - Gradient.colors[c - 1].w)) * step(c, Gradient.colorsLength - 1);color = lerp(color, Gradient.colors[c].rgb, lerp(colorPos, step(0.01, colorPos), Gradient.type));}#ifdef UNITY_COLORSPACE_GAMMAcolor = LinearToSRGB(color);#endiffloat alpha = Gradient.alphas[0].x;[unroll]for (int a = 1; a < Gradient.alphasLength; a++){float alphaPos = saturate((Time - Gradient.alphas[a - 1].y) / (Gradient.alphas[a].y - Gradient.alphas[a - 1].y)) * step(a, Gradient.alphasLength - 1);alpha = lerp(alpha, Gradient.alphas[a].x, lerp(alphaPos, step(0.01, alphaPos), Gradient.type));}Out = float4(color, alpha);}struct appdata{//顶点着色器语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDNfloat4 vertex : POSITION;float3  normal  : NORMAL;float4  tan  : TANGENT;float2 uv : TEXCOORD0;};struct v2f{//像素着色器语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDNfloat4 positionCS : SV_POSITION;float3  normal  : NORMAL;float2 uv : TEXCOORD0;float3 positionWS : TEXCOORD1;};//从片段着色器的返回结构,SV_Target,SV_Depth等,不知道这两个之外还有能用的不。SV_Target可以从0到7,在多渲染目标(MRT)时很有用struct fragOutput {//语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDNfloat4 Emission : SV_Target;};sampler2D _MainTex;float4 _MainTex_ST; float _HitSpreadNoiseScale;float _HitSpreadNoiseMulti;int count;float3 hitposarray[20];float hitsizearray[20];float hitspreadarray[20];float hitsizemaxarray[20];float disappearspreadarray[20];v2f vert(appdata v, uint vid : SV_VertexID){v2f o;o.positionCS = TransformObjectToHClip(v.vertex);o.positionWS = TransformObjectToWorld(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.normal = v.normal;return o;}float4 CalculateCircle(v2f i, float3 _HitPos, float _HitSize, float _HitSpread, float _HitSizeMax, float _DisappearSpread){float3 tempdis = distance(_HitPos, i.positionWS);float tempupmul = clamp(((tempdis - _HitSizeMax) * (-1) )/ _DisappearSpread, 0, 1);float noiseout = 0;Unity_SimpleNoise_Deterministic_float(i.uv, _HitSpreadNoiseScale, noiseout);noiseout = noiseout * _HitSpreadNoiseMulti;float temp1 = noiseout + (tempdis - _HitSize);float temp2 = 1 - clamp(temp1 / min(_HitSize, _HitSpread), 0, 1);Gradient _Gradient = NewGradient(0, 4, 2, float4(0, 0, 0, 0),float4(0.767647, 0.767647, 0.767647, 0.1058824),float4(0.6861503, 0.6861503, 0.6861503, 0.7705958),float4(0, 0, 0, 0.9647059),float4(0, 0, 0, 0),float4(0, 0, 0, 0),float4(0, 0, 0, 0),float4(0, 0, 0, 0), float2(1, 0),float2(1, 1),float2(0, 0),float2(0, 0),float2(0, 0),float2(0, 0),float2(0, 0),float2(0, 0));float4 gradientout = 0;Unity_SampleGradientV1_float(_Gradient, temp2, gradientout);return tempupmul * gradientout;}fragOutput frag(v2f i) : SV_Target{fragOutput o = (fragOutput)0;float4 tempemission = 0;for(int j = 0; j < count; j++){tempemission += CalculateCircle(i, hitposarray[j], hitsizearray[j], hitspreadarray[j], hitsizemaxarray[j], disappearspreadarray[j]);};o.Emission = tempemission;return o;}ENDHLSL}}Fallback Off
}

particle system制作为在点击位置射线检测,生成粒子,并逐渐放大,最后消失。

弄好后关闭粒子的renderer,使其不可见。

然后创建脚本根据particle system产生的粒子位置和大小,particle system,按个数传入shader代码的数组中,按照粒子的位置和大小同步shader数组中的值以实现效果。

using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.InputSystem;
using static UnityEngine.Rendering.DebugUI;[ExecuteAlways]
public class ForceField : MonoBehaviour
{//编辑器引用public GameObject forcefield;public ParticleSystem ps;//静态存储[Header("粒子系统最大数量")]public int psAmount = 20;Material material;Shader shader;Mouse mouse;//动态变化存储RaycastHit raycastHit;ParticleSystem.Particle[] particles;bool isInited = false;void Init(){if (material == null)material = forcefield.GetComponent<MeshRenderer>().sharedMaterial;if (shader == null)shader = material.shader;if (mouse == null)mouse = Mouse.current;particles = new ParticleSystem.Particle[psAmount];}void Update(){//编辑器模式下就要做的事情if (forcefield == null) return;if (ps == null) return;if (!isInited){Init();isInited = true;}//运行模式下才要做的事情if (!Application.isPlaying) return;if (mouse.leftButton.wasPressedThisFrame)//Status:鼠标左键按下  运行时才有作用{Vector2 mousePos = Pointer.current.position.ReadValue();Ray ray = Camera.main.ScreenPointToRay(mousePos);Physics.Raycast(ray, out raycastHit, 1000, LayerMask.GetMask("ForceField"));if(raycastHit.collider != null)//检测有效,做以下操作{ps.transform.position = raycastHit.point;ps.Emit(1);}}ParticleSystem.MainModule psMainModule = ps.main;int count = ps.GetParticles(particles);Debug.Log(count);material.SetInteger("count", count);  //  激活的个数if(count > 0){Vector4[] hitposs = new Vector4[20];float[] hitsizes = new float[20];float[] hitspreads = new float[20];float[] hitsizemaxs = new float[20];float[] disappearspreads = new float[20];for (int i = 0; i < count; i++){hitposs[i] = new Vector4(particles[i].position.x, particles[i].position.y, particles[i].position.z, 1);hitsizes[i] = particles[i].GetCurrentSize(ps);hitspreads[i] = 1;hitsizemaxs[i] = psMainModule.startSize.constantMax;disappearspreads[i] = psMainModule.startSize.constantMax / 2;}material.SetVectorArray("hitposarray", hitposs);material.SetFloatArray("hitsizearray", hitsizes);material.SetFloatArray("hitspreadarray", hitspreads);material.SetFloatArray("hitsizemaxarray", hitsizemaxs);material.SetFloatArray("disappearspreadarray", disappearspreads);}}}


http://www.ppmy.cn/news/1150633.html

相关文章

Windows提权方法论

Windows提权方法论 1.溢出漏洞提权2.计划任务提权3.SAM文件提权4.启动项提权5.不带引号的服务路径提权 1.溢出漏洞提权 溢出提权攻击的基本原理是&#xff0c;通过向目标系统发送过长的输入数据&#xff0c;超出了程序所分配的缓冲区大小&#xff0c;导致溢出。攻击者可以利用…

小程序使用uni.createAnimation只执行一次的问题

思路&#xff1a; 在页面创建的时候&#xff0c;创建一个临时动画对象调用 step() 来表示一组动画完成通过动画实例的export方法导出动画数据传递给组件的animation属性还原动画页面卸载的时候&#xff0c;清除动画数据 <template><view class"content"&g…

【mysql】 bash: mysql: command not found

在linux 服务器上安装了mysql 也可以正常运行。 但是执行命令&#xff0c;系统提示&#xff1a;bash: mysql: command not found bash:mysql:找不到命令 执行的命令是&#xff1a; mysql -u root -h 127.0.0.1 -p由于系统默认会查找的 /usr/bin/ 中下的命令&#xff0c;如…

机器人制作开源方案 | 扫地机器人

1. 功能描述 扫地机器人是现代家庭清洁的得力助手&#xff0c;能够自主规划清扫路径&#xff0c;避开障碍物&#xff0c;有效覆盖整个清洁区域。扫地机器人的出现极大地减轻了家庭清洁的负担&#xff0c;节省了时间和精力&#xff0c;它可以定期清理地面&#xff0c;确保家居环…

lvgl overview

https://docs.lvgl.io/master/get-started/quick-overview.html 图像元素 屏幕上的图像元素以单根对象树管理&#xff0c;默认情况下根对象就是显示器的活动显示器——act_scr&#xff0c;在显示器注册时创建,参见lv_disp_drv_register。 应用也可以自己创建screen的根对象&…

机器学习与模式识别作业----决策树属性划分计算

文章目录 1.决策树划分原理1.1.特征选择1--信息增益1.2.特征选择2--信息增益比1.3.特征选择3--基尼系数 2.决策树属性划分计算题2.1.信息增益计算2.2.1.属性1的信息增益计算2.2.2.属性2的信息增益计算2.2.3.属性信息增益比较 2.2.信息增益比计算2.3.基尼系数计算 1.决策树划分原…

CentOS yum update

详情内容 CentOS yum update升级命令详解&#xff0c;包括yum check-update&#xff0c;yum update&#xff0c;yum install等升级安装命令详细使用方法。 1.列出所有可更新的软件清单 命令&#xff1a; yum check-update 2.安装所有更新软件 命令&#xff1a; yum updat…

倾斜摄影三维模型的顶层构建的问题分析

倾斜摄影三维模型的顶层构建的问题分析 在构建倾斜摄影超大场景的三维模型时&#xff0c;常见的顶层构建问题可能包括以下几个方面&#xff1a; 1、数据质量问题&#xff1a;倾斜摄影所获取的原始数据可能存在噪点、缺失、重叠或者变形等问题&#xff0c;这些问题会直接影响到…