[程式] 做出發光效果 (用shader/Godot)

看板GameDesign (遊戲設計)作者 (meowyih)時間3年前 (2021/07/02 21:21), 3年前編輯推噓3(300)
留言3則, 3人參與, 3年前最新討論串1/1
這篇的圖片和範例出處是 GDQuest shader secret 的 BlurGlowDemo 連結 https://github.com/GDQuest/godot-shaders 算是讀書報告吧? 目標是用 shader language 在下面的圖片背後加上神秘的光芒 https://i.imgur.com/5RC7n1X.png
[Step 1] 首先用下面的 shader 做個剪影 shader_type canvas_item; uniform vec4 glow_color : hint_color = vec4(1.0); void fragment() { vec4 color = texture(TEXTURE, UV); COLOR = vec4(glow_color.rgb, color.a); } 就把每個 UV 顏色 換成預計要的發光色 glow_color https://i.imgur.com/YG1EwuM.png
[Step 2] 再來用高斯亂數雜訊 對 X 軸做模糊化 (ex: blur_scale = (4,0)) shader_type canvas_item; const float SAMPLES = 71.0; const float PI2 = 6.283185307179586476925286766559; uniform vec2 blur_scale = vec2(1, 0); float gaussian(float x) { float x_squared = x*x; float width = 1.0 / sqrt(PI2 * SAMPLES); return width * exp((x_squared / (2.0 * SAMPLES)) * -1.0); } void fragment() { vec2 scale = TEXTURE_PIXEL_SIZE * blur_scale; float weight = 0.0; float total_weight = 0.0; vec4 color = vec4(0.0); for(int i=-int(SAMPLES)/2; i < int(SAMPLES)/2; ++i) { weight = gaussian(float(i)); color += texture(TEXTURE, UV + scale * vec2(float(i))) * weight; total_weight += weight; } COLOR = color / total_weight; } https://i.imgur.com/HixMdyz.png
[Step 3] 然後模糊化的圖形基礎上 用同樣的方法對 Y 軸做模糊化 (ex: blur_scale = (0,4)) https://i.imgur.com/66R0DyM.png
需注意的地方是, 這要分二個步驟做, 一次同時模糊化 X/Y 結果是如下的類 shear matrix 的效果 (ex: blur_scale = (4,4)) 這不是我們要的 https://i.imgur.com/tMR3shc.png
[Step 4] 最後, 用下面的 shader 把 1. 一開始的剪影 (prepass_texture) 2. 模糊化的影像 (blur_texture) 3. 機器人的原圖 (TEXTURE) 三個合體,產生最後的圖 shader_type canvas_item; uniform sampler2D prepass_texture; uniform sampler2D blur_texture; uniform float glow_intensity; void fragment() { vec4 color = texture(TEXTURE, UV); vec4 prepass = texture(prepass_texture, UV); vec4 blurred = texture(blur_texture, UV); vec3 glow = max(vec3(0.0), blurred.rgb-prepass.rgb); vec3 out_color = color.rgb + glow.rgb * glow_intensity; COLOR = vec4(out_color, clamp(out_color.r + out_color.g + out_color.b, 0, 1)); } https://i.imgur.com/9TQmsVq.png
如果拿掉上面的機器人圖長這樣 https://i.imgur.com/39nwpiQ.png
完成了 更改剪影顏色可以改光的顏色 更改最後的 glow_intensity 或模糊化的 blur_scale 可以更改光暈或亮度 ================== 然後是 Godot 實作相關 當 shader 裡要取得前幾個步驟的圖片的像素, 需要用 ViewPort Texture。 所以範例裏做剪影用了一個 viewport, 模糊化X/Y各用一個 viewport, 最後合體也用了一個 viewport, 然後因為 shader 或 Godot 需要, 每個 ViewPortContainer 要改 size 然後 viewport 要改 1. size 2. transparent_bg = true 3. Usage = 2D 4. Update Mode = Always 然後 viewport 需要用 ViewPortContainer (VPC) 包起來 因此檔案架構像是這樣 +Blur_Y (VPC, 模糊圖) + viewport + Blur_X (VPC) + viewport + Prepass (VPC) + Sprite (機器人圖) +MainView (VPC, 合體) + viewport + Sprite (機器人圖) 範例看起來很複雜, 不過做的事就上面寫的那些 ================= 如果到 Youtube 上找 Godot 2D Glow Effect, 會找到好幾個用 WorldEnvironment -> Glow 來做發光的範例, viewport 裡面可以加獨立的 Environment 用裡面的 Glow 效果做出來的長相是 https://i.imgur.com/q9He3K3.png
你可以看出來 雖然都叫 Glow 但這是完全不同的效果 如果想要類似的效果 我預想是可以先用 shader 做剪影 再對剪影套用 WorldEnvironment Glow, 再蓋上原圖的作法 不過這部分是我猜想的 實驗部份我就不做了 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.231.97.136 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/GameDesign/M.1625232088.A.011.html ※ 編輯: meowyih (36.231.97.136 臺灣), 07/02/2021 21:23:39 ※ 編輯: meowyih (36.231.97.136 臺灣), 07/03/2021 10:08:45

07/03 16:31, 3年前 , 1F
推認真
07/03 16:31, 1F

07/04 11:03, 3年前 , 2F
推,很清楚的步驟,感謝分享
07/04 11:03, 2F

07/04 13:07, 3年前 , 3F
講學推
07/04 13:07, 3F
文章代碼(AID): #1WtnBO0H (GameDesign)
文章代碼(AID): #1WtnBO0H (GameDesign)