[Bf-blender-cvs] [5a91df3] master: Implement GPU-side dither

Sergey Sharybin noreply at git.blender.org
Fri Dec 13 07:36:48 CET 2013


Commit: 5a91df32713b7ad9be6befa7124b31890063d91b
Author: Sergey Sharybin
Date:   Fri Dec 13 12:36:45 2013 +0600
http://developer.blender.org/rB5a91df32713b7ad9be6befa7124b31890063d91b

Implement GPU-side dither

Summary:
Uses some magic pseudo-random which is actually a
texture coordinate hashing function.

TODOs:
- Dither noise is the same for all the frames.
- It's different from Floyd's dither we've been
  using before.
- Currently CPU and GPU dithering used different
  implementation. Ideally we need to use the same
  dither in CPU.

Reviewers: brecht

Reviewed By: brecht

Differential Revision: http://developer.blender.org/D58

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

M	intern/opencolorio/fallback_impl.cc
M	intern/opencolorio/gpu_shader_display_transform.glsl
M	intern/opencolorio/ocio_capi.cc
M	intern/opencolorio/ocio_capi.h
M	intern/opencolorio/ocio_impl.h
M	intern/opencolorio/ocio_impl_glsl.cc
M	source/blender/editors/render/render_internal.c
M	source/blender/editors/screen/glutil.c
M	source/blender/editors/space_sequencer/sequencer_draw.c
M	source/blender/imbuf/IMB_colormanagement.h
M	source/blender/imbuf/intern/colormanagement.c
M	source/blender/imbuf/intern/divers.c
M	source/blender/makesrna/intern/rna_render.c

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

diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index 6383bbb..c0797cb 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -419,7 +419,8 @@ bool FallbackImpl::supportGLSLDraw(void)
 }
 
 bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/,
-                                 OCIO_CurveMappingSettings * /*curve_mapping_settings*/, bool /*predivide*/)
+                                 OCIO_CurveMappingSettings * /*curve_mapping_settings*/,
+                                 float /*dither*/,  bool /*predivide*/)
 {
 	return false;
 }
diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
index 6ba3fa5..8a85d6c 100644
--- a/intern/opencolorio/gpu_shader_display_transform.glsl
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -2,6 +2,10 @@ uniform sampler2D image_texture;
 uniform sampler3D lut3d_texture;
 uniform bool predivide;
 
+#ifdef USE_DITHER
+uniform float dither;
+#endif
+
 #ifdef USE_CURVE_MAPPING
 /* Curve mapping parameters
  *
@@ -102,6 +106,33 @@ vec4 curvemapping_evaluate_premulRGBF(vec4 col)
 }
 #endif
 
+#ifdef USE_DITHER
+float dither_random_value(vec2 co)
+{
+	return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453) * 0.005 * dither;
+}
+
+vec2 round_to_pixel(vec2 st)
+{
+	vec2 result;
+	vec2 size = textureSize(image_texture, 0);
+	result.x = float(int(st.x * size.x)) / size.x;
+	result.y = float(int(st.y * size.y)) / size.y;
+	return result;
+}
+
+vec4 apply_dither(vec2 st, vec4 col)
+{
+	vec4 result;
+	float random_value = dither_random_value(round_to_pixel(st));
+	result.r = col.r + random_value;
+	result.g = col.g + random_value;
+	result.b = col.b + random_value;
+	result.a = col.a;
+	return result;
+}
+#endif
+
 void main()
 {
 	vec4 col = texture2D(image_texture, gl_TexCoord[0].st);
@@ -119,5 +150,12 @@ void main()
 	 *       and the reason is simple -- opengl is always configured
 	 *       for straight alpha at this moment
 	 */
-	gl_FragColor = OCIODisplay(col, lut3d_texture);
+
+	vec4 result = OCIODisplay(col, lut3d_texture);
+
+#ifdef USE_DITHER
+	result = apply_dither(gl_TexCoord[0].st, result);
+#endif
+
+	gl_FragColor = result;
 }
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 47ee3af..a4f2db4 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -324,9 +324,9 @@ int OCIO_supportGLSLDraw(void)
 }
 
 int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
-                       OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide)
+                       OCIO_CurveMappingSettings *curve_mapping_settings, float dither, bool predivide)
 {
-	return (int) impl->setupGLSLDraw(state_r, processor, curve_mapping_settings, predivide);
+	return (int) impl->setupGLSLDraw(state_r, processor, curve_mapping_settings, dither, predivide);
 }
 
 void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state)
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 5abe104..d667dec 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -189,7 +189,7 @@ 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,
-                       OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
+                       OCIO_CurveMappingSettings *curve_mapping_settings, float dither, bool predivide);
 void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state);
 void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state);
 
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 4e7c1bc..47e6d82 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -107,7 +107,7 @@ public:
 
 	virtual bool supportGLSLDraw(void) = 0;
 	virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
-	                           OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide) = 0;
+	                           OCIO_CurveMappingSettings *curve_mapping_settings, float dither, bool predivide) = 0;
 	virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0;
 	virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0;
 
@@ -194,7 +194,7 @@ public:
 
 	bool supportGLSLDraw(void);
 	bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
-	                   OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
+	                   OCIO_CurveMappingSettings *curve_mapping_settings, float dither, bool predivide);
 	void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
 	void freeGLState(struct OCIO_GLSLDrawState *state_r);
 
@@ -282,7 +282,7 @@ public:
 
 	bool supportGLSLDraw(void);
 	bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
-	                   OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide);
+	                   OCIO_CurveMappingSettings *curve_mapping_settings, float dither, bool predivide);
 	void finishGLSLDraw(struct OCIO_GLSLDrawState *state);
 	void freeGLState(struct OCIO_GLSLDrawState *state_r);
 
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index 2af3bef..3a23c26 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -33,6 +33,7 @@
  *
  */
 
+#include <limits>
 #include <sstream>
 #include <string.h>
 
@@ -62,6 +63,8 @@ typedef struct OCIO_GLSLDrawState {
 
 	float *lut3d;  /* 3D LUT table */
 
+	bool dither_used;
+
 	bool curve_mapping_used;
 	bool curve_mapping_texture_allocated;
 	bool curve_mapping_texture_valid;
@@ -229,10 +232,12 @@ bool OCIOImpl::supportGLSLDraw()
  * restore OpenGL context to it's pre-GLSL draw state.
  */
 bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor,
-                             OCIO_CurveMappingSettings *curve_mapping_settings, bool predivide)
+                             OCIO_CurveMappingSettings *curve_mapping_settings,
+                             float dither, bool predivide)
 {
 	ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor;
 	bool use_curve_mapping = curve_mapping_settings != NULL;
+	bool use_dither = dither > std::numeric_limits<float>::epsilon();
 
 	/* Create state if needed. */
 	OCIO_GLSLDrawState *state;
@@ -267,7 +272,7 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 
 	/* Step 1: Create a GPU Shader Description */
 	GpuShaderDesc shaderDesc;
-	shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_0);
+	shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_3);
 	shaderDesc.setFunctionName("OCIODisplay");
 	shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE);
 
@@ -297,7 +302,8 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 	std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc);
 	if (state->program == 0 ||
 	    shaderCacheID != state->shadercacheid ||
-	    use_curve_mapping != state->curve_mapping_used)
+	    use_curve_mapping != state->curve_mapping_used ||
+	    use_dither != state->dither_used)
 	{
 		state->shadercacheid = shaderCacheID;
 
@@ -311,6 +317,12 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 
 		std::ostringstream os;
 
+		os << "#version 130\n";
+
+		if (use_dither) {
+			os << "#define USE_DITHER\n";
+		}
+
 		if (use_curve_mapping) {
 			os << "#define USE_CURVE_MAPPING\n";
 		}
@@ -325,6 +337,7 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 		}
 
 		state->curve_mapping_used = use_curve_mapping;
+		state->dither_used = use_dither;
 	}
 
 	if (state->program) {
@@ -344,6 +357,10 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
 		glUniform1i(glGetUniformLocation(state->program, "lut3d_texture"), 1);
 		glUniform1i(glGetUniformLocation(state->program, "predivide"), predivide);
 
+		if (use_dither) {
+			glUniform1f(glGetUniformLocation(state->program, "dither"), dither);
+		}
+
 		if (use_curve_mapping) {
 			glUniform1i(glGetUniformLocation(state->program, "curve_mapping_texture"), 2);
 			glUniform1i(glGetUniformLocation(state->program, "curve_mapping_lut_size"), curve_mapping_settings->lut_size);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index e1a271e..1b090cb 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -1150,7 +1150,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
 
 		/* Try using GLSL display transform. */
 		if (force_fallback == false) {
-			if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, true)) {
+			if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, 0.0f, true)) {
 				glEnable(GL_BLEND);
 				glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 				glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT,
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 57d9717..af5f9d3 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -1044,9 +1044,6 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
 	if (ibuf->rect == NULL && ibuf->rect_float == NULL)
 		return;
 
-	/* Dithering is not supported on GLSL yet */
-	force_fallback |= ibuf->dither != 0.0f;
-
 	/* Single channel images could not be transformed using GLSL yet */
 	force_fallback |= ibuf->channels == 1;
 
@@ -1093,15 +1090,18 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
 		if (ibuf->rect_float) {
 			if (ibuf->float_colorspace) {
 				ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, displa

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list