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>
44 glm::vec3 lightdir_local;
52 glm::mat4 projectionMatrix;
54 glm::mat4 worldMatrix;
55 glm::vec4 diffuseColor;
58 static const uint32_t indices[] = {
78 static const uint32_t edgeIndices[] = {
88 static const glm::vec3 positions[] = {
100 static const glm::vec4 boxColor[4] = {
101 glm::vec4(0.4f, 1.0f, 0.2f, 1.0f),
102 glm::vec4(0.4f, 1.0f, 1.0f, 1.0f),
103 glm::vec4(0.4f, 0.4f, 1.0f, 1.0f),
104 glm::vec4(1.0f, 0.4f, 1.0f, 1.0f),
109 RenderInstrumentationScope(taskContext->device->
getImmediateContext(), SCOPE_VOLUMETRIC,
"Octtree::debugRenderCallback");
110 auto * device = drawContext->device;
111 auto * context = drawContext->deviceContext;
114 auto & worldFromLocal = drawContext->context->transformSystem->getLocalToWorld(transComp);
123 context->setDepthStencilState(drawContext->renderer->
getRenderStates().commonDepthStates[RenderStates::noWriteDepthStencilState]);
124 context->setBlendState(drawContext->renderer->
getRenderStates().blendStates[size_t(BlendMode::None)].handle);
126 auto cubeIndices = device->getBuffers()->loadIndexBuffer(edgeIndices,
sizeof(edgeIndices) /
sizeof(uint32_t),
sizeof(uint32_t));
130 sizeof(positions) /
sizeof(glm::vec3),
131 Cogs::Core::VertexFormats::Pos3f);
132 uint32_t strides[] = {
sizeof(glm::vec3) };
133 drawContext->deviceContext->
setVertexBuffers(&cubeVertices, 1, strides,
nullptr);
135 context->setInputLayout(octSys->inputLayoutHandle);
136 context->setEffect(octSys->effectHandle);
144 Volumetric::OctSystem::LocalFromIndexSpaceTransform(*octtreeData->comp, *octtreeData)*
145 glm::translate(glm::mat4(), glm::vec3(node.extentMin)) *
146 glm::scale(glm::mat4(), glm::vec3(node.extentMax - node.extentMin));
161 constants->projectionMatrix = drawContext->cameraData->projectionMatrix;
162 constants->viewMatrix = drawContext->cameraData->viewMatrix;
163 constants->worldMatrix = world;
164 constants->diffuseColor = boxColor[node.ix4.w & 3];
167 context->setConstantBuffer(
"DebugBuffer", constantBuffer);
173 for (
const auto nodeIx : octtreeData->front) {
174 renderNode(octtreeData->nodes[nodeIx]);
177 for (
const auto & node : octtreeData->nodes) {
183 for (
const auto & it : octtreeData->baseBlocks) {
184 const auto & baseBlock = it.second;
186 glm::mat4 world = glm::translate(glm::vec3(baseBlock.i - 0x7fff,
187 baseBlock.j - 0x7fff,
188 baseBlock.k - 0x7fff));
192 constants->projectionMatrix = drawContext->cameraData->projectionMatrix;
193 constants->viewMatrix = drawContext->cameraData->viewMatrix;
194 constants->worldMatrix = world;
195 constants->diffuseColor = boxColor[node.ix4.w & 3];
198 context->setConstantBuffer(
"DebugBuffer", constantBuffer);
204 device->getBuffers()->releaseBuffer(constantBuffer);
205 device->getBuffers()->releaseIndexBuffer(cubeIndices);
206 device->getBuffers()->releaseVertexBuffer(cubeVertices);
212 const auto * octComp = octData->comp;
213 const auto * camData = drawContext->cameraData;
214 auto * renderer = taskContext->renderer;
217 auto * iContext = device->getImmediateContext();
218 auto * octtreeRenderer = octComp->system->renderer;
220 iContext->setViewport(camData->viewportOrigin.x,
221 camData->viewportOrigin.y,
222 camData->viewportSize.x != 0 ? camData->viewportSize.x : renderer->getSize().x,
223 camData->viewportSize.y != 0 ? camData->viewportSize.y : renderer->getSize().y);
226 iContext->setDepthStencilState(taskContext->states->commonDepthStates[item->depthState]);
228 iContext->setBlendState(taskContext->states->blendStates[item->blendState].handle);
231 const RenderPassOptions passOptions = initRenderPassOptions(*camData, item->materialInstance);
232 iContext->setRasterizerState(taskContext->states->rasterizerStateHandles[getRasterizerState(renderer, *item, passOptions, camData->flipWindingOrder)]);
234 applyMaterialPermutation(taskContext, drawContext, drawContext->binding, item->renderMaterialInstance);
235 task->applyMaterial(*drawContext, *item, drawContext->binding);
237 applyMaterialInstance(drawContext, drawContext->binding, item->renderMaterialInstance);
240 assert(item->renderMaterialInstance);
243 octtreeRenderer->cubeVertices,
244 octData->instanceBufferHandle
248 iContext->setVertexBuffers(vertexBuffers, 2);
249 iContext->setIndexBuffer(octtreeRenderer->cubeIndices);
251 EngineBuffers & engineBuffers = renderer->getEngineBuffers();
252 ObjectBuffer & objectParameters = engineBuffers.objectBuffer;
255 const auto & worldMatrix = taskContext->context->transformSystem->getLocalToWorld(octComp->getComponent<
TransformComponent>());
256 auto worldFromIndex =
258 Volumetric::OctSystem::LocalFromIndexSpaceTransform(*octComp, *octData);
260 objectParameters.encodeWorldMatrix(worldFromIndex);
262 auto localToView = camData->viewMatrix * worldFromIndex;
264 const auto bindings = drawContext->binding;
268 if (objectBuffer) std::memcpy(objectBuffer.get(), &objectParameters,
sizeof(
ObjectBuffer));
270 iContext->setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
271 auto octBinding = effects->getConstantBufferBinding(drawContext->binding->renderEffect->effectHandle,
"OctParams");
274 auto eye_local = glm::inverse(localToView)*glm::vec4(0, 0, 0, 1);
278 op->eye_local = (1.f / eye_local.w)*glm::vec3(eye_local);
279 op->valueMin = octComp->valueMin;
280 op->lightdir_local = -glm::normalize(glm::vec3(1, 1, 1));
281 op->valueScale = 1.f / (octComp->valueMax - octComp->valueMin);
282 op->turbidity = std::max(1.f, octComp->turbidity);
283 op->ageScale = octComp->ageScale;
286 iContext->setConstantBuffer(octBinding, octtreeRenderer->octParamsBuffer);
290 iContext->setTexture(
"atlasTexture0", unit, octData->atlas.textureAtlas0);
291 iContext->setSamplerState(
"atlasSampler0", unit, octtreeRenderer->atlasSampler);
295 iContext->setTexture(
"atlasTexture1", unit, octData->atlas.textureAtlas1);
296 iContext->setSamplerState(
"atlasSampler1", unit, octtreeRenderer->atlasSampler);
300 RenderTexture * transferTex = drawContext->renderer->getRenderResources().getRenderTexture(octComp->transferTexture);
301 if (transferTex ==
nullptr)
return;
303 iContext->setTexture(
"transferTexture", unit, transferTex->textureHandle);
304 iContext->setSamplerState(
"transferSampler", unit, octtreeRenderer->atlasSampler);
313 octSystem = ExtensionRegistry::getExtensionSystem<OctSystem>(context);
314 this->device = device;
315 this->context = context;
322 cubeVertices = device->
getBuffers()->
loadVertexBuffer(positions,
sizeof(positions) /
sizeof(glm::vec3), Cogs::Core::VertexFormats::Pos3f);
329 atlasSampler = textures->loadSamplerState(sampler);
342 octStreamsLayout.
vertexFormats[1] = Cogs::VertexFormats::createVertexFormat(elements, std::size(elements));
346 defaultMatInstance = context->materialInstanceManager->createMaterialInstance(context->materialManager->getDefaultMaterial());
351 auto * iContext = device->getImmediateContext();
352 auto * buffers = device->getBuffers();
356 for (
auto & octComp : octSystem->pool) {
357 auto & octData = octSystem->getData(&octComp);
359 if (octData.gpuCacheWipe) handleAtlasWipe(renderingContext, octComp, octData);
361 octData.atlas.handleStaging(renderingContext, octComp, octData, octData.currentTimestamp);
363 octData.instanceCount =
static_cast<unsigned>(octData.front.size());
364 if (octData.instanceCount) {
366 static bool missingDataPrev =
false;
368 bool missingData =
false;
370 unsigned W = octComp.tileSize * octComp.gpuCacheSize;
372 float texW = (octComp.tileSize - 2.f) / W;
373 float texS = 1.f / W;
375 octData.instanceBufferHandle = buffers->loadVertexBuffer(
nullptr, octData.instanceCount, octStreamsLayout.vertexFormats[1]);
379 for (
size_t i = 0; i < octData.instanceCount; i++) {
380 const auto & node = octData.nodes[octData.front[i]];
382 auto slotPos = octData.atlas.slotPosition(octComp, createTileKey(node.ix4, octData.alignMinToZeroShift));
384 bool missing = (slotPos.x == 0) && (slotPos.y == 0) && (slotPos.z == 0);
386 if (missing) missingData =
true;
389 const float scale =
static_cast<float>(1 << node.ix4.w);
390 const glm::uvec3 lll = glm::uvec3(node.ix4.x << node.ix4.w,
391 node.ix4.y << node.ix4.w,
392 node.ix4.z << node.ix4.w);
394 float ageShift = 0.f;
395 if (octComp.alphaCallback.func) {
396 ageShift = octComp.alphaCallback.func(octComp.alphaCallback.data,
397 octData.atlas.slots[slotPos.w].clientData);
400 instanceData[i].min = glm::vec4((1.f / scale)*glm::vec3(glm::uvec3(node.extentMin) - lll), ageShift);
401 instanceData[i].max = glm::vec4((1.f / scale)*glm::vec3(glm::uvec3(node.extentMax) - lll), 0.f);
403 instanceData[i].texpos = glm::vec4((
float)slotPos.x / octComp.gpuCacheSize + texS,
404 (
float)slotPos.y / octComp.gpuCacheSize + texS,
405 (
float)slotPos.z / octComp.gpuCacheSize + texS,
406 missing ? -1.f : texW);
408 assert(0 <= instanceData[i].min.x);
409 assert(0 <= instanceData[i].min.y);
410 assert(0 <= instanceData[i].min.z);
411 assert(instanceData[i].max.x <= 1.f);
412 assert(instanceData[i].max.y <= 1.f);
413 assert(instanceData[i].max.z <= 1.f);
414 instanceData[i].key = node.ix4;
417 if (missingDataPrev != missingData) {
419 missingDataPrev = missingData;
427 for (
const auto & octRenderComp : octSystem->pool) {
428 auto & octRenderData = octSystem->getData(&octRenderComp);
429 if (octRenderData.instanceCount) {
430 buffers->releaseVertexBuffer(octRenderData.instanceBufferHandle);
441 octData.gpuCacheWipe =
false;
444 while (!octData.tileResponses.empty()) {
445 octData.tileResponsesStash.push_back(std::move(octData.tileResponses.back()));
446 octData.tileResponses.pop_back();
448 octData.atlas.reset(renderingContext, octData, octComp.tileSize, octComp.gpuCacheSize, octData.currentTimestamp);
453 for (
auto & octComp : octSystem->pool) {
455 if (sceneComp->visible ==
false)
continue;
458 if (!transformComponent)
continue;
460 auto & octData = octSystem->getData(&octComp);
461 if (octData.instanceCount == 0)
continue;
465 if (octComp.drawDebug) {
466 auto & item = renderList->createCustom(&debugStreamsLayout);
467 item.
layer = RenderLayers::Default;
471 item.materialInstance = defaultMatInstance.resolve();
476 item.flags = RenderItemFlags::Custom;
477 item.setCallbackData(&octData);
478 item.callback = octtreeDebugRenderCallback;
481 auto & item = renderList->createCustom(&octStreamsLayout);
482 item.
layer = RenderLayers::Default;
485 item.materialInstance = octData.materialInstance.
resolve();
492 item.flags = RenderItemFlags::Custom2 | RenderItemFlags::Transparent;
493 item.setCallbackData(&octData);
494 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.
@ TriangleList
List of triangles.
@ 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.
bool isDebugEffectReady(Context *context)
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.
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.