载入中...
搜索中...
未找到
SkyProceduralAsset.cpp
浏览该文件的文档.
1#include <algorithm>
2#include <cmath>
3#include <exception>
4#include <numbers>
6
7namespace eve::graphics {
8namespace {
9uint32_t hash(uint32_t x) {
10 x ^= x >> 16;
11 x *= 0x7feb352dU;
12 x ^= x >> 15;
13 x *= 0x846ca68bU;
14 return x ^ (x >> 16);
15}
16float random(uint32_t x) { return float(hash(x) >> 8) / 16777216.f; }
17float noise(float x, float y, uint32_t period, uint32_t seed) {
18 auto ix = static_cast<uint32_t>(std::floor(x)), iy = static_cast<uint32_t>(std::floor(y));
19 float u = x - std::floor(x), v = y - std::floor(y);
20 u = u * u * (3 - 2 * u);
21 v = v * v * (3 - 2 * v);
22 const auto sample = [&](uint32_t a, uint32_t b) {
23 return random(seed ^ hash(a % period) ^ hash((b % period) + 7351));
24 };
25 return std::lerp(std::lerp(sample(ix, iy), sample(ix + 1, iy), u),
26 std::lerp(sample(ix, iy + 1), sample(ix + 1, iy + 1), u), v);
27}
28float fractal(float u, float v, uint32_t seed) {
29 float value = 0, weight = .5f;
30 for (uint32_t frequency = 4; frequency <= 64; frequency *= 2) {
31 value += weight * noise(u * float(frequency), v * float(frequency), frequency, seed);
32 weight *= .5f;
33 }
34 return value;
35}
36std::byte channel(float x) { return std::byte(static_cast<unsigned char>(std::clamp(x, 0.f, 1.f) * 255.f + .5f)); }
37void mips(std::vector<std::byte>& pixels, ShaderImageInput& image, uint32_t size, bool repeat) {
38 image.width = image.height = size;
40 size_t offset = 0;
41 image.mipLevels = 1;
42 for (uint32_t previous = size; previous > 1; previous /= 2) {
43 const uint32_t next = previous / 2;
44 const size_t nextOffset = pixels.size();
45 pixels.resize(nextOffset + size_t(next) * next * 4);
46 for (uint32_t y = 0; y < next; ++y)
47 for (uint32_t x = 0; x < next; ++x)
48 for (size_t c = 0; c < 4; ++c) {
49 unsigned sum = 0;
50 for (uint32_t dy = 0; dy < 2; ++dy)
51 for (uint32_t dx = 0; dx < 2; ++dx)
52 sum += std::to_integer<unsigned>(
53 pixels[offset + ((size_t(y * 2 + dy) * previous) + x * 2 + dx) * 4 + c]);
54 pixels[nextOffset + (size_t(y) * next + x) * 4 + c] = std::byte((sum + 2) / 4);
55 }
56 offset = nextOffset;
57 ++image.mipLevels;
58 }
59 image.bytes = pixels;
61 image.sampler.repeatU = image.sampler.repeatV = repeat;
62}
63} // namespace
65 try {
66 auto data = std::make_shared<Impl>();
67 auto& w = data->layer;
68 constexpr float pi = std::numbers::pi_v<float>;
69 constexpr uint32_t longitude = 96, latitude = 48, cloudSize = 512, starSize = 1024, moonSize = 256;
70 const auto vertex = [&](uint32_t x, uint32_t y) {
71 const float u = float(x) / float(longitude), v = float(y) / float(latitude);
72 const float elevation = (v - .5f) * pi, azimuth = u * 2 * pi;
73 const float z = std::sin(elevation);
74 const std::array<float, 9> p{100 * std::cos(elevation) * std::cos(azimuth),
75 100 * std::cos(elevation) * std::sin(azimuth),
76 100 * z,
77 u,
78 v,
79 std::max(0.f, z),
80 0,
81 0,
82 1};
83 data->corners.insert(data->corners.end(), p.begin(), p.end());
84 };
85 for (uint32_t y = 0; y < latitude; ++y)
86 for (uint32_t x = 0; x < longitude; ++x) {
87 vertex(x, y);
88 vertex(x + 1, y);
89 vertex(x + 1, y + 1);
90 vertex(x, y);
91 vertex(x + 1, y + 1);
92 vertex(x, y + 1);
93 }
94 data->pixels.resize(cloudSize * cloudSize);
95 for (uint32_t y = 0; y < cloudSize; ++y)
96 for (uint32_t x = 0; x < cloudSize; ++x) {
97 const float u = float(x) / float(cloudSize), v = float(y) / float(cloudSize);
98 const float n = fractal(u * 2, v, seed ^ 0x434c4f55U);
99 data->pixels[size_t(y) * cloudSize + x] = channel(std::max(0.f, n - .36f) * 2.4f);
100 }
101 auto& density = data->texture;
102 density.width = density.height = cloudSize;
103 density.format = ShaderImageFormat::R8;
104 density.bytes = data->pixels;
105 density.sampler = TextureSampler::linear();
106 density.sampler.repeatU = density.sampler.repeatV = true;
107 for (size_t i = 0; i < 4; ++i) {
108 const uint32_t size = i == 0 ? starSize : (i == 1 ? 64 : moonSize);
109 auto& pixels = data->celestialPixels[i];
110 pixels.resize(size_t(size) * size * 4);
111 for (uint32_t y = 0; y < size; ++y)
112 for (uint32_t x = 0; x < size; ++x) {
113 const size_t at = (size_t(y) * size + x) * 4;
114 float r = 0, g = 0, b = 0, a = 1;
115 if (i == 0) {
116 const float sample = random(seed ^ 0x53544152U ^ hash(y * size + x));
117 r = g = b = sample > .9985f ? .35f + .65f * random(y * size + x) : 0;
118 } else if (i == 1) {
119 r = g = b = random(seed ^ 0x4e4f4953U ^ hash(y * size + x));
120 } else {
121 const float u = (float(x) + .5f) / float(size), v = (float(y) + .5f) / float(size);
122 const float nx = 2 * u - 1, nz = 2 * v - 1, rr = nx * nx + nz * nz;
123 const float depth = std::sqrt(std::max(0.f, 1 - rr));
124 a = rr <= 1 ? 1.f : 0.f;
125 if (i == 2) {
126 // Independently generated maria and crater mottling, not an astronomical map.
127 const float terrain = fractal(u, v, seed ^ 0x4d4f4f4eU);
128 const float fine = noise(u * 64, v * 64, 64, seed ^ 0x43524154U);
129 r = g = b = std::clamp(.28f + terrain * .65f + (fine - .5f) * .12f, .15f, .9f);
130 } else {
131 r = (nx + 1) * .5f;
132 g = (nz + 1) * .5f;
133 b = (1 - depth) * .5f;
134 }
135 }
136 pixels[at] = channel(r);
137 pixels[at + 1] = channel(g);
138 pixels[at + 2] = channel(b);
139 pixels[at + 3] = channel(a);
140 }
141 mips(pixels, data->celestialImages[i], size, i < 2);
142 }
143 w.corners = data->corners;
144 w.densityTexture = &density;
145 w.starsTexture = &data->celestialImages[0];
146 w.starsNoiseTexture = &data->celestialImages[1];
147 w.moonColorTexture = &data->celestialImages[2];
148 w.moonNormalTexture = &data->celestialImages[3];
149 w.daylightEnabled = w.opticalCycleEnabled = w.authoredSkyLighting = true;
150 w.materialContrast = {.1f, .85f, .375f};
151 w.sunDiskColor = {1068, 934, 681};
152 w.daylight.moonDiskColor[3] = 1;
153 for (size_t i = 0; i < w.daylight.scatteringCurve.size(); ++i) {
154 const float t = float(i) / float(w.daylight.scatteringCurve.size() - 1);
155 const float value = t * t * (3 - 2 * t);
156 w.daylight.scatteringCurve[i] = {80 + 100 * t, value, value, value};
157 }
158 auto valid = w.daylight.validate();
159 if (!valid) return Result<SkyWispsAsset>::failure(valid.status());
160 return Result<SkyWispsAsset>::success(SkyWispsAsset(std::move(data)));
161 } catch (const std::exception& e) {
162 return Result<SkyWispsAsset>::failure(Diagnostic::error(DiagnosticCode::Failed, e.what(), "sky.procedural-v1"));
163 }
164}
165} // namespace eve::graphics
double value
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::string terrain
float nx
float nz
glm::vec4 p[6]
std::array< std::uint8_t, 32 > hash
Definition Evpack.cpp:172
tensor::Graph g
Definition GpuGraph.cpp:7
vk::UniqueImage image
float u
Definition Grass.cpp:233
glm::vec3 n
Definition Grass.cpp:63
double r
float v
std::int32_t c
float elevation
size_t offset
bool valid
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
graphics::Canvas * previous
std::uint32_t seed
Definition PointSet.cpp:807
float t
uint8_t * pixels
bool mips
float dy
float dx
Battle::Random random
float size
Definition TreeMesh.cpp:156
std::uint32_t depth
std::size_t at
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Immutable owned sky mesh and textures, loaded from a pack or generated procedurally.
static Result< SkyWispsAsset > generate(uint32_t seed)
Generate a complete independent sky using a named procedural-v1 seed.
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
constexpr HexDirection next(HexDirection d) noexcept
The next direction clockwise (NW wraps to NE).
Definition HexMetrics.h:76
double sample(const Heightmap &map, double u, double v)
Sample.
static TextureSampler linear()
Linear.
static TextureSampler linearMipmap()
Trilinear (linear + linear mips). Caller should create the texture with generateMipmaps.