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

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

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

Q&A

解決済

3回答

2064閲覧

Texture2Dをななめに切り出す方法

Aran1976734

総合スコア7

1グッド

2クリップ

投稿2017/08/17 20:41

Texture2Dをななめに切り出す方法を探しています。
4点を基準に画像を切り取る関数などはないでしょうか?
GetPixelsの引数も一つの座標と幅、高さしかないためどう斜めに切り取ればいいかわかりません。

teraps👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

Unityの備え付けの機能で目的に適いそうなものは見つけられませんでした...
ですが、テクスチャを4点で切り取るというのは面白そうでしたので、どうにかならないかと思い、下記のような方法を試してみましたが、ご参考になりますでしょうか?

ホモグラフィ変換で検索すると役に立ちそうなサイトがいろいろ出てきましたので、それらを参考にしました。

下のような画像をp、q、r、sの4点で切り抜きたいとすると、
テクスチャ
下の式のような、元の四隅(0, 0)、(0, 1)、(1, 1)、(1, 0)を与えると切り抜きたい四隅p、q、r、sを得られるようなa、b、c、d、e、f、g、hが分かればいいのかと思います。
1
上の式のx、yに(0, 0)、(0, 1)、(1, 1)、(1, 0)を代入すると、まずc、fを
2
と確定でき、
3
4
5
の関係が得られます。これらを変形すると、
6
の形になってg、hを確定でき、芋づる式にa、b、c、dが決定します。

Unityのデフォルトのシェーダーを一部改造して、生のUV座標の代わりに上記行列で変換した座標を使うようにしました。スプライト用シェーダーをベースにしましたが、他のものでも構わないかと思います。

Shader "Sprites/Homography" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1) [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 [HideInInspector] _BottomLeftTopLeft ("BottomLeftTopLeft", Vector) = (0,0,0,1) // 追加...左下と左上の隅 [HideInInspector] _TopRightBottomRight ("TopRightBottomRight", Vector) = (1,1,1,0) // 追加...右上と右下の隅 [HideInInspector] _HomographyMatrixR0 ("HomographyMatrixR0", Vector) = (1,0,0,0) // 追加...UV変換行列0行目 [HideInInspector] _HomographyMatrixR1 ("HomographyMatrixR1", Vector) = (0,1,0,0) // 追加...UV変換行列1行目 [HideInInspector] _HomographyMatrixR2 ("HomographyMatrixR2", Vector) = (0,0,1,0) // 追加...UV変換行列2行目(実際にはこの行はいつも一定なので、削除してもいいかと思います) [HideInInspector] _HomographyMatrixR3 ("HomographyMatrixR3", Vector) = (0,0,0,1) // 追加...UV変換行列3行目 } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Cull Off Lighting Off ZWrite Off Blend One OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex SpriteVert #pragma fragment SpriteFrag #pragma target 2.0 #pragma multi_compile_instancing #pragma multi_compile _ PIXELSNAP_ON #pragma multi_compile _ ETC1_EXTERNAL_ALPHA // 以下、#include "UnitySprites.cginc"の代わりにUnitySprites.cgincの内容をペーストし、一部修正を加える #include "UnityCG.cginc" #ifdef UNITY_INSTANCING_ENABLED UNITY_INSTANCING_CBUFFER_START(PerDrawSprite) // SpriteRenderer.Color while Non-Batched/Instanced. fixed4 unity_SpriteRendererColorArray[UNITY_INSTANCED_ARRAY_SIZE]; // this could be smaller but that's how bit each entry is regardless of type float4 unity_SpriteFlipArray[UNITY_INSTANCED_ARRAY_SIZE]; UNITY_INSTANCING_CBUFFER_END #define _RendererColor unity_SpriteRendererColorArray[unity_InstanceID] #define _Flip unity_SpriteFlipArray[unity_InstanceID] #endif // instancing CBUFFER_START(UnityPerDrawSprite) #ifndef UNITY_INSTANCING_ENABLED fixed4 _RendererColor; float4 _Flip; #endif float _EnableExternalAlpha; CBUFFER_END // Material Color. fixed4 _Color; float4 _HomographyMatrixR0; // 追加...UV座標変換用の行列0行目 float4 _HomographyMatrixR1; // 追加...UV座標変換用の行列1行目 float4 _HomographyMatrixR2; // 追加...UV座標変換用の行列2行目(実際にはこの行はいつも一定なので、削除してもいいかと思います) float4 _HomographyMatrixR3; // 追加...UV座標変換用の行列3行目 struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float3 texcoord : TEXCOORD0; // 変更...float2をfloat3に UNITY_VERTEX_OUTPUT_STEREO }; v2f SpriteVert(appdata_t IN) { v2f OUT; UNITY_SETUP_INSTANCE_ID (IN); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); #ifdef UNITY_INSTANCING_ENABLED IN.vertex.xy *= _Flip.xy; #endif OUT.vertex = UnityObjectToClipPos(IN.vertex); OUT.texcoord = mul(float4x4(_HomographyMatrixR0, _HomographyMatrixR1, _HomographyMatrixR2, _HomographyMatrixR3), float4(IN.texcoord, 0.0, 1.0)).xyw; // 変更...IN.texcoordを変換してからx、y、wを渡す OUT.color = IN.color * _Color * _RendererColor; #ifdef PIXELSNAP_ON OUT.vertex = UnityPixelSnap (OUT.vertex); #endif return OUT; } sampler2D _MainTex; sampler2D _AlphaTex; fixed4 SampleSpriteTexture (float2 uv) { fixed4 color = tex2D (_MainTex, uv); #if ETC1_EXTERNAL_ALPHA fixed4 alpha = tex2D (_AlphaTex, uv); color.a = lerp (color.a, alpha.r, _EnableExternalAlpha); #endif return color; } fixed4 SpriteFrag(v2f IN) : SV_Target { fixed4 c = SampleSpriteTexture (IN.texcoord.xy / IN.texcoord.z) * IN.color; // 変更...受け取ったIN.texcoordのx、yをzで割ってサンプリング座標とする c.rgb *= c.a; return c; } ENDCG } } CustomEditor "HomographyShaderGUI" // 追加...パラメータ設定用のカスタムUI }

また、シェーダーのパラメータ設定用スクリプトを作り、その中で先の式により変換行列を作ってシェーダーに渡しました。

using UnityEditor; using UnityEngine; public class HomographyShaderGUI : ShaderGUI { public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) { var material = materialEditor.target as Material; var bottomLeftTopLeft = FindProperty("_BottomLeftTopLeft", properties).vectorValue; var topRightBottomRight = FindProperty("_TopRightBottomRight", properties).vectorValue; EditorGUI.BeginChangeCheck(); var bottomLeft = EditorGUILayout.Vector2Field( "Bottom Left", new Vector2(bottomLeftTopLeft.x, bottomLeftTopLeft.y)); var topLeft = EditorGUILayout.Vector2Field( "Top Left", new Vector2(bottomLeftTopLeft.z, bottomLeftTopLeft.w)); var topRight = EditorGUILayout.Vector2Field( "Top Right", new Vector2(topRightBottomRight.x, topRightBottomRight.y)); var bottomRight = EditorGUILayout.Vector2Field( "Bottom Right", new Vector2(topRightBottomRight.z, topRightBottomRight.w)); if (EditorGUI.EndChangeCheck()) { material.SetVector( "_BottomLeftTopLeft", new Vector4(bottomLeft.x, bottomLeft.y, topLeft.x, topLeft.y)); material.SetVector( "_TopRightBottomRight", new Vector4(topRight.x, topRight.y, bottomRight.x, bottomRight.y)); var matrix = HomographyMatrix(bottomLeft, topLeft, topRight, bottomRight); material.SetVector("_HomographyMatrixR0", matrix.GetRow(0)); material.SetVector("_HomographyMatrixR1", matrix.GetRow(1)); material.SetVector("_HomographyMatrixR2", matrix.GetRow(2)); material.SetVector("_HomographyMatrixR3", matrix.GetRow(3)); } base.OnGUI(materialEditor, properties); } /// <summary> /// Vector2の外積を求める /// </summary> /// <param name="a">左項</param> /// <param name="b">右項</param> /// <returns>外積</returns> private static float Cross(Vector2 a, Vector2 b) { return (a.x * b.y) - (b.x * a.y); } /// <summary> /// 4隅の座標を変換する行列を求める /// </summary> /// <param name="bl">(0, 0)の変換先</param> /// <param name="tl">(0, 1)の変換先</param> /// <param name="tr">(1, 1)の変換先</param> /// <param name="br">(1, 0)の変換先</param> /// <returns>変換行列</returns> private static Matrix4x4 HomographyMatrix(Vector2 bl, Vector2 tl, Vector2 tr, Vector2 br) { var cf = bl; // cとfはblの座標で確定 Vector2 ghMatR0; Vector2 ghMatR1; Inverse(br - tr, tl - tr, out ghMatR0, out ghMatR1); var v = (bl + tr) - (tl + br); var gh = new Vector2(Vector2.Dot(ghMatR0, v), Vector2.Dot(ghMatR1, v)); // まずgとhを求める var ad = ((gh.x + 1.0f) * br) - bl; // gを使ってaとdを求める var be = ((gh.y + 1.0f) * tl) - bl; // hを使ってbとeを求める var result = Matrix4x4.identity; // Unityで扱うには4次元ベースの方が便利そうなので、Matrix4x4に整形しました result.SetColumn(0, new Vector4(ad.x, ad.y, 0.0f, gh.x)); result.SetColumn(1, new Vector4(be.x, be.y, 0.0f, gh.y)); result.SetColumn(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f)); result.SetColumn(3, new Vector4(cf.x, cf.y, 0.0f, 1.0f)); return result; } /// <summary> /// 2x2行列の逆行列を求める /// </summary> /// <param name="column0">元の行列の0列目</param> /// <param name="column1">元の行列の1列目</param> /// <param name="inverseRow0">逆行列の0行目</param> /// <param name="inverseRow1">逆行列の1行目</param> private static void Inverse(Vector2 column0, Vector2 column1, out Vector2 inverseRow0, out Vector2 inverseRow1) { var determinant = Cross(column0, column1); inverseRow0 = new Vector2(column1.y, -column1.x) / determinant; inverseRow1 = new Vector2(-column0.y, column0.x) / determinant; } }

動かしてみるとこんな感じです。

プレビュー

投稿2017/08/19 00:44

編集2017/08/23 02:16
Bongo

総合スコア10816

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

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

Aran1976734

2017/08/20 04:42

スクリプトから動かしたかったので助かりました! 丁寧に行列の説明までしてくださりとても分かりやすかったです! コードもありがとうございます!! 無事切り出すことができました!
guest

0

xstarteraさんのコメントに対して追記しようとしましたが、またもやうまくいかなかったため別回答にて追記します(一応字数制限はクリアしたつもりでしたが...何がいけなかったんでしょうか?)。

4つのノブを動かしてUV座標を決めるパターンを作ってみました。ノブのドラッグ時に新しいUV座標を求め、マテリアルのホモグラフィ行列を更新する方式としています。

ヒエラルキー
ヒエラルキー

  • ResultLabel、OriginalLabel...板の上方に浮かんでいる文字
  • ResultQuad...後述のResultControllerをアタッチした板、マテリアルは後述のUnlit/Homographyを使用
  • OriginalQuad...元のテクスチャを表示する板、マテリアルは改変なしのUnlit/Textureを使用
  • Line...ノブを繋ぐ線を描画するためのラインレンダラーをアタッチ
  • TopLeftKnob〜BottomLeftKnob...4色の球体、それぞれ後述のKnobControllerがアタッチされており、あらかじめインスペクタ上でCornerToControlを対応する頂点の値にセットしておく(併せてLine、OriginalQuad、ResultQuadもそれぞれヒエラルキー上の各オブジェクトをセット)

TopLeftKnob〜BottomLeftKnob用スクリプト

C#

1using System.Linq; 2using UnityEngine; 3 4public class KnobController : MonoBehaviour 5{ 6 public enum CornerToControl 7 { 8 TopLeft, 9 TopRight, 10 BottomRight, 11 BottomLeft 12 } 13 14 private static readonly Vector2[] UvForCorner = 15 { 16 new Vector2(0.0f, 1.0f), 17 new Vector2(1.0f, 1.0f), 18 new Vector2(1.0f, 0.0f), 19 new Vector2(0.0f, 0.0f) 20 }; 21 22 public CornerToControl Corner; 23 public LineRenderer Line; 24 public GameObject OriginalQuad; 25 public GameObject ResultQuad; 26 private Vector3 originalQuadOrigin; 27 private Vector3 originalQuadUVector; 28 private Vector3 originalQuadVVector; 29 private ResultController resultController; 30 31 /// <summary> 32 /// 直線と交差する平面上のUV座標を得る 33 /// </summary> 34 /// <param name="rayOrigin">直線の起点のワールド座標</param> 35 /// <param name="rayDirection">直線のワールド方向</param> 36 /// <param name="planeU">平面のワールドUベクトル</param> 37 /// <param name="planeV">平面のワールドVベクトル</param> 38 /// <param name="planeOrigin">平面原点のワールド座標</param> 39 /// <returns>UV座標(交点のワールド座標はplaneU * u + planeV * v + planeOrigin)</returns> 40 private static Vector2 GetUv( 41 Vector3 rayOrigin, 42 Vector3 rayDirection, 43 Vector3 planeU, 44 Vector3 planeV, 45 Vector3 planeOrigin) 46 { 47 var matrix = Matrix4x4.identity; 48 matrix.SetColumn(0, planeU); 49 matrix.SetColumn(1, planeV); 50 matrix.SetColumn(2, -rayDirection); 51 return matrix.inverse * (rayOrigin - planeOrigin); 52 } 53 54 private void OnMouseDrag() 55 { 56 this.UpdateKnobPosition(Input.mousePosition); 57 } 58 59 private void Start() 60 { 61 this.resultController = this.ResultQuad.GetComponent<ResultController>(); 62 63 // OriginalQuadのメッシュの4頂点から原点・Uベクトル・Vベクトルを調べ、ノブの初期位置を合わせる 64 var originalMesh = this.OriginalQuad.GetComponent<MeshFilter>().sharedMesh; 65 var vertices = originalMesh.vertices.Select(v => this.OriginalQuad.transform.TransformPoint(v)).ToArray(); 66 var uvs = originalMesh.uv; 67 var vertexCount = vertices.Length; 68 var bottomLeft = Vector3.zero; 69 var topLeft = Vector3.up; 70 var bottomRight = Vector3.right; 71 for (var i = 0; i < vertexCount; i++) 72 { 73 var uv = uvs[i]; 74 if (uv == UvForCorner[(int)CornerToControl.BottomLeft]) 75 { 76 bottomLeft = vertices[i]; 77 } 78 else if (uv == UvForCorner[(int)CornerToControl.TopLeft]) 79 { 80 topLeft = vertices[i]; 81 } 82 else if (uv == UvForCorner[(int)CornerToControl.BottomRight]) 83 { 84 bottomRight = vertices[i]; 85 } 86 } 87 88 this.originalQuadOrigin = bottomLeft; 89 this.originalQuadUVector = bottomRight - bottomLeft; 90 this.originalQuadVVector = topLeft - bottomLeft; 91 var knobUv = UvForCorner[(int)this.Corner]; 92 for (var i = 0; i < vertexCount; i++) 93 { 94 if (uvs[i] == knobUv) 95 { 96 this.UpdateKnobPosition(Camera.main.WorldToScreenPoint(vertices[i])); 97 break; 98 } 99 } 100 101 this.UpdateLine(); 102 } 103 104 private void UpdateKnobPosition(Vector3 screenPosition) 105 { 106 // ノブの位置を更新 107 // UV座標はレイキャストで求めてもいいのですが、レイがOriginalQuadを外れても対応できるよう、自前で算出することにしました 108 var ray = Camera.main.ScreenPointToRay(screenPosition); 109 var newUv = GetUv( 110 ray.origin, 111 ray.direction, 112 this.originalQuadUVector, 113 this.originalQuadVVector, 114 this.originalQuadOrigin); 115 // ノブの位置はレイ交点とレイ原点の中間としました 116 this.transform.position = Vector3.Lerp( 117 ray.origin, 118 (this.originalQuadUVector * newUv.x) + (this.originalQuadVVector * newUv.y) + this.originalQuadOrigin, 119 0.5f); 120 // ノブと対応するResultControllerの頂点に求めたUV座標をセット 121 switch (this.Corner) 122 { 123 default: 124 case CornerToControl.TopLeft: 125 this.resultController.TopLeft = newUv; 126 break; 127 case CornerToControl.TopRight: 128 this.resultController.TopRight = newUv; 129 break; 130 case CornerToControl.BottomRight: 131 this.resultController.BottomRight = newUv; 132 break; 133 case CornerToControl.BottomLeft: 134 this.resultController.BottomLeft = newUv; 135 break; 136 } 137 this.UpdateLine(); // ラインレンダラーの頂点位置を更新 138 } 139 140 private void UpdateLine() 141 { 142 this.Line.SetPosition((int)this.Corner, this.transform.position); 143 } 144}

ResultQuad用スクリプト
ここに以前の回答で例示したホモグラフィ変換行列算出メソッドを引っ越しました。4頂点のUV座標はプロパティとし、set中でマテリアル更新メソッドを呼ぶことにしました。

C#

1using UnityEngine; 2 3[RequireComponent(typeof(Renderer))] 4public class ResultController : MonoBehaviour 5{ 6 private Vector2 bottomLeft; 7 private Vector2 bottomRight; 8 private Material resultMaterial; 9 private Vector2 topLeft; 10 private Vector2 topRight; 11 12 public Vector2 BottomLeft 13 { 14 get { return this.bottomLeft; } 15 set 16 { 17 this.bottomLeft = value; 18 this.UpdateTexture(); 19 } 20 } 21 22 public Vector2 BottomRight 23 { 24 get { return this.bottomRight; } 25 set 26 { 27 this.bottomRight = value; 28 this.UpdateTexture(); 29 } 30 } 31 32 public Vector2 TopLeft 33 { 34 get { return this.topLeft; } 35 set 36 { 37 this.topLeft = value; 38 this.UpdateTexture(); 39 } 40 } 41 42 public Vector2 TopRight 43 { 44 get { return this.topRight; } 45 set 46 { 47 this.topRight = value; 48 this.UpdateTexture(); 49 } 50 } 51 52 private static float Cross(Vector2 a, Vector2 b) 53 { 54 return (a.x * b.y) - (b.x * a.y); 55 } 56 57 private static Matrix4x4 HomographyMatrix(Vector2 bl, Vector2 tl, Vector2 tr, Vector2 br) 58 { 59 var cf = bl; 60 Vector2 ghMatR0; 61 Vector2 ghMatR1; 62 Inverse(br - tr, tl - tr, out ghMatR0, out ghMatR1); 63 var v = (bl + tr) - (tl + br); 64 var gh = new Vector2(Vector2.Dot(ghMatR0, v), Vector2.Dot(ghMatR1, v)); 65 var ad = ((gh.x + 1.0f) * br) - bl; 66 var be = ((gh.y + 1.0f) * tl) - bl; 67 var result = Matrix4x4.identity; 68 result.SetColumn(0, new Vector4(ad.x, ad.y, 0.0f, gh.x)); 69 result.SetColumn(1, new Vector4(be.x, be.y, 0.0f, gh.y)); 70 result.SetColumn(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f)); 71 result.SetColumn(3, new Vector4(cf.x, cf.y, 0.0f, 1.0f)); 72 return result; 73 } 74 75 private static void Inverse(Vector2 column0, Vector2 column1, out Vector2 inverseRow0, out Vector2 inverseRow1) 76 { 77 var determinant = Cross(column0, column1); 78 inverseRow0 = new Vector2(column1.y, -column1.x) / determinant; 79 inverseRow1 = new Vector2(-column0.y, column0.x) / determinant; 80 } 81 82 private void Start() 83 { 84 this.topLeft = new Vector2(0.0f, 1.0f); 85 this.topRight = new Vector2(1.0f, 1.0f); 86 this.bottomRight = new Vector2(1.0f, 0.0f); 87 this.bottomLeft = new Vector2(0.0f, 0.0f); 88 } 89 90 private void UpdateTexture() 91 { 92 // 現在の4頂点から変換行列を求め、マテリアルにセット 93 if (this.resultMaterial == null) 94 { 95 this.resultMaterial = this.GetComponent<Renderer>().material; 96 } 97 this.resultMaterial.SetMatrix( 98 "_HomographyMatrix", 99 HomographyMatrix(this.bottomLeft, this.topLeft, this.topRight, this.bottomRight)); 100 } 101}

ResultQuadのマテリアル用シェーダー

HLSL

1Shader "Unlit/Homography" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 SubShader 8 { 9 Tags { "RenderType"="Opaque" } 10 LOD 100 11 12 Pass 13 { 14 CGPROGRAM 15 #pragma vertex vert 16 #pragma fragment frag 17 // make fog work 18 #pragma multi_compile_fog 19 20 #include "UnityCG.cginc" 21 22 struct appdata 23 { 24 float4 vertex : POSITION; 25 float2 uv : TEXCOORD0; 26 }; 27 28 struct v2f 29 { 30 float3 uv : TEXCOORD0; // float2をfloat3に 31 UNITY_FOG_COORDS(1) 32 float4 vertex : SV_POSITION; 33 }; 34 35 sampler2D _MainTex; 36 float4 _MainTex_ST; 37 float4x4 _HomographyMatrix; // 変換行列は行ごとに分割せず丸ごと送る 38 39 v2f vert (appdata v) 40 { 41 v2f o; 42 o.vertex = UnityObjectToClipPos(v.vertex); 43 o.uv = mul(_HomographyMatrix, float4(TRANSFORM_TEX(v.uv, _MainTex), 0.0, 1.0)).xyw; // uvを変換してからx、y、wを渡す 44 UNITY_TRANSFER_FOG(o,o.vertex); 45 return o; 46 } 47 48 fixed4 frag (v2f i) : SV_Target 49 { 50 // sample the texture 51 fixed4 col = tex2D(_MainTex, i.uv.xy / i.uv.z); // i.uvのx、yをzで割ってサンプリング座標とする 52 // apply fog 53 UNITY_APPLY_FOG(i.fogCoord, col); 54 return col; 55 } 56 ENDCG 57 } 58 } 59}

実行時の様子
図ではカメラがPerspectiveですが、Orthographicでも大丈夫なようにしたつもりです。
プレビュー

投稿2017/12/30 00:40

編集2017/12/30 01:22
Bongo

総合スコア10816

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

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

teraps

2018/01/26 13:08

反応が遅くなってしまって申し訳ありません. 試してみたところ,理想としていた処理を実現することができました! また,これで行いたかった処理も,まだ実装中なのですが上手く活用することができそうです. なにからなにまで,本当にありがとうございます. 自力でも組んでいけるよう今後の参考にさせて頂きます!
guest

0

先の回答へ追記を行おうとしましたが、うまくいかなかったため別回答にて追記します。

「ななめに切り出す」の意図を読み違えていたかもしれません。スプライトエディターでアウトラインを編集する方が適切でしょうか?こちらでしたらシェーダーを用意する必要がなく、より簡単に実現できるかと思います。こちらのサイトの記事もご参考になりそうです。

プレビュー

スクリプトからアウトラインを変更する場合はOverrideGeometryが使えそうです。

投稿2017/08/19 22:59

Bongo

総合スコア10816

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

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

teraps

2017/12/28 16:28

>Bongoさん Unityで射影変換を行いたかったため,非常に参考になりました.ありがとうございます. この処理ではスクリプトから変換したい座標をInspector上で数値入力していると思うのですが, Gameビュー上で切り出したい4点をクリック,あるいはPhotoshopの拡大処理のように ドラッグで台形を作成して指定するようなGUIを構築したいと考えております. Rayなどを飛ばして,通常のUV座標を取得することはできるのですが, これらの変換に用いる座標は通常のUV座標とは異なることと存じます, なにか,良い方法があれば教えて頂けませんでしょうか. この処理に用いている座標についての情報だけでも助かります. 質問に質問を重ねる形になってしまいすみませんが,回答頂けると幸いです.
Bongo

2017/12/28 21:41

ご参考になりましたようで幸いです。 射影変換行列にさらに適当な変換行列を掛ければ異なる座標系にも対応可能と思いますが、xstarteraさんの想定されるUV座標はどのようなものでしょうか? 私が回答中で想定したのはテクスチャ画像の左下隅が原点、そこから上方向がU軸+で画像上端がU+1.0、原点から右方向がV軸+で画像右端がV+1.0なのですが、試しにQuadオブジェクトに対してレイキャストし、得られたRaycastHitのtextureCoordを見てみたところ、その場合はちゃんとこの座標系になっていたようです。xstarteraさんの場合はどのような条件でレイキャストされましたでしょうか。
teraps

2017/12/29 16:25

すみません,勘違いしておりました.RaycastでのUV座標取得は問題なく行えました. (ただ,0.1-0.9の小数点第一までですが…) 別の質問になってしまうのですが,EditorスクリプトだとRaycastが使えず(?)困っております. 他のMonoBehaviourスクリプトを作ってそこから持ってくるのも上手くいかず,, また,exeにビルドする際などもEditorスクリプトは出力できないようです. このShaderでのホモグラフィ処理を,Editor上ではなくMonoBehaviourスクリプトで 実行することは可能でしょうか?そちらで動かせた方が扱いやすいと思って改変を試しています. 何度もすみませんが,よければご助力頂けると幸いですm(_ _)m
Bongo

2017/12/30 00:41

実際のところ、上記のシェーダーコードで「_BottomLeftTopLeft」「_TopRightBottomRight」で四隅の座標を覚えさせたり、「_HomographyMatrixR0」〜「_HomographyMatrixR3」でわざわざ行列を行に分けて渡したりしているのは、インスペクタ上で4隅の座標を設定できるように試行錯誤した結果でして、本来は不要なものです。このへんを削除し単純化して、実際の実行時の使用を主眼とした例を追記します。ご参考になりますでしょうか? ※コード中のコメントにもありますが、UV座標をレイキャストで求める方式ですとレイが板に命中しなかった場合にUV座標が得られないことに後になって気付き、自前で交点を求めることにしました。板の下辺をU軸、左辺をV軸とする平面との交点をUV座標として採用しております。また、字数を少々オーバーしてしまったため、以前の回答ではホモグラフィ行列算出メソッドに付いていたドキュメントコメントを削除しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問