[Bf-blender-cvs] [7ad802cf3ae] master: Cycles/Eevee: unified and improved texture image color space handling

Brecht Van Lommel noreply at git.blender.org
Mon May 13 16:33:26 CEST 2019


Commit: 7ad802cf3ae500bc72863b6dba0f28a488fce3d1
Author: Brecht Van Lommel
Date:   Tue Apr 23 13:56:30 2019 +0200
Branches: master
https://developer.blender.org/rB7ad802cf3ae500bc72863b6dba0f28a488fce3d1

Cycles/Eevee: unified and improved texture image color space handling

Cycles now uses the color space on the image datablock, and uses OpenColorIO
to convert to scene linear as needed. Byte images do not take extra memory,
they are compressed in scene linear + sRGB transfer function which in common
cases is a no-op.

Eevee and workbench were changed to work similar. Float images are stored as
scene linear. Byte images are compressed as scene linear + sRGB and stored in
a GL_SRGB8_ALPHA8 texture. From the GLSL shader side this means they are read
as scene linear, simplifying the code and taking advantage of hardware support.

Further, OpenGL image textures are now all stored with premultiplied alpha.
Eevee texture sampling looks a little different now because interpolation
happens premultiplied and in scene linear space.

Overlays and grease pencil work in sRGB space so those now have an extra
conversion to sRGB after reading from image textures. This is not particularly
elegant but as long as engines use different conventions, one or the other
needs to do conversion.

This change breaks compatibility for cases where multiple image texture nodes
were using the same image with different color space node settings. However it
gives more predictable behavior for baking and texture painting if save, load
and image editing operations have a single color space to handle.

Differential Revision: https://developer.blender.org/D4807

===================================================================

M	intern/cycles/blender/blender_shader.cpp
M	intern/cycles/render/colorspace.cpp
M	intern/opencolorio/ocio_capi.h
M	intern/opencolorio/ocio_impl.cc
M	source/blender/blenkernel/BKE_blender_version.h
M	source/blender/blenloader/intern/versioning_cycles.c
M	source/blender/draw/engines/gpencil/gpencil_draw_utils.c
M	source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
M	source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
M	source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
M	source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
M	source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
M	source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
M	source/blender/draw/engines/workbench/workbench_forward.c
M	source/blender/draw/engines/workbench/workbench_materials.c
M	source/blender/draw/intern/draw_manager_data.c
M	source/blender/draw/modes/object_mode.c
M	source/blender/draw/modes/paint_texture_mode.c
M	source/blender/draw/modes/shaders/object_empty_image_frag.glsl
M	source/blender/draw/modes/shaders/paint_texture_frag.glsl
M	source/blender/editors/sculpt_paint/paint_image_proj.c
M	source/blender/editors/space_node/drawnode.c
M	source/blender/gpu/GPU_draw.h
M	source/blender/gpu/GPU_material.h
M	source/blender/gpu/GPU_texture.h
M	source/blender/gpu/intern/gpu_codegen.c
M	source/blender/gpu/intern/gpu_codegen.h
M	source/blender/gpu/intern/gpu_draw.c
M	source/blender/gpu/intern/gpu_material.c
M	source/blender/gpu/intern/gpu_texture.c
M	source/blender/gpu/shaders/gpu_shader_material.glsl
M	source/blender/imbuf/IMB_colormanagement.h
M	source/blender/imbuf/intern/IMB_colormanagement_intern.h
M	source/blender/imbuf/intern/colormanagement.c
M	source/blender/makesdna/DNA_image_types.h
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_color.c
M	source/blender/makesrna/intern/rna_image_api.c
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/shader/node_shader_util.h
M	source/blender/nodes/shader/nodes/node_shader_tex_environment.c
M	source/blender/nodes/shader/nodes/node_shader_tex_image.c

===================================================================

diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index e6ec8b22d7a..a08f767f964 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -651,6 +651,9 @@ static ShaderNode *add_node(Scene *scene,
         image->builtin_data = NULL;
       }
 
+      PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
+      image->colorspace = get_enum_identifier(colorspace_ptr, "name");
+
       image->animated = b_image_node.image_user().use_auto_refresh();
       image->use_alpha = b_image.use_alpha();
 
@@ -662,18 +665,11 @@ static ShaderNode *add_node(Scene *scene,
                                                image->builtin_data,
                                                get_image_interpolation(b_image_node),
                                                get_image_extension(b_image_node),
-                                               image->use_alpha);
+                                               image->use_alpha,
+                                               image->colorspace);
       }
 #endif
     }
-    switch (b_image_node.color_space()) {
-      case BL::ShaderNodeTexImage::color_space_NONE:
-        image->colorspace = u_colorspace_raw;
-        break;
-      case BL::ShaderNodeTexImage::color_space_COLOR:
-        image->colorspace = u_colorspace_auto;
-        break;
-    }
     image->projection = (NodeImageProjection)b_image_node.projection();
     image->interpolation = get_image_interpolation(b_image_node);
     image->extension = get_image_extension(b_image_node);
@@ -703,6 +699,9 @@ static ShaderNode *add_node(Scene *scene,
         env->builtin_data = NULL;
       }
 
+      PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
+      env->colorspace = get_enum_identifier(colorspace_ptr, "name");
+
       env->animated = b_env_node.image_user().use_auto_refresh();
       env->use_alpha = b_image.use_alpha();
 
@@ -714,18 +713,11 @@ static ShaderNode *add_node(Scene *scene,
                                                env->builtin_data,
                                                get_image_interpolation(b_env_node),
                                                EXTENSION_REPEAT,
-                                               env->use_alpha);
+                                               env->use_alpha,
+                                               env->colorspace);
       }
 #endif
     }
-    switch (b_env_node.color_space()) {
-      case BL::ShaderNodeTexEnvironment::color_space_NONE:
-        env->colorspace = u_colorspace_raw;
-        break;
-      case BL::ShaderNodeTexEnvironment::color_space_COLOR:
-        env->colorspace = u_colorspace_auto;
-        break;
-    }
     env->interpolation = get_image_interpolation(b_env_node);
     env->projection = (NodeEnvironmentProjection)b_env_node.projection();
     BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
diff --git a/intern/cycles/render/colorspace.cpp b/intern/cycles/render/colorspace.cpp
index cdce1f70188..7b57478ff51 100644
--- a/intern/cycles/render/colorspace.cpp
+++ b/intern/cycles/render/colorspace.cpp
@@ -242,6 +242,10 @@ inline void processor_apply_pixels(const OCIO::Processor *processor,
                                    size_t width,
                                    size_t height)
 {
+  /* TODO: implement faster version for when we know the conversion
+   * is a simple matrix transform between linear spaces. In that case
+   * unpremultiply is not needed. */
+
   /* Process large images in chunks to keep temporary memory requirement down. */
   size_t y_chunk_size = max(1, 16 * 1024 * 1024 / (sizeof(float4) * width));
   vector<float4> float_pixels(y_chunk_size * width);
@@ -252,7 +256,16 @@ inline void processor_apply_pixels(const OCIO::Processor *processor,
 
     for (size_t y = y0; y < y1; y++) {
       for (size_t x = 0; x < width; x++, i++) {
-        float_pixels[i] = cast_to_float4(pixels + 4 * (y * width + x));
+        float4 value = cast_to_float4(pixels + 4 * (y * width + x));
+
+        if (!(value.w == 0.0f || value.w == 1.0f)) {
+          float inv_alpha = 1.0f / value.w;
+          value.x *= inv_alpha;
+          value.y *= inv_alpha;
+          value.z *= inv_alpha;
+        }
+
+        float_pixels[i] = value;
       }
     }
 
@@ -263,25 +276,20 @@ inline void processor_apply_pixels(const OCIO::Processor *processor,
     for (size_t y = y0; y < y1; y++) {
       for (size_t x = 0; x < width; x++, i++) {
         float4 value = float_pixels[i];
+
+        value.x *= value.w;
+        value.y *= value.w;
+        value.z *= value.w;
+
         if (compress_as_srgb) {
           value = color_linear_to_srgb_v4(value);
         }
+
         cast_from_float4(pixels + 4 * (y * width + x), value);
       }
     }
   }
 }
-
-/* Fast version for float images, which OpenColorIO can handle natively. */
-template<>
-inline void processor_apply_pixels(const OCIO::Processor *processor,
-                                   float *pixels,
-                                   size_t width,
-                                   size_t height)
-{
-  OCIO::PackedImageDesc desc(pixels, width, height, 4);
-  processor->apply(desc);
-}
 #endif
 
 template<typename T>
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index f4d7717ba46..9ba2d8fb8f9 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -31,6 +31,7 @@ struct OCIO_GLSLDrawState;
     int unused; \
   } * name
 
+#define OCIO_ROLE_DATA "data"
 #define OCIO_ROLE_SCENE_LINEAR "scene_linear"
 #define OCIO_ROLE_COLOR_PICKING "color_picking"
 #define OCIO_ROLE_TEXTURE_PAINT "texture_paint"
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index 644117e0000..25c1df70045 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -552,7 +552,7 @@ void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
     processor = (*config)->getProcessor((*cs)->getName(), "scene_linear");
   }
   catch (Exception &exception) {
-    OCIO_reportException(exception);
+    /* Silently ignore if no conversion possible, then it's not scene linear or sRGB. */
     is_scene_linear = false;
     is_srgb = false;
     return;
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 16275c96eec..74d33a9c275 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -27,7 +27,7 @@
  * \note Use #STRINGIFY() rather than defining with quotes.
  */
 #define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 62
+#define BLENDER_SUBVERSION 63
 /** Several breakages with 280, e.g. collections vs layers. */
 #define BLENDER_MINVERSION 280
 #define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index 023bd685352..2bd379c6f19 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -38,6 +38,8 @@
 #include "BKE_main.h"
 #include "BKE_node.h"
 
+#include "IMB_colormanagement.h"
+
 #include "BLO_readfile.h"
 #include "readfile.h"
 
@@ -262,6 +264,33 @@ static void ambient_occlusion_node_relink(bNodeTree *ntree)
   }
 }
 
+static void image_node_colorspace(bNode *node)
+{
+  if (node->id == NULL) {
+    return;
+  }
+
+  int color_space;
+  if (node->type == SH_NODE_TEX_IMAGE) {
+    NodeTexImage *tex = node->storage;
+    color_space = tex->color_space;
+  }
+  else if (node->type == SH_NODE_TEX_ENVIRONMENT) {
+    NodeTexEnvironment *tex = node->storage;
+    color_space = tex->color_space;
+  }
+  else {
+    return;
+  }
+
+  const int SHD_COLORSPACE_NONE = 0;
+  Image *image = (Image *)node->id;
+  if (color_space == SHD_COLORSPACE_NONE) {
+    STRNCPY(image->colorspace_settings.name,
+            IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA));
+  }
+}
+
 void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
 {
   /* Particle shape shared with Eevee. */
@@ -326,6 +355,12 @@ void do_versions_after_linking_cycles(Main *bmain)
       if (!MAIN_VERSION_ATLEAST(bmain, 279, 5)) {
         ambient_occlusion_node_relink(ntree);
       }
+
+      if (!MAIN_VERSION_ATLEAST(bmain, 280, 63)) {
+        for (bNode *node = ntree->nodes.first; node; node = node->next) {
+          image_node_colorspace(node);
+        }
+      }
     }
     FOREACH_NODETREE_END;
   }
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index c23b4c254e4..d57c43ab375 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -465,7 +465,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(GPENCIL_e_data *e_data,
       BKE_image_release_ibuf(image, ibuf, NULL);
     }
     else {
-      GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true);
+      GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D);
       DRW_shgroup_uniform_texture(grp, "myTexture", texture);
 
       stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0;
@@ -631,7 +631,7 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(GPENCIL_e_data *e_data,
       BKE_image_release_ibuf(image, ibuf, NULL);
     }
     else {
-      GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true);
+      GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D);
       DRW_shgroup_uniform_texture(grp, "myTexture", texture);
 
       BKE_image_release_ibuf(image, ibuf, NULL);
@@ -787,7 +787,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data,
       BKE_image_release_ibuf(image, ibuf, NULL);
     }
     else {
-      GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true);
+      GPUTexture *texture = GPU_texture_from_blender(gp_style->sima

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list