[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60632] trunk/blender: Implementation of curve mapping in GLSL

Sergey Sharybin sergey.vfx at gmail.com
Wed Oct 9 17:57:33 CEST 2013


Revision: 60632
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60632
Author:   nazgul
Date:     2013-10-09 15:57:32 +0000 (Wed, 09 Oct 2013)
Log Message:
-----------
Implementation of curve mapping in GLSL

The title says it all, now having curve mapping
enabled in color management settings wouldn't
force fallback from GLSL to CPU based color space
conversion.

Modified Paths:
--------------
    trunk/blender/SConstruct
    trunk/blender/intern/opencolorio/CMakeLists.txt
    trunk/blender/intern/opencolorio/SConscript
    trunk/blender/intern/opencolorio/fallback_impl.cc
    trunk/blender/intern/opencolorio/ocio_capi.cc
    trunk/blender/intern/opencolorio/ocio_capi.h
    trunk/blender/intern/opencolorio/ocio_impl.h
    trunk/blender/intern/opencolorio/ocio_impl_glsl.cc
    trunk/blender/source/blender/editors/render/render_internal.c
    trunk/blender/source/blender/editors/screen/glutil.c
    trunk/blender/source/blender/imbuf/IMB_colormanagement.h
    trunk/blender/source/blender/imbuf/intern/colormanagement.c
    trunk/blender/source/blender/makesrna/intern/rna_render.c

Added Paths:
-----------
    trunk/blender/intern/opencolorio/gpu_shader_display_transform.glsl

Modified: trunk/blender/SConstruct
===================================================================
--- trunk/blender/SConstruct	2013-10-09 15:51:14 UTC (rev 60631)
+++ trunk/blender/SConstruct	2013-10-09 15:57:32 UTC (rev 60632)
@@ -552,6 +552,7 @@
     data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl")
     data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl")
     data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl")
+    data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl")
 
     # --- blender ---
     data_to_c_simple("release/datafiles/bfont.pfb")

Modified: trunk/blender/intern/opencolorio/CMakeLists.txt
===================================================================
--- trunk/blender/intern/opencolorio/CMakeLists.txt	2013-10-09 15:51:14 UTC (rev 60631)
+++ trunk/blender/intern/opencolorio/CMakeLists.txt	2013-10-09 15:57:32 UTC (rev 60632)
@@ -62,6 +62,8 @@
 			${BOOST_INCLUDE_DIR}
 		)
 	endif()
+
+	data_to_c_simple(gpu_shader_display_transform.glsl SRC)
 endif()
 
 

Modified: trunk/blender/intern/opencolorio/SConscript
===================================================================
--- trunk/blender/intern/opencolorio/SConscript	2013-10-09 15:51:14 UTC (rev 60631)
+++ trunk/blender/intern/opencolorio/SConscript	2013-10-09 15:57:32 UTC (rev 60632)
@@ -39,6 +39,13 @@
 
     if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
         incs += ' ' + env['BF_BOOST_INC']
+
+    # generated data files
+    import os
+    sources.extend((
+        os.path.join(env['DATA_SOURCES'], "gpu_shader_display_transform.glsl.c"),
+    ))
+
 else:
     sources.remove('ocio_impl.cc')
     sources.remove('ocio_impl_glsl.cc')

Modified: trunk/blender/intern/opencolorio/fallback_impl.cc
===================================================================
--- trunk/blender/intern/opencolorio/fallback_impl.cc	2013-10-09 15:51:14 UTC (rev 60631)
+++ trunk/blender/intern/opencolorio/fallback_impl.cc	2013-10-09 15:57:32 UTC (rev 60632)
@@ -418,7 +418,8 @@
 	return false;
 }
 
-bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/, bool /*predivide*/)
+bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/,
+                                 OCIO_CurveMappingSettings * /*curve_mapping_settings*/, bool /*predivide*/)
 {
 	return false;
 }

Added: trunk/blender/intern/opencolorio/gpu_shader_display_transform.glsl
===================================================================
--- trunk/blender/intern/opencolorio/gpu_shader_display_transform.glsl	                        (rev 0)
+++ trunk/blender/intern/opencolorio/gpu_shader_display_transform.glsl	2013-10-09 15:57:32 UTC (rev 60632)
@@ -0,0 +1,123 @@
+uniform sampler2D image_texture;
+uniform sampler3D lut3d_texture;
+uniform bool predivide;
+
+#ifdef USE_CURVE_MAPPING
+/* Curve mapping parameters
+ *
+ * See documentation for OCIO_CurveMappingSettings to get fields descriptions.
+ * (this ones pretyt much copies stuff from C structure.)
+ */
+uniform sampler1D curve_mapping_texture;
+uniform int curve_mapping_lut_size;
+uniform ivec4 use_curve_mapping_extend_extrapolate;
+uniform vec4 curve_mapping_mintable;
+uniform vec4 curve_mapping_range;
+uniform vec4 curve_mapping_ext_in_x;
+uniform vec4 curve_mapping_ext_in_y;
+uniform vec4 curve_mapping_ext_out_x;
+uniform vec4 curve_mapping_ext_out_y;
+uniform vec4 curve_mapping_first_x;
+uniform vec4 curve_mapping_first_y;
+uniform vec4 curve_mapping_last_x;
+uniform vec4 curve_mapping_last_y;
+uniform vec3 curve_mapping_black;
+uniform vec3 curve_mapping_bwmul;
+
+float read_curve_mapping(int table, int index)
+{
+	/* TODO(sergey): Without -1 here image is getting darken after applying unite curve.
+	 *               But is it actually correct to subtract 1 here?
+	 */
+	float texture_index = float(index) / float(curve_mapping_lut_size  - 1);
+	return texture1D(curve_mapping_texture, texture_index) [table];
+}
+
+float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
+{
+	if (x <= first[0]) {
+		if (use_curve_mapping_extend_extrapolate[table] == 0) {
+			/* no extrapolate */
+			return first[1];
+		}
+		else {
+			if (curve_mapping_ext_in_x[table] == 0.0)
+				return first[1] + curve_mapping_ext_in_y[table] * 10000.0;
+			else
+				return first[1] + curve_mapping_ext_in_y[table] * (x - first[0]) / curve_mapping_ext_in_x[table];
+		}
+	}
+	else if (x >= last[0]) {
+		if (use_curve_mapping_extend_extrapolate[table] == 0) {
+			/* no extrapolate */
+			return last[1];
+		}
+		else {
+			if (curve_mapping_ext_out_x[table] == 0.0)
+				return last[1] - curve_mapping_ext_out_y[table] * 10000.0;
+			else
+				return last[1] + curve_mapping_ext_out_y[table] * (x - last[0]) / curve_mapping_ext_out_x[table];
+		}
+	}
+	return 0.0;
+}
+
+float curvemap_evaluateF(int table, float value)
+{
+	float mintable_ = curve_mapping_mintable[table];
+	float range = curve_mapping_range[table];
+	float mintable = 0.0;
+	int CM_TABLE = curve_mapping_lut_size - 1;
+
+	float fi;
+	int i;
+
+	/* index in table */
+	fi = (value - mintable) * range;
+	i = int(fi);
+
+	/* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */
+	if (fi < 0.0 || fi > float(CM_TABLE)) {
+		return curvemap_calc_extend(table, value,
+		                            vec2(curve_mapping_first_x[table], curve_mapping_first_y[table]),
+		                            vec2(curve_mapping_last_x[table], curve_mapping_last_y[table]));
+	}
+	else {
+		if (i < 0) return read_curve_mapping(table, 0);
+		if (i >= CM_TABLE) return read_curve_mapping(table, CM_TABLE);
+
+		fi = fi - float(i);
+		return (1.0 - fi) * read_curve_mapping(table, i) + fi * read_curve_mapping(table, i + 1);
+	}
+}
+
+vec4 curvemapping_evaluate_premulRGBF(vec4 col)
+{
+	vec4 result = col;
+	result[0] = curvemap_evaluateF(0, (col[0] - curve_mapping_black[0]) * curve_mapping_bwmul[0]);
+	result[1] = curvemap_evaluateF(1, (col[1] - curve_mapping_black[1]) * curve_mapping_bwmul[1]);
+	result[2] = curvemap_evaluateF(2, (col[2] - curve_mapping_black[2]) * curve_mapping_bwmul[2]);
+	result[3] = col[3];
+	return result;
+}
+#endif
+
+void main()
+{
+	vec4 col = texture2D(image_texture, gl_TexCoord[0].st);
+#ifdef USE_CURVE_MAPPING
+	col = curvemapping_evaluate_premulRGBF(col);
+#endif
+	if (predivide && col[3] > 0.0 && col[3] < 1.0) {
+		float inv_alpha = 1.0 / col[3];
+		col[0] *= inv_alpha;
+		col[1] *= inv_alpha;
+		col[2] *= inv_alpha;
+	}
+
+	/* NOTE: This is true we only do de-premul here and NO premul
+	 *       and the reason is simple -- opengl is always configured
+	 *       for straight alpha at this moment
+	 */
+	gl_FragColor = OCIODisplay(col, lut3d_texture);
+}

Modified: trunk/blender/intern/opencolorio/ocio_capi.cc
===================================================================
--- trunk/blender/intern/opencolorio/ocio_capi.cc	2013-10-09 15:51:14 UTC (rev 60631)
+++ trunk/blender/intern/opencolorio/ocio_capi.cc	2013-10-09 15:57:32 UTC (rev 60632)
@@ -323,9 +323,10 @@
 	return (int) impl->supportGLSLDraw();
 }
 
-int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide)
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+                       OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide)
 {
-	return (int) impl->setupGLSLDraw(state_r, processor, (bool) predivide);
+	return (int) impl->setupGLSLDraw(state_r, processor, curve_mapping_settings, predivide);
 }
 
 void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)

Modified: trunk/blender/intern/opencolorio/ocio_capi.h
===================================================================
--- trunk/blender/intern/opencolorio/ocio_capi.h	2013-10-09 15:51:14 UTC (rev 60631)
+++ trunk/blender/intern/opencolorio/ocio_capi.h	2013-10-09 15:57:32 UTC (rev 60632)
@@ -54,6 +54,62 @@
 OCIO_DECLARE_HANDLE(OCIO_MatrixTransformRcPtr);
 OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr);
 
+/* This structure is used to pass curve mapping settings from
+ * blender's DNA structure stored in view transform settings
+ * to a generic OpenColorIO C-API.
+ */
+typedef struct OCIO_CurveMappingSettings {
+	/* This is a LUT which contain values for all 4 curve mapping tables
+	 * (combined, R, G and B).
+	 *
+	 * Element I for table T is stored at I * 4 + T element of this LUT.
+	 *
+	 * This array is usually returned by curvemapping_table_RGBA().
+	 */
+	float *lut;
+
+	/* Size of single curve mapping table, 1/4 size of lut array. */
+	int lut_size;
+
+	/* Extend extrapolation flags for all the tables.
+	 * if use_extend_extrapolate[T] != 0 means extrapolation for
+	 * table T is needed.
+	 */
+	int use_extend_extrapolate[4];
+
+	/* Minimal X value of the curve mapping tables. */
+	float mintable[4];
+
+	/* Per curve mapping table range. */
+	float range[4];
+
+	/* Lower extension value, stored as per-component arrays. */
+	float ext_in_x[4], ext_in_y[4];
+
+	/* Higher extension value, stored as per-component arrays. */
+	float ext_out_x[4], ext_out_y[4];
+
+	/* First points of the tables, both X and Y values.
+	 * Needed for easier and faster access when extrapolating.
+	 */
+	float first_x[4], first_y[4];
+
+	/* Last points of the tables, both X and Y values.
+	 * Needed for easier and faster access when extrapolating.
+	 */
+	float last_x[4], last_y[4];
+
+	/* Premultiplication settings: black level and scale to match
+	 * with white level.
+	 */
+	float black[3], bwmul[3];
+
+	/* Cache id of the original curve mapping, used to detect when
+	 * upload of new settings to GPU is needed.
+	 */
+	size_t cache_id;
+} OCIO_CurveMappingSettings;
+
 void OCIO_init(void);
 void OCIO_exit(void);
 
@@ -132,7 +188,8 @@
 void OCIO_matrixTransformScale(float *m44, float *offset4, const float *scale4);
 
 int OCIO_supportGLSLDraw(void);
-int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide);
+int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
+                       OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
 void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
 void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
 

Modified: trunk/blender/intern/opencolorio/ocio_impl.h

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list