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#include "Rendering/IEffects.h"
22
23#include "Foundation/Logging/Logger.h"
24
25#include <glm/glm.hpp>
26#include <array>
27#include <cassert>
28
29namespace
30{
31 const Cogs::Logging::Log logger = Cogs::Logging::getLogger("EditorRenderTask");
32
33 struct DebugConstants
34 {
35 glm::mat4 projectionMatrix;
36 glm::mat4 viewMatrix;
37 glm::mat4 worldMatrix;
38 glm::vec4 diffuseColor;
39 };
40
41 static constexpr uint16_t indexesEntity[] = {
42 0, 1, 0, 2, 0, 4,
43 1, 3, 1, 5,
44 2, 3, 2, 6,
45 3, 7,
46 4, 5, 4, 6,
47 5, 7,
48 6, 7
49 };
50}
51
52void Cogs::Core::EditorRenderTask::init(const ViewContext* viewContext, IGraphicsDevice * device)
53{
54 this->viewContext = viewContext;
55 Cogs::IBuffers* buffers = device->getBuffers();
56
58 .name = "EditorEffect",
59 .flags = viewContext->getContext()->renderer->getEffectFlags(),
61 };
62
63 switch (device->getType()) {
65 desc.vertexShader = "Engine/DebugVS.wgsl";
66 desc.pixelShader = "Engine/DebugPS.wgsl";
67 desc.vsEntryPoint = "vs_main";
68 desc.psEntryPoint = "fs_main";
69 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::WGSL);
70 break;
72 desc.vertexShader = "Engine/DebugVS.es30.glsl";
73 desc.pixelShader = "Engine/DebugPS.es30.glsl";
74 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::GLSL);
75 break;
76 default:
77 desc.vertexShader = "Engine/DebugVS.hlsl";
78 desc.pixelShader = "Engine/DebugPS.hlsl";
79 break;
80 }
81 effectHandle = device->getEffects()->loadEffect(desc);
82
83 static constexpr VertexElement elements[] = {
84 { 0, DataFormat::X32Y32Z32_FLOAT, ElementSemantic::Position, 0, InputType::VertexData, 0 }
85 };
86 vertexFormat = buffers->createVertexFormat(elements, 1);
87
88 constantBuffer = device->getBuffers()->loadBuffer(nullptr, sizeof(DebugConstants), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
89 device->getBuffers()->annotate(constantBuffer, "SelectedBounds");
90}
91
93{
94 Cogs::IEffects* effects = context->device->getEffects();
95 Cogs::ResourceStatus status = effects->checkEffect(effectHandle);
96
97 if (status == Cogs::ResourceStatus::Ready && effectStatus != Cogs::ResourceStatus::Ready) {
98 Cogs::IBuffers* buffers = context->device->getBuffers();
99 inputLayoutHandle = buffers->loadInputLayout(&vertexFormat, 1, effectHandle);
100 }
101
102 if (status == Cogs::ResourceStatus::Error && effectStatus != Cogs::ResourceStatus::Error) {
103 LOG_ERROR(logger, "EditorRenderTask: Failed to build editor debug effect.");
104 }
105
106 effectStatus = status;
107 return status;
108}
109
110void Cogs::Core::EditorRenderTask::apply(RenderTaskContext * renderContext)
111{
112 IEditor* editor = renderContext->context->engine->getEditor();
113
114 if (!editor->isActive()) return;
115
116 assert(effectStatus == Cogs::ResourceStatus::Ready);
117
118 EditorState* state = editor->getState();
119 std::string erasedSelections = state->eraseInvalidSelected();
120 if (!erasedSelections.empty()) {
121 LOG_WARNING(logger, "Removed selection of invalid entities (Asset temp Entities?): %s", erasedSelections.data());
122 }
123
124 Renderer* renderer = renderContext->renderer;
125 Cogs::IGraphicsDevice* device = renderer->getDevice();
126 Cogs::IContext* context = device->getImmediateContext();
127 const RenderStates& renderStates = renderer->getRenderStates();
128
129 context->setEffect(effectHandle);
130
131 context->setRasterizerState(renderStates.defaultRasterizerStateHandle);
132 context->setDepthStencilState(renderStates.commonDepthStates[RenderStates::noWriteDepthStencilState]);
133 context->setBlendState(renderStates.blendStates[size_t(BlendMode::None)].handle);
134
135 const CameraData& cameraData = renderContext->context->cameraSystem->getMainCameraData();
136
137 Cogs::IBuffers* buffers = device->getBuffers();
138 context->setInputLayout(inputLayoutHandle);
139
140 context->setViewport(cameraData.viewportOrigin.x, cameraData.viewportOrigin.y, cameraData.viewportSize.x, cameraData.viewportSize.y);
141
142
143 // Render selected Cameras. No use rendering View Camera as bounds not visible.
144 if (renderContext->context->cameraSystem->pool.size() > 1) {
145 for (const CameraComponent& cameraComponent : renderContext->context->cameraSystem->pool) {
146 const Entity* entity = cameraComponent.getContainer();
147
148 if (cameraComponent.projectionMode != ProjectionMode::Perspective) continue;
149 if (!state->isSelected(entity->getId())) continue;
150 if (entity == viewContext->getCamera().get()) continue;
151
152 glm::vec4 diffuseColor(0.0f, 0.8f, 0.1f, 1.0f);
153 renderCamera(renderContext, cameraComponent, diffuseColor);
154 }
155 }
156
157
158 // Draw Bounds for selected entities:
159 if (!state->selected.empty()) {
160
161 const std::array positions = {
162 glm::vec3(-1, -1, -1),
163 glm::vec3(1, -1, -1),
164 glm::vec3(-1, 1, -1),
165 glm::vec3(1, 1, -1),
166
167 glm::vec3(-1, -1, 1),
168 glm::vec3(1, -1, 1),
169 glm::vec3(-1, 1, 1),
170 glm::vec3(1, 1, 1),
171 };
172
173 auto ib = buffers->loadIndexBuffer(indexesEntity, std::size(indexesEntity), sizeof(indexesEntity[0]));
174 auto vb = buffers->loadVertexBuffer(positions.data(), positions.size(), VertexFormats::Pos3f);
175
176 context->setIndexBuffer(ib, sizeof(indexesEntity[0]));
177 static constexpr uint32_t strides[] = { sizeof(glm::vec3) };
178 context->setVertexBuffers(&vb, 1, strides, nullptr);
179
180 glm::vec4 boxColor(0.8f, 0.7f, 0.2f, 1.0f);
181
182 for (EntityId id : state->selected) {
183 renderEntity(renderContext, id, boxColor);
184 }
185
186 buffers->releaseIndexBuffer(ib);
187 buffers->releaseVertexBuffer(vb);
188 }
189}
190
191void Cogs::Core::EditorRenderTask::renderEntity(RenderTaskContext* renderContext, const EntityId id, glm::vec4 diffuseColor)
192{
193 Renderer* renderer = renderContext->renderer;
194 Cogs::IGraphicsDevice* device = renderer->getDevice();
195 Cogs::IContext* context = device->getImmediateContext();
196 const CameraData& cameraData = renderContext->context->cameraSystem->getMainCameraData();
197
198 Geometry::BoundingBox bounds = Bounds::getBounds(renderContext->context, id, true);
199 if (bounds.empty()) {
200 return;
201 }
202
203 glm::vec3 center = bounds.getCenter();
204 glm::vec3 scale = 0.5f * bounds.getExtent();
205
206 glm::mat4 world = glm::translate(glm::mat4(1.0f), center) * glm::scale(glm::mat4(1.0f), scale);
207
208 if (HandleIsValid(constantBuffer)) {
209 {
210 MappedBuffer<DebugConstants> constants(context, constantBuffer, MapMode::WriteDiscard);
211 if (constants) {
212 constants->projectionMatrix = cameraData.projectionMatrix;
213 constants->viewMatrix = cameraData.viewMatrix;
214 constants->worldMatrix = world;
215 constants->diffuseColor = diffuseColor;
216 }
217 }
218 context->setConstantBuffer("DebugBuffer", constantBuffer);
219 }
220 else {
221 assert(false);
222 }
223
224 context->drawIndexed(PrimitiveType::LineList, 0, std::size(indexesEntity));
225}
226
227void Cogs::Core::EditorRenderTask::renderCamera(RenderTaskContext* renderContext, const CameraComponent& cameraComponent, glm::vec4 diffuseColor)
228{
229 Renderer* renderer = renderContext->renderer;
230 Cogs::IGraphicsDevice* device = renderer->getDevice();
231 Cogs::IContext* context = device->getImmediateContext();
232 Cogs::IBuffers* buffers = device->getBuffers();
233 const CameraData& cameraData = renderContext->context->cameraSystem->getMainCameraData();
234
235 const std::array<glm::vec4, 8U> positionsClip = {
236 glm::vec4(-1, -1, 0, 1),
237 glm::vec4(1, -1, 0, 1),
238 glm::vec4(1, 1, 0, 1),
239 glm::vec4(-1, 1, 0, 1),
240
241 glm::vec4(-1, -1, 1, 1),
242 glm::vec4(1, -1, 1, 1),
243 glm::vec4(1, 1, 1, 1),
244 glm::vec4(-1, 1, 1, 1),
245 };
246
247 std::array<glm::vec3, positionsClip.size()> positionsWS;
248 const CameraData& cData = renderContext->context->cameraSystem->getData(&cameraComponent);
249
250 for (size_t i = 0; i < positionsWS.size(); ++i) {
251 glm::vec4 posWS = cData.inverseViewProjectionMatrix * positionsClip[i];
252 posWS /= posWS.w;
253
254 positionsWS[i] = glm::vec3(posWS);
255 }
256
257 static constexpr uint16_t indexesCamera[] = {
258 0, 1, 1, 2, 2, 3, 3, 0,
259 4, 5, 5, 6, 6, 7, 7, 4,
260 0, 4, 1, 5, 2, 6, 3, 7
261 };
262
263 auto ib = buffers->loadIndexBuffer(indexesCamera, std::size(indexesCamera), sizeof(indexesCamera[0]));
264 auto vb = buffers->loadVertexBuffer(positionsWS.data(), positionsWS.size(), VertexFormats::Pos3f);
265
266 context->setIndexBuffer(ib, sizeof(indexesCamera[0]));
267 static constexpr uint32_t strides[] = { sizeof(glm::vec3) };
268 context->setVertexBuffers(&vb, 1, strides, nullptr);
269
270 const glm::mat4 world = glm::mat4(1.0f);
271
272 if (HandleIsValid(constantBuffer)) {
273 {
274 MappedBuffer<DebugConstants> constants(context, constantBuffer, MapMode::WriteDiscard);
275 if (constants) {
276 constants->projectionMatrix = cameraData.projectionMatrix;
277 constants->viewMatrix = cameraData.viewMatrix;
278 constants->worldMatrix = world;
279 constants->diffuseColor = diffuseColor;
280 }
281 else {
282 LOG_ERROR_ONCE(logger, "MappedBuffer<DebugConstants> for Camera fail");
283 }
284 }
285 context->setConstantBuffer("DebugBuffer", constantBuffer);
286 }
287 else {
288 assert(false);
289 }
290
291 context->drawIndexed(PrimitiveType::LineList, 0, std::size(indexesCamera));
292
293 buffers->releaseIndexBuffer(ib);
294 buffers->releaseVertexBuffer(vb);
295}
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
std::unique_ptr< class Engine > engine
Engine instance.
Definition: Context.h:222
Cogs::ResourceStatus checkReady(RenderTaskContext *context) override
Check if the task is ready to be applied, e.g.
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.
Log implementation class.
Definition: LogManager.h:140
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:181
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ WebGPU
Graphics device using the WebGPU API Backend.
ResourceStatus
Status of an asynchronously loaded resource, such as an effect or a pipeline.
Definition: Common.h:198
@ Error
The resource failed to load.
@ Ready
The resource has loaded successfully and is ready for use.
@ 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
std::string eraseInvalidSelected()
Definition: EditorState.h:161
Contains an effect description used to load a single effect.
Definition: IEffects.h:62
EEffectFlags
Effect source flags.
Definition: IEffects.h:27
@ WGSL
Effect source is WGSL.
Definition: IEffects.h:43
@ GLSL
Effect source is GLSL.
Definition: IEffects.h:33
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 setRasterizerState(const RasterizerStateHandle handle)=0
Set the current rasterizer state.
virtual void drawIndexed(PrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex=0)=0
Draws indexed, non-instanced primitives.
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.
Provides effects and shader management functionality.
Definition: IEffects.h:158
virtual ResourceStatus checkEffect(EffectHandle effectHandle)=0
Check the load status of the effect with the given effectHandle.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Definition: Flags.h:103
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30