diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-12-13 10:36:45 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-12-13 10:36:45 +0400 |
commit | 5a91df32713b7ad9be6befa7124b31890063d91b (patch) | |
tree | 11309c67510bb0ffd29438318896cf86b8024c02 | |
parent | 669b5902298f0f80159395d020657d6630a532ac (diff) |
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
-rw-r--r-- | intern/opencolorio/fallback_impl.cc | 3 | ||||
-rw-r--r-- | intern/opencolorio/gpu_shader_display_transform.glsl | 40 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.cc | 4 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.h | 2 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl.h | 6 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl_glsl.cc | 23 | ||||
-rw-r--r-- | source/blender/editors/render/render_internal.c | 2 | ||||
-rw-r--r-- | source/blender/editors/screen/glutil.c | 12 | ||||
-rw-r--r-- | source/blender/editors/space_sequencer/sequencer_draw.c | 6 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_colormanagement.h | 9 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 19 | ||||
-rw-r--r-- | source/blender/imbuf/intern/divers.c | 104 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_render.c | 1 |
13 files changed, 138 insertions, 93 deletions
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 6383bbbb07f..c0797cbc37f 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 6ba3fa55e8f..8a85d6cbffe 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 47ee3afddfd..a4f2db456e8 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 5abe104fcd4..d667dece62a 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 4e7c1bcc832..47e6d829902 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 2af3befc8a9..3a23c266345 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 e1a271e996b..1b090cb16ec 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 57d97178be5..af5f9d3c875 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, display_settings, - ibuf->float_colorspace, true); + ibuf->float_colorspace, + ibuf->dither, true); } else { - ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, true); + ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, + ibuf->dither, true); } } else { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - ibuf->rect_colorspace, false); + ibuf->rect_colorspace, + ibuf->dither, false); } if (ok) { diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index cb69a7fe654..267b070fd42 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1086,10 +1086,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq type = GL_FLOAT; if (ibuf->float_colorspace) { - glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, true); + glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, ibuf->dither, true); } else { - glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, true); + glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true); } } else if (ibuf->rect) { @@ -1097,7 +1097,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq format = GL_RGBA; type = GL_UNSIGNED_BYTE; - glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, false); + glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, ibuf->dither, false); } else { format = GL_RGBA; diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 09cdb3a4ee9..7e115b265de 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -178,16 +178,17 @@ bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings /* Configures GLSL shader for conversion from scene linear to display space */ bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, - bool predivide); + float dither, bool predivide); /* Same as above, but display space conversion happens from a specified space */ bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, struct ColorSpace *colorspace, - bool predivide); + float dither, bool predivide); /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ -bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, bool predivide); +bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, float dither, bool predivide); /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ -bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, bool predivide); +bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, + float dither, bool predivide); /* Finish GLSL-based display space conversion */ void IMB_colormanagement_finish_glsl_draw(void); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 3c1a96e4005..a2e2fab7ba1 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -3091,7 +3091,8 @@ bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSE */ bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - struct ColorSpace *from_colorspace, bool predivide) + struct ColorSpace *from_colorspace, + float dither, bool predivide) { ColorManagedViewSettings default_view_settings; const ColorManagedViewSettings *applied_view_settings; @@ -3114,33 +3115,35 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettin return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL, - predivide); + dither, predivide); } /* Configures GLSL shader for conversion from scene linear to display space */ bool IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - bool predivide) + float dither, bool predivide) { return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - NULL, predivide); + NULL, dither, predivide); } /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ -bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, bool predivide) +bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const bContext *C, struct ColorSpace *from_colorspace, + float dither, bool predivide) { ColorManagedViewSettings *view_settings; ColorManagedDisplaySettings *display_settings; IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); - return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide); + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, + dither, predivide); } /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ -bool IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, bool predivide) +bool IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, float dither, bool predivide) { - return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, predivide); + return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, dither, predivide); } /* Finish GLSL-based display space conversion */ diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index af9f7109106..a3647c7b45b 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -31,7 +31,6 @@ * \ingroup imbuf */ -#include "BLI_rand.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -107,63 +106,33 @@ void IMB_interlace(ImBuf *ibuf) /************************* Floyd-Steinberg dithering *************************/ typedef struct DitherContext { - int *error_buf, *e; - int v[4], v0[4], v1[4]; - float f; + float dither; } DitherContext; -static DitherContext *create_dither_context(int w, float factor) +static DitherContext *create_dither_context(float dither) { DitherContext *di; - int i; - - di = MEM_callocN(sizeof(DitherContext), "dithering context"); - di->f = factor / 16.0f; - di->error_buf = MEM_callocN(4 * (w + 1) * sizeof(int), "dithering error"); - di->e = di->error_buf; - for (i = 0; i < 4; ++i) - di->v[i] = di->v0[i] = di->v1[i] = 1024.0f * (BLI_frand() - 0.5f); + di = MEM_mallocN(sizeof(DitherContext), "dithering context"); + di->dither = dither; return di; } static void clear_dither_context(DitherContext *di) { - MEM_freeN(di->error_buf); MEM_freeN(di); } -static void dither_finish_row(DitherContext *di) +MINLINE float dither_random_value(float s, float t) { - int i; - - for (i = 0; i < 4; i++) - di->v[i] = di->v0[i] = di->v1[i] = 0; + static float vec[2] = {12.9898f, 78.233f}; + float st[2]; + float value; + copy_v2_fl2(st, s, t); - di->e = di->error_buf; -} - -MINLINE unsigned char dither_value(unsigned short v_in, DitherContext *di, int i) -{ - int dv, d2; - unsigned char v_out; - - di->v[i] = v_in + (2 * di->v[i] + di->e[4]) * di->f; - CLAMP(di->v[i], 0, 0xFF00); - v_out = USHORTTOUCHAR(di->v[i]); - di->v[i] -= v_out << 8; - dv = di->v[i]; - d2 = di->v[i] << 1; - di->v[i] += d2; - *(di->e++) = di->v[i] + di->v0[i]; - di->v[i] += d2; - - di->v0[i] = di->v[i] + di->v1[i]; - di->v1[i] = dv; - di->v[i] += d2; - - return v_out; + value = sinf(dot_v2v2(st, vec)) * 43758.5453f; + return value - floor(value); } /************************* Generic Buffer Conversion *************************/ @@ -176,18 +145,32 @@ MINLINE void ushort_to_byte_v4(uchar b[4], const unsigned short us[4]) b[3] = USHORTTOUCHAR(us[3]); } -MINLINE void ushort_to_byte_dither_v4(uchar b[4], const unsigned short us[4], DitherContext *di) +MINLINE unsigned char ftochar(float value) +{ + return FTOCHAR(value); +} + +MINLINE void ushort_to_byte_dither_v4(uchar b[4], const unsigned short us[4], DitherContext *di, float s, float t) { - b[0] = dither_value(us[0], di, 0); - b[1] = dither_value(us[1], di, 1); - b[2] = dither_value(us[2], di, 2); - b[3] = dither_value(us[3], di, 3); +#define USHORTTOFLOAT(val) ((float)val / 65535.0f) + float dither_value = dither_random_value(s, t) * 0.005f * di->dither; + + b[0] = ftochar(dither_value + USHORTTOFLOAT(us[0])); + b[1] = ftochar(dither_value + USHORTTOFLOAT(us[1])); + b[2] = ftochar(dither_value + USHORTTOFLOAT(us[2])); + b[3] = USHORTTOUCHAR(us[3]); + +#undef USHORTTOFLOAT } -MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext *di) +MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext *di, float s, float t) { - unsigned short us[4] = {FTOUSHORT(f[0]), FTOUSHORT(f[1]), FTOUSHORT(f[2]), FTOUSHORT(f[3])}; - ushort_to_byte_dither_v4(b, us, di); + float dither_value = dither_random_value(s, t) * 0.005f * di->dither; + + b[0] = ftochar(dither_value + f[0]); + b[1] = ftochar(dither_value + f[1]); + b[2] = ftochar(dither_value + f[2]); + b[3] = FTOCHAR(f[3]); } /* float to byte pixels, output 4-channel RGBA */ @@ -198,15 +181,19 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, float tmp[4]; int x, y; DitherContext *di = NULL; + float inv_width = 1.0f / width, + inv_height = 1.0f / height; /* we need valid profiles */ BLI_assert(profile_to != IB_PROFILE_NONE); BLI_assert(profile_from != IB_PROFILE_NONE); if (dither) - di = create_dither_context(width, dither); + di = create_dither_context(dither); for (y = 0; y < height; y++) { + float t = y * inv_height; + if (channels_from == 1) { /* single channel input */ const float *from = rect_from + stride_from * y; @@ -256,12 +243,12 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { premul_to_straight_v4_v4(straight, from); - float_to_byte_dither_v4(to, straight, di); + float_to_byte_dither_v4(to, straight, di, (float) x * inv_width, t); } } else if (dither) { for (x = 0; x < width; x++, from += 4, to += 4) - float_to_byte_dither_v4(to, from, di); + float_to_byte_dither_v4(to, from, di, (float) x * inv_width, t); } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { @@ -283,13 +270,13 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, for (x = 0; x < width; x++, from += 4, to += 4) { premul_to_straight_v4_v4(straight, from); linearrgb_to_srgb_ushort4(us, from); - ushort_to_byte_dither_v4(to, us, di); + ushort_to_byte_dither_v4(to, us, di, (float) x * inv_width, t); } } else if (dither) { for (x = 0; x < width; x++, from += 4, to += 4) { linearrgb_to_srgb_ushort4(us, from); - ushort_to_byte_dither_v4(to, us, di); + ushort_to_byte_dither_v4(to, us, di, (float) x * inv_width, t); } } else if (predivide) { @@ -311,13 +298,13 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_predivide_v4(tmp, from); - float_to_byte_dither_v4(to, tmp, di); + float_to_byte_dither_v4(to, tmp, di, (float) x * inv_width, t); } } else if (dither) { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_v4(tmp, from); - float_to_byte_dither_v4(to, tmp, di); + float_to_byte_dither_v4(to, tmp, di, (float) x * inv_width, t); } } else if (predivide) { @@ -334,9 +321,6 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, } } } - - if (dither) - dither_finish_row(di); } if (dither) diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 9c3c6ce6c04..854275ccb64 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -73,6 +73,7 @@ static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene { IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, + scene->r.dither_intensity, false); } |