質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

2655閲覧

パーティクルのノイズにランダム性を与えたいです

YutoHayashi

総合スコア8

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/03/26 19:16

前提・実現したいこと

Shaderの知識がとても薄い状況です。
水中の泡のパーティクルを作っていて、ただの正円だった泡にシェーダーから歪みエフェクトをかけることまではできたのですが、全てのパーティクルが同期して同じタイミング同じ形に歪むため、不自然に見えます。
パーティクルの粒ひとつひとつでノイズのタイミングをずらすにはどうしたらよいでしょうか?

イメージ説明

該当のソースコード

Shader "Custom/DistortedBubbleShader" { Properties { _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5) _MainTex ("Particle Texture", 2D) = "white" {} _NoiseTex ("Noise Texture", 2D) = "white" {} _Speed ("Speed", Range(0, 10)) = 2 _NoiseAmount ("NoiseAmount", Range(0, 0.1)) = 0.025 } Category { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" } Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull Off Lighting Off ZWrite Off SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_particles #pragma multi_compile_fog #include "UnityCG.cginc" sampler2D _MainTex; fixed4 _TintColor; struct appdata_t { float4 vertex : POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; UNITY_FOG_COORDS(1) UNITY_VERTEX_OUTPUT_STEREO }; float4 _MainTex_ST; float _Speed; sampler2D _NoiseTex; float _NoiseAmount; v2f vert (appdata_t v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); o.vertex = UnityObjectToClipPos(v.vertex); o.color = v.color * _TintColor; o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture); fixed4 frag (v2f i) : SV_Target { float2 nUv = i.texcoord; nUv.y += _Time.x * _Speed; float4 uvNoise = 2 * tex2D(_NoiseTex, nUv) -1;//0 - 1座標を-1 - 1に変換 i.texcoord += uvNoise.xy * _NoiseAmount; fixed4 col = 2.0f * i.color * tex2D(_MainTex, i.texcoord); col.a = saturate(col.a); // alpha should not have double-brightness applied to it, but we can't fix that legacy behavior without breaking everyone's effects, so instead clamp the output to get sensible HDR behavior (case 967476) UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } } }

試したこと

パーティクルの粒ごとのワールド座標を用いればいいのか、などと考えましたが、ParticleSystem.Particleからはマテリアルに到達できず、(そもそも一つ一つにマテリアルのインスタンスが当たっているわけではないのでしょうか?Shaderの動きもですが、パーティクルのマテリアルとの関係性もよくわかりません)行き詰りました。

補足情報(FW/ツールのバージョンなど)

2019.2.19f1
OculusQuestでの動作を想定

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

おっしゃるように、粒子ごとに異なる何らかの値を使ってノイズサンプリング位置をずらしてやるのがよさそうに思います。
ワールド座標を使うという発想も面白いと思うのですが、パーティクルシステムの場合は時間経過とともに粒子の位置が移動するので値がころころ変わるでしょうから、今回のような用途にはちょっと使いにくいかもしれません。

代案として、Custom Dataモジュールで値を供給してやるのはどうでしょう。
まず、下図のように粒子ごとに適当な範囲のランダムな値を生じさせて...

図1

RendererモジュールのCustom Vertex StreamsにCustom1.xを追加します。項目表示のカッコ書きによると、この値はどうやらUV座標のZ成分として送られるようです。

図2

そして、シェーダーコードではまずテクスチャ座標をfloat3に変え...

ShaderLab

1 struct appdata_t { 2 float4 vertex : POSITION; 3 fixed4 color : COLOR; 4 float3 texcoord : TEXCOORD0; 5 UNITY_VERTEX_INPUT_INSTANCE_ID 6 }; 7 8 struct v2f { 9 float4 vertex : SV_POSITION; 10 fixed4 color : COLOR; 11 float3 texcoord : TEXCOORD0; 12 UNITY_FOG_COORDS(1) 13 UNITY_VERTEX_OUTPUT_STEREO 14 };

バーテックスシェーダーでは、テクスチャ座標のXとYは当初のとおりタイリング・オフセットを適用、Zは入力頂点のZをそのまま引き渡し...

ShaderLab

1 v2f vert (appdata_t v) 2 { 3 v2f o; 4 UNITY_SETUP_INSTANCE_ID(v); 5 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 6 o.vertex = UnityObjectToClipPos(v.vertex); 7 o.color = v.color * _TintColor; 8 o.texcoord.xy = TRANSFORM_TEX(v.texcoord,_MainTex); 9 o.texcoord.z = v.texcoord.z; 10 UNITY_TRANSFER_FOG(o,o.vertex); 11 return o; 12 }

フラグメントシェーダーでは、受け取ったi.texcoord.zをノイズUVに加算して座標をずらしてやるとどうでしょう。

ShaderLab

1 fixed4 frag (v2f i) : SV_Target 2 { 3 float2 nUv = i.texcoord.xy; 4 nUv.y += _Time.x * _Speed + i.texcoord.z; 5 float4 uvNoise = 2 * tex2D(_NoiseTex, nUv) -1;//0 - 1座標を-1 - 1に変換 6 i.texcoord.xy += uvNoise.xy * _NoiseAmount; 7 8 fixed4 col = 2.0f * i.color * tex2D(_MainTex, i.texcoord.xy); 9 col.a = saturate(col.a); // alpha should not have double-brightness applied to it, but we can't fix that legacy behavior without breaking everyone's effects, so instead clamp the output to get sensible HDR behavior (case 967476) 10 11 UNITY_APPLY_FOG(i.fogCoord, col); 12 return col; 13 }

投稿2020/03/26 22:35

Bongo

総合スコア10811

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YutoHayashi

2020/03/27 04:30

ありがとうございました! StableRandomの方から値をもらってノイズテクスチャずらせました!Shaderの理解も少し深まったように思います。 本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問