Cogs.Core
DebugGeometryRenderers.cpp
1#include <glm/gtc/type_ptr.hpp>
2#include "Rendering/ICapabilities.h"
3#include "Rendering/IGraphicsDevice.h"
4#include "Rendering/IBuffers.h"
5
6#include "Renderer/RenderList.h"
7#include "Renderer/Tasks/RenderTask.h"
8#include "Renderer/RenderStateUpdater.h"
9#include "Renderer/RenderTarget.h"
10#include "Renderer/Renderer.h"
11
12#include "Resources/VertexFormats.h"
13
14#include "Resources/MaterialManager.h"
15
16#include "DebugGeometryRenderers.h"
17
18namespace {
19 using namespace Cogs;
20 using namespace Cogs::Core;
21
22 struct DebugConstants
23 {
24 glm::mat4 projectionMatrix;
25 glm::mat4 viewMatrix;
26 glm::mat4 worldMatrix;
27 glm::vec4 diffuseColor;
28 };
29
30 Cogs::EffectHandle *effectHandleP;
31 Cogs::InputLayoutHandle *inputLayoutHandleP;
32 Cogs::BufferHandle *constantBufferP;
33
34 const glm::mat4 identityMatrix = glm::mat4();
35
36 const glm::vec3 coordSysData[] = {
37 glm::vec3(0, 0, 0),
38 glm::vec3(1, 0, 0),
39 glm::vec3(0, 0, 0),
40 glm::vec3(0, 1, 0),
41 glm::vec3(0, 0, 0),
42 glm::vec3(0, 0, 1),
43 };
44 Cogs::VertexBufferHandle *coordSysVerticesP;
45
46 void setupCoordSysVertices(Cogs::IGraphicsDevice* device)
47 {
48 if (HandleIsValid(*coordSysVerticesP)) return;
49 auto * buffers = device->getBuffers();
50 *coordSysVerticesP = buffers->loadVertexBuffer(coordSysData, sizeof(coordSysData) / sizeof(glm::vec3), Cogs::Core::VertexFormats::Pos3f);
51 buffers->annotate(*coordSysVerticesP, "CoordSys vertices");
52 }
53
54 const glm::vec3 unitVerticesData[] = {
55 glm::vec3(0, 0, 0),
56 glm::vec3(1, 0, 0),
57 glm::vec3(0, 1, 0),
58 glm::vec3(1, 1, 0),
59
60 glm::vec3(0, 0, 1),
61 glm::vec3(1, 0, 1),
62 glm::vec3(0, 1, 1),
63 glm::vec3(1, 1, 1),
64 };
65 Cogs::VertexBufferHandle *unitVerticesP;
66
67 void setupUnitVertices(Cogs::IGraphicsDevice* device)
68 {
69 if (HandleIsValid(*unitVerticesP)) return;
70 auto * buffers = device->getBuffers();
71 *unitVerticesP = buffers->loadVertexBuffer(unitVerticesData, sizeof(unitVerticesData) / sizeof(glm::vec3), Cogs::Core::VertexFormats::Pos3f);
72 buffers->annotate(*unitVerticesP, "Unit box vertices");
73 }
74
75
76 const glm::vec3 oneOneVerticesData[] = {
77 glm::vec3(-1, -1, -1),
78 glm::vec3(1, -1, -1),
79 glm::vec3(-1, 1, -1),
80 glm::vec3(1, 1, -1),
81
82 glm::vec3(-1, -1, 1),
83 glm::vec3(1, -1, 1),
84 glm::vec3(-1, 1, 1),
85 glm::vec3(1, 1, 1),
86
87 // Near
88 glm::vec3(-1 + 0.1f, 1 - 0.1f, -1), // 8
89 glm::vec3(-1 + 0.3f, 1 - 0.1f, -1), // 9
90 glm::vec3(-1 + 0.1f, 1 - 0.3f, -1), // 10
91 glm::vec3(-1 + +.3f, 1 - 0.3f, -1), // 11
92
93 // Far
94 glm::vec3(1 - 0.1f, 1 - 0.1f, 1), // 12
95 glm::vec3(1 - 0.1f, 1 - 0.2f, 1), // 13
96 glm::vec3(1 - 0.1f, 1 - 0.3f, 1), // 14
97 glm::vec3(1 - 0.2f, 1 - 0.2f, 1), // 15
98 glm::vec3(1 - 0.3f, 1 - 0.1f, 1), // 16
99
100 // X +
101 glm::vec3(1, 1 - 0.1f, -1 + 0.1f), // 17
102 glm::vec3(1, 1 - 0.3f, -1 + 0.1f), // 18
103 glm::vec3(1, 1 - 0.1f, -1 + 0.3f), // 19
104 glm::vec3(1, 1 - 0.3f, -1 + 0.3f), // 20
105
106 glm::vec3(1, 1 - 0.2, -1 + 0.4f), // 21
107 glm::vec3(1, 1 - 0.2, -1 + 0.6f), // 22
108 glm::vec3(1, 1 - 0.1, -1 + 0.5f), // 23
109 glm::vec3(1, 1 - 0.3, -1 + 0.5f), // 24
110
111 // X -
112 glm::vec3(-1, 1 - 0.1f, 1 - 0.1f), // 25
113 glm::vec3(-1, 1 - 0.3f, 1 - 0.1f), // 26
114 glm::vec3(-1, 1 - 0.1f, 1 - 0.3f), // 27
115 glm::vec3(-1, 1 - 0.3f, 1 - 0.3f), // 28
116 glm::vec3(-1, 1 - 0.2, 1 - 0.4f), // 29
117 glm::vec3(-1, 1 - 0.2, 1 - 0.6f), // 30
118
119 // Y +
120 glm::vec3(1 - 0.1f, 1, -1 + 0.1f), // 31
121 glm::vec3(1 - 0.3f, 1, -1 + 0.1f), // 32
122 glm::vec3(1 - 0.2f, 1, -1 + 0.2f), // 33
123 glm::vec3(1 - 0.2f, 1, -1 + 0.3f), // 34
124
125 glm::vec3(1 - 0.4f, 1, -1 + 0.2f), // 35
126 glm::vec3(1 - 0.6f, 1, -1 + 0.2f), // 36
127 glm::vec3(1 - 0.5f, 1, -1 + 0.1f), // 37
128 glm::vec3(1 - 0.5f, 1, -1 + 0.3f), // 38
129
130 // Y-
131 glm::vec3(-1 + 0.1f, -1, -1 + 0.1f), // 39
132 glm::vec3(-1 + 0.3f, -1, -1 + 0.1f), // 40
133 glm::vec3(-1 + 0.2f, -1, -1 + 0.2f), // 41
134 glm::vec3(-1 + 0.2f, -1, -1 + 0.3f), // 42
135
136 glm::vec3(-1 + 0.4f, -1, -1 + 0.2f), // 43
137 glm::vec3(-1 + 0.6f, -1, -1 + 0.2f), // 44
138
139 };
140 Cogs::VertexBufferHandle *oneOneVerticesP;
141
142 void setupOneOneVertices(Cogs::IGraphicsDevice* device)
143 {
144 if (HandleIsValid(*oneOneVerticesP)) return;
145 auto * buffers = device->getBuffers();
146 *oneOneVerticesP = buffers->loadVertexBuffer(oneOneVerticesData, sizeof(oneOneVerticesData) / sizeof(glm::vec3), Cogs::Core::VertexFormats::Pos3f);
147 buffers->annotate(*oneOneVerticesP, "One-one box vertices");
148 }
149
150
151 const uint16_t edgeIndicesData[] = {
152 0, 1, 0, 2, 0, 4,
153 1, 3, 1, 5,
154 2, 3, 2, 6,
155 3, 7,
156 4, 5, 4, 6,
157 5, 7,
158 6, 7,
159
160 8, 10, 8, 11, 9, 11, // N
161 12, 13, 13, 14, 13, 15, 12, 16, // F
162 17, 20, 18, 19, 21, 22, 23, 24, // X+
163 25, 28, 26, 27, 29, 30, // X-
164 31, 33, 33, 32, 33, 34, 35, 36, 37, 38, // Y+
165 39, 41, 41, 40, 41, 42, 43, 44 // Y-
166 };
167 Cogs::IndexBufferHandle *edgeIndicesP;
168
169 void setupEdgeIndices(Cogs::IGraphicsDevice* device)
170 {
171 if (HandleIsValid(*edgeIndicesP)) return;
172 auto * buffers = device->getBuffers();
173 *edgeIndicesP = buffers->loadIndexBuffer(edgeIndicesData, sizeof(edgeIndicesData) / sizeof(uint16_t), sizeof(uint16_t));
174 buffers->annotate(*edgeIndicesP, "Box edge indices");
175 }
176
177 const glm::vec4 colors[6] =
178 {
179 glm::vec4(1.f, 0.f, 0.f, 1.f), // red
180 glm::vec4(0.f, 1.f, 0.f, 1.f), // green
181 glm::vec4(0.f, 0.f, 1.f, 1.f), // blue
182 glm::vec4(0.f, 1.f, 1.f, 1.f), // cyan
183 glm::vec4(1.f, 1.f, 0.f, 1.f), // yellow
184 glm::vec4(1.f, 0.f, 1.f, 1.f), // magenta
185 };
186
187 void setConstants(RenderTaskContext * taskContext, Cogs::BufferHandle constantBuffer, const glm::mat4 &M, const glm::vec4 &color)
188 {
189 auto * device = taskContext->device;
190 auto * context = device->getImmediateContext();
191
192 if (HandleIsValid(constantBuffer)) {
193 {
194 MappedBuffer<DebugConstants> constants(context, constantBuffer, MapMode::WriteDiscard);
195
196 if (constants) {
197 constants->projectionMatrix = M;
198 constants->viewMatrix = identityMatrix;
199 constants->worldMatrix = identityMatrix;
200 constants->diffuseColor = color;
201 }
202 }
203 context->setConstantBuffer("DebugBuffer", constantBuffer);
204 }
205 else{
206 assert(false);
207 }
208 }
209
210 void drawWireBox(RenderTaskContext * taskContext, DrawContext * drawContext, Cogs::VertexBufferHandle vertices, Cogs::BufferHandle constantBuffer, const glm::mat4& M, const glm::vec4& color)
211 {
212 auto * renderer = taskContext->renderer;
213 auto * device = taskContext->device;
214 auto * context = device->getImmediateContext();
215 const auto * camData = drawContext->cameraData;
216
217 setupEdgeIndices(device);
218
219 bool useCamData = 2.f < std::min(camData->viewportSize.x, camData->viewportSize.y);
220
221 context->setEffect(*effectHandleP);
222 context->setInputLayout(*inputLayoutHandleP);
223
224 auto w = useCamData ? camData->viewportSize.x : (drawContext->renderTarget ? drawContext->renderTarget->width : renderer->getSize().x);
225 auto h = useCamData ? camData->viewportSize.y : (drawContext->renderTarget ? drawContext->renderTarget->height : renderer->getSize().y);
226 context->setViewport(camData->viewportOrigin.x, camData->viewportOrigin.y, w, h);
227 context->setRasterizerState(taskContext->states->rasterizerStateHandles[drawContext->renderer->getRenderStates().getRasterizerState(Cogs::RasterizerState::DefaultState())]);
228 context->setDepthStencilState(drawContext->renderer->getRenderStates().defaultDepthStencilStateHandle);
229 context->setBlendState(drawContext->renderer->getRenderStates().blendStates[size_t(BlendMode::None)].handle);
230 const uint32_t strides[] = { sizeof(glm::vec3) };
231 context->setVertexBuffers(&vertices, 1, strides, nullptr);
232 context->setIndexBuffer(*edgeIndicesP, 2);
233
234 setConstants(taskContext, constantBuffer, M, color);
235
236 context->drawIndexed(Cogs::PrimitiveType::LineList, 0, glm::countof(edgeIndicesData));
237 }
238
239 MaterialInstanceHandle *defaultMaterialInstanceP;
240}
241
242MaterialInstanceHandle Cogs::Core::getDefaultMaterialInstance(Context* context)
243{
244 if (!HandleIsValid(*defaultMaterialInstanceP)) {
245 *defaultMaterialInstanceP = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
246 }
247 return *defaultMaterialInstanceP;
248}
249
250void Cogs::Core::drawUnitWireBox(RenderTaskContext * taskContext, DrawContext * drawContext, const RenderItem * /*item*/, const glm::mat4& M, unsigned color)
251{
252 setupUnitVertices(taskContext->device);
253 drawWireBox(taskContext, drawContext, *unitVerticesP, *constantBufferP, M, colors[color % 6]);
254}
255
256void Cogs::Core::drawOneOneWireBox(RenderTaskContext * taskContext, DrawContext * drawContext, const RenderItem * /*item*/, const glm::mat4& M, unsigned color)
257{
258 setupOneOneVertices(taskContext->device);
259 drawWireBox(taskContext, drawContext, *oneOneVerticesP, *constantBufferP, M, colors[color % 6]);
260}
261
262void Cogs::Core::drawCoordSys(RenderTaskContext * taskContext, DrawContext * drawContext, const RenderItem * /*item*/, const glm::mat4& M, bool overlay)
263{
264 auto * renderer = taskContext->renderer;
265 auto * device = taskContext->device;
266 auto * context = device->getImmediateContext();
267 const auto * camData = drawContext->cameraData;
268
269 setupCoordSysVertices(taskContext->device);
270
271 context->setEffect(*effectHandleP);
272 context->setInputLayout(*inputLayoutHandleP);
273
274 if (overlay) {
275 context->setDepthStencilState(drawContext->renderer->getRenderStates().noTestDepthStencilStateHandle);
276 }
277 else {
278 bool useCamData = 2.f < std::min(camData->viewportSize.x, camData->viewportSize.y);
279 auto w = useCamData ? camData->viewportSize.x : (drawContext->renderTarget ? drawContext->renderTarget->width : renderer->getSize().x);
280 auto h = useCamData ? camData->viewportSize.y : (drawContext->renderTarget ? drawContext->renderTarget->height : renderer->getSize().y);
281 context->setViewport(camData->viewportOrigin.x, camData->viewportOrigin.y, w, h);
282 context->setDepthStencilState(drawContext->renderer->getRenderStates().defaultDepthStencilStateHandle);
283 }
284
285 context->setRasterizerState(taskContext->states->rasterizerStateHandles[drawContext->renderer->getRenderStates().getRasterizerState(Cogs::RasterizerState::DefaultState())]);
286 context->setBlendState(drawContext->renderer->getRenderStates().blendStates[size_t(BlendMode::None)].handle);
287 const uint32_t strides[] = { sizeof(glm::vec3) };
288 context->setVertexBuffers(coordSysVerticesP, 1, strides, nullptr);
289
290 glm::vec4 colors3[3] = {
291 glm::vec4(1,0,0,1),
292 glm::vec4(0,1,0,1),
293 glm::vec4(0,0,1,1)
294 };
295 setConstants(taskContext, *constantBufferP, M, colors3[0]);
296 context->draw(Cogs::PrimitiveType::LineList, 0, 2);
297 setConstants(taskContext, *constantBufferP, M, colors3[1]);
298 context->draw(Cogs::PrimitiveType::LineList, 2, 2);
299 setConstants(taskContext, *constantBufferP, M, colors3[2]);
300 context->draw(Cogs::PrimitiveType::LineList, 4, 2);
301}
302
303void DebugGeometryRenderer::initialize(class Renderer* renderer, IGraphicsDevice * device)
304{
305 auto buffers = device->getBuffers();
306 Cogs::EffectDescription desc = {};
307 desc.name = "DebugEffect";
308 desc.flags = renderer->getEffectFlags();
309 desc.type = EffectDescriptionType::File;
310 switch (device->getType()) {
312 desc.vertexShader = "Engine/DebugVS.wgsl";
313 desc.pixelShader = "Engine/DebugPS.wgsl";
314 desc.vsEntryPoint = "vs_main";
315 desc.psEntryPoint = "fs_main";
316 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::WGSL);
317 break;
319 desc.vertexShader = "Engine/DebugVS.es30.glsl";
320 desc.pixelShader = "Engine/DebugPS.es30.glsl";
321 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::GLSL);
322 break;
323 default:
324 desc.vertexShader = "Engine/DebugVS.hlsl";
325 desc.pixelShader = "Engine/DebugPS.hlsl";
326 break;
327 }
328 effectHandle = device->getEffects()->loadEffect(desc);
329
330 VertexElement elements[] = {
331 { 0, DataFormat::X32Y32Z32_FLOAT, ElementSemantic::Position, 0, InputType::VertexData, 0 }
332 };
333 auto vertexFormat = buffers->createVertexFormat(elements, 1);
334 inputLayoutHandle = buffers->loadInputLayout(&vertexFormat, 1, effectHandle);
335
336 constantBuffer = device->getBuffers()->loadBuffer(nullptr, sizeof(DebugConstants), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
337 device->getBuffers()->annotate(constantBuffer, "DebugGeometryConstants");
338
339 effectHandleP = &effectHandle;
340 inputLayoutHandleP = &inputLayoutHandle;
341 constantBufferP = &constantBuffer;
342 coordSysVerticesP = &coordSysVertices;
343 unitVerticesP = &unitVertices;
344 oneOneVerticesP = &oneOneVertices;
345 edgeIndicesP = &edgeIndices;
346 defaultMaterialInstanceP = &defaultMaterialInstance;
347}
348void DebugGeometryRenderer::cleanup()
349{
351 inputLayoutHandle = Cogs::InputLayoutHandle::InvalidHandle;
352 constantBuffer = Cogs::BufferHandle::InvalidHandle;
357 defaultMaterialInstance = MaterialInstanceHandle::NoHandle;
358 effectHandleP = nullptr;
359 inputLayoutHandleP = nullptr;
360 constantBufferP = nullptr;
361 coordSysVerticesP = nullptr;
362 unitVerticesP = nullptr;
363 oneOneVerticesP = nullptr;
364 edgeIndicesP = nullptr;
365 defaultMaterialInstanceP = nullptr;
366}
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
Core renderer system.
Definition: Renderer.h:28
RenderStates & getRenderStates() override
Get the reference to the RenderStates structure.
Definition: Renderer.h:68
EffectFlags::EEffectFlags getEffectFlags() const override
Get the EffectFlags.
Definition: Renderer.h:69
Represents a graphics device used to manage graphics resources and issue drawing commands.
virtual IEffects * getEffects()=0
Get a pointer to the effect management interface.
virtual IContext * getImmediateContext()=0
Get a pointer to the immediate context used to issue commands to the graphics device.
virtual IBuffers * getBuffers()=0
Get a pointer to the buffer management interface.
virtual GraphicsDeviceType getType() const
Get the type of the graphics device.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ WebGPU
Graphics device using the WebGPU API Backend.
@ VertexData
Per vertex data.
@ LineList
List of lines.
@ Position
Position semantic.
@ Write
The buffer can be mapped and written to by the CPU after creation.
Definition: Flags.h:50
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
Definition: Flags.h:72
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.
Contains an effect description used to load a single effect.
Definition: IEffects.h:55
EEffectFlags
Effect source flags.
Definition: IEffects.h:20
@ WGSL
Effect source is WGSL.
Definition: IEffects.h:36
@ GLSL
Effect source is GLSL.
Definition: IEffects.h:26
static const Handle_t InvalidHandle
Represents an invalid handle.
Definition: Common.h:81
virtual void annotate(BufferHandle handle, const StringView &name)
Associate a name with an object for use in graphics debugging.
Definition: IBuffers.h:17
virtual BufferHandle loadBuffer(const void *data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t stride=0)=0
Loads a new buffer using the given data to populate the buffer.
virtual EffectHandle loadEffect(const EffectDescription &description)=0
Load an effect from the given description.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Definition: Flags.h:103
Provides RAII style mapping of a buffer resource.
Definition: IBuffers.h:160
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30
Vertex element structure used to describe a single data element in a vertex for the input assembler.
Definition: VertexFormat.h:38