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

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

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

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

Unity

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

Q&A

1回答

1135閲覧

Unity)波形画像のシェーダーをpngで保存したい

unitymoa55

総合スコア0

C#

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

Unity

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

0グッド

0クリップ

投稿2022/03/18 05:46

編集2022/03/19 00:02

シェーダーを利用して音声波形を描くことは
下記ページを参考にできました。
https://setchi.hatenablog.com/entry/2015/10/25/220844

質問はこの波形をPngファイルにして保存したいのですが
textureを

c#

1byte [] pngName = texture.EncodeToPNG(); 2File.WriteAllBytes(filePath, pngName);

でPngファイルにしたのですが
ファイルはできるのですが開いてみるとグレーな表示
だけでなぜか波形画像が表示されません。
イメージ説明
そこで今度はスクショにすれば波形画像が保存できるかと思い
下記のスクリプトで保存したところできたファイルを
開くとやはり波形画像の部分のみグレーになっています。

c#

1public void OnClickTest() 2 { 3 string path = Application.persistentDataPath + "screenshot.png"; 4 5 StartCoroutine(LoadScreenshot()); 6 7 } 8 9 IEnumerator LoadScreenshot() 10 { 11 yield return new WaitForEndOfFrame(); 12 Texture2D tex = 13 ScreenCapture.CaptureScreenshotAsTexture(); 14 // 切り取る画像の左下位置を求める 15 int x = (tex.width - width) / 2; 16 int y = (tex.height - height) / 2; 17 Color[] colors = tex.GetPixels(x, y, width, height); 18 Texture2D saveText = new Texture2D(width, height, TextureFormat.ARGB32, false); 19 saveText.SetPixels(colors); 20 string path = Application.persistentDataPath + "ss.png"; 21 File.WriteAllBytes(path, saveText.EncodeToPNG());

ちなみに

c#

1ScreenCapture.CaptureScreenshot(path);

で保存したところ波形画像の部分は問題なく表示されましたが
イメージ説明
ScreenCapture.CaptureScreenshotには範囲を指定して
キャプチャーする方法が見当たりません。
シェーダーに表示した波形をpngファイルに保存する方法をわかる方
教えてください。

環境)
OS: macOS Monterey
Unity2020.3.21f1
言語:C#

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

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

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

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

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

guest

回答1

0

テクスチャにデータを書き込んだはずなのに反映されていない...といったケースでさしあたり心当たりがあるのは、Applyを実行し忘れているとかでしょうかね?
見たところ少なくとも後者のCaptureScreenshot案のコードにはApplyがないように見えます。saveText.SetPixels(colors);の後にsaveText.Apply();を入れてみると変化はあるでしょうか。

前者の直接保存案がうまくいかなかった件については、こちらはもっと詳しくコードをご提示いただく必要がありそうです。ご参考になさった「【Unity】シェーダーを利用して音声波形を描く - setchi’s blog」によると、WaveformRenderertexture自体は音声データを赤色の強度で表した高さ1ピクセルのテクスチャのようですから、それを最終的な緑色の線の画像にするにはどこかで記事中のシェーダーを使ったレンダリングを行う必要があるかと思います。ご質問者さんがどのようになさっているかお示しいただければ手がかりになるかもしれません。

RawImageから画像データを作る例

生成された波形データテクスチャをRawImage上にレンダリングして波形図にすることを前提とすると、そのRawImageのマテリアルを使って波形データテクスチャを同様にオフスクリーンレンダリングする手があるんじゃないかと思いました。
ご参考までに、たとえば下記のようなスクリプトをプロジェクト内に入れておけばRawImageからPNGデータを作れるんじゃないでしょうかね?

C#

1using UnityEngine; 2using UnityEngine.UI; 3 4public static class RawImageExtensions 5{ 6 /// <summary> 7 /// RawImageをキャプチャーし、PNGフォーマットにエンコードします。出力されるデータの幅、高さはRawImageのsizeDeltaを使用します。 8 /// </summary> 9 /// <param name="rawImage">キャプチャー対象のRawImage。</param> 10 /// <param name="ignoreAlpha">透明度を無視し、RGBのみのデータとして出力するか。</param> 11 /// <returns>エンコードされたPNGバイト配列。</returns> 12 public static byte[] EncodeToPNG(this RawImage rawImage, bool ignoreAlpha = false) 13 { 14 // 引数なしで実行した場合は、rawImageのsizeDeltaを出力テクスチャサイズとして使用する 15 return rawImage.EncodeToPNG(Vector2Int.FloorToInt(rawImage.rectTransform.sizeDelta), ignoreAlpha); 16 } 17 18 /// <summary> 19 /// RawImageをキャプチャーし、PNGフォーマットにエンコードします。 20 /// </summary> 21 /// <param name="rawImage">キャプチャー対象のRawImage。</param> 22 /// <param name="outputSize">出力されるPNGデータの幅、高さ。</param> 23 /// <param name="ignoreAlpha">透明度を無視し、RGBのみのデータとして出力するか。</param> 24 /// <returns>エンコードされたPNGバイト配列。</returns> 25 public static byte[] EncodeToPNG(this RawImage rawImage, Vector2Int outputSize, bool ignoreAlpha = false) 26 { 27 // 入力テクスチャを取得する 28 // rawImageにテクスチャがセットされていればそれを使い、なければマテリアルの 29 // メインテクスチャを使い、それもなければ白色テクスチャを使う 30 var sourceTexture = rawImage.mainTexture; 31 32 // マテリアルを取得する 33 var material = rawImage.material; 34 35 // 出力サイズは最低でも1ピクセル四方とする 36 outputSize = Vector2Int.Max(Vector2Int.one, outputSize); 37 38 // PNGデータ生成用のテクスチャを作成する 39 // ignoreAlphaがtrueの場合はフォーマットをRGB24とし、アルファを捨てるようにする 40 var resultTexture = new Texture2D( 41 outputSize.x, 42 outputSize.y, 43 ignoreAlpha ? TextureFormat.RGB24 : TextureFormat.RGBA32, 44 false); 45 46 // レンダリング用のテクスチャを生成する 47 var resultRenderTexture = RenderTexture.GetTemporary(outputSize.x, outputSize.y, 0); 48 49 // 後でアクティブテクスチャを原状復帰するため、現在のアクティブテクスチャを覚えておく 50 var activeTexture = RenderTexture.active; 51 52 // resultRenderTexture上にmaterialを使ってsourceTextureをレンダリングする 53 Graphics.Blit(sourceTexture, resultRenderTexture, material); 54 55 // レンダリング結果をresultTextureに読み取る 56 RenderTexture.active = resultRenderTexture; 57 resultTexture.ReadPixels(new Rect(Vector2.zero, outputSize), 0, 0); 58 59 // アクティブテクスチャを原状復帰する 60 RenderTexture.active = activeTexture; 61 62 // もうresultRenderTextureは不要なので解放する 63 RenderTexture.ReleaseTemporary(resultRenderTexture); 64 65 // PNGデータを取得する 66 var result = resultTexture.EncodeToPNG(); 67 68 // もうresultTextureは不要なので破壊する 69 Object.Destroy(resultTexture); 70 71 // PNGデータを返す 72 return result; 73 } 74}

投稿2022/03/18 17:35

編集2022/03/19 14:03
Bongo

総合スコア10816

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問