1#include "Renderer/Tasks/RenderListTask.h"
2#include "Renderer/Renderer.h"
3#include "Renderer/RenderStateUpdater.h"
4#include "Renderer/Tasks/FilterListTask.h"
5#include "Resources/VertexFormats.h"
6#include "Resources/MaterialManager.h"
7#include "Components/Core/RenderComponent.h"
8#include "Components/Core/SceneComponent.h"
9#include "Systems/Core/CameraSystem.h"
10#include "Systems/Core/TransformSystem.h"
11#include "Renderer/Tasks/RenderListTask.h"
12#include "ExtensionRegistry.h"
14#include "OctRenderer.h"
15#include "../Systems/OctSystem.h"
17#include "Rendering/RasterizerState.h"
18#include "Rendering/IGraphicsDevice.h"
19#include "Rendering/IBuffers.h"
20#include "Rendering/IRenderTargets.h"
22#include "Foundation/Memory/MemoryBuffer.h"
24#include <unordered_map>
43 glm::vec3 lightdir_local;
51 glm::mat4 projectionMatrix;
53 glm::mat4 worldMatrix;
54 glm::vec4 diffuseColor;
57 static const uint32_t indices[] = {
77 static const uint32_t edgeIndices[] = {
87 static const glm::vec3 positions[] = {
99 static const glm::vec4 boxColor[4] = {
100 glm::vec4(0.4f, 1.0f, 0.2f, 1.0f),
101 glm::vec4(0.4f, 1.0f, 1.0f, 1.0f),
102 glm::vec4(0.4f, 0.4f, 1.0f, 1.0f),
103 glm::vec4(1.0f, 0.4f, 1.0f, 1.0f),
108 RenderInstrumentationScope(taskContext->device->
getImmediateContext(), SCOPE_VOLUMETRIC,
"Octtree::debugRenderCallback");
109 auto * device = drawContext->device;
110 auto * context = drawContext->deviceContext;
113 auto & worldFromLocal = drawContext->context->transformSystem->getLocalToWorld(transComp);
117 context->setDepthStencilState(drawContext->renderer->
getRenderStates().noWriteDepthStencilStateHandle);
118 context->setBlendState(drawContext->renderer->
getRenderStates().blendStates[size_t(BlendMode::None)].handle);
120 auto cubeIndices = device->getBuffers()->loadIndexBuffer(edgeIndices,
sizeof(edgeIndices) /
sizeof(uint32_t),
sizeof(uint32_t));
124 sizeof(positions) /
sizeof(glm::vec3),
125 Cogs::Core::VertexFormats::Pos3f);
126 uint32_t strides[] = {
sizeof(glm::vec3) };
127 drawContext->deviceContext->
setVertexBuffers(&cubeVertices, 1, strides,
nullptr);
129 auto octSys = octtreeData->comp->system;
131 context->setInputLayout(octSys->inputLayoutHandle);
132 context->setEffect(octSys->effectHandle);
140 Volumetric::OctSystem::LocalFromIndexSpaceTransform(*octtreeData->comp, *octtreeData)*
141 glm::translate(glm::mat4(), glm::vec3(node.extentMin)) *
142 glm::scale(glm::mat4(), glm::vec3(node.extentMax - node.extentMin));
157 constants->projectionMatrix = drawContext->cameraData->projectionMatrix;
158 constants->viewMatrix = drawContext->cameraData->viewMatrix;
159 constants->worldMatrix = world;
160 constants->diffuseColor = boxColor[node.ix4.w & 3];
163 context->setConstantBuffer(
"DebugBuffer", constantBuffer);
169 for (
const auto nodeIx : octtreeData->front) {
170 renderNode(octtreeData->nodes[nodeIx]);
173 for (
const auto & node : octtreeData->nodes) {
179 for (
const auto & it : octtreeData->baseBlocks) {
180 const auto & baseBlock = it.second;
182 glm::mat4 world = glm::translate(glm::vec3(baseBlock.i - 0x7fff,
183 baseBlock.j - 0x7fff,
184 baseBlock.k - 0x7fff));
188 constants->projectionMatrix = drawContext->cameraData->projectionMatrix;
189 constants->viewMatrix = drawContext->cameraData->viewMatrix;
190 constants->worldMatrix = world;
191 constants->diffuseColor = boxColor[node.ix4.w & 3];
194 context->setConstantBuffer(
"DebugBuffer", constantBuffer);
200 device->getBuffers()->releaseBuffer(constantBuffer);
201 device->getBuffers()->releaseIndexBuffer(cubeIndices);
202 device->getBuffers()->releaseVertexBuffer(cubeVertices);
208 const auto * octComp = octData->comp;
209 const auto * camData = drawContext->cameraData;
210 auto * renderer = taskContext->renderer;
213 auto * iContext = device->getImmediateContext();
214 auto * octtreeRenderer = octComp->system->renderer;
216 iContext->setViewport(camData->viewportOrigin.x,
217 camData->viewportOrigin.y,
218 camData->viewportSize.x != 0 ? camData->viewportSize.x : renderer->getSize().x,
219 camData->viewportSize.y != 0 ? camData->viewportSize.y : renderer->getSize().y);
222 iContext->setDepthStencilState(taskContext->states->commonDepthStates[item->depthState]);
224 iContext->setBlendState(taskContext->states->blendStates[item->blendState].handle);
228 iContext->setRasterizerState(taskContext->states->rasterizerStateHandles[getRasterizerState(renderer, *item, passOptions, camData->flipWindingOrder)]);
230 applyMaterialPermutation(taskContext, drawContext, item->binding, item->renderMaterialInstance);
231 task->applyMaterial(*drawContext, *item);
233 applyMaterialInstance(drawContext, item->binding, item->renderMaterialInstance);
236 assert(item->renderMaterialInstance);
239 octtreeRenderer->cubeVertices,
240 octData->instanceBufferHandle
244 iContext->setVertexBuffers(vertexBuffers, 2);
245 iContext->setIndexBuffer(octtreeRenderer->cubeIndices);
247 EngineBuffers & engineBuffers = renderer->getEngineBuffers();
248 ObjectBuffer & objectParameters = engineBuffers.objectBuffer;
251 const auto & worldMatrix = taskContext->context->transformSystem->getLocalToWorld(octComp->getComponent<
TransformComponent>());
252 auto worldFromIndex =
254 Volumetric::OctSystem::LocalFromIndexSpaceTransform(*octComp, *octData);
256 objectParameters.worldMatrix = worldFromIndex;
258 auto localToView = camData->viewMatrix * objectParameters.worldMatrix;
260 const auto bindings = item->binding;
264 if (objectBuffer) std::memcpy(objectBuffer.get(), &objectParameters,
sizeof(
ObjectBuffer));
266 iContext->setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
267 auto octBinding = effects->getConstantBufferBinding(item->binding->renderEffect->effectHandle,
"OctParams");
270 auto eye_local = glm::inverse(localToView)*glm::vec4(0, 0, 0, 1);
274 op->eye_local = (1.f / eye_local.w)*glm::vec3(eye_local);
275 op->valueMin = octComp->valueMin;
276 op->lightdir_local = -glm::normalize(glm::vec3(1, 1, 1));
277 op->valueScale = 1.f / (octComp->valueMax - octComp->valueMin);
278 op->turbidity = std::max(1.f, octComp->turbidity);
279 op->ageScale = octComp->ageScale;
282 iContext->setConstantBuffer(octBinding, octtreeRenderer->octParamsBuffer);
286 iContext->setTexture(
"atlasTexture0", unit, octData->atlas.textureAtlas0);
287 iContext->setSamplerState(
"atlasSampler0", unit, octtreeRenderer->atlasSampler);
291 iContext->setTexture(
"atlasTexture1", unit, octData->atlas.textureAtlas1);
292 iContext->setSamplerState(
"atlasSampler1", unit, octtreeRenderer->atlasSampler);
296 RenderTexture * transferTex = drawContext->renderer->getRenderResources().getRenderTexture(octComp->transferTexture);
297 if (transferTex ==
nullptr)
return;
299 iContext->setTexture(
"transferTexture", unit, transferTex->textureHandle);
300 iContext->setSamplerState(
"transferSampler", unit, octtreeRenderer->atlasSampler);
309 octSystem = ExtensionRegistry::getExtensionSystem<OctSystem>(context);
310 this->device = device;
311 this->context = context;
318 cubeVertices = device->
getBuffers()->
loadVertexBuffer(positions,
sizeof(positions) /
sizeof(glm::vec3), Cogs::Core::VertexFormats::Pos3f);
325 atlasSampler = textures->loadSamplerState(sampler);
338 octStreamsLayout.
vertexFormats[1] = Cogs::VertexFormats::createVertexFormat(elements, glm::countof(elements));
342 defaultMatInstance = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
347 auto * iContext = device->getImmediateContext();
348 auto * buffers = device->getBuffers();
352 for (
auto & octComp : octSystem->pool) {
353 auto & octData = octSystem->getData(&octComp);
355 if (octData.gpuCacheWipe) handleAtlasWipe(renderingContext, octComp, octData);
357 octData.atlas.handleStaging(renderingContext, octComp, octData, octData.currentTimestamp);
359 octData.instanceCount =
static_cast<unsigned>(octData.front.size());
360 if (octData.instanceCount) {
362 static bool missingDataPrev =
false;
364 bool missingData =
false;
366 unsigned W = octComp.tileSize * octComp.gpuCacheSize;
368 float texW = (octComp.tileSize - 2.f) / W;
369 float texS = 1.f / W;
371 octData.instanceBufferHandle = buffers->loadVertexBuffer(
nullptr, octData.instanceCount, octStreamsLayout.vertexFormats[1]);
375 for (
size_t i = 0; i < octData.instanceCount; i++) {
376 const auto & node = octData.nodes[octData.front[i]];
378 auto slotPos = octData.atlas.slotPosition(octComp, createTileKey(node.ix4, octData.alignMinToZeroShift));
380 bool missing = (slotPos.x == 0) && (slotPos.y == 0) && (slotPos.z == 0);
382 if (missing) missingData =
true;
385 const float scale =
static_cast<float>(1 << node.ix4.w);
386 const glm::uvec3 lll = glm::uvec3(node.ix4.x << node.ix4.w,
387 node.ix4.y << node.ix4.w,
388 node.ix4.z << node.ix4.w);
390 float ageShift = 0.f;
391 if (octComp.alphaCallback.func) {
392 ageShift = octComp.alphaCallback.func(octComp.alphaCallback.data,
393 octData.atlas.slots[slotPos.w].clientData);
396 instanceData[i].min = glm::vec4((1.f / scale)*glm::vec3(glm::uvec3(node.extentMin) - lll), ageShift);
397 instanceData[i].max = glm::vec4((1.f / scale)*glm::vec3(glm::uvec3(node.extentMax) - lll), 0.f);
399 instanceData[i].texpos = glm::vec4((
float)slotPos.x / octComp.gpuCacheSize + texS,
400 (
float)slotPos.y / octComp.gpuCacheSize + texS,
401 (
float)slotPos.z / octComp.gpuCacheSize + texS,
402 missing ? -1.f : texW);
404 assert(0 <= instanceData[i].min.x);
405 assert(0 <= instanceData[i].min.y);
406 assert(0 <= instanceData[i].min.z);
407 assert(instanceData[i].max.x <= 1.f);
408 assert(instanceData[i].max.y <= 1.f);
409 assert(instanceData[i].max.z <= 1.f);
410 instanceData[i].key = node.ix4;
413 if (missingDataPrev != missingData) {
415 missingDataPrev = missingData;
423 for (
const auto & octRenderComp : octSystem->pool) {
424 auto & octRenderData = octSystem->getData(&octRenderComp);
425 if (octRenderData.instanceCount) {
426 buffers->releaseVertexBuffer(octRenderData.instanceBufferHandle);
437 octData.gpuCacheWipe =
false;
440 while (!octData.tileResponses.empty()) {
441 octData.tileResponsesStash.push_back(std::move(octData.tileResponses.back()));
442 octData.tileResponses.pop_back();
444 octData.atlas.reset(renderingContext, octData, octComp.tileSize, octComp.gpuCacheSize, octData.currentTimestamp);
449 for (
auto & octComp : octSystem->pool) {
451 if (sceneComp->visible ==
false)
continue;
454 if (!transformComponent)
continue;
456 auto & octData = octSystem->getData(&octComp);
457 if (octData.instanceCount == 0)
continue;
461 if (octComp.drawDebug) {
462 auto & item = renderList->createCustom(&debugStreamsLayout);
463 item.
layer = RenderLayers::Default;
467 item.materialInstance = defaultMatInstance.resolve();
472 item.flags = RenderItemFlags::Custom;
473 item.setCallbackData(&octData);
474 item.callback = octtreeDebugRenderCallback;
477 auto & item = renderList->createCustom(&octStreamsLayout);
478 item.
layer = RenderLayers::Default;
481 item.materialInstance = octData.materialInstance.
resolve();
488 item.flags = RenderItemFlags::Custom2 | RenderItemFlags::Transparent;
489 item.setCallbackData(&octData);
490 item.callback2 = renderCallback;
ComponentType * getComponent() const
A Context instance contains all the services, systems and runtime components needed to use Cogs.
RenderStates & getRenderStates() override
Get the reference to the RenderStates structure.
IGraphicsDevice * getDevice() override
Get the graphics device used by the renderer.
Contains information on how the entity behaves in the scene.
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.
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.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
@ NoWrite
Depth test enabled, write disabled.
Contains all Cogs related functionality.
@ InstanceData
Per instance data.
@ InstanceVector
Instance vector 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.
std::vector< TextureValue > textureVariables
Texture property values for this instance.
VertexFormatHandle vertexFormats[maxStreams]
COGSCORE_DLL_API void updateHash()
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.
Representing a block or node in the oct-tree.
std::vector< TileRequest > tileRequests
Requests for tiles, populated by OctSystem::update, consumed by provider.
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.
Encapsulates state for depth buffer usage and stencil buffer usage in a state object.
virtual IndexBufferHandle loadIndexBuffer(const void *indexData, const size_t count, const size_t indexSize)=0
Loads a new index buffer and populates it with the given indexData.
virtual VertexBufferHandle loadVertexBuffer(const void *vertexData, const size_t count, const VertexFormat &vertexFormat)=0
Loads a new vertex buffer and populates it with the given data.
virtual void setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride=4, uint32_t offset=0)=0
Sets the current index buffer.
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 DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState)=0
Load a depth stencil state object.
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Provides RAII style mapping of a buffer resource.
@ TriangleList
List of triangles.
static RasterizerState DefaultState()
Constructs a rasterizer state initialized with the default values.
Encapsulates state for texture sampling in a state object.
static SamplerState & DefaultState()
Constructs a sampler state initialized with the default values.
AddressMode addressModeW
Specifies the addressing mode along the W axis in texture coordinate space.
AddressMode addressModeS
Specifies the addressing mode along the S axis in texture coordinate space.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
@ MinMagMipLinear
Linear sampling for both minification and magnification.
FilterMode filter
Specifies the filter to use for texture sampling.
AddressMode addressModeT
Specifies the addressing mode along the T axis in texture coordinate space.
@ 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.