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