diff options
Diffstat (limited to 'intern/cycles/blender/blender_image.cpp')
-rw-r--r-- | intern/cycles/blender/blender_image.cpp | 380 |
1 files changed, 120 insertions, 260 deletions
diff --git a/intern/cycles/blender/blender_image.cpp b/intern/cycles/blender/blender_image.cpp index 55ce6a295d1..459dc1779fb 100644 --- a/intern/cycles/blender/blender_image.cpp +++ b/intern/cycles/blender/blender_image.cpp @@ -14,206 +14,71 @@ * limitations under the License. */ -#include "render/image.h" +#include "MEM_guardedalloc.h" -#include "blender/blender_sync.h" +#include "blender/blender_image.h" #include "blender/blender_session.h" #include "blender/blender_util.h" CCL_NAMESPACE_BEGIN -/* builtin image file name is actually an image datablock name with - * absolute sequence frame number concatenated via '@' character - * - * this function splits frame from builtin name - */ -int BlenderSession::builtin_image_frame(const string &builtin_name) +/* Packed Images */ + +BlenderImageLoader::BlenderImageLoader(BL::Image b_image, int frame) + : b_image(b_image), frame(frame), free_cache(!b_image.has_data()) { - int last = builtin_name.find_last_of('@'); - return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str()); } -void BlenderSession::builtin_image_info(const string &builtin_name, - void *builtin_data, - ImageMetaData &metadata) +bool BlenderImageLoader::load_metadata(ImageMetaData &metadata) { - /* empty image */ - metadata.width = 1; - metadata.height = 1; - - if (!builtin_data) - return; - - /* recover ID pointer */ - PointerRNA ptr; - RNA_id_pointer_create((ID *)builtin_data, &ptr); - BL::ID b_id(ptr); - - if (b_id.is_a(&RNA_Image)) { - /* image data */ - BL::Image b_image(b_id); + metadata.width = b_image.size()[0]; + metadata.height = b_image.size()[1]; + metadata.depth = 1; + metadata.channels = b_image.channels(); - metadata.builtin_free_cache = !b_image.has_data(); - metadata.is_float = b_image.is_float(); - metadata.width = b_image.size()[0]; - metadata.height = b_image.size()[1]; - metadata.depth = 1; - metadata.channels = b_image.channels(); - - if (metadata.is_float) { - /* Float images are already converted on the Blender side, - * no need to do anything in Cycles. */ - metadata.colorspace = u_colorspace_raw; + if (b_image.is_float()) { + if (metadata.channels == 1) { + metadata.type = IMAGE_DATA_TYPE_FLOAT; } - } - else if (b_id.is_a(&RNA_Object)) { - /* smoke volume data */ - BL::Object b_ob(b_id); - BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); - - metadata.is_float = true; - metadata.depth = 1; - metadata.channels = 1; - - if (!b_domain) - return; - - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) - metadata.channels = 1; - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) - metadata.channels = 4; - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) - metadata.channels = 3; - else - return; - - int3 resolution = get_int3(b_domain.domain_resolution()); - int amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; - - /* Velocity and heat data is always low-resolution. */ - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { - amplify = 1; + else if (metadata.channels == 4) { + metadata.type = IMAGE_DATA_TYPE_FLOAT4; } - - metadata.width = resolution.x * amplify; - metadata.height = resolution.y * amplify; - metadata.depth = resolution.z * amplify; - } - else { - /* TODO(sergey): Check we're indeed in shader node tree. */ - PointerRNA ptr; - RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); - BL::Node b_node(ptr); - if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { - BL::ShaderNodeTexPointDensity b_point_density_node(b_node); - metadata.channels = 4; - metadata.width = b_point_density_node.resolution(); - metadata.height = metadata.width; - metadata.depth = metadata.width; - metadata.is_float = true; + else { + return false; } - } -} -bool BlenderSession::builtin_image_pixels(const string &builtin_name, - void *builtin_data, - int tile, - unsigned char *pixels, - const size_t pixels_size, - const bool associate_alpha, - const bool free_cache) -{ - if (!builtin_data) { - return false; - } - - const int frame = builtin_image_frame(builtin_name); - - PointerRNA ptr; - RNA_id_pointer_create((ID *)builtin_data, &ptr); - BL::Image b_image(ptr); - - const int width = b_image.size()[0]; - const int height = b_image.size()[1]; - const int channels = b_image.channels(); - - unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile); - const size_t num_pixels = ((size_t)width) * height; - - if (image_pixels && num_pixels * channels == pixels_size) { - memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char)); + /* Float images are already converted on the Blender side, + * no need to do anything in Cycles. */ + metadata.colorspace = u_colorspace_raw; } else { - if (channels == 1) { - memset(pixels, 0, pixels_size * sizeof(unsigned char)); + if (metadata.channels == 1) { + metadata.type = IMAGE_DATA_TYPE_BYTE; + } + else if (metadata.channels == 4) { + metadata.type = IMAGE_DATA_TYPE_BYTE4; } else { - const size_t num_pixels_safe = pixels_size / channels; - unsigned char *cp = pixels; - for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) { - cp[0] = 255; - cp[1] = 0; - cp[2] = 255; - if (channels == 4) { - cp[3] = 255; - } - } + return false; } } - if (image_pixels) { - MEM_freeN(image_pixels); - } - - /* Free image buffers to save memory during render. */ - if (free_cache) { - b_image.buffers_free(); - } - - if (associate_alpha) { - /* Premultiply, byte images are always straight for Blender. */ - unsigned char *cp = pixels; - for (size_t i = 0; i < num_pixels; i++, cp += channels) { - cp[0] = (cp[0] * cp[3]) >> 8; - cp[1] = (cp[1] * cp[3]) >> 8; - cp[2] = (cp[2] * cp[3]) >> 8; - } - } return true; } -bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, - void *builtin_data, - int tile, - float *pixels, - const size_t pixels_size, - const bool, - const bool free_cache) +bool BlenderImageLoader::load_pixels(const ImageMetaData &metadata, + void *pixels, + const size_t pixels_size, + const bool associate_alpha) { - if (!builtin_data) { - return false; - } + const size_t num_pixels = ((size_t)metadata.width) * metadata.height; + const int channels = metadata.channels; + const int tile = 0; /* TODO(lukas): Support tiles here? */ - PointerRNA ptr; - RNA_id_pointer_create((ID *)builtin_data, &ptr); - BL::ID b_id(ptr); - - if (b_id.is_a(&RNA_Image)) { + if (b_image.is_float()) { /* image data */ - BL::Image b_image(b_id); - int frame = builtin_image_frame(builtin_name); - - const int width = b_image.size()[0]; - const int height = b_image.size()[1]; - const int channels = b_image.channels(); - float *image_pixels; image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile); - const size_t num_pixels = ((size_t)width) * height; if (image_pixels && num_pixels * channels == pixels_size) { memcpy(pixels, image_pixels, pixels_size * sizeof(float)); @@ -224,7 +89,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, } else { const size_t num_pixels_safe = pixels_size / channels; - float *fp = pixels; + float *fp = (float *)pixels; for (int i = 0; i < num_pixels_safe; i++, fp += channels) { fp[0] = 1.0f; fp[1] = 0.0f; @@ -239,107 +104,91 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, if (image_pixels) { MEM_freeN(image_pixels); } - - /* Free image buffers to save memory during render. */ - if (free_cache) { - b_image.buffers_free(); - } - - return true; } - else if (b_id.is_a(&RNA_Object)) { - /* smoke volume data */ - BL::Object b_ob(b_id); - BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); - - if (!b_domain) { - return false; - } -#ifdef WITH_FLUID - int3 resolution = get_int3(b_domain.domain_resolution()); - int length, amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; - - /* Velocity and heat data is always low-resolution. */ - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) || - builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { - amplify = 1; - } - - const int width = resolution.x * amplify; - const int height = resolution.y * amplify; - const int depth = resolution.z * amplify; - const size_t num_pixels = ((size_t)width) * height * depth; + else { + unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile); - if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) { - FluidDomainSettings_density_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_density_grid_get(&b_domain.ptr, pixels); - return true; - } - } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) { - /* this is in range 0..1, and interpreted by the OpenGL smoke viewer - * as 1500..3000 K with the first part faded to zero density */ - FluidDomainSettings_flame_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_flame_grid_get(&b_domain.ptr, pixels); - return true; - } + if (image_pixels && num_pixels * channels == pixels_size) { + memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char)); } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) { - /* the RGB is "premultiplied" by density for better interpolation results */ - FluidDomainSettings_color_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels * 4) { - FluidDomainSettings_color_grid_get(&b_domain.ptr, pixels); - return true; + else { + if (channels == 1) { + memset(pixels, 0, pixels_size * sizeof(unsigned char)); } - } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) { - FluidDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels * 3) { - FluidDomainSettings_velocity_grid_get(&b_domain.ptr, pixels); - return true; + else { + const size_t num_pixels_safe = pixels_size / channels; + unsigned char *cp = (unsigned char *)pixels; + for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) { + cp[0] = 255; + cp[1] = 0; + cp[2] = 255; + if (channels == 4) { + cp[3] = 255; + } + } } } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { - FluidDomainSettings_heat_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_heat_grid_get(&b_domain.ptr, pixels); - return true; - } + + if (image_pixels) { + MEM_freeN(image_pixels); } - else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) { - FluidDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length); - if (length == num_pixels) { - FluidDomainSettings_temperature_grid_get(&b_domain.ptr, pixels); - return true; + + if (associate_alpha) { + /* Premultiply, byte images are always straight for Blender. */ + unsigned char *cp = (unsigned char *)pixels; + for (size_t i = 0; i < num_pixels; i++, cp += channels) { + cp[0] = (cp[0] * cp[3]) >> 8; + cp[1] = (cp[1] * cp[3]) >> 8; + cp[2] = (cp[2] * cp[3]) >> 8; } } - else { - fprintf( - stderr, "Cycles error: unknown volume attribute %s, skipping\n", builtin_name.c_str()); - pixels[0] = 0.0f; - return false; - } -#endif - fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); } - else { - /* We originally were passing view_layer here but in reality we need a - * a depsgraph to pass to the RE_point_density_minmax() function. - */ - /* TODO(sergey): Check we're indeed in shader node tree. */ - PointerRNA ptr; - RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr); - BL::Node b_node(ptr); - if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) { - BL::ShaderNodeTexPointDensity b_point_density_node(b_node); - int length; - b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels); - } + + /* Free image buffers to save memory during render. */ + if (free_cache) { + b_image.buffers_free(); } - return false; + return true; +} + +string BlenderImageLoader::name() const +{ + return BL::Image(b_image).name(); +} + +bool BlenderImageLoader::equals(const ImageLoader &other) const +{ + const BlenderImageLoader &other_loader = (const BlenderImageLoader &)other; + return b_image == other_loader.b_image && frame == other_loader.frame; +} + +/* Point Density */ + +BlenderPointDensityLoader::BlenderPointDensityLoader(BL::Depsgraph b_depsgraph, + BL::ShaderNodeTexPointDensity b_node) + : b_depsgraph(b_depsgraph), b_node(b_node) +{ +} + +bool BlenderPointDensityLoader::load_metadata(ImageMetaData &metadata) +{ + metadata.channels = 4; + metadata.width = b_node.resolution(); + metadata.height = metadata.width; + metadata.depth = metadata.width; + metadata.type = IMAGE_DATA_TYPE_FLOAT4; + return true; +} + +bool BlenderPointDensityLoader::load_pixels(const ImageMetaData &, + void *pixels, + const size_t, + const bool) +{ + int length; + b_node.calc_point_density(b_depsgraph, &length, (float **)&pixels); + return true; } void BlenderSession::builtin_images_load() @@ -357,4 +206,15 @@ void BlenderSession::builtin_images_load() manager->device_load_builtin(device, session->scene, session->progress); } +string BlenderPointDensityLoader::name() const +{ + return BL::ShaderNodeTexPointDensity(b_node).name(); +} + +bool BlenderPointDensityLoader::equals(const ImageLoader &other) const +{ + const BlenderPointDensityLoader &other_loader = (const BlenderPointDensityLoader &)other; + return b_node == other_loader.b_node && b_depsgraph == other_loader.b_depsgraph; +} + CCL_NAMESPACE_END |