模仿草的運動 – GPU(Pixel Shader & Vertex Shader)實作
介紹
随着硬體的不斷更新模仿草的運動不在需要循環播放一個重複的動畫了,GPU的強大性能使得模仿更真實的草的運動得以實作。是以(^_^ )下面介紹做一模仿草的運動的Demo。
原理
1.泰勒級數的定義:
圖1:泰勒級數公式
2. 泰勒級數在幂級數展開中的應用:
圖2:泰勒級數在幂級數中的展開
3. 波動:
草的波浪起伏運動用一個Vertex Shader完成。草片紋理是一個四方行(如圖2),草的渲染可以通過随機放置交叉的草片紋理。對草片紋理通過Alpha測試(Alpha Test)處理讓草片紋理上面黑色部分象素不能通過。草的運動通過給草片紋理所貼的四邊形上面兩點混合四個正弦波(Sinusoidal),正弦波通過泰勒級數來逼近(泰勒級數如圖1、泰勒級數展開如圖2),用不同頻率産生混合正弦波所形成的草的自然波就不像固定動畫那樣死闆。
圖2:草片紋理
4. 光照模型
草片紋理在風中飄動,它将會改變方向,随着太陽産生不同的顔色,面向太陽時草片的顔色比背向太陽時草片的顔色會亮一些。本例是通過一個草片紋理産生不同方向和位置的草片,是以不可能通過改變單個草片的光照來改變整個場景的草的顔色。而草片顔色的改變是發生在草片的運動過程中,是以可以通過正弦波來産生顔色,同一個正弦波根據光照方向可以産生兩個顔色,通過改變綠通道的顔色使得草片顔色在微黃色和褐色之間變更(如圖3、4)。
圖3:面向太陽的微黃色的草
圖4:背向太陽的褐色的草
實作
1. Vertex Shader
Sinusoidal vertex motion for waving grass
pos + sumOverI(wavedirI * texcoordy * sin( xdirI * (xpos+time)) + ydirI * (ypos+time)))
v0 - Vertex Position
v7 - Vertex Texture Data u,v
c0 - commonConst ( 0.0, 0.5, 1.0, 2.0);
c1 - appConst( time, 0.0, 0.0, 0.0);
c4 - Composite World-View-Projection Matrix
c8 - sin9 ( -1/3!, 1/5!, -1/7!, 1/9! )
c10 - frcFixup ( 1.07, 0.0, 0.0, 0.0)
c11 - waveDistortx ( 3.0, 0.4, 0.0, 0.3)
c12 - waveDistorty ( 3.0, 0.4, 0.0, 0.3)
c13 - waveDistortz ( -1.0, -0.133, -0.333, -0.10)
c14 - waveDirx ( -0.006, -0.012, 0.024, 0.048)
c15 - waveDiry ( -0.003, -0.006, -0.012, -0.048)
c16 - waveSpeed ( 0.3, 0.6, 0.7, 1.4)
c17 - piVector (4.0, pi/2, pi, pi*2)
c18 - lightingWaveScale ( 0.35, 0.10, 0.10, 0.03);
c19 - lightingScaleBias ( 0.6, 0.7, 0.2, 0.0);
// vs.2.x for grass
vs_2_x
dcl_position v0
dcl_texcoord v7
mul r0, c14, v0.x // use vertex pos x as inputs to sinusoidal warp
mad r0, c15, v0.y, r0 // use vertex pos y as inputs to sinusoidal warp
mov r1, c1.x // get current time
mad r0, r1, c16, r0 // add scaled time to move bumps according to speed
frc r0.xy, r0 // take frac of all 4 components
frc r1.xy, r0.zwzw //
mov r0.zw, r1.xyxy //
mul r0, r0, c10.x // multiply by fixup factor (due to inaccuracy of taylor series)
sub r0, r0, c0.y // subtract 0.5
mul r1, r0, c17.w // r0 *= 2pi coords range from(-pi to pi)
mul r2, r1, r1 // (wave vec)^2
mul r3, r2, r1 // (wave vec)^3
mul r5, r3, r2 // (wave vec)^5
mul r7, r5, r2 // (wave vec)^7
mul r9, r7, r2 // (wave vec)^9
mad r0, r3, c8.x, r1 // (wave vec) - ((wave vec)^3)/3!
mad r0, r5, c8.y, r0 // + ((wave vec)^5)/5!
mad r0, r7, c8.z, r0 // - ((wave vec)^7)/7!
mad r0, r9, c8.w, r0 // + ((wave vec)^9)/9!
dp4 r3.x, r0, c11
dp4 r3.y, r0, c12
dp4 r3.zw, r0, c13
sub r4, c0.z, v7.y
mul r4, r4, r4
mul r3, r3, r4 // attenuate sinusoidal warping by (1-tex0.y)^2
mov r2.w, v0
add r2.xyz, r3, v0 // add sinusoidal warping to grass position
m4x4 oPos, r2, c4
dp4 r1.x, r0, c18 // scale and add sin waves together
mad oD0, c19.xzxz, -r1.x, c19.y
mov oT0, v7 // scale and bias color values (green is scaled more than red and blue)
此段代碼是用于渲染地面,如用上面的代碼,那麼地面也會跟着波動。
// vs.2.x for ground
vs_2_x
dcl_position v0
dcl_texcoord v7
m4x4 oPos, v0, c4
mov oT0, v7
mov r0, c20
add oD0, r0, c21
2. Pixel Shader
// ps.1.4 for grass
ps_1_4
texld r0, t0
mul_x2 r0, r0, v0
感覺現在ps.3.x都出來了(雖然我的機器不支援),而我還用ps.1.4有點落後了,是以今天用ps.2.x重寫了ps的渲染代碼。
// ps.2.x for grass
ps_2_x
dcl_2d s0
dcl t0
dcl v0
texld r0, t0, s0
mul r0, r0, v0
add r0, r0, r0
mov oC0, r0
本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/genius_wu/archive/2006/06/27/840382.aspx