以前的部落格有提到如何實作植被擺動的效果:點選打開連結
核心問題就是,擺動的幅度是根據什麼樣的權重.我簡單分為三種.
1.UV坐标作為權重
2.頂點到模型原點的距離作為權重
3.頂點顔色作為權重
以CE3引擎來講,整體擺動用第二種,細節抖動用第三種,兩種結合使用,就可以實作完美的擺動效果.但是用第二種,就不能用靜态合批了.因為靜态合批以後,模型的原點就變了,這個權重的計算也是錯誤的了.如果要用靜态合批還要完美的擺動,怎麼辦呢?
我想到一個辦法,就是把第二種的權重,儲存到頂點顔色的一個通道裡面,這樣即使靜态合批了,這個權重值也不會改變的,那麼問題來了,如何儲存呢.打開3DMAX的頂點顔色繪制工具,你會發現根本就刷不出這種權重值,那麼隻能程式來生成了,是以我就用3DMAX的腳本語言寫了一個工具來自動生成這個整體擺動的權重.
工具界面:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gzNwIDMyETMyUDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
我用藍色通道來儲存這個整體擺動權重值.
過渡曲線我嘗試了幾種:
權重過渡支援從上到下或者從下到上,這樣的好處是可以支援燈籠這種倒挂物件的擺動.
至于頂點擺動的代碼,可參考Unity官方地形的植被動畫的代碼,其實都是從CE3改進過來的,我的有改寫過:
inline float4 AnimateVertex2(float4 pos, half3 normal, fixed4 animParams, float4 wind)
{
// animParams stored in vertext color
// animParams.x = branch phase = unused
// animParams.y = edge bending factor = green
// animParams.z = branch bending factor = red
// animParams.w = main bending factor = blue
float fDetailAmp = 0.1f;
float fBranchAmp = 0.3f;
// Phases (object, vertex, branch)
float fObjPhase = dot(unity_ObjectToWorld[3].xyz, 1);
float fBranchPhase = fObjPhase;// + animParams.x;
float fVtxPhase = dot(pos.xyz, animParams.y + fBranchPhase);
// x is used for edges; y is used for branches
float2 vWavesIn = _EdgeFrequencyFactor * _Time.yy + pos.xz *.3 + float2(fVtxPhase, fBranchPhase );
float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0);
vWaves = SmoothTriangleWave( vWaves );
float2 vWavesSum = vWaves.xz + vWaves.yw;
// Edge (xz) and branch bending (y)
// sign important to match normals of both faces!!! otherwise edge fluttering will be corrupted.
float3 bend = animParams.y * fDetailAmp * normal.xyz * sign(normal.xyz) * _EdgeBendingFactor;
bend.y = animParams.z * fBranchAmp * _BranchBendingFactor;
pos.xyz += vWavesSum.xyx * bend * wind.w;
// main bending
float3 mainBend = wind.xyz * wind.w * animParams.w * _MainBendingFactor;
pos.xyz += mainBend * vWavesSum.y * _MainBendingFactor2;
pos.xyz += mainBend;
return pos;
}
max腳本:
Utility LuoyinanVertexColorTool "LuoyinanVertexColorTool"
(
global g_CurveType = "cubic"
global g_FadeDirection = "up"
Dropdownlist ddlist "Curve Type:" items:#("cubic","quadratic","linear")
on ddlist selected i do
g_CurveType = ddlist.items[i]
Dropdownlist ddlist2 "Fade Direction:" items:#("up","down")
on ddlist2 selected i do
g_FadeDirection = ddlist2.items[i]
button b "Start Paint"
on b pressed do
(
for selectNode in selection do
(
Recursion selectNode
)
)
)
fn Recursion node=
(
if (Editable_mesh == classOf node) then
(
ModifyVertexColor node
)
else
(
for i = 1 to node.children.count do Recursion node.children[i]
)
)
fn ModifyVertexColor node=
(
addModifier node (vertexPaint())
collapseStack node
theMesh = node.mesh
numtverts = getNumVerts theMesh
print (format "g_CurveType:% g_FadeDirection:%\n" g_CurveType g_FadeDirection)
print (format "name:% numfaces:% numtverts:% numcpvverts:% getNumVerts:%\n" node.name theMesh.numfaces theMesh.numtverts theMesh.numcpvverts numtverts)
minHeight = 100000
maxHeight = -100000
for v = 1 to numtverts do
(
vert = getVert theMesh v
if (vert.z > maxHeight) then (maxHeight = vert.z)
if (vert.z < minHeight) then (minHeight = vert.z)
)
for f = 1 to theMesh.numfaces do
(
face = getFace theMesh f
v1 = getVert theMesh face.x
v2 = getVert theMesh face.y
v3 = getVert theMesh face.z
w1 = (v1.z - minHeight) / (maxHeight - minHeight)
w2 = (v2.z - minHeight) / (maxHeight - minHeight)
w3 = (v3.z - minHeight) / (maxHeight - minHeight)
if (g_FadeDirection == "down")then
(
w1 = 1 - w1
w2 = 1 - w2
w3 = 1 - w3
)
if (g_CurveType == "cubic") then
(
w1 = 2 * w1 * w1 * w1 / (1 + w1)
w2 = 2 * w2 * w2 * w2 / (1 + w2)
w3 = 2 * w3 * w3 * w3 / (1 + w3)
)
else if (g_CurveType == "quadratic") then
(
w1 = 2 * w1 * w1 / (1 + w1)
w2 = 2 * w2 * w2 / (1 + w2)
w3 = 2 * w3 * w3 / (1 + w3)
)
vc_face = getVCFace theMesh f
vc1 = getVertColor theMesh vc_face.x
vc2 = getVertColor theMesh vc_face.y
vc3 = getVertColor theMesh vc_face.z
vc1.b = w1 * 255
vc2.b = w2 * 255
vc3.b = w3 * 255
setVertColor theMesh vc_face.x vc1
setVertColor theMesh vc_face.y vc2
setVertColor theMesh vc_face.z vc3
)
update theMesh
)
至于MAX腳本的如何使用,請自行百度...