iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 15
1
Modern Web

寫給工程師的 WebGL 學習心得系列 第 15

[WebGL - Day15] Shadertoy - 與使用者滑鼠互動

  • 分享至 

  • xImage
  •  

今天討論與使用者滑鼠互動


先前的文章提到, Shadertoy 有內建滑鼠輸入 iMouse

uniform vec4 iMouse;

iMouse 是 vec4,也就是有 4 個值 (x, y, z, w)

howto 頁裡,沒有實際說明 iMouse 的四個值的意義,
而是在 Special Shadertoy features 這篇提到, iMouse 的 .xy.zw 的值

  • iMouse.xy: last mouse click or current mouse drag position.
    ( Attention: these are integers, while pixels are between integers. )
  • iMouse.zw:
    大於 0: starting drag position.

.zw 相當特別,
大於 0: starting drag position.
滑鼠放開的時候, .zw 會回傳的座標 (#註1)


Demo:mouse
mouse
這個 Demo 用 iMouse 實作了:

  • mouseDown:滑鼠按下時,畫面上有紅點、藍點、畫面會填滿透明度 0.25 的綠色
  • mouseMove:紅點跟著滑鼠移動,畫面維持透明度 0.25 的綠色
  • mouseUp:藍點停留在最後 mouseDown 位置,紅點停留在最後 mouseUp 的位置,綠色消失

程式碼

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
  vec2  uv = (fragCoord.xy / iResolution.xy);
  vec4  m  = iMouse / iResolution.xyxy;
  float m0 = (m.z > 0.0) ? 0.25 : 0.0;
  float m1 = smoothbump(m.x,0.05,uv.x) *
             smoothbump(m.y,0.05,uv.y);
  float m2 = smoothbump(abs(m.z),0.05,uv.x) *
             smoothbump(abs(m.w),0.05,uv.y);
  fragColor = vec4(m1,m0,m2,1.0);
}

輸出時使用三個顏色表示滑鼠的各種狀態:

fragColor = vec4(m1, m0, m2, 1.0);
  • m1(R),紅色
  • m0(G),綠色
  • m2(B),藍色

以下分項解說


m0(G),綠色

滑鼠 mousedown 時是綠色,滑鼠放開時綠色消失
mouse
(為方便對照,再貼一次 Gif)
程式碼

float m0 = (m.z > 0.0) ? 0.25 : 0.0;
fragColor = vec4(m1,m0,m2,1.0);

m.z > 0.0 時, m0 (G) 的值是 0.25,輸出畫面會偏綠

m.z 值,對應滑鼠座標的 uv.x,
m.w 值,對應滑鼠座標的 uv.y

當滑鼠按下時,會取得點擊座標 uv.x (正值)
當滑鼠放開時,顯示為點擊座標 *-1,此時 m.z 與 m.w 皆為負值
(乘上負1 在下方會補充說明)
m.z <= 0.0 時, m0 (G) 的值是 0.0,畫面不輸出綠色
Shadertoy 使用這樣的方式判斷 mousedown 事件


m1(R),紅色

滑鼠在 mousedown、mousemove、mouseup 時,紅點跟著畫面移動
mouse
(為方便對照,再貼一次 Gif)
程式碼

float m1 = smoothbump(m.x,0.05,uv.x) *
           smoothbump(m.y,0.05,uv.y);
fragColor = vec4(m1,m0,m2,1.0);

相較 m0、 m2 單純, m1 (R) 在 mousedown、mousemove、mouseup 時
皆顯示 滑鼠的座標


m2(B),藍色

滑鼠在 mousedown 時,藍點出現在滑鼠最後 mousedown 的位置
滑鼠在 mouseup 時,藍點出現在滑鼠最後 mousedown 的位置
mouse
(為方便對照,再貼一次 Gif)

程式碼

float m2 = smoothbump(abs(m.z),0.05,uv.x) *
           smoothbump(abs(m.w),0.05,uv.y);
fragColor = vec4(m1,m0,m2,1.0);

m2(B) 使用 m.z 與 m.w 座標繪製位置,與 m0(G) 的情形類似
而 m.z 值得變化情形為 (m.w) 相同,對應的是 uv.y:
當滑鼠 mousedown 時,會取得點擊座標 uv.x (正值)
當滑鼠 mouseup 時,顯示為點擊座標 *-1

也因此要在畫面上顯示 mousedown 的座標,且在滑鼠放開時
點仍留在畫面上
因此需要使用 abs(m.z)abs(m.w) ,取 m.z 與 m.w 的絕對值 (#註1)


註1:

左下角滑鼠座標,在滑鼠放開時顯示為點擊時座標 乘上-1
可實際於 Demo:iResolution, iMouse, iDate, etc 操作:
iResolution, iMouse, iDate, etc
如錄製 Gif 左下角的兩次示意:
兩次示意的座標 (-150,-213) 與 (-136,-208),
在滑鼠點下移動時維持在點下的座標
滑鼠放開時瞬間 乘上-1
若不特別處理,輸出結果可能會與想像不同

註2:

m1 與 m2 使用相乘的方式取點,
可參考:
[WebGL - Day14] Shadertoy - 加減乘除好吃驚、用 Shader 做遮罩

Mouse Multiply
(示意分別為取 uv.x, uv.y, uv.x*uv.y 三種狀態)


使用 iMouse 試做效果

既然 iMouse 是 Shadertoy 提供的方法,自然只有在 Shadertoy 裡可以使用
實際在寫 Shader 的程式時,也可能不一定會照著 Shadertoy 的 iMouse 實作

即使 iMouse 有些不直覺,
但在 Shadertoy 使用 iMouse 事件來模擬之後的結果,
也是相當有效的實作方式

例:
Mouse Interactive


上一篇
[WebGL - Day14] Shadertoy - 加減乘除好吃驚、用 Shader 做遮罩
下一篇
[WebGL - Day16] Shadertoy - 使用文字
系列文
寫給工程師的 WebGL 學習心得30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言