1#include "TextureGenerator.h"
3#include <unordered_map>
5#include <glm/gtc/constants.hpp>
7#include "Foundation/Platform/Threads.h"
9#include "Resources/TextureManager.h"
10#include "Utilities/NoiseSampler.h"
20 glm::detail::hdata r, g, b, a;
25 glm::vec3 inverseSphereGeoTexMapping(
float u,
float v)
28 dir.z = -std::cos(glm::pi<float>() * v);
29 float t = 1.f / std::sqrt(1.f - dir.z*dir.z);
30 dir.y = std::cos(2.f*glm::pi<float>()* u) / t;
31 dir.x = (u < 0.5 ? 1 : -1.f)* std::sqrt(1.f - dir.z*dir.z - dir.y*dir.y);
37 glm::mat3 cubeMapPermutationMatrix(
size_t f)
45 R = glm::mat3(0.f, 0.f, -1.f,
51 R = glm::mat3(0.f, 0.f, 1.f,
57 R = glm::mat3(1.f, 0.f, 0.f,
63 R = glm::mat3(1.f, 0.f, 0.f,
69 R = glm::mat3(1.f, 0.f, 0.f,
76 R = glm::mat3(-1.f, 0.f, 0.f,
85 glm::vec3 cubeMapDir(
float u,
float v,
size_t f)
87 glm::mat3 T(2.f, 0.f, 0.f,
90 return glm::normalize(cubeMapPermutationMatrix(f)*(T*glm::vec3(u, v, 1.f)));
93 template<
typename Kernel,
typename Collection,
typename Element>
96 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f);
99 template<
typename Kernel,
typename Collection>
100 struct Sampler<Kernel, Collection, glm::u8vec4>
102 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f)
104 for (
size_t k = 0; k < f; k++) {
105 for (
size_t j = 0; j < h; j++) {
106 for (
size_t i = 0; i < w; i++) {
107 const auto v = kernel(i, j, k);
108 rgba[(k*h + j)*w + i].r =
static_cast<uint8_t
>(glm::clamp(255.f*v.r, 0.f, 255.f));
109 rgba[(k*h + j)*w + i].g =
static_cast<uint8_t
>(glm::clamp(255.f*v.g, 0.f, 255.f));
110 rgba[(k*h + j)*w + i].b =
static_cast<uint8_t
>(glm::clamp(255.f*v.b, 0.f, 255.f));
111 rgba[(k*h + j)*w + i].a =
static_cast<uint8_t
>(glm::clamp(255.f*v.a, 0.f, 255.f));
118 template<
typename Kernel,
typename Collection>
119 struct Sampler<Kernel, Collection, half4>
121 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f)
123 for (
size_t k = 0; k < f; k++) {
124 for (
size_t j = 0; j < h; j++) {
125 for (
size_t i = 0; i < w; i++) {
126 const auto v = kernel(i, j, k);
127 rgba[(k*h + j)*w + i].r = glm::detail::toFloat16(v.r);
128 rgba[(k*h + j)*w + i].g = glm::detail::toFloat16(v.g);
129 rgba[(k*h + j)*w + i].b = glm::detail::toFloat16(v.b);
130 rgba[(k*h + j)*w + i].a = glm::detail::toFloat16(v.a);
137 template<
typename Kernel,
typename Collection>
138 struct Sampler<Kernel, Collection, glm::vec4>
140 static void run(Collection& rgba,
const Kernel& kernel,
const size_t w,
const size_t h,
const size_t f)
142 for (
size_t k = 0; k < f; k++) {
143 for (
size_t j = 0; j < h; j++) {
144 for (
size_t i = 0; i < w; i++) {
145 const auto v = kernel(i, j, k);
146 rgba[(k*h + j)*w + i].r = v.r;
147 rgba[(k*h + j)*w + i].g = v.g;
148 rgba[(k*h + j)*w + i].b = v.b;
149 rgba[(k*h + j)*w + i].a = v.a;
171 float cubeTexelSolidAngle(
float uMin,
float uMax,
float vMin,
float vMax)
173 float fA = std::atan2(uMin * vMin, std::sqrt(uMin * uMin + vMin * vMin + 1));
174 float fB = std::atan2(uMax * vMin, std::sqrt(uMax * uMax + vMin * vMin + 1));
175 float fC = std::atan2(uMax * vMax, std::sqrt(uMax * uMax + vMax * vMax + 1));
176 float fD = std::atan2(uMin * vMax, std::sqrt(uMin * uMin + vMax * vMax + 1));
177 return fA - fB + fC - fD;
182 for (
size_t k1 = 0; k1 < 6; k1++) {
183 glm::mat3 P1 = cubeMapPermutationMatrix(k1)*glm::mat3(2.f / W, 0.f, 0.f,
185 -(1.f - 1.f / W), 1.f - 1.f / H, 1.f);
186 for (
size_t j1 = 0; j1 < H; j1++) {
187 for (
size_t i1 = 0; i1 < W; i1++) {
188 auto d1 = glm::normalize(P1*glm::vec3(i1, j1, 1.f));
190 glm::vec3 irradiance;
191 for (
size_t k0 = 0; k0 < 6; k0++) {
192 glm::mat3 P0 = cubeMapPermutationMatrix(k0)*glm::mat3(2.f / W, 0.f, 0.f,
194 -(1.f - 1.f / W), 1.f - 1.f / H, 1.f);
195 for (
size_t j0 = 0; j0 < H; j0++) {
196 for (
size_t i0 = 0; i0 < W; i0++) {
197 auto d0 = glm::normalize(P0*glm::vec3(i0, j0, 1.f));
198 if (0.f < glm::dot(d0, d1)) {
200 float uMin = 2.f*(i0 + 0.f) / W - 1.f;
201 float uMax = 2.f*(i0 + 1.f) / W - 1.f;
202 float vMin = 2.f*(j0 + 0.f) / H - 1.f;
203 float vMax = 2.f*(j0 + 1.f) / H - 1.f;
204 float w = cubeTexelSolidAngle(uMin, uMax, vMin, vMax);
206 irradiance += w * glm::vec3(radiance[(k0*H + j0)*W + i0]);
213 dst[(k1*H + j1)*W + i1].r = glm::detail::toFloat16(irradiance.r);
214 dst[(k1*H + j1)*W + i1].g = glm::detail::toFloat16(irradiance.g);
215 dst[(k1*H + j1)*W + i1].b = glm::detail::toFloat16(irradiance.b);
216 dst[(k1*H + j1)*W + i1].a = glm::detail::toFloat16(1.f);
227 float indirectDirectRatio = 70.f / 1050.f;
232 constexpr float radianceIrradianceRatio = 1.f / glm::pi<float>();
239 const auto& s = definition.sunDirection;
240 const glm::vec3 sunDir = glm::normalize(glm::vec3(s.x, s.z, s.y));
241 const glm::vec3 up = normalize(glm::vec3(0, 1, 0));
243 auto sunIrradiance = definition.sunIrradiance;
244 auto sunRadiance = radianceIrradianceRatio * indirectDirectRatio*glm::length(sunIrradiance);
245 auto sunCol = (1.f / (std::max(std::max(sunIrradiance.r, sunIrradiance.g), sunIrradiance.b)))*sunIrradiance;
247 auto kernel = [&sunDir, sunRadiance, &sunCol, lightBottom, withSky, withSun, &up, w, h](
size_t i,
size_t j,
size_t k) {
248 auto sampleDir = cubeMapDir(
float(i + 0.5f) /
float(w),
float(j + 0.5f) /
float(h), k);
255 float zeta_cos = std::max(0.f, glm::dot(sunDir, sampleDir));
256 float zeta = std::acos(zeta_cos);
257 float gamma_sin = std::max(0.f, dot(sampleDir, up));
258 float gamma_s_sin = std::max(0.f, dot(sunDir, up));
260 float pi2_zeta_s = glm::half_pi<float>() - std::asin(gamma_s_sin);
261 float pi2_zeta_s_cos = std::cos(pi2_zeta_s);
263 float phi_gamma = 1.f - std::exp(-0.32f / gamma_sin);
265 float f_zeta = 0.91f + 19.f * std::exp(-3.f * zeta) + 0.45f*zeta_cos*zeta_cos;
267 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;
268 float phi_pi2 = 0.27385f;
271 float clear = (phi_gamma*f_zeta) / (phi_pi2* f_pi2_zeta_s);
275 rv = glm::mix(glm::vec3(0.f, 0.1f, 0.3f), sunCol, 0.1f*std::max(0.f, clear - 0.5f));
279 rv += 20.f*std::pow(zeta_cos, 100.f)*sunCol;
282 if (!lightBottom && glm::dot(sampleDir, up) < 0.f) {
283 rv = glm::mix(rv, glm::vec3(0, 0, 0.0), glm::clamp(-3 * glm::dot(sampleDir, up), 0.f, 1.f));
285 return glm::vec4(sunRadiance*rv, 1.f);
287 rgba.resize(w * h * 6);
288 Sampler<
decltype(kernel),
decltype(rgba), T>::run(rgba, kernel, w, h, 6);
294 const auto& s = definition.sunDirection;
295 const glm::vec3 sunDir = glm::normalize(glm::vec3(s.x, s.z, s.y));
296 auto sunRadiance = glm::length(definition.sunIrradiance);
298 auto kernel = [&sunDir, sunRadiance, w, h](
size_t i,
size_t j,
size_t k) {
299 auto sampleDir = cubeMapDir(
float(i + 0.5f) /
float(w),
float(j + 0.5f) /
float(h), k);
301 const glm::vec3 seaColor(0.1f, 0.7f, 1.f);
303 float t = std::pow(1.f - (1.f / glm::pi<float>())*std::acos(glm::dot(sampleDir, sunDir)), 3.f);
305 return glm::vec4(1e-3f*seaColor*sunRadiance*t, 1.f);
307 rgba.resize(w * h * 6);
308 Sampler<
decltype(kernel),
decltype(rgba), T>::run(rgba, kernel, w, h, 6);
314 auto kernel = [w, h](
size_t i,
size_t j,
size_t k) {
315 auto dir = cubeMapDir(
float(i) /
float(w),
float(j) /
float(h), k);
316 float z = 0.5f*(dir.z + 1.f);
318 const glm::vec3 waterColor(0.f, 0.2, 0.3);
319 const glm::vec3 skyColorHorizon(0.3, 0.4, 0.5);
320 const glm::vec3 skyColorZenith(0.8, 0.9, 1.0);
323 c = glm::mix(waterColor, skyColorHorizon, 2.f*z);
326 c = 1.5f*glm::mix(skyColorHorizon, skyColorZenith, 2.f*(z - 0.5f));
328 return glm::vec4(c, 1.f);
331 rgba.resize(w * h * 6);
332 Sampler<
decltype(kernel),
decltype(rgba), T>::run(rgba, kernel, w, h, 6);
335 template<
typename Collection>
336 void sampleSky(Collection & rgba,
size_t w,
size_t h)
338 glm::vec3 waterColor(0.f, 0.2, 0.3);
339 glm::vec3 skyColorHorizon(0.3, 0.4, 0.5);
340 glm::vec3 skyColorZenith(0.8, 0.9, 1.0);
342 for (
size_t j = 0; j < h; j++) {
343 for (
size_t i = 0; i < w; i++) {
344 float z = float(j) / float(h);
347 c = glm::mix(waterColor, skyColorHorizon, 2.f*z);
350 c = 1.5f*glm::mix(skyColorHorizon, skyColorZenith, 2.f*(z - 0.5f));
353 rgba[4 * (w*j + i) + 0] =
static_cast<uint8_t
>(255.f*glm::clamp(c.r, 0.f, 1.f));
354 rgba[4 * (w*j + i) + 1] =
static_cast<uint8_t
>(255.f*glm::clamp(c.g, 0.f, 1.f));
355 rgba[4 * (w*j + i) + 2] =
static_cast<uint8_t
>(255.f*glm::clamp(c.b, 0.f, 1.f));
356 rgba[4 * (w*j + i) + 3] = 255;
363 const size_t w = std::max(1u, definition.width);
364 const size_t h = std::max(1u, definition.height);
365 const size_t l = std::max(1u, definition.layers);
366 switch (definition.type) {
367 case ImageType::CheckerBoard:
369 auto kernel = [](
size_t i,
size_t j,
size_t ) {
370 bool t = ((i / 16 + j / 16) & 0x1) == 1;
371 return glm::vec4(1.f, 1.f, t ? 0.5f : 1.f, 1.f);
373 auto rgba = texture->
map<glm::u8vec4>((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
374 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 1);
378 case ImageType::ColorfulCheckerBoard:
380 auto kernel = [A = 1.f / w, B = 1.f / h, C = 1.f / l, l](
size_t i,
size_t j,
size_t k) {
381 bool t = ((i / 16 + j / 16) & 0x1) == 1;
382 return glm::vec4(t ? A * i : 1.f, t ? B * j : 1.f, t ? 0.f : C * (
float(l - k)), 1.f);
385 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, l);
387 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);
390 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);
395 case ImageType::Dirt:
397 std::vector<float> noise(w*h);
399 noiseSampler.gradNoise2DTurbulence(noise.data(), 16.0f, 256.f, (
int)w, (
int)h);
400 auto kernel = [&noise, w, h](
size_t i,
size_t j,
size_t ) {
401 float n0 = 0.5f + 0.5f*noise[w*j + i];
402 float n1 = 0.5f + 0.5f*noise[w*((2 * j + 15) % h) + ((2 * i + 44) % w)];
403 return glm::vec4(0.3f + 0.20f*n0 + 0.15f*n1,
404 0.2f + 0.15f*n0 + 0.20f*n1,
405 0.1f + 0.05f*n0 + 0.15f*n1,
408 auto rgba = texture->
map<glm::u8vec4>((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
409 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 1);
414 case ImageType::Steel:
416 std::vector<float> noise(w*h);
418 noiseSampler.gradNoise2DTurbulence(noise.data(), 16.0f, 64.f, (
int)w, (
int)h);
419 auto kernel = [&noise, w, h](
size_t i,
size_t j,
size_t ) {
420 float n0 = 0.5f + 0.5f*noise[w*((j) % h) + (8 * i) % w];
421 float n1 = 0.5f + 0.5f*noise[w*((j + 0) % h) + ((i) % w)];
422 return glm::vec4(0.5f + 0.10f*n0 + 0.07f*n1,
423 0.5f + 0.10f*n0 + 0.06f*n1,
424 0.5f + 0.13f*n0 + 0.05f*n1,
427 auto rgba = texture->
map<glm::u8vec4>((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
428 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 1);
433 case ImageType::ColorCube:
435 auto kernel = [w, h](
size_t i,
size_t j,
size_t k) {
436 float U = (2.f*i) / w - 1.f;
437 float V = 1.f - (2.f * j) / h;
440 glm::vec3 d = cubeMapPermutationMatrix(k)*(glm::vec3(U, V, 1.f));
442 float m = (((i / 64) + (j / 64)) & 1) ? 1.f : 0.5f;
443 return glm::vec4(m, m, m, 1)*glm::vec4(0.5f*d + glm::vec3(0.5f), 1.f);
446 Sampler<
decltype(kernel),
decltype(rgba), glm::u8vec4>::run(rgba, kernel, w, h, 6);
447 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);
453 auto rgb = texture->
map((uint16_t)w, (uint16_t)h, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
454 sampleSky(rgb, w, h);
458 case ImageType::SkyCube:
460 if (!std::isfinite(definition.sunDirection.x) ||
461 !std::isfinite(definition.sunDirection.y) ||
462 !std::isfinite(definition.sunDirection.z))
464 auto newDefininition = definition;
465 newDefininition.type = ImageType::ColorCube;
466 return factory(texture, newDefininition);
469 if (definition.hdr) {
471 sampleSkyLuminance(rgba, definition, w, h,
false,
true,
true);
472 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);
476 sampleSkyCube(rgba, definition, w, h);
477 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);
482 case ImageType::SkyRadiance:
484 if (!std::isfinite(definition.sunDirection.x) ||
485 !std::isfinite(definition.sunDirection.y) ||
486 !std::isfinite(definition.sunDirection.z))
488 auto newDefininition = definition;
489 newDefininition.type = ImageType::ColorCube;
490 return factory(texture, newDefininition);
492 size_t W = std::min((
size_t)128, w);
493 size_t H = std::min((
size_t)128, h);
496 sampleSkyLuminance(rgba, definition, W, H,
true,
true,
true);
497 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);
501 case ImageType::SkyIrradiance:
503 if (!std::isfinite(definition.sunDirection.x) ||
504 !std::isfinite(definition.sunDirection.y) ||
505 !std::isfinite(definition.sunDirection.z))
507 auto newDefininition = definition;
508 newDefininition.type = ImageType::ColorCube;
509 return factory(texture, newDefininition);
511 size_t W = std::min((
size_t)8, w);
512 size_t H = std::min((
size_t)8, h);
517 sampleSkyLuminance(radiance, definition, W, H,
true,
false,
true);
518 calcIrradiance(rgba, radiance, W, H);
519 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);
523 case ImageType::SkyAmbientIrradiance:
525 if(!std::isfinite(definition.sunDirection.x) ||
526 !std::isfinite(definition.sunDirection.y) ||
527 !std::isfinite(definition.sunDirection.z))
529 auto newDefininition = definition;
530 newDefininition.type = ImageType::ColorCube;
531 return factory(texture, newDefininition);
533 size_t W = std::min((
size_t)8, w);
534 size_t H = std::min((
size_t)8, h);
539 sampleSkyLuminance(radiance, definition, W, H,
true,
true,
false);
540 for (
size_t i = 0; i < W*H*6; i++) {
541 radiance[i] = glm::vec4(0.5f*glm::vec3(radiance[i]), 1);
543 calcIrradiance(rgba, radiance, W, H);
544 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);
549 case ImageType::SubseaRadiance:
551 if (!std::isfinite(definition.sunDirection.x) ||
552 !std::isfinite(definition.sunDirection.y) ||
553 !std::isfinite(definition.sunDirection.z))
555 auto newDefininition = definition;
556 newDefininition.type = ImageType::ColorCube;
557 return factory(texture, newDefininition);
559 size_t W = std::min((
size_t)32, w);
560 size_t H = std::min((
size_t)32, h);
563 sampleSubseaLuminance(rgba, definition, W, H);
564 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);
568 case ImageType::GradientRainbow:
570 uint8_t rgba[8 * 4] = {
571 0x9d, 0x00, 0xff, 0xff,
572 0x00, 0x27, 0xff, 0xff,
573 0x00, 0xc4, 0xff, 0xff,
574 0x00, 0xff, 0x9d, 0xff,
575 0x00, 0xff, 0x00, 0xff,
576 0xc4, 0xff, 0x00, 0xff,
577 0xff, 0x9d, 0x00, 0xff,
578 0xff, 0x00, 0x00, 0xff,
580 texture->
setData(Cogs::ResourceDimensions::Texture2D, rgba,
sizeof(rgba), 8, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
583 case ImageType::GradientHeat:
585 uint8_t rgba[8 * 4] = {
586 0x1e, 0x00, 0x00, 0xff,
587 0x55, 0x00, 0x00, 0xff,
588 0xc3, 0x26, 0x0c, 0xff,
589 0xf2, 0x74, 0x29, 0xff,
590 0xfb, 0xc6, 0x21, 0xff,
591 0xf8, 0xf1, 0x4c, 0xff,
592 0xf9, 0xf5, 0xa8, 0xff,
593 0xff, 0xff, 0xff, 0xff,
595 texture->
setData(Cogs::ResourceDimensions::Texture2D, rgba,
sizeof(rgba), 8, 1, Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB,
true);
606 for (
auto & v : p.values) {
607 if (key == v.key)
return &v;
615 if (!p)
return defaultValue;
619 case ParsedDataType::UInt:
620 case ParsedDataType::Int:
623 case ParsedDataType::Float:
624 return static_cast<int>(p->floatValue);
632 uint32_t getUInt(
ParsedValue * p, uint32_t defaultValue)
634 return static_cast<uint32_t
>(getInt(p,
static_cast<int>(defaultValue)));
639 return p !=
nullptr && p->type == ParsedDataType::Bool ? p->boolValue : defaultValue;
642 glm::vec3 getFloat3(
ParsedValue * p,
const glm::vec3& defaultValue)
644 return p !=
nullptr && p->type == ParsedDataType::Float3 ? p->float3Value : defaultValue;
654 std::unordered_map<size_t, TextureHandle> images;
658Cogs::Core::TextureGenerator::TextureGenerator(
Context * context) :
664Cogs::Core::TextureGenerator::~TextureGenerator()
668void Cogs::Core::TextureGenerator::cleanup()
670 LockGuard cacheLock(cache->lock);
672 cache->images.clear();
683 .sunDirection = getFloat3(getValue(parameters,
"sunDirection"),
ImageDefinition().sunDirection),
684 .sunIrradiance = getFloat3(getValue(parameters,
"sunIrradiance"),
ImageDefinition().sunIrradiance),
686 .width = getUInt(getValue(parameters,
"width"),
ImageDefinition().width),
687 .height = getUInt(getValue(parameters,
"height"),
ImageDefinition().height),
688 .layers = getUInt(getValue(parameters,
"layers"),
ImageDefinition().layers),
692 size_t hashValue = definition.hash();
695 LockGuard cacheLock(cache->lock);
697 auto found = cache->images.find(hashValue);
699 if (found != cache->images.end()) {
700 return found->second;
704 auto texture = context->textureManager->create();
706 factory(texture.resolve(), definition);
708 LockGuard cacheLock(cache->lock);
710 cache->images[hashValue] = texture;
717 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.