Changes to Color Management
authorMatt Ebb <matt@mke3.net>
Wed, 2 Dec 2009 07:56:34 +0000 (07:56 +0000)
committerMatt Ebb <matt@mke3.net>
Wed, 2 Dec 2009 07:56:34 +0000 (07:56 +0000)
After testing and feedback, I've decided to slightly modify the way color
management works internally. While the previous method worked well for
rendering, was a smaller transition and had some advantages over this
new method, it was a bit more ambiguous, and was making things difficult
for other areas such as compositing.

This implementation now considers all color data (with only a couple of
exceptions such as brush colors) to be stored in linear RGB color space,
rather than sRGB as previously. This brings it in line with Nuke, which also
operates this way, quite successfully. Color swatches, pickers, color ramp
display are now gamma corrected to display gamma so you can see what
you're doing, but the numbers themselves are considered linear. This
makes understanding blending modes more clear (a 0.5 value on overlay
will not change the result now) as well as making color swatches act more
predictably in the compositor, however bringing over color values from
applications like photoshop or gimp, that operate in a gamma space,
will give identical results.

This commit will convert over existing files saved by earlier 2.5 versions to
work generally the same, though there may be some slight differences with
things like textures. Now that we're set on changing other areas of shading,
this won't be too disruptive overall.

I've made a diagram explaining the pipeline here:
http://mke3.net/blender/devel/2.5/25_linear_workflow_pipeline.png

and some docs here:
http://www.blender.org/development/release-logs/blender-250/color-management/

30 files changed:
release/scripts/ui/properties_material.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_colortools.h
source/blender/blenkernel/intern/colortools.c
source/blender/blenkernel/intern/object.c
source/blender/blenlib/BLI_math_color.h
source/blender/blenlib/intern/math_color.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_draw.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_regions.c
source/blender/editors/interface/interface_utils.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/gpu/intern/gpu_draw.c
source/blender/makesrna/RNA_types.h
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_brush.c
source/blender/makesrna/intern/rna_color.c
source/blender/makesrna/intern/rna_material.c
source/blender/makesrna/intern/rna_rna.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/pixelshading.c
source/blender/render/intern/source/shadeinput.c
source/blender/render/intern/source/sss.c
source/blender/render/intern/source/texture.c

index eb2a73d1790f27bc2fd88013e5d79c1559b7311e..50fc0a7ded99a5b895e78e8846bf5b8f14c37e52 100644 (file)
@@ -495,7 +495,7 @@ class MATERIAL_PT_sss(MaterialButtonsPanel):
         col.prop(sss, "ior")
         col.prop(sss, "scale")
         col.prop(sss, "color", text="")
-        col.prop(sss, "radius", text="RGB Radius")
+        col.prop(sss, "radius", text="RGB Radius", expand=True)
 
         if wide_ui:
             col = split.column()
index ebeec31c98458b919816b1e5b1ade96e82b6dff8..7bbcb63a7f51173eed993e32c5192d15e46d9aa9 100644 (file)
@@ -43,7 +43,7 @@ struct bContext;
 struct ReportList;
 
 #define BLENDER_VERSION                        250
-#define BLENDER_SUBVERSION             7
+#define BLENDER_SUBVERSION             8
 
 #define BLENDER_MINVERSION             250
 #define BLENDER_MINSUBVERSION  0
index c83a260690be92be70dd8c8402a4758e8dcd35be..c571688737a036d01228b37a9f5912b705d56958 100644 (file)
@@ -34,12 +34,6 @@ struct CurveMap;
 struct ImBuf;
 struct rctf;
 
-void                           gamma_correct_rec709(float *c, float gamma);
-void                           gamma_correct(float *c, float gamma);
-float                          srgb_to_linearrgb(float c);
-float                          linearrgb_to_srgb(float c);
-void                           color_manage_linearize(float *col_to, float *col_from);
-
 void                           floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
 void                           floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w);
 
index f3448a60b5af1b4e4b66780f3b3d2897564b14e8..48e42bc539f0e474f97447cda915e5657a559c86 100644 (file)
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
-/* ********************************* color transforms ********************************* */
-
-/*Transform linear RGB values to nonlinear RGB values. Rec.
-  709 is ITU-R Recommendation BT. 709 (1990) ``Basic
-  Parameter Values for the HDTV Standard for the Studio and
-  for International Programme Exchange'', formerly CCIR Rec.
-  709.*/
-void gamma_correct_rec709(float *c, float gamma)
-{
-       /* Rec. 709 gamma correction. */
-       const float cc = 0.018f;
-       
-       if (*c < cc)
-           *c *= ((1.099f * (float)powf(cc, gamma)) - 0.099f) * (1.0f/cc);
-       else 
-           *c = (1.099f * (float)powf(*c, gamma)) - 0.099f;
-}
-
-void gamma_correct(float *c, float gamma)
-{
-       *c = powf((*c), gamma);
-}
-
-float srgb_to_linearrgb(float c)
-{
-       if (c < 0.04045f)
-               return (c < 0.0f)? 0.0f: c*(1.0f/12.92f);
-       else
-               return powf((c + 0.055f)*(1.0f/1.055f), 2.4f);
-}
-
-float linearrgb_to_srgb(float c)
-{
-       if (c < 0.0031308f)
-               return (c < 0.0f)? 0.0f: c * 12.92f;
-       else
-               return  1.055f * powf(c, 1.0f/2.4f) - 0.055f;
-}
-
-/* utility function convert an RGB triplet from sRGB to linear RGB color space */
-void color_manage_linearize(float *col_to, float *col_from)
-{
-       col_to[0] = srgb_to_linearrgb(col_from[0]);
-       col_to[1] = srgb_to_linearrgb(col_from[1]);
-       col_to[2] = srgb_to_linearrgb(col_from[2]);
-}
 
 void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w)
 {
index 1e04738064132dd16e13b8a40cf5b0a7f6cf6c17..41255415b67dae3106f28317c2a3776b44c2720f 100644 (file)
@@ -795,7 +795,7 @@ void *add_lamp(char *name)
        la->sun_intensity = 1.0f;
        la->skyblendtype= MA_RAMP_ADD;
        la->skyblendfac= 1.0f;
-       la->sky_colorspace= BLI_CS_CIE;
+       la->sky_colorspace= BLI_XYZ_CIE;
        la->sky_exposure= 1.0f;
        
        curvemapping_initialize(la->curfalloff);
index b2d14f3ecbd2c51cf2f35936430a2b4186f7bcf9..7444e01c3a67bcabc6bdfa196506e93d2f5d4820 100644 (file)
 extern "C" {
 #endif
 
-#define BLI_CS_SMPTE   0
-#define BLI_CS_REC709  1
-#define BLI_CS_CIE             2
+/* primaries */
+#define BLI_XYZ_SMPTE  0
+#define BLI_XYZ_REC709_SRGB    1
+#define BLI_XYZ_CIE            2
 
+/* built-in profiles */
+#define BLI_PR_NONE            0
+#define BLI_PR_SRGB            1
+#define BLI_PR_REC709  2
+       
 /******************* Conversion to RGB ********************/
 
 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
@@ -53,6 +59,16 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv);
 unsigned int rgb_to_cpack(float r, float g, float b);
 unsigned int hsv_to_cpack(float h, float s, float v);
 
+/***************** Profile Transformations ********************/
+
+void gamma_correct(float *c, float gamma);
+float rec709_to_linearrgb(float c);
+float linearrgb_to_rec709(float c);
+float srgb_to_linearrgb(float c);
+float linearrgb_to_srgb(float c);
+void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from);
+void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from);
+       
 /************************** Other *************************/
 
 int constrain_rgb(float *r, float *g, float *b);
index 7ae380a1dde07b38ebbc1e0706a5089271be4ca2..6dbd9c1381f095e798695332cb11fb84ba3cdb58 100644 (file)
@@ -208,17 +208,17 @@ void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
 void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int colorspace)
 {
        switch (colorspace) { 
-       case BLI_CS_SMPTE:
+       case BLI_XYZ_SMPTE:
                *r = (3.50570f   * xc) + (-1.73964f      * yc) + (-0.544011f * zc);
                *g = (-1.06906f  * xc) + (1.97781f       * yc) + (0.0351720f * zc);
                *b = (0.0563117f * xc) + (-0.196994f * yc) + (1.05005f   * zc);
                break;
-       case BLI_CS_REC709:
+       case BLI_XYZ_REC709_SRGB:
                *r = (3.240476f  * xc) + (-1.537150f * yc) + (-0.498535f * zc);
                *g = (-0.969256f * xc) + (1.875992f  * yc) + (0.041556f  * zc);
                *b = (0.055648f  * xc) + (-0.204043f * yc) + (1.057311f  * zc);
                break;
-       case BLI_CS_CIE:
+       case BLI_XYZ_CIE:
                *r = (2.28783848734076f * xc) + (-0.833367677835217f    * yc) + (-0.454470795871421f    * zc);
                *g = (-0.511651380743862f * xc) + (1.42275837632178f * yc) + (0.0888930017552939f * zc);
                *b = (0.00572040983140966f      * xc) + (-0.0159068485104036f   * yc) + (1.0101864083734f       * zc);
@@ -274,6 +274,61 @@ void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
        *b /= 255.0f;
 }
 
+/* ********************************* color transforms ********************************* */
+
+
+void gamma_correct(float *c, float gamma)
+{
+       *c = powf((*c), gamma);
+}
+
+float rec709_to_linearrgb(float c)
+{
+       if (c < 0.081f)
+               return (c < 0.0f)? 0.0f: c * (1.0f/4.5f);
+       else
+               return powf((c + 0.099f)*(1.0f/1.099f), (1.0f/0.45f));
+}
+
+float linearrgb_to_rec709(float c)
+{
+       if (c < 0.018f)
+               return (c < 0.0f)? 0.0f: c * 4.5f;
+       else
+               return 1.099f * powf(c, 0.45f) - 0.099f;
+}
+
+float srgb_to_linearrgb(float c)
+{
+       if (c < 0.04045f)
+               return (c < 0.0f)? 0.0f: c * (1.0f/12.92f);
+       else
+               return powf((c + 0.055f)*(1.0f/1.055f), 2.4f);
+}
+
+float linearrgb_to_srgb(float c)
+{
+       if (c < 0.0031308f)
+               return (c < 0.0f)? 0.0f: c * 12.92f;
+       else
+               return  1.055f * powf(c, 1.0f/2.4f) - 0.055f;
+}
+
+void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from)
+{
+       col_to[0] = srgb_to_linearrgb(col_from[0]);
+       col_to[1] = srgb_to_linearrgb(col_from[1]);
+       col_to[2] = srgb_to_linearrgb(col_from[2]);
+}
+
+void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from)
+{
+       col_to[0] = linearrgb_to_srgb(col_from[0]);
+       col_to[1] = linearrgb_to_srgb(col_from[1]);
+       col_to[2] = linearrgb_to_srgb(col_from[2]);
+}
+
+
 void minmax_rgb(short c[])
 {
        if(c[0]>255) c[0]=255;
index ce760643b3de87e0af7c65e246d36f51e1f64884..6103c582da0dedbb31b4dfb43ab3a78c46bf94e1 100644 (file)
@@ -10064,7 +10064,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       /* put 2.50 compatibility code here until next subversion bump */
+       if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 8))
        {
                {
                        Scene *sce= main->scene.first;
@@ -10108,7 +10108,47 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ob=ob->id.next;
                        }
                }
+               
+               /* only convert old 2.50 files with color management */
+               if (main->versionfile == 250) {
+                       Scene *sce=main->scene.first;
+                       Material *ma=main->mat.first;
+                       World *wo=main->world.first;
+                       int convert=0;
+                       
+                       /* convert to new color management system:
+                        while previously colors were stored as srgb, 
+                        now they are stored as linear internally, 
+                        with screen gamma correction in certain places in the UI. */
+
+                       /* don't know what scene is active, so we'll convert if any scene has it enabled... */
+                       while (sce) {
+                               if(sce->r.color_mgt_flag & R_COLOR_MANAGEMENT)
+                                       convert=1;
+                               sce=sce->id.next;
+                       }
+                       
+                       if (convert) {
+                               while(ma) {
+                                       srgb_to_linearrgb_v3_v3(&ma->r, &ma->r);
+                                       srgb_to_linearrgb_v3_v3(&ma->specr, &ma->specr);
+                                       srgb_to_linearrgb_v3_v3(&ma->mirr, &ma->mirr);
+                                       srgb_to_linearrgb_v3_v3(ma->sss_col, ma->sss_col);
+                                       ma=ma->id.next;
+                               }
+                               
+                               while(wo) {
+                                       srgb_to_linearrgb_v3_v3(&wo->ambr, &wo->ambr);
+                                       srgb_to_linearrgb_v3_v3(&wo->horr, &wo->horr);
+                                       srgb_to_linearrgb_v3_v3(&wo->zenr, &wo->zenr);
+                                       wo=wo->id.next;
+                               }
+                       }
+               }
        }
+       
+       /* put 2.50 compatibility code here until next subversion bump */
+       
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
index 70bef5534a19be30e0b0e5f5db5d72ceef4e186e..f0d09c505ac674009bc97b1f202791925aabff44 100644 (file)
@@ -1790,14 +1790,17 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor
 {
        uiBlock *block;
        wmWindow *window;
+       Scene *scn;
        int getsizex, getsizey;
 
        window= CTX_wm_window(C);
+       scn = CTX_data_scene(C);
 
        block= MEM_callocN(sizeof(uiBlock), "uiBlock");
        block->active= 1;
        block->dt= dt;
        block->evil_C= (void*)C; // XXX
+       if (scn) block->color_profile= (scn->r.color_mgt_flag & R_COLOR_MANAGEMENT);
        BLI_strncpy(block->name, name, sizeof(block->name));
 
        if(region)
@@ -2295,6 +2298,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short
        if(ELEM(but->type, HSVCUBE, HSVCIRCLE)) { /* hsv buttons temp storage */
                float rgb[3];
                ui_get_but_vectorf(but, rgb);
+
                rgb_to_hsv(rgb[0], rgb[1], rgb[2], but->hsv, but->hsv+1, but->hsv+2);
        }
 
index 762ec541bffc3bfa4c25a5ff00e4d5a6f7f378d1..e6e5cb198aafc94d01e1a0502d648adb7fc94e0e 100644 (file)
@@ -736,6 +736,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *wcol, rcti *rect)
        for( a = 1; a < sizex; a++ ) {
                pos = ((float)a) / (sizex-1);
                do_colorband( coba, pos, colf );
+               if (but->block->color_profile != BLI_PR_NONE)
+                       linearrgb_to_srgb_v3_v3(colf, colf);
                
                v1[0]=v2[0]= x1 + a;
                
index 6d65a2a57a1ac378a75427119fe5ced52b7cf566..a51824f10e92f7aadc9ea79ad196bf810be73764 100644 (file)
@@ -2697,7 +2697,13 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
 {
        float x, y;
        int changed= 1;
-
+       int color_profile = but->block->color_profile;
+       
+       if (but->rnaprop) {
+               if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
+                       color_profile = BLI_PR_NONE;
+       }
+               
        /* relative position within box */
        x= ((float)mx-but->x1)/(but->x2-but->x1);
        y= ((float)my-but->y1)/(but->y2-but->y1);
@@ -2719,8 +2725,12 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
        else if(but->a1==3) {
                but->hsv[0]= x; 
        }
-       else
+       else {
+               /* vertical 'value' strip */
                but->hsv[2]= y; 
+               if (color_profile)
+                       but->hsv[2] = srgb_to_linearrgb(but->hsv[2]);
+       }
 
        ui_set_but_hsv(but);    // converts to rgb
        
index 21425bbb261b9e6cc8387c9f5f71222e74a07f4c..97ef1f1ea176bb62593ad6ab2759e36d12758acd 100644 (file)
@@ -303,6 +303,8 @@ struct uiBlock {
 
        int active;                                     // to keep blocks while drawing and free them afterwards
        int puphash;                            // popup menu hash for memory
+       
+       int color_profile;                              // color profile for correcting linear colors for display
 
        void *evil_C;                           // XXX hack for dynamic operator enums
 };
index d46cb4df1c0bffd11dcb4bf08de1a6cb43764a60..175f1ff1e2a467d3e69af6ee5a2937a97bfbd7a9 100644 (file)
@@ -409,10 +409,10 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon
                }
        }
        else {
-               if(ELEM(subtype, PROP_COLOR, PROP_RGB))
+               if(ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA))
                        uiDefAutoButR(block, ptr, prop, -1, "", 0, 0, 0, w, UI_UNIT_Y);
 
-               if(!ELEM(subtype, PROP_COLOR, PROP_RGB) || expand) {
+               if(!ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) || expand) {
                        /* layout for known array subtypes */
                        char str[3];
 
@@ -439,7 +439,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, char *name, int icon
                                        but->type= TOG;
                        }
                }
-               else if(ELEM(subtype, PROP_COLOR, PROP_RGB) && len == 4) {
+               else if(ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && len == 4) {
                        but= uiDefAutoButR(block, ptr, prop, 3, "A:", 0, 0, 0, w, UI_UNIT_Y);
                        if(slider && but->type==NUM)
                                but->type= NUMSLI;
index c3eac3f389344ae33a32d889063d2c863337d90e..55b908a44ce1526a2a26f1e4ea237942dae47965 100644 (file)
@@ -1902,9 +1902,16 @@ static void uiBlockPickerNew(uiBlock *block, float *col, float *hsv, float *old,
        static short colormode= 0;      /* temp? 0=rgb, 1=hsv, 2=hex */
        uiBut *bt;
        int width;
+       static char tip[50];
        
        VECCOPY(old, col);      // old color stored there, for palette_cb to work
        
+       /* existence of profile means storage is in linear colour space, with display correction */
+       if (block->color_profile == BLI_PR_NONE)
+               sprintf(tip, "Value in Display Color Space");
+       else
+               sprintf(tip, "Value in Linear RGB Color Space");
+       
        /* HS circle */
        bt= uiDefButF(block, HSVCIRCLE, retval, "",     0, 0,SPICK1,SPICK1, col, 0.0, 0.0, 0, 0, "");
        uiButSetFunc(bt, do_picker_small_cb, bt, hsv);
@@ -1930,11 +1937,11 @@ static void uiBlockPickerNew(uiBlock *block, float *col, float *hsv, float *old,
        sprintf(hexcol, "%02X%02X%02X", (unsigned int)(col[0]*255.0), (unsigned int)(col[1]*255.0), (unsigned int)(col[2]*255.0));      
 
        uiBlockBeginAlign(block);
-       bt= uiDefButF(block, NUMSLI, 0, "R ",   0, -60, width, 19, col, 0.0, 1.0, 10, 3, "");
+       bt= uiDefButF(block, NUMSLI, 0, "R ",   0, -60, width, 19, col, 0.0, 1.0, 10, 3, tip);
        uiButSetFunc(bt, do_palette1_cb, bt, hsv);
-       bt= uiDefButF(block, NUMSLI, 0, "G ",   0, -80, width, 19, col+1, 0.0, 1.0, 10, 3, "");
+       bt= uiDefButF(block, NUMSLI, 0, "G ",   0, -80, width, 19, col+1, 0.0, 1.0, 10, 3, tip);
        uiButSetFunc(bt, do_palette1_cb, bt, hsv);
-       bt= uiDefButF(block, NUMSLI, 0, "B ",   0, -100, width, 19, col+2, 0.0, 1.0, 10, 3, "");
+       bt= uiDefButF(block, NUMSLI, 0, "B ",   0, -100, width, 19, col+2, 0.0, 1.0, 10, 3, tip);
        uiButSetFunc(bt, do_palette1_cb, bt, hsv);
        uiBlockEndAlign(block);
 
@@ -2000,6 +2007,13 @@ uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_bu
        
        block= uiBeginBlock(C, handle->region, "colorpicker", UI_EMBOSS);
        
+       /* XXX ideally the colour picker buttons would reference the rna property itself */
+       if (but->rnaprop) {
+               if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+                       block->color_profile = BLI_PR_NONE;
+               }
+       }
+       
        uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT);
        
        VECCOPY(handle->retvec, but->editvec);
index ecd8c9720c88eb12d7873d3e16e6e27b30845b9d..7aaa6cbb42b23062ee8a15ef9839ddfc9d474bd0 100644 (file)
@@ -80,7 +80,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
                case PROP_INT:
                case PROP_FLOAT:
                        if(arraylen && index == -1) {
-                               if(RNA_property_subtype(prop) == PROP_COLOR)
+                               if(ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA))
                                        but= uiDefButR(block, COL, 0, name, x1, y1, x2, y2, ptr, propname, 0, 0, 0, -1, -1, NULL);
                        }
                        else if(RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR)
index e148fd9217f7498e6cb8d2d69b9d929d3d72760e..4c9698974b41455967450318401a8aea67ce34b0 100644 (file)
@@ -44,6 +44,8 @@
 #include "BKE_global.h"
 #include "BKE_utildefines.h"
 
+#include "RNA_access.h"
+
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
@@ -1693,6 +1695,17 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
        uiWidgetBase wtb;
        float rad= 0.5f*(rect->xmax - rect->xmin);
        float x, y;
+       float v = but->hsv[2];
+       int color_profile = but->block->color_profile;
+       
+       if (but->rnaprop) {
+               if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
+                       color_profile = BLI_PR_NONE;
+               }
+       }
+
+       if (color_profile)
+               v = linearrgb_to_srgb(v);
        
        widget_init(&wtb);
        
@@ -1709,8 +1722,8 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
        widgetbase_draw(&wtb, &wcol_tmp);
 
        /* cursor */
-       x= rect->xmin + 0.5f*(rect->xmax-rect->xmin);
-       y= rect->ymin + but->hsv[2]*(rect->ymax-rect->ymin);
+       x= rect->xmin + 0.5f * (rect->xmax-rect->xmin);
+       y= rect->ymin + v * (rect->ymax-rect->ymin);
        CLAMP(y, rect->ymin+3.0, rect->ymax-3.0);
        
        ui_hsv_cursor(x, y);
@@ -2005,6 +2018,12 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
 {
        uiWidgetBase wtb;
        float col[4];
+       int color_profile = but->block->color_profile;
+       
+       if (but->rnaprop) {
+               if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
+                       color_profile = BLI_PR_NONE;
+       }
        
        widget_init(&wtb);
        
@@ -2012,6 +2031,10 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
        round_box_edges(&wtb, roundboxalign, rect, 5.0f);
                
        ui_get_but_vectorf(but, col);
+       
+       if (color_profile)
+               linearrgb_to_srgb_v3_v3(col, col);
+       
        wcol->inner[0]= FTOCHAR(col[0]);
        wcol->inner[1]= FTOCHAR(col[1]);
        wcol->inner[2]= FTOCHAR(col[2]);
index bf73e70367cdef84897da21eb095958d379264fd..51c7ba1a4bdeb6f7608f788b379605d87de5e24d 100644 (file)
@@ -341,8 +341,9 @@ static int set_draw_settings_cached(int clearcache, int textured, MTFace *texfac
 struct TextureDrawState {
        Object *ob;
        int islit, istex;
+       int color_profile;
        unsigned char obcol[4];
-} Gtexdraw = {NULL, 0, 0, {0, 0, 0, 0}};
+} Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}};
 
 static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
 {
@@ -371,6 +372,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
 
        Gtexdraw.ob = ob;
        Gtexdraw.istex = istex;
+       Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
        memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
        set_draw_settings_cached(1, 0, 0, Gtexdraw.islit, 0, 0, 0);
        glShadeModel(GL_SMOOTH);
@@ -413,7 +415,13 @@ static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr)
                if (tface) glColor3f(1.0, 1.0, 1.0);
                else {
                        Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
-                       if(ma) glColor3f(ma->r, ma->g, ma->b);
+                       if(ma) {
+                               float col[3];
+                               if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
+                               else copy_v3_v3(col, &ma->r);
+                               
+                               glColor3fv(col);
+                       }
                        else glColor3f(1.0, 1.0, 1.0);
                }
                return 2; /* Don't set color */
@@ -478,13 +486,19 @@ static void add_tface_color_layer(DerivedMesh *dm)
                                }
                        }
                        else {
+                               float col[3];
                                Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
-                               if(ma) 
+                               
+                               if(ma) {
+                                       if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
+                                       else copy_v3_v3(col, &ma->r);
+                                       
                                        for(j=0;j<4;j++) {
-                                               finalCol[i*4+j].b = ma->b;
-                                               finalCol[i*4+j].g = ma->g;
-                                               finalCol[i*4+j].r = ma->r;
+                                               finalCol[i*4+j].b = col[2];
+                                               finalCol[i*4+j].g = col[1];
+                                               finalCol[i*4+j].r = col[0];
                                        }
+                               }
                                else
                                        for(j=0;j<4;j++) {
                                                finalCol[i*4+j].b = 255;
index 75e8073aafd68df65af3ece544e46c8bc3127ef7..c2cf4dfa9fd7f92312413c50c5d1f244b4346c25 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "GL/glew.h"
 
+#include "BLI_math.h"
+
 #include "DNA_image_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
@@ -856,6 +858,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
        GPUMaterial *gpumat;
        GPUBlendMode blendmode;
        int a;
+       int gamma = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
        
        /* initialize state */
        memset(&GMS, 0, sizeof(GMS));
@@ -930,6 +933,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
                                GMS.matbuf[a][0][0]= ma->r;
                                GMS.matbuf[a][0][1]= ma->g;
                                GMS.matbuf[a][0][2]= ma->b;
+                               if(gamma) linearrgb_to_srgb_v3_v3(&GMS.matbuf[a][0][0], &GMS.matbuf[a][0][0]);
                        } else {
                                GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
                                GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
@@ -939,6 +943,11 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
                                GMS.matbuf[a][1][1]= ma->spec*ma->specg;
                                GMS.matbuf[a][1][2]= ma->spec*ma->specb;
                                GMS.matbuf[a][1][3]= 1.0;
+                               
+                               if(gamma) {
+                                       linearrgb_to_srgb_v3_v3(&GMS.matbuf[a][0][0], &GMS.matbuf[a][0][0]);
+                                       linearrgb_to_srgb_v3_v3(&GMS.matbuf[a][1][0], &GMS.matbuf[a][1][0]);
+                               }
                        }
 
                        blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
index ff01f76fe7137cc11566cae0de0779060aae1587..27dd1069c1c1b26e579e64ff476c2fb311335a7a 100644 (file)
@@ -115,7 +115,7 @@ typedef enum PropertySubType {
        PROP_QUATERNION = 27,
        PROP_AXISANGLE = 28,
        PROP_XYZ = 29,
-       PROP_RGB = 30,
+       PROP_COLOR_GAMMA = 30,
 
        /* booleans */
        PROP_LAYER = 40,
index 3d4e128c3aca2658fcf170089f0456777e96ab9c..543e1f3ecc03a74b6d8d95d3ce8cc3d7208c9455 100644 (file)
@@ -1430,7 +1430,7 @@ static const char *rna_property_subtypename(PropertyType type)
                case PROP_VELOCITY: return "PROP_VELOCITY";
                case PROP_ACCELERATION: return "PROP_ACCELERATION";
                case PROP_XYZ: return "PROP_XYZ";
-               case PROP_RGB: return "PROP_RGB";
+               case PROP_COLOR_GAMMA: return "PROP_COLOR_GAMMA";
                case PROP_LAYER: return "PROP_LAYER";
                case PROP_LAYER_MEMBER: return "PROP_LAYER_MEMBER";
                default: {
index 6c0a3c57f653a203ec54e49f793b5b4728e6a6a1..5ee811d4c464214a28b1d20099342d0f56411907 100644 (file)
@@ -693,7 +693,7 @@ char RNA_property_array_item_char(PropertyRNA *prop, int index)
                return quatitem[index];
        else if((index < 4) && ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
                return vectoritem[index];
-       else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_RGB))
+       else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA))
                return coloritem[index];
 
        return '\0';
@@ -731,7 +731,7 @@ int RNA_property_array_item_index(PropertyRNA *prop, char name)
                                return 3;
                }
        }
-       else if (ELEM(subtype, PROP_COLOR, PROP_RGB)) {
+       else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
                switch (name) {
                        case 'R':
                                return 0;
index e9744c7f5eda37d1a488218c23aa22875045a94c..28f546c07f106e72db185e5ee7fff0704075c8ad 100644 (file)
@@ -203,7 +203,7 @@ static void rna_def_brush(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Rate", "Number of paints per second for Airbrush.");
        RNA_def_property_update(prop, 0, "rna_Brush_update");
        
-       prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
+       prop= RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
        RNA_def_property_float_sdna(prop, NULL, "rgb");
        RNA_def_property_ui_text(prop, "Color", "");
        RNA_def_property_update(prop, 0, "rna_Brush_update");
index 2a97eb78382dd1dd08a967fb7276435a85e8ba27..c4edd00045b56b90fd8a9791ed60a49fd9dabb53 100644 (file)
@@ -216,13 +216,13 @@ static void rna_def_curvemapping(BlenderRNA *brna)
        RNA_def_property_struct_type(prop, "CurveMap");
        RNA_def_property_ui_text(prop, "Curves", "");
 
-       prop= RNA_def_property(srna, "black_level", PROP_FLOAT, PROP_RGB);
+       prop= RNA_def_property(srna, "black_level", PROP_FLOAT, PROP_COLOR);
        RNA_def_property_float_sdna(prop, NULL, "black");
        RNA_def_property_range(prop, -1000.0f, 1000.0f);
        RNA_def_property_ui_text(prop, "Black Level", "For RGB curves, the color that black is mapped to");
        RNA_def_property_float_funcs(prop, NULL, "rna_CurveMapping_black_level_set", NULL);
 
-       prop= RNA_def_property(srna, "white_level", PROP_FLOAT, PROP_RGB);
+       prop= RNA_def_property(srna, "white_level", PROP_FLOAT, PROP_COLOR);
        RNA_def_property_float_sdna(prop, NULL, "white");
        RNA_def_property_range(prop, -1000.0f, 1000.0f);
        RNA_def_property_ui_text(prop, "White Level", "For RGB curves, the color that white is mapped to");
index 5ff8bffe7159608e2fcee14d6eb88c9462fbb80c..85007482dc49c279d61b8ac4e2c2e2fbd3674dbd 100644 (file)
@@ -1239,7 +1239,7 @@ static void rna_def_material_sss(BlenderRNA *brna)
        RNA_def_struct_nested(brna, srna, "Material");
        RNA_def_struct_ui_text(srna, "Material Subsurface Scattering", "Diffuse subsurface scattering settings for a Material datablock.");
 
-       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_RGB|PROP_UNIT_LENGTH);
+       prop= RNA_def_property(srna, "radius", PROP_FLOAT, PROP_COLOR|PROP_UNIT_LENGTH);
        RNA_def_property_float_sdna(prop, NULL, "sss_radius");
        RNA_def_property_range(prop, 0.001, FLT_MAX);
        RNA_def_property_ui_range(prop, 0.001, 10000, 1, 3);
index f8adb1a79d8aea6de4ccf9f05774cd60f5572429..5997867030d051e95001b38a5b051e2666108b74 100644 (file)
@@ -869,7 +869,7 @@ static void rna_def_property(BlenderRNA *brna)
                {PROP_EULER, "EULER", 0, "Euler", ""},
                {PROP_QUATERNION, "QUATERNION", 0, "Quaternion", ""},
                {PROP_XYZ, "XYZ", 0, "XYZ", ""},
-               {PROP_RGB, "RGB", 0, "RGB", ""},
+               {PROP_COLOR_GAMMA, "COLOR_GAMMA", 0, "Gamma Corrected Color", ""},
                {PROP_LAYER, "LAYER", 0, "Layer", ""},
                {PROP_LAYER_MEMBER, "LAYER_MEMBERSHIP", 0, "Layer Membership", ""},
                {0, NULL, 0, NULL, NULL}};
index 32c2e18197f42f71f80326e63daa5afd77070283..8f8e083523b4882eb9608999c6c626a04fbfadaf 100644 (file)
@@ -4848,8 +4848,7 @@ void RE_Database_FromScene(Render *re, Scene *scene, int use_camera_view)
        
        /* still bad... doing all */
        init_render_textures(re);
-       if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(amb, &re->wrld.ambr);
-       else VECCOPY(amb, &re->wrld.ambr);
+       VECCOPY(amb, &re->wrld.ambr);
        init_render_materials(re->r.mode, amb);
        set_node_shader_lamp_loop(shade_material_loop);
 
@@ -5538,8 +5537,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob)
        /* still bad... doing all */
        init_render_textures(re);
        
-       if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(amb, &re->wrld.ambr);
-       else VECCOPY(amb, &re->wrld.ambr);
+       VECCOPY(amb, &re->wrld.ambr);
        init_render_materials(re->r.mode, amb);
        
        set_node_shader_lamp_loop(shade_material_loop);
index d4b7c403f502208473ed7262ee29c0126c5fa1ba..6fef8279c7ed06f588f71df05bbc0d62f9a5f207 100644 (file)
@@ -537,15 +537,9 @@ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short th
                /* the fraction of how far we are above the bottom of the screen */
                blend= fabs(0.5+ view[1]);
        }
-       
-       if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-               color_manage_linearize(hor, &R.wrld.horr);
-               color_manage_linearize(zen, &R.wrld.zenr);
-       }
-       else {
-               VECCOPY(hor, &R.wrld.horr);
-               VECCOPY(zen, &R.wrld.zenr);
-       }
+
+       VECCOPY(hor, &R.wrld.horr);
+       VECCOPY(zen, &R.wrld.zenr);
 
        /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If           */
        /* SKYBLEND is active, the texture and color blend are added.           */
@@ -633,10 +627,7 @@ void shadeSkyPixel(float *collector, float fx, float fy, short thread)
        } 
        else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) {
                /* 2. solid color */
-               if(R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
-                       color_manage_linearize(collector, &R.wrld.horr);
-               else
-                       VECCOPY(collector, &R.wrld.horr);
+               VECCOPY(collector, &R.wrld.horr);
 
                collector[3] = 0.0f;
        } 
index 396c713cfb75587fcf1e4991c631652b0ccfe54d..fd1e27ab28a083226eddf396d91a99d3b7352d97 100644 (file)
@@ -91,42 +91,16 @@ extern struct Render R;
  * doing inverse gamma correction where applicable */
 void shade_input_init_material(ShadeInput *shi)
 {
-       if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-               color_manage_linearize(&shi->r, &shi->mat->r);
-               color_manage_linearize(&shi->specr, &shi->mat->specr);
-               color_manage_linearize(&shi->mirr, &shi->mat->mirr);
-               
-               /* material ambr / ambg / ambb is overwritten from world
-               color_manage_linearize(shi->ambr, shi->mat->ambr);
-               */
-               
-               /* note, keep this synced with render_types.h */
-               memcpy(&shi->amb, &shi->mat->amb, 11*sizeof(float));
-               shi->har= shi->mat->har;
-       } else {
-               /* note, keep this synced with render_types.h */
-               memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
-               shi->har= shi->mat->har;
-       }
-
-}
-
-static void shadeinput_colors_linearize(ShadeInput *shi)
-{
-       color_manage_linearize(&shi->r, &shi->r);
-       color_manage_linearize(&shi->specr, &shi->specr);
-       color_manage_linearize(&shi->mirr, &shi->mirr);
+       /* note, keep this synced with render_types.h */
+       memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
+       shi->har= shi->mat->har;
 }
 
 /* also used as callback for nodes */
 /* delivers a fully filled in ShadeResult, for all passes */
 void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
 {
-       /* because node materials don't have access to rendering context,
-        * inverse gamma correction must happen here. evil. */
-       if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT && shi->nodes == 1)
-               shadeinput_colors_linearize(shi);
-       
+
        shade_lamp_loop(shi, shr);      /* clears shr */
        
        if(shi->translucency!=0.0f) {
@@ -626,7 +600,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert
        
        if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
                if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) {
-                       color_manage_linearize(shi->vcol, shi->vcol);
+                       srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol);
                }
        }
        
@@ -1291,7 +1265,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
        */
        if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
                if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP|MA_FACETEXTURE)) {
-                       color_manage_linearize(shi->vcol, shi->vcol);
+                       srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol);
                }
        }
        
index 25cfc0f1253e2801b9effa698f1f3f52d659013a..e551cf0f3d2e4cc410953ce2b2aa18f6c2db7eac 100644 (file)
@@ -926,20 +926,17 @@ static void sss_create_tree_mat(Render *re, Material *mat)
        if(!re->test_break(re->tbh)) {
                SSSData *sss= MEM_callocN(sizeof(*sss), "SSSData");
                float ior= mat->sss_ior, cfac= mat->sss_colfac;
-               float col[3], *radius= mat->sss_radius;
+               float *radius= mat->sss_radius;
                float fw= mat->sss_front, bw= mat->sss_back;
                float error = mat->sss_error;
 
                error= get_render_aosss_error(&re->r, error);
                if((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f)
                        error= 0.5f;
-
-               if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) color_manage_linearize(col, mat->sss_col);
-               else VECCOPY(col, mat->sss_col);
                
-               sss->ss[0]= scatter_settings_new(col[0], radius[0], ior, cfac, fw, bw);
-               sss->ss[1]= scatter_settings_new(col[1], radius[1], ior, cfac, fw, bw);
-               sss->ss[2]= scatter_settings_new(col[2], radius[2], ior, cfac, fw, bw);
+               sss->ss[0]= scatter_settings_new(mat->sss_col[0], radius[0], ior, cfac, fw, bw);
+               sss->ss[1]= scatter_settings_new(mat->sss_col[1], radius[1], ior, cfac, fw, bw);
+               sss->ss[2]= scatter_settings_new(mat->sss_col[2], radius[2], ior, cfac, fw, bw);
                sss->tree= scatter_tree_new(sss->ss, mat->sss_scale, error,
                        co, color, area, totpoint);
 
index a9f6e7a53fd813d471527886feca8a112992f3ed..16372d7a15d95b2078f97932b7e10cc41a65a6a7 100644 (file)
@@ -2051,8 +2051,13 @@ void do_material_tex(ShadeInput *shi)
                                else texres.tin= texres.ta;
                                
                                /* inverse gamma correction */
-                               if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-                                       color_manage_linearize(tcol, tcol);
+                               if (tex->type==TEX_IMAGE) {
+                                       Image *ima = tex->ima;
+                                       ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser);
+                                       
+                                       /* don't linearize float buffers, assumed to be linear */
+                                       if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
+                                               srgb_to_linearrgb_v3_v3(tcol, tcol);
                                }
                                
                                if(mtex->mapto & MAP_COL) {
@@ -2404,11 +2409,6 @@ void do_volume_tex(ShadeInput *shi, float *xyz, int mapto_flag, float *col, floa
                                                texres.tin= texres.ta;
                                }
                                
-                               /* inverse gamma correction */
-                               if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-                                       color_manage_linearize(tcol, tcol);
-                               }
-                               
                                /* used for emit */
                                if((mapto_flag & MAP_EMISSION_COL) && (mtex->mapto & MAP_EMISSION_COL)) {
                                        float colemitfac= mtex->colemitfac*stencilTin;
@@ -2556,8 +2556,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf)
                else texres.tin= texres.ta;
 
                /* inverse gamma correction */
-               if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-                       color_manage_linearize(&texres.tr, &texres.tr);
+               if (mtex->tex->type==TEX_IMAGE) {
+                       Image *ima = mtex->tex->ima;
+                       ImBuf *ibuf = BKE_image_get_ibuf(ima, &mtex->tex->iuser);
+                       
+                       /* don't linearize float buffers, assumed to be linear */
+                       if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
+                               srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr);
                }
 
                fact= texres.tin*mtex->colfac;
@@ -2605,6 +2610,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf)
 void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag, short thread)
 {
        MTex *mtex;
+       Tex *tex;
        TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
        float *co, fact, stencilTin=1.0;
        float tempvec[3], texvec[3], dxt[3], dyt[3];
@@ -2618,7 +2624,8 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f
                if(R.wrld.mtex[tex_nr]) {
                        mtex= R.wrld.mtex[tex_nr];
                        
-                       if(mtex->tex==0) continue;
+                       tex= mtex->tex;
+                       if(tex==0) continue;
                        /* if(mtex->mapto==0) continue; */
                        
                        /* which coords */
@@ -2700,7 +2707,7 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f
                        else texvec[2]= mtex->size[2]*(mtex->ofs[2]);
                        
                        /* texture */
-                       if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
+                       if(tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
                
                        rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output);
                        
@@ -2748,8 +2755,13 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f
                                tcol[0]= texres.tr; tcol[1]= texres.tg; tcol[2]= texres.tb;
 
                                /* inverse gamma correction */
-                               if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-                                       color_manage_linearize(tcol, tcol);
+                               if (tex->type==TEX_IMAGE) {
+                                       Image *ima = tex->ima;
+                                       ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser);
+                                       
+                                       /* don't linearize float buffers, assumed to be linear */
+                                       if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
+                                               srgb_to_linearrgb_v3_v3(tcol, tcol);
                                }
 
                                if(mtex->mapto & WOMAP_HORIZ) {
@@ -2947,8 +2959,13 @@ void do_lamp_tex(LampRen *la, float *lavec, ShadeInput *shi, float *colf, int ef
                                else texres.tin= texres.ta;
 
                                /* inverse gamma correction */
-                               if (R.r.color_mgt_flag & R_COLOR_MANAGEMENT) {
-                                       color_manage_linearize(&texres.tr, &texres.tr);
+                               if (tex->type==TEX_IMAGE) {
+                                       Image *ima = tex->ima;
+                                       ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser);
+                                       
+                                       /* don't linearize float buffers, assumed to be linear */
+                                       if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
+                                               srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr);
                                }
 
                                /* lamp colors were premultiplied with this */