载入中...
搜索中...
未找到
GraphicsPrimitives.cpp
浏览该文件的文档.
1#include "common/Exception.h"
6
7#include <algorithm>
8
9namespace eve::graphics::webgpu {
10namespace {
11
12wgpu::ShaderModule primitiveShader(wgpu::Device &device, const char *source) {
13 wgpu::ShaderSourceWGSL wgsl{};
14 wgsl.code = source;
15 wgpu::ShaderModuleDescriptor descriptor{};
16 descriptor.nextInChain = &wgsl;
17 return device.CreateShaderModule(&descriptor);
18}
19
20} // namespace
21
22wgpu::RenderPipeline Graphics::getPrimitive3DPipeline(PrimitiveDepthMode depth, BlendMode blend, PrimitiveCullMode cull,
23 WGPUTextureFormat format, uint32_t sampleCount) {
24 const uint64_t key = static_cast<uint64_t>(depth) | (static_cast<uint64_t>(blend) << 2u) |
25 (static_cast<uint64_t>(cull) << 5u) | (static_cast<uint64_t>(uint32_t(format)) << 8u) |
26 (static_cast<uint64_t>(sampleCount) << 40u);
27 if (auto found = primitive3DPipelines.find(key); found != primitive3DPipelines.end()) return found->second;
28
29 static constexpr const char *kPrimitiveVert = R"wgsl(
30struct VSIn { @location(0) clipPosition: vec4f, @location(1) color: vec4f };
31struct VSOut { @builtin(position) position: vec4f, @location(0) color: vec4f };
32@vertex fn vs_main(input: VSIn) -> VSOut {
33 var output: VSOut;
34 output.position = input.clipPosition;
35 // Match the Vulkan-convention clip coordinates used by the shared resolver.
36 output.position.y = -output.position.y;
37 output.color = input.color;
38 return output;
39}
40)wgsl";
41 static constexpr const char *kPrimitiveFrag = R"wgsl(
42@fragment fn fs_main(@location(0) color: vec4f) -> @location(0) vec4f { return color; }
43)wgsl";
44 wgpu::VertexAttribute attributes[2]{};
45 attributes[0].format = wgpu::VertexFormat::Float32x4;
46 attributes[0].offset = offsetof(Primitive3DVertex, clipPosition);
47 attributes[0].shaderLocation = 0;
48 attributes[1].format = wgpu::VertexFormat::Float32x4;
49 attributes[1].offset = offsetof(Primitive3DVertex, color);
50 attributes[1].shaderLocation = 1;
51 PipelineBuilder builder;
52 builder.label("eve_primitive3d")
53 .vertexLayout(sizeof(Primitive3DVertex), wgpu::VertexStepMode::Vertex, attributes, 2)
54 .shader(primitiveShader(device, kPrimitiveVert), "vs_main", primitiveShader(device, kPrimitiveFrag), "fs_main")
55 .colorTarget(format, blend)
56 .depth(WGPUTextureFormat_Depth32Float,
57 depth == PrimitiveDepthMode::Ignore ? static_cast<wgpu::CompareFunction>(WGPUCompareFunction_Always)
58 : wgpu::CompareFunction::LessEqual,
60 .sampleCount(sampleCount)
61 .frontFace(wgpu::FrontFace::CCW)
62 .cull(cull == PrimitiveCullMode::Back
63 ? wgpu::CullMode::Back
64 : (cull == PrimitiveCullMode::Front ? wgpu::CullMode::Front
65 : static_cast<wgpu::CullMode>(WGPUCullMode_None)));
66 wgpu::RenderPipeline pipeline = builder.build(device);
67 primitive3DPipelines.emplace(key, pipeline);
68 return pipeline;
69}
70
72 if (!frame3DStarted) throw Exception("drawPrimitiveScene: call begin3DFrame first");
74 if (resolved.vertices.empty()) return;
75
76 const std::size_t firstSequence = primitive3DDraws.size();
77 primitive3DDraws.reserve(firstSequence + resolved.batches3D.size());
78 for (const ResolvedPrimitiveBatch3D &batch : resolved.batches3D) {
79 Primitive3DDraw draw;
80 draw.paint = batch.paint;
81 draw.averageDepth = batch.averageDepth;
82 draw.sequence = firstSequence + batch.sequence;
83 draw.vertices.reserve(batch.vertexCount);
84 for (std::size_t vertex = batch.firstVertex; vertex < batch.firstVertex + batch.vertexCount; ++vertex)
85 draw.vertices.push_back({resolved.vertices[vertex].clipPosition, resolved.vertices[vertex].color});
86 primitive3DDraws.push_back(std::move(draw));
87 }
88}
89
90void Graphics::flushPrimitive3D(wgpu::RenderPassEncoder pass, WGPUTextureFormat format, uint32_t sampleCount) {
91 if (primitive3DDraws.empty()) return;
92 std::stable_sort(primitive3DDraws.begin(), primitive3DDraws.end(),
93 [](const Primitive3DDraw &a, const Primitive3DDraw &b) {
94 const bool ignoreA = a.paint.depth == PrimitiveDepthMode::Ignore;
95 const bool ignoreB = b.paint.depth == PrimitiveDepthMode::Ignore;
96 if (ignoreA != ignoreB) return !ignoreA;
97 if (a.paint.layer != b.paint.layer) return a.paint.layer < b.paint.layer;
98 const bool transparentA = a.paint.blend != BlendMode::Opaque || a.paint.color.a < 1.f;
99 const bool transparentB = b.paint.blend != BlendMode::Opaque || b.paint.color.a < 1.f;
100 if (transparentA != transparentB) return !transparentA;
101 if (transparentA && a.averageDepth != b.averageDepth) return a.averageDepth > b.averageDepth;
102 return a.sequence < b.sequence;
103 });
104 auto &arena = currentVertexArena();
105 std::size_t totalBytes = 0;
106 for (const Primitive3DDraw &draw : primitive3DDraws) totalBytes += draw.vertices.size() * sizeof(Primitive3DVertex);
107 ensureVertexArena(arena, arena.used + totalBytes);
108 std::vector<Primitive3DVertex> vertices;
109 vertices.reserve(totalBytes / sizeof(Primitive3DVertex));
110 for (const Primitive3DDraw &draw : primitive3DDraws)
112 const uint64_t offset = arena.alloc(totalBytes);
113 queue.WriteBuffer(arena.buffer, offset, vertices.data(), totalBytes);
114 pass.SetVertexBuffer(0, arena.buffer, offset, totalBytes);
115 uint32_t firstVertex = 0;
116 for (const Primitive3DDraw &draw : primitive3DDraws) {
117 if (draw.vertices.empty()) continue;
118 pass.SetPipeline(
119 getPrimitive3DPipeline(draw.paint.depth, draw.paint.blend, draw.paint.cull, format, sampleCount));
120 pass.Draw(static_cast<uint32_t>(draw.vertices.size()), 1, firstVertex, 0);
121 firstVertex += static_cast<uint32_t>(draw.vertices.size());
122 }
123 primitive3DDraws.clear();
124}
125
126} // namespace eve::graphics::webgpu
std::string descriptor
vkb::Device & device
std::uint32_t firstVertex
std::uint32_t key
float blend
size_t offset
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
MeshVfxBatchedDraw draw
std::vector< Point > vertices
float begin
bool found
float size
Definition TreeMesh.cpp:156
const UnitySourceAsset & source
std::uint32_t depth
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
Frame-local scene recorder for 3D line primitives.
void drawPrimitiveScene(const PrimitiveSceneCanvas3D &canvas) override
Draws primitive scene.
PrimitiveCullMode
Face culling used by filled 3D primitives.
eve::BlendMode BlendMode
Compatibility alias for the shared 2D blend mode.
Definition BlendMode.h:8
ResolvedPrimitiveTriangles resolvePrimitiveStrokes3D(const PrimitiveSceneCanvas3D &canvas)
Resolves 3D stroke segment bodies with near-plane clipping.
PrimitiveDepthMode
Depth behavior of one 3D primitive.
One contiguous 3D pipeline/sort batch in the resolved vertex stream.
Owning backend-neutral triangle stream for one primitive pass.
std::vector< PrimitiveTriangleVertex > vertices
std::vector< ResolvedPrimitiveBatch3D > batches3D
glm::vec4 color