Cogs.Core
BoundsRenderer.cpp
1#include "BoundsRenderer.h"
2
3#include "Rendering/ICapabilities.h"
4#include "Rendering/IContext.h"
5#include "Rendering/IBuffers.h"
6#include "Rendering/IEffects.h"
7
8#include "Foundation/Logging/Logger.h"
9
10#include "Context.h"
11
12#include "Renderer/IRenderer.h"
13
14#include "Resources/VertexFormats.h"
15#include "Resources/DefaultMaterial.h"
16#include "Resources/Mesh.h"
17
18#include "Systems/Core/CameraSystem.h"
19#include "Systems/Core/TransformSystem.h"
20
21#include "Scene/GetBounds.h"
22
23#include <glm/vec3.hpp>
24#include <glm/vec4.hpp>
25#include <glm/mat4x4.hpp>
26#include <glm/ext/matrix_transform.hpp>
27#include <iterator>
28
29using namespace Cogs::Geometry;
30
31namespace{
32 const Cogs::Logging::Log logger = Cogs::Logging::getLogger("BoundsRenderer");
33
34 struct DebugConstants
35 {
36 glm::mat4 projectionMatrix;
37 glm::mat4 viewMatrix;
38 glm::mat4 worldMatrix;
39 glm::vec4 diffuseColor;
40 };
41
42 const uint16_t indexes[] = {
43 0, 1, 0, 2, 0, 4,
44 1, 3, 1, 5,
45 2, 3, 2, 6,
46 3, 7,
47 4, 5, 4, 6,
48 5, 7,
49 6, 7
50 };
51
52 const glm::vec3 positions[] = {
53 glm::vec3(-1, -1, -1),
54 glm::vec3(1, -1, -1),
55 glm::vec3(-1, 1, -1),
56 glm::vec3(1, 1, -1),
57
58 glm::vec3(-1, -1, 1),
59 glm::vec3(1, -1, 1),
60 glm::vec3(-1, 1, 1),
61 glm::vec3(1, 1, 1),
62 };
63}
64
65void Cogs::Core::BoundsRenderer::initialize(class IRenderer* renderer, IGraphicsDevice * device)
66{
67 auto buffers = device->getBuffers();
68
70 desc.name = "DebugEffect";
71 desc.flags = renderer->getEffectFlags();
73 switch (device->getType()) {
75 desc.vertexShader = "Engine/DebugVS.wgsl";
76 desc.pixelShader = "Engine/DebugPS.wgsl";
77 desc.vsEntryPoint = "vs_main";
78 desc.psEntryPoint = "fs_main";
79 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::WGSL);
80 break;
82 desc.vertexShader = "Engine/DebugVS.es30.glsl";
83 desc.pixelShader = "Engine/DebugPS.es30.glsl";
84 desc.flags = static_cast<EffectFlags::EEffectFlags>(desc.flags | EffectFlags::GLSL);
85 break;
86 default:
87 desc.vertexShader = "Engine/DebugVS.hlsl";
88 desc.pixelShader = "Engine/DebugPS.hlsl";
89 break;
90 }
91 effectHandle = device->getEffects()->loadEffect(desc);
92
93 VertexElement elements[] = {
94 { 0, DataFormat::X32Y32Z32_FLOAT, ElementSemantic::Position, 0, InputType::VertexData, 0 }
95 };
96 vertexFormat = buffers->createVertexFormat(elements, 1);
97
98 constantBuffer = device->getBuffers()->loadBuffer(nullptr, sizeof(DebugConstants), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
99 device->getBuffers()->annotate(constantBuffer, "BoundsConstants");
100}
101void Cogs::Core::BoundsRenderer::renderBounds(class IRenderer * renderer, class Context* mainContext, const RenderList & renderList)
102{
103 auto device = renderer->getDevice();
104 auto context = device->getImmediateContext();
105 auto & renderStates = renderer->getRenderStates();
106
107 Cogs::IEffects * effects = device->getEffects();
108 Cogs::ResourceStatus status = HandleIsValid(effectHandle) ? effects->checkEffect(effectHandle) : Cogs::ResourceStatus::Error;
109
110 if (status == Cogs::ResourceStatus::Ready && effectStatus != Cogs::ResourceStatus::Ready) {
111 inputLayoutHandle = device->getBuffers()->loadInputLayout(&vertexFormat, 1, effectHandle);
112 }
113
114 if (status == Cogs::ResourceStatus::Error && effectStatus != Cogs::ResourceStatus::Error) {
115 LOG_ERROR(logger, "BoundsRenderer: Invalid debug effect handle.");
116 }
117
118 effectStatus = status;
119
120 if (effectStatus != Cogs::ResourceStatus::Ready) {
121 return;
122 }
123
124 context->setEffect(effectHandle);
125
126 context->setRasterizerState(renderStates.defaultRasterizerStateHandle);
127 context->setDepthStencilState(renderStates.commonDepthStates[RenderStates::noWriteDepthStencilState]);
128 context->setBlendState(renderStates.blendStates[size_t(BlendMode::None)].handle);
129
130 auto ib = device->getBuffers()->loadIndexBuffer(indexes, sizeof(indexes) / sizeof(uint16_t), sizeof(uint16_t));
131 auto vb = device->getBuffers()->loadVertexBuffer(positions, sizeof(positions) / sizeof(glm::vec3), VertexFormats::Pos3f);
132
133 context->setInputLayout(inputLayoutHandle);
134 context->setIndexBuffer(ib, 2);
135 uint32_t strides[] = { sizeof(glm::vec3) };
136 context->setVertexBuffers(&vb, 1, strides, nullptr);
137
138 auto & cameraData = mainContext->cameraSystem->getMainCameraData();
139
140 for (auto & renderItem : renderList) {
141 if (renderItem.layer == RenderLayers::Sky) continue;
142 if (renderItem.isSprite()) continue;
143
144 Geometry::BoundingBox bbox;
145
146 if (renderItem.hasBoundingBox()) {
147 bbox = *renderItem.boundingBox;
148 } else {
149 if (renderItem.cullingIndex == static_cast<uint32_t>(-1)) continue;
150
151 assert(renderItem.cullingIndex < cameraData.cullingData->source->bbMinWorld.size() && "Bounds index out of range.");
152 bbox = {
153 cameraData.cullingData->source->bbMinWorld[renderItem.cullingIndex],
154 cameraData.cullingData->source->bbMaxWorld[renderItem.cullingIndex]
155 };
156 }
157
158 auto center = (bbox.max + bbox.min) * 0.5f;
159 auto scale = 0.5f * glm::vec3(
160 bbox.max.x - bbox.min.x,
161 bbox.max.y - bbox.min.y,
162 bbox.max.z - bbox.min.z);
163
164 glm::mat4 world = glm::translate(glm::mat4(1.0f), center) * glm::scale(glm::mat4(1.0f), scale);
165 glm::vec4 diffuseColor = glm::vec4(0.4f, 1.0f, 0.2f, 1.0f);
166 if (renderItem.materialInstance->isDefaultMaterial()) {
167 diffuseColor = renderItem.materialInstance->getVec4Property(DefaultMaterial::DiffuseColor);
168 diffuseColor.a = 1.0f;
169 }
170
171 if (HandleIsValid(constantBuffer)) {
172 {
173 MappedBuffer<DebugConstants> constants(context, constantBuffer, MapMode::WriteDiscard);
174
175 if (constants) {
176 constants->projectionMatrix = cameraData.projectionMatrix;
177 constants->viewMatrix = cameraData.viewMatrix;
178 constants->worldMatrix = world;
179 constants->diffuseColor = diffuseColor;
180 }
181 }
182 context->setConstantBuffer("DebugBuffer", constantBuffer);
183 }
184 else{
185 assert(false);
186 }
187
188 context->drawIndexed(PrimitiveType::LineList, 0, std::size(indexes));
189
190 if (renderItem.isInstanced() && renderItem.numInstances < 10000) {
191 auto instanceMesh = renderItem.instanceData;
192 const auto & instanceBounds = renderItem.meshData->getMesh()->boundingBox;
193
194 //TODO/FIXME: Use stream slots to help figure out which data may be position/color data.
195 auto[pPos, pCount, pStride] = instanceMesh->getMesh()->getSemanticStream(ElementSemantic::InstanceVector, DataFormat::X32Y32Z32_FLOAT);
196 auto[cColor, cCount, cStride] = instanceMesh->getMesh()->getSemanticStream(ElementSemantic::InstanceVector, DataFormat::X32Y32Z32W32_FLOAT);
197
198 if (!isEmpty(instanceBounds) && pPos && pCount >= renderItem.numInstances) {
199 auto instanceCenter = (instanceBounds.min + instanceBounds.max) * 0.5f;
200 auto instanceScale = 0.5f * glm::vec3(
201 instanceBounds.max.x - instanceBounds.min.x,
202 instanceBounds.max.y - instanceBounds.min.y,
203 instanceBounds.max.z - instanceBounds.min.z);
204
205 const auto worldMatrix = renderItem.worldMatrix ? *renderItem.worldMatrix : glm::mat4(1.0f);
206
207 for (size_t i = 0; i < renderItem.numInstances; ++i) {
208 const glm::vec3 & instancePosition = *reinterpret_cast<const glm::vec3 *>(pPos + pStride * (renderItem.startInstance + i));
209 const glm::mat4 instanceTransform = worldMatrix * glm::translate(glm::mat4(1.0f), instanceCenter + instancePosition) * glm::scale(glm::mat4(1.0f), instanceScale);
210
211 glm::vec4 col;
212 if (cColor && cCount >= renderItem.numInstances) {
213 const float *color = reinterpret_cast<const float *>(cColor + cStride * i);
214 col = glm::vec4(color[0], color[1], color[2], color[3]);
215 } else {
216 col = diffuseColor;
217 }
218
219 if (HandleIsValid(constantBuffer)) {
220 {
221 MappedBuffer<DebugConstants> constants(context, constantBuffer, MapMode::WriteDiscard);
222
223 if (constants) {
224 constants->projectionMatrix = cameraData.projectionMatrix;
225 constants->viewMatrix = cameraData.viewMatrix;
226 constants->worldMatrix = instanceTransform;
227 constants->diffuseColor = col;
228 }
229 }
230 context->setConstantBuffer("DebugBuffer", constantBuffer);
231 }
232 else{
233 assert(false);
234 }
235
236 context->drawIndexed(PrimitiveType::LineList, 0, std::size(indexes));
237 }
238 }
239 }
240 }
241
242 device->getBuffers()->releaseIndexBuffer(ib);
243 device->getBuffers()->releaseVertexBuffer(vb);
244}
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.
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.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
Contains geometry calculations and generation.
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.
@ InstanceVector
Instance vector 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: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
virtual void releaseVertexBuffer(VertexBufferHandle vertexBufferHandle)=0
Release the vertex buffer with the given handle.
virtual void annotate(BufferHandle handle, const StringView &name)
Associate a name with an object for use in graphics debugging.
Definition: IBuffers.h:17
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 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 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.
Provides effects and shader management functionality.
Definition: IEffects.h:158
virtual EffectHandle loadEffect(const EffectDescription &description)=0
Load an effect from the given description.
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
Provides RAII style mapping of a buffer resource.
Definition: IBuffers.h:160
@ 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