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 bool useCamData = 2.f < std::min(camData->viewportSize.x, camData->viewportSize.y);
49 Renderer* renderer = taskContext->renderer;
50 float w = useCamData ? camData->viewportSize.x : (drawContext->renderTarget ? drawContext->renderTarget->width : renderer->
getSize().x);
51 float h = useCamData ? camData->viewportSize.y : (drawContext->renderTarget ? drawContext->renderTarget->height : renderer->
getSize().y);
64 iContext->
setViewport(camData->viewportOrigin.x, camData->viewportOrigin.y, w, h);
66 iContext->
setBlendState(taskContext->states->blendStates[renderItem->blendState].handle);
68 const RenderPassOptions passOptions = initRenderPassOptions(*renderItem, *camData);
69 iContext->
setRasterizerState(taskContext->states->rasterizerStateHandles[getRasterizerState(renderer, *renderItem, passOptions, camData->flipWindingOrder,
true)]);
73 applyMaterialPermutation(taskContext, drawContext, renderItem->binding, renderItem->renderMaterialInstance);
77 drawContext->task->applyMaterial(*drawContext, *renderItem);
80 applyMaterialInstance(drawContext, renderItem->binding, renderItem->renderMaterialInstance);
82 updateSceneBindings(drawContext, drawContext->cameraData, renderItem->binding);
84 updateMaterialBindings(drawContext, renderItem->renderMaterialInstance, renderItem->binding,
true);
88 const glm::mat3 viewFromLocal = glm::mat3(drawContext->cameraData->viewMatrix) * rendererData->worldFromLocal;
89 const glm::mat3 localFromView = rendererData->localFromWorld * glm::mat3(drawContext->cameraData->inverseViewMatrix);
90 const float clipSpaceNearPlane = drawContext->context->
variables->get(
"renderer.reverseDepth",
false) ? 1.f : -1.f;
92 const EngineBuffers& engineBuffers = *drawContext->engineBuffers;
96 .worldFromLocal = rendererData->worldFromLocal,
97 .localFromWorld = rendererData->localFromWorld,
98 .clipSpaceNearPlane = clipSpaceNearPlane,
99 .valueScale = rendererData->value.scale,
100 .valueBias = rendererData->value.bias,
101 .depthScale = rendererData->depth.scale,
102 .depthBias = rendererData->depth.bias,
103 .baseSize = float(rendererData->baseSize),
104 .noDataDepth = rendererData->noDataDepth
106 iContext->
updateBuffer(rendererData->constants, &constants,
sizeof(constants));
112 objectBuffer.objectId = renderItem->
objectId;
113 iContext->
updateBuffer(rendererData->constants, &objectBuffer,
sizeof(objectBuffer));
114 iContext->
setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
117 iContext->
setTexture(
"encodedTrees", 0, rendererData->encodedTreesTex);
120 iContext->
setTexture(
"tilesValue", 1, rendererData->value.tilesTex);
123 iContext->
setTexture(
"tilesDepth", 2, rendererData->depth.tilesTex);
131 constexpr const char* atlasBlitVS_es30 = R
"(#version 300 es
132precision highp float;
136 gl_Position = vec4(a_POSITION, 0, 1);
140 constexpr const char* atlasBlitFloatPS_es30 = R
"(#version 300 es
141precision highp float;
142precision highp sampler2DArray;
146uniform sampler2DArray source;
150 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
154 constexpr const char* atlasBlitUIntPS_es30 = R
"(#version 300 es
155precision highp float;
157precision highp usampler2DArray;
161uniform usampler2DArray source;
162out uvec4 destination;
165 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
175 auto& atlasBlit = rendererExtension->atlasBlit;
183 atlasBlit.f.effect = effects->
loadEffectSource(atlasBlitVS_es30, atlasBlitFloatPS_es30);
185 atlasBlit.f.inputLayout = buffers->
loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.
vertexFormats[0], 1, atlasBlit.f.effect);
186 atlasBlit.f.srcTexBinding = effects->
getTextureBinding(atlasBlit.f.effect,
"source", 0);
191 atlasBlit.u.effect = effects->
loadEffectSource(atlasBlitVS_es30, atlasBlitUIntPS_es30);
193 atlasBlit.u.inputLayout = buffers->
loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.
vertexFormats[0], 1, atlasBlit.u.effect);
194 atlasBlit.u.srcTexBinding = effects->
getTextureBinding(atlasBlit.u.effect,
"source", 0);
206 .comparisonFunction = Cogs::SamplerState::ComparisonFunction::Never,
208 .borderColor = { 0, 0, 0, 1 }
212 .depthEnabled =
false,
213 .writeEnabled =
true,
219 .sourceBlend = Cogs::BlendState::Blend::One,
220 .destinationBlend = Cogs::BlendState::Blend::Zero,
221 .operation = Cogs::BlendState::BlendOperation::Add
228 uint32_t w, uint32_t h, Cogs::TextureFormat fmt)
230 bool formatIsFloat =
true;
232 case Cogs::DataFormat::R8G8B8A8_UNORM:
233 case Cogs::DataFormat::R8G8B8A8_UNORM_SRGB:
234 formatIsFloat =
true;
239 case Cogs::DataFormat::R16_UINT:
240 formatIsFloat =
false;
246 LOG_ERROR_ONCE(logger,
"Trying to blit unsupported format: %d",
static_cast<uint32_t
>(fmt));
256 .layerIndex =
static_cast<uint16_t
>(dstLayer),
263 immediateContext->
setViewport(0.f, 0.f,
static_cast<float>(w),
static_cast<float>(h));
264 immediateContext->
updateBuffer(rendererExtension->atlasBlit.paramBuffer, &srcLayer,
sizeof(uint32_t));
266 immediateContext->
setEffect(rendererExtension->atlasBlit.f.effect);
267 immediateContext->
setInputLayout(rendererExtension->atlasBlit.f.inputLayout);
268 immediateContext->
setConstantBuffer(rendererExtension->atlasBlit.f.paramBinding, rendererExtension->atlasBlit.paramBuffer);
269 immediateContext->
setTexture(rendererExtension->atlasBlit.f.srcTexBinding, srcTex);
270 immediateContext->
setSamplerState(rendererExtension->atlasBlit.f.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
273 immediateContext->
setEffect(rendererExtension->atlasBlit.u.effect);
274 immediateContext->
setInputLayout(rendererExtension->atlasBlit.u.inputLayout);
275 immediateContext->
setConstantBuffer(rendererExtension->atlasBlit.u.paramBinding, rendererExtension->atlasBlit.paramBuffer);
276 immediateContext->
setTexture(rendererExtension->atlasBlit.u.srcTexBinding, srcTex);
277 immediateContext->
setSamplerState(rendererExtension->atlasBlit.u.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
279 immediateContext->
setVertexBuffers(&rendererExtension->fullScreenTriangle.vertices, 1);
281 immediateContext->
setBlendState(rendererExtension->atlasBlit.blendState);
296 this->device = device;
297 this->context = context;
298 im360System = ExtensionRegistry::getExtensionSystem<Image360System>(context);
306 fullScreenTriangle.streamsLayout.vertexFormats[0] = VertexFormats::createVertexFormat(element);
307 fullScreenTriangle.streamsLayout.numStreams = 1;
308 fullScreenTriangle.streamsLayout.updateHash();
310 static const float fullScreenTriangleVertexData[] = {
315 fullScreenTriangle.vertices = buffers->
loadVertexBuffer(fullScreenTriangleVertexData,
316 sizeof(fullScreenTriangleVertexData) /
sizeof(fullScreenTriangleVertexData[0]),
317 fullScreenTriangle.streamsLayout.vertexFormats[0]);
318 atlasBlitInit(context,
this);
322void Cogs::Core::Image360::RendererExtension::release()
333void Cogs::Core::Image360::RendererExtension::releaseRenderingResources(
RendererExtensionData& rendererData)
358 rendererData.depth.tilesData.clear();
364 if (!renderingContext)
return;
368 RenderResources & resources = renderingContext->renderer->getRenderResources();
370 IContext* deviceContext = renderingContext->deviceContext;
376 Image360Data& im360Data = im360System->getData(&im360Comp);
379 if ((im360Data.state == Image360Data::State::WaitingForBaseLevel) || (im360Data.state == Image360Data::State::Running))
381 im360Data.rendererData.baseSize = im360Data.config.
baseSize;
382 im360Data.rendererData.noDataDepth = im360Data.config.
noDataDepth;
385 rendererData.value.scale = channel.scale;
386 rendererData.value.bias = channel.bias;
387 switch (channel.dataType) {
390 rendererData.value.sampler = 3;
393 rendererData.value.sampler = 1;
398 rendererData.value.scale = 1.f;
399 rendererData.value.bias = 0.f;
407 rendererData.depth.scale = channel.scale;
408 rendererData.depth.bias = channel.bias;
409 switch (channel.dataType) {
412 rendererData.depth.sampler = 3;
415 rendererData.depth.sampler = 1;
429 if(!im360Data.lodTree.data.empty()) {
431 desc.target = Cogs::ResourceDimensions::Texture2D;
432 desc.width =
static_cast<uint32_t
>(im360Data.lodTree.data.size());
434 desc.format = Cogs::TextureFormat::R16_SINT;
438 rendererData.encodedTreesTex = textures->
loadTexture(desc, &textureData);
440 if (rendererData.currentTreeSize != desc.width) {
441 rendererData.currentTreeSize = desc.width;
442 LOG_TRACE(logger,
"Current tree size: %u", rendererData.currentTreeSize);
447 uint32_t cacheItemCount = std::max(6u,
static_cast<uint32_t
>(im360Data.cache.items.size()));
448 bool resizeCache = (!
HandleIsValid(im360Data.rendererData.value.tilesTex) ||
454 Cogs::ResourceDimensions target = Cogs::ResourceDimensions::Unknown;
457 rendererData.cacheLayout.cols = 1;
458 rendererData.cacheLayout.rows = 1;
460 target = Cogs::ResourceDimensions::Texture2DArray;
465 desc.target = target;
466 desc.width = rendererData.cacheLayout.cols * im360Data.config.
baseSize;
467 desc.height = rendererData.cacheLayout.rows * im360Data.config.
baseSize;
468 desc.layers = rendererData.cacheLayout.layers;
477 desc.format = Cogs::DataFormat::R8G8B8A8_UNORM_SRGB;
481 desc.format = Cogs::DataFormat::R16_UINT;
484 assert(
false &&
"Invalid enum value");
488 rendererData.value.tilesTex = textures->
loadTexture(desc,
nullptr);
491 for (uint32_t i = 0; i < toCopy; i++) {
492 if (im360Data.cache.items[i].value.state == Cache::Item::State::Resident) {
493 if (!atlasTileBlit(context,
this,
494 rendererData.value.tilesTex, i,
498 deviceContext->copyTexture(rendererData.value.tilesTex,
500 tilesValueOldTex, i);
512 desc.target = target;
513 desc.width = rendererData.cacheLayout.cols * im360Data.config.
baseSize;
514 desc.height = rendererData.cacheLayout.rows * im360Data.config.
baseSize;
515 desc.layers = rendererData.cacheLayout.layers;
520 desc.format = Cogs::DataFormat::R16_UINT;
523 assert(
false &&
"Invalid enum value");
527 rendererData.depth.tilesTex = textures->
loadTexture(desc,
nullptr);
530 for (uint32_t i = 0; i < toCopy; i++) {
531 if (im360Data.cache.items[i].depth.state == Cache::Item::State::Resident) {
532 if (!atlasTileBlit(context,
this,
533 rendererData.depth.tilesTex, i,
537 deviceContext->copyTexture(rendererData.depth.tilesTex,
539 tilesDepthOldTex, i);
553 Cache::Item& item = im360Data.cache.items[loadItem.slotIx];
555 bool consumed =
false;
556 if (loadItem.channelIx == im360Data.config.
valueChannel) {
557 if (item.value.state == Cache::Item::State::Loaded) {
560 uint32_t slice = loadItem.slotIx;
562 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
563 deviceContext->copyTexture(rendererData.value.tilesTex,
565 texture->textureHandle, 0);
566 item.value.state = Cache::Item::State::Resident;
571 if (loadItem.channelIx == im360Data.config.
depthChannel) {
572 if (item.depth.state == Cache::Item::State::Loaded) {
575 uint32_t slice = loadItem.slotIx;
577 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
578 deviceContext->copyTexture(rendererData.depth.tilesTex,
580 texture->textureHandle, 0);
581 item.depth.state = Cache::Item::State::Resident;
583 size_t tileByteSize =
sizeof(uint16_t) * im360Data.config.
baseSize * im360Data.config.
baseSize;
584 if (loadItem.buffer && loadItem.buffer->size() == tileByteSize) {
586 if (0 <= loadItem.slotIx &&
size_t(loadItem.slotIx) < rendererData.depth.tilesData.size()) {
587 rendererData.depth.tilesData[loadItem.slotIx] = std::move(loadItem.buffer);
595 LOG_WARNING(logger,
"Unexpected load item not uploaded to GPU");
598 im360Data.fetcher.itemsUploading.clear();
603 releaseRenderingResources(rendererData);
619 if (!renderingContext)
return;
625 Image360Data& im360Data = im360System->getData(&im360Comp);
626 if (im360Data.state != Image360Data::State::Running)
continue;
631 RenderItem& renderItem = renderList->createCustom(&fullScreenTriangle.streamsLayout);
632 renderItem.lod = im360Comp.lod;
634 renderItem.cullingIndex = ~0u;;
637 renderItem.flags |= materialInstance->
hasTransparency() ? RenderItemFlags::Transparent : RenderItemFlags::None;
638 if (materialInstance->
isBackdrop() || ((renderItem.
layer & RenderLayers::Sky)) != RenderLayers::None) {
639 renderItem.flags |= RenderItemFlags::Backdrop;
641 renderItem.materialInstance = materialInstance;
642 getTransparencyState(renderingContext->renderer->
getRenderStates(), materialInstance, renderItem);
644 renderItem.setCallbackData(
this);
645 renderItem.setCallbackData2(&im360Data.rendererData);
646 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.
glm::vec2 getSize() const override
Get the output surface size of 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.
@ 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::EPrimitiveType 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.
@ TriangleStrip
Triangle strip.
@ TriangleList
List of triangles.
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.