1#include "TextureGenerator.h"
3#include <unordered_map>
6#include <glm/gtc/constants.hpp>
8#include "Foundation/Platform/Threads.h"
10#include "Resources/TextureManager.h"
11#include "Utilities/NoiseSampler.h"
21 glm::detail::hdata r, g, b, a;
26 glm::vec3 inverseSphereGeoTexMapping(
float u,
float v)
29 dir.z = -std::cos(glm::pi<float>() * v);
30 float t = 1.f / std::sqrt(1.f - dir.z*dir.z);
31 dir.y = std::cos(2.f*glm::pi<float>()* u) / t;
32 dir.x = (u < 0.5 ? 1 : -1.f)* std::sqrt(1.f - dir.z*dir.z - dir.y*dir.y);
38 glm::mat3 cubeMapPermutationMatrix(
size_t f)
46 R = glm::mat3(0.f, 0.f, -1.f,
52 R = glm::mat3(0.f, 0.f, 1.f,
58 R = glm::mat3(1.f, 0.f, 0.f,
64 R = glm::mat3(1.f, 0.f, 0.f,
70 R = glm::mat3(1.f, 0.f, 0.f,
77 R = glm::mat3(-1.f, 0.f, 0.f,
86 glm::vec3 cubeMapDir(
float u,
float v,
size_t f)
88 glm::mat3 T(2.f, 0.f, 0.f,
91 return glm::normalize(cubeMapPermutationMatrix(f)*(T*glm::vec3(u, v, 1.f)));
94 template<
typename Kernel,
typename Collection,
typename Element>
97 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f);
100 template<
typename Kernel,
typename Collection>
101 struct Sampler<Kernel, Collection, glm::u8vec4>
103 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f)
105 for (
size_t k = 0; k < f; k++) {
106 for (
size_t j = 0; j < h; j++) {
107 for (
size_t i = 0; i < w; i++) {
108 const auto v = kernel(i, j, k);
109 rgba[(k*h + j)*w + i].r =
static_cast<uint8_t
>(glm::clamp(255.f*v.r, 0.f, 255.f));
110 rgba[(k*h + j)*w + i].g =
static_cast<uint8_t
>(glm::clamp(255.f*v.g, 0.f, 255.f));
111 rgba[(k*h + j)*w + i].b =
static_cast<uint8_t
>(glm::clamp(255.f*v.b, 0.f, 255.f));
112 rgba[(k*h + j)*w + i].a =
static_cast<uint8_t
>(glm::clamp(255.f*v.a, 0.f, 255.f));
119 template<
typename Kernel,
typename Collection>
120 struct Sampler<Kernel, Collection, half4>
122 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f)
124 for (
size_t k = 0; k < f; k++) {
125 for (
size_t j = 0; j < h; j++) {
126 for (
size_t i = 0; i < w; i++) {
127 const auto v = kernel(i, j, k);
128 rgba[(k*h + j)*w + i].r = glm::detail::toFloat16(v.r);
129 rgba[(k*h + j)*w + i].g = glm::detail::toFloat16(v.g);
130 rgba[(k*h + j)*w + i].b = glm::detail::toFloat16(v.b);
131 rgba[(k*h + j)*w + i].a = glm::detail::toFloat16(v.a);
138 template<
typename Kernel,
typename Collection>
139 struct Sampler<Kernel, Collection, glm::vec4>
141 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f)
143 for (
size_t k = 0; k < f; k++) {
144 for (
size_t j = 0; j < h; j++) {
145 for (
size_t i = 0; i < w; i++) {
146 const auto v = kernel(i, j, k);
147 rgba[(k*h + j)*w + i].r = v.r;
148 rgba[(k*h + j)*w + i].g = v.g;
149 rgba[(k*h + j)*w + i].b = v.b;
150 rgba[(k*h + j)*w + i].a = v.a;
172 float cubeTexelSolidAngle(
float uMin,
float uMax,
float vMin,
float vMax)
174 float fA = std::atan2(uMin * vMin, std::sqrt(uMin * uMin + vMin * vMin + 1));
175 float fB = std::atan2(uMax * vMin, std::sqrt(uMax * uMax + vMin * vMin + 1));
176 float fC = std::atan2(uMax * vMax, std::sqrt(uMax * uMax + vMax * vMax + 1));
177 float fD = std::atan2(uMin * vMax, std::sqrt(uMin * uMin + vMax * vMax + 1));
178 return fA - fB + fC - fD;
183 for (
size_t k1 = 0; k1 < 6; k1++) {
184 glm::mat3 P1 = cubeMapPermutationMatrix(k1)*glm::mat3(2.f / W, 0.f, 0.f,
186 -(1.f - 1.f / W), 1.f - 1.f / H, 1.f);
187 for (
size_t j1 = 0; j1 < H; j1++) {
188 for (
size_t i1 = 0; i1 < W; i1++) {
189 auto d1 = glm::normalize(P1*glm::vec3(i1, j1, 1.f));
191 glm::vec3 irradiance;
192 for (
size_t k0 = 0; k0 < 6; k0++) {
193 glm::mat3 P0 = cubeMapPermutationMatrix(k0)*glm::mat3(2.f / W, 0.f, 0.f,
195 -(1.f - 1.f / W), 1.f - 1.f / H, 1.f);
196 for (
size_t j0 = 0; j0 < H; j0++) {
197 for (
size_t i0 = 0; i0 < W; i0++) {
198 auto d0 = glm::normalize(P0*glm::vec3(i0, j0, 1.f));
199 if (0.f < glm::dot(d0, d1)) {
201 float uMin = 2.f*(i0 + 0.f) / W - 1.f;
202 float uMax = 2.f*(i0 + 1.f) / W - 1.f;
203 float vMin = 2.f*(j0 + 0.f) / H - 1.f;
204 float vMax = 2.f*(j0 + 1.f) / H - 1.f;
205 float w = cubeTexelSolidAngle(uMin, uMax, vMin, vMax);
207 irradiance += w * glm::vec3(radiance[(k0*H + j0)*W + i0]);
214 dst[(k1*H + j1)*W + i1].r = glm::detail::toFloat16(irradiance.r);
215 dst[(k1*H + j1)*W + i1].g = glm::detail::toFloat16(irradiance.g);
216 dst[(k1*H + j1)*W + i1].b = glm::detail::toFloat16(irradiance.b);
217 dst[(k1*H + j1)*W + i1].a = glm::detail::toFloat16(1.f);
228 float indirectDirectRatio = 70.f / 1050.f;
233 constexpr float radianceIrradianceRatio = 1.f / std::numbers::pi_v<float>;
240 const auto& s = definition.sunDirection;
241 const glm::vec3 sunDir = glm::normalize(glm::vec3(s.x, s.z, s.y));
242 const glm::vec3 up = normalize(glm::vec3(0, 1, 0));
244 auto sunIrradiance = definition.sunIrradiance;
245 auto sunRadiance = radianceIrradianceRatio * indirectDirectRatio*glm::length(sunIrradiance);
246 auto sunCol = (1.f / (std::max(std::max(sunIrradiance.r, sunIrradiance.g), sunIrradiance.b)))*sunIrradiance;
248 auto kernel = [&sunDir, sunRadiance, &sunCol, lightBottom, withSky, withSun, &up, w, h](
size_t i,
size_t j,
size_t k) {
249 auto sampleDir = cubeMapDir(
float(i + 0.5f) /
float(w),
float(j + 0.5f) /
float(h), k);
256 float zeta_cos = std::max(0.f, glm::dot(sunDir, sampleDir));
257 float zeta = std::acos(zeta_cos);
258 float gamma_sin = std::max(0.f, dot(sampleDir, up));
259 float gamma_s_sin = std::max(0.f, dot(sunDir, up));
261 float pi2_zeta_s = glm::half_pi<float>() - std::asin(gamma_s_sin);
262 float pi2_zeta_s_cos = std::cos(pi2_zeta_s);
264 float phi_gamma = 1.f - std::exp(-0.32f / gamma_sin);
266 float f_zeta = 0.91f + 19.f * std::exp(-3.f * zeta) + 0.45f*zeta_cos*zeta_cos;
268 float f_pi2_zeta_s = 0.91f + 19 * std::exp(-3.f * pi2_zeta_s) + 0.45f*pi2_zeta_s_cos*pi2_zeta_s_cos;
269 float phi_pi2 = 0.27385f;
272 float clear = (phi_gamma*f_zeta) / (phi_pi2* f_pi2_zeta_s);
276 rv = glm::mix(glm::vec3(0.f, 0.1f, 0.3f), sunCol, 0.1f*std::max(0.f, clear - 0.5f));
280 rv += 20.f*std::pow(zeta_cos, 100.f)*sunCol;
283 if (!lightBottom && glm::dot(sampleDir, up) < 0.f) {
284 rv = glm::mix(rv, glm::vec3(0, 0, 0.0), glm::clamp(-3 * glm::dot(sampleDir, up), 0.f, 1.f));
286 return glm::vec4(sunRadiance*rv, 1.f);
288 rgba.resize(w * h * 6);
289 Sampler<
decltype(kernel),
decltype(rgba), T>::run(rgba, kernel, w, h, 6);
295 const auto& s = definition.sunDirection;
296 const glm::vec3 sunDir = glm::normalize(glm::vec3(s.x, s.z, s.y));
297 auto sunRadiance = glm::length(definition.sunIrradiance);
299 auto kernel = [&sunDir, sunRadiance, w, h](
size_t i,
size_t j,
size_t k) {
300 auto sampleDir = cubeMapDir(
float(i + 0.5f) /
float(w),
float(j + 0.5f) /
float(h), k);
302 const glm::vec3 seaColor(0.1f, 0.7f, 1.f);
304 float t = std::pow(1.f - (1.f / glm::pi<float>())*std::acos(glm::dot(sampleDir, sunDir)), 3.f);
306 return glm::vec4(1e-3f*seaColor*sunRadiance*t, 1.f);
308 rgba.resize(w * h * 6);
309 Sampler<
decltype(kernel),
decltype(rgba), T>::run(rgba, kernel, w, h, 6);
315 auto kernel = [w, h](
size_t i,
size_t j,
size_t k) {
316 auto dir = cubeMapDir(
float(i) /
float(w),
float(j) /
float(h), k);
317 float z = 0.5f*(dir.z + 1.f);
319 const glm::vec3 waterColor(0.f, 0.2, 0.3);
320 const glm::vec3 skyColorHorizon(0.3, 0.4, 0.5);
321 const glm::vec3 skyColorZenith(0.8, 0.9, 1.0);
324 c = glm::mix(waterColor, skyColorHorizon, 2.f*z);
327 c = 1.5f*glm::mix(skyColorHorizon, skyColorZenith, 2.f*(z - 0.5f));
329 return glm::vec4(c, 1.f);
332 rgba.resize(w * h * 6);
333 Sampler<
decltype(kernel),
decltype(rgba), T>::run(rgba, kernel, w, h, 6);
336 template<
typename Collection>
337 void sampleSky(Collection & rgba,
size_t w,
size_t h)
339 glm::vec3 waterColor(0.f, 0.2, 0.3);
340 glm::vec3 skyColorHorizon(0.3, 0.4, 0.5);
341 glm::vec3 skyColorZenith(0.8, 0.9, 1.0);
343 for (
size_t j = 0; j < h; j++) {
344 for (
size_t i = 0; i < w; i++) {
345 float z = float(j) / float(h);
348 c = glm::mix(waterColor, skyColorHorizon, 2.f*z);
351 c = 1.5f*glm::mix(skyColorHorizon, skyColorZenith, 2.f*(z - 0.5f));
354 rgba[4 * (w*j + i) + 0] =
static_cast<uint8_t
>(255.f*glm::clamp(c.r, 0.f, 1.f));
355 rgba[4 * (w*j + i) + 1] =
static_cast<uint8_t
>(255.f*glm::clamp(c.g, 0.f, 1.f));
356 rgba[4 * (w*j + i) + 2] =
static_cast<uint8_t
>(255.f*glm::clamp(c.b, 0.f, 1.f));
357 rgba[4 * (w*j + i) + 3] = 255;
364 const size_t w = std::max(1u, definition.width);
365 const size_t h = std::max(1u, definition.height);
366 const size_t l = std::max(1u, definition.layers);
367 switch (definition.type) {
368 case ImageType::CheckerBoard:
370 auto kernel = [](
size_t i,
size_t j,
size_t ) {
371 bool t = ((i / 16 + j / 16) & 0x1) == 1;
372 return glm::vec4(1.f, 1.f, t ? 0.5f : 1.f, 1.f);
374 auto rgba = texture->
map<glm::u8vec4>((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
375 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 1);
379 case ImageType::ColorfulCheckerBoard:
381 auto kernel = [A = 1.f / w, B = 1.f / h, C = 1.f / l, l](
size_t i,
size_t j,
size_t k) {
382 bool t = ((i / 16 + j / 16) & 0x1) == 1;
383 return glm::vec4(t ? A * i : 1.f, t ? B * j : 1.f, t ? 0.f : C * (
float(l - k)), 1.f);
386 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, l);
388 texture->
setData(Cogs::ResourceDimensions::Texture2DArray, rgba.data(), rgba.byteSize(), (uint32_t)w, (uint32_t)h, 1, uint32_t(l), 1, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
391 texture->
setData(Cogs::ResourceDimensions::Texture2D, rgba.data(), rgba.byteSize(), (uint32_t)w, (uint32_t)h, 1, uint32_t(l), 1, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
396 case ImageType::Dirt:
398 std::vector<float> noise(w*h);
400 noiseSampler.gradNoise2DTurbulence(noise.data(), 16.0f, 256.f, (
int)w, (
int)h);
401 auto kernel = [&noise, w, h](
size_t i,
size_t j,
size_t ) {
402 float n0 = 0.5f + 0.5f*noise[w*j + i];
403 float n1 = 0.5f + 0.5f*noise[w*((2 * j + 15) % h) + ((2 * i + 44) % w)];
404 return glm::vec4(0.3f + 0.20f*n0 + 0.15f*n1,
405 0.2f + 0.15f*n0 + 0.20f*n1,
406 0.1f + 0.05f*n0 + 0.15f*n1,
409 auto rgba = texture->
map<glm::u8vec4>((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
410 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 1);
415 case ImageType::Steel:
417 std::vector<float> noise(w*h);
419 noiseSampler.gradNoise2DTurbulence(noise.data(), 16.0f, 64.f, (
int)w, (
int)h);
420 auto kernel = [&noise, w, h](
size_t i,
size_t j,
size_t ) {
421 float n0 = 0.5f + 0.5f*noise[w*((j) % h) + (8 * i) % w];
422 float n1 = 0.5f + 0.5f*noise[w*((j + 0) % h) + ((i) % w)];
423 return glm::vec4(0.5f + 0.10f*n0 + 0.07f*n1,
424 0.5f + 0.10f*n0 + 0.06f*n1,
425 0.5f + 0.13f*n0 + 0.05f*n1,
428 auto rgba = texture->
map<glm::u8vec4>((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
429 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 1);
434 case ImageType::ColorCube:
436 auto kernel = [w, h](
size_t i,
size_t j,
size_t k) {
437 float U = (2.f*i) / w - 1.f;
438 float V = 1.f - (2.f * j) / h;
441 glm::vec3 d = cubeMapPermutationMatrix(k)*(glm::vec3(U, V, 1.f));
443 float m = (((i / 64) + (j / 64)) & 1) ? 1.f : 0.5f;
444 return glm::vec4(m, m, m, 1)*glm::vec4(0.5f*d + glm::vec3(0.5f), 1.f);
447 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 6);
448 texture->
setData(Cogs::ResourceDimensions::TextureCube, rgba.data(), rgba.byteSize(), (uint32_t)w, (uint32_t)h, 1, 1, 6, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
454 auto rgb = texture->
map((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
455 sampleSky(rgb, w, h);
459 case ImageType::SkyCube:
461 if (!std::isfinite(definition.sunDirection.x) ||
462 !std::isfinite(definition.sunDirection.y) ||
463 !std::isfinite(definition.sunDirection.z))
465 auto newDefininition = definition;
466 newDefininition.type = ImageType::ColorCube;
467 return factory(texture, newDefininition);
470 if (definition.hdr) {
472 sampleSkyLuminance(rgba, definition, w, h,
false,
true,
true);
473 texture->
setData(Cogs::ResourceDimensions::TextureCube, rgba.data(), rgba.byteSize(),
static_cast<uint32_t
>(w),
static_cast<uint32_t
>(h), 1, 1, 6, 1, Cogs::TextureFormat::R16G16B16A16_FLOAT,
true);
477 sampleSkyCube(rgba, definition, w, h);
478 texture->
setData(Cogs::ResourceDimensions::TextureCube, rgba.data(), rgba.byteSize(),
static_cast<uint32_t
>(w),
static_cast<uint32_t
>(h), 1, 1, 6, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
483 case ImageType::SkyRadiance:
485 if (!std::isfinite(definition.sunDirection.x) ||
486 !std::isfinite(definition.sunDirection.y) ||
487 !std::isfinite(definition.sunDirection.z))
489 auto newDefininition = definition;
490 newDefininition.type = ImageType::ColorCube;
491 return factory(texture, newDefininition);
493 size_t W = std::min((
size_t)128, w);
494 size_t H = std::min((
size_t)128, h);
497 sampleSkyLuminance(rgba, definition, W, H,
true,
true,
true);
498 texture->
setData(Cogs::ResourceDimensions::TextureCube, rgba.data(), rgba.byteSize(),
static_cast<uint32_t
>(W),
static_cast<uint32_t
>(H), 1, 1, 6, 1, Cogs::TextureFormat::R16G16B16A16_FLOAT,
true);
502 case ImageType::SkyIrradiance:
504 if (!std::isfinite(definition.sunDirection.x) ||
505 !std::isfinite(definition.sunDirection.y) ||
506 !std::isfinite(definition.sunDirection.z))
508 auto newDefininition = definition;
509 newDefininition.type = ImageType::ColorCube;
510 return factory(texture, newDefininition);
512 size_t W = std::min((
size_t)8, w);
513 size_t H = std::min((
size_t)8, h);
518 sampleSkyLuminance(radiance, definition, W, H,
true,
false,
true);
519 calcIrradiance(rgba, radiance, W, H);
520 texture->
setData(Cogs::ResourceDimensions::TextureCube, rgba.data(), rgba.byteSize(),
static_cast<uint32_t
>(W),
static_cast<uint32_t
>(H), 1, 1, 6, 1, Cogs::TextureFormat::R16G16B16A16_FLOAT,
true);
524 case ImageType::SkyAmbientIrradiance:
526 if(!std::isfinite(definition.sunDirection.x) ||
527 !std::isfinite(definition.sunDirection.y) ||
528 !std::isfinite(definition.sunDirection.z))
530 auto newDefininition = definition;
531 newDefininition.type = ImageType::ColorCube;
532 return factory(texture, newDefininition);
534 size_t W = std::min((
size_t)8, w);
535 size_t H = std::min((
size_t)8, h);
540 sampleSkyLuminance(radiance, definition, W, H,
true,
true,
false);
541 for (
size_t i = 0; i < W*H*6; i++) {
542 radiance[i] = glm::vec4(0.5f*glm::vec3(radiance[i]), 1);
544 calcIrradiance(rgba, radiance, W, H);
545 texture->
setData(Cogs::ResourceDimensions::TextureCube, rgba.data(), rgba.byteSize(),
static_cast<uint32_t
>(W),
static_cast<uint32_t
>(H), 1, 1, 6, 1, Cogs::TextureFormat::R16G16B16A16_FLOAT,
true);
550 case ImageType::SubseaRadiance:
552 if (!std::isfinite(definition.sunDirection.x) ||
553 !std::isfinite(definition.sunDirection.y) ||
554 !std::isfinite(definition.sunDirection.z))
556 auto newDefininition = definition;
557 newDefininition.type = ImageType::ColorCube;
558 return factory(texture, newDefininition);
560 size_t W = std::min((
size_t)32, w);
561 size_t H = std::min((
size_t)32, h);
564 sampleSubseaLuminance(rgba, definition, W, H);
565 texture->
setData(Cogs::ResourceDimensions::TextureCube, rgba.data(), rgba.byteSize(),
static_cast<uint32_t
>(W),
static_cast<uint32_t
>(H), 1, 1, 6, 1, Cogs::TextureFormat::R16G16B16A16_FLOAT,
true);
569 case ImageType::GradientRainbow:
571 uint8_t rgba[8 * 4] = {
572 0x9d, 0x00, 0xff, 0xff,
573 0x00, 0x27, 0xff, 0xff,
574 0x00, 0xc4, 0xff, 0xff,
575 0x00, 0xff, 0x9d, 0xff,
576 0x00, 0xff, 0x00, 0xff,
577 0xc4, 0xff, 0x00, 0xff,
578 0xff, 0x9d, 0x00, 0xff,
579 0xff, 0x00, 0x00, 0xff,
581 texture->
setData(Cogs::ResourceDimensions::Texture2D, rgba,
sizeof(rgba), 8, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
584 case ImageType::GradientHeat:
586 uint8_t rgba[8 * 4] = {
587 0x1e, 0x00, 0x00, 0xff,
588 0x55, 0x00, 0x00, 0xff,
589 0xc3, 0x26, 0x0c, 0xff,
590 0xf2, 0x74, 0x29, 0xff,
591 0xfb, 0xc6, 0x21, 0xff,
592 0xf8, 0xf1, 0x4c, 0xff,
593 0xf9, 0xf5, 0xa8, 0xff,
594 0xff, 0xff, 0xff, 0xff,
596 texture->
setData(Cogs::ResourceDimensions::Texture2D, rgba,
sizeof(rgba), 8, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
607 for (
auto & v : p.values) {
608 if (key == v.key)
return &v;
616 if (!p)
return defaultValue;
620 case ParsedDataType::UInt:
621 case ParsedDataType::Int:
624 case ParsedDataType::Float:
625 return static_cast<int>(p->floatValue);
633 uint32_t getUInt(
ParsedValue * p, uint32_t defaultValue)
635 return static_cast<uint32_t
>(getInt(p,
static_cast<int>(defaultValue)));
640 return p !=
nullptr && p->type == ParsedDataType::Bool ? p->boolValue : defaultValue;
643 glm::vec3 getFloat3(
ParsedValue * p,
const glm::vec3& defaultValue)
645 return p !=
nullptr && p->type == ParsedDataType::Float3 ? p->float3Value : defaultValue;
655 std::unordered_map<size_t, TextureHandle> images;
659Cogs::Core::TextureGenerator::TextureGenerator(
Context * context) :
665Cogs::Core::TextureGenerator::~TextureGenerator()
669void Cogs::Core::TextureGenerator::cleanup()
671 LockGuard cacheLock(cache->lock);
673 cache->images.clear();
684 .sunDirection = getFloat3(getValue(parameters,
"sunDirection"),
ImageDefinition().sunDirection),
685 .sunIrradiance = getFloat3(getValue(parameters,
"sunIrradiance"),
ImageDefinition().sunIrradiance),
687 .width = getUInt(getValue(parameters,
"width"),
ImageDefinition().width),
688 .height = getUInt(getValue(parameters,
"height"),
ImageDefinition().height),
689 .layers = getUInt(getValue(parameters,
"layers"),
ImageDefinition().layers),
693 size_t hashValue = definition.hash();
696 LockGuard cacheLock(cache->lock);
698 auto found = cache->images.find(hashValue);
700 if (found != cache->images.end()) {
701 return found->second;
705 auto texture = context->textureManager->create();
707 factory(texture.resolve(), definition);
709 LockGuard cacheLock(cache->lock);
711 cache->images[hashValue] = texture;
718 factory(texture, definition);
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Provides a weakly referenced view over the contents of a string.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
Stores the parsed output of a key/value pair.
Texture resources contain raster bitmap data to use for texturing.
MappedTexture< uint8_t > map(uint16_t width, uint16_t height, TextureFormat format, bool generateMipMap)
Map the texture data, ensuring the data is sized to hold width * height * bpp of the format bytes.
void setData(ResourceDimensions target, const void *data, size_t size, int width, int height, TextureFormat format, bool generateMipMap)
Set the texture data.