自言自语
很早以前学B站一个UP主的东西。今天突然想起来。果然发现看不懂了。不理解了。然后自己又啃了一遍。总算理解了。并且发现了一些不合适的地方。进行了改进和注释。Shader是URP的。要搬到builltin也是非常容易的。存档以后使用和继续改进
一、效果和面板
因为是结合粒子系统做的。利用粒子系统的各个流数据。以及粒子系统本身可以拿到的数据来进行计算 如果要让特效使用的舒服就尽量集成到粒子系统吧 反正我是这么干的。
二、Shader
Shader "FX_Partical/fx_CubeTransformParticlesAutoV2.0"
{
Properties
{
[Header(Tips)]
_Tips("===========注释说明参数本身无意义==================================================",int) =0
[Space(20)]
_1x("Custom1 . x 正数为纵向发射 负数为横向发射",int)=0
[Space]_7x(" x的绝对值的大小决定了拉扯长度",int)=0
[Space]_2x(" y 正反 1 向上 向左发射 -1 为向下 向右发射",int)=0
[Space]_3x(" z 从内到外还是从外到内发射用曲线控制",int)=0
[Space] _4x("w 是方块边缘条的宽窄控制--可以曲线控制",int)=0
[Space][Space][Space][Space]
[Space(20)] _5x("Custom2 就是Color 是控制方块内部颜色的 ",int)=0
[Header(Tips)]
_Tips("===========边缘颜色强度值参数影响颜色强度==================================================",int) =0
[Space] _6x("方块边缘颜色为 粒子编辑器上的传统颜色条乘以了10 调色时 适当降低明度",float)=0
// y 正反 1 向上 向左发射 -1 为向下 向右发射
// z 拉扯长度值
// w 是方块边缘条的宽窄控制
// Custom2 就是Color 是控制方块内部颜色的
// 粒子编辑器上的传统颜色条是控制方块边缘颜色的 由于这个传统颜色条不支持HDR 因此shader中给这个颜色乘以了10 调色时 适当降低明度
//size就是控制缩放朝向...用overlifetime
}
SubShader
{
//定义管线为
Tags { "RenderType"="Opaque" "RenderPipeline" ="UniversalPipeline" }
LOD 100
Pass
{
Blend Off
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
// -------------------------------------
// Unity defined keywords
#pragma multi_compile_fog
#pragma multi_compile_instancing
#pragma multi_compile_particles
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
float _Length;
float _6x;
CBUFFER_END
struct a2v
{
//这里对应的 粒子系统的 custom vertex stream的存储语义
float4 vertex : POSITION;
//从粒子编辑器里传过来的center参数存在 TEXCOORD1中. 对于Cube来说 中心点为000
float3 center : TEXCOORD1;
float4 color : COLOR;
float4 uv : TEXCOORD0;
float4 Custom1 : TEXCOORD2;
//粒子系统的size信息经测试是可以直接传进来的
float3 size : TEXCOORD3;
float4 CustomeColor : TEXCOORD4;
//同样的顶点信息 输入 这几句话还是关于顶点动画的 URP下要做顶点动画 就得把这几句话写上
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float2 uv : TEXCOORD0;
float fogCoord : TEXCOORD3;
float4 vertexColor : COLOR;
float4 pos : SV_POSITION;
float3 posWS : TEXCOORD5;
//引入粒子系统的vertexstream
float4 Custom1 : TEXCOORD1;
float4 CustomCol : TEXCOORD4;
float4 posOS : TEXCOORD6;
//这两句是指我们要定义 顶点信息的输入和输出 也就是说有这才能拿到顶点信息进行顶点动画
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(a2v v)
{
v2f o = (v2f)0;
//v2f o;
//第一句话是使shader支持 GPUinstance 第二句话是使我们进行的顶点动画
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
//得到世界空间坐标顶点坐标作为标准参考值
o.posWS = TransformObjectToWorld(v.vertex.xyz);
//让粒子系统本身的color值能够影响到模型本身顶点色
o.vertexColor = v.color;
//自定义颜色流 传入shader中
o.CustomCol =v.CustomeColor;
//计算z增量对x y的位移坐标影响
float p0 = o.posWS.y+v.Custom1.z;
float p1 = o.posWS.x+v.Custom1.z;
//这里用来控制缩放从0到大粒子本身大小随着overlifetime size 的变化 最终变化为1
v.vertex.xyz = lerp(v.center,v.vertex.xyz,saturate(v.size));
//通过Custom1.y 来设置竖直方向 -1 为正 1 为负
//通过tep(0,v.Custom1.x); 来开关 是否在Y轴或者X轴上进行移动 Clamp 用来限制值为-1,1 因为只需要方向 不需要大小变化 也可以用if来写 不过step来做开关性能更好
//顶点动画的两轴缩放算法。p-2 是为了区分原本的p 这样可以区分缩放 拉伸 以及颜色变化 不过颜色变化已经融合到粒子系统中 因此这里没有使用p-1
v.vertex.y += max(0,(p0-2)*abs(v.Custom1.x))*clamp(v.Custom1.y,-1,1)* step(0,v.Custom1.x);
v.vertex.x += max(0,(p1-2)*abs(v.Custom1.x))*clamp(v.Custom1.y,-1,1)*step(v.Custom1.x,0);
//这里计算各个空间的顺序不要高反了 先进行顶点动画 然后再进行空间变换把顶点弄到齐次坐标裁剪空间
VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
雾效的计算 可以不用
//o.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
o.pos = vertexInput.positionCS;
//将变化的数值传入片元 用作修正UV因模型拉伸而造成的边框拉伸
o.posOS =float4(v.vertex.x,v.vertex.y,0,0);
o.Custom1 = v.Custom1;
o.uv =v.uv.xy;
return o;
}
half4 frag(v2f i) : SV_Target
{
//第一句话是使shader支持 GPUinstance 第二句话是使我们进行的顶点动画
UNITY_SETUP_INSTANCE_ID(i);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
//abs(i.uv.x-0.5)*2 是为了把UV分布改成 对称分布的 1 0 1 这样 做中间向两边扩散的动画效果
//此处用abs是因为他会取绝对值, 用saturate就不行 因为saturate映射是小于0的也就取0了 不能做对称
//通过用Custom1.w 来设置边的宽窄 abs(i.uv.x-0.5)*0.125*i.posOS.x 没什么道理 就是修正下模型拉伸时对UV拉伸的影响程度
float edge =step(abs(i.uv.x-0.5)*2,(1-i.Custom1.w)+abs(i.uv.x-0.5)*0.125*i.posOS.x)*step(abs(i.uv.y-0.5)*2,(1-i.Custom1.w)+abs(i.uv.y-0.5)*0.125*i.posOS.y);
//给顶点色乘以一个系数_6x, 让他能够颜色值大于1 这样能出光晕效果
half4 color = lerp(i.CustomCol,i.vertexColor*_6x,1-edge);
return color;
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
//CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.UnlitShader"
}
总结
真的是猴子搬苞米。边学边忘啊。不过总归还是能有所进步,至少能进行优化修改了。 继续加油