-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAlbedoBaker.cs
More file actions
120 lines (106 loc) · 4.62 KB
/
Copy pathAlbedoBaker.cs
File metadata and controls
120 lines (106 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System.Drawing;
using System.Drawing.Imaging;
using System.Numerics;
using System.Runtime.InteropServices;
namespace RustMapViewer;
public static class AlbedoBaker
{
private static readonly Vector4 StartColor = new(0.28627452f, 23f / 85f, 0.24705884f, 1f);
private static readonly Vector4 WaterColor = new(0.16941601f, 0.31755757f, 0.36200002f, 1f);
private static readonly Vector4 GravelColor = new(0.25f, 37f / 152f, 0.22039475f, 1f);
private static readonly Vector4 DirtColor = new(0.6f, 0.47959462f, 0.33f, 1f);
private static readonly Vector4 SandColor = new(0.7f, 0.65968585f, 0.5277487f, 1f);
private static readonly Vector4 GrassColor = new(0.35486364f, 0.37f, 0.2035f, 1f);
private static readonly Vector4 ForestColor = new(0.24843751f, 0.3f, 9f / 128f, 1f);
private static readonly Vector4 RockColor = new(0.4f, 0.39379844f, 0.37519377f, 1f);
private static readonly Vector4 SnowColor = new(0.86274517f, 0.9294118f, 0.94117653f, 1f);
private static readonly Vector4 PebbleColor = new(7f / 51f, 0.2784314f, 0.2761563f, 1f);
private static readonly Vector4 OffShoreColor = new(0.04090196f, 0.22060032f, 14f / 51f, 1f);
private static readonly Vector3 SunDirection = Vector3.Normalize(new Vector3(0.95f, 2.87f, 2.37f));
private static readonly Vector4 Half = new(0.5f, 0.5f, 0.5f, 0.5f);
private const int ChDirt = 0;
private const int ChSnow = 1;
private const int ChSand = 2;
private const int ChRock = 3;
private const int ChGrass = 4;
private const int ChForest = 5;
private const int ChStones = 6;
private const int ChGravel = 7;
public static string BakeJpegDataUri(HeightMap height, SplatMap splat, float worldSize, int res, long jpegQuality = 85)
{
byte[] pixels = new byte[res * res * 3];
float half = worldSize * 0.5f;
float step = worldSize / (res - 1);
Parallel.For(0, res, row =>
{
int z = res - 1 - row;
float wz = -half + z * step;
for (int x = 0; x < res; x++)
{
float wx = -half + x * step;
float h = height.GetHeight(wx, wz);
Vector4 c = StartColor;
c = Vector4.Lerp(c, GravelColor, splat.GetSplat(wx, wz, ChGravel) * GravelColor.W);
c = Vector4.Lerp(c, PebbleColor, splat.GetSplat(wx, wz, ChStones) * PebbleColor.W);
c = Vector4.Lerp(c, RockColor, splat.GetSplat(wx, wz, ChRock) * RockColor.W);
c = Vector4.Lerp(c, DirtColor, splat.GetSplat(wx, wz, ChDirt) * DirtColor.W);
c = Vector4.Lerp(c, GrassColor, splat.GetSplat(wx, wz, ChGrass) * GrassColor.W);
c = Vector4.Lerp(c, ForestColor, splat.GetSplat(wx, wz, ChForest) * ForestColor.W);
c = Vector4.Lerp(c, SandColor, splat.GetSplat(wx, wz, ChSand) * SandColor.W);
c = Vector4.Lerp(c, SnowColor, splat.GetSplat(wx, wz, ChSnow) * SnowColor.W);
float depth = -h;
if (depth > 0f)
{
c = Vector4.Lerp(c, WaterColor, Math.Clamp(0.5f + depth / 5f, 0f, 1f));
c = Vector4.Lerp(c, OffShoreColor, Math.Clamp(depth / 50f, 0f, 1f));
}
else
{
float hl = height.GetHeight(wx - step, wz);
float hr = height.GetHeight(wx + step, wz);
float hd = height.GetHeight(wx, wz - step);
float hu = height.GetHeight(wx, wz + step);
Vector3 normal = Vector3.Normalize(new Vector3(hl - hr, 2f * step, hd - hu));
float sun = MathF.Max(Vector3.Dot(normal, SunDirection), 0f);
c += (sun - 0.5f) * 0.65f * c;
c = (c - Half) * 0.94f + Half;
}
c *= 1.05f;
int o = (row * res + x) * 3;
pixels[o] = ToByte(c.Z);
pixels[o + 1] = ToByte(c.Y);
pixels[o + 2] = ToByte(c.X);
}
});
using Bitmap bitmap = new(res, res, PixelFormat.Format24bppRgb);
BitmapData data = bitmap.LockBits(new Rectangle(0, 0, res, res), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
try
{
for (int row = 0; row < res; row++)
{
Marshal.Copy(pixels, row * res * 3, data.Scan0 + row * data.Stride, res * 3);
}
}
finally
{
bitmap.UnlockBits(data);
}
return JpegDataUri(bitmap, jpegQuality);
}
public static string JpegDataUri(Bitmap bitmap, long quality)
{
ImageCodecInfo codec = ImageCodecInfo.GetImageEncoders().First(e => e.FormatID == ImageFormat.Jpeg.Guid);
using EncoderParameters encoderParams = new(1);
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
using MemoryStream ms = new();
bitmap.Save(ms, codec, encoderParams);
return "data:image/jpeg;base64," + Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}
public static string PngDataUri(Bitmap bitmap)
{
using MemoryStream ms = new();
bitmap.Save(ms, ImageFormat.Png);
return "data:image/png;base64," + Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}
private static byte ToByte(float v) => (byte)Math.Clamp(v * 255f, 0f, 255f);
}