1#include "GenerateListTask.h"
4#include "EntityStore.h"
6#include "Components/Core/RenderComponent.h"
8#include "Foundation/ComponentModel/Entity.h"
9#include "Foundation/Logging/Logger.h"
11#include "Rendering/ICapabilities.h"
12#include "Rendering/IBuffers.h"
14#include "Renderer/Renderer.h"
15#include "Renderer/RenderResources.h"
16#include "Renderer/RenderStateUpdater.h"
17#include "Renderer/CustomRenderer/DebugGeometryRenderers.h"
19#include "Resources/MaterialManager.h"
20#include "Resources/Mesh.h"
22#include "Services/Services.h"
23#include "Services/Variables.h"
24#include "Services/PipelineService.h"
26#include "Systems/Core/MeshSystem.h"
27#include "Systems/Core/RenderSystem.h"
28#include "Systems/Core/SubMeshRenderSystem.h"
29#include "Systems/Core/InstancedMeshRenderSystem.h"
30#include "Systems/Core/SpriteRenderSystem.h"
31#include "Systems/Core/AnimationSystem.h"
32#include "Systems/Core/StaticModelSystem.h"
33#include "Systems/Core/LightSystem.h"
34#include "Systems/Core/CameraSystem.h"
35#include "Systems/Core/ClipShapeSystem.h"
40#pragma warning(disable: 4127)
41#include <glm/ext/matrix_clip_space.hpp>
45#include <glm/gtx/transform.hpp>
51 constexpr uint32_t minObjectBufferCapacity = 1024;
58 if (instance->masterInstance && ((instance->masterInstance->getMaterialFlags() & overrideFlag) == overrideFlag)) {
65 void getTransparencyState(RenderStates & ,
const MaterialInstance * materialInstance, RenderItem & renderItem)
68 const auto hasTransparency = instance->hasTransparency();
69 auto blendMode = instance->options.blendMode;
73 renderItem.blendState = (uint16_t)blendMode;
76 RenderItemFlags getMaterialFlags(
const MaterialInstance * materialInstance)
78 RenderItemFlags flags = RenderItemFlags::None;
79 flags |= (materialInstance->instanceFlags &
MaterialFlags::CustomBucket) != 0 ? RenderItemFlags::CustomBucket : RenderItemFlags::None;
80 flags |= materialInstance->hasTransparency() ? RenderItemFlags::Transparent : RenderItemFlags::None;
81 flags |= materialInstance->isBackdrop() ? RenderItemFlags::Backdrop : RenderItemFlags::None;
86uint8_t Cogs::Core::ClipShapeCache::getIndex(Context* context, ComponentModel::ComponentHandle clipShapeHandle)
91 for (
size_t i = 1; i < count; i++) {
92 if (handles[i] == clipShapeHandle) {
93 return static_cast<uint8_t
>(i);
98 if (ClipShapeComponent* clipComp = clipShapeHandle.resolveComponent<ClipShapeComponent>(); clipComp) {
99 const ClipShapeData& clipData = context->clipShapeSystem->getData(clipComp);
101 switch (clipData.shape) {
106 if (count < ClipShapeCache::maxClipShapes) {
107 handles[count] = clipShapeHandle;
117 .clipShape = clipData.shape
119 return static_cast<uint8_t
>(count++);
123 assert(
false &&
"Invalid enum");
125 LOG_ERROR_ONCE(logger,
"Exceeding max number of clip shapes");
131Cogs::Core::RenderItem& Cogs::Core::GenerateListTask::createRenderItem(Context* context, RenderBatch& batch,
const glm::mat4* localToWorld,
const RenderComponent* renderComponent)
133 if (renderComponent && (renderComponent->layer&RenderLayers::AllReserved)!=0) {
134 LOG_WARNING_ONCE(logger,
"Using a reserved RenderLayer (Consider switching to RenderLayer::Custom).");
137 RenderItem& item = batch.alloc();
139 item.cullingIndex = (uint32_t)-1;
141 item.worldMatrix = localToWorld;
143 item.flags = RenderItemFlags::None;
145 const uint32_t objectId = renderComponent ? renderComponent->objectId : NoObjectId;
147 if (listObjectBuffer.isInUse()) {
149 if (listObjectBuffer.cpuCapacity == listObjectBuffer.fill) {
150 listObjectBuffer.cpuCapacity = std::max(minObjectBufferCapacity,
151 listObjectBuffer.cpuCapacity + std::min(1024u * 16u, listObjectBuffer.cpuCapacity / 2));
152 listObjectBuffer.cpu.resize(
size_t(listObjectBuffer.stride) * listObjectBuffer.cpuCapacity);
155 item.flags |= RenderItemFlags::ObjectBufferSlot;
156 item.objectBufferSlot = listObjectBuffer.fill++;
158 ObjectBuffer* objectBuffer =
reinterpret_cast<ObjectBuffer*
>((uint8_t*)(listObjectBuffer.cpu.data()) +
size_t(listObjectBuffer.stride) * item.objectBufferSlot);
160 objectBuffer->encodeWorldMatrix(*localToWorld);
162 objectBuffer->encodeObjectId(objectId);
165 item.objectId = objectId;
168 if (renderComponent) {
169 ComponentModel::ComponentHandle clipShapeHandle = renderComponent->clipShapeComponent;
171 item.clipShapeIx = clipShapeCache.getIndex(context, clipShapeHandle);
177size_t Cogs::Core::GenerateListTask::generateItems(Context* context, RenderBatch& batch, Renderer* renderer, RenderSystem* renderSystem, MeshSystem* )
180 for (
const auto& renderComponent : renderSystem->pool) {
181 if (!renderComponent.isVisible())
continue;
183 auto& renderData = renderSystem->getData<MeshRenderData>(&renderComponent);
185 const MeshComponent* meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
186 if (meshComponent ==
nullptr) {
187 LOG_ERROR_ONCE(logger,
"No mesh component defined");
191 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
198 Mesh * mesh = meshComponent->meshHandle.resolve();
200 MaterialInstance * materialInstance = renderComponent.material.resolve();
202 if (!materialInstance) {
207 RenderItem& renderBlock = createRenderItem(context, batch, &renderData.localToWorld, &renderComponent);
208 renderBlock.lod = renderComponent.lod;
209 renderBlock.layer = renderComponent.layer;
210 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
212 if (renderComponent.disableCulling()) {
213 renderBlock.flags |= RenderItemFlags::DisableCulling;
216 renderBlock.cullingIndex = renderData.cullingIndex;
219 renderBlock.meshData = renderMesh;
221 const uint32_t meshCount = mesh->getCount();
223 if (renderComponent.vertexCount == uint32_t(-1)) {
224 renderBlock.startIndex = 0;
225 renderBlock.numIndexes = meshCount;
228 renderBlock.startIndex = renderComponent.startIndex;
229 renderBlock.numIndexes = renderComponent.vertexCount;
230 if (meshCount <= renderBlock.startIndex || meshCount < renderBlock.startIndex + renderBlock.numIndexes) {
231 LOG_ERROR_ONCE(logger,
"RenderComponent draw range is out of bounds");
235 renderBlock.primitiveType = renderComponent.primitiveType != (
PrimitiveType)-1 ? renderComponent.primitiveType : mesh->primitiveType;
238 renderBlock.flags |= RenderItemFlags::Instanced;
239 renderBlock.numIndexes = mesh->getCount();
240 renderBlock.numInstances = mesh->getInstanceCount();
243 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
244 const AnimationComponent* animationComponent = renderComponent.getComponent<AnimationComponent>();
245 if (animationComponent ==
nullptr) {
246 LOG_ERROR_ONCE(logger,
"No animation component defined");
249 const AnimationData& animationData = context->animationSystem->getData(animationComponent);
250 renderBlock.poseData = animationData.pose.get();
253 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
254 renderBlock.flags |= getMaterialFlags(materialInstance);
255 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
257 renderBlock.materialInstance = materialInstance;
259 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
260 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
266void Cogs::Core::GenerateListTask::initialize(RenderTaskContext* renderContext)
268 RenderTask::initialize(renderContext);
271void Cogs::Core::GenerateListTask::cleanup(RenderTaskContext* renderContext)
274 IBuffers* buffers = renderContext->device->getBuffers();
275 buffers->releaseBuffer(listObjectBuffer.gpu);
280void Cogs::Core::GenerateListTask::apply(RenderTaskContext * renderTaskContext)
282 RenderInstrumentationScope(renderTaskContext->device->getImmediateContext(), SCOPE_RENDERING,
"GenerateListTask::apply");
285 clipShapeCache.data[0] = ClipShapeCache::Item{
288 clipShapeCache.count = 1;
290 auto & renderList = *output.get(RenderResourceType::RenderList)->renderList;
292 auto context = renderTaskContext->context;
293 auto renderer = renderTaskContext->renderer;
295 ICapabilities* caps = renderTaskContext->device->getCapabilities();
298 bool useArrayObjectBuffer =
false;
299 const StringView arrayObjectBufferKey =
"renderer.arrayObjectBuffer";
301 useArrayObjectBuffer =
true;
303 if (Variable* var = context->variables->get(arrayObjectBufferKey); !var->isEmpty()) {
304 useArrayObjectBuffer = var->getBool();
307 context->variables->set(arrayObjectBufferKey, useArrayObjectBuffer);
310 LOG_WARNING(logger,
"Only WebGPU supports renderer.arrayObjectBuffer. Base instance support lacking in other backends.");
311 context->variables->set(arrayObjectBufferKey,
false);
312 useArrayObjectBuffer =
false;
316 bool useListObjectBuffer =
false;
317 const StringView listObjectBufferKey =
"renderer.listObjectBuffer";
318 if (Variable* var = context->variables->get(listObjectBufferKey); !var->isEmpty()) {
319 useListObjectBuffer = var->getBool();
322 context->variables->set(listObjectBufferKey, useListObjectBuffer);
324 if(useArrayObjectBuffer) useListObjectBuffer =
false;
325 if (useListObjectBuffer && caps->getDeviceCapabilities().ConstantBufferRange) {
326 listObjectBuffer.stride = std::max(uint32_t(
sizeof(ObjectBuffer)), uint32_t(caps->getDeviceCapabilities().ConstantBufferOffsetAlignment));
329 listObjectBuffer.stride = 0;
331 listObjectBuffer.fill = 0;
334 generateItems(context, renderList.batch, renderer, context->renderSystem, context->meshSystem);
336 for (
auto & staticModel : context->staticModelSystem->pool) {
337 if (!staticModel.model)
continue;
339 auto renderSystem = context->staticModelSystem->getRenderSystem(&staticModel);
340 auto meshSystem = context->staticModelSystem->getMeshSystem(&staticModel);
342 if (!renderSystem || !renderSystem->pool.size())
continue;
344 auto batch = context->staticModelSystem->getRenderBatch(&staticModel);
346 if (batch->generation != renderSystem->getGeneration()) {
348 auto missing = generateItems(context, *batch, renderer, renderSystem, meshSystem);
349 batch->missing = missing;
350 batch->generation = renderSystem->getGeneration();
353 renderList.batches.emplace_back(batch);
356 for (
const SubMeshRenderComponent& renderComponent : context->subMeshRenderSystem->pool) {
357 if (!renderComponent.isVisible())
continue;
359 auto & renderData = context->subMeshRenderSystem->getData<SubMeshRenderData>(&renderComponent);
361 const MeshComponent* meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
362 if (meshComponent ==
nullptr) {
363 LOG_ERROR_ONCE(logger,
"No mesh component defined");
367 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
369 if (!renderMesh)
continue;
371 Mesh * mesh = meshComponent->meshHandle.resolve();
372 const uint32_t meshCount = mesh->getCount();
374 size_t subMeshBegin = 0;
375 size_t subMeshEnd = mesh->getSubMeshes().size();
377 if ((0 <= renderComponent.subMesh) && (
static_cast<size_t>(renderComponent.subMesh) < subMeshEnd)) {
378 subMeshBegin = renderComponent.subMesh;
379 subMeshEnd = subMeshBegin + 1;
382 for (
size_t m = subMeshBegin; m < subMeshEnd; ++m) {
383 auto & subMesh = mesh->getSubMeshes()[m];
385 if (subMesh.numIndexes && renderMesh->streamsLayout.numStreams) {
386 auto materialInstance = ((renderComponent.materials.size() > m) ? renderComponent.materials[m] : renderComponent.materials.front()).resolve();
388 if (!materialInstance)
continue;
390 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &renderData.localToWorld, &renderComponent);
391 renderBlock.lod = renderComponent.lod;
392 renderBlock.layer = renderComponent.layer;
393 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
395 renderBlock.cullingIndex = renderData.cullingIndex;
397 renderBlock.meshData = renderMesh;
398 if (subMesh.numIndexes == uint32_t(-1)) {
399 renderBlock.startIndex = 0;
400 renderBlock.numIndexes = meshCount;
403 renderBlock.startIndex = subMesh.startIndex;
404 renderBlock.numIndexes = subMesh.numIndexes;
405 if (meshCount <= renderBlock.startIndex || meshCount < renderBlock.startIndex + renderBlock.numIndexes) {
406 LOG_ERROR_ONCE(logger,
"SubMeshRenderComponent draw range is out of bounds");
411 renderBlock.primitiveType = subMesh.primitiveType;
413 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
414 auto animationComponent = renderComponent.getComponent<AnimationComponent>();
415 const auto & animationData = context->animationSystem->getData(animationComponent);
416 renderBlock.poseData = animationData.pose.get();
419 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
420 renderBlock.flags |= getMaterialFlags(materialInstance);
421 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
423 renderBlock.materialInstance = materialInstance;
425 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
426 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
431 for (
const auto & renderComponent : context->instancedMeshRenderSystem->pool) {
432 if (!renderComponent.isVisible())
continue;
434 auto & renderData = context->instancedMeshRenderSystem->getData<InstancedMeshRenderData>(&renderComponent);
436 const MeshComponent * meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
438 assert(meshComponent &&
"No mesh component defined");
440 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
441 if (!renderMesh)
continue;
443 RenderMesh * instanceRenderMesh = renderer->getRenderResources().getRenderMesh(renderComponent.instanceMesh);
444 if (!instanceRenderMesh)
continue;
446 Mesh * mesh = meshComponent->meshHandle.resolve();
447 Mesh * instanceMesh = renderComponent.instanceMesh.resolve();
449 MaterialInstance * materialInstance = renderComponent.material.resolve();
450 if (!materialInstance)
continue;
453 if (instanceCount == 0) {
457 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &renderData.localToWorld, &renderComponent);
458 renderBlock.lod = renderComponent.lod;
459 renderBlock.layer = renderComponent.layer;
460 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
461 renderBlock.flags |= RenderItemFlags::Instanced;
463 renderBlock.cullingIndex = renderData.cullingIndex;
465 renderBlock.meshData = renderMesh;
466 renderBlock.instanceData = instanceRenderMesh;
467 renderBlock.startIndex = renderComponent.startIndex;
469 renderBlock.startInstance = renderComponent.startInstance;
470 renderBlock.numInstances = instanceCount;
471 renderBlock.primitiveType = renderComponent.primitiveType != (
PrimitiveType) - 1 ? renderComponent.primitiveType : mesh->primitiveType;
473 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
474 auto animationComponent = renderComponent.getComponent<AnimationComponent>();
475 const auto & animationData = context->animationSystem->getData(animationComponent);
476 renderBlock.poseData = animationData.pose.get();
479 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
480 renderBlock.flags |= getMaterialFlags(materialInstance);
481 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
483 renderBlock.materialInstance = materialInstance;
485 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
486 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
489 for (
const SpriteBatch& batch : context->spriteRenderSystem->getSpriteBatches()) {
490 if (!batch.count)
continue;
492 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(batch.mesh);
494 if (!renderMesh || !renderMesh->numVertexes) {
498 MaterialInstance * materialInstance = batch.material.resolve();
500 if (!materialInstance)
continue;
502 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &batch.transform,
nullptr);
503 renderBlock.lod = batch.lod;
504 renderBlock.cullingIndex = NoCullingIndex;
505 renderBlock.depth = batch.depth;
507 renderBlock.flags |= batch.flags | RenderItemFlags::Sprite;
508 renderBlock.layer = RenderLayers::Overlay;
510 renderBlock.setBounds(&batch.bbox);
512 renderBlock.materialInstance = materialInstance;
513 renderBlock.blendState = (uint16_t)batch.blendMode;
515 renderBlock.meshData = renderMesh;
516 renderBlock.startIndex =
static_cast<uint32_t
>(batch.start);
517 renderBlock.numIndexes =
static_cast<uint32_t
>(batch.count);
518 renderBlock.primitiveType = batch.mesh->primitiveType;
521 if (context->variables->getOrAdd(
"renderer.showCoordSys",
false)) {
523 static auto renderCallback = [](RenderTaskContext * taskContext, DrawContext * drawContext,
const RenderItem * item)
525 RenderInstrumentationScope(taskContext->device->getImmediateContext(), SCOPE_RENDERING,
"showCoordSysRender");
526 auto * renderer = taskContext->renderer;
527 const auto M = renderer->getProjectionMatrix(glm::frustum(-0.7f, 0.7f, -0.7f, 0.7f, 1.0f, 3.0f)) * glm::translate(glm::vec3(0,0,-2.0f)) * glm::mat4(glm::mat3(drawContext->cameraData->viewMatrix));
528 auto b = drawContext->cameraData->viewportOrigin.y + drawContext->cameraData->viewportSize.y;
529 auto * deviceContext = taskContext->device->getImmediateContext();
532 deviceContext->setViewport(0, 0, 80, 80);
534 deviceContext->setViewport(0, b - 80, 80, 80);
535 drawCoordSys(taskContext, drawContext, item, M,
true);
536 auto & o = drawContext->cameraData->viewportOrigin;
537 auto & s = drawContext->cameraData->viewportSize;
538 deviceContext->setViewport(o.x, o.y, s.x, s.y);
541 auto & item = renderList.createCustom(
nullptr);
542 item.layer = RenderLayers::Annotations;
543 item.materialInstance = getDefaultMaterialInstance(context).
resolve();
547 item.flags |= RenderItemFlags::Custom2 | RenderItemFlags::DisableCulling;
548 item.callback = renderCallback;
551 if (context->variables->getOrAdd(
"renderer.showFrustums",
false)) {
553 static auto renderCallback = [](RenderTaskContext * taskContext, DrawContext * drawContext,
const RenderItem * item)
555 RenderInstrumentationScope(taskContext->device->getImmediateContext(), SCOPE_RENDERING,
"showFrustumsRender");
556 const auto * camData = item->getCallbackData<CameraData>();
557 const auto M = drawContext->cameraData->viewProjection * camData->inverseViewMatrix * glm::inverse(camData->rawProjectionMatrix);
558 drawOneOneWireBox(taskContext, drawContext, item, M,
static_cast<unsigned>(
reinterpret_cast<size_t>(item->getCallbackData2<
void>())));
562 auto genFrustumItem = [&](CameraData* cd,
size_t i)
564 auto & item = renderList.createCustom(
nullptr);
565 item.layer = RenderLayers::Annotations;
566 item.materialInstance = getDefaultMaterialInstance(context).
resolve();
570 item.flags |= RenderItemFlags::Custom2 | RenderItemFlags::DisableCulling;
571 item.setCallbackData(cd);
572 item.setCallbackData2(
reinterpret_cast<void*
>(i));
573 item.callback = renderCallback;
577 auto* pipeService = context->services->getService<PipelineService>();
578 for (
const auto* run : pipeService->runs) {
579 if (run->cameraData) {
580 genFrustumItem(run->cameraData, o);
584 for (
const auto & cameraComp : context->cameraSystem->pool) {
586 auto & camData = context->cameraSystem->getData(&cameraComp);
587 genFrustumItem(&camData, o);
590 for (
const auto & lightComp : context->lightSystem->pool) {
591 auto & lightData = context->lightSystem->getData(&lightComp);
592 if (lightData.castShadows) {
593 for (
unsigned i = 0; i < lightData.numViewports; i++) {
594 genFrustumItem(&lightData.lightCameraData[i], i);
600 for (
auto & extension : renderer->getExtensions()) {
601 extension->generateCommands(renderTaskContext, &renderList);
605 if (listObjectBuffer.isInUse()) {
607 if (2 * std::max(minObjectBufferCapacity, listObjectBuffer.fill) < listObjectBuffer.cpuCapacity) {
608 listObjectBuffer.cpuCapacity = listObjectBuffer.cpuCapacity / 2;
609 listObjectBuffer.cpu.resize(
size_t(listObjectBuffer.stride)* listObjectBuffer.cpuCapacity);
612 if (listObjectBuffer.gpuCapacity != listObjectBuffer.cpuCapacity) {
614 if (listObjectBuffer.gpuCapacity == 0) {
615 LOG_DEBUG(logger,
"Setting up list object buffer GPU storage");
618 listObjectBuffer.gpuCapacity = listObjectBuffer.cpuCapacity;
620 IBuffers* buffers = renderTaskContext->device->getBuffers();
623 buffers->releaseBuffer(listObjectBuffer.gpu);
627 listObjectBuffer.gpu = buffers->loadBuffer(
nullptr,
628 size_t(listObjectBuffer.stride) * listObjectBuffer.gpuCapacity,
632 buffers->annotate(listObjectBuffer.gpu,
"ListObjectBuffer");
636 if (listObjectBuffer.fill) {
637 IContext* immediateContext = renderTaskContext->device->getImmediateContext();
638 immediateContext->updateBuffer(listObjectBuffer.gpu,
639 listObjectBuffer.cpu.data(),
640 size_t(listObjectBuffer.stride) * listObjectBuffer.fill);
643 renderList.listObjectBuffer = &listObjectBuffer;
647 IBuffers* buffers = renderTaskContext->device->getBuffers();
648 buffers->releaseBuffer(listObjectBuffer.gpu);
650 listObjectBuffer.gpuCapacity = 0;
652 listObjectBuffer.cpu.clear();
653 listObjectBuffer.cpuCapacity = 0;
655 LOG_DEBUG(logger,
"Released list object buffer GPU storage");
658 renderList.clipShapeCache = &clipShapeCache;
static uint32_t getRenderCount(uint32_t startIndex, uint32_t instanceCount, uint32_t meshCount)
Get number of instanced Meshes to render.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
@ InvertedCube
Clip the inside of a cube.
@ None
No clipping at all.
@ Cube
Clip the outside of a cube,.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
@ EnableRender
Renderable.
@ Blend
Render with regular alpha blending.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
@ Default
Default, depth test & write enabled.
@ Disabled
Depth test/write disabled.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ OpenGL20
Graphics device using OpenGL, supporting at least OpenGL 2.0.
@ WebGPU
Graphics device using the WebGPU API Backend.
PrimitiveType
Primitive types for interpreting vertex data sent to the graphics pipeline.
@ Write
The buffer can be mapped and written to by the CPU after creation.
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
static ComponentHandle Empty()
Returns an empty, invalid handle. Will evaluate to false if tested against using operator bool().
EMaterialFlags
Material flags.
@ OverrideAlpha
Override alpha of any inheriting materials.
@ CustomBucket
Items with this flag should be put in Custom rendering buckets.
MaterialInstanceHandle masterInstance
Master material instance overriding properties in this instance if override is enabled.
@ Instanced
Mesh contains instance data.
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
static const Handle_t NoHandle
Represents a handle to nothing.
@ Dynamic
Buffer will be loaded and modified with some frequency.