static void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *) data_v; int x, y; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int pixel_index = (y * width + x) * 4; float pixel[3], result[3], mask[3] = {1.0f, 1.0f, 1.0f}; float hsv[3], f; if (rect_float) copy_v3_v3(pixel, rect_float + pixel_index); else rgb_uchar_to_float(pixel, rect + pixel_index); rgb_to_hsv(pixel[0], pixel[1], pixel[2], hsv, hsv + 1, hsv + 2); /* adjust hue, scaling returned default 0.5 up to 1 */ f = curvemapping_evaluateF(curve_mapping, 0, hsv[0]); hsv[0] += f - 0.5f; /* adjust saturation, scaling returned default 0.5 up to 1 */ f = curvemapping_evaluateF(curve_mapping, 1, hsv[0]); hsv[1] *= (f * 2.0f); /* adjust value, scaling returned default 0.5 up to 1 */ f = curvemapping_evaluateF(curve_mapping, 2, hsv[0]); hsv[2] *= (f * 2.f); hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */ CLAMP(hsv[1], 0.0f, 1.0f); /* convert back to rgb */ hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2); if (mask_rect_float) copy_v3_v3(mask, mask_rect_float + pixel_index); else if (mask_rect) rgb_uchar_to_float(mask, mask_rect + pixel_index); result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0]; result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1]; result[2] = pixel[2] * (1.0f - mask[2]) + result[2] * mask[2]; if (rect_float) copy_v3_v3(rect_float + pixel_index, result); else rgb_float_to_uchar(rect + pixel_index, result); } } }
/* MultiresBake callback for normals' baking * general idea: * - find coord and normal of point with specified UV in hi-res mesh * - multiply it by tangmat * - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y) { MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5}; lores_dm->getTessFace(lores_dm, face_index, &mface); st0 = mtface[face_index].uv[0]; st1 = mtface[face_index].uv[1]; st2 = mtface[face_index].uv[2]; if (mface.v4) { st3 = mtface[face_index].uv[3]; resolve_quad_uv(uv, st, st0, st1, st2, st3); } else resolve_tri_uv(uv, st, st0, st1, st2); CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); get_ccgdm_data(lores_dm, hires_dm, normal_data->orig_index_mf_to_mpoly, normal_data->orig_index_mp_to_orig, lvl, face_index, uv[0], uv[1], NULL, n); mul_v3_m3v3(vec, tangmat, n); normalize_v3(vec); mul_v3_fl(vec, 0.5); add_v3_v3(vec, tmp); if (ibuf->rect_float) { float *rrgbf = ibuf->rect_float + pixel * 4; rrgbf[0] = vec[0]; rrgbf[1] = vec[1]; rrgbf[2] = vec[2]; rrgbf[3] = 1.0f; } else { unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4; rgb_float_to_uchar(rrgb, vec); rrgb[3] = 255; } }
void IMB_saturation(ImBuf *ibuf, float sat) { size_t i; unsigned char *rct = (unsigned char *)ibuf->rect; float *rct_fl = ibuf->rect_float; float hsv[3]; if (rct) { float rgb[3]; for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) { rgb_uchar_to_float(rgb, rct); rgb_to_hsv_v(rgb, hsv); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2); rgb_float_to_uchar(rct, rgb); } } if (rct_fl) { for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) { rgb_to_hsv_v(rct_fl, hsv); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2); } } }
/* 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; }
/* float to byte pixels, output 4-channel RGBA */ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, int channels_from, float dither, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from) { float tmp[4]; int x, y; DitherContext *di = NULL; float inv_width = 1.0f / width; float 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(dither); } for (y = 0; y < height; y++) { float t = y * inv_height; if (channels_from == 1) { /* single channel input */ const float *from = rect_from + ((size_t)stride_from) * y; uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) { to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]); } } else if (channels_from == 3) { /* RGB input */ const float *from = rect_from + ((size_t)stride_from) * y * 3; uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ for (x = 0; x < width; x++, from += 3, to += 4) { rgb_float_to_uchar(to, from); to[3] = 255; } } else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ for (x = 0; x < width; x++, from += 3, to += 4) { linearrgb_to_srgb_v3_v3(tmp, from); rgb_float_to_uchar(to, tmp); to[3] = 255; } } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert from sRGB to linear */ for (x = 0; x < width; x++, from += 3, to += 4) { srgb_to_linearrgb_v3_v3(tmp, from); rgb_float_to_uchar(to, tmp); to[3] = 255; } } } else if (channels_from == 4) { /* RGBA input */ const float *from = rect_from + ((size_t)stride_from) * y * 4; uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { float straight[4]; /* no color space conversion */ 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)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)x * inv_width, t); } } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { premul_to_straight_v4_v4(straight, from); rgba_float_to_uchar(to, straight); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { rgba_float_to_uchar(to, from); } } } else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ unsigned short us[4]; float straight[4]; if (dither && predivide) { 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, (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, (float)x * inv_width, t); } } else if (predivide) { 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_v4(to, us); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_v4(to, us); } } } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert from sRGB to linear */ 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)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)x * inv_width, t); } } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_predivide_v4(tmp, from); rgba_float_to_uchar(to, tmp); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_v4(tmp, from); rgba_float_to_uchar(to, tmp); } } } } } if (dither) { clear_dither_context(di); } }
/* float to byte pixels, output 4-channel RGBA */ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, int channels_from, float dither, bool predivide, int width, int height, int stride_to, int stride_from, char *mask) { int x, y; DitherContext *di = NULL; float inv_width = 1.0f / width, inv_height = 1.0f / height; if (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 + ((size_t)stride_from) * y; uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) { if (*mask++ == FILTER_MASK_USED) { to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]); } } } else if (channels_from == 3) { /* RGB input */ const float *from = rect_from + ((size_t)stride_from) * y * 3; uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from += 3, to += 4) { if (*mask++ == FILTER_MASK_USED) { rgb_float_to_uchar(to, from); to[3] = 255; } } } else if (channels_from == 4) { /* RGBA input */ const float *from = rect_from + ((size_t)stride_from) * y * 4; uchar *to = rect_to + ((size_t)stride_to) * y * 4; float straight[4]; if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { if (*mask++ == FILTER_MASK_USED) { premul_to_straight_v4_v4(straight, from); 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) { if (*mask++ == FILTER_MASK_USED) { 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) { if (*mask++ == FILTER_MASK_USED) { premul_to_straight_v4_v4(straight, from); rgba_float_to_uchar(to, straight); } } } else { for (x = 0; x < width; x++, from += 4, to += 4) { if (*mask++ == FILTER_MASK_USED) { rgba_float_to_uchar(to, from); } } } } } if (dither) { clear_dither_context(di); } }
static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) { const MPoly *mp = dm->getPolyArray(dm); const int mpoly_num = dm->getNumPolys(dm); MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); MLoopCol *finalCol; int i, j; MLoopCol *mloopcol = NULL; /* cache material values to avoid a lot of lookups */ Material *ma = NULL; short mat_nr_prev = -1; enum { COPY_CALC, COPY_ORIG, COPY_PREV, } copy_mode = COPY_CALC; if (use_mcol) { mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL); if (!mloopcol) mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL); } if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) { finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL); } else { finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer"); CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData); } for (i = mpoly_num; i--; mp++) { const short mat_nr = mp->mat_nr; if (UNLIKELY(mat_nr_prev != mat_nr)) { ma = give_current_material(Gtexdraw.ob, mat_nr + 1); copy_mode = COPY_CALC; mat_nr_prev = mat_nr; } /* avoid lookups */ if (copy_mode == COPY_ORIG) { memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); } else if (copy_mode == COPY_PREV) { int loop_index = mp->loopstart; const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart]; for (j = 0; j < mp->totloop; j++, loop_index++) { finalCol[loop_index] = *lcol_prev; } } /* (copy_mode == COPY_CALC) */ else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) { if (mloopcol) { memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); copy_mode = COPY_ORIG; } else { memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); copy_mode = COPY_PREV; } } else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw)) { int loop_index = mp->loopstart; for (j = 0; j < mp->totloop; j++, loop_index++) { finalCol[loop_index].r = 255; finalCol[loop_index].g = 0; finalCol[loop_index].b = 255; } copy_mode = COPY_PREV; } else if (ma && (ma->shade_flag & MA_OBCOLOR)) { int loop_index = mp->loopstart; for (j = 0; j < mp->totloop; j++, loop_index++) { copy_v3_v3_char((char *)&finalCol[loop_index].r, (char *)Gtexdraw.obcol); } copy_mode = COPY_PREV; } else { if (mloopcol) { memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop); copy_mode = COPY_ORIG; } else if (mtexpoly) { memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); copy_mode = COPY_PREV; } else { float col[3]; if (ma) { int loop_index = mp->loopstart; MLoopCol lcol; if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); else copy_v3_v3(col, &ma->r); rgb_float_to_uchar((unsigned char *)&lcol.r, col); lcol.a = 255; for (j = 0; j < mp->totloop; j++, loop_index++) { finalCol[loop_index] = lcol; } } else { memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop); } copy_mode = COPY_PREV; } } } }
/* 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; }
static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[3]) { unsigned char blendcol[3]; SolidColorVars *colvars = (SolidColorVars *)seq->effectdata; switch (seq->type) { case SEQ_TYPE_IMAGE: UI_GetThemeColor3ubv(TH_SEQ_IMAGE, col); break; case SEQ_TYPE_META: UI_GetThemeColor3ubv(TH_SEQ_META, col); break; case SEQ_TYPE_MOVIE: UI_GetThemeColor3ubv(TH_SEQ_MOVIE, col); break; case SEQ_TYPE_MOVIECLIP: UI_GetThemeColor3ubv(TH_SEQ_MOVIECLIP, col); break; case SEQ_TYPE_MASK: UI_GetThemeColor3ubv(TH_SEQ_MASK, col); /* TODO */ break; case SEQ_TYPE_SCENE: UI_GetThemeColor3ubv(TH_SEQ_SCENE, col); if (seq->scene == curscene) { UI_GetColorPtrShade3ubv(col, col, 20); } break; /* transitions */ case SEQ_TYPE_CROSS: case SEQ_TYPE_GAMCROSS: case SEQ_TYPE_WIPE: UI_GetThemeColor3ubv(TH_SEQ_TRANSITION, col); /* slightly offset hue to distinguish different effects */ if (seq->type == SEQ_TYPE_CROSS) rgb_byte_set_hue_float_offset(col, 0.04); if (seq->type == SEQ_TYPE_GAMCROSS) rgb_byte_set_hue_float_offset(col, 0.08); if (seq->type == SEQ_TYPE_WIPE) rgb_byte_set_hue_float_offset(col, 0.12); break; /* effects */ case SEQ_TYPE_TRANSFORM: case SEQ_TYPE_SPEED: case SEQ_TYPE_ADD: case SEQ_TYPE_SUB: case SEQ_TYPE_MUL: case SEQ_TYPE_ALPHAOVER: case SEQ_TYPE_ALPHAUNDER: case SEQ_TYPE_OVERDROP: case SEQ_TYPE_GLOW: case SEQ_TYPE_MULTICAM: case SEQ_TYPE_ADJUSTMENT: UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col); /* slightly offset hue to distinguish different effects */ if (seq->type == SEQ_TYPE_ADD) rgb_byte_set_hue_float_offset(col, 0.04); else if (seq->type == SEQ_TYPE_SUB) rgb_byte_set_hue_float_offset(col, 0.08); else if (seq->type == SEQ_TYPE_MUL) rgb_byte_set_hue_float_offset(col, 0.12); else if (seq->type == SEQ_TYPE_ALPHAOVER) rgb_byte_set_hue_float_offset(col, 0.16); else if (seq->type == SEQ_TYPE_ALPHAUNDER) rgb_byte_set_hue_float_offset(col, 0.20); else if (seq->type == SEQ_TYPE_OVERDROP) rgb_byte_set_hue_float_offset(col, 0.24); else if (seq->type == SEQ_TYPE_GLOW) rgb_byte_set_hue_float_offset(col, 0.28); else if (seq->type == SEQ_TYPE_TRANSFORM) rgb_byte_set_hue_float_offset(col, 0.36); else if (seq->type == SEQ_TYPE_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32); else if (seq->type == SEQ_TYPE_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40); break; case SEQ_TYPE_COLOR: rgb_float_to_uchar(col, colvars->col); break; case SEQ_TYPE_SOUND_RAM: UI_GetThemeColor3ubv(TH_SEQ_AUDIO, col); blendcol[0] = blendcol[1] = blendcol[2] = 128; if (seq->flag & SEQ_MUTE) UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5, 20); break; default: col[0] = 10; col[1] = 255; col[2] = 40; break; } }
static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang) { BakeShade *bs = handle; ShadeSample *ssamp = &bs->ssamp; ShadeResult shr; VlakRen *vlr = shi->vlr; shade_input_init_material(shi); if (bs->type == RE_BAKE_AO) { ambient_occlusion(shi); if (R.r.bake_flag & R_BAKE_NORMALIZE) { copy_v3_v3(shr.combined, shi->ao); } else { zero_v3(shr.combined); environment_lighting_apply(shi, &shr); } } else { if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ shi->r = shi->g = shi->b = 1.0f; shade_input_set_shade_texco(shi); /* only do AO for a full bake (and obviously AO bakes) * AO for light bakes is a leftover and might not be needed */ if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT)) shade_samples_do_AO(ssamp); if (shi->mat->nodetree && shi->mat->use_nodes) { ntreeShaderExecTree(shi->mat->nodetree, shi, &shr); shi->mat = vlr->mat; /* shi->mat is being set in nodetree */ } else shade_material_loop(shi, &shr); if (bs->type == RE_BAKE_NORMALS) { float nor[3]; copy_v3_v3(nor, shi->vn); if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) { /* pass */ } else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { float mat[3][3], imat[3][3]; /* bitangent */ if (tvn && ttang) { copy_v3_v3(mat[0], ttang); cross_v3_v3v3(mat[1], tvn, ttang); mul_v3_fl(mat[1], ttang[3]); copy_v3_v3(mat[2], tvn); } else { copy_v3_v3(mat[0], shi->nmaptang); cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang); mul_v3_fl(mat[1], shi->nmaptang[3]); copy_v3_v3(mat[2], shi->nmapnorm); } invert_m3_m3(imat, mat); mul_m3_v3(imat, nor); } else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT) mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */ else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD) mul_mat3_m4_v3(R.viewinv, nor); normalize_v3(nor); /* in case object has scaling */ /* The invert of the red channel is to make * the normal map compliant with the outside world. * It needs to be done because in Blender * the normal used in the renderer points inward. It is generated * this way in calc_vertexnormals(). Should this ever change * this negate must be removed. */ shr.combined[0] = (-nor[0]) / 2.0f + 0.5f; shr.combined[1] = nor[1] / 2.0f + 0.5f; shr.combined[2] = nor[2] / 2.0f + 0.5f; } else if (bs->type == RE_BAKE_TEXTURE) { copy_v3_v3(shr.combined, &shi->r); shr.alpha = shi->alpha; } else if (bs->type == RE_BAKE_SHADOW) { copy_v3_v3(shr.combined, shr.shad); shr.alpha = shi->alpha; } else if (bs->type == RE_BAKE_SPEC_COLOR) { copy_v3_v3(shr.combined, &shi->specr); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_SPEC_INTENSITY) { copy_v3_fl(shr.combined, shi->spec); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_MIRROR_COLOR) { copy_v3_v3(shr.combined, &shi->mirr); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_MIRROR_INTENSITY) { copy_v3_fl(shr.combined, shi->ray_mirror); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_ALPHA) { copy_v3_fl(shr.combined, shi->alpha); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_EMIT) { copy_v3_fl(shr.combined, shi->emit); shr.alpha = 1.0f; } else if (bs->type == RE_BAKE_VERTEX_COLORS) { copy_v3_v3(shr.combined, shi->vcol); shr.alpha = shi->vcol[3]; } } if (bs->rect_float && !bs->vcol) { float *col = bs->rect_float + 4 * (bs->rectx * y + x); copy_v3_v3(col, shr.combined); if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) { col[3] = shr.alpha; } else { col[3] = 1.0; } } else { /* Target is char (LDR). */ unsigned char col[4]; if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { float rgb[3]; copy_v3_v3(rgb, shr.combined); if (R.scene_color_manage) { /* Vertex colors have no way to specify color space, so they * default to sRGB. */ if (!bs->vcol) IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); else linearrgb_to_srgb_v3_v3(rgb, rgb); } rgb_float_to_uchar(col, rgb); } else { rgb_float_to_uchar(col, shr.combined); } if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) { col[3] = FTOCHAR(shr.alpha); } else { col[3] = 255; } if (bs->vcol) { /* Vertex color baking. Vcol has no useful alpha channel (it exists * but is used only for vertex painting). */ bs->vcol->r = col[0]; bs->vcol->g = col[1]; bs->vcol->b = col[2]; } else { unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x); copy_v4_v4_char((char *)imcol, (char *)col); } } if (bs->rect_mask) { bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED; } if (bs->do_update) { *bs->do_update = true; } }
static void mloopcol_from_float(MLoopCol *mloopcol, const float col[3]) { rgb_float_to_uchar((unsigned char *)&mloopcol->r, col); }
/* TODO, use define for 'texfall' arg */ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction) { ImBuf *ibuf; float xy[2], rgba[4], *dstf; int x, y, rowbytes, xoff, yoff, imbflag; const int radius = BKE_brush_size_get(scene, brush); unsigned char *dst, crgb[3]; const float alpha = BKE_brush_alpha_get(scene, brush); float brush_rgb[3]; imbflag = (flt) ? IB_rectfloat : IB_rect; xoff = -bufsize / 2.0f + 0.5f; yoff = -bufsize / 2.0f + 0.5f; rowbytes = bufsize * 4; if (*outbuf) ibuf = *outbuf; else ibuf = IMB_allocImBuf(bufsize, bufsize, 32, imbflag); if (flt) { copy_v3_v3(brush_rgb, brush->rgb); if (use_color_correction) { srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb); } for (y = 0; y < ibuf->y; y++) { dstf = ibuf->rect_float + y * rowbytes; for (x = 0; x < ibuf->x; x++, dstf += 4) { xy[0] = x + xoff; xy[1] = y + yoff; if (texfall == 0) { copy_v3_v3(dstf, brush_rgb); dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } else if (texfall == 1) { BKE_brush_sample_tex(scene, brush, xy, dstf, 0); } else { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3v3(dstf, rgba, brush_rgb); dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } } } } else { float alpha_f; /* final float alpha to convert to char */ rgb_float_to_uchar(crgb, brush->rgb); for (y = 0; y < ibuf->y; y++) { dst = (unsigned char *)ibuf->rect + y * rowbytes; for (x = 0; x < ibuf->x; x++, dst += 4) { xy[0] = x + xoff; xy[1] = y + yoff; if (texfall == 0) { alpha_f = alpha * BKE_brush_curve_strength(brush, len_v2(xy), radius); dst[0] = crgb[0]; dst[1] = crgb[1]; dst[2] = crgb[2]; dst[3] = FTOCHAR(alpha_f); } else if (texfall == 1) { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); rgba_float_to_uchar(dst, rgba); } else if (texfall == 2) { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3(rgba, brush->rgb); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); rgb_float_to_uchar(dst, rgba); dst[3] = FTOCHAR(alpha_f); } else { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); dst[0] = crgb[0]; dst[1] = crgb[1]; dst[2] = crgb[2]; dst[3] = FTOCHAR(alpha_f); } } } } *outbuf = ibuf; }
static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4]) { GHashIterator iter; /**** dots ****/ glPointSize(3.0f); glBegin(GL_POINTS); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_DOT) continue; glColor3f(elem->color[0], elem->color[1], elem->color[2]); glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); } glEnd(); /**** circles ****/ { float circle[16][2] = { {0.000000, 1.000000}, {0.382683, 0.923880}, {0.707107, 0.707107}, {0.923880, 0.382683}, {1.000000, -0.000000}, {0.923880, -0.382683}, {0.707107, -0.707107}, {0.382683, -0.923880}, {-0.000000, -1.000000}, {-0.382683, -0.923880}, {-0.707107, -0.707107}, {-0.923879, -0.382684}, {-1.000000, 0.000000}, {-0.923879, 0.382684}, {-0.707107, 0.707107}, {-0.382683, 0.923880} }; for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); float radius = elem->v2[0]; float co[3]; int i; if (elem->type != SIM_DEBUG_ELEM_CIRCLE) continue; glColor3f(elem->color[0], elem->color[1], elem->color[2]); glBegin(GL_LINE_LOOP); for (i = 0; i < 16; ++i) { co[0] = radius * circle[i][0]; co[1] = radius * circle[i][1]; co[2] = 0.0f; mul_mat3_m4_v3(imat, co); add_v3_v3(co, elem->v1); glVertex3f(co[0], co[1], co[2]); } glEnd(); } } /**** lines ****/ glBegin(GL_LINES); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_LINE) continue; glColor3f(elem->color[0], elem->color[1], elem->color[2]); glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); glVertex3f(elem->v2[0], elem->v2[1], elem->v2[2]); } glEnd(); /**** vectors ****/ glPointSize(2.0f); glBegin(GL_POINTS); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_VECTOR) continue; glColor3f(elem->color[0], elem->color[1], elem->color[2]); glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); } glEnd(); glBegin(GL_LINES); for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); float t[3]; if (elem->type != SIM_DEBUG_ELEM_VECTOR) continue; glColor3f(elem->color[0], elem->color[1], elem->color[2]); glVertex3f(elem->v1[0], elem->v1[1], elem->v1[2]); add_v3_v3v3(t, elem->v1, elem->v2); glVertex3f(t[0], t[1], t[2]); } glEnd(); /**** strings ****/ for (BLI_ghashIterator_init(&iter, debug_data->gh); !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter)) { SimDebugElement *elem = BLI_ghashIterator_getValue(&iter); if (elem->type != SIM_DEBUG_ELEM_STRING) continue; unsigned char col[4]; rgb_float_to_uchar(col, elem->color); col[3] = 255; view3d_cached_text_draw_add(elem->v1, elem->str, strlen(elem->str), 0, V3D_CACHE_TEXT_GLOBALSPACE, col); } }