Cogs.Core
PostProcessTask.cpp
1#include "PostProcessTask.h"
2#include "Resources/VertexFormats.h"
3
4#include "Context.h"
5#include "Renderer/Renderer.h"
6#include "Renderer/RenderTarget.h"
7#include "Systems/Core/CameraSystem.h"
8
9#include "Rendering/IGraphicsDevice.h"
10#include "Rendering/IContext.h"
11#include "Rendering/IBuffers.h"
12
13#include "Resources/ShaderBuilderPostProcess.h"
14
15#include <glm/gtc/type_ptr.hpp>
16
17#include "Foundation/Logging/Logger.h"
18
19using namespace Cogs;
20
21namespace
22{
23 const char * names[] = {
24 "linearSampler",
25 "linearClampSampler",
26 "pointSampler",
27 "pointClampSampler",
28 };
29
30 Cogs::Logging::Log logger = Cogs::Logging::getLogger("PostProcessTask");
31}
32
33void Cogs::Core::PostProcessTask::initialize(RenderTaskContext* context)
34{
35 ProcessTask::initialize(context);
36}
37
38void Cogs::Core::PostProcessTask::initialize(RenderTaskContext * context, const RenderTaskDefinition& taskDefinition)
39{
40 ProcessTask::initialize(context, taskDefinition);
41
42 auto effects = context->device->getEffects();
43
44 EffectDescription desc = createEffectDesc(context);
45 desc.vs = "Engine/FullscreenV3T2VS.hlsl";
46
47 for (auto & p : effectParameter.values) {
48 if (p.key == "definitions") {
49 for (auto & d : p.values) {
50 desc.definitions.push_back({ d.key, d.value });
51 }
52 }
53 if (p.key == "source") {
54 desc.ps = p.value;
55 }
56 }
57
58 {
59 Cogs::GraphicsDeviceType graphicsDeviceType = context->renderer->getDevice()->getType();
60 bool success;
61 switch (graphicsDeviceType)
62 {
64 success = Cogs::Core::buildPostProcessEffectES3(context, desc, this);
65 break;
67 success = buildPostProcessEffectWebGPU(context, desc, this);
68 break;
69 default:
70 success = buildPostProcessEffect(context, desc, this);
71 break;
72 }
73 if (!success) {
74 LOG_ERROR(logger, "Failed to build post processing shader source");
75 }
76 }
77
78 effect = context->renderer->getEffectCache().loadEffect(context, desc);
79
80 if (!HandleIsValid(effect->handle)) {
81 return;
82 }
83 auto * buffers = context->device->getBuffers();
84 inputLayout = buffers->loadInputLayout(&VertexFormats::Pos4f, 1, effect->handle);
85
86 for (size_t i = 0; i < 4; ++i) {
87 auto binding = effects->getSamplerStateBinding(effect->handle, names[i], 0);
88
89 if (HandleIsValid(binding)) {
90 samplerStateBindings[i] = binding;
91 samplerStates[i] = context->states->commonSamplerStates[i];
92 } else {
93 samplerStateBindings[i] = SamplerStateBindingHandle::NoHandle;
94 }
95 }
96}
97
98void Cogs::Core::PostProcessTask::apply(RenderTaskContext * context)
99{
100 if (scopeName.empty()) {
101 scopeName = std::string("PostProcessTask<") + name + ">::apply";
102 }
103
104 DynamicRenderInstrumentationScope(context->device->getImmediateContext(), SCOPE_RENDERING, "PostProcessTask", scopeName.c_str());
105
106 RenderTarget* renderTarget = output.get(RenderResourceType::RenderTarget)->renderTarget;
107
108 if (!renderTarget) {
109 return;
110 }
111
112 if (!HandleIsValid(effect->handle)) {
113 return;
114 }
115
116 auto deviceContext = context->device->getImmediateContext();
117 deviceContext->setEffect(effect->handle);
118 deviceContext->setRenderTarget(renderTarget->renderTargetHandle, renderTarget->depthTargetHandle);
119
120 if (clearColor) {
121 if (clearToDefault) {
122 deviceContext->clearRenderTarget(glm::value_ptr(context->renderer->getBackgroundColor()));
123 } else {
124 deviceContext->clearRenderTarget(glm::value_ptr(renderTarget->getClearColor()));
125 }
126 }
127 if (clearDepth) {
128 if (HandleIsValid(renderTarget->depthTargetHandle) || !HandleIsValid(renderTarget->renderTargetHandle)) {
129 deviceContext->clearDepth(context->renderer->getClearDepth());
130 }
131 }
132
133 if (viewportFromTarget) {
134 deviceContext->setViewport(0.0f, 0.0f, static_cast<float>(renderTarget->width), static_cast<float>(renderTarget->height));
135 }
136 else {
137 // Note: context->cameraData is set when updating engine buffers, so its value is from the last invocation.
138 deviceContext->setViewport(
139 context->cameraData->viewportOrigin.x, context->cameraData->viewportOrigin.y,
140 context->cameraData->viewportSize.x, context->cameraData->viewportSize.y
141 );
142 }
143
144 if (writeDepth) {
145 deviceContext->setDepthStencilState(context->states->noTestDepthStencilStateHandle);
146 } else {
147 deviceContext->setDepthStencilState(context->states->noDepthStencilStateHandle);
148 }
149
150 deviceContext->setRasterizerState(context->states->defaultRasterizerStateHandle);
151
152 for (size_t i = 0; i < 4; ++i) {
153 if (HandleIsValid(samplerStateBindings[i])) {
154 deviceContext->setSamplerState(samplerStateBindings[i], samplerStates[i]);
155 }
156 }
157
158 setProperties(context);
159
160 if (!writeColor){
161 deviceContext->setBlendState(context->states->blendStates[size_t(BlendMode::Zero)].handle);
162 }
163
164 deviceContext->setVertexBuffers(&context->states->fullScreenTriangle, 1);
165 deviceContext->setIndexBuffer(IndexBufferHandle::NoHandle);
166 deviceContext->setInputLayout(inputLayout);
167 deviceContext->draw(PrimitiveType::TriangleList, 0, 3);
168}
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.
@ Zero
Disable all color writes.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
GraphicsDeviceType
Contains types of graphics devices that may be supported.
Definition: Base.h:48
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ WebGPU
Graphics device using the WebGPU API Backend.
@ TriangleList
List of triangles.
Contains an effect description used to load a single effect.
Definition: IEffects.h:55
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78