24# include <OSL/oslexec.h>
51 return "nanovdb_float";
53 return "nanovdb_float3";
57 return "nanovdb_fp16";
59 assert(!
"System enumerator type, should never be used");
62 assert(!
"Unhandled image data type");
102 manager->remove_image_user(slot);
126 manager->load_image_metadata(img);
136 if (
manager->osl_texture_system) {
151 svm_slots.reserve(num_nodes);
152 for (
size_t i = 0; i < num_nodes; i++) {
156 node.
x =
manager->images[slot]->loader->get_tile_number();
161 node.
z =
manager->images[slot]->loader->get_tile_number();
169 svm_slots.push_back(node);
199 if (loader ==
NULL) {
296 return (a &&
b &&
typeid(*a) ==
typeid(*
b) && a->
equals(*
b));
310 osl_texture_system =
NULL;
319 for (
size_t slot = 0; slot < images.size(); slot++) {
320 assert(!images[slot]);
326 osl_texture_system = texture_system;
331 if (frame != animation_frame) {
333 animation_frame = frame;
335 for (
size_t slot = 0; slot < images.size(); slot++) {
336 if (images[slot] && images[slot]->
params.animated) {
345void ImageManager::load_image_metadata(
Image *img)
347 if (!img->need_metadata) {
352 if (!img->need_metadata) {
356 ImageMetaData &metadata = img->metadata;
357 metadata = ImageMetaData();
360 if (img->loader->load_metadata(features, metadata)) {
374 img->need_metadata =
false;
395 string tile_filename = filename;
402 int u = ((
tile - 1001) % 10);
403 int v = ((
tile - 1001) / 10);
417 const size_t slot = add_image_slot(loader,
params, builtin);
430 const size_t slot = add_image_slot(loader,
params,
true);
438size_t ImageManager::add_image_slot(
ImageLoader *loader,
448 for (slot = 0; slot < images.size(); slot++) {
458 for (slot = 0; slot < images.size(); slot++) {
464 if (slot == images.size()) {
465 images.resize(images.size() + 1);
471 img->loader = loader;
472 img->need_metadata =
true;
473 img->need_load = !(osl_texture_system && !img->loader->osl_filepath().empty());
474 img->builtin = builtin;
485void ImageManager::add_image_user(
size_t slot)
494void ImageManager::remove_image_user(
size_t slot)
506 if (
image->users == 0) {
520template<TypeDesc::BASETYPE FileFormat,
typename StorageType>
521bool ImageManager::file_load_image(
Image *img,
int texture_limit)
524 if (!(img->metadata.channels > 0)) {
529 int width = img->metadata.width;
530 int height = img->metadata.height;
531 int depth = img->metadata.depth;
532 int components = img->metadata.channels;
537 const size_t max_size =
max(
max(width, height), depth);
544 if (texture_limit > 0 && max_size > texture_limit) {
545 pixels_storage.resize(((
size_t)width) * height * depth * 4);
546 pixels = &pixels_storage[0];
550 pixels = (StorageType *)img->mem->alloc(width, height, depth);
553 if (pixels ==
NULL) {
558 const size_t num_pixels = ((size_t)width) * height * depth;
559 img->loader->load_pixels(
572 if (components == 2) {
574 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
575 pixels[i * 4 + 3] = pixels[i * 2 + 1];
576 pixels[i * 4 + 2] = pixels[i * 2 + 0];
577 pixels[i * 4 + 1] = pixels[i * 2 + 0];
578 pixels[i * 4 + 0] = pixels[i * 2 + 0];
581 else if (components == 3) {
583 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
584 pixels[i * 4 + 3] = one;
585 pixels[i * 4 + 2] = pixels[i * 3 + 2];
586 pixels[i * 4 + 1] = pixels[i * 3 + 1];
587 pixels[i * 4 + 0] = pixels[i * 3 + 0];
590 else if (components == 1) {
592 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
593 pixels[i * 4 + 3] = one;
594 pixels[i * 4 + 2] = pixels[i];
595 pixels[i * 4 + 1] = pixels[i];
596 pixels[i * 4 + 0] = pixels[i];
602 for (
size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
603 pixels[i * 4 + 3] = one;
613 img->metadata.colorspace, pixels, num_pixels, is_rgba, img->metadata.compress_as_srgb);
617 if constexpr (FileFormat == TypeDesc::FLOAT) {
622 for (
size_t i = 0; i < num_pixels; i += 4) {
623 StorageType *pixel = &pixels[i * 4];
624 if (!isfinite(pixel[0]) || !isfinite(pixel[1]) || !isfinite(pixel[2]) ||
635 for (
size_t i = 0; i < num_pixels; ++i) {
636 StorageType *pixel = &pixels[i];
637 if (!isfinite(pixel[0])) {
645 if (pixels_storage.size() > 0) {
646 float scale_factor = 1.0f;
647 while (max_size * scale_factor > texture_limit) {
648 scale_factor *= 0.5f;
650 VLOG_WORK <<
"Scaling image " << img->loader->name() <<
" by a factor of " << scale_factor
653 size_t scaled_width, scaled_height, scaled_depth;
665 StorageType *texture_pixels;
669 texture_pixels = (StorageType *)img->mem->alloc(scaled_width, scaled_height, scaled_depth);
672 memcpy(texture_pixels, &scaled_pixels[0], scaled_pixels.size() *
sizeof(StorageType));
678void ImageManager::device_load_image(
Device *device,
Scene *scene,
size_t slot,
Progress *progress)
684 Image *img = images[slot];
686 progress->
set_status(
"Updating Images",
"Loading " + img->loader->name());
690 load_image_metadata(img);
703 img->mem =
new device_texture(
704 device, img->mem_name.c_str(), slot, type, img->params.interpolation, img->params.extension);
705 img->mem->info.use_transform_3d = img->metadata.use_transform_3d;
706 img->mem->info.transform_3d = img->metadata.transform_3d;
710 if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit)) {
713 float *pixels = (
float *)img->mem->alloc(1, 1);
722 if (!file_load_image<TypeDesc::FLOAT, float>(img, texture_limit)) {
725 float *pixels = (
float *)img->mem->alloc(1, 1);
731 if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit)) {
734 uchar *pixels = (
uchar *)img->mem->alloc(1, 1);
743 if (!file_load_image<TypeDesc::UINT8, uchar>(img, texture_limit)) {
746 uchar *pixels = (
uchar *)img->mem->alloc(1, 1);
752 if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit)) {
755 half *pixels = (
half *)img->mem->alloc(1, 1);
764 if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit)) {
773 if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, texture_limit)) {
785 if (!file_load_image<TypeDesc::HALF, half>(img, texture_limit)) {
788 half *pixels = (
half *)img->mem->alloc(1, 1);
798 void *pixels = img->mem->alloc(img->metadata.byte_size, 0);
800 if (pixels !=
NULL) {
801 img->loader->load_pixels(img->metadata, pixels, img->metadata.byte_size,
false);
808 img->mem->copy_to_device();
812 img->loader->cleanup();
813 img->need_load =
false;
816void ImageManager::device_free_image(
Device *,
size_t slot)
818 Image *img = images[slot];
823 if (osl_texture_system) {
825 ustring filepath = img->loader->osl_filepath();
826 if (!filepath.empty()) {
827 ((OSL::TextureSystem *)osl_texture_system)->invalidate(filepath);
855 for (
size_t slot = 0; slot < images.size(); slot++) {
856 Image *img = images[slot];
857 if (img && img->
users == 0) {
858 device_free_image(device, slot);
862 function_bind(&ImageManager::device_load_image,
this, device, scene, slot, &progress));
868 need_update_ =
false;
876 Image *img = images[slot];
879 if (img->
users == 0) {
880 device_free_image(device, slot);
883 device_load_image(device, scene, slot, progress);
896 for (
size_t slot = 0; slot < images.size(); slot++) {
897 Image *img = images[slot];
900 function_bind(&ImageManager::device_load_image,
this, device, scene, slot, &progress));
909 for (
size_t slot = 0; slot < images.size(); slot++) {
910 Image *img = images[slot];
912 device_free_image(device, slot);
919 for (
size_t slot = 0; slot < images.size(); slot++) {
920 device_free_image(device, slot);
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
ATTR_WARN_UNUSED_RESULT const BMVert * v
static bool colorspace_is_data(ustring colorspace)
static ustring detect_known_colorspace(ustring colorspace, const char *file_colorspace, const char *file_format, bool is_float)
static void to_scene_linear(ustring colorspace, T *pixels, size_t num_pixels, bool is_rgba, bool compress_as_srgb)
vector< size_t > tile_slots
ImageManager * get_manager() const
bool operator==(const ImageHandle &other) const
friend class ImageManager
VDBImageLoader * vdb_loader(const int tile_index=0) const
device_texture * image_memory(const int tile_index=0) const
ImageHandle & operator=(const ImageHandle &other)
int svm_slot(const int tile_index=0) const
vector< int4 > get_svm_slots() const
virtual bool equals(const ImageLoader &other) const =0
virtual ustring osl_filepath() const
virtual int get_tile_number() const
virtual bool is_vdb_loader() const
bool set_animation_frame_update(int frame)
ImageManager(const DeviceInfo &info)
void device_update(Device *device, Scene *scene, Progress &progress)
void device_free(Device *device)
void device_update_slot(Device *device, Scene *scene, size_t slot, Progress *progress)
void device_load_builtin(Device *device, Scene *scene, Progress &progress)
void device_free_builtin(Device *device)
ImageHandle add_image(const string &filename, const ImageParams ¶ms)
void collect_statistics(RenderStats *stats)
void set_osl_texture_system(void *texture_system)
ImageAlphaType alpha_type
void add_entry(const NamedSizeEntry &entry)
void add_entry(const NamedTimeEntry &entry)
void set_status(const string &status_, const string &substatus_="")
ustring u_colorspace_srgb
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
local_group_size(16, 16) .push_constant(Type b
T util_image_cast_from_float(float value)
CCL_NAMESPACE_BEGIN OIIO_NAMESPACE_USING void util_image_resize_pixels(const vector< T > &input_pixels, const size_t input_width, const size_t input_height, const size_t input_depth, const size_t components, vector< T > *output_pixels, size_t *output_width, size_t *output_height, size_t *output_depth)
#define CCL_NAMESPACE_END
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
ccl_global const KernelWorkTile * tile
const char * name_from_type(ImageDataType type)
static bool image_associate_alpha(ImageManager::Image *img)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
void string_replace(string &haystack, const string &needle, const string &other)
SceneUpdateStats * update_stats
void push(TaskRunFunction &&task)
void wait_work(Summary *stats=NULL)
std::unique_lock< std::mutex > thread_scoped_lock
@ IMAGE_DATA_TYPE_NANOVDB_FP16
@ IMAGE_DATA_TYPE_USHORT4
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
@ IMAGE_DATA_TYPE_NANOVDB_FPN
@ IMAGE_ALPHA_CHANNEL_PACKED
#define TEX_IMAGE_MISSING_R
#define TEX_IMAGE_MISSING_B
#define TEX_IMAGE_MISSING_A
#define TEX_IMAGE_MISSING_G
ccl_device_inline size_t divide_up(size_t x, size_t y)