载入中...
搜索中...
未找到
TerrainImageMask.cpp
浏览该文件的文档.
2#include <array>
5
6namespace eve::procgen {
7namespace {
8std::array<double, 3> lab(double r, double g, double b) {
9 auto linear = [](double v) { return 100 * (v > 0.04045 ? std::pow((v + 0.055) / 1.055, 2.4) : v / 12.92); };
10 r = linear(r);
11 g = linear(g);
12 b = linear(b);
13 auto f = [](double v) { return v > 0.008856 ? std::pow(v, 1.0 / 3) : 7.787 * v + 16.0 / 116; };
14 const double x = f((r * 0.4124 + g * 0.3576 + b * 0.1805) / 95.047);
15 const double y = f((r * 0.2126 + g * 0.7152 + b * 0.0722) / 100);
16 const double z = f((r * 0.0193 + g * 0.1192 + b * 0.9505) / 108.883);
17 return {116 * y - 16, 500 * (x - y), 200 * (y - z)};
18}
19} // namespace
21 const Heightmap& green, const Heightmap& blue, const Heightmap& alpha,
23 using namespace raster_detail;
24 auto same = [](const Heightmap& a, const Heightmap& b) {
25 return a.getWidth() == b.getWidth() && a.getHeight() == b.getHeight();
26 };
27 if (!validRaster(target) || !validRaster(input) || !validRaster(red) || !validRaster(green) || !validRaster(blue) ||
28 !validRaster(alpha) || !validRaster(curve) || !same(target, input) || !same(red, green) || !same(red, blue) ||
29 !same(red, alpha) || curve.getHeight() != 1 || s.scaleX == 0 || s.scaleZ == 0 || s.accuracy < 0 ||
30 s.accuracy > 1 || s.filter < TerrainImageFilter::MaximumRgb || s.filter > TerrainImageFilter::Alpha ||
31 mode < TerrainMaskBlend::Multiply || mode > TerrainMaskBlend::Subtract)
32 return invalid("terrain.imageMask: finite compatible planes, curve and valid settings required");
33 for (float v : {s.offsetX, s.offsetZ, s.scaleX, s.scaleZ, s.rotation, s.red, s.green, s.blue, s.accuracy})
34 if (!std::isfinite(v)) return invalid("terrain.imageMask: finite settings required");
35 const auto selected = lab(s.red, s.green, s.blue);
36 const double cosine = std::cos(double(s.rotation)), sine = std::sin(double(s.rotation));
37 std::vector<float> output(target.data().size());
38 for (int z = 0; z < target.getHeight(); ++z)
39 for (int x = 0; x < target.getWidth(); ++x) {
40 const double px = ((x + 0.5) / target.getWidth() - 0.5 - s.offsetX) / s.scaleX;
41 const double pz = ((z + 0.5) / target.getHeight() - 0.5 - s.offsetZ) / s.scaleZ;
42 double u = cosine * px + sine * pz + 0.5, v = -sine * px + cosine * pz + 0.5;
43 if (s.tiling) {
44 auto wrap = [](double q) { return q > 0 ? std::fmod(q, 1.0) : 1 + std::fmod(q, 1.0); };
45 u = wrap(u);
46 v = wrap(v);
47 }
48 double filter = 0;
49 if (u >= 0 && u <= 1 && v >= 0 && v <= 1) {
50 const double r = textureSample(red, u, v), g = textureSample(green, u, v),
51 b = textureSample(blue, u, v);
52 switch (s.filter) {
53 case TerrainImageFilter::MaximumRgb: filter = std::max({r, g, b}); break;
54 case TerrainImageFilter::Red: filter = r; break;
55 case TerrainImageFilter::Green: filter = g; break;
56 case TerrainImageFilter::Blue: filter = b; break;
57 case TerrainImageFilter::Alpha: filter = textureSample(alpha, u, v); break;
59 double difference = 0;
60 if (!(std::abs(r - s.red) < 0.00001 && std::abs(g - s.green) < 0.00001 &&
61 std::abs(b - s.blue) < 0.00001)) {
62 const auto color = lab(r, g, b);
63 difference = std::clamp(
64 std::hypot(color[0] - selected[0], color[1] - selected[1], color[2] - selected[2]), 0.0,
65 100.0);
66 }
67 if (difference < (1 - double(s.accuracy)) * 100) filter = 1 - difference / 100 * s.accuracy;
68 break;
69 }
70 }
71 }
72 const double transformed = curveSample(curve, filter);
73 const size_t i = size_t(z) * target.getWidth() + x;
74 const double old = input.data()[i];
75 double result = old;
76 switch (mode) {
77 case TerrainMaskBlend::Multiply: result = old * transformed; break;
78 case TerrainMaskBlend::Maximum: result = std::max(old, transformed); break;
79 case TerrainMaskBlend::Minimum: result = std::min(old, transformed); break;
80 case TerrainMaskBlend::Add: result = old + transformed; break;
81 case TerrainMaskBlend::Subtract: result = old - transformed; break;
82 }
83 if (!isRepresentable(result)) return invalid("terrain.imageMask: output exceeds finite float range");
84 output[i] = float(result);
85 }
86 return publish(target, std::move(output));
87}
88
91 TerrainMaskBlend mode) {
92 auto scalarSettings = settings;
93 scalarSettings.filter = TerrainImageFilter::Red;
94 return generateTerrainImageMask(target, input, source, source, source, source, curve, scalarSettings, mode);
95}
96} // namespace eve::procgen
LogicalId target
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::string output
const std::string & s
float pz
EvpackChunkInput input
Definition Evpack.cpp:170
tensor::Graph g
Definition GpuGraph.cpp:7
float u
Definition Grass.cpp:233
std::array< double, 10 > q
double r
float v
std::vector< Colorf > px
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float f
std::string filter
Heightmap curve
TerrainThermalSettings settings
const UnitySourceAsset & source
Move-only operation result carrying either a value or Status.
Definition Result.h:155
In-memory terrain heightmap: a dense float grid (row-major, index = y * width + x) materialized from ...
Definition Heightmap.h:21
int getHeight() const
Returns the height.
Definition Heightmap.cpp:17
double textureSample(const Heightmap &map, double u, double v)
Texture sample.
double curveSample(const Heightmap &curve, double value)
Curve sample.
Result< int > publish(Heightmap &target, std::vector< float > candidate)
Publish.
bool validRaster(const Heightmap &map)
Valid raster.
Result< int > invalid(std::string message)
Invalid.
bool isRepresentable(double value)
True when representable.
Result< int > generateTerrainImageMask(Heightmap &target, const Heightmap &input, const Heightmap &red, const Heightmap &green, const Heightmap &blue, const Heightmap &alpha, const Heightmap &curve, const TerrainImageMaskSettings &s, TerrainMaskBlend mode)
Generate the reference image-mask filter from borrowed RGBA scalar planes.
Result< int > applyTerrainGlobalSpawnerMask(Heightmap &target, const Heightmap &input, const Heightmap &source, const Heightmap &curve, const TerrainImageMaskSettings &settings, TerrainMaskBlend mode)
Apply a scalar GlobalSpawnerMaskStack output through Pcg's image-mask transform, curve and blend pass...
TerrainMaskBlend
Ordered scalar-mask arithmetic; intermediate values are not clamped.
Definition TerrainStamp.h:9
Image UV transform and color-selection settings, rotation in radians.
glm::vec4 color