目的
便于后续自己的 CTRL+C,V的面向复制、粘贴编程
思路
非常简单:可以使用 perlin noise,simple noise 或是其他的 noise 函数,又或是 noise tex 来提取顶点 xyz 的偏移
然后 vs 里便宜就好了,需要阴影跟随飘动的投影就加上 “LightMode”=“ShadowCaster” 的 pass
Script
include cginc
#ifndef __WIND_COMMON_H__
#define __WIND_COMMON_H__
#include "UnityCG.cginc"
#if defined(_WIND_ON)
half _WindSpeed;
half _WindWavesScale;
half _WindForce;
half4 _WindDir;
half _MoveHeight;
half _MoveHeightPow;
float3 mod3D289(float3 x) { return x - floor(x / 289.0) * 289.0; }
float4 mod3D289(float4 x) { return x - floor(x / 289.0) * 289.0; }
float4 permute(float4 x) { return mod3D289((x * 34.0 + 1.0) * x); }
float4 taylorInvSqrt(float4 r) { return 1.79284291400159 - r * 0.85373472095314; }
float snoise(float3 v)
{
const float2 C = float2(1.0 / 6.0, 1.0 / 3.0);
float3 i = floor(v + dot(v, C.yyy));
float3 x0 = v - i + dot(i, C.xxx);
float3 g = step(x0.yzx, x0.xyz);
float3 l = 1.0 - g;
float3 i1 = min(g.xyz, l.zxy);
float3 i2 = max(g.xyz, l.zxy);
float3 x1 = x0 - i1 + C.xxx;
float3 x2 = x0 - i2 + C.yyy;
float3 x3 = x0 - 0.5;
i = mod3D289(i);
float4 p = permute(permute(permute(i.z + float4(0.0, i1.z, i2.z, 1.0)) + i.y + float4(0.0, i1.y, i2.y, 1.0)) + i.x + float4(0.0, i1.x, i2.x, 1.0));
float4 j = p - 49.0 * floor(p / 49.0);
float4 x_ = floor(j / 7.0);
float4 y_ = floor(j - 7.0 * x_);
float4 x = (x_ * 2.0 + 0.5) / 7.0 - 1.0;
float4 y = (y_ * 2.0 + 0.5) / 7.0 - 1.0;
float4 h = 1.0 - abs(x) - abs(y);
float4 b0 = float4(x.xy, y.xy);
float4 b1 = float4(x.zw, y.zw);
float4 s0 = floor(b0) * 2.0 + 1.0;
float4 s1 = floor(b1) * 2.0 + 1.0;
float4 sh = -step(h, 0.0);
float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
float3 g0 = float3(a0.xy, h.x);
float3 g1 = float3(a0.zw, h.y);
float3 g2 = float3(a1.xy, h.z);
float3 g3 = float3(a1.zw, h.w);
float4 norm = taylorInvSqrt(float4(dot(g0, g0), dot(g1, g1), dot(g2, g2), dot(g3, g3)));
g0 *= norm.x;
g1 *= norm.y;
g2 *= norm.z;
g3 *= norm.w;
float4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
m = m * m;
m = m * m;
float4 px = float4(dot(x0, g0), dot(x1, g1), dot(x2, g2), dot(x3, g3));
return 42.0 * dot(m, px);
}
void windNoiseHandle(inout float4 posOS, float modelY, float uv_v)
{
if (_MoveHeight <= 0) return;
float3 positionOS = posOS;
float windSpeed = _Time.y * (_WindSpeed * 5);
float windNoise = snoise((mul(unity_ObjectToWorld, posOS) + windSpeed) * _WindWavesScale);
windNoise = (windNoise * 0.01);
windNoise = (windNoise * pow(modelY / _MoveHeight, _MoveHeightPow));
windNoise = (windNoise * (_WindForce * 30));
posOS.xyz += (_WindDir.xyz * windNoise) * (1 + (sin(_Time.y * 0.5) * 0.5 + 0.5));
}
#define VERT_WIND(wpos, modelY, uv_v) windNoiseHandle(wpos, modelY, uv_v);
#else
#define VERT_WIND(wpos, modelY, uv_v)
#endif
#endif
appled shader
Shader "OnePiece/Legacy Shaders/Transparent/Cutout/Diffuse_DoubleSide_Wind" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
LOD 200
Cull Off
CGPROGRAM
#define _WIND_ON
#pragma surface surf Lambert fullforwardshadows addshadow alphatest:_Cutoff vertex:vert
#include "Includes/CG/WindCommon.cginc"
sampler2D _MainTex;
fixed4 _Color;
struct Input {
float2 uv_MainTex;
};
void vert(inout appdata_full v)
{
VERT_WIND(v.vertex, v.vertex.y, v.texcoord.y)
}
void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
Fallback "Legacy Shaders/Transparent/Cutout/VertexLit"
}
csharp
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
[ExecuteInEditMode]
public class WindArgsController : MonoBehaviour
{
private static int _WindForce = Shader.PropertyToID("_WindForce");
private static int _WindWavesScale = Shader.PropertyToID("_WindWavesScale");
private static int _WindSpeed = Shader.PropertyToID("_WindSpeed");
private static int _WindStrengthen = Shader.PropertyToID("_WindStrengthen");
private static int _WindDir = Shader.PropertyToID("_WindDir");
private static int _MoveHeight = Shader.PropertyToID("_MoveHeight");
private static int _MoveHeightPow = Shader.PropertyToID("_MoveHeightPow");
public bool windToggle = true;
private bool lastWindToggle = false;
[Range(0.0f, 1.0f)]
public float WindSpeed = 0.3f;
private float lastWindSpeed;
[Range(0.0f, 1.0f)]
public float WindStrengthen = 1;
private float lastWindStrengthen = 1;
[Range(0.0f, 1.0f)]
public float WindWavesScale = 0.25f;
private float lastWindWavesScale;
[Range(0.0f, 1.0f)]
public float WindForce = 0.5f;
private float lastWindForce;
public bool DirFromForward = true;
public Vector4 WindDir = new Vector4(1, 0, 0, 0);
private Vector4 lastWindDir;
public float MoveHeight = 5.0f;
private float lastMoveHeight;
[Range(0.001f, 5.0f)]
public float MoveHeightPow = 1.0f;
private float lastMoveHeightPow;
#if UNITY_EDITOR
public float GizmosDirLineSize = 8.0f;
public Color GizmosDirLineColor = Color.green;
public Color GizmosCircleColor = Color.red;
public int GizmosDirHeadCircleLineSegmentNum = 12;
public int GizmosDirHeadCircleLineRadius = 2;
#endif
private void Start()
{
WindDir = transform.forward;
if (windToggle)
Shader.EnableKeyword("_WIND_ON");
else
Shader.DisableKeyword("_WIND_ON");
Shader.SetGlobalFloat(_WindSpeed, WindSpeed);
Shader.SetGlobalFloat(_WindWavesScale, WindWavesScale);
Shader.SetGlobalFloat(_WindForce, WindForce);
Shader.SetGlobalVector(_WindDir, WindDir);
Shader.SetGlobalFloat(_MoveHeight, MoveHeight);
Shader.SetGlobalFloat(_MoveHeightPow, MoveHeightPow);
}
private void Update()
{
if (lastWindToggle != windToggle)
{
lastWindToggle = windToggle;
if (windToggle)
Shader.EnableKeyword("_WIND_ON");
else
Shader.DisableKeyword("_WIND_ON");
}
if (lastWindSpeed != WindSpeed)
{
lastWindSpeed = WindSpeed;
Shader.SetGlobalFloat(_WindSpeed, WindSpeed);
}
if (lastWindStrengthen != WindStrengthen)
{
lastWindStrengthen = WindStrengthen;
Shader.SetGlobalFloat(_WindStrengthen, WindStrengthen);
}
if (lastWindWavesScale != WindWavesScale)
{
lastWindWavesScale = WindWavesScale;
Shader.SetGlobalFloat(_WindWavesScale, WindWavesScale);
}
if (lastWindForce != WindForce)
{
lastWindForce = WindForce;
Shader.SetGlobalFloat(_WindForce, WindForce);
}
if (DirFromForward)
{
WindDir = transform.forward;
}
if (!lastWindDir.Equals(WindDir))
{
lastWindDir = WindDir;
Shader.SetGlobalVector(_WindDir, WindDir);
}
if (lastMoveHeight != MoveHeight)
{
lastMoveHeight = MoveHeight;
Shader.SetGlobalFloat(_MoveHeight, MoveHeight);
}
if (lastMoveHeightPow != MoveHeightPow)
{
lastMoveHeightPow = MoveHeightPow;
Shader.SetGlobalFloat(_MoveHeightPow, MoveHeightPow);
}
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
var transWPos = transform.position;
Vector3 transForward;
if (DirFromForward)
{
transForward = transform.forward;
}
else
{
transForward = WindDir;
}
var srcCol = Gizmos.color;
int count = GizmosDirHeadCircleLineSegmentNum;
float curAngle = 0;
float perIterateAngle = (2.0f * Mathf.PI) / count;
Gizmos.color = GizmosCircleColor;
Gizmos.DrawLine(transWPos, transWPos + transForward * GizmosDirLineSize);
var L2WMat = transform.localToWorldMatrix;
for (int i = 0; i < count; i++)
{
Gizmos.color = GizmosCircleColor;
var cx = Mathf.Cos(curAngle);
var cy = Mathf.Sin(curAngle);
var cv = new Vector3(cx, cy, 0) * GizmosDirHeadCircleLineRadius;
cv = L2WMat.MultiplyVector(cv);
curAngle += perIterateAngle;
var nx = Mathf.Cos(curAngle);
var ny = Mathf.Sin(curAngle);
var nv = new Vector3(nx, ny, 0) * GizmosDirHeadCircleLineRadius;
nv = L2WMat.MultiplyVector(nv);
Gizmos.DrawLine(transWPos + cv, transWPos + nv);
Gizmos.color = GizmosDirLineColor;
Gizmos.DrawLine(transWPos + cv, transWPos + cv + transForward * GizmosDirLineSize);
}
Gizmos.color = srcCol;
}
#endif
}
效果
|