载入中...
搜索中...
未找到
ReflectionProbeCapture.cpp
浏览该文件的文档.
2
3#include "graphics/Canvas.h"
4#include "graphics/Graphics.h"
5#include "graphics/Mesh.h"
8
9#include <algorithm>
10#include <array>
11#include <cmath>
12
13namespace eve::graphics {
14
16
18 const auto registries = registries_;
19 for (ReflectionProbeRegistry *registry : registries)
20 if (registry) registry->remove(this);
21}
22
23void ReflectionProbeCapture::attachRegistry(ReflectionProbeRegistry *registry) {
24 if (!registry || std::find(registries_.begin(), registries_.end(), registry) != registries_.end())
25 return;
26 registries_.push_back(registry);
27}
28
29void ReflectionProbeCapture::detachRegistry(ReflectionProbeRegistry *registry) {
30 registries_.erase(std::remove(registries_.begin(), registries_.end(), registry),
31 registries_.end());
32}
33
34void ReflectionProbeCapture::configure(float x, float y, float z, int resolution, float nearZ,
35 float farZ) {
36 const int clampedResolution = std::clamp(resolution, 16, 2048);
37 const float clampedNear = std::max(nearZ, 0.001f);
38 const float clampedFar = std::max(farZ, clampedNear + 0.01f);
39 const bool changed = x != centerX_ || y != centerY_ || z != centerZ_ ||
40 clampedResolution != resolution_ || clampedNear != nearZ_ ||
41 clampedFar != farZ_;
42 centerX_ = x;
43 centerY_ = y;
44 centerZ_ = z;
45 resolution_ = clampedResolution;
46 nearZ_ = clampedNear;
47 farZ_ = clampedFar;
48 if (changed) requestCapture();
49}
50
52 nextFace_ = 0;
53 pending_ = true;
54 recaptureAfterPublish_ = false;
55 captureSkyR_ = skyR_;
56 captureSkyG_ = skyG_;
57 captureSkyB_ = skyB_;
58 captureSkyFaceTextures_ = skyFaceTextures_;
59 captureSkyFaceTextureScales_ = skyFaceTextureScales_;
60 captureSkyIntensity_ = skyIntensity_;
61 captureEnvironmentLighting_ = environmentLighting_;
62 captureEnvironmentLightingIntensity_ = environmentLightingIntensity_;
63 captureLodDistanceScale_ = lodDistanceScale_;
64 snapshotCaptureTransparent_ = captureTransparent_;
65 snapshotCaptureClusteredLighting_ = captureClusteredLighting_;
66 if (camera_) {
67 camera_->setEnvMap(captureEnvironmentLighting_);
68 camera_->setEnvIntensity(captureEnvironmentLightingIntensity_);
69 }
70}
71
72void ReflectionProbeCapture::requestCaptureAfterPublish() {
73 if (pending_ && nextFace_ == 0) {
75 return;
76 }
77 if (pending_ || publishedRevision_ != revision_) {
78 recaptureAfterPublish_ = true;
79 return;
80 }
82}
83
84void ReflectionProbeCapture::queueCapture() { requestCaptureAfterPublish(); }
85
86void ReflectionProbeCapture::ensureResources() {
87 if (!gfx_) return;
88 if (!camera_) {
89 camera_ = Camera3D::createCamera();
90 camera_->setActive(false);
91 camera_->setFov(90.f);
92 camera_->setAmbient(0.f, 0.f, 0.f);
93 camera_->setEnvMap(captureEnvironmentLighting_);
94 camera_->setEnvIntensity(captureEnvironmentLightingIntensity_);
95 camera_->setAutoExposure(false);
96 camera_->setExposure(0.f);
97 camera_->setBloom(0.f, 1.f);
98 camera_->clearEnvProbe();
99 for (int i = 0; i < Camera3D::Data::kMaxReflectionProbes; ++i)
100 camera_->clearReflectionProbe(i);
101 }
102 if (!skyQuad_) {
103 static constexpr float positions[] = {
104 -1.f, -1.f, 0.f, 1.f, -1.f, 0.f, 1.f, 1.f, 0.f, -1.f, 1.f, 0.f,
105 };
106 static constexpr float normals[] = {
107 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f,
108 };
109 static constexpr float uvs[] = {0.f, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f, 0.f};
110 static constexpr uint32_t indices[] = {0, 1, 2, 0, 2, 3};
111 skyQuad_ = gfx_->newMeshFromArrays(positions, normals, uvs, 4, indices, 6);
112 }
113 if (allocatedResolution_ == resolution_ && faces_[0]) return;
114 for (Canvas *&face : faces_) face = gfx_->newHDRCanvas(resolution_, resolution_);
115 allocatedResolution_ = resolution_;
116}
117
118void ReflectionProbeCapture::captureFace(int face) {
119 static constexpr std::array<std::array<float, 3>, 6> directions{{
120 {{1.f, 0.f, 0.f}}, {{-1.f, 0.f, 0.f}}, {{0.f, 1.f, 0.f}},
121 {{0.f, -1.f, 0.f}}, {{0.f, 0.f, 1.f}}, {{0.f, 0.f, -1.f}},
122 }};
123 static constexpr std::array<std::array<float, 3>, 6> ups{{
124 {{0.f, -1.f, 0.f}}, {{0.f, -1.f, 0.f}}, {{0.f, 0.f, 1.f}},
125 {{0.f, 0.f, -1.f}}, {{0.f, -1.f, 0.f}}, {{0.f, -1.f, 0.f}},
126 }};
127 const auto &direction = directions[static_cast<size_t>(face)];
128 const auto &up = ups[static_cast<size_t>(face)];
129 camera_->setEye(centerX_, centerY_, centerZ_);
130 camera_->setTarget(centerX_ + direction[0], centerY_ + direction[1], centerZ_ + direction[2]);
131 camera_->setUp(up[0], up[1], up[2]);
132 auto data = camera_->data();
133 data->nearZ = nearZ_;
134 data->farZ = farZ_;
135 faces_[static_cast<size_t>(face)]->clear(
136 Color(captureSkyR_[static_cast<size_t>(face)] * captureSkyIntensity_,
137 captureSkyG_[static_cast<size_t>(face)] * captureSkyIntensity_,
138 captureSkyB_[static_cast<size_t>(face)] * captureSkyIntensity_, 1.f),
139 std::nullopt, 1.0);
140 RenderSystem3D::renderToCanvas(*gfx_, faces_[static_cast<size_t>(face)], camera_, captureMask_,
141 captureLodDistanceScale_, snapshotCaptureTransparent_,
142 snapshotCaptureClusteredLighting_,
143 captureSkyFaceTextures_[static_cast<size_t>(face)], skyQuad_,
144 captureSkyFaceTextureScales_[static_cast<size_t>(face)]);
145}
146
147bool ReflectionProbeCapture::update(int faceBudget) {
148 lastCapturedFaceCount_ = 0;
149 if (!pending_ || !gfx_) return isCaptureComplete();
150 ensureResources();
151 const int budget = std::clamp(faceBudget, 1, 6);
152 float capturedGpuDurationMs = 0.f;
153 for (int captured = 0; captured < budget && nextFace_ < 6; ++captured) {
154 captureFace(nextFace_++);
155 capturedGpuDurationMs += gfx_->getLastOffscreen3DGpuDurationMs();
156 ++lastCapturedFaceCount_;
157 ++totalCapturedFaceCount_;
158 }
159 reportGpuDurationMs(capturedGpuDurationMs);
160 if (nextFace_ >= 6) {
161 pending_ = false;
162 ++revision_;
163 }
164 return isCaptureComplete();
165}
166
168 if (face < 0 || face >= 6) return nullptr;
169 return faces_[static_cast<size_t>(face)];
170}
171
173 if (!gfx_ || !isCaptureComplete()) return false;
174 if (stagedRevision_ == revision_ && stagingCubemap_) return true;
175 if (!stagingCubemap_ || stagingResolution_ != resolution_) {
176 stagingCubemap_ = gfx_->newHDRCubemap(resolution_);
177 stagingResolution_ = stagingCubemap_ ? resolution_ : 0;
178 }
179 if (!stagingCubemap_) return false;
180 if (!gfx_->copyHDRCanvasesToCubemap(faces_.data(), static_cast<int>(faces_.size()),
181 stagingCubemap_))
182 return false;
184 stagedRevision_ = revision_;
185 return true;
186}
187
189 if (!gfx_ || !stagingCubemap_ || stagedRevision_ != revision_) return false;
190 if (!gfx_->filterHDRReflectionCubemap(stagingCubemap_, sampleCount)) return false;
192 lastFilterSampleCount_ = std::clamp(sampleCount, 8, 512);
193 Texture *previousActive = activeCubemap_;
194 const int previousResolution = activeResolution_;
195 activeCubemap_ = stagingCubemap_;
196 activeResolution_ = resolution_;
197 publishedRevision_ = stagedRevision_;
198 stagingCubemap_ = previousResolution == resolution_ ? previousActive : nullptr;
199 stagingResolution_ = stagingCubemap_ ? resolution_ : 0;
200 framesSincePublish_ = 0;
201 return true;
202}
203
204void ReflectionProbeCapture::setUpdateMode(const std::string &mode) {
205 if (mode == "static")
206 updateMode_ = UpdateMode::Static;
207 else if (mode == "realtime")
208 updateMode_ = UpdateMode::Realtime;
209 else if (mode == "time_sliced" || mode == "timesliced")
210 updateMode_ = UpdateMode::TimeSliced;
211 else
212 updateMode_ = UpdateMode::OnDemand;
213}
214
216 switch (updateMode_) {
217 case UpdateMode::Static: return "static";
218 case UpdateMode::Realtime: return "realtime";
219 case UpdateMode::TimeSliced: return "time_sliced";
220 case UpdateMode::OnDemand: return "on_demand";
221 }
222 return "on_demand";
223}
224
226 refreshInterval_ = std::clamp(frames, 1, 36000);
227}
228
230 const uint32_t nextMask = static_cast<uint32_t>(mask);
231 if (nextMask == captureMask_) return;
232 captureMask_ = nextMask;
234}
235
236void ReflectionProbeCapture::setEnvironmentLighting(Texture *environment, float intensity) {
237 const float nextIntensity = std::max(intensity, 0.f);
238 if (environment == environmentLighting_ && nextIntensity == environmentLightingIntensity_)
239 return;
240 environmentLighting_ = environment;
241 environmentLightingIntensity_ = nextIntensity;
242 requestCaptureAfterPublish();
243}
244
245void ReflectionProbeCapture::setSkyColor(float r, float g, float b, float intensity) {
246 const float nextR = std::max(r, 0.f);
247 const float nextG = std::max(g, 0.f);
248 const float nextB = std::max(b, 0.f);
249 const float nextIntensity = std::max(intensity, 0.f);
250 bool changed = nextIntensity != skyIntensity_;
251 for (size_t face = 0; face < 6; ++face) {
252 changed = changed || skyR_[face] != nextR || skyG_[face] != nextG ||
253 skyB_[face] != nextB;
254 skyR_[face] = nextR;
255 skyG_[face] = nextG;
256 skyB_[face] = nextB;
257 }
258 skyIntensity_ = nextIntensity;
259 if (changed) requestCaptureAfterPublish();
260}
261
262void ReflectionProbeCapture::setSkyFaceColor(int face, float r, float g, float b) {
263 if (face < 0 || face >= 6) return;
264 const size_t index = static_cast<size_t>(face);
265 const float nextR = std::max(r, 0.f);
266 const float nextG = std::max(g, 0.f);
267 const float nextB = std::max(b, 0.f);
268 if (skyR_[index] == nextR && skyG_[index] == nextG && skyB_[index] == nextB) return;
269 skyR_[index] = nextR;
270 skyG_[index] = nextG;
271 skyB_[index] = nextB;
272 requestCaptureAfterPublish();
273}
274
276 if (face < 0 || face >= 6) return;
277 const size_t index = static_cast<size_t>(face);
278 if (skyFaceTextures_[index] == texture) return;
279 skyFaceTextures_[index] = texture;
280 requestCaptureAfterPublish();
281}
282
284 if (face < 0 || face >= 6) return nullptr;
285 return skyFaceTextures_[static_cast<size_t>(face)];
286}
287
289 if (face < 0 || face >= 6) return;
290 const size_t index = static_cast<size_t>(face);
291 const float nextScale = std::clamp(scale, 0.f, 64.f);
292 if (skyFaceTextureScales_[index] == nextScale) return;
293 skyFaceTextureScales_[index] = nextScale;
294 requestCaptureAfterPublish();
295}
296
298 if (face < 0 || face >= 6) return 1.f;
299 return skyFaceTextureScales_[static_cast<size_t>(face)];
300}
301
302float ReflectionProbeCapture::getSkyFaceColor(int face, int component) const {
303 if (face < 0 || face >= 6 || component < 0 || component >= 3) return 0.f;
304 const size_t index = static_cast<size_t>(face);
305 if (component == 0) return skyR_[index];
306 if (component == 1) return skyG_[index];
307 return skyB_[index];
308}
309
311 const float nextScale = std::clamp(scale, 0.25f, 4.f);
312 if (nextScale == lodDistanceScale_) return;
313 lodDistanceScale_ = nextScale;
314 requestCaptureAfterPublish();
315}
316
318 if (enabled == captureTransparent_) return;
319 captureTransparent_ = enabled;
320 requestCaptureAfterPublish();
321}
322
324 if (enabled == captureClusteredLighting_) return;
325 captureClusteredLighting_ = enabled;
326 requestCaptureAfterPublish();
327}
328
330 gpuBudgetMs_ = std::clamp(milliseconds, 0.1f, 16.f);
331 underBudgetReports_ = 0;
332}
333
335 if (milliseconds <= 0.f || !std::isfinite(milliseconds)) return;
336 smoothedGpuDurationMs_ = smoothedGpuDurationMs_ > 0.f
337 ? smoothedGpuDurationMs_ * 0.8f + milliseconds * 0.2f
338 : milliseconds;
339
340 if (smoothedGpuDurationMs_ > gpuBudgetMs_ * 1.1f) {
341 underBudgetReports_ = 0;
342 if (adaptiveFaceBudget_ > 1)
343 --adaptiveFaceBudget_;
344 else
345 adaptiveFilterSamples_ = std::max(adaptiveFilterSamples_ / 2, 8);
346 return;
347 }
348
349 if (smoothedGpuDurationMs_ < gpuBudgetMs_ * 0.7f) {
350 if (++underBudgetReports_ < 4) return;
351 underBudgetReports_ = 0;
352 if (adaptiveFilterSamples_ < 64)
353 adaptiveFilterSamples_ = std::min(adaptiveFilterSamples_ * 2, 64);
354 else
355 adaptiveFaceBudget_ = std::min(adaptiveFaceBudget_ + 1, 6);
356 } else {
357 underBudgetReports_ = 0;
358 }
359}
360
362 return tick(adaptiveFaceBudget_, adaptiveFilterSamples_);
363}
364
365void ReflectionProbeCapture::advanceRefreshPolicy() {
366 ++framesSincePublish_;
367 if (!pending_) {
368 if (recaptureAfterPublish_ && publishedRevision_ == revision_)
370 else if (updateMode_ == UpdateMode::Realtime ||
371 (updateMode_ == UpdateMode::TimeSliced && framesSincePublish_ >= refreshInterval_))
373 else if (updateMode_ == UpdateMode::Static && revision_ == 0)
375 }
376}
377
378bool ReflectionProbeCapture::tick(int faceBudget, int filterSamples) {
380 advanceRefreshPolicy();
381 if (pending_ && !update(faceBudget)) return false;
382 if (publishedRevision_ == revision_) return false;
383 if (!stageCapturedFaces()) return false;
384 return filterAndPublish(filterSamples);
385}
386
387void ReflectionProbeCapture::configureInfluence(float extentX, float extentY, float extentZ,
388 float intensity, float blendDistance,
389 int priority) {
390 influenceExtentX_ = std::max(extentX, 0.001f);
391 influenceExtentY_ = std::max(extentY, 0.001f);
392 influenceExtentZ_ = std::max(extentZ, 0.001f);
393 influenceIntensity_ = std::max(intensity, 0.f);
394 influenceBlendDistance_ = std::max(blendDistance, 0.f);
395 influencePriority_ = priority;
396}
397
399 if (!camera || !activeCubemap_ || publishedRevision_ == 0) return false;
400 camera->setReflectionProbe(slot, activeCubemap_, centerX_, centerY_, centerZ_,
401 influenceExtentX_, influenceExtentY_, influenceExtentZ_,
402 influenceIntensity_, influenceBlendDistance_, influencePriority_);
403 return true;
404}
405
406bool ReflectionProbeCapture::applyToCamera(Camera3D *camera, int slot, float extentX,
407 float extentY, float extentZ, float intensity,
408 float blendDistance, int priority) {
409 configureInfluence(extentX, extentY, extentZ, intensity, blendDistance, priority);
410 return applyConfiguredToCamera(camera, slot);
411}
412
413} // namespace eve::graphics
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
int mask
int priority
tensor::Graph g
Definition GpuGraph.cpp:7
float camera[2]
double r
std::vector< std::uint32_t > indices
std::vector< float > normals
std::vector< float > positions
HexVec3 up
std::array< float, 3 > scale
MeleePoint3 b
Definition MeleeHit.cpp:41
double & milliseconds
Definition OnnxGpgpu.cpp:19
size_t directions
Definition OnnxLstm.cpp:29
RoadLaneDirection direction
SimulationTick tick
uint32_t index
EVENGINE_API_BACKENDS public API.
void setBloom(float intensity, float threshold=1.f)
Configure HDR bloom. Zero intensity disables it.
void setUp(float x, float y, float z)
void clearEnvProbe()
Disable box projection and return to an infinite-distance environment.
void clearReflectionProbe(int slot)
Disable one local reflection probe slot.
void setFov(float fovYDeg)
void setExposure(float ev)
Set exposure compensation in photographic stops. Positive values brighten.
void setEnvIntensity(float intensity)
static Camera3D * createCamera()
void setAutoExposure(bool enabled, float minEV=-8.f, float maxEV=8.f)
Enable log-average automatic exposure and set its EV clamp range.
void setTarget(float x, float y, float z)
void setAmbient(float r, float g, float b)
void setActive(bool active)
void setEye(float x, float y, float z)
void setEnvMap(Texture *cube)
Specular IBL cubemap (Graphics::newCubemap). nullptr disables IBL.
Canvas public API.
Definition Canvas.h:17
virtual bool copyHDRCanvasesToCubemap(Canvas *const *sources, int faceCount, Texture *cubemap)
Copy consecutive RGBA16F canvases into cubemap base-level faces.
Definition Graphics.h:590
virtual bool filterHDRReflectionCubemap(Texture *cubemap, int sampleCount=64)
Generate GGX specular mips and final diffuse irradiance for an HDR cubemap. @compatibility Preserves ...
Definition Graphics.h:601
virtual float getLastOffscreen3DGpuDurationMs() const
Return the GPU timestamp duration of the most recently completed offscreen 3D pass,...
Definition Graphics.h:1030
virtual Mesh * newMeshFromArrays(const float *posXYZ, const float *nrmXYZ, const float *uvST, int vertexCount, const uint32_t *indices, int indexCount)=0
Upload a triangle mesh from packed CPU arrays. Owned by Graphics. posXYZ required (vertexCount*3)....
virtual Texture * newHDRCubemap(int faceSize)
Allocate a linear RGBA16F six-layer staging cubemap for runtime capture.
Definition Graphics.h:562
void requestCapture()
Mark all six faces dirty and restart capture at +X.
void setGpuBudgetMs(float milliseconds)
Set the GPU-time budget used by adaptive capture scheduling, in milliseconds.
~ReflectionProbeCapture()
Detach this probe from every registry before script-owned destruction.
bool applyConfiguredToCamera(Camera3D *camera, int slot)
Submit the persistent influence and active cubemap to a Camera3D slot. @compatibility Preserves the s...
std::string getUpdateMode() const
Return the current refresh mode.
bool tickAdaptive()
Advance capture and filtering using the GPU-budget controller's workload.
void setEnvironmentLighting(Texture *environment, float intensity=1.f)
Set non-recursive global environment lighting for captured geometry.
bool tick(int faceBudget=1, int filterSamples=64)
Advance capture, staging, filtering and publishing under the selected policy.
Canvas * getFaceCanvas(int face) const
Return one captured HDR face Canvas in +X,-X,+Y,-Y,+Z,-Z order. @lifetime Returned canvas is borrowed...
void setRefreshInterval(int frames)
Set automatic refresh interval in frames for time_sliced mode.
void setCaptureClusteredLighting(bool enabled)
Enable clustered lighting for captures that exceed the legacy light pack.
bool isCaptureComplete() const
True after at least one complete six-face capture.
void setSkyFaceTextureScale(int face, float scale)
Set the linear HDR radiance multiplier for one sky face texture.
ReflectionProbeCapture(Graphics *gfx)
Reflection probe capture.
void setSkyFaceTexture(int face, Texture *texture)
Set a directional per-pixel sky texture for one capture face.
void configureInfluence(float extentX, float extentY, float extentZ, float intensity=1.f, float blendDistance=1.f, int priority=0)
Configure the persistent box influence used for lighting and editor display.
void reportGpuDurationMs(float milliseconds)
Report a backend timestamp duration for the most recent probe workload.
bool update(int faceBudget=1)
Capture up to faceBudget dirty faces.
void queueCapture()
Queue a coherent recapture without restarting a revision already in progress.
float getSkyFaceTextureScale(int face) const
Return one sky face texture's linear HDR radiance multiplier.
void setSkyFaceColor(int face, float r, float g, float b)
Override one directional backup sky face in +X,-X,+Y,-Y,+Z,-Z order.
void setUpdateMode(const std::string &mode)
Set refresh mode: static, on_demand, time_sliced, or realtime.
bool applyToCamera(Camera3D *camera, int slot, float extentX, float extentY, float extentZ, float intensity=1.f, float blendDistance=1.f, int priority=0)
Assign the active cubemap to a Camera3D local reflection-probe slot.
void setCaptureMask(int mask)
Set the object-layer mask visible to this reflection capture.
Texture * getSkyFaceTexture(int face) const
Return one directional per-pixel sky texture, or nullptr. @lifetime Returned texture is borrowed; its...
void setCaptureLodDistanceScale(float scale)
Set capture LOD distance scale; below one retains higher-detail LODs farther away.
void configure(float x, float y, float z, int resolution=128, float nearZ=0.1f, float farZ=100.f)
Configure the probe origin, face resolution and clipping planes.
bool stageCapturedFaces()
Copy a complete capture revision into a backend HDR staging cubemap. @compatibility Preserves the scr...
void setSkyColor(float r, float g, float b, float intensity=1.f)
Set a linear HDR backup sky color for empty capture pixels.
bool filterAndPublish(int sampleCount=64)
Filter with 8-512 samples and atomically publish the active cubemap. @compatibility Preserves the scr...
float getSkyFaceColor(int face, int component) const
Return one directional sky-face color component, or zero for invalid indices.
void setCaptureTransparent(bool enabled)
Enable or disable transparent/hair surfaces in probe captures.
Scene-level stable selection of published reflection probes for a camera.
static void renderToCanvas(Graphics &gfx, Canvas *target, Camera3D *camera, uint32_t reflectionCaptureMask=0xffffffffu, float lodDistanceScale=1.f, bool includeTransparent=true, bool useClusteredLighting=true, Texture *skyFaceTexture=nullptr, Mesh *skyQuad=nullptr, float skyFaceTextureScale=1.f)
Forward 3D pass into an offscreen canvas using multipart materials, LOD, masked surfaces and sorted t...
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13
bool enabled
static constexpr int kMaxReflectionProbes