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 = drawContext->binding;
149 auto forwardPermutation = renderingContext->renderer->getEnginePermutations().get(
"Forward");
151 RenderPassOptions passOptions = drawContext->cameraData->passOptions ? *drawContext->cameraData->passOptions : RenderPassOptions{};
152 passOptions.updateHash();
154 const EffectBinding* depthBindings = depthRenderMaterial->checkReady(terrainData.terrainStreamsLayout, forwardPermutation, passOptions,
ClipShapeType(0), drawContext->renderTarget);
155 if (!depthBindings) {
159 if (!bindings->renderEffect->isActive() || !depthBindings->renderEffect->isActive())
return;
162 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, *drawContext->cameraData);
164 const size_t permutation = drawContext->permutationIndex;
165 terrainData.renderContext.permutation = permutation;
166 auto & permutationRenderContextData = terrainData.renderContext.getPermutationDependentRenderContextData(permutation);
167 permutationRenderContextData.clipmapEffect = bindings->renderEffect->effectHandle;
168 permutationRenderContextData.clipmapDepthEffect = depthBindings->renderEffect->effectHandle;
170 auto pass = drawContext->cameraData->renderPass;
172 case RenderPass::Refraction:
173 terrainData.renderContext.renderPass = TerrainRenderPass::Refraction;
175 case RenderPass::Reflection:
176 terrainData.renderContext.renderPass = TerrainRenderPass::Reflection;
178 case RenderPass::Other:
179 terrainData.renderContext.renderPass = TerrainRenderPass::Other;
182 terrainData.renderContext.renderPass = TerrainRenderPass::Main;
187 const bool isRegularPass = effect == bindings->renderEffect->effectHandle;
190 drawContext->deviceContext->setBlendState(drawContext->renderer->getRenderStates().blendStates[terrainItem->blendState].handle);
192 updateSceneBindings(drawContext, drawContext->cameraData, bindings);
193 drawContext->task->applyMaterial(*drawContext, *terrainItem, bindings);
194 updateMaterialBindings(drawContext, renderMaterial, bindings,
true);
195 applyMaterialPerObject(drawContext, renderMaterial, *terrainItem, bindings);
197 drawContext->deviceContext->setBlendState(drawContext->renderer->getRenderStates().blendStates[
size_t(
BlendMode::None)].handle);
199 updateSceneBindings(drawContext, drawContext->cameraData, depthBindings);
200 applyMaterialPerObject(drawContext, depthRenderMaterial, *terrainItem, depthBindings);
204 if (terrainData.visible) {
205 if (terrainData.renderContext.renderPass == TerrainRenderPass::Main) {
206 auto & camSystem = renderingContext->context->cameraSystem;
207 auto mainCam = camSystem->getMainCamera();
209 auto oldData = drawContext->cameraData;
210 for (
auto & cameraComponent : camSystem->pool) {
211 if (mainCam == &cameraComponent)
continue;
214 auto & cameraData = renderingContext->context->cameraSystem->getData(&cameraComponent);
215 drawContext->cameraData = &cameraData;
217 updateEngineBuffers(renderingContext, drawContext->renderTarget, &cameraData,
nullptr);
218 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, cameraData);
219 terrainDepthRender(terrainData.context, &terrainData.renderContext);
222 drawContext->cameraData = oldData;
223 updateEngineBuffers(renderingContext, drawContext->renderTarget, drawContext->cameraData,
nullptr);
224 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, *drawContext->cameraData);
227 terrainDepthRender(terrainData.context, &terrainData.renderContext);
228 terrainRender(terrainData.context, &terrainData.renderContext);
231 if (terrainData.oceanData) {
233 auto oceanRenderComponent = terrainData.oceanData->oceanComponent->getComponent<RenderComponent>();
235 if (oceanRenderComponent && oceanRenderComponent->isVisible()) {
236 terrainDepthRender(terrainData.context, &terrainData.renderContext);
242 if (terrainData.renderContext.oceanEnabled) {
243 auto & oceanData = *terrainData.oceanData;
245 if (!oceanData.initialized)
break;
247 auto renderComponent_ = oceanData.oceanComponent->getComponent<RenderComponent>();
249 if (!renderComponent_->isVisible())
continue;
251 auto & oceanItem = renderList->createCustom(&oceanData.streamsLayout);
252 oceanItem.layer = RenderLayers::Ocean;
254 oceanItem.flags |= RenderItemFlags::Transparent;
256 if ((terrainItem.flags & RenderItemFlags::Transparent) != 0) {
257 oceanItem.drawOrder = terrainItem.drawOrder + 1;
260 oceanItem.drawOrder = 0;
262 oceanItem.materialInstance = oceanData.material.resolve();
263 oceanItem.objectId = renderComponent_->objectId;
266 oceanData.bounds->getBounds(context, oceanData.bbox, dummy_);
268 oceanItem.setBounds(&oceanData.bbox);
270 oceanItem.setCallbackData(&oceanData);
271 oceanItem.callback = [](RenderTaskContext * renderingContext, DrawContext * drawContext,
const RenderItem * oceanItem)
273 auto & oceanData = *oceanItem->getCallbackData<OceanData>();
275 if (drawContext->permutation->isShadowPass())
return;
277 RenderMaterialInstance * oceanRenderMaterial = renderingContext->renderer->getRenderResources().getRenderMaterialInstance(oceanData.material);
279 if (!oceanRenderMaterial)
return;
281 const EffectBinding * oceanBindings = drawContext->binding;
283 if (!oceanBindings || !oceanBindings->renderEffect)
return;
285 if (oceanBindings->renderEffect->isDelayed()) {
286 oceanBindings->renderEffect->requestLoad();
291 if (!oceanBindings->renderEffect->isActive())
return;
292 if (!
HandleIsValid(oceanBindings->sceneBufferBinding))
return;
294 auto & terrainData = *oceanData.terrainData;
296 updateTerrainContext(terrainData, renderingContext, drawContext->renderTarget, *drawContext->cameraData);
298 const size_t permutation = drawContext->permutationIndex;
299 terrainData.renderContext.permutation = permutation;
300 auto & permutationRenderContextData = terrainData.renderContext.getPermutationDependentRenderContextData(permutation);
301 permutationRenderContextData.oceanEffect = oceanBindings->renderEffect->effectHandle;
304 drawContext->task->applyMaterial(*drawContext, *oceanItem, oceanBindings);
305 updateMaterialBindings(drawContext, oceanRenderMaterial, oceanBindings,
false);
306 updateSceneBindings(drawContext, drawContext->cameraData, oceanBindings);
307 applyMaterialPerObject(drawContext, oceanRenderMaterial, *oceanItem, oceanBindings);
310 oceanRender(terrainData.context, &terrainData.renderContext);
316void Cogs::Core::TerrainRenderer::preRender(TerrainComponent & terrain,
const DrawContext * drawContext)
319 if (drawContext->cameraData != &context->cameraSystem->getMainCameraData())
return;
321 auto & terrainData = terrainSystem->getData(&terrain);
323 if (!terrainData.initialized)
return;
325 auto renderComponent = terrain.getComponent<RenderComponent>();
327 if (!renderComponent->isVisible()) {
328 if (terrainData.oceanData) {
330 auto renderComponent_ = terrainData.oceanData->oceanComponent->getComponent<RenderComponent>();
332 if (!renderComponent_->isVisible())
return;
339 updateTerrainContext(terrainData, drawContext->taskContext, drawContext->renderTarget, *drawContext->cameraData);
341 terrainPreRender(terrainData.context, &terrainData.renderContext);
343void Cogs::Core::TerrainRenderer::postRender(TerrainComponent & terrain,
const DrawContext * renderingContext)
345 auto & terrainData = terrainSystem->getData(&terrain);
347 if (!terrainData.initialized)
return;
348 if (!terrainData.visible && !terrainData.oceanData)
return;
349 if (!terrainData.renderContext.context)
return;
351 terrainPostRender(terrainData.context, &terrainData.renderContext);
353 if (terrainRequiresRedraw(terrainData.context)) {
354 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.