载入中...
搜索中...
未找到
RenderSystem.cpp
浏览该文件的文档.
2#include "graphics/Graphics.h"
3#include "graphics/Canvas.h"
4#include "graphics/Light.h"
5#include "graphics/Quad.h"
6#include "common/Exception.h"
8#include "zeroerr/assert.h"
9
10#include <algorithm>
11#include <cmath>
12#include <cstdint>
13#include <unordered_map>
14#include <vector>
15
16namespace eve::graphics {
17
18void Renderable2D::release() { ecs::DestroyEntity(this); }
19
20void Renderable2D::setPosition(float x, float y) {
21 transform()->x = x;
22 transform()->y = y;
23}
24float Renderable2D::getX() { return transform()->x; }
25float Renderable2D::getY() { return transform()->y; }
26void Renderable2D::setRotation(float degrees) { transform()->rot = degrees; }
27float Renderable2D::getRotation() { return transform()->rot; }
28void Renderable2D::setScale(float sx, float sy) {
29 transform()->sx = sx;
30 transform()->sy = sy;
31}
32float Renderable2D::getScaleX() { return transform()->sx; }
33float Renderable2D::getScaleY() { return transform()->sy; }
35 if (width < 0.f || height < 0.f)
36 throw Exception("Sprite2D.setSize: width/height must be >= 0");
37 sprite()->width = width;
38 sprite()->height = height;
39}
40float Renderable2D::getWidth() { return sprite()->width; }
41float Renderable2D::getHeight() { return sprite()->height; }
42void Renderable2D::setTexture(Texture *texture) { sprite()->texture = texture; }
43Texture *Renderable2D::getTexture() { return sprite()->texture; }
44void Renderable2D::setNormalTexture(Texture *texture) { sprite()->normalTexture = texture; }
45Texture *Renderable2D::getNormalTexture() { return sprite()->normalTexture; }
46void Renderable2D::setQuad(Quad *quad) { sprite()->quad = quad; }
47Quad *Renderable2D::getQuad() { return sprite()->quad; }
48void Renderable2D::setColor(float r, float g, float b, float a) {
49 sprite()->r = r;
50 sprite()->g = g;
51 sprite()->b = b;
52 sprite()->a = a;
53}
54void Renderable2D::setLayer(int layer) { sprite()->layer = layer; }
55int Renderable2D::getLayer() { return sprite()->layer; }
56void Renderable2D::setVisible(bool visible) { sprite()->visible = visible; }
57bool Renderable2D::getVisible() { return sprite()->visible; }
58void Renderable2D::setReceiveLight(bool receive) { sprite()->receiveLight = receive; }
59bool Renderable2D::getReceiveLight() { return sprite()->receiveLight; }
60void Renderable2D::setBlend(const std::string &blend) {
61 if (blend == "alpha") sprite()->blend = BlendMode::Alpha;
62 else if (blend == "additive" || blend == "add") sprite()->blend = BlendMode::Additive;
63 else if (blend == "opaque") sprite()->blend = BlendMode::Opaque;
64 else if (blend == "premultiplied" || blend == "premultiplied_alpha")
65 sprite()->blend = BlendMode::Premultiplied;
66 else if (blend == "multiply") sprite()->blend = BlendMode::Multiply;
67 else throw Exception(
68 "Sprite2D.setBlend: expected alpha|additive|opaque|premultiplied|multiply");
69}
71 switch (sprite()->blend) {
72 case BlendMode::Additive: return "additive";
73 case BlendMode::Opaque: return "opaque";
74 case BlendMode::Premultiplied: return "premultiplied";
75 case BlendMode::Multiply: return "multiply";
76 default: return "alpha";
77 }
78}
79void Renderable2D::setAnchor(float x, float y) {
80 sprite()->anchorX = x;
81 sprite()->anchorY = y;
82}
83float Renderable2D::getAnchorX() { return sprite()->anchorX; }
84float Renderable2D::getAnchorY() { return sprite()->anchorY; }
85void Renderable2D::setFlip(bool horizontal, bool vertical) {
86 sprite()->flipX = horizontal;
87 sprite()->flipY = vertical;
88}
89bool Renderable2D::getFlipX() { return sprite()->flipX; }
90bool Renderable2D::getFlipY() { return sprite()->flipY; }
91void Renderable2D::setFrameLayout(int sourceW, int sourceH, int trimW, int trimH, int offsetX, int offsetY) {
92 setSize(float(sourceW), float(sourceH));
93 sprite()->trimW = trimW;
94 sprite()->trimH = trimH;
95 sprite()->offsetX = offsetX;
96 sprite()->offsetY = offsetY;
97}
98
99void Camera2D::setAmbient(float r, float g, float b) {
100 auto d = data();
101 d->ambientR = r;
102 d->ambientG = g;
103 d->ambientB = b;
104}
105
106void Camera2D::setPosition(float x, float y) {
107 auto d = data();
108 d->x = x;
109 d->y = y;
110}
111
112float Camera2D::getX() { return data()->x; }
113float Camera2D::getY() { return data()->y; }
114
115void Camera2D::setZoom(float zoom) { data()->zoom = zoom; }
116float Camera2D::getZoom() { return data()->zoom; }
117
118float Camera2D::screenToWorldX(float screenX, float /*screenY*/, float viewW, float /*viewH*/) {
119 auto d = data();
120 float z = d->zoom <= 0.f ? 1e-4f : d->zoom;
121 return (screenX - viewW * 0.5f) / z + d->x;
122}
123
124float Camera2D::screenToWorldY(float /*screenX*/, float screenY, float /*viewW*/, float viewH) {
125 auto d = data();
126 float z = d->zoom <= 0.f ? 1e-4f : d->zoom;
127 return (screenY - viewH * 0.5f) / z + d->y;
128}
129
130float Camera2D::worldToScreenX(float worldX, float /*worldY*/, float viewW, float /*viewH*/) {
131 auto d = data();
132 float z = d->zoom <= 0.f ? 1e-4f : d->zoom;
133 return (worldX - d->x) * z + viewW * 0.5f;
134}
135
136float Camera2D::worldToScreenY(float /*worldX*/, float worldY, float /*viewW*/, float viewH) {
137 auto d = data();
138 float z = d->zoom <= 0.f ? 1e-4f : d->zoom;
139 return (worldY - d->y) * z + viewH * 0.5f;
140}
141
142void Renderable2D::setCastOcclusion(bool cast) { sprite()->castOcclusion = cast; }
143
144bool Renderable2D::getCastOcclusion() { return sprite()->castOcclusion; }
145
146namespace {
147
148float clampZoom(float z) { return z <= 0.f ? 1e-4f : z; }
149
150struct ViewCam {
151 float x = 0.f;
152 float y = 0.f;
153 float zoom = 1.f;
154 bool valid = false;
155 Color clearColor{0.1f, 0.1f, 0.12f, 1.f};
156 float ambientR = 0.15f, ambientG = 0.15f, ambientB = 0.18f;
157};
158
159ViewCam fromEntity(Camera2D *ent) {
160 ViewCam v;
161 if (!ent) return v;
162 auto d = ent->data();
163 v.valid = true;
164 v.x = d->x;
165 v.y = d->y;
166 v.zoom = d->zoom;
167 v.clearColor = Color(d->r, d->g, d->b, d->a);
168 v.ambientR = d->ambientR;
169 v.ambientG = d->ambientG;
170 v.ambientB = d->ambientB;
171 return v;
172}
173
174void applyCamera(float wx, float wy, float ww, float wh, const ViewCam &cam, int viewW, int viewH,
175 float &sx, float &sy, float &sw, float &sh) {
176 if (!cam.valid) {
177 sx = wx;
178 sy = wy;
179 sw = ww;
180 sh = wh;
181 return;
182 }
183 ASSERT_GT(viewW, 0);
184 ASSERT_GT(viewH, 0);
185 const float z = clampZoom(cam.zoom);
186 ASSERT_GT(z, 0.f);
187 sx = (wx - cam.x) * z + float(viewW) * 0.5f;
188 sy = (wy - cam.y) * z + float(viewH) * 0.5f;
189 sw = ww * z;
190 sh = wh * z;
191}
192
193struct PackedLight {
194 Light2D::Data *data = nullptr;
195 bool isPoint = true;
196};
197
198void collectLights(Canvas *canvasKey, std::vector<PackedLight> &out) {
199 out.clear();
200 if (ecs::current()->getManager<Light2D>() == nullptr) return;
201 auto view = ecs::View<Light2D, Light2D::Data>();
202 for (auto it = view.begin(); it != view.end(); ++it) {
203 auto [d] = *it;
204 if (!d->enabled) continue;
205 if (d->volumetricOnly) continue; // emissive proxies skip surface lighting
206 if (d->canvas != canvasKey) continue;
207 PackedLight pl;
208 pl.data = d;
209 pl.isPoint = (d->type != "dir");
210 out.push_back(pl);
211 }
212 std::stable_sort(out.begin(), out.end(), [](const PackedLight &a, const PackedLight &b) {
213 if (a.isPoint != b.isPoint) return a.isPoint && !b.isPoint;
214 return a.data->intensity > b.data->intensity;
215 });
216 if (out.size() > size_t(Lighting2DUBO::kMaxLights))
217 out.resize(size_t(Lighting2DUBO::kMaxLights));
218}
219
220Lighting2DUBO packLights(const std::vector<PackedLight> &lights, const ViewCam &cam, int viewW,
221 int viewH) {
222 Lighting2DUBO ubo{};
223 ubo.ambient = glm::vec4(cam.ambientR, cam.ambientG, cam.ambientB, 0.f);
224 ubo.meta = glm::vec4(float(lights.size()), float(viewW), float(viewH), 0.f);
225 for (size_t i = 0; i < lights.size(); ++i) {
226 const auto *d = lights[i].data;
227 Light2DGpu &g = ubo.lights[i];
228 g.color = glm::vec4(d->r * d->intensity, d->g * d->intensity, d->b * d->intensity, 1.f);
229 g.spot = glm::vec4(0.f, 0.f, -2.f, -2.f);
230 if (lights[i].isPoint) {
231 float lx = d->x, ly = d->y;
232 float lr = d->radius;
233 if (cam.valid) {
234 const float z = clampZoom(cam.zoom);
235 lx = (d->x - cam.x) * z + float(viewW) * 0.5f;
236 ly = (d->y - cam.y) * z + float(viewH) * 0.5f;
237 lr = d->radius * z;
238 }
239 // Spot keeps cone metadata even at radius 0 so shaders/CPU can reject the
240 // directional branch (w<=0 alone is the dir discriminator for point/dir).
241 if (d->type == "spot") {
242 float dx = d->dx, dy = d->dy;
243 const float len = std::sqrt(dx * dx + dy * dy);
244 if (len > 1e-6f) {
245 dx /= len;
246 dy /= len;
247 } else {
248 dx = 0.f;
249 dy = -1.f;
250 }
251 float cosOuter = 0.f, cosInner = 0.f;
252 light2dSpotCosines(d->spotAngleDeg, d->spotSoftness, cosOuter, cosInner);
253 g.spot = glm::vec4(dx, dy, cosOuter, cosInner);
254 }
255 g.posRadius = glm::vec4(lx, ly, 0.f, lr);
256 } else {
257 float dx = d->dx, dy = d->dy;
258 const float len = std::sqrt(dx * dx + dy * dy);
259 if (len > 1e-6f) {
260 dx /= len;
261 dy /= len;
262 } else {
263 dx = 0.f;
264 dy = -1.f;
265 }
266 g.posRadius = glm::vec4(dx, dy, 0.f, 0.f);
267 }
268 }
269 return ubo;
270}
271
272Color modulateUnlit(Color base, float cx, float cy, bool receiveLight, const Lighting2DUBO &ubo) {
273 if (!receiveLight) return base;
274 glm::vec3 lit(ubo.ambient.r, ubo.ambient.g, ubo.ambient.b);
275 const int count = int(ubo.meta.x + 0.5f);
276 for (int i = 0; i < count; ++i) {
277 const auto &L = ubo.lights[i];
278 glm::vec3 col(L.color.r, L.color.g, L.color.b);
279 if (L.posRadius.w <= 0.f) {
280 // Zero-range spots contribute nothing; do not treat position as a dir vector.
281 if (L.spot.z <= -1.5f) {
282 // Directional: approximate as constant contribution for unlit sprites.
283 lit += col * 0.65f;
284 }
285 } else {
286 const float dx = L.posRadius.x - cx;
287 const float dy = L.posRadius.y - cy;
288 const float dist = std::sqrt(dx * dx + dy * dy);
289 float atten = 1.f - dist / std::max(L.posRadius.w, 1.f);
290 if (atten < 0.f) atten = 0.f;
291 atten *= atten;
292 if (L.spot.z > -1.5f) {
293 const float fx = cx - L.posRadius.x;
294 const float fy = cy - L.posRadius.y;
295 const float fl = std::sqrt(fx * fx + fy * fy);
296 float spotAtten = 1.f;
297 if (fl > 1e-4f) {
298 const float beamLen =
299 std::sqrt(L.spot.x * L.spot.x + L.spot.y * L.spot.y);
300 if (beamLen > 1e-6f) {
301 const float cosTheta = (fx * L.spot.x + fy * L.spot.y) / (fl * beamLen);
302 const float t = (cosTheta - L.spot.z) / std::max(L.spot.w - L.spot.z, 1e-4f);
303 spotAtten = std::clamp(t, 0.f, 1.f);
304 spotAtten = spotAtten * spotAtten * (3.f - 2.f * spotAtten);
305 } else {
306 spotAtten = 0.f;
307 }
308 }
309 atten *= spotAtten;
310 }
311 lit += col * atten;
312 }
313 }
314 return Color(base.r * lit.r, base.g * lit.g, base.b * lit.b, base.a);
315}
316
317} // namespace
318
319void RenderSystem::collectSprites(std::vector<DrawItem2D> &out) {
320 std::unordered_map<Canvas *, Camera2D *> defaultCam;
321 if (ecs::current()->getManager<Camera2D>() != nullptr) {
322 auto camView = ecs::View<Camera2D, Camera2D::Data>();
323 for (auto it = camView.begin(); it != camView.end(); ++it) {
324 auto [data] = *it;
325 if (!data->active) continue;
326 ASSERT(data->entity != nullptr);
327 if (!data->entity) continue;
328 Canvas *key = data->canvas;
329 if (defaultCam.find(key) == defaultCam.end()) defaultCam[key] = data->entity;
330 }
331 }
332
333 auto view = ecs::View<Renderable2D, Renderable2D::Transform2D, Renderable2D::Sprite>();
334 for (auto it = view.begin(); it != view.end(); ++it) {
335 auto [xf, sp] = *it;
336 if (!sp->visible) continue;
337
338 Camera2D *camEnt = sp->camera;
339 if (!camEnt) {
340 auto found = defaultCam.find(sp->canvas);
341 camEnt = (found != defaultCam.end()) ? found->second : nullptr;
342 }
343
344 ViewCam cam = fromEntity(camEnt);
345 DrawItem2D item;
346 item.x = xf->x + float(sp->offsetX) * xf->sx;
347 item.y = xf->y + float(sp->offsetY) * xf->sy;
348 item.w = float(sp->trimW > 0 ? sp->trimW : sp->width) * xf->sx;
349 item.h = float(sp->trimH > 0 ? sp->trimH : sp->height) * xf->sy;
350 item.depthY = xf->y + sp->height * xf->sy;
351 item.rotation = xf->rot;
352 item.anchorX = sp->trimW > 0
353 ? (sp->anchorX * sp->width - float(sp->offsetX)) / float(sp->trimW)
354 : sp->anchorX;
355 item.anchorY = sp->trimH > 0
356 ? (sp->anchorY * sp->height - float(sp->offsetY)) / float(sp->trimH)
357 : sp->anchorY;
358 item.flipX = sp->flipX;
359 item.flipY = sp->flipY;
360 item.color = Color(sp->r, sp->g, sp->b, sp->a);
361 item.layer = sp->layer;
362 item.blend = sp->blend;
363 item.texture = sp->texture;
364 item.normal = sp->normalTexture;
365 item.quad = sp->quad;
366 item.shader = sp->shader;
367 item.canvas = sp->canvas;
368 item.camera = camEnt;
369 item.camValid = cam.valid;
370 item.camX = cam.x;
371 item.camY = cam.y;
372 item.camZoom = cam.zoom;
373 item.camClear = cam.clearColor;
374 item.camAmbientR = cam.ambientR;
375 item.camAmbientG = cam.ambientG;
376 item.camAmbientB = cam.ambientB;
377 item.receiveLight = sp->receiveLight;
378 item.litPath = sp->receiveLight && sp->normalTexture != nullptr && sp->texture != nullptr &&
379 sp->shader == nullptr;
380 if (item.quad && item.texture) {
381 item.hasUV = true;
382 item.quad->getUV(item.texture->getWidth(), item.texture->getHeight(), item.u0, item.v0,
383 item.u1, item.v1);
384 }
385 out.push_back(item);
386 }
387}
388
389void RenderSystem::drawItems(Graphics &gfx, std::vector<DrawItem2D> &items, bool present) {
390 eve::debug::RenderPassScope pass("RenderSystem2D");
391 sortDrawItems2D(items);
392
393 std::unordered_map<Canvas *, Camera2D *> defaultCam;
394 if (ecs::current()->getManager<Camera2D>() != nullptr) {
395 auto camView = ecs::View<Camera2D, Camera2D::Data>();
396 for (auto it = camView.begin(); it != camView.end(); ++it) {
397 auto [data] = *it;
398 if (!data->active) continue;
399 if (!data->entity) continue;
400 Canvas *key = data->canvas;
401 if (defaultCam.find(key) == defaultCam.end()) defaultCam[key] = data->entity;
402 }
403 }
404
405 Canvas *current = reinterpret_cast<Canvas *>(static_cast<uintptr_t>(1));
406 Lighting2DUBO currentLights{};
407 for (size_t i = 0; i < items.size(); ++i) {
408 Canvas *next = items[i].canvas;
409 if (i == 0 || next != current) {
410 Color clearCol = gfx.getBackgroundColor();
411 ViewCam groupCam{};
412 auto defIt = defaultCam.find(next);
413 if (defIt != defaultCam.end()) {
414 groupCam = fromEntity(defIt->second);
415 clearCol = groupCam.clearColor;
416 } else if (items[i].camValid) {
417 groupCam.valid = true;
418 groupCam.x = items[i].camX;
419 groupCam.y = items[i].camY;
420 groupCam.zoom = items[i].camZoom;
421 groupCam.clearColor = items[i].camClear;
422 groupCam.ambientR = items[i].camAmbientR;
423 groupCam.ambientG = items[i].camAmbientG;
424 groupCam.ambientB = items[i].camAmbientB;
425 clearCol = groupCam.clearColor;
426 }
427
428 gfx.setCanvas(next);
429 eve::debug::rtTarget(next ? "canvas" : "screen");
430 // Only clear when presenting a full sprite pass; map-unified draws must not wipe.
431 if (present) gfx.clear(clearCol, std::nullopt, std::nullopt);
432 current = next;
433
434 int viewW = next ? next->getWidth() : gfx.getWidth();
435 int viewH = next ? next->getHeight() : gfx.getHeight();
436 std::vector<PackedLight> packed;
437 collectLights(next, packed);
438 currentLights = packLights(packed, groupCam, viewW, viewH);
439 gfx.setLighting2D(currentLights);
440 }
441
442 const auto &it = items[i];
443 ViewCam cam{};
444 if (it.camValid) {
445 cam.valid = true;
446 cam.x = it.camX;
447 cam.y = it.camY;
448 cam.zoom = it.camZoom;
449 } else if (it.camera) {
450 cam = fromEntity(it.camera);
451 }
452 int viewW = it.canvas ? it.canvas->getWidth() : gfx.getWidth();
453 int viewH = it.canvas ? it.canvas->getHeight() : gfx.getHeight();
454 float sx, sy, sw, sh;
455 applyCamera(it.x, it.y, it.w, it.h, cam, viewW, viewH, sx, sy, sw, sh);
456
457 float u0 = it.hasUV ? it.u0 : 0.f;
458 float v0 = it.hasUV ? it.v0 : 0.f;
459 float u1 = it.hasUV ? it.u1 : 1.f;
460 float v1 = it.hasUV ? it.v1 : 1.f;
461 if (!it.hasUV && it.quad && it.texture)
462 it.quad->getUV(it.texture->getWidth(), it.texture->getHeight(), u0, v0, u1, v1);
463 if (it.flipX) std::swap(u0, u1);
464 if (it.flipY) std::swap(v0, v1);
465
466 const float pivotX = sx + sw * it.anchorX;
467 const float pivotY = sy + sh * it.anchorY;
468 const float radians = it.rotation * 3.14159265358979323846f / 180.f;
469 const float ox = sw * (0.5f - it.anchorX);
470 const float oy = sh * (0.5f - it.anchorY);
471 const float centerX = pivotX + ox * std::cos(radians) - oy * std::sin(radians);
472 const float centerY = pivotY + ox * std::sin(radians) + oy * std::cos(radians);
473
474 if (it.sceneColorDistortion) {
475 eve::debug::rtBind("texture", "distortion");
476 eve::debug::rtBind("texture", "sceneColor");
477 eve::debug::rtDraw("drawSceneColorDistortionUVRotated", "distortion");
478 gfx.drawSceneColorDistortionUVRotated(it.texture, centerX, centerY, sw, sh, it.rotation,
479 u0, v0, u1, v1, it.distortionStrength,
480 it.color.a, it.rotatedUV);
481 } else if (it.litPath) {
482 eve::debug::rtBind("texture", "albedo");
483 eve::debug::rtBind("texture", "normal");
484 if (it.rotation != 0.f) {
485 eve::debug::rtDraw("drawTexturedRectLitUVRotated", "lit2d");
486 gfx.drawTexturedRectLitUVRotated(it.texture, it.normal, centerX, centerY, sw, sh, it.rotation, u0, v0,
487 u1, v1, it.color, it.blend);
488 } else {
489 eve::debug::rtDraw("drawTexturedRectLitUV", "lit2d");
490 gfx.drawTexturedRectLitUV(it.texture, it.normal, sx, sy, sw, sh, u0, v0, u1, v1, it.color, it.blend);
491 }
492 } else if (it.texture) {
493 Color c = it.color;
494 if (it.receiveLight && !it.normal)
495 c = modulateUnlit(c, sx + sw * 0.5f, sy + sh * 0.5f, true, currentLights);
496 eve::debug::rtBind("texture", "sprite");
497 if (it.shader) eve::debug::rtBind("shader", "custom");
498 if (it.rotation != 0.f) {
499 eve::debug::rtDraw("drawTexturedRectShaderUVRotated",
500 it.shader ? "shader" : "textured");
501 gfx.drawTexturedRectShaderUVRotated(it.texture, it.shader, centerX,
502 centerY, sw, sh, it.rotation, u0, v0, u1,
503 v1, c, it.rotatedUV, it.blend);
504 } else {
505 eve::debug::rtDraw("drawTexturedRectShaderUV", it.shader ? "shader" : "textured");
506 gfx.drawTexturedRectShaderUV(it.texture, it.shader, sx, sy, sw, sh, u0, v0, u1, v1, c,
507 it.rotatedUV, it.blend);
508 }
509 } else {
510 Color c = it.color;
511 if (it.receiveLight)
512 c = modulateUnlit(c, sx + sw * 0.5f, sy + sh * 0.5f, true, currentLights);
513 eve::debug::rtDraw("drawSolidRect", "solid");
514 if (it.rotation != 0.f)
515 gfx.drawSolidRectRotated(centerX, centerY, sw, sh, it.rotation, c,
516 it.blend);
517 else
518 gfx.drawSolidRect(sx, sy, sw, sh, c, it.blend);
519 }
520 }
521
522 if (present) {
523 gfx.setCanvas();
524 eve::debug::rtPassBegin("Present");
525 gfx.present();
526 eve::debug::rtPassEnd("Present");
527 }
528}
529
532 std::vector<DrawItem2D> items;
533 collectSprites(items);
534 drawItems(gfx, items, true);
536}
537
538} // namespace eve::graphics
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
float cx
Definition CardTypes.cpp:33
float cy
Definition CardTypes.cpp:34
float degrees
Definition CardTypes.cpp:35
tensor::Graph g
Definition GpuGraph.cpp:7
std::vector< eve::ProcgenProbeDesc > lights
std::uint32_t key
double r
float v
std::int32_t c
float blend
std::uint32_t height
std::uint32_t width
bool valid
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
TileLayer * layer
float d
float t
glm::mat4 view
float zoom
Color clearColor
bool isPoint
float ambientG
float ambientR
float ambientB
bool found
double current
float dy
float dx
std::uint32_t count
float offsetX
float offsetY
bool visible
double oy
double ox
float wx
float wy
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
RAII pass scope for C++ call sites.
Definition RenderTrace.h:75
Declarative 2D camera (viewport center + zoom).
float screenToWorldY(float screenX, float screenY, float viewW, float viewH)
float worldToScreenY(float worldX, float worldY, float viewW, float viewH)
float worldToScreenX(float worldX, float worldY, float viewW, float viewH)
float screenToWorldX(float screenX, float screenY, float viewW, float viewH)
Convert screen pixel (origin top-left of viewport) to world coordinates. viewW/viewH are the current ...
void setZoom(float zoom)
void setAmbient(float r, float g, float b)
void setPosition(float x, float y)
World-space look-at center and zoom (1 = identity).
Canvas public API.
Definition Canvas.h:17
virtual void clear(std::optional< Color > color, std::optional< int > stencil, std::optional< double > depth)=0
Clears .
int getWidth() const
Returns the width.
Definition Graphics.h:502
virtual void drawTexturedRectShaderUV(Texture *texture, Shader *shader, float x, float y, float w, float h, float u0, float v0, float u1, float v1, const Color &color, bool rotatedUV=false, BlendMode blend=BlendMode::Alpha)=0
UV draw with an explicit Shader (nullptr = default textured pipeline).
virtual void drawTexturedRectLitUVRotated(Texture *albedo, Texture *normal, float cx, float cy, float w, float h, float degrees, float u0, float v0, float u1, float v1, const Color &color, BlendMode blend=BlendMode::Alpha)=0
Lit 2D draw rotated degrees clockwise (screen Y-down) around (cx, cy). Fragment tangent frame is rebu...
Color getBackgroundColor() const
Returns the background color.
Definition Graphics.h:1494
virtual void setLighting2D(const Lighting2DUBO &ubo)=0
Upload per-frame / per-canvas 2D lighting constants for subsequent lit draws.
virtual SceneColorDistortionStatus drawSceneColorDistortionUVRotated(Texture *displacement, float cx, float cy, float w, float h, float degrees, float u0, float v0, float u1, float v1, float strengthPixels, float opacity, bool rotatedUV=false)
Draws scene color distortion uv rotated.
Definition Graphics.h:796
virtual void drawSolidRect(float x, float y, float w, float h, float r, float g, float b, float a=1.f)
RGBA-float overload matching the script-facing drawSolidRect name.
virtual void drawTexturedRectShaderUVRotated(Texture *texture, Shader *shader, float cx, float cy, float w, float h, float degrees, float u0, float v0, float u1, float v1, const Color &color, bool rotatedUV=false, BlendMode blend=BlendMode::Alpha)=0
UV draw rotated degrees clockwise (screen Y-down) around the rect center. texture may be null → solid...
virtual void drawSolidRectRotated(float cx, float cy, float w, float h, float degrees, const Color &color, BlendMode blend=BlendMode::Alpha)=0
Rotated solid quad degrees clockwise (screen Y-down) around (cx, cy).
virtual void setCanvas(Canvas *canvas)=0
nullptr or this → screen. Switching flushes pending draws to the previous target.
virtual void present()=0
Present.
virtual void drawTexturedRectLitUV(Texture *albedo, Texture *normal, float x, float y, float w, float h, float u0, float v0, float u1, float v1, const Color &color, BlendMode blend=BlendMode::Alpha)=0
Lit 2D draw (albedo + normal map). Uses Lighting2DUBO from setLighting2D. normal may be null → treate...
int getHeight() const
Returns the height.
Definition Graphics.h:504
Pixel-space sub-rectangle of a Texture (atlas cell / sprite frame). UV conversion uses the texture's ...
Definition Quad.h:11
void getUV(int texW, int texH, float &u0, float &v0, float &u1, float &v1) const
Convert pixel rect to normalized UVs for a texture of size texW×texH.
Definition Quad.cpp:18
static void render(Graphics &gfx)
Full sprite pass + present (existing tests / sprite-only scenes).
static void collectSprites(std::vector< DrawItem2D > &out)
Append visible Renderable2D sprites into a shared queue.
static void drawItems(Graphics &gfx, std::vector< DrawItem2D > &items, bool present)
Sort and draw items. If present=true, calls gfx.present() at the end. Map::render uses present=false ...
void setCastOcclusion(bool cast)
Enable or disable volumetric occlusion casting.
void setVisible(bool visible)
Include or exclude the sprite from collection.
float getScaleY()
Return Y scale.
float getRotation()
Return center rotation in degrees.
void setBlend(const std::string &blend)
Set blend mode (alpha or additive).
void setScale(float sx, float sy)
Set independent X/Y scale.
void setPosition(float x, float y)
Set world-space position in pixels.
Texture * getTexture()
Return the assigned texture.
float getX()
Return world-space X position.
bool getReceiveLight()
Return whether the sprite receives 2D lights.
bool getFlipX()
Return horizontal mirror state.
void release() override
Entity.
void setNormalTexture(Texture *texture)
Assign an optional tangent-space normal map for the GPU lit2d path.
void setFrameLayout(int sourceW, int sourceH, int trimW, int trimH, int offsetX, int offsetY)
Apply trimmed-frame layout while preserving the original canvas origin.
void setRotation(float degrees)
Set center rotation in degrees.
void setLayer(int layer)
Set integer painter-order layer.
void setColor(float r, float g, float b, float a=1.f)
Set RGBA tint.
Quad * getQuad()
Return the assigned UV quad.
void setTexture(Texture *texture)
Assign the borrowed sprite texture.
float getScaleX()
Return X scale.
float getWidth()
Return unscaled width.
void setFlip(bool horizontal, bool vertical)
Mirror atlas UVs without changing transform scale.
Texture * getNormalTexture()
Return the assigned normal map, or nullptr when unlit/flat. @ownership Returns a borrowed Texture*; t...
std::string getBlend()
Return blend mode name.
bool getVisible()
Return whether the sprite is visible.
bool getCastOcclusion()
Return whether the sprite casts volumetric occlusion.
void setQuad(Quad *quad)
Assign the borrowed UV quad.
int getLayer()
Return painter-order layer.
void setAnchor(float x, float y)
Set normalized transform pivot; (0,0) top-left, (0.5,0.5) center.
float getAnchorY()
Return normalized vertical pivot.
float getY()
Return world-space Y position.
float getAnchorX()
Return normalized horizontal pivot.
void setSize(float width, float height)
Set unscaled sprite dimensions in pixels.
float getHeight()
Return unscaled height.
void setReceiveLight(bool receive)
Enable or disable 2D light reception.
bool getFlipY()
Return vertical mirror state.
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
int getWidth() const
Returns the width.
Definition Texture.cpp:28
int getHeight() const
Returns the height.
Definition Texture.cpp:33
void rtBind(const char *kind, const char *name)
Rt bind.
Definition RenderTrace.h:62
void rtTarget(const char *name)
Rt target.
Definition RenderTrace.h:58
void rtPassBegin(const char *name)
Rt pass begin.
Definition RenderTrace.h:50
void rtFrameBegin()
Rt frame begin.
Definition RenderTrace.h:42
void rtFrameEnd()
Rt frame end.
Definition RenderTrace.h:46
void rtDraw(const char *api, const char *detail=nullptr)
Rt draw.
Definition RenderTrace.h:66
void rtPassEnd(const char *name)
Rt pass end.
Definition RenderTrace.h:54
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
void light2dSpotCosines(float angleDeg, float softness, float &cosOuter, float &cosInner)
Backward-compatible alias for lightSpotCosines.
Definition Light.h:40
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13
void sortDrawItems2D(std::vector< DrawItem2D > &items)
Sort draw items 2 d.
Definition DrawItem2D.h:61
Shared 2D draw queue item (sprites + tiles).
Definition DrawItem2D.h:18
BlendMode blend
2D quad blending (alpha / additive / opaque).
Definition DrawItem2D.h:36
float camX
Screen-space camera already resolved; if cameraEntity set, RenderSystem resolves.
Definition DrawItem2D.h:54
float anchorX
Normalized transform pivot; (0,0) top-left, (0.5,0.5) center.
Definition DrawItem2D.h:27
float rotation
Degrees, clockwise, around the rectangle center (screen Y-down).
Definition DrawItem2D.h:25
Lighting2DUBO public API.
Definition Light.h:53
static constexpr int kMaxLights
Definition Light.h:54