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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

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

Q&A

解決済

1回答

4524閲覧

unity Texture2Dをリサイズしたいのですが,ピントが少しボケてしまいます。

29507-01

総合スコア46

Unity

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

0グッド

1クリップ

投稿2020/05/04 03:16

編集2020/05/12 09:29

前提・実現したいこと

Texture2Dをリサイズしたいのですが解像度? ピントが少しボケています。
良い方法があれば教えて頂けませんか。
scaner
イメージ説明
resize (pcにて)
イメージ説明
resize (スマホにて)
イメージ説明
元の画像 (640,1136)
イメージ説明
シェーダーのリサイズ
イメージ説明
canvas/image
イメージ説明
イメージ説明
canvas
イメージ説明

該当のソースコード

unity

1 private static Texture2D GetResized(Texture2D texture, int width, int height) 2 { 3 // リサイズ後のサイズを持つRenderTextureを作成して書き込む 4 var rt = RenderTexture.GetTemporary(width, height); 5 Graphics.Blit(texture, rt); 6 7 // リサイズ後のサイズを持つTexture2Dを作成してRenderTextureから書き込む 8 var preRT = RenderTexture.active; 9 RenderTexture.active = rt; 10 var ret = new Texture2D(width, height); 11 ret.ReadPixels(new Rect(0, 0, width, height), 0, 0); 12 ret.Apply(); 13 RenderTexture.active = preRT; 14 15 RenderTexture.ReleaseTemporary(rt); 16 return ret; 17 }

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

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

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

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

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

sakura_hana

2020/05/04 04:40

試しに元の画像と同じ大きさの値を渡すとどうなるか確認してみてください。 但し拡大時は当然ボケますし、縮小時も適切な補完がされるのか怪しいので多少ボケるのは仕方無い気もします。
29507-01

2020/05/04 05:00 編集

縦,横サイズが違うPNGを(200,200)にリサイズするのは無理がありますか? 現在 そのまま書き出した画像と200,200にリサイズした画像を比べた場合 200,200にリサイズした画像はボケている形です。
sakura_hana

2020/05/04 05:42

元の縦横サイズの明示や、ボケている画像を貼ってもらうと分かりやすいですが、 とりあえず前述の通り拡大するならボケますし、縮小の場合も縦か横が引き伸ばされるor潰されるのでイマイチな見た目になる気がします。
edo_m18

2020/05/04 05:51

そもそもの話として、ボケることの解消が本題ではなく、実際にやりたいことをセットで説明したほうがよりよい回答が得られると思います。(場合によってはアプローチ自体も間違っていることもありますし)
29507-01

2020/05/04 22:05 編集

スマホで撮った写真を200,200のサイズにリサイズしたい。
29507-01

2020/05/04 06:34

画像を添付しましたがこの程度だと我慢する?
sakura_hana

2020/05/04 07:00

個人的にはscanerの方が荒く見えますしresizeのボケ方もこれぐらいならいいのでは?と思いますが、許容値は個人差があります。 「この程度ならよしとする」か「別の方法を調べる」か「200,200以外の値(例えば640,640とか)に出来ないか調べ直す」かはご自分で決めてください。 (別の方法案として「640,640の画像を200,200の領域に表示」とかも考えられますがシステム上それでいいのかと、結構縮小率が高いので綺麗に見えるか定かでないです)
29507-01

2020/05/04 07:07

有難うございます。 参考にします。
guest

回答1

0

ベストアンサー

確かにちょっとぼやけているように感じますね。
元の画像が

図1

のとき(サイズ640×640)、ご質問者さんの方法で200×200に縮小すると

図2

となるのに対して、Photoshopの「バイリニア法」だと

図3

「バイキュービック法 - シャープ (縮小)」だと

図4

といった結果になり、ぼやけの程度が小さく抑えられています。
毎フレーム行う処理でないのなら多少処理コストがかかってもかまわないでしょうから、自前でバイキュービック法のような縮小方法を実装するとか、あるいはアンシャープマスク処理を加えてやるのがいいかもしれません。

あるいは単純に、縮小前のテクスチャ中において縮小後の1ピクセルが占める領域を何カ所もサンプリングするというのはどうでしょうか。
たとえば下記のようなシェーダーを用意しておいて...

ShaderLab

1// 字数節約のため削除しました...削除前のコードは編集履歴をご参照ください

ご質問者さんのスクリプトを下記のように改変して実行したところ...

C#

1using System.IO; 2using UnityEditor; 3using UnityEngine; 4 5public static class TextureResizer 6{ 7 private static Material overSamplingMaterial; 8 9 [MenuItem("Utility/Resize Selected Texture to 200 x 200")] 10 public static void ResizeTextureTo200x200() 11 { 12 const int newWidth = 200; 13 const int newHeight = 200; 14 const int loopCount = 16; 15 var targetTexture = Selection.activeObject as Texture2D; 16 if (targetTexture == null) 17 { 18 return; 19 } 20 21 var targetPath = AssetDatabase.GetAssetPath(targetTexture); 22 if (string.IsNullOrEmpty(targetPath)) 23 { 24 return; 25 } 26 27 var targetDirectory = Path.GetDirectoryName(targetPath); 28 var targetName = Path.GetFileNameWithoutExtension(targetPath); 29 var targetExtension = Path.GetExtension(targetPath); 30 var newName = $"{targetName}({newWidth}x{newHeight})"; 31 var newPath = $"{targetDirectory}{Path.DirectorySeparatorChar}{newName}{targetExtension}"; 32 var newTexture = GetResized(targetTexture, newWidth, newHeight, loopCount); 33 File.WriteAllBytes(newPath, newTexture.EncodeToPNG()); 34 AssetDatabase.ImportAsset(newPath); 35 } 36 37 private static Texture2D GetResized(Texture2D texture, int width, int height, int loopCount) 38 { 39 // オーバーサンプリング用マテリアルを作成する 40 if (overSamplingMaterial == null) 41 { 42 overSamplingMaterial = new Material(Shader.Find("Hidden/OverSampling")); 43 } 44 45 // まず元と同じサイズのRenderTextureに書き込む 46 var sourceRT = RenderTexture.GetTemporary(texture.width, texture.height); 47 Graphics.Blit(texture, sourceRT); 48 49 // filterModeをPointにしておき、サンプリング時に注目点以外の色が混じらないようにしておく 50 sourceRT.filterMode = FilterMode.Point; 51 52 // リサイズ後のサイズを持つRenderTextureを作成して、オーバーサンプリングマテリアルを使って書き込む 53 var rt = RenderTexture.GetTemporary(width, height); 54 overSamplingMaterial.SetInt("_LoopCount", Mathf.Max(loopCount, 1)); 55 Graphics.Blit(sourceRT, rt, overSamplingMaterial); 56 57 // リサイズ後のサイズを持つTexture2Dを作成してRenderTextureから書き込む 58 var preRT = RenderTexture.active; 59 RenderTexture.active = rt; 60 var ret = new Texture2D(width, height); 61 ret.ReadPixels(new Rect(0, 0, width, height), 0, 0); 62 ret.Apply(); 63 RenderTexture.active = preRT; 64 RenderTexture.ReleaseTemporary(rt); 65 RenderTexture.ReleaseTemporary(sourceRT); 66 return ret; 67 } 68}

loopCountが1だと(これは実質的にニアレストネイバー法と同等のはずです)...

図5

loopCountが4だと(1ピクセルにつき16点サンプリング)...

図6

loopCountが16だと(1ピクセルにつき256点サンプリング)...

図7

となりました。だいぶ精密さが向上したんじゃないかと思いますが、いかがでしょうか?

正方形トリミングについて

まずシェーダーコードは下記のように変更して、UV座標を操作することで画像切り出し範囲を調整できるようにしておきます。

ShaderLab

1Shader "Hidden/OverSampling" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 SubShader 8 { 9 Cull Off ZWrite Off ZTest Always 10 11 Pass 12 { 13 CGPROGRAM 14 #pragma vertex vert 15 #pragma fragment frag 16 17 #include "UnityCG.cginc" 18 19 struct appdata 20 { 21 float4 vertex : POSITION; 22 float2 uv : TEXCOORD0; 23 }; 24 25 struct v2f 26 { 27 float2 uv : TEXCOORD0; 28 float4 vertex : SV_POSITION; 29 }; 30 31 sampler2D _MainTex; 32 float4 _TilingAndOffset; 33 int _LoopCount; 34 35 v2f vert(appdata v) 36 { 37 v2f o; 38 o.vertex = UnityObjectToClipPos(v.vertex); 39 o.uv = (v.uv * _TilingAndOffset.xy) + _TilingAndOffset.zw; 40 return o; 41 } 42 43 float4 frag (v2f i) : SV_Target 44 { 45 float2 texelSize = fwidth(i.uv); 46 float2 deltaUV = texelSize / _LoopCount; 47 float2 uv0 = i.uv + ((deltaUV - texelSize) * 0.5); 48 float4 col = 0.0; 49 for (int j = 0; j < _LoopCount; j++) 50 { 51 for (int i = 0; i < _LoopCount; i++) 52 { 53 col += tex2D(_MainTex, uv0 + (float2(i, j) * deltaUV)); 54 } 55 } 56 return col / (_LoopCount * _LoopCount); 57 } 58 ENDCG 59 } 60 } 61}

そして制御用のスクリプトは下記のようにしました。
ご追記のスクリーンショットを拝見しますに、どうやらImageを使って縮小後のテクスチャを表示している様子ですね。表示用のスプライトはどのように用意していますでしょうか?私の場合はさしあたり縮小後のテクスチャを使ったスプライトを新規作成し、それをImageコンポーネントにセットしてやることにしました。
スクリプトはサイズ200×200のImageオブジェクトにアタッチして使うことを想定しており、Start内で元テクスチャをロード・縮小テクスチャを生成・スプライトを作成してImageにセット...の処理を行っています。

C#

1using UnityEngine; 2using UnityEngine.UI; 3 4[RequireComponent(typeof(Image))] 5public class ResizedImageLoader : MonoBehaviour 6{ 7 private static Material overSamplingMaterial; 8 9 [SerializeField] private bool useActualSize; 10 11 private void Start() 12 { 13 var texture2D = Resources.Load<Texture2D>("motogp"); 14 15 // 目標サイズは200x200決め打ちではなく、Imageのサイズを見て決めることにする 16 var image = this.GetComponent<Image>(); 17 var rectTransform = this.transform as RectTransform; 18 var sizeDelta = rectTransform.sizeDelta; 19 var toWidth = Mathf.RoundToInt(sizeDelta.x); 20 var toHeight = Mathf.RoundToInt(sizeDelta.y); 21 22 // インスペクターの「Use Actual Size」がオンの場合 23 // 目標サイズを最終的な表示サイズに合わせて調整する 24 if (this.useActualSize) 25 { 26 var canvas = image.canvas; 27 var canvasCamera = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera; 28 var corners = new Vector3[4]; 29 rectTransform.GetWorldCorners(corners); 30 var bottomLeft = RectTransformUtility.WorldToScreenPoint(canvasCamera, corners[0]); 31 var topRight = RectTransformUtility.WorldToScreenPoint(canvasCamera, corners[2]); 32 var actualSize = topRight - bottomLeft; 33 toWidth = Mathf.RoundToInt(Mathf.Abs(actualSize.x)); 34 toHeight = Mathf.RoundToInt(Mathf.Abs(actualSize.y)); 35 } 36 37 // 元のテクスチャから切り出すべき領域を求める 38 // テクスチャの中心からなるべく大きな矩形を切り出したいので 39 // まずテクスチャの高さに縦横比を掛けて希望切り出し幅を求める 40 // テクスチャの幅が希望切り出し幅よりも小さい場合、切り出し幅は 41 // テクスチャ幅とし、代わりに切り出し高さを切り詰める 42 // 起点のズレは余白の大きさの半分ということになる 43 var toAspect = (float)toWidth / toHeight; 44 var width = texture2D.width; 45 var height = texture2D.height; 46 var expectedWidth = Mathf.RoundToInt(height * toAspect); 47 var fromWidth = Mathf.Min(width, expectedWidth); 48 var fromHeight = expectedWidth > width ? Mathf.RoundToInt(width / toAspect) : height; 49 var offsetX = (width - fromWidth) / 2; 50 var offsetY = (height - fromHeight) / 2; 51 52 // 確認のため、リサイズ前とリサイズ後のサイズをコンソールに表示してみる 53 Debug.LogFormat("({0}, {1}) -> [({2}, {3}), ({4}, {5})] -> ({6}, {7})", 54 width, height, 55 offsetX, offsetY, fromWidth, fromHeight, 56 toWidth, toHeight); 57 58 // 切り出された領域をリサイズして最終的なテクスチャとする 59 // ちなみに、ご質問者さんが作成された方のGetResizedも残してありますので、 60 // 引数を元テクスチャと目標サイズだけに省略するとそちらが使われます 61 // そちらに切り替えてみると、トリミング処理の有無による違いやぼけ具合の 62 // 比較ができるかと思います 63 var resizedTexture = GetResized(texture2D, offsetX, offsetY, fromWidth, fromHeight, toWidth, toHeight); 64 //var resizedTexture = GetResized(texture2D, 200, 200); 65 66 // 最終的に表示される位置・サイズによっては、小数点以下のズレのため 67 // ぼやけやImage外周部に反対側の辺の色が乗る現象が起こる可能性がある 68 // そこで、それらを回避するようにテクスチャの設定を変更する 69 resizedTexture.filterMode = FilterMode.Point; 70 resizedTexture.wrapMode = TextureWrapMode.Clamp; 71 72 // リサイズ後のテクスチャをもとにスプライトを作成し、Imageにセット 73 var sprite = Sprite.Create( 74 resizedTexture, 75 new Rect(0, 0, resizedTexture.width, resizedTexture.height), 76 new Vector2(0.5f, 0.5f)); 77 image.sprite = sprite; 78 } 79 80 // 元のテクスチャから(fromX, fromY)を起点とする幅fromWidth、高さfromHeightの領域を 81 // 切り出し、それを幅toWidth、高さtoHeightにリサイズしたテクスチャを生成する 82 private static Texture2D GetResized( 83 Texture2D texture, 84 int fromX, int fromY, int fromWidth, int fromHeight, 85 int toWidth, int toHeight, 86 int loopCount = 16, 87 bool generateMipmaps = false) 88 { 89 if (overSamplingMaterial == null) 90 { 91 overSamplingMaterial = new Material(Shader.Find("Hidden/OverSampling")); 92 } 93 94 // まずは以前同様に元テクスチャをRenderTextureに写し取り、FilterModeをPointにしておく 95 var preRT = RenderTexture.active; 96 var sourceWidth = texture.width; 97 var sourceHeight = texture.height; 98 var sourceRT = RenderTexture.GetTemporary(sourceWidth, sourceHeight); 99 Graphics.Blit(texture, sourceRT); 100 sourceRT.filterMode = FilterMode.Point; 101 102 // マテリアルの設定を行う 103 // 元のテクスチャから起点(fromX, fromY)、サイズ(fromWidth, fromHeight)の部分を 104 // 切り出すということは、UV座標のタイリング・オフセットは下記のようになる 105 overSamplingMaterial.SetVector( 106 "_TilingAndOffset", 107 new Vector4( 108 (float)fromWidth / sourceWidth, 109 (float)fromHeight / sourceHeight, 110 (float)fromX / sourceWidth, 111 (float)fromY / sourceHeight)); 112 overSamplingMaterial.SetInt("_LoopCount", Mathf.Max(loopCount, 1)); 113 114 // あとは以前と同様にリサイズし、結果を返す 115 var rt = RenderTexture.GetTemporary(toWidth, toHeight); 116 Graphics.Blit(sourceRT, rt, overSamplingMaterial); 117 RenderTexture.active = rt; 118 var ret = new Texture2D(toWidth, toHeight, TextureFormat.ARGB32, generateMipmaps); 119 ret.ReadPixels(new Rect(0, 0, toWidth, toHeight), 0, 0); 120 ret.Apply(); 121 RenderTexture.active = preRT; 122 RenderTexture.ReleaseTemporary(rt); 123 RenderTexture.ReleaseTemporary(sourceRT); 124 return ret; 125 } 126 127 // ご質問者さんの方法によるGetResized 128 private static Texture2D GetResized(Texture2D texture, int width, int height) 129 { 130 var rt = RenderTexture.GetTemporary(width, height); 131 Graphics.Blit(texture, rt); 132 var preRT = RenderTexture.active; 133 RenderTexture.active = rt; 134 var ret = new Texture2D(width, height); 135 ret.ReadPixels(new Rect(0, 0, width, height), 0, 0); 136 ret.Apply(); 137 RenderTexture.active = preRT; 138 RenderTexture.ReleaseTemporary(rt); 139 return ret; 140 } 141}

当初の方法だと、縦長の画像が正方形に縮小されることで縦に潰れてしまっていたのが...

図8

正方形に切り出す処理が加わることで、被写体が潰れないようになりました。

図9

投稿2020/05/06 06:33

編集2020/05/13 08:30
Bongo

総合スコア10807

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

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

29507-01

2020/05/09 11:08 編集

遅くなり申し訳ありません。 var newName = $"{targetName}({newWidth}x{newHeight})"; var newPath = $"{targetDirectory}{Path.DirectorySeparatorChar}{newName}{targetExtension}"; この箇所がc#4では使用できませんと表示されます。 申し訳無いですが,修正方法を教えて頂けませんか?
Bongo

2020/05/09 11:22

すみませんでした、昔のバージョンのUnityをお使いでしょうか? では、 var newName = string.Format("{0}({1}x{2})", targetName, newWidth, newHeight); var newPath = string.Format("{0}{1}{2}{3}", targetDirectory, Path.DirectorySeparatorChar, newName, targetExtension); ならどうでしょうか。他の箇所はたぶん旧バージョンでも大丈夫だろうとは思うのですが、見落としているかもしれませんのでエラーがありましたらコメントいただければ修正してみます。
29507-01

2020/05/09 22:06

初心者なもので申し訳ないのですが,エラーは無くなったのですが 内部関数として扱っていたので texture2D = GetResized(texture2D, 200, 200);で呼んで処理していました。 外部のClassの呼び方がわかりません。 教えて頂けないでしょうか。
Bongo

2020/05/09 22:49 編集

説明が足りずすみません。あの「TextureResizer」は、回答文中に実験結果を画像として載せるために、縮小したTexture2DをPNGファイルとして出力させる目的で作ったものです(ちなみに、使い方としてはプロジェクトに「Editor」フォルダを作ってTextureResizerスクリプトを入れ、処理対象のテクスチャファイルを選択し、メニューに新しく現れた「Utility」→「Resize Selected Texture to 200 x 200」を実行する...という手順を想定しています)。 Texture2Dを作るだけでしたらGetResizedメソッドと「private static Material overSamplingMaterial;」があれば十分なようにしたつもりですので、それらを適当なスクリプト...たとえばご質問者さんが使っているスクリプトにコピー&ペーストして、あとはシェーダーコードだけあれば、従来と似たような形で「texture2D = GetResized(texture2D, 200, 200, 16);」といった風に使用できるかと思います。 なお念のため申し上げますと、今回の例ではシェーダーをShader.Findを使って探す方法をとっています。ですのでプレイモードで動かす上ではそのままでもいいですが、ビルドして動作させるには「Edit」→「Project Settings...」の「Graphics」→「Built-in Shader Settings」→「Always Included Shaders」に「Hidden/OverSampling」を追加してやる必要があるでしょう。
29507-01

2020/05/09 23:08 編集

すみません。最後の行を見ていませんでした。
29507-01

2020/05/09 23:29

エレメントを一つ増やし,None(Shader)になったのですが Hidden/OverSamplingの登録ができません。
Bongo

2020/05/09 23:46

シェーダーが見つからないということでしょうか? 増やした欄の右端の◎ボタンで選択しようとしているのでしたら、その選択ウィンドウ中ではシェーダー名(「Hidden/OverSampling」)ではなくシェーダーファイル名(「OverSampling.shader」という名前で作成した場合は「OverSampling」)になるっぽいので、ウィンドウ上部の検索ボックスでその名前で探してみてはいかがでしょう。
29507-01

2020/05/10 00:24 編集

単純にHidden/OverSamplingというシェーダーをAssetsから作成し実行できたのですが 画像が崩れています。Assetsからシェーダーを作ったのですが作り方に問題があるのでしょうか? .jpgのリサイズにシェーダーを使う意味がわからないのですが 以下の方法でやってみました。 texture2D = Resources.Load<Texture2D>("motogp"); texture2D = GetResized(texture2D, 200, 200, 16);
Bongo

2020/05/10 01:34 編集

「Assets」→「Create」→...で作成したのでしたら手順的に問題はないと思います。 texture2D = Resources.Load<Texture2D>("motogp"); texture2D = GetResized(texture2D, 200, 200, 16); の方も別段おかしいところはなさそうですね... 画像が崩れるといいますと、どのような状態でしょうか?縮小前の画像と、崩れてしまった縮小後の画像を質問文に追記いただけますでしょうか(たとえばライセンス的な問題で画像をアップロードすることはできないようでしたら、代わりに何か別の問題ない画像で同様に縮小して、崩れてしまった様子をお示しいただくのでもかまいません)。 併せて、その縮小前のテクスチャファイルをProjectビュー上で選択するとインスペクター上にテクスチャのインポート設定が表示されるかと思いますが、その内容もご提示いただけますでしょうか。もしかするとこっちの設定が関係しているかもしれません。ちょっと予想外の症状で原因特定に時間がかかるかもしれませんが、調べてみようと思います。
29507-01

2020/05/10 02:47 編集

画像を添付しました。 指摘の内容とあっているでしょうか?
Bongo

2020/05/10 09:35

お返事遅くなりました。ちょっと念のため確認したいのですが、まさか「単純にHidden/OverSamplingというシェーダーをAssetsから作成し実行できたのですが」とおっしゃるのは... 1. 「Assets」→「Create」→「Shader」→「Image Effect Shader」で新規シェーダーファイルを作る。 2. ファイル名入力待ち状態になるので、「OverSampling」と入力、確定する。 3. するとシェーダー名が「Hidden/OverSampling」のシェーダーができあがる。 としたあと、そのOverSamplingシェーダーの内容を何も変更しないまま実行した...ということでしょうか? ご提示いただいた異常画像がどうしてあんな風に白黒反転するのか謎で手詰まりだったのですが、もし仮にそのような手順だったと仮定しますと、そのデフォルト状態のイメージエフェクトシェーダーは白黒反転機能を持っていますので説明がつきそうだ...と思ったわけです。 それともう一つ、ご質問者さんのおっしゃる「リサイズ」というのは、正方形からはみ出た部分をトリミングする事も含むと考えていいでしょうか? つまり、ご提示の元画像は縦長で、中央に写っているレーサーの上下にはサーキットの路面が写っていますが、「scaner」や「resize (スマホにて)」の画像は上下がトリミングされ、画像が縦に潰れることなく正方形になっています。 もしその方が望ましいのなら、もう少しコードに手を加える必要がありそうです。
29507-01

2020/05/11 10:44 編集

遅くなり申し訳ございません。 OverSamplingシェーダーの内容を何も変更しないまま実行しました。 シェーダーを使った事がないもので。 又,正方形からはみ出た部分をトリミングしたいですが, 現在 canvas/imageがありカメラロールの画像をimageに取り込んでいるので 場合によっては画像が正方形内に上手く収まったり,人間だと頭の部分がカットされたりしている状況です。 カメラロールから画像を取り込み,その絵にBongoさんから教えていただいた方法で絵を描こうと思っています。 最終的にはカメラロールの写真をcanvasに表示し枠内の画像を200X200のサイズに変更し絵を描きたいです。
Bongo

2020/05/11 11:36

なるほど、白黒反転してしまったのはそれが原因だったようですね。私の意図としては、新規作成されたシェーダーファイルの内容を丸ごと回答文中に載せた「Hidden/OverSampling」のコードで置き換えていただくことを想定しておりました。言葉足らずですみません。 なお、もしこれから置き換えていただけるのでしたら、最初の回答投稿時に載せたコードの代わりに、先ほど追記しました部分に載せた同名の「Hidden/OverSampling」を使ってみてください。こちらは最初のコードに範囲切り出し機能を追加したものでして、そのさらに後に載せました正方形切り出し機能付きスクリプトに対応させたものです。ご参考になりましたら幸いです。 とはいえ、あの例では単純に画像中心から正方形に切り出しているだけですので、見せたい部分が中心にない場合...「人間だと頭の部分がカットされたり」とおっしゃるようなケースにも対応するにはさらに工夫が必要そうですね。 GetResized自体は任意の範囲を切り出せるように作ったつもりですので、あとは切り出し範囲をどう決定するかという問題のように思います。もし画像に応じて被写体を自動認識し中央に据えてくれるような機能が作れたとしたら、ゲームのプレイヤーにとってはかなり親切でしょうが、さすがにそこまでのものとなるとお手軽に作るわけにはいかないでしょうね... 「画像選択後、まずはプレイヤーに切り出し前の長方形状態の画像を提示して被写体をタップしてもらい、その点を中心とした正方形領域を切り出す」あたりのレベルに妥協した方がいいかもしれません。 ところで話題が変わりますが、縮小後のテクスチャがもっとも美しく表示されるのは最終的にテクスチャが画面上に表示される時のサイズとテクスチャのサイズが一致する時だと考えられますので、表示方法にも気を遣っていただくとさらに効果的だと思います。 縮小後のテクスチャサイズと画面上の表示サイズが異なる場合、縮小済みのテクスチャがさらにUnityのレンダリングエンジンによって拡大あるいは縮小されて最終的なサイズになるはずで、このときの拡大縮小は当初ご質問者さんがご提示いただいたコードのようなマテリアルなしBlitと同等の品質で行われると思われます。ですのでせっかく高品質に縮小しても、そのあとの拡大縮小によって品質が悪化してしまう可能性があるでしょう。 インスペクターのスクリーンショットを拝見しますにImageオブジェクト自体は200×200に設定されているようですが、それより上の階層はどうでしょうか? たとえばCanvasオブジェクトのCanvas Scalerの設定次第では、キャンバス全体に拡大縮小がかかって最終的な表示サイズが200×200にならないかもしれません(UI Scale ModeがScale With Screen Sizeの場合だとか)。もしぼやけが解消しないようでしたら、このへんの設定をご提示いただければ、もしいい回避案が思いつきましたら修正してみようと思います。
29507-01

2020/05/13 19:04 編集

有難うございます。被写体が潰れないようになりました。 コーディングについては週末の時間のある時に見ようと思います。 この後はcanvasに全体像を表示し枠内を切り抜きしようと思います。 Canvasのスクショを登録しました。 Canvas Scalerの設定次第では、キャンバス全体に拡大縮小がかかって最終的な表示サイズが200×200にならないかもしれません(UI Scale ModeがScale With Screen Sizeの場合だとか) テクスチャがもっとも美しく表示されるのは最終的にテクスチャが画面上に表示される時のサイズとテクスチャのサイズが一致する時 よろしければ,この辺りの事を教えて頂けませんか?
Bongo

2020/05/13 08:31

Canvas Scalerの件に関しては、「Unity Canvas Scaler」あたりのキーワードで検索(https://www.google.com/search?q=Unity+Canvas+Scaler )していただけるといろいろな解説が出てくるかと思います。「実行時のモバイル端末の解像度がさまざまでも、UIのレイアウトを同じように見せるにはどうするべきか」というテーマで説明しているサイトが多いように思われますね。 UI Scale ModeをScale With Screen Sizeとして、ゲームビュー上部の解像度プルダウンメニューを「Free Aspect」とした状態でゲームビューの外周をドラッグしてサイズを変更してみると、Canvasのインスペクター上のRect TransformのScaleの値がゲームビューのサイズに応じて変化する様子を観察できるかと思います。 Canvas ScalerのReference Resolutionで設定した解像度よりもゲームビューのサイズが小さければCanvasは縮小され、大きければ拡大されるはずです。Canvasの子であるImageも拡大縮小の影響を受け、たとえImage自身のサイズを200×200に設定していたとしても、ゲームビューのスクリーンショットを撮影して実際のサイズを画像処理ソフトで調べてみると200ピクセル×200ピクセルになっているとは限らないんじゃないでしょうか。 前回追記しましたスクリプトを改変して、200×200決め打ちではなく実際の表示サイズを考慮してリサイズするオプションを追加してみました(インスペクター上で「Use Actual Size」をオンにしてみてください)。シェーダーコードはいじっていません。 また、その結果投稿字数制限を超えてしまったため、すみませんが最初の回答で例示しました古い方の「Hidden/OverSampling」のコードを回答文から削除しました。 私の回答欄本文の末尾に編集を行った日時が表示されているはずですが、そのリンクを開くとどの部分が変更されたか見ることができるかと思います。
29507-01

2020/05/13 09:06

丁寧に有難うございました。 勉強になる事ばかりです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問