Cogs.Core
EngineBuffers.cpp
1#include <array>
2
3#include "Context.h"
4#include "EngineBuffers.h"
5#include "Renderer.h"
6#include "RenderTarget.h"
7
8#include "Services/Time.h"
9#include "Services/Random.h"
10#include "Systems/Core/LightSystem.h"
11#include "Systems/Core/FogSystem.h"
12#include "Systems/Core/EnvironmentSystem.h"
13#include "Tasks/RenderTask.h"
14#include "Systems/Core/CameraArraySystem.h"
15
16#include "Rendering/IBuffers.h"
17#include "Rendering/ICapabilities.h"
18
19void Cogs::Core::initializeEngineBuffers(IBuffers * buffers, ICapabilities* capabilites, EngineBuffers & engineBuffers)
20{
21 engineBuffers.sceneBufferHandle = buffers->loadBuffer(nullptr, sizeof(SceneBuffer), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
22 engineBuffers.viewBufferHandle = buffers->loadBuffer(nullptr, sizeof(ViewBufferEntry) * 2, Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
23 engineBuffers.objectBufferHandle = buffers->loadBuffer(nullptr, sizeof(ObjectBuffer), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
24 engineBuffers.animationBuffer = buffers->loadBuffer(nullptr, sizeof(AnimationBuffer), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
25
26 buffers->annotate(engineBuffers.sceneBufferHandle, "Engine:SceneBuffer");
27 buffers->annotate(engineBuffers.objectBufferHandle, "Engine:ObjectBuffer");
28 buffers->annotate(engineBuffers.animationBuffer, "Engine::AnimationBuffer");
29
30 if (capabilites && capabilites->getDeviceCapabilities().ConstantBufferRange) {
31 uint32_t alignment = capabilites->getDeviceCapabilities().ConstantBufferOffsetAlignment;
32 assert(alignment && ((alignment & (alignment - 1)) == 0) && "Constant buffer alignment is not a power of two");
33
34 engineBuffers.objectBatch.stride = uint32_t((sizeof(ObjectBuffer) + (alignment - 1))) & ~(alignment - 1);
35 engineBuffers.objectBatch.count = 128;
36 engineBuffers.objectBatch.bufferHandle = buffers->loadBuffer(nullptr, engineBuffers.objectBatch.stride * engineBuffers.objectBatch.count, Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
37 buffers->annotate(engineBuffers.objectBatch.bufferHandle, "Engine:ObjectBatchBuffer");
38 } else {
39 engineBuffers.objectBatch.count = 0;
40 }
41}
42
43namespace {
44 using namespace Cogs::Core;
45
46 void updateViewBuffer(Context* context, Cogs::BufferHandle& viewBufferHandle, const CameraData* viewportData)
47 {
48 RenderPassOptions passOptions = viewportData->passOptions ? *viewportData->passOptions : RenderPassOptions{};
49
50
51 if (passOptions.multiViews && viewportData->cameraArray) {
52 const CameraArrayComponent* camArrComp = viewportData->cameraArray.resolveComponent<CameraArrayComponent>();
53 const CameraArrayData& camArrData = context->cameraArraySystem->getData(camArrComp);
54
55 // These are populated by CameraArraySystem::update
56 assert(camArrData.viewBuffer.size() == passOptions.multiViews);
57 if (HandleIsValid(viewBufferHandle)) {
58 Cogs::IGraphicsDevice* device = context->renderer->getDevice();
59 Cogs::IContext* deviceContext = device->getImmediateContext();
60 deviceContext->updateBuffer(viewBufferHandle, camArrData.viewBuffer.data(), sizeof(camArrData.viewBuffer[0]) * camArrData.viewBuffer.size());
61 }
62 }
63 }
64
65 void updateLightBuffer(RenderTaskContext* taskContext, const CameraData* viewportData)
66 {
67 ActiveLights& activeLights = taskContext->renderer->getActiveLights();
68 EngineBuffers& engineBuffers = taskContext->renderer->getEngineBuffers();
69 LightSystem& lightSystem = *taskContext->context->lightSystem;
70 LightBuffer& lightParameters = engineBuffers.lightParameters;
71 lightParameters = {};
72 lightParameters.eyePosition = viewportData->inverseViewMatrix[3];
73
74 size_t numActiveLights = activeLights.lights.size();
75 for (size_t i = 0; i < numActiveLights; i++) {
76 const LightComponent* light = activeLights.lights[i];
77 const LightData& lightData = lightSystem.getData(light);
78 lightParameters.lightPositions[i] = lightData.lightPosition;
79 lightParameters.lightDirections[i] = lightData.lightDirection;
80 lightParameters.lightColorIntensity[i] = lightData.lightColor;
81 lightParameters.lightColorIntensity[i].a = (light->lightingLayer & viewportData->lightingMask) == 0 ? 0.f : light->intensity;
82 lightParameters.lightParameters[i].r = lightData.shadowIntensityOffset;
83 lightParameters.lightParameters[i].a = light->range;
84 }
85 lightParameters.numLights[0] = static_cast<uint32_t>(numActiveLights);
86 lightParameters.ambientColor = taskContext->renderer->getSettings().ambientColor;
87 lightParameters.ambientIntensity = taskContext->renderer->getSettings().ambientIntensity;
88
89 const FogComponent* globalFog = taskContext->context->fogSystem->getGlobalFog();
90 if (globalFog && globalFog->enabled) {
91 lightParameters.fogEnabled = 1;
92 lightParameters.fogColor = globalFog->color;
93 lightParameters.fogDistance = globalFog->distance;
94 lightParameters.fogAmount = globalFog->amount;
95 }
96 else {
97 lightParameters.fogEnabled = 0;
98 }
99
100 const EnvironmentComponent* environmentComponent = viewportData->environment.resolveComponent<EnvironmentComponent>();
101 lightParameters.seaFlags = 0;
102 lightParameters.flags = 0;
103 lightParameters.environmentBrightness = 1.0f;
104 lightParameters.skyMultiplier = 1.0f;
105 if (environmentComponent) {
106 lightParameters.environmentBrightness = environmentComponent->brightness;
107 lightParameters.skyMultiplier = environmentComponent->skyMultiplier;
108 lightParameters.flags = ((HandleIsValid(environmentComponent->skyDome) ? 1 : 0) |
109 (HandleIsValid(environmentComponent->radiance) ? 2 : 0) |
110 (HandleIsValid(environmentComponent->irradiance) ? 4 : 0) |
111 (HandleIsValid(environmentComponent->subseaRadiance) ? 8 : 0) |
112 (HandleIsValid(environmentComponent->ambientIrradiance) ? 16 : 0) |
113 (HandleIsValid(environmentComponent->brdfLUT) ? 32 : 0));
114
115 if (environmentComponent->subseaSupport) {
116 lightParameters.seaFlags = environmentComponent->isSubmerged(viewportData);
117 if (lightParameters.seaFlags) {
118 lightParameters.fogEnabled = 2 + 4;
119 lightParameters.fogColor = glm::vec4(1, 0, 0, 1);
120 lightParameters.fogDistance = environmentComponent->subseaTurbidityDistance;
121 lightParameters.fogAmount = environmentComponent->subseaTurbidityAmount;
122 }
123 }
124 }
125 }
126
127 const glm::vec4 softShadowJitter[] = {
128 { -2.5f, -2.5f, 0.0f, 0.0f },
129 { -2.5f, -1.5f, -1.5f, 0.0f },
130 { -2.5f, -0.5f, 0.0f, -1.5f },
131 { -2.5f, 0.5f, 0.0f, 1.5f },
132 { -2.5f, 1.5f, 1.5f, 0.0f },
133 { -2.5f, 2.5f, -1.5f, -1.5f },
134 { -1.5f, -2.5f, -1.5f, 1.5f },
135 { -1.5f, -1.5f, 1.5f, -1.5f },
136 { -1.5f, -0.5f, 1.5f, 1.5f },
137 { -1.5f, 0.5f, 0.0f, 0.0f },
138 { -1.5f, 1.5f, 0.0f, 0.0f },
139 { -1.5f, 2.5f, 0.0f, 0.0f },
140 { -0.5f, -2.5f, 0.0f, 0.0f },
141 { -0.5f, -1.5f, 0.0f, 0.0f },
142 { -0.5f, -0.5f, 0.0f, 0.0f },
143 { -0.5f, 0.5f, 0.0f, 0.0f },
144 { -0.5f, 1.5f, 0.0f, 0.0f },
145 { -0.5f, 2.5f, 0.0f, 0.0f },
146 { 0.5f, -2.5f, 0.0f, 0.0f },
147 { 0.5f, -1.5f, 0.0f, 0.0f },
148 { 0.5f, -0.5f, 0.0f, 0.0f },
149 { 0.5f, 0.5f, 0.0f, 0.0f },
150 { 0.5f, 1.5f, 0.0f, 0.0f },
151 { 0.5f, 2.5f, 0.0f, 0.0f },
152 { 1.5f, -2.5f, 0.0f, 0.0f },
153 { 1.5f, -1.5f, 0.0f, 0.0f },
154 { 1.5f, -0.5f, 0.0f, 0.0f },
155 { 1.5f, 0.5f, 0.0f, 0.0f },
156 { 1.5f, 1.5f, 0.0f, 0.0f },
157 { 1.5f, 2.5f, 0.0f, 0.0f },
158 { 2.5f, -2.5f, 0.0f, 0.0f },
159 { 2.5f, -1.5f, 0.0f, 0.0f },
160 { 2.5f, -0.5f, 0.0f, 0.0f },
161 { 2.5f, 0.5f, 0.0f, 0.0f },
162 { 2.5f, 1.5f, 0.0f, 0.0f },
163 { 2.5f, 2.5f, 0.0f, 0.0f }
164 };
165
166 void updateShadowBuffer(RenderTaskContext* taskContext)
167 {
168 ActiveLights& activeLights = taskContext->renderer->getActiveLights();
169 EngineBuffers& engineBuffers = taskContext->renderer->getEngineBuffers();
170 LightSystem& lightSystem = *taskContext->context->lightSystem;
171
172 ShadowBuffer& shadowParameters = engineBuffers.shadowBuffer;
173 shadowParameters = {};
174 static_assert(sizeof(softShadowJitter) == sizeof(ShadowBuffer::softShadowJitter));
175 std::memcpy(&shadowParameters.softShadowJitter, &softShadowJitter, sizeof(ShadowBuffer::softShadowJitter));
176 const bool reverseDepth = taskContext->context->variables->get("renderer.reverseDepth", false);
177 glm::mat4 viewportTransform;
178 switch (taskContext->device->getType())
179 {
182 // - Do not flip Y
183 if(taskContext->device->getCapabilities()->getDeviceCapabilities().DepthNegativeOneToOne){
184 // - Scale depth from [-1, 1] to [0,1]
185 viewportTransform = glm::mat4(0.5f, 0.0f, 0.0f, 0.0f,
186 0.0f, 0.5f, 0.0f, 0.0f,
187 0.0f, 0.0f, 0.5f, 0.0f,
188 0.5f, 0.5f, 0.5f, 1.0f);
189 }
190 else{
191 // - Depth is already scaled to [0,1] by projection matrix generated by getProjectionMatrix
192 viewportTransform = glm::mat4(0.5f, 0.0f, 0.0f, 0.0f,
193 0.0f, 0.5f, 0.0f, 0.0f,
194 0.0f, 0.0f, 1.0f, 0.0f,
195 0.5f, 0.5f, 0.0f, 1.0f);
196 }
197 break;
198 default:
199 // - Flip Y
200 // - Depth is already scaled to [0,1] by projection matrix generated by getProjectionMatrix
201 viewportTransform = glm::mat4(0.5f, 0.0f, 0.0f, 0.0f,
202 0.0f, -0.5f, 0.0f, 0.0f,
203 0.0f, 0.0f, 1.0f, 0.0f,
204 0.5f, 0.5f, 0.0f, 1.0f);
205 break;
206 }
207
208
209 for (size_t i = 0; i < activeLights.numDirectionalShadowLights; i++) {
210 const LightComponent* light = activeLights.lights[i];
211 const LightData& lightData = lightSystem.getData(light);
212 shadowParameters.cascadeOffsets[i].x = lightData.arrayOffset;
213 ShadowData& shadow = shadowParameters.shadowData[i];
214 shadow.shadowsEnabled = lightData.enabled && lightData.castShadows;
215 shadow.texelSize = 1.f / lightData.textureSize;
216 shadow.cascadeLine = lightData.cascadeLine;
217 shadow.nearSplits = *reinterpret_cast<const glm::vec4*>(lightData.nearDepths);
218 shadow.farSplits = *reinterpret_cast<const glm::vec4*>(lightData.farDepths);
219 shadow.shadowSampleBias = reverseDepth ? -light->shadowSampleBias : light->shadowSampleBias;
220 shadow.numCascades = lightData.numViewports;
221 for (size_t k = 0; k < lightData.numViewports; k++) {
222 shadow.lightMatrix[k] = viewportTransform * lightData.lightCameraData[k].viewProjection;
223 }
224 }
225
226 for (size_t i = 0; i < activeLights.numPointShadowLights; i++) {
227 size_t o = activeLights.numDirectionalShadowLights + activeLights.numDirectionalLights + i;
228 const LightComponent* light = activeLights.lights[o];
229 const LightData& lightData = lightSystem.getData(light);
230
231 shadowParameters.cascadeOffsets[o].x = lightData.arrayOffset / 6;
232
233 ShadowData& shadow = shadowParameters.shadowData[o];
234 shadow.shadowsEnabled = lightData.enabled && lightData.castShadows;
235 shadow.texelSize = 1.f / lightData.textureSize;
236 shadow.cascadeLine = lightData.cascadeLine;
237 shadow.nearSplits = *reinterpret_cast<const glm::vec4*>(lightData.nearDepths);
238 shadow.farSplits = *reinterpret_cast<const glm::vec4*>(lightData.farDepths);
239 shadow.shadowSampleBias = reverseDepth ? -light->shadowSampleBias : light->shadowSampleBias;
240 shadow.numCascades = lightData.numViewports;
241 for (size_t k = 0; k < lightData.numViewports; k++) {
242 shadow.lightMatrix[k] = viewportTransform * lightData.lightCameraData[k].viewProjection;
243 }
244 }
245 }
246}
247
248void Cogs::Core::updateViewportBuffer(RenderTaskContext* taskContext, BufferHandle& sceneBufferHandle, BufferHandle& viewBufferHandle, const RenderTarget* renderTarget, const CameraData* viewportData, const std::array<glm::vec4, 6>* clipEquations)
249{
250 IGraphicsDevice* device = taskContext->renderer->getDevice();
251 IContext* deviceContext = device->getImmediateContext();
252 auto& engineBuffers = taskContext->renderer->getEngineBuffers();
253 auto& random = taskContext->context->random;
254
255 updateViewBuffer(taskContext->context, viewBufferHandle, viewportData);
256
257 {
258 auto& sceneParameters = engineBuffers.sceneParameters;
259
260 static std::uniform_int_distribution<uint32_t> dist(0, 63);
261 glm::uvec4 offset(dist(random->mt), dist(random->mt), viewportData->blueNoiseOffset);
262 sceneParameters.blueNoiseOffset = offset;
263
264 sceneParameters.projectionMatrix = viewportData->projectionMatrix;
265 sceneParameters.viewMatrix = viewportData->viewMatrix;
266 sceneParameters.inverseViewMatrix = viewportData->inverseViewMatrix;
267 sceneParameters.worldToClipMatrix = sceneParameters.projectionMatrix * sceneParameters.viewMatrix;
268 sceneParameters.inverseProjectionMatrix = viewportData->inverseProjectionMatrix;
269 sceneParameters.viewFromViewportMatrix = viewportData->viewFromViewportMatrix;
270 sceneParameters.viewportFromViewMatrix = viewportData->viewportFromViewMatrix;
271 sceneParameters.viewportOrigin = viewportData->viewportOrigin;
272 sceneParameters.viewportSize = viewportData->viewportSize;
273 sceneParameters.viewportSizeRcp = 1.0f / viewportData->viewportSize;
274
275 RenderPassOptions passOptions = viewportData->passOptions ? *viewportData->passOptions : RenderPassOptions{};
276 if (viewportData->cameraArray && !passOptions.multiViews) {
277 const CameraArrayComponent* camArrComp = viewportData->cameraArray.resolveComponent<CameraArrayComponent>();
278 const CameraArrayData& camArrData = taskContext->context->cameraArraySystem->getData(camArrComp);
279 const ViewBufferEntry &entry = camArrData.viewBuffer[renderTarget->depthLayerIndex];
280 sceneParameters.projectionMatrix = entry.clipFromView;
281 sceneParameters.worldToClipMatrix = entry.clipFromWorld;
282 sceneParameters.viewMatrix = entry.viewFromWorld;
283 sceneParameters.inverseProjectionMatrix = entry.viewFromClip;
284 sceneParameters.inverseViewMatrix = entry.worldFromView;
285 }
286 {
287 glm::dvec3 origin = taskContext->context->transformSystem->getOrigin();
288 glm::vec3 originHigh = glm::vec3(origin);
289 glm::vec3 originLow = glm::vec3(origin - glm::dvec3(originHigh));
290 sceneParameters.originHigh = glm::vec4(originHigh, 0.f);
291 sceneParameters.originLow = glm::vec4(originLow, 0.f);
292 }
293
294 const bool reverseDepth = taskContext->context->variables->get("renderer.reverseDepth", false);
295 float depthClamp = viewportData->depthClamp;
296 if(reverseDepth){
297 depthClamp = 1.0f - depthClamp;
298 }
300 sceneParameters.shadowDepthClamp = 2.f * depthClamp - 1.f;
301 }
302 else{
303 sceneParameters.shadowDepthClamp = depthClamp;
304 }
305
306 sceneParameters.animationTime = static_cast<float>(taskContext->context->time->getAnimationTime());
307 sceneParameters.exposure = viewportData->exposure;
308
309 const float aspect = viewportData->viewportSize.y == 0 ? 1.0f : viewportData->viewportSize.x / viewportData->viewportSize.y;
310 sceneParameters.projectionParameters.y = 2.0f * viewportData->nearDistance * glm::tan(0.5f * viewportData->fieldOfView);
311 sceneParameters.projectionParameters.x = aspect * sceneParameters.projectionParameters.y;
312 sceneParameters.projectionParameters.z = aspect;
313 sceneParameters.projectionParameters.w = viewportData->fieldOfView;
314
315 unsigned sceneFlags = 0;
316 if ((renderTarget == taskContext->defaultRenderTarget && taskContext->renderer->getSettings().defaultRenderTargetExpectsSRGB) || renderTarget->expectsSRGB) {
317 sceneFlags |= COGS_SCENEFLAGS_OUTPUT_SRGB;
318 }
319 if (auto* environment = viewportData->environment.resolveComponent<EnvironmentComponent>(); environment && environment->isSubmerged(viewportData)) {
320 sceneFlags |= COGS_SCENEFLAGS_SUBMERGED;
321 }
322 sceneParameters.sceneFlags = sceneFlags;
323 sceneParameters.clientFlags = viewportData->clientFlags;
324 if (taskContext->context->environmentSystem) {
325 auto* envComp = taskContext->context->environmentSystem->getGlobalEnvironment();
326 if (envComp) {
327 auto& envData = taskContext->context->environmentSystem->getData(envComp);
328 sceneParameters.numEnvironmentIrradianceMips = static_cast<float>(envData.irradianceLods);
329 sceneParameters.numEnvironmentRadianceMips = static_cast<float>(envData.radianceLods);
330 }
331 }
332
333 static const std::array<glm::vec4, 6> noClipEquations = {
334 glm::vec4(0.f, 0.f, 0.f, 1.f), glm::vec4(0.f, 0.f, 0.f, 1.f),
335 glm::vec4(0.f, 0.f, 0.f, 1.f), glm::vec4(0.f, 0.f, 0.f, 1.f),
336 glm::vec4(0.f, 0.f, 0.f, 1.f), glm::vec4(0.f, 0.f, 0.f, 1.f)
337 };
338 std::memcpy(&sceneParameters.clippingPlanes, clipEquations ? clipEquations : &noClipEquations, sizeof(std::array<glm::vec4, 6>));
339
340 taskContext->cameraData = viewportData;
341 }
342
343 updateLightBuffer(taskContext, viewportData);
344 updateShadowBuffer(taskContext);
345
346 {
347 engineBuffers.sceneBuffer.scene = engineBuffers.sceneParameters;
348 engineBuffers.sceneBuffer.light = engineBuffers.lightParameters;
349 engineBuffers.sceneBuffer.shadow = engineBuffers.shadowBuffer;
350 }
351
352 if (HandleIsValid(sceneBufferHandle)) {
353 deviceContext->updateBuffer(sceneBufferHandle, &engineBuffers.sceneBuffer, sizeof(SceneBuffer));
354 }
355}
356
357void Cogs::Core::updateEngineBuffers(RenderTaskContext * taskContext, const RenderTarget* renderTarget, const CameraData * viewportData, const std::array<glm::vec4, 6>* clipEquations)
358{
359 if (!viewportData) return;
360
361 auto & engineBuffers = taskContext->renderer->getEngineBuffers();
362 updateViewportBuffer(taskContext, engineBuffers.sceneBufferHandle, engineBuffers.viewBufferHandle, renderTarget, viewportData, clipEquations);
363}
Multi-view: Render a set of related views into array texture layers.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
class IRenderer * renderer
Renderer.
Definition: Context.h:228
std::unique_ptr< class Random > random
Random Number service instance.
Definition: Context.h:189
std::unique_ptr< class Variables > variables
Variables service instance.
Definition: Context.h:180
std::unique_ptr< class Time > time
Time service instance.
Definition: Context.h:198
Contains data to describe fog.
Definition: FogComponent.h:17
glm::vec4 color
Fog color.
Definition: FogComponent.h:23
float amount
Amount of fog to blend in.
Definition: FogComponent.h:29
float distance
Distance at which the fog is at its most dense.
Definition: FogComponent.h:26
bool enabled
If the fog should be enabled or disabled.
Definition: FogComponent.h:32
virtual IGraphicsDevice * getDevice()=0
Get the graphics device used by the renderer.
Defines a single light source and its behavior.
float intensity
Intensity of the light source.
float shadowSampleBias
Constant term shadow map sampling bias.
LightingLayers lightingLayer
The lighting layer the light belongs to.
float range
Falloff range.
Holds all LightComponent instances in the system.
Definition: LightSystem.h:78
ActiveLights & getActiveLights() override
Get the reference to the ActiveLights structure.
Definition: Renderer.h:72
EngineBuffers & getEngineBuffers() override
Get the reference to the EngineBuffers structure.
Definition: Renderer.h:67
IGraphicsDevice * getDevice() override
Get the graphics device used by the renderer.
Definition: Renderer.h:45
const RenderSettings & getSettings() const override
Get the settings of the renderer.
Definition: Renderer.h:46
glm::dvec3 getOrigin() const
Gets the Origin offset of the scene.
Represents a graphics device used to manage graphics resources and issue drawing commands.
virtual ICapabilities * getCapabilities()=0
Get a pointer to the capability management interface used to query the graphics device capability fla...
virtual IContext * getImmediateContext()=0
Get a pointer to the immediate context used to issue commands to the graphics device.
virtual GraphicsDeviceType getType() const
Get the type of the graphics device.
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.
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ OpenGL20
Graphics device using OpenGL, supporting at least OpenGL 2.0.
ComponentType * resolveComponent() const
Definition: Component.h:90
Active lights settings.
Definition: IRenderer.h:47
Contains data describing a Camera instance and its derived data structured such as matrix data and vi...
Definition: CameraSystem.h:67
Defines calculated light data.
Definition: LightSystem.h:34
bool DepthNegativeOneToOne
If true, min z depth=-1 otherwise it is min z depth = 0 (max z depth = 1).
virtual const GraphicsDeviceCapabilities & getDeviceCapabilities() const
Gets the device capabilities in a structure.
Represents a graphics device context which can receive rendering commands.
Definition: IContext.h:43
virtual void updateBuffer(BufferHandle bufferHandle, const void *data, size_t size)=0
Replace contents of buffer with new data.