現状では画面上だと数ピクセル~数十ピクセル四方しかないタイル上に320×320のテクスチャを貼っている状態かと思いますので、テクスチャが縮小されすぎて潰れていると言えそうです。
ズームの仕組みをいじってもおそらくダメなんじゃないでしょうかね...?もし仮にカメラのSizeを変えずに、代わりにたとえばワールドマップのメッシュオブジェクトのスケールを拡大縮小することで縮尺を操作したとしても、結局遠距離視点では状況的に同じことになってディテールが潰れてしまうでしょう。
テクスチャの反復周期をもっと長くして、広い範囲にマッピングしてやる必要があるかと思います。先日C# - Unity2D 描画がちらつく|teratailの回答中で申し上げた「2枚ポリゴン化作戦」で使用したWorldシェーダーをベースに、下記のように改変してみました。
ShaderLab
1Shader "Unlit/World"
2{
3 Properties
4 {
5 _MainTex ("Texture", 2D) = "white" {}
6 _DataTex ("Data", 2D) = "black" {}
7 _Width ("Width", Int) = 250
8 _Height ("Height", Int) = 250
9 [IntRange] _Magnification ("Magnification", Range(1, 32)) = 8
10 [Toggle] _Dynamic ("Dynamic", Float) = 0
11 }
12 SubShader
13 {
14 Tags { "RenderType"="Opaque" }
15
16 Pass
17 {
18 CGPROGRAM
19 #pragma vertex vert
20 #pragma fragment frag
21 #pragma multi_compile _ _DYNAMIC_ON
22 #include "UnityCG.cginc"
23
24 struct appdata
25 {
26 float4 vertex : POSITION;
27 float2 uv : TEXCOORD0;
28 };
29
30 struct v2f
31 {
32 float2 uv : TEXCOORD0;
33 float4 vertex : SV_POSITION;
34 };
35
36 sampler2D _MainTex;
37 float4 _MainTex_ST;
38 float4 _MainTex_TexelSize;
39 sampler2D _DataTex;
40 float4 _DataTex_TexelSize;
41 int _Width;
42 int _Height;
43 int _Magnification; // 拡大率...たとえば8なら、マップ上の8x8タイルをテクスチャ反復の1周期とする
44
45 v2f vert(appdata v)
46 {
47 v2f o;
48 o.vertex = UnityObjectToClipPos(v.vertex);
49 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
50 return o;
51 }
52
53 // 固定拡大...テクスチャ反復数を縮尺によらず一定にする
54 fixed4 fixedMagnification(v2f i)
55 {
56 float2 worldSize = float2(_Width, _Height);
57 float2 worldUv = i.uv * worldSize;
58 float2 tileCoord = floor(worldUv);
59 float2 dataUv = (tileCoord + 0.5) * _DataTex_TexelSize.xy;
60 float4 texCorners = tex2D(_DataTex, dataUv);
61
62 // worldUvを拡大率で割ることでtileUvの周期を長くする
63 worldUv /= _Magnification;
64 float2 tileUv = frac(worldUv);
65
66 // 画面上で1ピクセルずれるとUV座標がどれだけ飛ぶかを求めておく
67 float2 gradScale = texCorners.zw - texCorners.xy;
68 float2 dUvdx = ddx(worldUv) * gradScale;
69 float2 dUvdy = ddy(worldUv) * gradScale;
70
71 // UV座標の飛び幅だけUV矩形を小さくして隣接テクスチャの色漏れを防止する
72 // テクスチャの外周が少し削ぎ落とされる欠点はありますが、テクスチャに幅広い余白を設けなくとも
73 // 縮尺によらず安定して色漏れを防止できるんじゃないかと思います
74 float2 texCornerOffset = min(gradScale, max(_MainTex_TexelSize.xy, dUvdx + dUvdy));
75
76 // ミップマップを使う場合、tex2Dだと引数に与えたUV座標の変化率を基にミップレベルが選択されますが
77 // 今回のように特殊なUV座標を使ってサンプリングすると、正しいレベルが選択されないことがあります
78 // そんな時はtex2Dgradを使うと、レベル選択に使われるUV変化率を独自に与えてやることができます
79 float2 uv = lerp(texCorners.xy + texCornerOffset, texCorners.zw - texCornerOffset, tileUv);
80 fixed4 col = tex2Dgrad(_MainTex, uv, dUvdx, dUvdy);
81 return col;
82 }
83
84 // 可変拡大...遠くから見たときほどテクスチャ反復数を減らす
85 fixed4 dynamicMagnification(v2f i)
86 {
87 // 基本拡大量は固定拡大版と同じ
88 float2 worldSize = float2(_Width, _Height);
89 float2 worldUv = i.uv * worldSize;
90 float2 tileCoord = floor(worldUv);
91 float2 dataUv = (tileCoord + 0.5) * _DataTex_TexelSize.xy;
92 float4 texCorners = tex2D(_DataTex, dataUv);
93 worldUv /= _Magnification;
94 float2 gradScale = texCorners.zw - texCorners.xy;
95 float2 dUvdx = ddx(worldUv) * gradScale;
96 float2 dUvdy = ddy(worldUv) * gradScale;
97
98 // 縮尺の程度による追加の拡大量を算出する
99 float2 magRatio = (dUvdx + dUvdy) * _MainTex_TexelSize.zw;
100 float level = log2(max(1.0, min(magRatio.x, magRatio.y)));
101 float levelIndex = floor(level);
102 float levelRatio = frac(level);
103 float extraScale = pow(0.5, levelIndex);
104
105 // 追加拡大を施してテクスチャをサンプリング
106 worldUv *= extraScale;
107 dUvdx *= extraScale;
108 dUvdy *= extraScale;
109 float2 tileUv = frac(worldUv);
110 float2 texCornerOffset = min(gradScale, max(_MainTex_TexelSize.xy, dUvdx + dUvdy));
111 float2 uv = lerp(texCorners.xy + texCornerOffset, texCorners.zw - texCornerOffset, tileUv);
112 float4 col0 = tex2Dgrad(_MainTex, uv, dUvdx, dUvdy);
113
114 // さらにもう一段階拡大してテクスチャをサンプリングし...
115 worldUv *= 0.5;
116 dUvdx *= 0.5;
117 dUvdy *= 0.5;
118 tileUv = frac(worldUv);
119 texCornerOffset = min(gradScale, max(_MainTex_TexelSize.xy, dUvdx + dUvdy));
120 uv = lerp(texCorners.xy + texCornerOffset, texCorners.zw - texCornerOffset, tileUv);
121 float4 col1 = tex2Dgrad(_MainTex, uv, dUvdx, dUvdy);
122
123 // 2つを混ぜることでレベル間のつなぎ目をなめらかにする
124 fixed4 col = lerp(col0, col1, levelRatio);
125 return col;
126 }
127
128 fixed4 frag(v2f i) : SV_Target
129 {
130 #ifdef _DYNAMIC_ON
131 return dynamicMagnification(i);
132 #else
133 return fixedMagnification(i);
134 #endif
135 }
136 ENDCG
137 }
138 }
139}
Generate Mip Mapsオン、Filter ModeはTrilinearとし、マテリアルのMagnificationは32、Dynamicはオフだと下図のような見え方になりました。タイルの数は250×250ですが、テクスチャは32×32タイルで1周期になるようにしましたので、ある程度離れた位置からでも砂紋の形が見えます。ですがマップ全域が映るほどの距離になるとディテールがわかりにくくなりますね。
Magnificationを4、Dynamicオンだと下図のような見え方になりました。遠距離であるほどテクスチャ反復数が小さくなるので、マップ全域でも砂紋(このスケールだと砂丘でしょうか)が見えています。一部分を拡大していくと全体と同じ形が再帰的に現れるような動作で面白そうだと思ったのですが、その分ちょっとDynamicオフよりも計算量は多くなってしまいます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/07/07 10:11 編集
2019/07/07 21:28
退会済みユーザー
2019/07/08 08:58 編集