HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2022
0214
youdaiHGIMG4で画像を波紋で波立たせるポストエフェクトを実装したい2解決


youdai

リンク

2022/2/14(Mon) 08:22:17|NO.95410

HGIMG4で画像を波紋で波立たせるポストエフェクトを実装したいです。

波紋というのは水に石などを投げたときにできる、輪になって広がっていく波の模様のことです。
その波紋を法線の向きとして実装できれば、その法線で画像が波紋で波立ったようなポストエフェクトが
できるのではないのかと思ったのですが、複雑でよく分かりません。

要はsin関数やcos関数等で生成される輪を、法線xを-1.0~1.0で、法線yを-1.0~1.0で波紋として描写すれば
波紋としての法線が生成できるのではないかと思います。

それから生成した波紋の数だけforでリピート処理をして法線を処理すれば、
波紋が波立ったような法線が生成できるのではないでしょうか。

以下のフラグメントシェーダーファイルはあくまで作りかけのイメージでしかないのですが、
こういった雰囲気のものを想定して作っていました。

p_normalRipple.frag


// Uniforms uniform texture2D u_texture; uniform float u_radius; // 波紋の発生中心位置のUV座標 uniform float u_power; // 波紋の高さの強さ uniform float u_time; // 経過時間 uniform float u_aspect; // 画面のアスペクト比。波紋を正円にする時に必要? // Varyings varying vec2 v_texCoord; /* normalRipple_computeの引き数について uv = 波紋の発生中心位置のUV座標 radius = 波紋の半径 power = 波紋の高さの強さ time = 経過時間 */ vec3 normalRipple_compute (vec2 uv, float radius, float power, float time) { vec3 normal; // 法線 // 何らかの処理 return normal; } // main void main() { vec3 normal; // 波紋の数だけ繰り返す // RIPPLE_COUNTはdefsで指定する波紋の数 for (int i = 0; i < RIPPLE_COUNT; ++i) { normal += normalRipple_compute(v_texCoord, u_radius, u_power, u_time); } vec2 uv = normal.xy; vec3 result = sampler2D(u_texture, uv); gl_FragColor = vec4(result ,1.0); }

頂点シェーダーについてはポストエフェクトなため、通常と変わりません。

p_normalRipple.vert


// Attributes attribute vec3 a_position; attribute vec2 a_texCoord; attribute vec4 a_color; // Uniforms uniform mat4 u_projectionMatrix; // Varyings varying vec2 v_texCoord; void main() { gl_Position = u_projectionMatrix * vec4(a_position, 1); v_texCoord = a_texCoord; }

アドバイスお願い致します。



この記事に返信する


usagi

リンク

2022/2/15(Tue) 04:31:05|NO.95426

一例として、
ポストエフェクトは2Dなので、法線計算はしないでシンプルにテクスチャ座標の参照をsin関数でシフトしてみました。
とりあえず中心から同心円状に波紋が一つ出る感じにしてみています。
おまけでcosは90°位相がズレますので、テクセルに乗算して簡易影つけてます。

・wave.vert は sprite.vartと一緒(コピペ)

・wave.frag

uniform sampler2D u_texture; uniform float u_frequency; uniform float u_phase; uniform float u_amplitude; uniform float u_attenuation; varying vec2 v_texCoord; varying vec4 v_color; const float E = 2.718281828459045; const float PI = 3.141592653589793; const float PI2 = PI * 2.0; void main() { vec2 p = v_texCoord * 2.0 - 1.0; // 0~1を-1~1に変換 float dist = 1.0 - length(p); // ①中心からの距離 1~-inf float atte = exp(1.0 - length(p) * u_attenuation) / E; // ②中心からの減衰 1~0 float theta = PI2 * u_frequency * dist; // 周波数 theta += u_phase; // 位相 float amp = sin(theta) * u_amplitude * atte; // ③振幅 vec2 uv = v_texCoord + normalize(p) * amp; // テクスチャ座標に波紋加算 uv = clamp(uv, 0.01, 0.99); // 端を繰り返すならコメントアウト gl_FragColor = texture2D(u_texture, uv); // 確認用 =================================== // ①中心からの距離表示 //gl_FragColor = vec4(vec3(dist), 1.0); // ②中心からの減衰表示 //gl_FragColor = vec4(vec3(atte), 1.0); // ③振幅表示 //gl_FragColor = vec4(vec3(amp*0.5+0.5), 1.0); // オマケ影 不要ならコメントアウト float light = (1.0 + (cos(theta)+1.0)*atte*0.1); vec3 col = texture2D(u_texture, uv).rgb * light; gl_FragColor = vec4(col, 1.0); }

・動作サンプル

#include "hgimg4.as" s = 512 : div = 32 : mode = 0 freq = 2.0 : amp = 0.01 : attenate = 1.0 : phase = 0.0 screen 0, s,s gpreset gpusershader "wave.vert", "wave.frag", "" buffer 1,s,s,screen_offscreen + screen_usergcopy gpgetmat wave_mat, 1, GPGETMAT_OPT_SCRMAT gpmatprm1 wave_mat, "u_frequency", freq gpmatprm1 wave_mat, "u_amplitude", amp gpmatprm1 wave_mat, "u_attenuation", attenate *GEN_TEX dim bitmap,s*s if mode = 0 {; タイル repeat s*s tcnt = cnt/div : bitmap(cnt) = ((tcnt\s+tcnt/s)\2==0)*$FFC0C0C0-$00404040 loop } else {; カラー repeat s*s tcnt=cnt*256/s : bitmap(cnt) = tcnt\s+((tcnt/s)<<8)+((s-tcnt\s)<<16) loop } celbitmap 1,bitmap gsel 0 *MAIN stick pad,$3e800 : if pad&16 : mode^=1 : goto *GEN_TEX if pad & $04000 : freq-=0.1 if pad & $10000 : freq+=0.1 if pad & $08000 : amp+=0.001 if pad & $20000 : amp-=0.001 if pad & $00800 : attenate = limitf(attenate-0.1, 0.0) if pad & $02000 : attenate+=0.1 if pad { gpmatprm1 wave_mat, "u_frequency", freq gpmatprm1 wave_mat, "u_amplitude", amp gpmatprm1 wave_mat, "u_attenuation", attenate } gpmatprm1 wave_mat, "u_phase", phase : phase += 0.1 redraw 1 : await 16 : redraw 0 : color : boxf pos 0, 0 : celput 1 rgbcolor $FFFFFF : pos 0,0 mes strf("freq: %4.2f, amp: %4.2f, attenate: %4.2f, phase: %4.2f", freq, amp, attenate, phase),4 mes strf("[<-A D->] Freq: %4.2f", freq),4 mes strf("[<-W S->] Amp: %4.2f", amp),4 mes strf("[<-Z C->] Attenate: %4.2f", attenate),4 mes strf("[ Space ] Texture: %d", mode),4 mes strf("Phase: %4.2f", phase),4 goto *MAIN

水滴エフェクトとか作ったらカッコよさそうですねぇ。



youdai

リンク

2022/2/15(Tue) 19:47:34|NO.95431

返信ありがとうございます。
大変参考になりました。
wave.fragのpの座標に加算することで、波紋を出現させる位置を変更できることも分かりました。
見栄えもとても素晴らしく、大変良いポストエフェクトだと思いました。
これはとても凄いと思います。
実際にサンプルを動かした時に感動してしまいました。



ONION software Copyright 1997-2025(c) All rights reserved.