Cycles: float texture support. Due to GPU limitations there are now 95 byte,
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 7 Mar 2012 12:27:18 +0000 (12:27 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 7 Mar 2012 12:27:18 +0000 (12:27 +0000)
and 5 float image textures. For CPU render this limit will be lifted later
on with image cache support. Patch by Mike Farnsworth.

Also changed color space option in image/environment texture node, to show
options Color and Non-Color Data, instead of sRGB and Linear, this is more
descriptive, and it was not really correct to equate Non-Color Data with
Linear.

12 files changed:
intern/cycles/kernel/kernel.cpp
intern/cycles/kernel/kernel_textures.h
intern/cycles/kernel/svm/svm_image.h
intern/cycles/render/image.cpp
intern/cycles/render/image.h
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
intern/cycles/render/scene.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/shader/nodes/node_shader_tex_environment.c
source/blender/nodes/shader/nodes/node_shader_tex_image.c

index a93f6172d28522b4d3b64340a33356d78b0ddfa4..667db1e5f03a953aa764766fef4b8af44c5ee560 100644 (file)
@@ -84,6 +84,25 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
 #define KERNEL_IMAGE_TEX(type, ttype, tname)
 #include "kernel_textures.h"
 
+       else if(strstr(name, "__tex_image_float")) {
+               texture_image_float4 *tex = NULL;
+               int id = atoi(name + strlen("__tex_image_float_"));
+
+               switch(id) {
+                       case 95: tex = &kg->__tex_image_float_095; break;
+                       case 96: tex = &kg->__tex_image_float_096; break;
+                       case 97: tex = &kg->__tex_image_float_097; break;
+                       case 98: tex = &kg->__tex_image_float_098; break;
+                       case 99: tex = &kg->__tex_image_float_099; break;
+                       default: break;
+               }
+
+               if(tex) {
+                       tex->data = (float4*)mem;
+                       tex->width = width;
+                       tex->height = height;
+               }
+       }
        else if(strstr(name, "__tex_image")) {
                texture_image_uchar4 *tex = NULL;
                int id = atoi(name + strlen("__tex_image_"));
@@ -184,11 +203,6 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
                        case 92: tex = &kg->__tex_image_092; break;
                        case 93: tex = &kg->__tex_image_093; break;
                        case 94: tex = &kg->__tex_image_094; break;
-                       case 95: tex = &kg->__tex_image_095; break;
-                       case 96: tex = &kg->__tex_image_096; break;
-                       case 97: tex = &kg->__tex_image_097; break;
-                       case 98: tex = &kg->__tex_image_098; break;
-                       case 99: tex = &kg->__tex_image_099; break;
                        default: break;
                }
 
index ca7ae432efa314a596efe4440e428b7f5bf07dc2..8bab735d0d15a0afeb99be0ae011490a38a4274e 100644 (file)
@@ -142,11 +142,13 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_091)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_092)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_093)
 KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_094)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_095)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_096)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_097)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_098)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_099)
+
+/* full-float image */
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_095)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_096)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_097)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_098)
+KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_099)
 
 #undef KERNEL_TEX
 #undef KERNEL_IMAGE_TEX
index 073021bdd54f318b84aaf90ed6b6b1dacdcf7283..3d737b483cbddbac1f7bdd5d42d3e444715cb5b5 100644 (file)
@@ -130,11 +130,11 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
                case 92: r = kernel_tex_image_interp(__tex_image_092, x, y); break;
                case 93: r = kernel_tex_image_interp(__tex_image_093, x, y); break;
                case 94: r = kernel_tex_image_interp(__tex_image_094, x, y); break;
-               case 95: r = kernel_tex_image_interp(__tex_image_095, x, y); break;
-               case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break;
-               case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break;
-               case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
-               case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break;
+               case 95: r = kernel_tex_image_interp(__tex_image_float_095, x, y); break;
+               case 96: r = kernel_tex_image_interp(__tex_image_float_096, x, y); break;
+               case 97: r = kernel_tex_image_interp(__tex_image_float_097, x, y); break;
+               case 98: r = kernel_tex_image_interp(__tex_image_float_098, x, y); break;
+               case 99: r = kernel_tex_image_interp(__tex_image_float_099, x, y); break;
                default: 
                        kernel_assert(0);
                        return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
index de3ab8edf48c10970b238b1e6ab47de5074d6657..78b8f06c7b468cb419eb1ace34053fbea5276a02 100644 (file)
@@ -39,9 +39,10 @@ ImageManager::ImageManager()
 
 ImageManager::~ImageManager()
 {
-       for(size_t slot = 0; slot < images.size(); slot++) {
+       for(size_t slot = 0; slot < images.size(); slot++)
                assert(!images[slot]);
-       }
+       for(size_t slot = 0; slot < float_images.size(); slot++)
+               assert(!float_images[slot]);
 }
 
 void ImageManager::set_osl_texture_system(void *texture_system)
@@ -49,39 +50,111 @@ void ImageManager::set_osl_texture_system(void *texture_system)
        osl_texture_system = texture_system;
 }
 
-int ImageManager::add_image(const string& filename)
+static bool is_float_image(const string& filename)
+{
+       ImageInput *in = ImageInput::create(filename);
+       bool is_float = false;
+
+       if(in) {
+               ImageSpec spec;
+
+               if(in->open(filename, spec)) {
+                       /* check the main format, and channel formats;
+                          if any are non-integer, we'll need a float texture slot */
+                       if(spec.format == TypeDesc::HALF ||
+                          spec.format == TypeDesc::FLOAT ||
+                          spec.format == TypeDesc::DOUBLE) {
+                               is_float = true;
+                       }
+
+                       for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
+                               if(spec.channelformats[channel] == TypeDesc::HALF ||
+                                  spec.channelformats[channel] == TypeDesc::FLOAT ||
+                                  spec.channelformats[channel] == TypeDesc::DOUBLE) {
+                                       is_float = true;
+                               }
+                       }
+
+                       in->close();
+               }
+
+               delete in;
+       }
+
+       return is_float;
+}
+
+int ImageManager::add_image(const string& filename, bool& is_float)
 {
        Image *img;
        size_t slot;
 
-       /* find existing image */
-       for(slot = 0; slot < images.size(); slot++) {
-               if(images[slot] && images[slot]->filename == filename) {
-                       images[slot]->users++;
-                       return slot;
+       /* load image info and find out if we need a float texture */
+       is_float = is_float_image(filename);
+
+       if(is_float) {
+               /* find existing image */
+               for(slot = 0; slot < float_images.size(); slot++) {
+                       if(float_images[slot] && float_images[slot]->filename == filename) {
+                               float_images[slot]->users++;
+                               return slot+TEX_IMAGE_FLOAT_START;
+                       }
                }
+
+               /* find free slot */
+               for(slot = 0; slot < float_images.size(); slot++) {
+                       if(!float_images[slot])
+                               break;
+               }
+
+               if(slot == float_images.size()) {
+                       /* max images limit reached */
+                       if(float_images.size() == TEX_NUM_FLOAT_IMAGES)
+                               return -1;
+
+                       float_images.resize(float_images.size() + 1);
+               }
+
+               /* add new image */
+               img = new Image();
+               img->filename = filename;
+               img->need_load = true;
+               img->users = 1;
+
+               float_images[slot] = img;
+               /* report slot out of total set of textures */
+               slot += TEX_IMAGE_FLOAT_START;
        }
+       else {
+               for(slot = 0; slot < images.size(); slot++) {
+                       if(images[slot] && images[slot]->filename == filename) {
+                               images[slot]->users++;
+                               return slot;
+                       }
+               }
 
-       /* find free slot */
-       for(slot = 0; slot < images.size(); slot++)
-               if(!images[slot])
-                       break;
-       
-       if(slot == images.size()) {
-               /* max images limit reached */
-               if(images.size() == TEX_IMAGE_MAX)
-                       return -1;
+               /* find free slot */
+               for(slot = 0; slot < images.size(); slot++) {
+                       if(!images[slot])
+                               break;
+               }
+
+               if(slot == images.size()) {
+                       /* max images limit reached */
+                       if(images.size() == TEX_NUM_IMAGES)
+                               return -1;
+
+                       images.resize(images.size() + 1);
+               }
 
-               images.resize(images.size() + 1);
+               /* add new image */
+               img = new Image();
+               img->filename = filename;
+               img->need_load = true;
+               img->users = 1;
+
+               images[slot] = img;
        }
-       
-       /* add new image */
-       img = new Image();
-       img->filename = filename;
-       img->need_load = true;
-       img->users = 1;
-
-       images[slot] = img;
        need_update = true;
 
        return slot;
@@ -91,24 +164,40 @@ void ImageManager::remove_image(const string& filename)
 {
        size_t slot;
 
-       for(slot = 0; slot < images.size(); slot++)
-               if(images[slot] && images[slot]->filename == filename)
+       for(slot = 0; slot < images.size(); slot++) {
+               if(images[slot] && images[slot]->filename == filename) {
+                       /* decrement user count */
+                       images[slot]->users--;
+                       assert(images[slot]->users >= 0);
+
+                       /* don't remove immediately, rather do it all together later on. one of
+                          the reasons for this is that on shader changes we add and remove nodes
+                          that use them, but we do not want to reload the image all the time. */
+                       if(images[slot]->users == 0)
+                               need_update = true;
+
                        break;
-       
-       if(slot == images.size())
-               return;
+               }
+       }
 
-       assert(images[slot]);
-
-       /* decrement user count */
-       images[slot]->users--;
-       assert(images[slot]->users >= 0);
-       
-       /* don't remove immediately, rather do it all together later on. one of
-          the reasons for this is that on shader changes we add and remove nodes
-          that use them, but we do not want to reload the image all the time. */
-       if(images[slot]->users == 0)
-               need_update = true;
+       if(slot == images.size()) {
+               /* see if it's in a float texture slot */
+               for(slot = 0; slot < float_images.size(); slot++) {
+                       if(float_images[slot] && float_images[slot]->filename == filename) {
+                               /* decrement user count */
+                               float_images[slot]->users--;
+                               assert(float_images[slot]->users >= 0);
+
+                               /* don't remove immediately, rather do it all together later on. one of
+                                  the reasons for this is that on shader changes we add and remove nodes
+                                  that use them, but we do not want to reload the image all the time. */
+                               if(float_images[slot]->users == 0)
+                                       need_update = true;
+
+                               break;
+                       }
+               }
+       }
 }
 
 bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
@@ -173,51 +262,168 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
        return true;
 }
 
+bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_img)
+{
+       if(img->filename == "")
+               return false;
+
+       /* load image from file through OIIO */
+       ImageInput *in = ImageInput::create(img->filename);
+
+       if(!in)
+               return false;
+
+       ImageSpec spec;
+
+       if(!in->open(img->filename, spec)) {
+               delete in;
+               return false;
+       }
+
+       /* we only handle certain number of components */
+       int width = spec.width;
+       int height = spec.height;
+       int components = spec.nchannels;
+
+       if(!(components == 1 || components == 3 || components == 4)) {
+               in->close();
+               delete in;
+               return false;
+       }
+
+       /* read RGBA pixels */
+       float *pixels = (float*)tex_img.resize(width, height);
+       int scanlinesize = width*components*sizeof(float);
+
+       in->read_image(TypeDesc::FLOAT,
+               (uchar*)pixels + (height-1)*scanlinesize,
+               AutoStride,
+               -scanlinesize,
+               AutoStride);
+
+       in->close();
+       delete in;
+
+       if(components == 3) {
+               for(int i = width*height-1; i >= 0; i--) {
+                       pixels[i*4+3] = 1.0f;
+                       pixels[i*4+2] = pixels[i*3+2];
+                       pixels[i*4+1] = pixels[i*3+1];
+                       pixels[i*4+0] = pixels[i*3+0];
+               }
+       }
+       else if(components == 1) {
+               for(int i = width*height-1; i >= 0; i--) {
+                       pixels[i*4+3] = 1.0f;
+                       pixels[i*4+2] = pixels[i];
+                       pixels[i*4+1] = pixels[i];
+                       pixels[i*4+0] = pixels[i];
+               }
+       }
+
+       return true;
+}
+
 void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int slot)
 {
        if(osl_texture_system)
                return;
 
-       Image *img = images[slot];
-       device_vector<uchar4>& tex_img = dscene->tex_image[slot];
+       Image *img;
+       bool is_float;
 
-       if(tex_img.device_pointer)
-               device->tex_free(tex_img);
+       if(slot < TEX_IMAGE_FLOAT_START) {
+               img = images[slot];
+               is_float = false;
+       }
+       else {
+               img = float_images[slot - TEX_IMAGE_FLOAT_START];
+               is_float = true;
+       }
 
-       if(!file_load_image(img, tex_img)) {
-               /* on failure to load, we set a 1x1 pixels black image */
-               uchar *pixels = (uchar*)tex_img.resize(1, 1);
+       if(is_float) {
+               device_vector<float4>& tex_img = dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START];
+
+               if(tex_img.device_pointer)
+                       device->tex_free(tex_img);
+
+               if(!file_load_float_image(img, tex_img)) {
+                       /* on failure to load, we set a 1x1 pixels black image */
+                       float *pixels = (float*)tex_img.resize(1, 1);
+
+                       pixels[0] = 0.0f;
+                       pixels[1] = 0.0f;
+                       pixels[2] = 0.0f;
+                       pixels[3] = 0.0f;
+               }
 
-               pixels[0] = 0;
-               pixels[1] = 0;
-               pixels[2] = 0;
-               pixels[3] = 0;
+               string name;
+
+               if(slot >= 10) name = string_printf("__tex_image_float_0%d", slot);
+               else name = string_printf("__tex_image_float_00%d", slot);
+
+               device->tex_alloc(name.c_str(), tex_img, true, true);
        }
+       else {
+               device_vector<uchar4>& tex_img = dscene->tex_image[slot];
+
+               if(tex_img.device_pointer)
+                       device->tex_free(tex_img);
+
+               if(!file_load_image(img, tex_img)) {
+                       /* on failure to load, we set a 1x1 pixels black image */
+                       uchar *pixels = (uchar*)tex_img.resize(1, 1);
 
-       string name;
+                       pixels[0] = 0;
+                       pixels[1] = 0;
+                       pixels[2] = 0;
+                       pixels[3] = 0;
+               }
+
+               string name;
 
-       if(slot >= 10) name = string_printf("__tex_image_0%d", slot);
-       else name = string_printf("__tex_image_00%d", slot);
+               if(slot >= 10) name = string_printf("__tex_image_0%d", slot);
+               else name = string_printf("__tex_image_00%d", slot);
 
-       device->tex_alloc(name.c_str(), tex_img, true, true);
+               device->tex_alloc(name.c_str(), tex_img, true, true);
+       }
 }
 
 void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int slot)
 {
-       if(images[slot]) {
+       Image *img;
+       bool is_float;
+
+       if(slot < TEX_IMAGE_FLOAT_START) {
+               img = images[slot];
+               is_float = false;
+       }
+       else {
+               img = float_images[slot - TEX_IMAGE_FLOAT_START];
+               is_float = true;
+       }
+
+       if(img) {
                if(osl_texture_system) {
 #ifdef WITH_OSL
                        ustring filename(images[slot]->filename);
                        ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
 #endif
                }
+               else if(is_float) {
+                       device->tex_free(dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START]);
+                       dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START].clear();
+
+                       delete float_images[slot - TEX_IMAGE_FLOAT_START];
+                       float_images[slot - TEX_IMAGE_FLOAT_START] = NULL;
+               }
                else {
                        device->tex_free(dscene->tex_image[slot]);
                        dscene->tex_image[slot].clear();
-               }
 
-               delete images[slot];
-               images[slot] = NULL;
+                       delete images[slot];
+                       images[slot] = NULL;
+               }
        }
 }
 
@@ -242,6 +448,22 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
                }
        }
 
+       for(size_t slot = 0; slot < float_images.size(); slot++) {
+               if(float_images[slot]) {
+                       if(float_images[slot]->users == 0) {
+                               device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
+                       }
+                       else if(float_images[slot]->need_load) {
+                               string name = path_filename(float_images[slot]->filename);
+                               progress.set_status("Updating Images", "Loading " + name);
+                               device_load_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
+                               float_images[slot]->need_load = false;
+                       }
+
+                       if(progress.get_cancel()) return;
+               }
+       }
+
        need_update = false;
 }
 
@@ -249,8 +471,11 @@ void ImageManager::device_free(Device *device, DeviceScene *dscene)
 {
        for(size_t slot = 0; slot < images.size(); slot++)
                device_free_image(device, dscene, slot);
+       for(size_t slot = 0; slot < float_images.size(); slot++)
+               device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START);
 
        images.clear();
+       float_images.clear();
 }
 
 CCL_NAMESPACE_END
index 0d49a1e6b6704c35634d2749f4dfccda045f0ba7..d789e6885e3a6f420c955c53b0fb43af3ea681b5 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
-#define TEX_IMAGE_MAX 100
+#define TEX_NUM_FLOAT_IMAGES   5
+#define TEX_NUM_IMAGES                 95
+#define TEX_IMAGE_MAX                  (TEX_NUM_IMAGES + TEX_NUM_FLOAT_IMAGES)
+#define TEX_IMAGE_FLOAT_START  TEX_NUM_IMAGES
 
 class Device;
 class DeviceScene;
@@ -37,7 +40,7 @@ public:
        ImageManager();
        ~ImageManager();
 
-       int add_image(const string& filename);
+       int add_image(const string& filename, bool& is_float);
        void remove_image(const string& filename);
 
        void device_update(Device *device, DeviceScene *dscene, Progress& progress);
@@ -56,9 +59,11 @@ private:
        };
 
        vector<Image*> images;
+       vector<Image*> float_images;
        void *osl_texture_system;
 
        bool file_load_image(Image *img, device_vector<uchar4>& tex_img);
+       bool file_load_float_image(Image *img, device_vector<float4>& tex_img);
 
        void device_load_image(Device *device, DeviceScene *dscene, int slot);
        void device_free_image(Device *device, DeviceScene *dscene, int slot);
index 982521b31f2dcd062110e54a8afa7b20e6b8fdf7..86f0f3127e9cce6d29184718be16fec63da21e7f 100644 (file)
@@ -93,8 +93,8 @@ static ShaderEnum color_space_init()
 {
        ShaderEnum enm;
 
-       enm.insert("Linear", 0);
-       enm.insert("sRGB", 1);
+       enm.insert("None", 0);
+       enm.insert("Color", 1);
 
        return enm;
 }
@@ -106,8 +106,9 @@ ImageTextureNode::ImageTextureNode()
 {
        image_manager = NULL;
        slot = -1;
+       is_float = false;
        filename = "";
-       color_space = ustring("sRGB");
+       color_space = ustring("Color");
 
        add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV);
        add_output("Color", SHADER_SOCKET_COLOR);
@@ -125,6 +126,7 @@ ShaderNode *ImageTextureNode::clone() const
        ImageTextureNode *node = new ImageTextureNode(*this);
        node->image_manager = NULL;
        node->slot = -1;
+       node->is_float = false;
        return node;
 }
 
@@ -136,7 +138,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
 
        image_manager = compiler.image_manager;
        if(slot == -1)
-               slot = image_manager->add_image(filename);
+               slot = image_manager->add_image(filename, is_float);
 
        if(!color_out->links.empty())
                compiler.stack_assign(color_out);
@@ -144,6 +146,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
                compiler.stack_assign(alpha_out);
 
        if(slot != -1) {
+               int srgb = (is_float || color_space != "Color")? 0: 1;
                compiler.stack_assign(vector_in);
 
                if(!tex_mapping.skip())
@@ -155,7 +158,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
                                vector_in->stack_offset,
                                color_out->stack_offset,
                                alpha_out->stack_offset,
-                               color_space_enum[color_space]));
+                               srgb));
        }
        else {
                /* image not found */
@@ -171,7 +174,10 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
 void ImageTextureNode::compile(OSLCompiler& compiler)
 {
        compiler.parameter("filename", filename.c_str());
-       compiler.parameter("color_space", color_space.c_str());
+       if(is_float || color_space != "Color")
+               compiler.parameter("color_space", "Linear");
+       else
+               compiler.parameter("color_space", "sRGB");
        compiler.add(this, "node_image_texture");
 }
 
@@ -184,8 +190,9 @@ EnvironmentTextureNode::EnvironmentTextureNode()
 {
        image_manager = NULL;
        slot = -1;
+       is_float = false;
        filename = "";
-       color_space = ustring("sRGB");
+       color_space = ustring("Color");
 
        add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION);
        add_output("Color", SHADER_SOCKET_COLOR);
@@ -203,6 +210,7 @@ ShaderNode *EnvironmentTextureNode::clone() const
        EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
        node->image_manager = NULL;
        node->slot = -1;
+       node->is_float = false;
        return node;
 }
 
@@ -214,7 +222,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
 
        image_manager = compiler.image_manager;
        if(slot == -1)
-               slot = image_manager->add_image(filename);
+               slot = image_manager->add_image(filename, is_float);
 
        if(!color_out->links.empty())
                compiler.stack_assign(color_out);
@@ -222,6 +230,8 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
                compiler.stack_assign(alpha_out);
 
        if(slot != -1) {
+               int srgb = (is_float || color_space != "Color")? 0: 1;
+
                compiler.stack_assign(vector_in);
 
                if(!tex_mapping.skip())
@@ -233,7 +243,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
                                vector_in->stack_offset,
                                color_out->stack_offset,
                                alpha_out->stack_offset,
-                               color_space_enum[color_space]));
+                               srgb));
        }
        else {
                /* image not found */
@@ -249,7 +259,10 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
 void EnvironmentTextureNode::compile(OSLCompiler& compiler)
 {
        compiler.parameter("filename", filename.c_str());
-       compiler.parameter("color_space", color_space.c_str());
+       if(is_float || color_space != "Color")
+               compiler.parameter("color_space", "Linear");
+       else
+               compiler.parameter("color_space", "sRGB");
        compiler.add(this, "node_environment_texture");
 }
 
index 338af4ef48ac9c1158d7cae83a5f4986e99fb887..6c9ed422b88de34c7f2cb6535e363cf153a77326 100644 (file)
@@ -64,6 +64,7 @@ public:
 
        ImageManager *image_manager;
        int slot;
+       bool is_float;
        string filename;
        ustring color_space;
 
@@ -78,6 +79,7 @@ public:
 
        ImageManager *image_manager;
        int slot;
+       bool is_float;
        string filename;
        ustring color_space;
 
index c251174b60784008336d66c931bb64d89d2dbadf..0a4f0ef5d95931f7db7a2a6a9b95bac05a22ca5c 100644 (file)
@@ -92,7 +92,8 @@ public:
        device_vector<uint> sobol_directions;
 
        /* images */
-       device_vector<uchar4> tex_image[TEX_IMAGE_MAX];
+       device_vector<uchar4> tex_image[TEX_NUM_IMAGES];
+       device_vector<float4> tex_float_image[TEX_NUM_FLOAT_IMAGES];
 
        KernelData data;
 };
index f0d0a556d92bebb84c1fe247606a31d7d438660a..0d309aad36c7fc2d4526a34557736990175eb791 100644 (file)
@@ -582,8 +582,8 @@ typedef struct TexNodeOutput {
 #define SHD_WAVE_TRI   2
 
 /* image/environment texture */
-#define SHD_COLORSPACE_LINEAR  0
-#define SHD_COLORSPACE_SRGB            1
+#define SHD_COLORSPACE_NONE            0
+#define SHD_COLORSPACE_COLOR   1
 
 /* blur node */
 #define CMP_NODE_BLUR_ASPECT_NONE              0
index 07d52f1a8bad360e45a0494c2d17aecbc803a48c..2caf1f06585fe3f7d4c7301d9298b08bbb7622f2 100644 (file)
@@ -1264,8 +1264,8 @@ static void def_sh_tex_sky(StructRNA *srna)
 static void def_sh_tex_environment(StructRNA *srna)
 {
        static const EnumPropertyItem prop_color_space_items[] = {
-               {SHD_COLORSPACE_SRGB, "SRGB", 0, "sRGB", "Image is in sRGB color space"},
-               {SHD_COLORSPACE_LINEAR, "LINEAR", 0, "Linear", "Image is in scene linear color space"},
+               {SHD_COLORSPACE_COLOR, "COLOR", 0, "Color", "Image contains color data, and will be converted to linear color for rendering"},
+               {SHD_COLORSPACE_NONE, "NONE", 0, "Non-Color Data", "Image contains non-color data, for example a displacement or normal map, and will not be converted"},
                {0, NULL, 0, NULL, NULL}};
 
        PropertyRNA *prop;
@@ -1289,8 +1289,8 @@ static void def_sh_tex_environment(StructRNA *srna)
 static void def_sh_tex_image(StructRNA *srna)
 {
        static const EnumPropertyItem prop_color_space_items[] = {
-               {SHD_COLORSPACE_LINEAR, "LINEAR", 0, "Linear", "Image is in scene linear color space"},
-               {SHD_COLORSPACE_SRGB, "SRGB", 0, "sRGB", "Image is in sRGB color space"},
+               {SHD_COLORSPACE_COLOR, "COLOR", 0, "Color", "Image contains color data, and will be converted to linear color for rendering"},
+               {SHD_COLORSPACE_NONE, "NONE", 0, "Non-Color Data", "Image contains non-color data, for example a displacement or normal map, and will not be converted"},
                {0, NULL, 0, NULL, NULL}};
 
        PropertyRNA *prop;
index dbdd6a8619b36879b2073fb4fc9e36e9b41d3ce8..d6957e53f102bfd240d95e56f2ae460106c57992 100644 (file)
@@ -44,7 +44,7 @@ static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode* no
        NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
        default_tex_mapping(&tex->base.tex_mapping);
        default_color_mapping(&tex->base.color_mapping);
-       tex->color_space = SHD_COLORSPACE_SRGB;
+       tex->color_space = SHD_COLORSPACE_COLOR;
 
        node->storage = tex;
 }
index aa679b4e04ea6dd260622ed137298ba6ace51c9d..aa7ff2791787c20c5efbd2764dc6bfd104874751 100644 (file)
@@ -44,7 +44,7 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode* node, bN
        NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
        default_tex_mapping(&tex->base.tex_mapping);
        default_color_mapping(&tex->base.color_mapping);
-       tex->color_space = SHD_COLORSPACE_SRGB;
+       tex->color_space = SHD_COLORSPACE_COLOR;
 
        node->storage = tex;
 }