Esempio n. 1
0
static void tonemapmodifier_apply_threaded_simple(int width,
                                                  int height,
                                                  unsigned char *rect,
                                                  float *rect_float,
                                                  unsigned char *mask_rect,
                                                  float *mask_rect_float,
                                                  void *data_v)
{
	AvgLogLum *avg = (AvgLogLum *)data_v;
	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			int pixel_index = (y * width + x) * 4;
			float input[4], output[4], mask[3] = {1.0f, 1.0f, 1.0f};
			/* Get input value. */
			if (rect_float) {
				copy_v4_v4(input, &rect_float[pixel_index]);
			}
			else {
				straight_uchar_to_premul_float(input, &rect[pixel_index]);
			}
			IMB_colormanagement_colorspace_to_scene_linear_v3(input, avg->colorspace);
			copy_v4_v4(output, input);
			/* Get mask value. */
			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);
			}
			/* Apply correction. */
			mul_v3_fl(output, avg->al);
			float dr = output[0] + avg->tmmd->offset;
			float dg = output[1] + avg->tmmd->offset;
			float db = output[2] + avg->tmmd->offset;
			output[0] /= ((dr == 0.0f) ? 1.0f : dr);
			output[1] /= ((dg == 0.0f) ? 1.0f : dg);
			output[2] /= ((db == 0.0f) ? 1.0f : db);
			const float igm = avg->igm;
			if (igm != 0.0f) {
				output[0] = powf(max_ff(output[0], 0.0f), igm);
				output[1] = powf(max_ff(output[1], 0.0f), igm);
				output[2] = powf(max_ff(output[2], 0.0f), igm);
			}
			/* Apply mask. */
			output[0] = input[0] * (1.0f - mask[0]) + output[0] * mask[0];
			output[1] = input[1] * (1.0f - mask[1]) + output[1] * mask[1];
			output[2] = input[2] * (1.0f - mask[2]) + output[2] * mask[2];
			/* Copy result back. */
			IMB_colormanagement_scene_linear_to_colorspace_v3(output, avg->colorspace);
			if (rect_float) {
				copy_v4_v4(&rect_float[pixel_index], output);
			}
			else {
				premul_float_to_straight_uchar(&rect[pixel_index], output);
			}
		}
	}
}
Esempio n. 2
0
static void whiteBalance_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
                                        unsigned char *mask_rect, float *mask_rect_float, void *data_v)
{
	int x, y;
	float multiplier[3];

	WhiteBalanceThreadData *data = (WhiteBalanceThreadData *) data_v;

	multiplier[0] = 1.0f / data->white[0];
	multiplier[1] = 1.0f / data->white[1];
	multiplier[2] = 1.0f / data->white[2];

	for (y = 0; y < height; y++) {
		for (x = 0; x < width; x++) {
			int pixel_index = (y * width + x) * 4;
			float result[3], mask[3] = {1.0f, 1.0f, 1.0f};

			if (rect_float) {
				copy_v3_v3(result, rect_float + pixel_index);
			}
			else {
				straight_uchar_to_premul_float(result, rect + pixel_index);
				IMB_colormanagement_colorspace_to_scene_linear_v3(result, data->colorspace);
			}

			mul_v3_v3(result, multiplier);

			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] = result[0] * (1.0f - mask[0]) + result[0] * mask[0];
			result[1] = result[1] * (1.0f - mask[1]) + result[1] * mask[1];
			result[2] = result[2] * (1.0f - mask[2]) + result[2] * mask[2];

			if (rect_float)
				copy_v3_v3(rect_float + pixel_index, result);
			else
				IMB_colormanagement_scene_linear_to_colorspace_v3(result, data->colorspace);
			premul_float_to_straight_uchar(rect + pixel_index, result);
		}
	}
}
Esempio n. 3
0
static void tonemapmodifier_apply_threaded_photoreceptor(int width,
                                                         int height,
                                                         unsigned char *rect,
                                                         float *rect_float,
                                                         unsigned char *mask_rect,
                                                         float *mask_rect_float,
                                                         void *data_v)
{
	AvgLogLum *avg = (AvgLogLum *)data_v;
	const float f = expf(-avg->tmmd->intensity);
	const float m = (avg->tmmd->contrast > 0.0f) ? avg->tmmd->contrast : (0.3f + 0.7f * powf(avg->auto_key, 1.4f));
	const float ic = 1.0f - avg->tmmd->correction, ia = 1.0f - avg->tmmd->adaptation;
	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			int pixel_index = (y * width + x) * 4;
			float input[4], output[4], mask[3] = {1.0f, 1.0f, 1.0f};
			/* Get input value. */
			if (rect_float) {
				copy_v4_v4(input, &rect_float[pixel_index]);
			}
			else {
				straight_uchar_to_premul_float(input, &rect[pixel_index]);
			}
			IMB_colormanagement_colorspace_to_scene_linear_v3(input, avg->colorspace);
			copy_v4_v4(output, input);
			/* Get mask value. */
			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);
			}
			/* Apply correction. */
			const float L = IMB_colormanagement_get_luminance(output);
			float I_l = output[0] + ic * (L - output[0]);
			float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]);
			float I_a = I_l + ia * (I_g - I_l);
			output[0] /= (output[0] + powf(f * I_a, m));
			I_l = output[1] + ic * (L - output[1]);
			I_g = avg->cav[1] + ic * (avg->lav - avg->cav[1]);
			I_a = I_l + ia * (I_g - I_l);
			output[1] /= (output[1] + powf(f * I_a, m));
			I_l = output[2] + ic * (L - output[2]);
			I_g = avg->cav[2] + ic * (avg->lav - avg->cav[2]);
			I_a = I_l + ia * (I_g - I_l);
			output[2] /= (output[2] + powf(f * I_a, m));
			/* Apply mask. */
			output[0] = input[0] * (1.0f - mask[0]) + output[0] * mask[0];
			output[1] = input[1] * (1.0f - mask[1]) + output[1] * mask[1];
			output[2] = input[2] * (1.0f - mask[2]) + output[2] * mask[2];
			/* Copy result back. */
			IMB_colormanagement_scene_linear_to_colorspace_v3(output, avg->colorspace);
			if (rect_float) {
				copy_v4_v4(&rect_float[pixel_index], output);
			}
			else {
				premul_float_to_straight_uchar(&rect[pixel_index], output);
			}
		}
	}
}
Esempio n. 4
0
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;
	}
}