diff options
author | Stefan Werner <stefan.werner@tangent-animation.com> | 2018-07-05 13:37:52 +0300 |
---|---|---|
committer | Stefan Werner <stefan.werner@tangent-animation.com> | 2018-07-05 14:53:34 +0300 |
commit | 4d00e95ee3ed91f86262bb218f1c5df901da724c (patch) | |
tree | 5d9af704609b38cca76a5786189c126ac7072332 /intern/cycles/render | |
parent | cd17b3258327522b8c6f56a3ee7239a91f2be149 (diff) |
Cycles: Adding native support for UINT16 textures.
Textures in 16 bit integer format are sometimes used for displacement, bump and normal maps and can be exported by tools like Substance Painter. Without this patch, Cycles would promote those textures to single precision floating point, causing them to take up twice as much memory as needed.
Reviewers: #cycles, brecht, sergey
Reviewed By: #cycles, brecht, sergey
Subscribers: sergey, dingto, #cycles
Tags: #cycles
Differential Revision: https://developer.blender.org/D3523
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/image.cpp | 82 |
1 files changed, 72 insertions, 10 deletions
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 9c6536edc4f..3c49d17aa82 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -39,6 +39,10 @@ static bool isfinite(half /*value*/) { return false; } +static bool isfinite(uint16_t /*value*/) +{ + return false; +} ImageManager::ImageManager(const DeviceInfo& info) { @@ -164,23 +168,27 @@ bool ImageManager::get_image_metadata(const string& filename, metadata.height = spec.height; metadata.depth = spec.depth; - /* check the main format, and channel formats; - * if any take up more than one byte, we'll need a float texture slot */ - if(spec.format.basesize() > 1) { + + /* Check the main format, and channel formats. */ + size_t channel_size = spec.format.basesize(); + + if(spec.format.is_floating_point()) { metadata.is_float = true; metadata.is_linear = true; } for(size_t channel = 0; channel < spec.channelformats.size(); channel++) { - if(spec.channelformats[channel].basesize() > 1) { + channel_size = max(channel_size, spec.channelformats[channel].basesize()); + if(spec.channelformats[channel].is_floating_point()) { metadata.is_float = true; metadata.is_linear = true; } } /* check if it's half float */ - if(spec.format == TypeDesc::HALF) + if(spec.format == TypeDesc::HALF) { metadata.is_half = true; + } /* basic color space detection, not great but better than nothing * before we do OpenColorIO integration */ @@ -208,6 +216,9 @@ bool ImageManager::get_image_metadata(const string& filename, else if(metadata.is_float) { metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT; } + else if(spec.format == TypeDesc::USHORT) { + metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT; + } else { metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE; } @@ -254,6 +265,10 @@ string ImageManager::name_from_type(int type) return "half4"; else if(type == IMAGE_DATA_TYPE_HALF) return "half"; + else if(type == IMAGE_DATA_TYPE_USHORT) + return "ushort"; + else if(type == IMAGE_DATA_TYPE_USHORT4) + return "ushort4"; else return "byte4"; } @@ -583,7 +598,8 @@ bool ImageManager::file_load_image(Image *img, */ bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 || type == IMAGE_DATA_TYPE_HALF4 || - type == IMAGE_DATA_TYPE_BYTE4); + type == IMAGE_DATA_TYPE_BYTE4 || + type == IMAGE_DATA_TYPE_USHORT4); if(is_rgba) { if(cmyk) { /* CMYK */ @@ -843,14 +859,61 @@ void ImageManager::device_load_image(Device *device, thread_scoped_lock device_lock(device_mutex); tex_img->copy_to_device(); } + else if(type == IMAGE_DATA_TYPE_USHORT) { + device_vector<uint16_t> *tex_img + = new device_vector<uint16_t>(device, img->mem_name.c_str(), MEM_TEXTURE); + + if(!file_load_image<TypeDesc::USHORT, uint16_t>(img, + type, + texture_limit, + *tex_img)) { + /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); + uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1); + + pixels[0] = TEX_IMAGE_MISSING_R; + } + + img->mem = tex_img; + img->mem->interpolation = img->interpolation; + img->mem->extension = img->extension; + + thread_scoped_lock device_lock(device_mutex); + tex_img->copy_to_device(); + } + else if(type == IMAGE_DATA_TYPE_USHORT4) { + device_vector<ushort4> *tex_img + = new device_vector<ushort4>(device, img->mem_name.c_str(), MEM_TEXTURE); + + if(!file_load_image<TypeDesc::USHORT, uint16_t>(img, + type, + texture_limit, + *tex_img)) { + /* on failure to load, we set a 1x1 pixels pink image */ + thread_scoped_lock device_lock(device_mutex); + uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1); + + pixels[0] = TEX_IMAGE_MISSING_R; + pixels[1] = TEX_IMAGE_MISSING_G; + pixels[2] = TEX_IMAGE_MISSING_B; + pixels[3] = TEX_IMAGE_MISSING_A; + } + + img->mem = tex_img; + img->mem->interpolation = img->interpolation; + img->mem->extension = img->extension; + + thread_scoped_lock device_lock(device_mutex); + tex_img->copy_to_device(); + } else if(type == IMAGE_DATA_TYPE_HALF) { device_vector<half> *tex_img = new device_vector<half>(device, img->mem_name.c_str(), MEM_TEXTURE); if(!file_load_image<TypeDesc::HALF, half>(img, - type, - texture_limit, - *tex_img)) { + type, + texture_limit, + *tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ thread_scoped_lock device_lock(device_mutex); half *pixels = (half*)tex_img->alloc(1, 1); @@ -865,7 +928,6 @@ void ImageManager::device_load_image(Device *device, thread_scoped_lock device_lock(device_mutex); tex_img->copy_to_device(); } - img->need_load = false; } |