Cogs.Core
EditorRenderTask.cpp
1#include "EditorRenderTask.h"
2
3#include "Context.h"
4#include "Engine.h"
5#include "Editor/Editor.h"
6#include "Editor.h"
7
8#include "Renderer/Renderer.h"
9
10#include "Resources/VertexFormats.h"
11#include "Resources/DefaultMaterial.h"
12
13#include "Scene/GetBounds.h"
14
15#include "Systems/Core/CameraSystem.h"
16#include "Components/Core/CameraComponent.h"
17
18#include "Rendering/ICapabilities.h"
19#include "Rendering/IContext.h"
20#include "Rendering/IBuffers.h"
21
22#include "Foundation/Logging/Logger.h"
23
24#include <glm/glm.hpp>
25#include <array>
26
27namespace
28{
29 const Cogs::Logging::Log logger = Cogs::Logging::getLogger("EditorRenderTask");
30
31 struct DebugConstants
32 {
33 glm::mat4 projectionMatrix;
34 glm::mat4 viewMatrix;
35 glm::mat4 worldMatrix;
36 glm::vec4 diffuseColor;
37 };
38
39 static constexpr uint16_t indexesEntity[] = {
40 0, 1, 0, 2, 0, 4,
41 1, 3, 1, 5,
42 2, 3, 2, 6,
43 3, 7,
44 4, 5, 4, 6,
45 5, 7,
46 6, 7
47 };
48}
49
50void Cogs::Core::EditorRenderTask::init(const ViewContext* viewContext, IGraphicsDevice * device)
51{
52 this->viewContext = viewContext;
53 Cogs::IBuffers* buffers = device->getBuffers();
54
56 .name = "EditorEffect",
57 .flags = viewContext->getContext()->renderer->getEffectFlags(),
59 };
60
61 switch (device->getType()) {
63 desc.vertexShader = "Engine/DebugVS.wgsl";
64 desc.pixelShader = "Engine/DebugPS.wgsl";
65 desc.vsEntryPoint = "vs_main";
66 desc.psEntryPoint = "fs_main";
67 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::WGSL);
68 break;
70 desc.vertexShader = "Engine/DebugVS.es30.glsl";
71 desc.pixelShader = "Engine/DebugPS.es30.glsl";
72 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::GLSL);
73 break;
74 default:
75 desc.vertexShader = "Engine/DebugVS.hlsl";
76 desc.pixelShader = "Engine/DebugPS.hlsl";
77 break;
78 }
79 effectHandle = device->getEffects()->loadEffect(desc);
80
81 static constexpr VertexElement elements[] = {
82 { 0, DataFormat::X32Y32Z32_FLOAT, ElementSemantic::Position, 0, InputType::VertexData, 0 }
83 };
84 Cogs::VertexFormatHandle vertexFormat = buffers->createVertexFormat(elements, 1);
85 inputLayoutHandle = buffers->loadInputLayout(&vertexFormat, 1, effectHandle);
86
87 constantBuffer = device->getBuffers()->loadBuffer(nullptr, sizeof(DebugConstants), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
88 device->getBuffers()->annotate(constantBuffer, "SelectedBounds");
89}
90
91void Cogs::Core::EditorRenderTask::apply(RenderTaskContext * renderContext)
92{
93 IEditor* editor = renderContext->context->engine->getEditor();
94
95 if (!editor->isActive()) return;
96
97 EditorState* state = editor->getState();
98 std::string erasedSelections = state->eraseInvalidSelected();
99 if (!erasedSelections.empty()) {
100 LOG_WARNING(logger, "Removed selection of invalid entities (Asset temp Entities?): %s", erasedSelections.data());
101 }
102
103 Renderer* renderer = renderContext->renderer;
104 Cogs::IGraphicsDevice* device = renderer->getDevice();
105 Cogs::IContext* context = device->getImmediateContext();
106 const RenderStates& renderStates = renderer->getRenderStates();
107
108 context->setEffect(effectHandle);
109
110 context->setRasterizerState(renderStates.defaultRasterizerStateHandle);
111 context->setDepthStencilState(renderStates.noWriteDepthStencilStateHandle);
112 context->setBlendState(renderStates.blendStates[size_t(BlendMode::None)].handle);
113
114 const CameraData& cameraData = renderContext->context->cameraSystem->getMainCameraData();
115
116 Cogs::IBuffers* buffers = device->getBuffers();
117 context->setInputLayout(inputLayoutHandle);
118
119 context->setViewport(cameraData.viewportOrigin.x, cameraData.viewportOrigin.y, cameraData.viewportSize.x, cameraData.viewportSize.y);
120
121
122 // Render selected Cameras. No use rendering View Camera as bounds not visible.
123 if (renderContext->context->cameraSystem->pool.size() > 1) {
124 for (const CameraComponent& cameraComponent : renderContext->context->cameraSystem->pool) {
125 const Entity* entity = cameraComponent.getContainer();
126
127 if (cameraComponent.projectionMode != ProjectionMode::Perspective) continue;
128 if (!state->isSelected(entity->getId())) continue;
129 if (entity == viewContext->getCamera().get()) continue;
130
131 glm::vec4 diffuseColor(0.0f, 0.8f, 0.1f, 1.0f);
132 renderCamera(renderContext, cameraComponent, diffuseColor);
133 }
134 }
135
136
137 // Draw Bounds for selected entities:
138 if (!state->selected.empty()) {
139
140 static constexpr std::array positions = {
141 glm::vec3(-1, -1, -1),
142 glm::vec3(1, -1, -1),
143 glm::vec3(-1, 1, -1),
144 glm::vec3(1, 1, -1),
145
146 glm::vec3(-1, -1, 1),
147 glm::vec3(1, -1, 1),
148 glm::vec3(-1, 1, 1),
149 glm::vec3(1, 1, 1),
150 };
151
152 auto ib = buffers->loadIndexBuffer(indexesEntity, std::size(indexesEntity), sizeof(indexesEntity[0]));
153 auto vb = buffers->loadVertexBuffer(positions.data(), positions.size(), VertexFormats::Pos3f);
154
155 context->setIndexBuffer(ib, sizeof(indexesEntity[0]));
156 static constexpr uint32_t strides[] = { sizeof(glm::vec3) };
157 context->setVertexBuffers(&vb, 1, strides, nullptr);
158
159 glm::vec4 boxColor(0.8f, 0.7f, 0.2f, 1.0f);
160
161 for (EntityId id : state->selected) {
162 renderEntity(renderContext, id, boxColor);
163 }
164
165 buffers->releaseIndexBuffer(ib);
166 buffers->releaseVertexBuffer(vb);
167 }
168}
169
170void Cogs::Core::EditorRenderTask::renderEntity(RenderTaskContext* renderContext, const EntityId id, glm::vec4 diffuseColor)
171{
172 Renderer* renderer = renderContext->renderer;
173 Cogs::IGraphicsDevice* device = renderer->getDevice();
174 Cogs::IContext* context = device->getImmediateContext();
175 const CameraData& cameraData = renderContext->context->cameraSystem->getMainCameraData();
176
177 Geometry::BoundingBox bounds = Bounds::getBounds(renderContext->context, id, true);
178 if (bounds.empty()) {
179 return;
180 }
181
182 glm::vec3 center = bounds.getCenter();
183 glm::vec3 scale = 0.5f * bounds.getExtent();
184
185 glm::mat4 world = glm::translate(glm::mat4(1.0f), center) * glm::scale(glm::mat4(1.0f), scale);
186
187 if (HandleIsValid(constantBuffer)) {
188 {
189 MappedBuffer<DebugConstants> constants(context, constantBuffer, MapMode::WriteDiscard);
190 if (constants) {
191 constants->projectionMatrix = cameraData.projectionMatrix;
192 constants->viewMatrix = cameraData.viewMatrix;
193 constants->worldMatrix = world;
194 constants->diffuseColor = diffuseColor;
195 }
196 }
197 context->setConstantBuffer("DebugBuffer", constantBuffer);
198 }
199 else {
200 assert(false);
201 }
202
203 context->drawIndexed(PrimitiveType::LineList, 0, std::size(indexesEntity));
204}
205
206void Cogs::Core::EditorRenderTask::renderCamera(RenderTaskContext* renderContext, const CameraComponent& cameraComponent, glm::vec4 diffuseColor)
207{
208 Renderer* renderer = renderContext->renderer;
209 Cogs::IGraphicsDevice* device = renderer->getDevice();
210 Cogs::IContext* context = device->getImmediateContext();
211 Cogs::IBuffers* buffers = device->getBuffers();
212 const CameraData& cameraData = renderContext->context->cameraSystem->getMainCameraData();
213
214 static constexpr std::array<glm::vec4, 8U> positionsClip = {
215 glm::vec4(-1, -1, 0, 1),
216 glm::vec4(1, -1, 0, 1),
217 glm::vec4(1, 1, 0, 1),
218 glm::vec4(-1, 1, 0, 1),
219
220 glm::vec4(-1, -1, 1, 1),
221 glm::vec4(1, -1, 1, 1),
222 glm::vec4(1, 1, 1, 1),
223 glm::vec4(-1, 1, 1, 1),
224 };
225
226 std::array<glm::vec3, positionsClip.size()> positionsWS;
227 const CameraData& cData = renderContext->context->cameraSystem->getData(&cameraComponent);
228
229 for (size_t i = 0; i < positionsWS.size(); ++i) {
230 glm::vec4 posWS = cData.inverseViewProjectionMatrix * positionsClip[i];
231 posWS /= posWS.w;
232
233 positionsWS[i] = glm::vec3(posWS);
234 }
235
236 static constexpr uint16_t indexesCamera[] = {
237 0, 1, 1, 2, 2, 3, 3, 0,
238 4, 5, 5, 6, 6, 7, 7, 4,
239 0, 4, 1, 5, 2, 6, 3, 7
240 };
241
242 auto ib = buffers->loadIndexBuffer(indexesCamera, std::size(indexesCamera), sizeof(indexesCamera[0]));
243 auto vb = buffers->loadVertexBuffer(positionsWS.data(), positionsWS.size(), VertexFormats::Pos3f);
244
245 context->setIndexBuffer(ib, sizeof(indexesCamera[0]));
246 static constexpr uint32_t strides[] = { sizeof(glm::vec3) };
247 context->setVertexBuffers(&vb, 1, strides, nullptr);
248
249 static constexpr glm::mat4 world = glm::mat4(1.0f);
250
251 if (HandleIsValid(constantBuffer)) {
252 {
253 MappedBuffer<DebugConstants> constants(context, constantBuffer, MapMode::WriteDiscard);
254 if (constants) {
255 constants->projectionMatrix = cameraData.projectionMatrix;
256 constants->viewMatrix = cameraData.viewMatrix;
257 constants->worldMatrix = world;
258 constants->diffuseColor = diffuseColor;
259 }
260 else {
261 LOG_ERROR_ONCE(logger, "MappedBuffer<DebugConstants> for Camera fail");
262 }
263 }
264 context->setConstantBuffer("DebugBuffer", constantBuffer);
265 }
266 else {
267 assert(false);
268 }
269
270 context->drawIndexed(PrimitiveType::LineList, 0, std::size(indexesCamera));
271
272 buffers->releaseIndexBuffer(ib);
273 buffers->releaseVertexBuffer(vb);
274}
Container for components, providing composition of dynamic entities.
Definition: Entity.h:18
constexpr size_t getId() const noexcept
Get the unique identifier of this entity.
Definition: Entity.h:113
Represents a graphics device used to manage graphics resources and issue drawing commands.
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.
Log implementation class.
Definition: LogManager.h:139
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
@ Perspective
Perspective projection.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ WebGPU
Graphics device using the WebGPU API Backend.
@ VertexData
Per vertex data.
@ 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
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
Provides buffer management functionality.
Definition: IBuffers.h:13
virtual void releaseVertexBuffer(VertexBufferHandle vertexBufferHandle)=0
Release the vertex buffer with the given handle.
virtual InputLayoutHandle loadInputLayout(const VertexFormatHandle *vertexFormats, const size_t count, EffectHandle effectHandle)=0
Loads a new input layout to map vertex flow between vertex buffers with the given vertexFormats to ef...
virtual IndexBufferHandle loadIndexBuffer(const void *indexData, const size_t count, const size_t indexSize)=0
Loads a new index buffer and populates it with the given indexData.
virtual void releaseIndexBuffer(IndexBufferHandle indexBufferHandle)=0
Releases the index buffer with the given handle.
virtual VertexBufferHandle loadVertexBuffer(const void *vertexData, const size_t count, const VertexFormat &vertexFormat)=0
Loads a new vertex buffer and populates it with the given data.
Represents a graphics device context which can receive rendering commands.
Definition: IContext.h:43
virtual void drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex=0)=0
Draws indexed, non-instanced primitives.
virtual void setRasterizerState(const RasterizerStateHandle handle)=0
Set the current rasterizer state.
virtual void setBlendState(const BlendStateHandle handle, const float *constant=nullptr)=0
Set the current blend state.
virtual void setInputLayout(const InputLayoutHandle inputLayoutHandle)=0
Sets the current input layout.
virtual void setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride=4, uint32_t offset=0)=0
Sets the current index buffer.
virtual void setDepthStencilState(const DepthStencilStateHandle handle)=0
Set the current depth stencil state.
virtual void setConstantBuffer(const StringView &name, const BufferHandle bufferHandle, const uint32_t offset=0, const uint32_t size=~0u)=0
Sets a constant buffer to be bound to the given name and slot.
virtual void setViewport(const float x, const float y, const float width, const float height)=0
Sets the current viewport to the given location and dimensions.
virtual void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets)=0
Sets the current vertex buffers.
virtual void setEffect(EffectHandle handle)=0
Set the current effect.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Definition: Flags.h:103
@ LineList
List of lines.
Definition: Common.h:120
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30