Skip to content

Commit 5479886

Browse files
committed
Texture scaling
1 parent 36810fe commit 5479886

File tree

3 files changed

+162
-9
lines changed

3 files changed

+162
-9
lines changed

Runtime/Utility/TextureScale.cs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
using System.Collections.Generic;
2+
using UnityEngine;
3+
using System.Threading.Tasks;
4+
5+
namespace Gameframe.Procgen
6+
{
7+
// Only works on ARGB32, RGB24 and Alpha8 textures that are marked readable
8+
public static class TextureScale
9+
{
10+
public class TaskData
11+
{
12+
public int start;
13+
public int end;
14+
15+
public TaskData(int s, int e)
16+
{
17+
start = s;
18+
end = e;
19+
}
20+
}
21+
22+
public static async Task PointAsync(Texture2D tex, int newWidth, int newHeight)
23+
{
24+
await ThreadedScaleAsync(tex, newWidth, newHeight, false);
25+
}
26+
27+
public static async Task BilinearAsync(Texture2D tex, int newWidth, int newHeight)
28+
{
29+
await ThreadedScaleAsync(tex, newWidth, newHeight, true);
30+
}
31+
32+
private static async Task ThreadedScaleAsync(Texture2D tex, int newWidth, int newHeight, bool useBilinear)
33+
{
34+
var texColors = tex.GetPixels();
35+
var newColors = new Color[newWidth * newHeight];
36+
37+
float ratioX;
38+
float ratioY;
39+
if (useBilinear)
40+
{
41+
ratioX = 1.0f / ((float) newWidth / (tex.width - 1));
42+
ratioY = 1.0f / ((float) newHeight / (tex.height - 1));
43+
}
44+
else
45+
{
46+
ratioX = ((float) tex.width) / newWidth;
47+
ratioY = ((float) tex.height) / newHeight;
48+
}
49+
50+
var width = tex.width;
51+
52+
var cores = Mathf.Min(SystemInfo.processorCount, newHeight);
53+
var slice = newHeight / cores;
54+
55+
var tasks = new List<Task>();
56+
57+
if (cores > 1)
58+
{
59+
for (var i = 0; i < cores; i++)
60+
{
61+
var taskData = new TaskData(slice * i, slice * (i + 1));
62+
var task = Task.Run(() =>
63+
{
64+
if (useBilinear)
65+
{
66+
BilinearScale(taskData,texColors,newColors,width,newWidth,ratioX,ratioY);
67+
}
68+
else
69+
{
70+
PointScale(taskData,texColors,newColors,width,newWidth,ratioX,ratioY);
71+
}
72+
});
73+
tasks.Add(task);
74+
}
75+
await Task.WhenAll(tasks);
76+
}
77+
else
78+
{
79+
var taskData = new TaskData(0, newHeight);
80+
await Task.Run(() =>
81+
{
82+
if (useBilinear)
83+
{
84+
BilinearScale(taskData,texColors,newColors,width,newWidth,ratioX,ratioY);
85+
}
86+
else
87+
{
88+
PointScale(taskData,texColors,newColors,width,newWidth,ratioX,ratioY);
89+
}
90+
});
91+
}
92+
93+
tex.Resize(newWidth, newHeight);
94+
tex.SetPixels(newColors);
95+
tex.Apply();
96+
}
97+
98+
private static void BilinearScale(TaskData taskData, Color[] texColors, Color[] newColors, int width, int newWidth, float ratioX, float ratioY)
99+
{
100+
for (var y = taskData.start; y < taskData.end; y++)
101+
{
102+
int yFloor = (int) Mathf.Floor(y * ratioY);
103+
var y1 = yFloor * width;
104+
var y2 = (yFloor + 1) * width;
105+
var yw = y * newWidth;
106+
107+
for (var x = 0; x < newWidth; x++)
108+
{
109+
int xFloor = (int) Mathf.Floor(x * ratioX);
110+
var xLerp = x * ratioX - xFloor;
111+
newColors[yw + x] = ColorLerpUnclamped(
112+
ColorLerpUnclamped(texColors[y1 + xFloor], texColors[y1 + xFloor + 1], xLerp),
113+
ColorLerpUnclamped(texColors[y2 + xFloor], texColors[y2 + xFloor + 1], xLerp),
114+
y * ratioY - yFloor);
115+
}
116+
}
117+
}
118+
119+
private static void PointScale(TaskData taskData, Color[] texColors, Color[] newColors, int width, int newWidth, float ratioX, float ratioY)
120+
{
121+
for (var y = taskData.start; y < taskData.end; y++)
122+
{
123+
var thisY = (int) (ratioY * y) * width;
124+
var yw = y * newWidth;
125+
for (var x = 0; x < newWidth; x++)
126+
{
127+
newColors[yw + x] = texColors[(int) (thisY + ratioX * x)];
128+
}
129+
}
130+
}
131+
132+
private static Color ColorLerpUnclamped(Color c1, Color c2, float value)
133+
{
134+
return new Color(c1.r + (c2.r - c1.r) * value,
135+
c1.g + (c2.g - c1.g) * value,
136+
c1.b + (c2.b - c1.b) * value,
137+
c1.a + (c2.a - c1.a) * value);
138+
}
139+
140+
}
141+
}

Runtime/Utility/TextureScale.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/WorldMap/Views/WorldMapTextureView.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@ namespace Gameframe.Procgen
44
{
55
public class WorldMapTextureView : MonoBehaviour, IWorldMapView
66
{
7-
[SerializeField] private Renderer _renderer = null;
7+
[SerializeField] private Material _material = null;
88
[SerializeField] private bool mainTexture = false;
99
[SerializeField] private string texturePropertyName = "_BaseMap";
1010

1111
[SerializeField] private TerrainTable _terrainTable = null;
12-
13-
[SerializeField] private bool scaleRenderer = false;
14-
12+
1513
[SerializeField] private bool gradiate = false;
1614

1715
[SerializeField] private bool fillRegions = false;
@@ -24,7 +22,10 @@ public class WorldMapTextureView : MonoBehaviour, IWorldMapView
2422
[SerializeField] private Color[] regionColors = new Color[0];
2523
[SerializeField] private FilterMode filterMode = FilterMode.Point;
2624

27-
public void DisplayMap(WorldMapData worldMapData)
25+
[SerializeField] private bool scaleTexture = false;
26+
[SerializeField] private float textureScale = 2f;
27+
28+
public async void DisplayMap(WorldMapData worldMapData)
2829
{
2930
var heightMapLayer = worldMapData.GetLayer<HeightMapLayerData>();
3031
var regionMapLayer = worldMapData.GetLayer<RegionMapLayerData>();
@@ -98,21 +99,21 @@ public void DisplayMap(WorldMapData worldMapData)
9899
texture.filterMode = filterMode;
99100
SetTexture(texture);
100101

101-
if (scaleRenderer)
102+
if (scaleTexture)
102103
{
103-
_renderer.transform.localScale = new Vector3(width, height, 1);
104+
await TextureScale.BilinearAsync(texture, Mathf.Min(2048,Mathf.RoundToInt(width * textureScale)), Mathf.Min(2048,Mathf.RoundToInt(height * textureScale)));
104105
}
105106
}
106107

107108
private void SetTexture(Texture2D texture)
108109
{
109110
if (!mainTexture)
110111
{
111-
_renderer.sharedMaterial.SetTexture(texturePropertyName, texture);
112+
_material.SetTexture(texturePropertyName, texture);
112113
}
113114
else
114115
{
115-
_renderer.sharedMaterial.mainTexture = texture;
116+
_material.mainTexture = texture;
116117
}
117118
}
118119

0 commit comments

Comments
 (0)