Cogs.Core
TwinVisualsTexAtlasRenderTask.cpp
1#include "Foundation/Logging/Logger.h"
2
3#include "Rendering/IGraphicsDevice.h"
4#include "Rendering/IContext.h"
5#include "Rendering/IEffects.h"
6#include "Rendering/IBuffers.h"
7#include "Rendering/IRenderTargets.h"
8#include "Rendering/ICapabilities.h"
9
10#include "Context.h"
11#include "ExtensionRegistry.h"
12
13#include "Systems/Core/LightSystem.h"
14
15#include "Renderer/Renderer.h"
16#include "Renderer/RenderStates.h"
17#include "Renderer/RenderTarget.h"
18#include "Renderer/RenderTexture.h"
19#include "Renderer/RenderPipelineDefinition.h"
20#include "Renderer/EngineBuffers.h"
21
22#include "Systems/Core/EnvironmentSystem.h"
23#include "Systems/Core/TransformSystem.h"
24
25#include "Utilities/Parsing.h"
26#include "Utilities/Preprocessor.h"
27#include "Resources/ResourceStore.h"
28
29#include "../../TexAtlas/Source/TexAtlasComponent.h"
30#include "../../TexAtlas/Source/TexAtlasSystem.h"
31
32#include "TwinVisualsSystem.h"
33#include "TwinVisualsComponent.h"
34#include "TwinVisualsTexAtlasRenderTask.h"
35
36#include <glm/gtc/color_space.hpp>
37#include <sstream>
38#include <regex>
39#include <map>
40
41namespace {
42 using namespace Cogs::Core;
43
44 Cogs::Logging::Log logger = Cogs::Logging::getLogger("TwinVisuals");
45
46 // Convert remaining #define directives to WGSL const expressions.
47 [[nodiscard]]
48 std::string convertDefinesToConst(const std::string& s) {
49 std::string result;
50 result.reserve(s.size());
51 std::istringstream iss(s);
52 std::regex e1("^\\s*#define\\s+([^\\s]+)\\s+([^\\s]+)");
53 std::regex e2("^\\s*#define\\s+([^\\s]+)\\s*$");
54 std::map<std::string, std::string> added;
55 for (std::string line; std::getline(iss, line); ) {
56 std::smatch match;
57 std::string id, val;
58 if (std::regex_search(line, match, e1)) {
59 id = match.str(1); val = match.str(2);
60 } else if (std::regex_search(line, match, e2)) {
61 id = match.str(1); val = "1";
62 }
63 if (id.empty()) {
64 result += line + "\n";
65 continue;
66 }
67 if (added.count(id)) continue;
68 result += "const " + id + " = " + val + ";\n";
69 added[id] = val;
70 }
71 return result;
72 }
73
74 // Preprocess a WGSL shader with the partial preprocessor.
75 [[nodiscard]]
76 std::string preprocessWgslShader(RenderTaskContext* rtc, const std::string& shaderPath,
77 const EffectDescription& desc, const std::string& suffix)
78 {
79 std::string src;
80 for (const auto& d : desc.definitions) {
81 src += "#define " + d.first + " " + d.second + "\n";
82 }
83 src += "#include \"" + shaderPath + "\"\n";
84
86 if (!pp.process(rtc->context, src)) {
87 LOG_ERROR(logger, "TwinVisualsTexAtlasRenderTask: Failed to preprocess %s", shaderPath.c_str());
88 return {};
89 }
90 src.swap(pp.processed);
91 src = convertDefinesToConst(src);
92
93 size_t code = Cogs::hash(src);
94 std::string resourcePath = "TwinVisuals/Shaders/TexAtlasTask" + suffix + "_" + std::to_string(code) + ".wgsl";
95 rtc->context->resourceStore->addResource(resourcePath, src);
96 return resourcePath;
97 }
98
99 struct TexAtlasState
100 {
101 struct {
102 glm::mat4 floatCoeffs[4];
103 glm::ivec4 intCoeffs[4];
104 glm::vec4 backgroundColor;
105 glm::vec4 groundColor;
106 glm::vec4 hazeColor;
107 glm::vec4 gridLineColorMaj;
108 glm::vec4 gridLineColorMin;
109 float opaqueness;
110 float groundElevation;
111 float gridRotationCos;
112 float gridRotationSin;
113 float gridOffsetX;
114 float gridOffsetY;
115 float gridScaleMaj;
116 float lineWidthMaj;
117 float lineWidthMin;
118 float fadeTweakMaj;
119 float fadeTweakMin;
120 } constants;
123 uint32_t levels[4] = { 0, 0, 0, 0 };
124 TwinVisualsTexAtlasStyle style = TwinVisualsTexAtlasStyle::Color;
125 };
126
127 void setupGlobalBindings(RenderTaskContext* renderTaskContext, GlobalBinding& globalBinding, Cogs::EffectHandle effect)
128 {
129 Cogs::IEffects* effects = renderTaskContext->device->getEffects();
130
131 globalBinding.shadowBufferBinding = effects->getConstantBufferBinding(effect, "ShadowBuffer");
132
133 globalBinding.shadowArrayBinding = effects->getTextureBinding(effect, "cascadedShadowMap", 1);
134 globalBinding.shadowArrayBinding_1 = effects->getTextureBinding(effect, "cascadedShadowMap_1", 1);
135 globalBinding.shadowCubeArrayBinding = effects->getTextureBinding(effect, "cubeShadowMap", 2);
136 globalBinding.shadowCubeArrayBinding_1 = effects->getTextureBinding(effect, "cubeShadowMap_1", 2);
137 globalBinding.shadowSamplerBinding = effects->getSamplerStateBinding(effect, "cascadedShadowSampler", 2);
138
139 globalBinding.linearSampler = effects->getSamplerStateBinding(effect, "linearSampler", 0);
140 globalBinding.radianceSamplerBinding = effects->getSamplerStateBinding(effect, "environmentRadianceSampler", 0);
141 globalBinding.irradianceSamplerBinding = effects->getSamplerStateBinding(effect, "environmentIrradianceSampler", 0);
142 globalBinding.ambientIrradianceSamplerBinding = effects->getSamplerStateBinding(effect, "ambientIrradianceSampler", 0);
143
144 globalBinding.skyBinding = effects->getTextureBinding(effect, "environmentSky", 0);
145 globalBinding.skySamplerBinding = effects->getSamplerStateBinding(effect, "environmentSkySampler", 0);
146
147 globalBinding.lightBufferBinding = effects->getConstantBufferBinding(effect, "LightBuffer");
148 globalBinding.sceneBufferBinding = effects->getConstantBufferBinding(effect, "SceneBuffer");
149 }
150
151 void applyGlobalBindings(RenderTaskContext* renderTaskContext, GlobalBinding& globalBinding)
152 {
153 Cogs::IContext* deviceContext = renderTaskContext->device->getImmediateContext();
154 EngineBuffers* engineBuffers = renderTaskContext->engineBuffers;
155 RenderResources* resources = renderTaskContext->resources;
156 RenderStates* states = renderTaskContext->states;
157
158 if (HandleIsValid(globalBinding.sceneBufferBinding)) {
159 deviceContext->setConstantBuffer(globalBinding.sceneBufferBinding, engineBuffers->sceneBufferHandle);
160 }
161
162 if (HandleIsValid(globalBinding.lightBufferBinding)) {
163 deviceContext->setConstantBuffer(globalBinding.lightBufferBinding, engineBuffers->lightBufferHandle);
164 }
165
166 if (bool shadowsEnabled = renderTaskContext->context->variables->get("renderer.shadowsEnabled", false); shadowsEnabled) {
167
168 LightSystem* lightSystem = renderTaskContext->context->lightSystem;
169
170 if (HandleIsValid(globalBinding.shadowBufferBinding)) {
171 deviceContext->setConstantBuffer(globalBinding.shadowBufferBinding, engineBuffers->shadowBufferHandle);
172
173 if (HandleIsValid(globalBinding.shadowArrayBinding)) {
174 if (RenderTexture* shadowTexture = resources->getRenderTexture(lightSystem->cascadeArray); shadowTexture) {
175 deviceContext->setTexture(globalBinding.shadowArrayBinding, shadowTexture->textureHandle);
176 }
177 }
178
179 if (HandleIsValid(globalBinding.shadowArrayBinding_1)) {
180 if (RenderTexture* shadowTexture = resources->getRenderTexture(lightSystem->cascadeArray); shadowTexture) {
181 deviceContext->setTexture(globalBinding.shadowArrayBinding_1, shadowTexture->textureHandle);
182 }
183 }
184
185 if (HandleIsValid(globalBinding.shadowCubeArrayBinding)) {
186 if (RenderTexture* shadowTexture = resources->getRenderTexture(lightSystem->cubeArray); shadowTexture) {
187 deviceContext->setTexture(globalBinding.shadowCubeArrayBinding, shadowTexture->textureHandle);
188 }
189 }
190
191 if (HandleIsValid(globalBinding.shadowCubeArrayBinding_1)) {
192 if (RenderTexture* shadowTexture = resources->getRenderTexture(lightSystem->cubeArray); shadowTexture) {
193 deviceContext->setTexture(globalBinding.shadowCubeArrayBinding_1, shadowTexture->textureHandle);
194 }
195 }
196 }
197
198 if (HandleIsValid(globalBinding.shadowSamplerBinding)) {
199 deviceContext->setSamplerState(globalBinding.shadowSamplerBinding, states->shadowSampler);
200 }
201 }
202
203 if (HandleIsValid(globalBinding.radianceSamplerBinding)) {
204 deviceContext->setSamplerState(globalBinding.radianceSamplerBinding, states->defaultSampler);
205 }
206 if (HandleIsValid(globalBinding.irradianceSamplerBinding)) {
207 deviceContext->setSamplerState(globalBinding.irradianceSamplerBinding, states->defaultSampler);
208 }
209 if (HandleIsValid(globalBinding.ambientIrradianceSamplerBinding)) {
210 deviceContext->setSamplerState(globalBinding.ambientIrradianceSamplerBinding, states->defaultSampler);
211 }
212 if (HandleIsValid(globalBinding.brdfLUTSamplerBinding)) {
213 deviceContext->setSamplerState(globalBinding.brdfLUTSamplerBinding, states->defaultSampler);
214 }
215 if (HandleIsValid(globalBinding.linearSampler)) {
216 deviceContext->setSamplerState(globalBinding.linearSampler, states->defaultSampler);
217 }
218
219 if (HandleIsValid(globalBinding.skyBinding)) {
220 EnvironmentSystem* environmentSystem = renderTaskContext->context->environmentSystem;
221 EnvironmentComponent* env = environmentSystem ? environmentSystem->getGlobalEnvironment() : nullptr;
222 if (env && env->skyDome) {
223 if (RenderTexture* skyTexture = renderTaskContext->renderer->getRenderResources().getRenderTexture(env->skyDome); skyTexture) {
224 deviceContext->setTexture(globalBinding.skyBinding, skyTexture->textureHandle);
225 }
226 }
227 }
228 if (HandleIsValid(globalBinding.skySamplerBinding)) {
229 deviceContext->setSamplerState(globalBinding.skySamplerBinding, states->defaultSampler);
230 }
231 }
232
233 void setupEffect(RenderTaskContext* renderTaskContext, TwinVisualsTexAtlasRenderTask& task, TexAtlasState& state)
234 {
235 const RenderSettings& renderSettings = renderTaskContext->renderer->getSettings();
236 const bool reverseDepth = renderTaskContext->context->variables->get("renderer.reverseDepth", false);
237
239 switch (renderTaskContext->renderer->getDevice()->getType()) {
241 desc.vs = "TwinVisuals/Shaders/TexAtlasTaskVS.es30.glsl";
242 desc.ps = "TwinVisuals/Shaders/TexAtlasTaskPS.es30.glsl";
243 break;
245 desc.vs = "TwinVisuals/Shaders/TexAtlasTaskVS.wgsl";
246 desc.ps = "TwinVisuals/Shaders/TexAtlasTaskPS.wgsl";
247 break;
248 default:
249 LOG_ERROR(logger, "TwinVisualsTexAtlasRenderTask: entity does not have a TexAtlasComponent");
250 return;
251 }
252
253 EnginePermutation* permutation = renderTaskContext->renderer->getEnginePermutations().get("Forward");
254 for (auto& d : permutation->getDefinition()->definitions) {
255 desc.definitions.emplace_back(d.first, d.second);
256 }
257
258 if (reverseDepth) {
259 desc.definitions.push_back({ "COGS_REVERSE_DEPTH", "1" });
260 }
261
262 // See Default.permutations for defines.
263 switch (renderSettings.sRGBConversion) {
264 case RenderSettings::SRGBConversion::Fast:
265 desc.definitions.push_back({ "COGS_SRGB_CONVERSION_FAST", "1" });
266 break;
267 case RenderSettings::SRGBConversion::Approx:
268 desc.definitions.push_back({ "COGS_SRGB_CONVERSION_APPROX", "1" });
269 break;
270 case RenderSettings::SRGBConversion::Exact:
271 desc.definitions.push_back({ "COGS_SRGB_CONVERSION_EXACT", "1" });
272 break;
273 default:
274 assert(false && "Invalid enum");
275 break;
276 }
277
278 // See Default.permutations for defines.
279 switch (renderSettings.tonemapper) {
280 case RenderSettings::Tonemapper::Reinhard:
281 desc.definitions.push_back({ "COGS_TONEMAP_REINHARD", "1" });
282 break;
283 case RenderSettings::Tonemapper::Filmic:
284 desc.definitions.push_back({ "COGS_TONEMAP_FILMIC", "1" });
285 break;
286 case RenderSettings::Tonemapper::ACESLuminance:
287 desc.definitions.push_back({ "COGS_TONEMAP_ACES_LUMINANCE", "1" });
288 break;
289 case RenderSettings::Tonemapper::PBRNeutral:
290 desc.definitions.push_back({ "COGS_TONEMAP_PBR_NEUTRAL", "1" });
291 break;
292 default:
293 assert(false && "Invalid enum");
294 break;
295 }
296
297 if (renderTaskContext->context->variables->get("renderer.backBuffer.sRGB", true)) {
298 desc.definitions.emplace_back("OUTPUT_SRGB", "1");
299 }
300 if (task.inputSrgb) {
301 desc.definitions.emplace_back("INPUT_SRGB", "1");
302 }
303 if (task.lumaInAlpha) {
304 desc.definitions.emplace_back("LUMA_IN_ALPHA", "1");
305 }
306
307 static const std::string keys[4] = {
308 "TEX_ATLAS_LEVELS_0",
309 "TEX_ATLAS_LEVELS_1",
310 "TEX_ATLAS_LEVELS_2",
311 "TEX_ATLAS_LEVELS_3"
312 };
313 for (size_t i = 0; i < 4; i++) {
314 if (0 < state.levels[i]) {
315 desc.definitions.emplace_back(keys[i], std::to_string(state.levels[i]));
316 }
317 }
318
319 switch (state.style) {
320 case TwinVisualsTexAtlasStyle::Grayscale:
321 desc.definitions.emplace_back("TEX_ATLAS_COLORING_GRAYSCALE", "1");
322 break;
323 case TwinVisualsTexAtlasStyle::None:
324 desc.definitions.emplace_back("TEX_ATLAS_COLORING_NONE", "1");
325 break;
326 case TwinVisualsTexAtlasStyle::Color:
327 break;
328 default:
329 assert(false && "Invalid enum");
330 break;
331 }
332
333 EnvironmentSystem* environmentSystem = renderTaskContext->context->environmentSystem;
334 EnvironmentComponent* env = environmentSystem ? environmentSystem->getGlobalEnvironment() : nullptr;
335 if (env && env->skyDome) {
336 desc.definitions.emplace_back("SKY_CUBEMAP", "1");
337 }
338
339 // For WebGPU, run the partial preprocessor to handle #ifdef/#include in WGSL
340 if (renderTaskContext->renderer->getDevice()->getType() == Cogs::GraphicsDeviceType::WebGPU) {
341 std::string vsPath = preprocessWgslShader(renderTaskContext, desc.vs, desc, "VS");
342 std::string psPath = preprocessWgslShader(renderTaskContext, desc.ps, desc, "PS");
343 if (vsPath.empty() || psPath.empty()) {
344 LOG_ERROR(logger, "TwinVisualsTexAtlasRenderTask: Failed to preprocess WGSL shaders");
345 return;
346 }
347 desc.vs = vsPath;
348 desc.ps = psPath;
349 desc.definitions.clear();
350 }
351
352 CachedEffect* effect = renderTaskContext->renderer->getEffectCache().loadEffect(renderTaskContext, desc);
353 if (effect && HandleIsValid(effect->handle) && effect != task.effect) {
354 setupGlobalBindings(renderTaskContext, task.globalBinding, effect->handle);
355 }
356 task.effect = effect;
357 }
358}
359
360Cogs::Core::TwinVisualsTexAtlasRenderTask::TwinVisualsTexAtlasRenderTask(
361 RenderTaskContext* renderTaskContext,
362 TexAtlasSystem* texAtlasSystem,
363 TwinVisualsSystem* twinVisualsSystem,
364 const RenderTaskDefinition& renderTaskDefinition,
365 const PipelineOptions& /*pipelineOptions*/)
366: texAtlasSystem(texAtlasSystem)
367, twinVisualsSystem(twinVisualsSystem)
368{
369 assert(texAtlasSystem);
370 assert(twinVisualsSystem);
371 const bool reverseDepth = renderTaskContext->context->variables->get("renderer.reverseDepth", false);
372
373 bool depthTest = true;
374 bool depthWrite = true;
375 for (const auto& p : renderTaskDefinition.parameters) {
376 if (p.key == "clear") {
377 p.asBool(clearColor);
378 } else if (p.key == "blendMode") {
379 blendMode = parseEnum<BlendMode>(p.value, blendMode);
380 } else if (p.key == "depthTest") {
381 p.asBool(depthTest);
382 }
383 else if (p.key == "writeDepth") {
384 p.asBool(depthWrite);
385 } else if (p.key == "inputSrgb") {
386 p.asBool(inputSrgb);
387 }
388 else if (p.key == "outputSrgb") {
389 p.asBool(outputSrgb);
390 } else if (p.key == "lumaInAlpha") {
391 p.asBool(lumaInAlpha);
392 } else if (p.key == "viewportFromTarget") {
393 p.asBool(viewportFromTarget);
394 }
395 }
396
397 Cogs::IGraphicsDevice* device = renderTaskContext->renderer->getDevice();
398 Cogs::IBuffers* buffers = device->getBuffers();
399 Cogs::IRenderTargets* renderTargets = device->getRenderTargets();
400
401 DepthStencilState depthState{};
402 if (depthTest) {
403 depthState = {
404 .depthEnabled = true,
405 .writeEnabled = depthWrite,
406 // Do depth test, but we use OrEqual so ground-plane that goes beyond farplane can use far-plane depth and win the tie.
407 .depthFunction = reverseDepth ? DepthStencilState::GreaterOrEqual : DepthStencilState::LessOrEqual
408 };
409 }
410 else if (depthWrite) {
411 depthState = {
412 .depthEnabled = true,
413 .writeEnabled = true,
414 .depthFunction = DepthStencilState::Always
415 };
416 }
417 else {
418 depthState = {
419 .depthEnabled = false,
420 .writeEnabled = false,
421 .depthFunction = DepthStencilState::Always
422 };
423 }
424 depthStencilStateHandle = renderTargets->loadDepthStencilState(depthState);
425
426 constants = buffers->loadBuffer(nullptr, sizeof(TexAtlasState::constants), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
427}
428
429void Cogs::Core::TwinVisualsTexAtlasRenderTask::apply(RenderTaskContext* renderTaskContext)
430{
431 TexAtlasState state{};
432 RenderResources& renderResources = renderTaskContext->renderer->getRenderResources();
433 RenderStates& renderStates = renderTaskContext->renderer->getRenderStates();
434
435 const glm::dvec3 origin = renderTaskContext->context->transformSystem->getOrigin();
436
437 size_t ix = 0;
438 if (TwinVisualsComponent* tvComp = twinVisualsSystem->globalTwinVisualsComponent; tvComp) {
439 state.style = tvComp->texAtlasStyle;
440
441 // Calculate shift to use in shader
442 const float c = std::cos(tvComp->gridRotation);
443 const float s = std::sin(tvComp->gridRotation);
444 glm::dvec2 o = glm::dvec2(origin) - tvComp->gridOrigin;
445 glm::dmat2 R(c, s,
446 -s, c);
447 glm::vec2 shift = glm::vec2(fract((1.0 / double(tvComp->gridSpacingMaj)) * (R * o)));
448
449 state.constants.backgroundColor = glm::convertSRGBToLinear(renderTaskContext->renderer->getBackgroundColor());
450 state.constants.groundColor = tvComp->groundColor;
451 state.constants.hazeColor = glm::vec4(tvComp->hazeColor,
452 tvComp->hazeIntensity);
453 state.constants.opaqueness = tvComp->groundOpaqueness;
454 state.constants.groundElevation = float(tvComp->groundElevation - origin.z);
455 state.constants.gridRotationCos = c;
456 state.constants.gridRotationSin = s;
457 state.constants.gridOffsetX = shift.x;
458 state.constants.gridOffsetY = shift.y;
459 state.constants.gridLineColorMaj = tvComp->gridLineColorMaj;
460 state.constants.gridLineColorMin = tvComp->gridLineColorMin;
461 state.constants.gridScaleMaj = tvComp->gridEnable ? (1.f / tvComp->gridSpacingMaj) : 0.f;
462 state.constants.lineWidthMaj = tvComp->gridLineWidthMaj;
463 state.constants.lineWidthMin = tvComp->gridLineWidthMin;
464 state.constants.fadeTweakMaj = tvComp->gridFadeTweakMaj;
465 state.constants.fadeTweakMin = tvComp->gridFadeTweakMin;
466
467 for (const WeakEntityPtr& weakEntity : tvComp->texAtlases) {
468 if (ix >= 4) break;
469
470 EntityPtr entity = weakEntity.lock();
471 if (!entity) continue;
472
473 TexAtlasComponent* texAtlasComp = entity->getComponent<TexAtlasComponent>();
474 if (!texAtlasComp) {
475 if (firstRun) {
476 LOG_ERROR(logger, "TwinVisualsTexAtlasRenderTask: entity does not have a TexAtlasComponent");
477 }
478 continue;
479 }
480
481 TexAtlasData& texAtlasData = texAtlasSystem->getData(texAtlasComp);
482 texAtlasData.inUse = true;
483
484 RenderTexture* treeTex = renderResources.getRenderTexture(texAtlasData.treeTex);
485 RenderTexture* tilesTex = renderResources.getRenderTexture(texAtlasData.tilesTex);
486 if (!treeTex || !tilesTex) continue;
487
488 state.constants.floatCoeffs[ix] = texAtlasData.floatCoefficients;
489 state.constants.intCoeffs[ix] = texAtlasData.intCoefficients;
490 state.tilesTex[ix] = tilesTex->textureHandle;
491 state.treeTex[ix] = treeTex->textureHandle;
492 state.levels[ix] = texAtlasData.levels;
493 ix++;
494 }
495 }
496
497 setupEffect(renderTaskContext, *this, state);
498 if (effect && HandleIsValid(effect->handle)) {
499
500 RenderList* renderList = input.get(RenderResourceType::RenderList)->renderList;
501 RenderTarget* renderTarget = output.get(RenderResourceType::RenderTarget)->renderTarget;
502
503 updateEngineBuffers(renderTaskContext, renderTarget, renderList->viewportData, nullptr);
504
505 IGraphicsDevice* device = renderTaskContext->renderer->getDevice();
506 IContext* deviceContext = device->getImmediateContext();
507 deviceContext->setEffect(effect->handle);
508
509 if(renderTaskContext->device->getCapabilities()->getDeviceCapabilities().RenderPass){
510 RenderPassInfo info;
511 info.renderTargetHandle = renderTarget->renderTargetHandle;
512 info.depthStencilHandle = DepthStencilHandle::NoHandle;
513 info.loadOp[0] = clearColor ? LoadOp::Clear : LoadOp::Load;
514 info.storeOp[0] = StoreOp::Store;
515 glm::vec4 color = renderTarget->getClearColor();
516 info.clearValue[0][0] = color[0];
517 info.clearValue[0][1] = color[1];
518 info.clearValue[0][2] = color[2];
519 info.clearValue[0][3] = color[3];
520 info.depthLoadOp = LoadOp::Load;
521 info.depthStoreOp = StoreOp::Discard;
522 deviceContext->beginRenderPass(info);
523 }
524 else{
525 deviceContext->setRenderTarget(renderTarget->renderTargetHandle, DepthStencilHandle::NoHandle);
526
527 if (clearColor) {
528 deviceContext->clearRenderTarget(glm::value_ptr(renderTarget->getClearColor()));
529 }
530 }
531
532 if (viewportFromTarget) {
533 deviceContext->setViewport(0.0f, 0.0f, static_cast<float>(renderTarget->width), static_cast<float>(renderTarget->height));
534 } else {
535 deviceContext->setViewport(0, 0, renderTaskContext->renderer->getSize().x, renderTaskContext->renderer->getSize().y);
536 }
537 deviceContext->setDepthStencilState(depthStencilStateHandle);
538 deviceContext->setRasterizerState(renderTaskContext->states->defaultRasterizerStateHandle);
539 deviceContext->setBlendState(renderTaskContext->states->blendStates[size_t(blendMode)].handle);
540 deviceContext->setVertexBuffers(nullptr, 0, nullptr, nullptr);
543
544 applyGlobalBindings(renderTaskContext, globalBinding);
545
546 deviceContext->updateBuffer(constants, &state.constants, sizeof(TexAtlasState::constants));
547 deviceContext->setConstantBuffer("TexAtlasCoefficients", constants);
548
549 static const std::string texAtlasTilesTextureName[4] = {
550 "texAtlasTiles0",
551 "texAtlasTiles1",
552 "texAtlasTiles2",
553 "texAtlasTiles3"
554 };
555 static const std::string texAtlasTilesSamplerName[4] = {
556 "texAtlasTiles0Sampler",
557 "texAtlasTiles1Sampler",
558 "texAtlasTiles2Sampler",
559 "texAtlasTiles3Sampler"
560 };
561 static const std::string texAtlasTreeTextureName[4] = {
562 "texAtlasTree0",
563 "texAtlasTree1",
564 "texAtlasTree2",
565 "texAtlasTree3"
566 };
567 static const std::string texAtlasTreeSamplerName[4] = {
568 "texAtlasTree0Sampler",
569 "texAtlasTree1Sampler",
570 "texAtlasTree2Sampler",
571 "texAtlasTree3Sampler"
572 };
573
574 for (size_t i = 0; i < 4; i++) {
575 deviceContext->setTexture(texAtlasTilesTextureName[i], uint32_t(i), state.tilesTex[i]);
576 deviceContext->setSamplerState(texAtlasTilesSamplerName[i], uint32_t(i), renderStates.commonSamplerStates[1]); // Clamp + MinMagMipLinear
577 deviceContext->setTexture(texAtlasTreeTextureName[i], uint32_t(i), state.treeTex[i]);
578 deviceContext->setSamplerState(texAtlasTreeSamplerName[i], uint32_t(i), renderStates.commonSamplerStates[3]); // Clamp + MinMagMipPoint
579 }
580
581 if (RenderTaskResource* color = input.get(RenderResourceType::RenderTexture, "ColorTexture"); color && color->renderTexure) {
582 deviceContext->setTexture("colorTexture", 5, color->renderTexure->textureHandle);
583 deviceContext->setSamplerState("colorTextureSampler", 5, renderStates.commonSamplerStates[1]); // Clamp + MinMagMipLinear
584 }
585 if (RenderTaskResource* depth = input.get(RenderResourceType::RenderTexture, "DepthTexture"); depth && depth->renderTexure) {
586 deviceContext->setTexture("depthTexture", 6, depth->renderTexure->textureHandle);
587 deviceContext->setSamplerState("depthTextureSampler", 6, renderStates.commonSamplerStates[3]); // Clamp + MinMagMipPoint
588 }
589 deviceContext->draw(PrimitiveType::TriangleList, 0, 3);
590 if (renderTaskContext->device->getCapabilities()->getDeviceCapabilities().RenderPass) {
591 deviceContext->endRenderPass();
592 }
593 }
594 firstRun = false;
595}
596
597void Cogs::Core::TwinVisualsTexAtlasRenderTask::cleanup(RenderTaskContext* renderTaskContext)
598{
599 Cogs::IGraphicsDevice* device = renderTaskContext->renderer->getDevice();
600 Cogs::IBuffers* buffers = device->getBuffers();
601 Cogs::IRenderTargets* renderTargets = device->getRenderTargets();
602 if (HandleIsValid(constants)) {
603 buffers->releaseBuffer(constants);
605 }
606 if (HandleIsValid(depthStencilStateHandle)) {
607 renderTargets->releaseDepthStencilState(depthStencilStateHandle);
608 depthStencilStateHandle = Cogs::DepthStencilStateHandle::NoHandle;
609 }
610}
ComponentType * getComponent() const
Definition: Component.h:159
std::unique_ptr< class Variables > variables
Variables service instance.
Definition: Context.h:180
EnvironmentComponent * getGlobalEnvironment() const
Get the global environment component.
Holds all LightComponent instances in the system.
Definition: LightSystem.h:78
Contains render resources used by the renderer.
RenderStates & getRenderStates() override
Get the reference to the RenderStates structure.
Definition: Renderer.h:68
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::vec4 getBackgroundColor() const override
Get the reference to the background color.
Definition: Renderer.h:42
EnginePermutations & getEnginePermutations() override
Get the reference to the EnginePermutations structure.
Definition: Renderer.h:76
EffectCache & getEffectCache() override
Get the reference to the EffectCache structure.
Definition: Renderer.h:70
glm::vec2 getSize() const override
Get the output surface size of the renderer.
Definition: Renderer.h:44
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 IEffects * getEffects()=0
Get a pointer to the effect management interface.
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 IBuffers * getBuffers()=0
Get a pointer to the buffer management interface.
virtual GraphicsDeviceType getType() const
Get the type of the graphics device.
virtual IRenderTargets * getRenderTargets()=0
Get a pointer to the render target management interface.
Log implementation class.
Definition: LogManager.h:140
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
Definition: EntityPtr.h:12
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
std::weak_ptr< ComponentModel::Entity > WeakEntityPtr
Weak Smart pointer for Entity access.
Definition: EntityPtr.h:18
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ WebGPU
Graphics device using the WebGPU API Backend.
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
@ TriangleList
List of triangles.
Partial C preprocessor.
Definition: Preprocessor.h:42
bool process(Context *context, const StringView input)
Run a text block through the preprocessor.
std::string processed
Resulting processed text.
Definition: Preprocessor.h:48
Render settings variables.
Encapsulates state for depth buffer usage and stencil buffer usage in a state object.
bool depthEnabled
If depth testing is enabled/disabled. Default is true.
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
Provides buffer management functionality.
Definition: IBuffers.h:13
virtual BufferHandle loadBuffer(const void *data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t stride=0)=0
Loads a new buffer using the given data to populate the buffer.
virtual void releaseBuffer(BufferHandle bufferHandle)=0
Releases the buffer with the given bufferHandle.
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 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 clearRenderTarget(const float *value)=0
Clear the currently set render target to the given value (4 component floating point RGBA).
virtual void endRenderPass()=0
End a render pass.
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 updateBuffer(BufferHandle bufferHandle, const void *data, size_t size)=0
Replace contents of buffer with new data.
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 beginRenderPass(const RenderPassInfo &info)=0
Begin a render pass.
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:148
virtual SamplerStateBindingHandle getSamplerStateBinding(EffectHandle effectHandle, const StringView &name, const unsigned int slot)=0
Get a handle to a sampler state object binding, mapping how to bind the sampler state to the given ef...
virtual ConstantBufferBindingHandle getConstantBufferBinding(EffectHandle effectHandle, const StringView &name)=0
Get a handle to a constant buffer binding, mapping how to bind a constant buffer to the given effect.
virtual TextureBindingHandle getTextureBinding(EffectHandle effectHandle, const StringView &name, const unsigned int slot)=0
Get a handle to a texture object binding, mapping how to bind textures to the given effect.
Provides render target management functionality.
virtual void releaseDepthStencilState(DepthStencilStateHandle handle)=0
Release the depth stencil state with the given handle.
virtual DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState)=0
Load a depth stencil state object.