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;
59 if (instance->masterInstance && ((instance->masterInstance->getMaterialFlags() & overrideFlag) == overrideFlag)) {
66 void getTransparencyState(RenderStates & ,
const MaterialInstance * materialInstance, RenderItem & renderItem)
69 const auto hasTransparency = instance->hasTransparency();
70 auto blendMode = instance->options.blendMode;
74 renderItem.blendState = (uint16_t)blendMode;
77 RenderItemFlags getMaterialFlags(
const MaterialInstance * materialInstance)
79 RenderItemFlags flags = RenderItemFlags::None;
80 flags |= (materialInstance->instanceFlags &
MaterialFlags::CustomBucket) != 0 ? RenderItemFlags::CustomBucket : RenderItemFlags::None;
81 flags |= materialInstance->hasTransparency() ? RenderItemFlags::Transparent : RenderItemFlags::None;
82 flags |= materialInstance->isBackdrop() ? RenderItemFlags::Backdrop : RenderItemFlags::None;
87uint8_t Cogs::Core::ClipShapeCache::getIndex(Context* context, ComponentModel::ComponentHandle clipShapeHandle)
92 for (
size_t i = 1; i < count; i++) {
93 if (handles[i] == clipShapeHandle) {
94 return static_cast<uint8_t
>(i);
99 if (ClipShapeComponent* clipComp = clipShapeHandle.resolveComponent<ClipShapeComponent>(); clipComp) {
100 const ClipShapeData& clipData = context->clipShapeSystem->getData(clipComp);
102 switch (clipData.shape) {
107 if (count < ClipShapeCache::maxClipShapes) {
108 handles[count] = clipShapeHandle;
118 .clipShape = clipData.shape
120 return static_cast<uint8_t
>(count++);
124 assert(
false &&
"Invalid enum");
126 LOG_ERROR_ONCE(logger,
"Exceeding max number of clip shapes");
132Cogs::Core::RenderItem& Cogs::Core::GenerateListTask::createRenderItem(Context* context, RenderBatch& batch,
const glm::mat4* localToWorld,
const RenderComponent* renderComponent)
134 if (renderComponent && (renderComponent->layer&RenderLayers::AllReserved)!=0) {
135 LOG_WARNING_ONCE(logger,
"Using a reserved RenderLayer (Consider switching to RenderLayer::Custom).");
138 RenderItem& item = batch.alloc();
140 item.cullingIndex = (uint32_t)-1;
142 item.worldMatrix = localToWorld;
144 item.flags = RenderItemFlags::None;
146 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->worldMatrix = *localToWorld;
162 objectBuffer->objectId = 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::EPrimitiveType)-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 useListObjectBuffer =
false;
299 const StringView listObjectBufferKey =
"renderer.listObjectBuffer";
300 if (Variable* var = context->variables->get(listObjectBufferKey); !var->isEmpty()) {
301 useListObjectBuffer = var->getBool();
304 context->variables->set(listObjectBufferKey, useListObjectBuffer);
306 if (useListObjectBuffer && caps->getDeviceCapabilities().ConstantBufferRange) {
307 listObjectBuffer.stride = std::max(uint32_t(
sizeof(ObjectBuffer)), uint32_t(caps->getDeviceCapabilities().ConstantBufferOffsetAlignment));
310 listObjectBuffer.stride = 0;
312 listObjectBuffer.fill = 0;
315 generateItems(context, renderList.batch, renderer, context->renderSystem, context->meshSystem);
317 for (
auto & staticModel : context->staticModelSystem->pool) {
318 if (!staticModel.model)
continue;
320 auto renderSystem = context->staticModelSystem->getRenderSystem(&staticModel);
321 auto meshSystem = context->staticModelSystem->getMeshSystem(&staticModel);
323 if (!renderSystem || !renderSystem->pool.size())
continue;
325 auto batch = context->staticModelSystem->getRenderBatch(&staticModel);
327 if (batch->generation != renderSystem->getGeneration()) {
329 auto missing = generateItems(context, *batch, renderer, renderSystem, meshSystem);
330 batch->missing = missing;
331 batch->generation = renderSystem->getGeneration();
334 renderList.batches.emplace_back(batch);
337 for (
const SubMeshRenderComponent& renderComponent : context->subMeshRenderSystem->pool) {
338 if (!renderComponent.isVisible())
continue;
340 auto & renderData = context->subMeshRenderSystem->getData<SubMeshRenderData>(&renderComponent);
342 const MeshComponent* meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
343 if (meshComponent ==
nullptr) {
344 LOG_ERROR_ONCE(logger,
"No mesh component defined");
348 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
350 if (!renderMesh)
continue;
352 Mesh * mesh = meshComponent->meshHandle.resolve();
353 const uint32_t meshCount = mesh->getCount();
355 size_t subMeshBegin = 0;
356 size_t subMeshEnd = mesh->getSubMeshes().size();
358 if ((0 <= renderComponent.subMesh) && (
static_cast<size_t>(renderComponent.subMesh) < subMeshEnd)) {
359 subMeshBegin = renderComponent.subMesh;
360 subMeshEnd = subMeshBegin + 1;
363 for (
size_t m = subMeshBegin; m < subMeshEnd; ++m) {
364 auto & subMesh = mesh->getSubMeshes()[m];
366 if (subMesh.numIndexes && renderMesh->streamsLayout.numStreams) {
367 auto materialInstance = ((renderComponent.materials.size() > m) ? renderComponent.materials[m] : renderComponent.materials.front()).resolve();
369 if (!materialInstance)
continue;
371 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &renderData.localToWorld, &renderComponent);
372 renderBlock.lod = renderComponent.lod;
373 renderBlock.layer = renderComponent.layer;
374 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
376 renderBlock.cullingIndex = renderData.cullingIndex;
378 renderBlock.meshData = renderMesh;
379 if (subMesh.numIndexes == uint32_t(-1)) {
380 renderBlock.startIndex = 0;
381 renderBlock.numIndexes = meshCount;
384 renderBlock.startIndex = subMesh.startIndex;
385 renderBlock.numIndexes = subMesh.numIndexes;
386 if (meshCount <= renderBlock.startIndex || meshCount < renderBlock.startIndex + renderBlock.numIndexes) {
387 LOG_ERROR_ONCE(logger,
"SubMeshRenderComponent draw range is out of bounds");
392 renderBlock.primitiveType = subMesh.primitiveType;
394 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
395 auto animationComponent = renderComponent.getComponent<AnimationComponent>();
396 const auto & animationData = context->animationSystem->getData(animationComponent);
397 renderBlock.poseData = animationData.pose.get();
400 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
401 renderBlock.flags |= getMaterialFlags(materialInstance);
402 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
404 renderBlock.materialInstance = materialInstance;
406 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
407 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
412 for (
const auto & renderComponent : context->instancedMeshRenderSystem->pool) {
413 if (!renderComponent.isVisible())
continue;
415 auto & renderData = context->instancedMeshRenderSystem->getData<InstancedMeshRenderData>(&renderComponent);
417 const MeshComponent * meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
419 assert(meshComponent &&
"No mesh component defined");
421 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
422 if (!renderMesh)
continue;
424 RenderMesh * instanceRenderMesh = renderer->getRenderResources().getRenderMesh(renderComponent.instanceMesh);
425 if (!instanceRenderMesh)
continue;
427 Mesh * mesh = meshComponent->meshHandle.resolve();
428 Mesh * instanceMesh = renderComponent.instanceMesh.resolve();
430 MaterialInstance * materialInstance = renderComponent.material.resolve();
431 if (!materialInstance)
continue;
434 if (instanceCount == 0) {
438 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &renderData.localToWorld, &renderComponent);
439 renderBlock.lod = renderComponent.lod;
440 renderBlock.layer = renderComponent.layer;
441 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
442 renderBlock.flags |= RenderItemFlags::Instanced;
444 renderBlock.cullingIndex = renderData.cullingIndex;
446 renderBlock.meshData = renderMesh;
447 renderBlock.instanceData = instanceRenderMesh;
448 renderBlock.startIndex = renderComponent.startIndex;
450 renderBlock.startInstance = renderComponent.startInstance;
451 renderBlock.numInstances = instanceCount;
452 renderBlock.primitiveType = renderComponent.primitiveType != (
PrimitiveType::EPrimitiveType) - 1 ? renderComponent.primitiveType : mesh->primitiveType;
454 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
455 auto animationComponent = renderComponent.getComponent<AnimationComponent>();
456 const auto & animationData = context->animationSystem->getData(animationComponent);
457 renderBlock.poseData = animationData.pose.get();
460 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
461 renderBlock.flags |= getMaterialFlags(materialInstance);
462 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
464 renderBlock.materialInstance = materialInstance;
466 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
467 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
470 for (
const SpriteBatch& batch : context->spriteRenderSystem->getSpriteBatches()) {
471 if (!batch.count)
continue;
473 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(batch.mesh);
475 if (!renderMesh || !renderMesh->numVertexes) {
479 MaterialInstance * materialInstance = batch.material.resolve();
481 if (!materialInstance)
continue;
483 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &batch.transform,
nullptr);
484 renderBlock.lod = batch.lod;
485 renderBlock.cullingIndex = NoCullingIndex;
486 renderBlock.depth = batch.depth;
488 renderBlock.flags |= batch.flags | RenderItemFlags::Sprite;
489 renderBlock.layer = RenderLayers::Overlay;
491 renderBlock.setBounds(&batch.bbox);
493 renderBlock.materialInstance = materialInstance;
494 renderBlock.blendState = (uint16_t)batch.blendMode;
496 renderBlock.meshData = renderMesh;
497 renderBlock.startIndex =
static_cast<uint32_t
>(batch.start);
498 renderBlock.numIndexes =
static_cast<uint32_t
>(batch.count);
499 renderBlock.primitiveType = batch.mesh->primitiveType;
502 if (context->variables->getOrAdd(
"renderer.showCoordSys",
false)) {
504 static auto renderCallback = [](RenderTaskContext * taskContext, DrawContext * drawContext,
const RenderItem * item)
506 RenderInstrumentationScope(taskContext->device->getImmediateContext(), SCOPE_RENDERING,
"showCoordSysRender");
507 auto * renderer = taskContext->renderer;
508 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));
509 auto b = drawContext->cameraData->viewportOrigin.y + drawContext->cameraData->viewportSize.y;
510 auto * deviceContext = taskContext->device->getImmediateContext();
513 deviceContext->setViewport(0, 0, 80, 80);
515 deviceContext->setViewport(0, b - 80, 80, 80);
516 drawCoordSys(taskContext, drawContext, item, M,
true);
517 auto & o = drawContext->cameraData->viewportOrigin;
518 auto & s = drawContext->cameraData->viewportSize;
519 deviceContext->setViewport(o.x, o.y, s.x, s.y);
522 auto & item = renderList.createCustom(
nullptr);
523 item.layer = RenderLayers::Annotations;
524 item.materialInstance = getDefaultMaterialInstance(context).
resolve();
528 item.flags |= RenderItemFlags::Custom2 | RenderItemFlags::DisableCulling;
529 item.callback = renderCallback;
532 if (context->variables->getOrAdd(
"renderer.showFrustums",
false)) {
534 static auto renderCallback = [](RenderTaskContext * taskContext, DrawContext * drawContext,
const RenderItem * item)
536 RenderInstrumentationScope(taskContext->device->getImmediateContext(), SCOPE_RENDERING,
"showFrustumsRender");
537 const auto * camData = item->getCallbackData<CameraData>();
538 const auto M = drawContext->cameraData->viewProjection * camData->inverseViewMatrix * glm::inverse(camData->rawProjectionMatrix);
539 drawOneOneWireBox(taskContext, drawContext, item, M,
static_cast<unsigned>(
reinterpret_cast<size_t>(item->getCallbackData2<
void>())));
543 auto genFrustumItem = [&](CameraData* cd,
size_t i)
545 auto & item = renderList.createCustom(
nullptr);
546 item.layer = RenderLayers::Annotations;
547 item.materialInstance = getDefaultMaterialInstance(context).
resolve();
551 item.flags |= RenderItemFlags::Custom2 | RenderItemFlags::DisableCulling;
552 item.setCallbackData(cd);
553 item.setCallbackData2(
reinterpret_cast<void*
>(i));
554 item.callback = renderCallback;
558 auto* pipeService = context->services->getService<PipelineService>();
559 for (
const auto* run : pipeService->runs) {
560 if (run->cameraData) {
561 genFrustumItem(run->cameraData, o);
565 for (
const auto & cameraComp : context->cameraSystem->pool) {
567 auto & camData = context->cameraSystem->getData(&cameraComp);
568 genFrustumItem(&camData, o);
571 for (
const auto & lightComp : context->lightSystem->pool) {
572 auto & lightData = context->lightSystem->getData(&lightComp);
573 if (lightData.castShadows) {
574 for (
unsigned i = 0; i < lightData.numViewports; i++) {
575 genFrustumItem(&lightData.lightCameraData[i], i);
583 for (
auto & extension : renderer->getExtensions()) {
584 extension->generateCommands(renderTaskContext, &renderList);
588 if (listObjectBuffer.isInUse()) {
590 if (2 * std::max(minObjectBufferCapacity, listObjectBuffer.fill) < listObjectBuffer.cpuCapacity) {
591 listObjectBuffer.cpuCapacity = listObjectBuffer.cpuCapacity / 2;
592 listObjectBuffer.cpu.resize(
size_t(listObjectBuffer.stride)* listObjectBuffer.cpuCapacity);
595 if (listObjectBuffer.gpuCapacity != listObjectBuffer.cpuCapacity) {
597 if (listObjectBuffer.gpuCapacity == 0) {
598 LOG_DEBUG(logger,
"Setting up list object buffer GPU storage");
601 listObjectBuffer.gpuCapacity = listObjectBuffer.cpuCapacity;
603 IBuffers* buffers = renderTaskContext->device->getBuffers();
606 buffers->releaseBuffer(listObjectBuffer.gpu);
610 listObjectBuffer.gpu = buffers->loadBuffer(
nullptr,
611 size_t(listObjectBuffer.stride) * listObjectBuffer.gpuCapacity,
615 buffers->annotate(listObjectBuffer.gpu,
"ListObjectBuffer");
619 if (listObjectBuffer.fill) {
620 IContext* immediateContext = renderTaskContext->device->getImmediateContext();
621 immediateContext->updateBuffer(listObjectBuffer.gpu,
622 listObjectBuffer.cpu.data(),
623 size_t(listObjectBuffer.stride) * listObjectBuffer.fill);
625 renderList.listObjectBuffer = &listObjectBuffer;
629 IBuffers* buffers = renderTaskContext->device->getBuffers();
630 buffers->releaseBuffer(listObjectBuffer.gpu);
632 listObjectBuffer.gpuCapacity = 0;
634 listObjectBuffer.cpu.clear();
635 listObjectBuffer.cpuCapacity = 0;
637 LOG_DEBUG(logger,
"Released list object buffer GPU storage");
640 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.
@ 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.
EPrimitiveType
Primitive type enumeration.
@ Dynamic
Buffer will be loaded and modified with some frequency.