1#include "ExtensionRegistry.h"
2#include "Renderer/Renderer.h"
3#include "Renderer/RenderList.h"
4#include "Renderer/RenderStateUpdater.h"
5#include "Renderer/RenderTarget.h"
6#include "Renderer/Tasks/RenderListTask.h"
7#include "Renderer/Tasks/FilterListTask.h"
8#include "Renderer/Tasks/GenerateListTask.h"
10#include "Image360System.h"
12#include "Rendering/IGraphicsDevice.h"
13#include "Rendering/ITextures.h"
14#include "Rendering/ICapabilities.h"
15#include "Rendering/IRenderTargets.h"
16#include "Foundation/Logging/Logger.h"
25 using namespace Cogs::Core::Image360;
31 glm::mat4 worldFromLocal;
32 glm::mat4 localFromWorld;
33 float clipSpaceNearPlane;
44 const auto* camData = drawContext->cameraData;
45 if (camData ==
nullptr)
return;
47 Renderer* renderer = taskContext->renderer;
60 if (drawContext->task->viewportFromTarget && drawContext->renderTarget) {
61 iContext->
setViewport(0.f, 0.f,
float(drawContext->renderTarget->width), float(drawContext->renderTarget->height));
64 iContext->
setViewport(camData->viewportOrigin.x, camData->viewportOrigin.y, camData->viewportSize.x, camData->viewportSize.y);
68 iContext->
setBlendState(taskContext->states->blendStates[renderItem->blendState].handle);
70 const RenderPassOptions passOptions = initRenderPassOptions(*camData , renderItem->materialInstance);
71 iContext->
setRasterizerState(taskContext->states->rasterizerStateHandles[getRasterizerState(renderer, *renderItem, passOptions, camData->flipWindingOrder,
true)]);
75 applyMaterialPermutation(taskContext, drawContext, renderItem->binding, renderItem->renderMaterialInstance);
79 drawContext->task->applyMaterial(*drawContext, *renderItem);
82 applyMaterialInstance(drawContext, renderItem->binding, renderItem->renderMaterialInstance);
84 updateSceneBindings(drawContext, drawContext->cameraData, renderItem->binding);
86 updateMaterialBindings(drawContext, renderItem->renderMaterialInstance, renderItem->binding,
true);
90 const glm::mat3 viewFromLocal = glm::mat3(drawContext->cameraData->viewMatrix) * rendererData->worldFromLocal;
91 const glm::mat3 localFromView = rendererData->localFromWorld * glm::mat3(drawContext->cameraData->inverseViewMatrix);
92 const float clipSpaceNearPlane = drawContext->context->
variables->get(
"renderer.reverseDepth",
false) ? 1.f : -1.f;
94 const EngineBuffers& engineBuffers = *drawContext->engineBuffers;
98 .worldFromLocal = rendererData->worldFromLocal,
99 .localFromWorld = rendererData->localFromWorld,
100 .clipSpaceNearPlane = clipSpaceNearPlane,
101 .valueScale = rendererData->value.scale,
102 .valueBias = rendererData->value.bias,
103 .depthScale = rendererData->depth.scale,
104 .depthBias = rendererData->depth.bias,
105 .baseSize = float(rendererData->baseSize),
106 .noDataDepth = rendererData->noDataDepth
108 iContext->
updateBuffer(rendererData->constants, &constants,
sizeof(constants));
114 objectBuffer.objectId = renderItem->
objectId;
115 iContext->
updateBuffer(rendererData->constants, &objectBuffer,
sizeof(objectBuffer));
116 iContext->
setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
119 iContext->
setTexture(
"encodedTrees", 0, rendererData->encodedTreesTex);
122 if (rendererData->isValueUint) {
123 iContext->
setTexture(
"tilesValue_uint", 1, rendererData->value.tilesTex);
128 iContext->
setTexture(
"tilesValue_srgb", 1, rendererData->value.tilesTex);
132 iContext->
setTexture(
"tilesDepth", 2, rendererData->depth.tilesTex);
140 constexpr const char* atlasBlitVS_es30 = R
"(#version 300 es
141precision highp float;
145 gl_Position = vec4(a_POSITION, 0, 1);
149 constexpr const char* atlasBlitFloatPS_es30 = R
"(#version 300 es
150precision highp float;
151precision highp sampler2DArray;
155uniform sampler2DArray source;
159 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
163 constexpr const char* atlasBlitUIntPS_es30 = R
"(#version 300 es
164precision highp float;
166precision highp usampler2DArray;
170uniform usampler2DArray source;
171out uvec4 destination;
174 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
184 auto& atlasBlit = rendererExtension->atlasBlit;
192 atlasBlit.f.effect = effects->
loadEffectSource(atlasBlitVS_es30, atlasBlitFloatPS_es30);
194 atlasBlit.f.inputLayout = buffers->
loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.
vertexFormats[0], 1, atlasBlit.f.effect);
195 atlasBlit.f.srcTexBinding = effects->
getTextureBinding(atlasBlit.f.effect,
"source", 0);
200 atlasBlit.u.effect = effects->
loadEffectSource(atlasBlitVS_es30, atlasBlitUIntPS_es30);
202 atlasBlit.u.inputLayout = buffers->
loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.
vertexFormats[0], 1, atlasBlit.u.effect);
203 atlasBlit.u.srcTexBinding = effects->
getTextureBinding(atlasBlit.u.effect,
"source", 0);
215 .comparisonFunction = Cogs::SamplerState::ComparisonFunction::Never,
217 .borderColor = { 0, 0, 0, 1 }
221 .depthEnabled =
false,
222 .writeEnabled =
true,
228 .sourceBlend = Cogs::BlendState::Blend::One,
229 .destinationBlend = Cogs::BlendState::Blend::Zero,
230 .operation = Cogs::BlendState::BlendOperation::Add
237 uint32_t w, uint32_t h, Cogs::TextureFormat fmt)
239 bool formatIsFloat =
true;
241 case Cogs::DataFormat::R8G8B8A8_UNORM:
242 case Cogs::DataFormat::R8G8B8A8_UNORM_SRGB:
243 formatIsFloat =
true;
248 case Cogs::DataFormat::R16_UINT:
249 formatIsFloat =
false;
255 LOG_ERROR_ONCE(logger,
"Trying to blit unsupported format: %d",
static_cast<uint32_t
>(fmt));
265 .layerIndex =
static_cast<uint16_t
>(dstLayer),
272 immediateContext->
setViewport(0.f, 0.f,
static_cast<float>(w),
static_cast<float>(h));
273 immediateContext->
updateBuffer(rendererExtension->atlasBlit.paramBuffer, &srcLayer,
sizeof(uint32_t));
275 immediateContext->
setEffect(rendererExtension->atlasBlit.f.effect);
276 immediateContext->
setInputLayout(rendererExtension->atlasBlit.f.inputLayout);
277 immediateContext->
setConstantBuffer(rendererExtension->atlasBlit.f.paramBinding, rendererExtension->atlasBlit.paramBuffer);
278 immediateContext->
setTexture(rendererExtension->atlasBlit.f.srcTexBinding, srcTex);
279 immediateContext->
setSamplerState(rendererExtension->atlasBlit.f.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
282 immediateContext->
setEffect(rendererExtension->atlasBlit.u.effect);
283 immediateContext->
setInputLayout(rendererExtension->atlasBlit.u.inputLayout);
284 immediateContext->
setConstantBuffer(rendererExtension->atlasBlit.u.paramBinding, rendererExtension->atlasBlit.paramBuffer);
285 immediateContext->
setTexture(rendererExtension->atlasBlit.u.srcTexBinding, srcTex);
286 immediateContext->
setSamplerState(rendererExtension->atlasBlit.u.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
288 immediateContext->
setVertexBuffers(&rendererExtension->fullScreenTriangle.vertices, 1);
290 immediateContext->
setBlendState(rendererExtension->atlasBlit.blendState);
305 this->device = device;
306 this->context = context;
307 im360System = ExtensionRegistry::getExtensionSystem<Image360System>(context);
315 fullScreenTriangle.streamsLayout.vertexFormats[0] = VertexFormats::createVertexFormat(element);
316 fullScreenTriangle.streamsLayout.numStreams = 1;
317 fullScreenTriangle.streamsLayout.updateHash();
319 static const float fullScreenTriangleVertexData[] = {
324 fullScreenTriangle.vertices = buffers->
loadVertexBuffer(fullScreenTriangleVertexData,
325 sizeof(fullScreenTriangleVertexData) /
sizeof(fullScreenTriangleVertexData[0]),
326 fullScreenTriangle.streamsLayout.vertexFormats[0]);
327 atlasBlitInit(context,
this);
331void Cogs::Core::Image360::RendererExtension::release()
342void Cogs::Core::Image360::RendererExtension::releaseRenderingResources(
RendererExtensionData& rendererData)
367 rendererData.depth.tilesData.clear();
373 if (!renderingContext)
return;
377 RenderResources & resources = renderingContext->renderer->getRenderResources();
379 IContext* deviceContext = renderingContext->deviceContext;
385 Image360Data& im360Data = im360System->getData(&im360Comp);
388 if ((im360Data.state == Image360Data::State::WaitingForBaseLevel) || (im360Data.state == Image360Data::State::Running))
390 im360Data.rendererData.baseSize = im360Data.config.
baseSize;
391 im360Data.rendererData.noDataDepth = im360Data.config.
noDataDepth;
394 rendererData.value.scale = channel.scale;
395 rendererData.value.bias = channel.bias;
396 switch (channel.dataType) {
399 rendererData.value.sampler = 3;
402 rendererData.value.sampler = 1;
407 rendererData.value.scale = 1.f;
408 rendererData.value.bias = 0.f;
416 rendererData.depth.scale = channel.scale;
417 rendererData.depth.bias = channel.bias;
418 switch (channel.dataType) {
421 rendererData.depth.sampler = 3;
424 rendererData.depth.sampler = 1;
438 if(!im360Data.lodTree.data.empty()) {
440 desc.target = Cogs::ResourceDimensions::Texture2D;
441 desc.width =
static_cast<uint32_t
>(im360Data.lodTree.data.size());
443 desc.format = Cogs::TextureFormat::R16_SINT;
447 rendererData.encodedTreesTex = textures->
loadTexture(desc, &textureData);
449 if (rendererData.currentTreeSize != desc.width) {
450 rendererData.currentTreeSize = desc.width;
451 LOG_TRACE(logger,
"Current tree size: %u", rendererData.currentTreeSize);
456 uint32_t cacheItemCount = std::max(6u,
static_cast<uint32_t
>(im360Data.cache.items.size()));
457 bool resizeCache = (!
HandleIsValid(im360Data.rendererData.value.tilesTex) ||
463 Cogs::ResourceDimensions target = Cogs::ResourceDimensions::Unknown;
466 rendererData.cacheLayout.cols = 1;
467 rendererData.cacheLayout.rows = 1;
469 target = Cogs::ResourceDimensions::Texture2DArray;
474 desc.target = target;
475 desc.width = rendererData.cacheLayout.cols * im360Data.config.
baseSize;
476 desc.height = rendererData.cacheLayout.rows * im360Data.config.
baseSize;
477 desc.layers = rendererData.cacheLayout.layers;
486 desc.format = Cogs::DataFormat::R8G8B8A8_UNORM_SRGB;
490 desc.format = Cogs::DataFormat::R16_UINT;
493 assert(
false &&
"Invalid enum value");
497 rendererData.value.tilesTex = textures->
loadTexture(desc,
nullptr);
500 for (uint32_t i = 0; i < toCopy; i++) {
501 if (im360Data.cache.items[i].value.state == Cache::Item::State::Resident) {
502 if (!atlasTileBlit(context,
this,
503 rendererData.value.tilesTex, i,
507 deviceContext->copyTexture(rendererData.value.tilesTex,
509 tilesValueOldTex, i);
521 desc.target = target;
522 desc.width = rendererData.cacheLayout.cols * im360Data.config.
baseSize;
523 desc.height = rendererData.cacheLayout.rows * im360Data.config.
baseSize;
524 desc.layers = rendererData.cacheLayout.layers;
529 desc.format = Cogs::DataFormat::R16_UINT;
532 assert(
false &&
"Invalid enum value");
536 rendererData.depth.tilesTex = textures->
loadTexture(desc,
nullptr);
539 for (uint32_t i = 0; i < toCopy; i++) {
540 if (im360Data.cache.items[i].depth.state == Cache::Item::State::Resident) {
541 if (!atlasTileBlit(context,
this,
542 rendererData.depth.tilesTex, i,
546 deviceContext->copyTexture(rendererData.depth.tilesTex,
548 tilesDepthOldTex, i);
562 Cache::Item& item = im360Data.cache.items[loadItem.slotIx];
564 bool consumed =
false;
565 if (loadItem.channelIx == im360Data.config.
valueChannel) {
566 if (item.value.state == Cache::Item::State::Loaded) {
569 uint32_t slice = loadItem.slotIx;
571 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
572 deviceContext->copyTexture(rendererData.value.tilesTex,
574 texture->textureHandle, 0);
575 item.value.state = Cache::Item::State::Resident;
580 if (loadItem.channelIx == im360Data.config.
depthChannel) {
581 if (item.depth.state == Cache::Item::State::Loaded) {
584 uint32_t slice = loadItem.slotIx;
586 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
587 deviceContext->copyTexture(rendererData.depth.tilesTex,
589 texture->textureHandle, 0);
590 item.depth.state = Cache::Item::State::Resident;
592 size_t tileByteSize =
sizeof(uint16_t) * im360Data.config.
baseSize * im360Data.config.
baseSize;
593 if (loadItem.buffer && loadItem.buffer->size() == tileByteSize) {
595 if (0 <= loadItem.slotIx &&
size_t(loadItem.slotIx) < rendererData.depth.tilesData.size()) {
596 rendererData.depth.tilesData[loadItem.slotIx] = std::move(loadItem.buffer);
604 LOG_WARNING(logger,
"Unexpected load item not uploaded to GPU");
607 im360Data.fetcher.itemsUploading.clear();
612 releaseRenderingResources(rendererData);
628 if (!renderingContext)
return;
634 Image360Data& im360Data = im360System->getData(&im360Comp);
635 if (im360Data.state != Image360Data::State::Running)
continue;
640 RenderItem& renderItem = renderList->createCustom(&fullScreenTriangle.streamsLayout);
641 renderItem.lod = im360Comp.lod;
643 renderItem.cullingIndex = ~0u;;
646 renderItem.flags |= materialInstance->
hasTransparency() ? RenderItemFlags::Transparent : RenderItemFlags::None;
647 if (materialInstance->
isBackdrop() || ((renderItem.
layer & RenderLayers::Sky)) != RenderLayers::None) {
648 renderItem.flags |= RenderItemFlags::Backdrop;
650 renderItem.materialInstance = materialInstance;
651 getTransparencyState(renderingContext->renderer->
getRenderStates(), materialInstance, renderItem);
653 renderItem.setCallbackData(
this);
654 renderItem.setCallbackData2(&im360Data.rendererData);
655 renderItem.callback = image360RenderCallback;
A Context instance contains all the services, systems and runtime components needed to use Cogs.
class IRenderer * renderer
Renderer.
std::unique_ptr< class Variables > variables
Variables service instance.
virtual IGraphicsDevice * getDevice()=0
Get the graphics device used by the renderer.
RenderLayers layer
Layer mask used to determine visibility for a given camera viewport.
int32_t drawOrder
Draw order within a render bucke.
constexpr bool isVisible() const
Check if the entity is visible or not.
uint32_t objectId
Object identifier passed to rendering commands.
Contains render resources used by the renderer.
RenderStates & getRenderStates() override
Get the reference to the RenderStates structure.
IGraphicsDevice * getDevice() override
Get the graphics device used by the renderer.
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 ITextures * getTextures()=0
Get a pointer to the texture 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 IRenderTargets * getRenderTargets()=0
Get a pointer to the render target management interface.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ VertexData
Per vertex data.
@ TriangleStrip
Triangle strip.
@ TriangleList
List of triangles.
@ Position
Position semantic.
@ 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.
float valueDomainMin
Set the source domain for scalar values, see 360.json's bias and scale to account for datatype.
float valueDomainMax
Set the source domain for scalar values, see 360.json's bias and scale to account for datatype.
@ SRGB8_JPEG
8-bit colors in SRGB color space stored as JPEG (.jpg).
@ U16_ZST
16-bit unsigned values stored as little endian raw values that are subsequently zstd compressed.
@ SRGBA8_PNG
8-bit colors in SRGB color space and a alpha channel (zero is transparent) stored as PNG (....
@ SRGB8_PNG
8-bit colors in SRGB color space stored as PNG (.png).
@ U16
16-bit unsigned values stored as little endian raw values.
uint32_t noDataDepth
Depth value that corresponds to noData.
uint32_t baseSize
Base image size of a cached tile. From json.
uint8_t valueChannel
Data channel to be used as value data. From component.
uint8_t depthChannel
Data channel that contains depth data. From json.
std::vector< Channel > channels
Data channels to use. From json.
bool hasDepth
If data has depth and component wants depth.
uint32_t gpuAllocatedCacheItemCount
Number of tiles allocated in current GPU cache texture.
uint32_t gpuActiveCacheItemCount
Number of tiles in current GPU cache that contain data.
void handleEvent(uint32_t eventId, const DrawContext *renderingContext) override
Called when rendering events occur.
void initialize(Context *context, IGraphicsDevice *device) override
Initialize the extension using the given context and device.
@ CustomBucket
Items with this flag should be put in Custom rendering buckets.
Material instances represent a specialized Material combined with state for all its buffers and prope...
bool hasTransparency() const
Get if this instance has any transparency and should be rendered with blending enabled.
bool isBackdrop() const
Get if geometry rendered with this material instance is to be treated as backdrops.
MaterialOptions options
Material rendering options used by this instance.
uint16_t instanceFlags
Material instance flags.
VertexFormatHandle vertexFormats[maxStreams]
int32_t drawOrder
Ordering of draw items within a bucket.
uint32_t objectId
Lower 6 of upper 8 bits are instance id bits, lower 24 bits are object id.
RenderLayers layer
Visibility mask.
@ PostRender
Rendering has finished for a given rendering context.
@ PreRender
Pre rendering happening for a given rendering context.
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
@ Always
Always evaluates to true.
static const Handle_t NoHandle
Represents a handle to nothing.
Provides buffer management functionality.
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 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 void releaseBuffer(BufferHandle bufferHandle)=0
Releases the buffer with the given bufferHandle.
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.
virtual void setTexture(const StringView &name, unsigned int unit, TextureHandle textureHandle)=0
Sets the texture slot given by unit with the given name to contain the given texture.
virtual void setRasterizerState(const RasterizerStateHandle handle)=0
Set the current rasterizer state.
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 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 updateBuffer(BufferHandle bufferHandle, const void *data, size_t size)=0
Replace contents of buffer with new data.
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 draw(PrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)=0
Draws non-indexed, non-instanced primitives.
virtual void setSamplerState(const StringView &name, unsigned int unit, SamplerStateHandle samplerStateHandle)=0
Sets the sampler slot given by unit with the given name to contain the given sampler state.
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.
virtual void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle)=0
Sets the current render target and an associated depth stencil target.
Provides effects and shader management functionality.
virtual SamplerStateBindingHandle getSamplerStateBinding(EffectHandle effectHandle, const StringView &name, const unsigned int slot)=0
Get a handle to a sampler state object binding, mapping how to bind the sampler state to the given ef...
virtual ConstantBufferBindingHandle getConstantBufferBinding(EffectHandle effectHandle, const StringView &name)=0
Get a handle to a constant buffer binding, mapping how to bind a constant buffer to the given effect.
virtual TextureBindingHandle getTextureBinding(EffectHandle effectHandle, const StringView &name, const unsigned int slot)=0
Get a handle to a texture object binding, mapping how to bind textures to the given effect.
virtual EffectHandle loadEffectSource(const StringView &vsSource, const StringView &psSource, EffectFlags::EEffectFlags effectFlags=EffectFlags::None)=0
Load an effect created from the vertex and pixel shader sources given.
Provides render target management functionality.
virtual BlendStateHandle loadBlendState(const BlendState &blendState)=0
Load a blend state object.
virtual DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState)=0
Load a depth stencil state object.
virtual void releaseRenderTarget(RenderTargetHandle renderTargetHandle)=0
Release the render target with the given renderTargetHandle.
virtual RenderTargetHandle createRenderTarget(TextureHandle textureHandle)
Create a render target using the given texture to render into.
Provides texture management functionality.
virtual SamplerStateHandle loadSamplerState(const SamplerState &state)=0
Load a sampler state object.
virtual void releaseTexture(TextureHandle textureHandle)=0
Release the texture with the given textureHandle.
virtual TextureHandle loadTexture(const unsigned char *bytes, unsigned int width, unsigned int height, TextureFormat format, unsigned int flags=0)=0
Load a texture using the given data to populate the texture contents.
Describes a single render target view and which resources to use from the underlying texture.
TextureHandle texture
Texture handle.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
@ MinMagMipPoint
Point sampling for both minification and magnification.
@ Default
Default usage, the texture can be loaded once and bound and sampled in shaders.
@ Dynamic
Buffer will be loaded and modified with some frequency.
Vertex element structure used to describe a single data element in a vertex for the input assembler.