1#include "TerrainRenderer.h"
3#include "RenderContext.h"
6#include "Systems/Core/TransformSystem.h"
7#include "Systems/Core/CameraSystem.h"
9#include "Components/Core/RenderComponent.h"
11#include "Resources/MaterialManager.h"
13#include "Renderer/RenderStateUpdater.h"
14#include "Renderer/RenderMaterialInstance.h"
15#include "Renderer/RenderEffect.h"
16#include "Renderer/RenderTarget.h"
17#include "Renderer/Tasks/RenderListTask.h"
18#include "Renderer/Tasks/GenerateListTask.h"
22#include "TerrainSystem.h"
23#include "OceanSystem.h"
25#include "Renderer/IRenderer.h"
27Cogs::Core::TerrainRenderer::~TerrainRenderer()
32 this->device = device;
33 this->context = context;
35 terrainSystem = ExtensionRegistry::getExtensionSystem<TerrainSystem>(context);
40 if (!renderingContext)
return;
44 for (
auto & terrain : terrainSystem->pool) {
45 preRender(terrain, renderingContext);
49 for (
auto & terrain : terrainSystem->pool) {
50 postRender(terrain, renderingContext);
64 auto & renderContext = terrainData.renderContext;
66 renderContext.renderTarget = renderTarget->renderTargetHandle;
67 renderContext.depthStencilTarget = renderTarget->depthTargetHandle;
69 renderContext.isOIT = renderingContext->renderer->
getSettings().transparencyAlgorithm == RenderSettings::TransparencyAlgorithm::OIT;
71 renderContext.offsetEnabled =
false;
72 renderContext.device = renderingContext->renderer->
getDevice();
74 if (terrainData.viewportFromTarget) {
75 renderContext.width =
static_cast<uint16_t
>(renderTarget->width);
76 renderContext.height =
static_cast<uint16_t
>(renderTarget->height);
77 renderContext.viewportX = 0;
78 renderContext.viewportY = 0;
81 renderContext.width =
static_cast<uint16_t
>(cameraData.viewportSize.x);
82 renderContext.height =
static_cast<uint16_t
>(cameraData.viewportSize.y);
83 renderContext.viewportX =
static_cast<uint16_t
>(cameraData.viewportOrigin.x);
84 renderContext.viewportY =
static_cast<uint16_t
>(cameraData.viewportOrigin.y);
86 renderContext.cullVolume.frustum = cameraData.frustum;
88 renderContext.origin = renderingContext->context->transformSystem->
getOrigin();
89 renderContext.cullOrigin = renderContext.origin;
90 renderContext.offset = terrainData.offset;
92 renderContext.scene.projectionMatrix = cameraData.projectionMatrix;
93 renderContext.scene.viewMatrix = cameraData.viewMatrix;
94 renderContext.scene.viewMatrixInverse = cameraData.inverseViewMatrix;
96 renderContext.wireframe = renderingContext->renderer->
getMode() == RenderMode::Wireframe;
98 renderContext.maxAppliedTilesPerFrame = terrainData.maxTilesPerFrame;
99 renderContext.offsetEnabled =
false;
101 renderContext.reverseDepth = renderingContext->context->
variables->get(
"renderer.reverseDepth",
false);
103 renderContext.rayPickIndex = cameraData.rayPickId;
108void Cogs::Core::TerrainRenderer::generateCommands(
const RenderTaskContext * renderingContext, RenderList * renderList)
110 for (
auto & terrain : terrainSystem->pool) {
111 auto & terrainData = terrainSystem->getData(&terrain);
113 if (!terrainData.initialized)
continue;
115 auto renderComponent = terrain.getComponent<RenderComponent>();
117 terrainData.visible = renderComponent->isVisible();
120 terrainData.getBounds->getBounds(context, terrainData.bbox, dummy);
122 auto & terrainItem = renderList->createCustom(&terrainData.terrainStreamsLayout);
123 terrainItem.materialInstance = terrain.material.resolve();
125 if (terrainItem.materialInstance) {
126 terrainItem.drawOrder = terrainItem.materialInstance->options.drawOrder;
128 getTransparencyState(*renderingContext->states, terrainItem.materialInstance, terrainItem);
129 if (terrainItem.blendState !=
static_cast<uint16_t
>(
BlendMode::None)) {
130 terrainItem.flags |= RenderItemFlags::Transparent;
132 terrainItem.layer = renderComponent->layer;
133 terrainItem.flags |= RenderItemFlags::Custom;
134 terrainItem.flags |= renderComponent->castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
135 terrainItem.objectId = renderComponent->objectId;
136 terrainItem.setBounds(&terrainData.bbox);
138 terrainItem.setCallbackData(&terrainData);
139 terrainItem.callback = [](RenderTaskContext * renderingContext, DrawContext * drawContext,
const RenderItem * terrainItem)
141 TerrainData & terrainData = *terrainItem->getCallbackData<TerrainData>();
143 RenderMaterialInstance * renderMaterial = renderingContext->renderer->getRenderResources().getRenderMaterialInstance(terrainItem->materialInstance);
144 RenderMaterialInstance * depthRenderMaterial = renderingContext->renderer->getRenderResources().getRenderMaterialInstance(terrainData.depthMaterial);
146 if (!renderMaterial || !depthRenderMaterial)
return;
148 auto bindings = terrainItem->binding;
149 auto forwardPermutation = renderingContext->renderer->getEnginePermutations().get(
"Forward");
151 RenderPassOptions passOptions = drawContext->cameraData->passOptions ? *drawContext->cameraData->passOptions : RenderPassOptions{};
152 passOptions.updateHash();
154 bool depthReady = depthRenderMaterial->checkReady(terrainData.terrainStreamsLayout, forwardPermutation, passOptions,
ClipShapeType(0)) !=
nullptr;
155 if (!depthReady)
return;
157 auto depthBindings = depthRenderMaterial->getBindings(terrainData.terrainStreamsLayout, forwardPermutation, passOptions,
ClipShapeType(0));
158 if (!depthBindings || !depthBindings->renderEffect || depthBindings->renderEffect->isDelayed()) {
162 if (!bindings->renderEffect->isActive() || !depthBindings->renderEffect->isActive())
return;
165 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, *drawContext->cameraData);
167 const size_t permutation = drawContext->permutationIndex;
168 terrainData.renderContext.permutation = permutation;
169 auto & permutationRenderContextData = terrainData.renderContext.getPermutationDependentRenderContextData(permutation);
170 permutationRenderContextData.clipmapEffect = bindings->renderEffect->effectHandle;
171 permutationRenderContextData.clipmapDepthEffect = depthBindings->renderEffect->effectHandle;
173 auto pass = drawContext->cameraData->renderPass;
175 case RenderPass::Refraction:
176 terrainData.renderContext.renderPass = TerrainRenderPass::Refraction;
178 case RenderPass::Reflection:
179 terrainData.renderContext.renderPass = TerrainRenderPass::Reflection;
181 case RenderPass::Other:
182 terrainData.renderContext.renderPass = TerrainRenderPass::Other;
185 terrainData.renderContext.renderPass = TerrainRenderPass::Main;
190 const bool isRegularPass = effect == bindings->renderEffect->effectHandle;
193 drawContext->deviceContext->setBlendState(drawContext->renderer->getRenderStates().blendStates[terrainItem->blendState].handle);
195 updateSceneBindings(drawContext, drawContext->cameraData, bindings);
196 drawContext->task->applyMaterial(*drawContext, *terrainItem);
197 updateMaterialBindings(drawContext, renderMaterial, bindings,
true);
198 applyMaterialPerObject(drawContext, renderMaterial, *terrainItem);
200 drawContext->deviceContext->setBlendState(drawContext->renderer->getRenderStates().blendStates[
size_t(
BlendMode::None)].handle);
202 updateSceneBindings(drawContext, drawContext->cameraData, depthRenderMaterial->getBindings(terrainData.terrainStreamsLayout, forwardPermutation, passOptions,
ClipShapeType(0)));
203 applyMaterialPerObject(drawContext, depthRenderMaterial, *terrainItem);
207 if (terrainData.visible) {
208 if (terrainData.renderContext.renderPass == TerrainRenderPass::Main) {
209 auto & camSystem = renderingContext->context->cameraSystem;
210 auto mainCam = camSystem->getMainCamera();
212 auto oldData = drawContext->cameraData;
213 for (
auto & cameraComponent : camSystem->pool) {
214 if (mainCam == &cameraComponent)
continue;
217 auto & cameraData = renderingContext->context->cameraSystem->getData(&cameraComponent);
218 drawContext->cameraData = &cameraData;
220 updateEngineBuffers(renderingContext, drawContext->renderTarget, &cameraData,
nullptr);
221 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, cameraData);
222 terrainDepthRender(terrainData.context, &terrainData.renderContext);
225 drawContext->cameraData = oldData;
226 updateEngineBuffers(renderingContext, drawContext->renderTarget, drawContext->cameraData,
nullptr);
227 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, *drawContext->cameraData);
230 terrainDepthRender(terrainData.context, &terrainData.renderContext);
231 terrainRender(terrainData.context, &terrainData.renderContext);
234 if (terrainData.oceanData) {
236 auto oceanRenderComponent = terrainData.oceanData->oceanComponent->getComponent<RenderComponent>();
238 if (oceanRenderComponent && oceanRenderComponent->isVisible()) {
239 terrainDepthRender(terrainData.context, &terrainData.renderContext);
245 if (terrainData.renderContext.oceanEnabled) {
246 auto & oceanData = *terrainData.oceanData;
248 if (!oceanData.initialized)
break;
250 auto renderComponent_ = oceanData.oceanComponent->getComponent<RenderComponent>();
252 if (!renderComponent_->isVisible())
continue;
254 auto & oceanItem = renderList->createCustom(&oceanData.streamsLayout);
255 oceanItem.layer = RenderLayers::Ocean;
257 oceanItem.flags |= RenderItemFlags::Transparent;
259 if ((terrainItem.flags & RenderItemFlags::Transparent) != 0) {
260 oceanItem.drawOrder = terrainItem.drawOrder + 1;
263 oceanItem.drawOrder = 0;
265 oceanItem.materialInstance = oceanData.material.resolve();
266 oceanItem.objectId = renderComponent_->objectId;
269 oceanData.bounds->getBounds(context, oceanData.bbox, dummy_);
271 oceanItem.setBounds(&oceanData.bbox);
273 oceanItem.setCallbackData(&oceanData);
274 oceanItem.callback = [](RenderTaskContext * renderingContext, DrawContext * drawContext,
const RenderItem * oceanItem)
276 auto & oceanData = *oceanItem->getCallbackData<OceanData>();
278 if (drawContext->permutation->isShadowPass())
return;
280 RenderMaterialInstance * oceanRenderMaterial = renderingContext->renderer->getRenderResources().getRenderMaterialInstance(oceanData.material);
282 if (!oceanRenderMaterial)
return;
284 const EffectBinding * oceanBindings = oceanItem->binding;
286 if (!oceanBindings || !oceanBindings->renderEffect)
return;
288 if (oceanBindings->renderEffect->isDelayed()) {
289 oceanBindings->renderEffect->requestLoad();
294 if (!oceanBindings->renderEffect->isActive())
return;
295 if (!
HandleIsValid(oceanBindings->sceneBufferBinding))
return;
297 auto & terrainData = *oceanData.terrainData;
299 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, *drawContext->cameraData);
301 const size_t permutation = drawContext->permutationIndex;
302 terrainData.renderContext.permutation = permutation;
303 auto & permutationRenderContextData = terrainData.renderContext.getPermutationDependentRenderContextData(permutation);
304 permutationRenderContextData.oceanEffect = oceanBindings->renderEffect->effectHandle;
307 drawContext->task->applyMaterial(*drawContext, *oceanItem);
308 updateMaterialBindings(drawContext, oceanRenderMaterial, oceanBindings,
false);
309 updateSceneBindings(drawContext, drawContext->cameraData, oceanBindings);
310 applyMaterialPerObject(drawContext, oceanRenderMaterial, *oceanItem);
313 oceanRender(terrainData.context, &terrainData.renderContext);
319void Cogs::Core::TerrainRenderer::preRender(TerrainComponent & terrain,
const DrawContext * drawContext)
322 if (drawContext->cameraData != &context->cameraSystem->getMainCameraData())
return;
324 auto & terrainData = terrainSystem->getData(&terrain);
326 if (!terrainData.initialized)
return;
328 auto renderComponent = terrain.getComponent<RenderComponent>();
330 if (!renderComponent->isVisible()) {
331 if (terrainData.oceanData) {
333 auto renderComponent_ = terrainData.oceanData->oceanComponent->getComponent<RenderComponent>();
335 if (!renderComponent_->isVisible())
return;
342 updateTerrainContext(terrainData, drawContext->taskContext, drawContext->renderTarget, *drawContext->cameraData);
344 terrainPreRender(terrainData.context, &terrainData.renderContext);
346void Cogs::Core::TerrainRenderer::postRender(TerrainComponent & terrain,
const DrawContext * renderingContext)
348 auto & terrainData = terrainSystem->getData(&terrain);
350 if (!terrainData.initialized)
return;
351 if (!terrainData.visible && !terrainData.oceanData)
return;
352 if (!terrainData.renderContext.context)
return;
354 terrainPostRender(terrainData.context, &terrainData.renderContext);
356 if (terrainRequiresRedraw(terrainData.context)) {
357 renderingContext->context->engine->setDirty();
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class Variables > variables
Variables service instance.
IGraphicsDevice * getDevice() override
Get the graphics device used by the renderer.
RenderMode getMode() const override
Get the Rendering mode used by the renderer.
const RenderSettings & getSettings() const override
Get the settings of the renderer.
void initialize(Context *context, IGraphicsDevice *device) override
Initialize the extension using the given context and device.
void handleEvent(uint32_t eventId, const DrawContext *renderingContext) override
Called when rendering events occur.
Represents a graphics device used to manage graphics resources and issue drawing commands.
virtual IContext * getImmediateContext()=0
Get a pointer to the immediate context used to issue commands to the graphics device.
ClipShapeType
Specifices what kind of shape a clip shape has.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
@ EnablePicking
Supports picking.
@ Blend
Render with regular alpha blending.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
Contains all Cogs related functionality.
Contains data describing a Camera instance and its derived data structured such as matrix data and vi...
@ PostRender
Rendering has finished for a given rendering context.
@ PreRender
Pre rendering happening for a given rendering context.