FCT
载入中...
搜索中...
未找到
VertexContext.cpp
浏览该文件的文档.
1//
2// Created by Administrator on 2025/5/4.
3//
4#include "../headers.h"
5namespace FCT
6{
8 {
9 /*
10 auto commandBufferImage = m_ctx->getResourceImage(VertexCommandBufferNameInShder);
11
12 if (commandBufferImage->width() * commandBufferImage->height() >= m_commandBuffer.size()) {
13
14 } else {
15 uint32_t requiredHeight = (m_commandBuffer.size() + 4095) / 4096;
16 commandBufferImage->resize(4096, requiredHeight);
17 }
18 auto res = commandBufferImage->updateToCurrent(m_commandBuffer.data(), m_commandBuffer.size() * sizeof(float));
19 auto job = new VertexSubmitJob([res]()
20 {
21 res->waitFor();
22 });
23 m_ctx->submit(job,m_uploadPassName);
24 job->release();
25 */
26 }
28 {
29 m_commandBuffer.clear();
30
31 if (m_screens.empty()) {
32 return;
33 }
34
35 m_mesh->clear();
36
37 for (size_t screenIndex = 0; screenIndex < m_screens.size(); screenIndex++) {
38 const auto& screen = m_screens[screenIndex];
39 const auto& paths = screen.getPaths();
40
41 for (const auto& path : paths) {
42 const auto& commands = path->getCommandQueue();
43 if (commands.empty()) {
44 continue;
45 }
46
47 uint32_t commandOffset = m_commandBuffer.size();
48 uint32_t commandSize = commands.size();
49
50 //m_commandBuffer.push_back(VertexCommand_SetTransform);
51 //for (int i = 0; i < 16; i++) {
52 // m_commandBuffer.push_back(path->transform.m[i]);
53 //}
54 m_commandBuffer.insert(m_commandBuffer.end(), commands.begin(), commands.end());
55
56 Vec4 bounds = path->getBoundingRect();
57
58 addRectangle(screenIndex, commandOffset, commandSize, bounds);
59 }
60 }
61
62 m_mesh->update();
63 }
64 void VertexContext::addRectangle(uint32_t screenId, uint32_t commandOffset, uint32_t commandSize, const Vec4& bounds)
65 {
66 float left = bounds.x;
67 float top = bounds.y;
68 float right = bounds.x + bounds.z;
69 float bottom = bounds.y + bounds.w;
70
71 uint32_t baseIndex = m_mesh->getVertexCount();
72
73 m_mesh->addVertex(Vec2(left, top), commandOffset, commandSize, screenId);
74
75 m_mesh->addVertex(Vec2(right, top), commandOffset, commandSize, screenId);
76
77 m_mesh->addVertex(Vec2(left, bottom), commandOffset, commandSize, screenId);
78
79 m_mesh->addVertex(Vec2(right, bottom), commandOffset, commandSize, screenId);
80
81 m_mesh->addIndex(baseIndex);
82 m_mesh->addIndex(baseIndex + 1);
83 m_mesh->addIndex(baseIndex + 2);
84
85 m_mesh->addIndex(baseIndex + 1);
86 m_mesh->addIndex(baseIndex + 3);
87 m_mesh->addIndex(baseIndex + 2);
88 }
90 {
92 m_vs = m_ctx->createResource<VertexShader>();
93 m_vs->pixelLayout(pixelLayout);
94 m_vs->addLayout(0, vertexLayout);
95 m_vs->addUniform(m_projectionMatrix.first);
96 m_vs->addUniform(m_viewMatrix.first);
97 m_vs->resourceLayout(resourceLayout);
98
99 m_ps = m_ctx->createResource<PixelShader>();
100 m_ps->pixelLayout(pixelLayout);
101 m_ps->resourceLayout(resourceLayout);
102
105
106 m_vs->create();
107 m_ps->create();
108
109 m_pso->vertexLayout = vertexLayout;
110 m_pso->pixelLayout = pixelLayout;
111 m_pso->resourceLayout = resourceLayout;
112 m_pso->vertexShader = m_vs;
113 m_pso->pixelShader = m_ps;
114
115 for (auto& resource : m_passResources)
116 {
117 resource->create();
118 }
119 // m_passResource->create();
120
122 m_mesh->reserveIndices(200);
123 m_mesh->reserveVertices(200);
124 m_mesh->create();
125 }
126
127
128 void VertexContext::addScreen(const std::string& name)
129 {
130 size_t index = m_infos.size();
131 m_screenIndexMap[name] = index;
132 m_infos.emplace_back();
133 m_screens.emplace_back(m_infos, index);
134 }
135 VertexScreen& VertexContext::setScreen(const std::string& name)
136 {
137 auto it = m_screenIndexMap.find(name);
138 if (it == m_screenIndexMap.end()) {
139 addScreen(name);
140 return m_screens.back();
141 }
142 return m_screens[it->second];
143 }
145 {
146 auto viewMatrix = layout.getElement(ConstType::ViewMatrix);
147 if (viewMatrix)
148 {
149 m_viewMatrix = { layout, viewMatrix };
150 }
151 auto projectionMatrix = layout.getElement(ConstType::ProjectionMatrix);
152 if (projectionMatrix)
153 {
154 m_projectionMatrix = { layout, projectionMatrix };
155 }
156 //todo:支持 vp合一矩阵 支持mvp合一 矩阵
157 }
158
159 /*
160 struct VertexScreenInfo {
161 Vec4 origin;
162 Vec4 XDir;
163 Vec4 YDir;
164 Vec4 originVertexCoord;
165 Vec4 VertexCoordSize;
166 };
167 */
168
170 {
171 std::string code;
172 code += "\n#define vertexOuputTarget " + std::string(ScreenInfoNameInShder);
173 code += R"(
174
175
176
177ShaderOut main(ShaderIn vsIn) {
178 ShaderOut vsOut;
179
180 uint screenId = uint(vsIn.screenId);
181
182 uint baseIndex = screenId * 5;
183
184 float4 origin = ScreenInfo.Load(int3(baseIndex, 0, 0));
185 float4 XDir = ScreenInfo.Load(int3(baseIndex + 1, 0, 0));
186 float4 YDir = ScreenInfo.Load(int3(baseIndex + 2, 0, 0));
187 float4 originVertexCoord = ScreenInfo.Load(int3(baseIndex + 3, 0, 0));
188 float4 VertexCoordSize = ScreenInfo.Load(int3(baseIndex + 4, 0, 0));
189
190 float2 vertexCoord = vsIn.vertexcoord;
191
192 float3 worldPos = origin.xyz +
193 XDir.xyz * (vertexCoord.x - originVertexCoord.x) / VertexCoordSize.x +
194 YDir.xyz * (vertexCoord.y - originVertexCoord.y) / VertexCoordSize.y;
195
196 float4 position = float4(worldPos, 1.0);
197)";
199 if (m_viewMatrix.second && m_projectionMatrix.second) {
200 std::string viewMatrixName = m_viewMatrix.second.getName();
201 std::string projMatrixName = m_projectionMatrix.second.getName();
202
203 code += " float4 viewPos = mul(" + viewMatrixName + ", position);\n";
204 code += " vsOut.pos = mul(" + projMatrixName + ", viewPos);\n";
205 } else if (m_viewMatrix.second) {
206 std::string viewMatrixName = m_viewMatrix.second.getName();
207
208 code += " vsOut.pos = mul(" + viewMatrixName + ", position);\n";
209 } else if (m_projectionMatrix.second) {
210 std::string projMatrixName = m_projectionMatrix.second.getName();
211
212 code += " vsOut.pos = mul(" + projMatrixName + ", position);\n";
213 } else {
214 code += " vsOut.pos = position;\n";
215 }
216
217 code += R"(
218 vsOut.cmdoffset = vsIn.cmdoffset;
219 vsOut.cmdSize = vsIn.cmdSize;
220 vsOut.screenId = vsIn.screenId;
221 vsOut.vertexcoord = vsIn.vertexcoord;
222
223 return vsOut;
224}
225)";
226
227 m_vs->code(code);
228 }
229
231 {
232 std::string code;
233 code += "\n#define VertexCommandBuffer " + std::string(VertexCommandBufferNameInShder);
234 code += "\n#define vertexOuputTarget target" + std::to_string(m_targetIndex);
235 code += R"(
236
237
238const float VertexCommand_End = -1.0;
239const float VertexCommand_MoveTo = 1.0;
240const float VertexCommand_LineTo = 2.0;
241const float VertexCommand_BezierCurveTo = 3.0;
242const float VertexCommand_SetColor = 4.0;
243const float VertexCommand_ArcTo = 6.0;
244const float VertexCommand_SetTransform = 5.0;
245const float VertexCommand_BeginPath = 7.0;
246const float VertexCommand_EndPath = 8.0;
247
248int GetCurveRootFlags(float v0, float v1, float v2) {
249 int shift = ((v0 > 0.0) ? 2 : 0) + ((v1 > 0.0) ? 4 : 0) + ((v2 > 0.0) ? 8 : 0);
250 return (0x2E74 >> shift) & 0x03;
251}
252
253float2 QuadCurveSolveXAxis(float2 v0, float2 v1, float2 v2) {
254 float2 a = v0 - 2.0 * v1 + v2;
255 float2 b = v0 - v1;
256 float c = v0.y;
257 float ra = 1.0 / a.y;
258 float rb = 0.5 / b.y;
259 float delta = sqrt(max(b.y * b.y - a.y * c, 0.0));
260 float2 t = float2((b.y - delta) * ra, (b.y + delta) * ra);
261 if (abs(a.y) < 0.0001220703125) t = float2(c * rb, c * rb);
262 return (a.x * t - b.x * 2.0) * t + v0.x;
263}
264
265float2 QuadCurveSolveYAxis(float2 v0, float2 v1, float2 v2) {
266 float2 a = v0 - 2.0 * v1 + v2;
267 float2 b = v0 - v1;
268 float c = v0.x;
269 float ra = 1.0 / a.x;
270 float rb = 0.5 / b.x;
271 float delta = sqrt(max(b.x * b.x - a.x * c, 0.0));
272 float2 t = float2((b.x - delta) * ra, (b.x + delta) * ra);
273 if (abs(a.x) < 0.0001220703125) t = float2(c * rb, c * rb);
274 return (a.y * t - b.y * 2.0) * t + v0.y;
275}
276
277float CurveTestXAxis(float2 v0, float2 v1, float2 v2, float2 pixelsPerUnit) {
278 if (max(max(v0.x, v1.x), v2.x) * pixelsPerUnit.x < -0.5) return 0.0;
279 int flags = GetCurveRootFlags(v0.y, v1.y, v2.y);
280 if (flags == 0) return 0.0;
281 float2 x1x2 = QuadCurveSolveXAxis(v0, v1, v2) * pixelsPerUnit.x;
282 float ret = 0.0;
283 if ((flags & 1) != 0) {
284 ret += clamp(x1x2.x + 0.5, 0.0, 1.0);
285 }
286 if ((flags & 2) != 0) {
287 ret -= clamp(x1x2.y + 0.5, 0.0, 1.0);
288 }
289 return ret;
290}
291
292float CurveTestYAxis(float2 v0, float2 v1, float2 v2, float2 pixelsPerUnit) {
293 if (max(max(v0.y, v1.y), v2.y) * pixelsPerUnit.y < -0.5) return 0.0;
294 int flags = GetCurveRootFlags(v0.x, v1.x, v2.x);
295 if (flags == 0) return 0.0;
296 float2 y1y2 = QuadCurveSolveYAxis(v0, v1, v2) * pixelsPerUnit.y;
297 float ret = 0.0;
298 if ((flags & 0x01) != 0) {
299 ret -= clamp(y1y2.x + 0.5, 0.0, 1.0);
300 }
301 if ((flags & 0x02) != 0) {
302 ret += clamp(y1y2.y + 0.5, 0.0, 1.0);
303 }
304 return ret;
305}
306
307float2 CurveTest(float2 v0, float2 v1, float2 v2, float2 pixelsPerUnit) {
308 return float2(
309 CurveTestXAxis(v0, v1, v2, pixelsPerUnit),
310 CurveTestYAxis(v0, v1, v2, pixelsPerUnit)
311 );
312}
313
314float2 LineTest(float2 v0, float2 v1, float2 pixelsPerUnit) {
315 float2 result = float2(0.0, 0.0);
316
317 if (max(v0.x, v1.x) * pixelsPerUnit.x >= -0.5) {
318 int signX = (v0.y > 0.0 ? 1 : 0) - (v1.y > 0.0 ? 1 : 0);
319 if (signX != 0) {
320 float xt = (v1.y * v0.x - v0.y * v1.x) / (v1.y - v0.y);
321 result.x = float(signX) * clamp(xt * pixelsPerUnit.x + 0.5, 0.0, 1.0);
322 }
323 }
324
325 if (max(v0.y, v1.y) * pixelsPerUnit.y >= -0.5) {
326 int signY = (v1.x > 0.0 ? 1 : 0) - (v0.x > 0.0 ? 1 : 0);
327 if (signY != 0) {
328 float yt = (v1.x * v0.y - v0.x * v1.y) / (v1.x - v0.x);
329 result.y = float(signY) * clamp(yt * pixelsPerUnit.y + 0.5, 0.0, 1.0);
330 }
331 }
332
333 return result;
334}
335
336float2 ArcTest(float2 pos, float2 bp, float2 ep, float2 c, float b, float e, float r, float q, float2 pixelsPerUnit) {
337 float2 ret = float2(0.0, 0.0);
338 float minX = min(bp.x, ep.x);
339 float minY = min(bp.y, ep.y);
340 float maxX = max(bp.x, ep.x);
341 float maxY = max(bp.y, ep.y);
342 bool isInx = (pos.x >= minX && pos.x <= maxX);
343 bool isIny = (pos.y >= minY && pos.y <= maxY);
344 bool isInCircle = length(pos - c) <= r;
345 float bLessE = b < e ? 1.0 : -1.0;
346
347 if (q == 1.0 || q == 4.0) {
348 ret.x = float(isIny && (isInCircle || pos.x < minX));
349 ret.x *= -bLessE;
350 } else {
351 ret.x = float(isIny && pos.x < maxX && !isInCircle);
352 ret.x *= bLessE;
353 }
354
355 if (q == 1.0 || q == 2.0) {
356 ret.y = float(isInx && (isInCircle || pos.y < minY));
357 ret.y *= -bLessE;
358 } else {
359 ret.y = float(isInx && pos.y < maxY && !isInCircle);
360 ret.y *= bLessE;
361 }
362
363 return ret;
364}
365
366float NoZeroSign(float x) {
367 return x >= 0.0 ? 1.0 : -1.0;
368}
369
370float2 applyTransform(float2 needTransformPoint, float3x3 transform) {
371 float3 transformedPoint = mul(float3(needTransformPoint, 1.0), transform);
372 return transformedPoint.xy / transformedPoint.z;
373}
374
375float fetchCommand(int commandIndex) {
376 int pixelIndex = commandIndex / 4;
377 int channelIndex = commandIndex % 4;
378
379 int x = pixelIndex % 4096;
380 int y = pixelIndex / 4096;
381
382 float4 pixel = VertexCommandBuffer.Load(int3(x, y, 0));
383
384 if (channelIndex == 0) return pixel.r;
385 else if (channelIndex == 1) return pixel.g;
386 else if (channelIndex == 2) return pixel.b;
387 else return pixel.a;
388}
389
390ShaderOut main(ShaderIn ps_input) {
391 float transformSign = 1.0;
392 float3x3 transform = float3x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
393 ShaderOut ps_output;
394 ps_output.vertexOuputTarget = float4(1.0, 1.0, 1.0, 1.0);
395
396 float2 unitsPerPixel = fwidth(ps_input.vertexcoord);
397 float2 pixelsPerUnit = 1.0 / unitsPerPixel;
398
399 float2 crossings = float2(0.0, 0.0);
400
401 int i = int(ps_input.cmdoffset);
402 float2 lastPos;
403 float4 fillColor = float4(1.0, 0.647, 0.0, 1.0);
404 float4 currentColor = float4(1.0, 0.647, 0.0, 1.0);
405 bool isPathStarted = false;
406 float2 pathCrossings = float2(0.0, 0.0);
407
408 float pathOperation = 0.0; // 0: 默认 1:并 2:交 3:补
409 int edge = i + int(ps_input.cmdSize);
410 while(i < edge) {
411 float command = fetchCommand(i);
412 i++;
413 switch (int(command)) {
414 case int(VertexCommand_BeginPath):
415{
416 isPathStarted = true;
417 pathCrossings = float2(0.0, 0.0);
418 pathOperation = fetchCommand(i);
419 i += 1;
420}
421 break;
422 case int(VertexCommand_EndPath):
423{
424 isPathStarted = false;
425 if (length(pathCrossings) > 0.0) {
426 fillColor = currentColor;
427 }
428 if (pathOperation == 0.0) {
429 crossings += pathCrossings;
430 } else if (pathOperation == 1.0) {
431 crossings = float2(
432 NoZeroSign(crossings.x) * NoZeroSign(pathCrossings.x) * max(abs(crossings.x), abs(pathCrossings.x)),
433 NoZeroSign(crossings.y) * NoZeroSign(pathCrossings.y) * max(abs(crossings.y), abs(pathCrossings.y))
434 );
435 } else if (pathOperation == 2.0) {
436 crossings = float2(
437 sign(crossings.x) * sign(pathCrossings.x) * min(abs(crossings.x), abs(pathCrossings.x)),
438 sign(crossings.y) * sign(pathCrossings.y) * min(abs(crossings.y), abs(pathCrossings.y))
439 );
440 } else if (pathOperation == 3.0) {
441 crossings += pathCrossings;
442 crossings = float2(
443 NoZeroSign(crossings.x) * (1.0 - abs(crossings.x)),
444 NoZeroSign(crossings.y) * (1.0 - abs(crossings.y))
445 );
446 }
447 pathCrossings = float2(0, 0);
448 pathOperation = 0.0;
449}
450 break;
451 case int(VertexCommand_MoveTo):
452{
453 lastPos.x = fetchCommand(i);
454 lastPos.y = fetchCommand(i+1);
455 lastPos = applyTransform(lastPos, transform);
456 i += 2;
457}
458 break;
459 case int(VertexCommand_LineTo):
460{
461 float2 to;
462 to.x = fetchCommand(i);
463 to.y = fetchCommand(i+1);
464 to = applyTransform(to, transform);
465 i += 2;
466
467 float2 v0 = lastPos - ps_input.vertexcoord;
468 float2 v1 = to - ps_input.vertexcoord;
469 pathCrossings += transformSign * LineTest(v0, v1, pixelsPerUnit);
470 lastPos = to;
471}
472 break;
473 case int(VertexCommand_SetColor):
474{
475 currentColor.r = fetchCommand(i);
476 currentColor.g = fetchCommand(i+1);
477 currentColor.b = fetchCommand(i+2);
478 currentColor.a = fetchCommand(i+3);
479 i += 4;
480}
481 break;
482 case int(VertexCommand_ArcTo):
483{
484 float2 bp = lastPos;
485 float2 c;
486 c.x = fetchCommand(i);
487 c.y = fetchCommand(i+1);
488 c = applyTransform(c, transform);
489 float r = length(c - bp);
490 float b = fetchCommand(i+2);
491 float e = fetchCommand(i+3);
492 float q = fetchCommand(i+4);
493 float2 ep = c + float2(r * cos(e), r * sin(e));
494 pathCrossings += transformSign * ArcTest(ps_input.vertexcoord, bp, ep, c, b, e, r, q, pixelsPerUnit);
495 lastPos = ep;
496 i += 5;
497}
498 break;
499 case int(VertexCommand_BezierCurveTo):
500{
501 float2 control = float2(fetchCommand(i),
502 fetchCommand(i+1));
503 float2 end = float2(fetchCommand(i+2),
504 fetchCommand(i+3));
505 control = applyTransform(control, transform);
506 end = applyTransform(end, transform);
507 i += 4;
508
509 float2 v0 = lastPos - ps_input.vertexcoord;
510 float2 v1 = control - ps_input.vertexcoord;
511 float2 v2 = end - ps_input.vertexcoord;
512 pathCrossings += transformSign * CurveTest(v0, v1, v2, pixelsPerUnit);
513 lastPos = end;
514}
515 break;
516 case int(VertexCommand_SetTransform):
517{
518 transform = float3x3(
519 fetchCommand(i), fetchCommand(i+1), fetchCommand(i+2),
520 fetchCommand(i+3), fetchCommand(i+4), fetchCommand(i+5),
521 fetchCommand(i+6), fetchCommand(i+7), fetchCommand(i+8)
522 );
523 i += 16;
524
525 float det = determinant(transform);
526 transformSign = NoZeroSign(det);
527}
528 break;
529 }
530 if (command == VertexCommand_End) break;
531 }
532
533 float weightX = 1.0 - abs(crossings.x * 2.0 - 1.0);
534 float weightY = 1.0 - abs(crossings.y * 2.0 - 1.0);
535 float coverage = max(abs(crossings.x * weightX + crossings.y * weightY) / max(weightX + weightY, 0.0001220703125), min(abs(crossings.x), abs(crossings.y)));
536
537
538 ps_output.vertexOuputTarget = fillColor;
539 ps_output.vertexOuputTarget.a *= coverage;
540
541 //ps_output.vertexOuputTarget.r = crossings.x;
542 //ps_output.vertexOuputTarget.g = crossings.y;
543 //ps_output.vertexOuputTarget.b = 0.0;
544 //ps_output.vertexOuputTarget.a = 1.0;
545 return ps_output;
546}
547)";
548 m_ps->code(code);
549 }
550 /*
551 *todo:矢量渲染
552 *1.提供屏幕设置,屏幕是空间 四边形
553 * 需要描述一个空间四边形的常量缓冲 趣
554 * 需要描述符空间四边形的四个顶点的vertexCoord
555 * 需要vertexCoord
556 *2.传进去的顶点只有vertexCoord,传出的位置通过空间平行四边形计算出来
557 *3.传进去的顶点需要指定命令所在缓存区offset
558 *3.提供drawPath(Transfomr),提供drawPath(位置),把位置弄进矩阵,
559 * 使用setTransform传递位置,大小
560 *4.addScreen("screenName")
561 * draw("screenName",Path,Transform)
562 * draw("screenName",Path,float x,float y)
563 *5.setScreen().set().set()
564 *6.需要 更新screen 的UniformBuffer
565 *7.空间四边形 表示,原点+ halfX+halfY
566 *8.使用纹理来进行屏幕数据的传递
567 */
568}
constexpr const ConstElement & getElement(size_t index) const noexcept
void mvpUniformLayout(ConstLayout layout)
std::map< std::string, uint32_t > m_screenIndexMap
std::vector< PassResource * > m_passResources
static constexpr PixelLayout pixelLayout
std::pair< ConstLayout, ConstElement > m_projectionMatrix
void addRectangle(uint32_t screenId, uint32_t commandOffset, uint32_t commandSize, const Vec4 &bounds)
static constexpr const char * VertexCommandBufferNameInShder
TraditionPipelineState * m_pso
std::vector< VertexScreen > m_screens
static constexpr const char * ScreenInfoNameInShder
std::vector< VertexScreenInfo > m_infos
static constexpr VertexLayout vertexLayout
static constexpr ResourceLayout resourceLayout
VertexScreen & setScreen(const std::string &name)
DynamicMesh< uint32_t > * m_mesh
std::vector< float > m_commandBuffer
std::pair< ConstLayout, ConstElement > m_viewMatrix
void addScreen(const std::string &name)
float z
定义 Vec.h:196
float y
定义 Vec.h:196
float w
定义 Vec.h:196
float x
定义 Vec.h:196