/* update rectangular section of the brush image */ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf, int origx, int origy, int w, int h, int xt, int yt) { Scene *scene = painter->scene; Brush *brush = painter->brush; rctf tex_mapping = painter->tex_mapping; rctf mask_mapping = painter->mask_mapping; struct ImagePool *pool = painter->pool; bool use_masking = painter->cache.use_masking; bool use_color_correction = painter->cache.use_color_correction; bool use_float = painter->cache.use_float; bool is_texbrush = painter->cache.is_texbrush; bool is_maskbrush = painter->cache.is_maskbrush; bool use_texture_old = (oldtexibuf != NULL); int x, y, thread = 0; float brush_rgb[3]; ImBuf *ibuf = painter->cache.ibuf; ImBuf *texibuf = painter->cache.texibuf; unsigned short *mask = painter->cache.mask; /* get brush color */ if (brush->imagepaint_tool == PAINT_TOOL_DRAW) { copy_v3_v3(brush_rgb, brush->rgb); if (use_color_correction) srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb); } else { brush_rgb[0] = 1.0f; brush_rgb[1] = 1.0f; brush_rgb[2] = 1.0f; } /* fill pixes */ for (y = origy; y < h; y++) { for (x = origx; x < w; x++) { /* sample texture and multiply with brush color */ float texco[3], rgba[4]; if (!use_texture_old) { if (is_texbrush) { brush_imbuf_tex_co(&tex_mapping, x, y, texco); BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); /* TODO(sergey): Support texture paint color space. */ if (!use_float) { linearrgb_to_srgb_v3_v3(rgba, rgba); } mul_v3_v3(rgba, brush_rgb); } else { copy_v3_v3(rgba, brush_rgb); rgba[3] = 1.0f; } if (is_maskbrush) { brush_imbuf_tex_co(&mask_mapping, x, y, texco); rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool); } } if (use_float) { /* handle float pixel */ float *bf = ibuf->rect_float + (y * ibuf->x + x) * 4; float *tf = texibuf->rect_float + (y * texibuf->x + x) * 4; /* read from old texture buffer */ if (use_texture_old) { float *otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4; copy_v4_v4(rgba, otf); } /* write to new texture buffer */ copy_v4_v4(tf, rgba); /* if not using masking, multiply in the mask now */ if (!use_masking) { unsigned short *m = mask + (y * ibuf->x + x); rgba[3] *= *m * (1.0f / 65535.0f); } /* output premultiplied float image, mf was already premultiplied */ mul_v3_v3fl(bf, rgba, rgba[3]); bf[3] = rgba[3]; } else { unsigned char crgba[4]; /* handle byte pixel */ unsigned char *b = (unsigned char *)ibuf->rect + (y * ibuf->x + x) * 4; unsigned char *t = (unsigned char *)texibuf->rect + (y * texibuf->x + x) * 4; /* read from old texture buffer */ if (use_texture_old) { unsigned char *ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4; crgba[0] = ot[0]; crgba[1] = ot[1]; crgba[2] = ot[2]; crgba[3] = ot[3]; } else rgba_float_to_uchar(crgba, rgba); /* write to new texture buffer */ t[0] = crgba[0]; t[1] = crgba[1]; t[2] = crgba[2]; t[3] = crgba[3]; /* if not using masking, multiply in the mask now */ if (!use_masking) { unsigned short *m = mask + (y * ibuf->x + x); crgba[3] = (crgba[3] * (*m)) / 65535; } /* write to brush image buffer */ b[0] = crgba[0]; b[1] = crgba[1]; b[2] = crgba[2]; b[3] = crgba[3]; } } } }
/* update rectangular section of the brush image */ static void brush_painter_imbuf_update(BrushPainter *painter, ImBuf *oldtexibuf, int origx, int origy, int w, int h, int xt, int yt) { Scene *scene = painter->scene; Brush *brush = painter->brush; const char *display_device = scene->display_settings.display_device; struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); rctf tex_mapping = painter->tex_mapping; struct ImagePool *pool = painter->pool; bool use_color_correction = painter->cache.use_color_correction; bool use_float = painter->cache.use_float; bool is_texbrush = painter->cache.is_texbrush; bool use_texture_old = (oldtexibuf != NULL); int x, y, thread = 0; float brush_rgb[3]; ImBuf *ibuf = painter->cache.ibuf; ImBuf *texibuf = painter->cache.texibuf; /* get brush color */ if (brush->imagepaint_tool == PAINT_TOOL_DRAW) { paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, 0.0, 1.0, brush_rgb, display); } else { brush_rgb[0] = 1.0f; brush_rgb[1] = 1.0f; brush_rgb[2] = 1.0f; } /* fill pixels */ for (y = origy; y < h; y++) { for (x = origx; x < w; x++) { /* sample texture and multiply with brush color */ float texco[3], rgba[4]; if (!use_texture_old) { if (is_texbrush) { brush_imbuf_tex_co(&tex_mapping, x, y, texco); BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); /* TODO(sergey): Support texture paint color space. */ if (!use_float) { IMB_colormanagement_scene_linear_to_display_v3(rgba, display); } mul_v3_v3(rgba, brush_rgb); } else { copy_v3_v3(rgba, brush_rgb); rgba[3] = 1.0f; } } if (use_float) { /* handle float pixel */ float *bf = ibuf->rect_float + (y * ibuf->x + x) * 4; float *tf = texibuf->rect_float + (y * texibuf->x + x) * 4; /* read from old texture buffer */ if (use_texture_old) { const float *otf = oldtexibuf->rect_float + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4; copy_v4_v4(rgba, otf); } /* write to new texture buffer */ copy_v4_v4(tf, rgba); /* output premultiplied float image, mf was already premultiplied */ mul_v3_v3fl(bf, rgba, rgba[3]); bf[3] = rgba[3]; } else { unsigned char crgba[4]; /* handle byte pixel */ unsigned char *b = (unsigned char *)ibuf->rect + (y * ibuf->x + x) * 4; unsigned char *t = (unsigned char *)texibuf->rect + (y * texibuf->x + x) * 4; /* read from old texture buffer */ if (use_texture_old) { unsigned char *ot = (unsigned char *)oldtexibuf->rect + ((y - origy + yt) * oldtexibuf->x + (x - origx + xt)) * 4; crgba[0] = ot[0]; crgba[1] = ot[1]; crgba[2] = ot[2]; crgba[3] = ot[3]; } else rgba_float_to_uchar(crgba, rgba); /* write to new texture buffer */ t[0] = crgba[0]; t[1] = crgba[1]; t[2] = crgba[2]; t[3] = crgba[3]; /* write to brush image buffer */ b[0] = crgba[0]; b[1] = crgba[1]; b[2] = crgba[2]; b[3] = crgba[3]; } } } }
/* create imbuf with brush color */ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size) { Scene *scene = painter->scene; Brush *brush = painter->brush; rctf tex_mapping = painter->tex_mapping; rctf mask_mapping = painter->mask_mapping; struct ImagePool *pool = painter->pool; bool use_masking = painter->cache.use_masking; bool use_color_correction = painter->cache.use_color_correction; bool use_float = painter->cache.use_float; bool is_texbrush = painter->cache.is_texbrush; bool is_maskbrush = painter->cache.is_maskbrush; float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush); int radius = BKE_brush_size_get(scene, brush); int xoff = -size * 0.5f + 0.5f; int yoff = -size * 0.5f + 0.5f; int x, y, thread = 0; float brush_rgb[3]; /* allocate image buffer */ ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect); /* get brush color */ if (brush->imagepaint_tool == PAINT_TOOL_DRAW) { copy_v3_v3(brush_rgb, brush->rgb); if (use_color_correction) srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb); } else { brush_rgb[0] = 1.0f; brush_rgb[1] = 1.0f; brush_rgb[2] = 1.0f; } /* fill image buffer */ for (y = 0; y < size; y++) { for (x = 0; x < size; x++) { /* sample texture and multiply with brush color */ float texco[3], rgba[4]; if (is_texbrush) { brush_imbuf_tex_co(&tex_mapping, x, y, texco); BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); /* TODO(sergey): Support texture paint color space. */ if (!use_float) { linearrgb_to_srgb_v3_v3(rgba, rgba); } mul_v3_v3(rgba, brush_rgb); } else { copy_v3_v3(rgba, brush_rgb); rgba[3] = 1.0f; } if (is_maskbrush) { brush_imbuf_tex_co(&mask_mapping, x, y, texco); rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool); } /* when not using masking, multiply in falloff and strength */ if (!use_masking) { float xy[2] = {x + xoff, y + yoff}; float len = len_v2(xy); rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius); } if (use_float) { /* write to float pixel */ float *dstf = ibuf->rect_float + (y * size + x) * 4; mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */ dstf[3] = rgba[3]; } else { /* write to byte pixel */ unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4; rgb_float_to_uchar(dst, rgba); dst[3] = FTOCHAR(rgba[3]); } } } return ibuf; }
/* create imbuf with brush color */ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size, float pressure, float distance) { Scene *scene = painter->scene; Brush *brush = painter->brush; const char *display_device = scene->display_settings.display_device; struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); rctf tex_mapping = painter->tex_mapping; struct ImagePool *pool = painter->pool; bool use_color_correction = painter->cache.use_color_correction; bool use_float = painter->cache.use_float; bool is_texbrush = painter->cache.is_texbrush; int x, y, thread = 0; float brush_rgb[3]; /* allocate image buffer */ ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect); /* get brush color */ if (brush->imagepaint_tool == PAINT_TOOL_DRAW) { paint_brush_color_get(scene, brush, use_color_correction, painter->cache.invert, distance, pressure, brush_rgb, display); } else { brush_rgb[0] = 1.0f; brush_rgb[1] = 1.0f; brush_rgb[2] = 1.0f; } /* fill image buffer */ for (y = 0; y < size; y++) { for (x = 0; x < size; x++) { /* sample texture and multiply with brush color */ float texco[3], rgba[4]; if (is_texbrush) { brush_imbuf_tex_co(&tex_mapping, x, y, texco); BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); /* TODO(sergey): Support texture paint color space. */ if (!use_float) { IMB_colormanagement_scene_linear_to_display_v3(rgba, display); } mul_v3_v3(rgba, brush_rgb); } else { copy_v3_v3(rgba, brush_rgb); rgba[3] = 1.0f; } if (use_float) { /* write to float pixel */ float *dstf = ibuf->rect_float + (y * size + x) * 4; mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */ dstf[3] = rgba[3]; } else { /* write to byte pixel */ unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4; rgb_float_to_uchar(dst, rgba); dst[3] = FTOCHAR(rgba[3]); } } } return ibuf; }