Cogs.Core
DeferredLightingTask.cpp
1#include "DeferredLightingTask.h"
2
3#include "Rendering/IGraphicsDevice.h"
4#include "Rendering/IContext.h"
5#include "Rendering/IEffects.h"
6#include "Rendering/CommandGroupAnnotation.h"
7
8#include "Context.h"
9#include "Renderer/Renderer.h"
10#include "Renderer/RenderTarget.h"
11#include "Renderer/RenderStateUpdater.h"
12#include "Services/Variables.h"
13#include "Systems/Core/LightSystem.h"
14#include "Systems/Core/EnvironmentSystem.h"
15#include "Utilities/Parsing.h"
16
17#include "Foundation/Logging/Logger.h"
18
19#include <cassert>
20
21using namespace Cogs;
22
23namespace
24{
25 Cogs::Logging::Log logger = Cogs::Logging::getLogger("DeferredLightingTask");
26}
27
29{
30 IGraphicsDevice* device = context->renderer->getDevice();
31 IContext* deviceContext = device->getImmediateContext();
32 CommandGroupAnnotation annotation(deviceContext, "DeferredLightingTask::initialize");
33
35 desc.vs = "Engine/FullscreenV3T2VS.hlsl";
36 desc.ps = "Engine/DeferredLightingPS.hlsl";
37 desc.definitions.push_back({ "COGS_FORWARD_SHADOWS_ENABLED", "1" });
38 desc.definitions.push_back({ "COGS_NUM_DIRECTIONAL_SHADOW_LIGHTS", std::to_string(context->renderer->getActiveLights().numDirectionalShadowLights) });
39 desc.definitions.push_back({ "COGS_NUM_DIRECTIONAL_LIGHTS", std::to_string(context->renderer->getActiveLights().numDirectionalLights) });
40 desc.definitions.push_back({ "COGS_NUM_POINT_SHADOW_LIGHTS", std::to_string(context->renderer->getActiveLights().numPointShadowLights) });
41 desc.definitions.push_back({ "COGS_NUM_POINT_LIGHTS", std::to_string(context->renderer->getActiveLights().numPointLights) });
42
43 auto softShadows = parseEnum<SoftShadows>(context->context->variables->get("shadows.softShadows", "Default"));
44 switch (softShadows) {
45 case SoftShadows::High:
46 desc.definitions.push_back({ "COGS_SOFT_SHADOWS_HIGH", "1" });
47 break;
48 case SoftShadows::Low:
49 desc.definitions.push_back({ "COGS_SOFT_SHADOWS_LOW", "1" });
50 break;
51 default:
52 break;
53 }
54 if (auto ec = context->context->environmentSystem->getGlobalEnvironment(); ec != nullptr) {
55 if (ec->subseaSupport) {
56 desc.definitions.push_back({ "COGS_SUBSEA_SUPPORT", "1" });
57 }
58 if (ec->imageBasedLighting) {
59 desc.definitions.push_back({ "COGS_IMAGE_BASED_LIGHTING", "1" });
60 }
61 }
62 if(context->context->variables->get("renderer.reverseDepth", false)){
63 desc.definitions.push_back({ "COGS_REVERSE_DEPTH", "1" });
64 }
65 effect = context->renderer->getEffectCache().loadEffect(context, desc);
66
67 IEffects* effects = device->getEffects();
68 Cogs::ResourceStatus status = HandleIsValid(effect->handle) ? effects->checkEffect(effect->handle) : Cogs::ResourceStatus::Error;
69
70 if (status == Cogs::ResourceStatus::Ready && (effectPrev != effect || effectStatus != Cogs::ResourceStatus::Ready)) {
71 initializeGlobalBindings(context, effect, bindings);
72 }
73
74 if (status == Cogs::ResourceStatus::Error && effectStatus != Cogs::ResourceStatus::Error) {
75 LOG_ERROR(logger, "Invalid deferred lighting effect handle.");
76 }
77
78 effectPrev = effect;
79 effectStatus = status;
80 return effectStatus;
81}
82
83void Cogs::Core::DeferredLightingTask::cleanup(RenderTaskContext * context)
84{
85 context->renderer->getEffectCache().release(context, effect);
86}
87
88void Cogs::Core::DeferredLightingTask::apply(RenderTaskContext * context)
89{
90 RenderInstrumentationScope(context->device->getImmediateContext(), SCOPE_RENDERING, "DeferredLightingTask::apply");
91
92 assert(effectStatus == Cogs::ResourceStatus::Ready);
93
94 RenderTarget* deferredRenderTarget = input.get(RenderResourceType::RenderTarget)->renderTarget;
95 RenderTarget* renderTarget = output.get(RenderResourceType::RenderTarget)->renderTarget;
96
97 IGraphicsDevice* device = context->renderer->getDevice();
98 IContext* deviceContext = device->getImmediateContext();
99
100 deviceContext->setEffect(effect->handle);
101
102 deviceContext->setRenderTarget(renderTarget->renderTargetHandle, DepthStencilHandle::NoHandle);
103
104 deviceContext->setViewport(
105 0,
106 0,
107 context->renderer->getSize().x,
108 context->renderer->getSize().y);
109
110 deviceContext->setDepthStencilState(context->states->commonDepthStates[RenderStates::noTestDepthStencilState]);
111 deviceContext->setRasterizerState(context->states->defaultRasterizerStateHandle);
112 deviceContext->setBlendState(context->states->blendStates[size_t(BlendMode::None)].handle);
113
114 applyGlobalBindings(context, bindings);
115
116 const char * textureName[] = {
117 "colorTexture",
118 "emissiveTexture",
119 "specularTexture",
120 "normalTexture",
121 "depthTexture"
122 };
123
124 deviceContext->setTexture("colorTexture", 0, deferredRenderTarget->get("Color"));
125 deviceContext->setTexture("emissiveTexture", 1, deferredRenderTarget->get("Emissive"));
126 deviceContext->setTexture("specularTexture", 2, deferredRenderTarget->get("Specular"));
127 deviceContext->setTexture("normalTexture", 3, deferredRenderTarget->get("Normals"));
128 deviceContext->setTexture("depthTexture", 4, deferredRenderTarget->depth->textureHandle);
129
130 deviceContext->setVertexBuffers(nullptr, 0, nullptr, nullptr);
133 deviceContext->draw(PrimitiveType::TriangleList, 0, 3);
134
135 for (size_t i = 0; i < 5; ++i) {
136 deviceContext->setTexture(textureName[i], 0, Cogs::TextureHandle::NoHandle);
137 }
138}
139
140void Cogs::Core::DeferredLightingTask::initializeGlobalBindings(RenderTaskContext * context, CachedEffect * effect, GlobalBinding & bindings)
141{
142 auto effects = context->device->getEffects();
143
144 bindings.sceneBufferBinding = effects->getConstantBufferBinding(effect->handle, "SceneBuffer");
145
146 bindings.shadowArrayBinding = effects->getTextureBinding(effect->handle, "cascadedShadowMap", 1);
147 bindings.shadowArrayBinding_1 = effects->getTextureBinding(effect->handle, "cascadedShadowMap_1", 1);
148 bindings.shadowCubeArrayBinding = effects->getTextureBinding(effect->handle, "cubeShadowMap", 2);
149 bindings.shadowCubeArrayBinding_1 = effects->getTextureBinding(effect->handle, "cubeShadowMap_1", 2);
150 bindings.shadowSamplerBinding = effects->getSamplerStateBinding(effect->handle, "cascadedShadowSampler", 2);
151
152 bindings.linearSampler = effects->getSamplerStateBinding(effect->handle, "linearSampler", 0);
153 bindings.radianceSamplerBinding = effects->getSamplerStateBinding(effect->handle, "environmentRadianceSampler", 0);
154 bindings.irradianceSamplerBinding = effects->getSamplerStateBinding(effect->handle, "environmentIrradianceSampler", 0);
155 bindings.ambientIrradianceSamplerBinding = effects->getSamplerStateBinding(effect->handle, "ambientIrradianceSampler", 0);
156}
157
158void Cogs::Core::DeferredLightingTask::applyGlobalBindings(RenderTaskContext * context, GlobalBinding & bindings)
159{
160 auto deviceContext = context->device->getImmediateContext();
161 auto engineBuffers = context->engineBuffers;
162
163 if (HandleIsValid(bindings.sceneBufferBinding)) {
164 deviceContext->setConstantBuffer(bindings.sceneBufferBinding, engineBuffers->sceneBufferHandle);
165 }
166
167 auto shadowsEnabled = context->context->variables->get("renderer.shadowsEnabled", false);
168 auto lightSystem = context->context->lightSystem;
169
170 if (shadowsEnabled) {
171 if (HandleIsValid(bindings.shadowArrayBinding)) {
172 auto shadowTexture = context->resources->getRenderTexture(lightSystem->cascadeArray);
173
174 if (shadowTexture) {
175 deviceContext->setTexture(bindings.shadowArrayBinding, shadowTexture->textureHandle);
176 }
177 }
178 if (HandleIsValid(bindings.shadowArrayBinding_1)) {
179 auto shadowTexture = context->resources->getRenderTexture(lightSystem->cascadeArray);
180
181 if (shadowTexture) {
182 deviceContext->setTexture(bindings.shadowArrayBinding_1, shadowTexture->textureHandle);
183 }
184 }
185
186 if (HandleIsValid(bindings.shadowCubeArrayBinding)) {
187 auto shadowTexture = context->resources->getRenderTexture(lightSystem->cubeArray);
188
189 if (shadowTexture) {
190 deviceContext->setTexture(bindings.shadowCubeArrayBinding, shadowTexture->textureHandle);
191 }
192 }
193 if (HandleIsValid(bindings.shadowCubeArrayBinding_1)) {
194 auto shadowTexture = context->resources->getRenderTexture(lightSystem->cubeArray);
195
196 if (shadowTexture) {
197 deviceContext->setTexture(bindings.shadowCubeArrayBinding_1, shadowTexture->textureHandle);
198 }
199 }
200
201 if (HandleIsValid(bindings.shadowSamplerBinding)) {
202 deviceContext->setSamplerState(bindings.shadowSamplerBinding, context->states->shadowSampler);
203 }
204 }
205 if (HandleIsValid(bindings.radianceSamplerBinding)) {
206 deviceContext->setSamplerState(bindings.radianceSamplerBinding, context->states->defaultSampler);
207 }
208 if (HandleIsValid(bindings.irradianceSamplerBinding)) {
209 deviceContext->setSamplerState(bindings.irradianceSamplerBinding, context->states->defaultSampler);
210 }
211 if (HandleIsValid(bindings.ambientIrradianceSamplerBinding)) {
212 deviceContext->setSamplerState(bindings.ambientIrradianceSamplerBinding, context->states->defaultSampler);
213 }
214 if (HandleIsValid(bindings.brdfLUTSamplerBinding)) {
215 deviceContext->setSamplerState(bindings.brdfLUTSamplerBinding, context->states->defaultSampler);
216 }
217 if (HandleIsValid(bindings.linearSampler)) {
218 deviceContext->setSamplerState(bindings.linearSampler, context->states->defaultSampler);
219 }
220}
std::unique_ptr< class Variables > variables
Variables service instance.
Definition: Context.h:180
ActiveLights & getActiveLights() override
Get the reference to the ActiveLights structure.
Definition: Renderer.h:74
IGraphicsDevice * getDevice() override
Get the graphics device used by the renderer.
Definition: Renderer.h:46
EffectCache & getEffectCache() override
Get the reference to the EffectCache structure.
Definition: Renderer.h:72
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 IContext * getImmediateContext()=0
Get a pointer to the immediate context used to issue commands to the graphics device.
Log implementation class.
Definition: LogManager.h:140
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.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
ResourceStatus
Status of an asynchronously loaded resource, such as an effect or a pipeline.
Definition: Common.h:198
@ Error
The resource failed to load.
@ Ready
The resource has loaded successfully and is ready for use.
@ TriangleList
List of triangles.
RAII-helper for pushCommandGroupAnnotation/pushCommandGroupAnnotation.
Cogs::ResourceStatus checkReady(RenderTaskContext *context) override
Check if the task is ready to be applied, e.g.
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
Represents a graphics device context which can receive rendering commands.
Definition: IContext.h:43
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 setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride=4, uint32_t offset=0)=0
Sets the current index buffer.
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 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 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.
Definition: IEffects.h:158
virtual ResourceStatus checkEffect(EffectHandle effectHandle)=0
Check the load status of the effect with the given effectHandle.