unityにて、建物の天井を鏡面にするためにリフレクションプローブを使っています。
天井は平らなのですが、上から見た時の形状は四角ではなく複雑な形をしています。
鏡面っぽくはなっています。しかし、映り込みが明らかにずれていたりして違和感があります。
自然に映るようにするための方法を試しましたが、その条件の一つとして、プローブの効果範囲(黄色い線で表示される)を対象のオブジェクトにピッタリ合わせないとならないようです。
天井の輪郭は複雑なので、うまくいきませんでした。
どのような方法であれば正確な映り込みを実現できるのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答2件
0
ベストアンサー
縁が複雑な形であっても、反射面が平面ならば、反射像を別途レンダリングして鏡面に投影するテクニックが使えるのではないかと思います。
MirrorReflection4 - Unify Community Wikiを試してみたところ、下図のように天井に不定形の鏡を設置することができました。
コードについては、2018.2.14f1でも少し修正するだけで動作しました。
MirrorReflection.csの...
- 166行目の
reflectionCamera = go.camera;
をreflectionCamera = go.GetComponent<Camera>();
にする - 170行目の
reflectionCamera.gameObject.AddComponent("FlareLayer");
をreflectionCamera.gameObject.AddComponent<FlareLayer>();
にする
参考:UnityのMirrorRefrectionによる鏡の表現 - Qiita
#追記
メッシュの点検用スクリプトを作ってみました。
Editorフォルダを作って、中に下記スクリプトを入れ...
C#
1using System.Linq; 2using UnityEditor; 3using UnityEngine; 4 5public static class MirrorMeshChecker 6{ 7 [MenuItem("Utility/Check Mirror Mesh")] 8 public static void CheckMirrorMesh() 9 { 10 var mesh = Selection.activeObject as Mesh; 11 if (mesh == null) 12 { 13 return; 14 } 15 16 var vertices = mesh.vertices; 17 var triangles = mesh.triangles; 18 var faceCount = triangles.Length / 3; 19 var normals = new Vector3[faceCount]; 20 for (var i = 0; i < faceCount; i++) 21 { 22 var j = i * 3; 23 var v0 = vertices[triangles[j]]; 24 var v1 = vertices[triangles[j + 1]]; 25 var v2 = vertices[triangles[j + 2]]; 26 normals[i] = Vector3.Cross(v1 - v0, v2 - v0).normalized; 27 } 28 29 var normal = normals.Aggregate((sum, n) => sum + n).normalized; 30 var normalVariance = normals.Aggregate( 31 Vector3.zero, 32 (variance, n) => 33 { 34 var d = n - normal; 35 return variance + Vector3.Scale(d, d); 36 }); 37 var plane = new Plane(normal, Vector3.zero); 38 var distances = vertices.Select(v => plane.GetDistanceToPoint(v)).ToArray(); 39 var distance = distances.Average(); 40 var distanceVariance = distances.Aggregate( 41 0.0f, 42 (variance, r) => 43 { 44 var d = r - distance; 45 return variance + (d * d); 46 }); 47 Debug.LogFormat("Normal:{0}", normal.ToString("F8")); 48 Debug.LogFormat("Normal Variance:{0}", normalVariance.ToString("F8")); 49 Debug.LogFormat("Distance:{0:F8}", distance); 50 Debug.LogFormat("Distance Variance:{0:F8}", distanceVariance); 51 } 52}
鏡メッシュを選択し...
「Utility」→「Check Mirror Mesh」を実行すると...
コンソールに結果が表示されるかと思います。
Normalがほぼ(0, 1, 0)で、Normal Varianceがほぼ(0, 0, 0)、DistanceとDistance Varianceがいずれもほぼ0ならメッシュに問題はなさそうなので、不具合の原因は他の部分にあると思われます。
Normal、Distanceが上記と異なっていても、Normal Varianceがほぼ(0, 0, 0)、Distance Varianceがほぼ0ならシェーダーの修正で対応可能なはずです。
Normal Variance、Distance Varianceが0から大きくずれているようですと、鏡が平面でない可能性が大きいです。その場合はモデルを修正する必要がありそうです...
#追記
プロジェクトファイルのご提示ありがとうございます。とても参考になりました。鏡のオブジェクトは「l2_slab」、メッシュは「_I_u_W_F_N」でよろしいでしょうか。
このメッシュは2つのサブメッシュから構成されており、鏡マテリアルの面も天井平面だけでなく側面も含んだ非平面のようでした。
回答に追記したMirrorMeshChecker
は、複数のサブメッシュを持たない平面メッシュを想定したものでしたので、正しく面の向き・位置を求めることができなかったようです。
さしあたり、下記のようにMirrorMeshChecker
に面法線が下方を向いている面だけを計算に加味するよう泥縄的改修を加えて実行してみたところ...
C#
1using System.Collections.Generic; 2using System.Linq; 3using UnityEditor; 4using UnityEngine; 5 6public static class MirrorMeshChecker 7{ 8 [MenuItem("Utility/Check Mirror Mesh")] 9 public static void CheckMirrorMesh() 10 { 11 var mesh = Selection.activeObject as Mesh; 12 if (mesh == null) 13 { 14 return; 15 } 16 17 var subMeshCount = mesh.subMeshCount; 18 var vertices = mesh.vertices; 19 for (var k = 0; k < subMeshCount; k++) 20 { 21 var triangles = mesh.GetTriangles(k); 22 var faceCount = triangles.Length / 3; 23 var normals = new List<Vector3>(); 24 var faceVertices = new HashSet<Vector3>(); 25 for (var i = 0; i < faceCount; i++) 26 { 27 var j = i * 3; 28 var v0 = vertices[triangles[j]]; 29 var v1 = vertices[triangles[j + 1]]; 30 var v2 = vertices[triangles[j + 2]]; 31 var n = Vector3.Cross(v1 - v0, v2 - v0).normalized; 32 if (Vector3.Dot(n, Vector3.down) < 0.9f) 33 { 34 continue; 35 } 36 normals.Add(n); 37 faceVertices.Add(v0); 38 faceVertices.Add(v1); 39 faceVertices.Add(v2); 40 } 41 42 if (normals.Count <= 0) 43 { 44 continue; 45 } 46 var normal = normals.Aggregate((sum, n) => sum + n).normalized; 47 var normalVariance = normals.Aggregate( 48 Vector3.zero, 49 (variance, n) => 50 { 51 var d = n - normal; 52 return variance + Vector3.Scale(d, d); 53 }); 54 var plane = new Plane(normal, Vector3.zero); 55 var distances = faceVertices.Select(v => plane.GetDistanceToPoint(v)).ToArray(); 56 var distance = distances.Average(); 57 var distanceVariance = distances.Aggregate( 58 0.0f, 59 (variance, r) => 60 { 61 var d = r - distance; 62 return variance + (d * d); 63 }); 64 Debug.LogFormat("Submesh {0}:", k); 65 Debug.LogFormat("\tNormal:{0}", normal.ToString("F8")); 66 Debug.LogFormat("\tNormal Variance:{0}", normalVariance.ToString("F8")); 67 Debug.LogFormat("\tDistance:{0:F8}", distance); 68 Debug.LogFormat("\tDistance Variance:{0:F8}", distanceVariance); 69 } 70 } 71}
下図のように向きは(0, -1, 0)で位置は約-5.2、つまり地上5.2mの位置にある...という結果になりました。
そこで、MirrorReflection.csの46、47行目を下記のように変更すると...
C#
1 Vector3 pos = transform.TransformPoint(new Vector3(0.0f, 5.2f, 0.0f)); 2 Vector3 normal = -transform.up;
下図のように、天井に風景が映り込みました。
投稿2018/11/05 13:13
編集2018/11/08 12:05総合スコア10816
0
Unityは使ったことがないですが、見た感じParallax-Corrected Cubemapのような技法で鏡面反射を表現する仕組みですかね。
これは鏡に映る対象が直方体の面に一致しているときのみ正しい結果が出ます。
その代わり曲面や無数の向きの違う鏡面を軽い処理で扱えます。
使う鏡面が1枚の平面なら必要ありません。Bongoさんの回答の手法が適切です。
天井の輪郭が複雑というのは部屋の壁も不定形でしょうか。でしたら対象を部屋に合わせられないのでどうやってもずれます。
投稿2018/11/06 01:20
総合スコア3047
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/11/07 06:28
2018/11/07 07:48
2018/11/07 08:39
2018/11/07 12:00
2018/11/07 13:28
2018/11/08 01:18
2018/11/08 03:10
2018/11/08 05:06
2018/11/08 12:17
2018/11/09 01:36
2018/11/09 01:55
2018/11/09 02:10
2018/11/09 03:01
2018/11/09 04:33