Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2013-12-13 10:36:45 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2013-12-13 10:36:45 +0400
commit5a91df32713b7ad9be6befa7124b31890063d91b (patch)
tree11309c67510bb0ffd29438318896cf86b8024c02 /source
parent669b5902298f0f80159395d020657d6630a532ac (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
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/screen/glutil.c12
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c6
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h9
-rw-r--r--source/blender/imbuf/intern/colormanagement.c19
-rw-r--r--source/blender/imbuf/intern/divers.c104
-rw-r--r--source/blender/makesrna/intern/rna_render.c1
7 files changed, 71 insertions, 82 deletions
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);
}