Пример #1
0
static void do_bake_shade(void *handle, int x, int y, float u, float v)
{
	BakeShade *bs = handle;
	VlakRen *vlr = bs->vlr;
	ObjectInstanceRen *obi = bs->obi;
	Object *ob = obi->obr->ob;
	float l, *v1, *v2, *v3, tvn[3], ttang[4];
	int quad;
	ShadeSample *ssamp = &bs->ssamp;
	ShadeInput *shi = ssamp->shi;

	/* fast threadsafe break test */
	if (R.test_break(R.tbh))
		return;

	/* setup render coordinates */
	if (bs->quad) {
		v1 = vlr->v1->co;
		v2 = vlr->v3->co;
		v3 = vlr->v4->co;
	}
	else {
		v1 = vlr->v1->co;
		v2 = vlr->v2->co;
		v3 = vlr->v3->co;
	}

	l = 1.0f - u - v;

	/* shrink barycentric coordinates inwards slightly to avoid some issues
	 * where baking selected to active might just miss the other face at the
	 * near the edge of a face */
	if (bs->actob) {
		const float eps = 1.0f - 1e-4f;
		float invsum;

		u = (u - 0.5f) * eps + 0.5f;
		v = (v - 0.5f) * eps + 0.5f;
		l = (l - 0.5f) * eps + 0.5f;

		invsum = 1.0f / (u + v + l);

		u *= invsum;
		v *= invsum;
		l *= invsum;
	}

	/* renderco */
	shi->co[0] = l * v3[0] + u * v1[0] + v * v2[0];
	shi->co[1] = l * v3[1] + u * v1[1] + v * v2[1];
	shi->co[2] = l * v3[2] + u * v1[2] + v * v2[2];

	/* avoid self shadow with vertex bake from adjacent faces [#33729] */
	if ((bs->vcol != NULL) && (bs->actob == NULL)) {
		madd_v3_v3fl(shi->co, vlr->n, 0.0001f);
	}

	if (obi->flag & R_TRANSFORMED)
		mul_m4_v3(obi->mat, shi->co);

	copy_v3_v3(shi->dxco, bs->dxco);
	copy_v3_v3(shi->dyco, bs->dyco);

	quad = bs->quad;
	bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v);

	if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) {
		shade_input_set_shade_texco(shi);
		copy_v3_v3(tvn, shi->nmapnorm);
		copy_v4_v4(ttang, shi->nmaptang);
	}

	/* if we are doing selected to active baking, find point on other face */
	if (bs->actob) {
		Isect isec, minisec;
		float co[3], minco[3], dist, mindist = 0.0f;
		int hit, sign, dir = 1;

		/* intersect with ray going forward and backward*/
		hit = 0;
		memset(&minisec, 0, sizeof(minisec));
		minco[0] = minco[1] = minco[2] = 0.0f;

		copy_v3_v3(bs->dir, shi->vn);

		for (sign = -1; sign <= 1; sign += 2) {
			memset(&isec, 0, sizeof(isec));
			isec.mode = RE_RAY_MIRROR;

			isec.orig.ob   = obi;
			isec.orig.face = vlr;
			isec.userdata = bs->actob;
			isec.check = RE_CHECK_VLR_BAKE;
			isec.skip = RE_SKIP_VLR_NEIGHBOUR;

			if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) {
				if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) {
					minisec = isec;
					mindist = dist;
					copy_v3_v3(minco, co);
					hit = 1;
					dir = sign;
				}
			}
		}

		if (ELEM(bs->type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) {
			if (hit)
				bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y);
			else
				bake_displacement(handle, shi, 0.0f, x, y);
			return;
		}

		/* if hit, we shade from the new point, otherwise from point one starting face */
		if (hit) {
			obi = (ObjectInstanceRen *)minisec.hit.ob;
			vlr = (VlakRen *)minisec.hit.face;
			quad = (minisec.isect == 2);
			copy_v3_v3(shi->co, minco);

			u = -minisec.u;
			v = -minisec.v;
			bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v);
		}
	}

	if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT)
		bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang);
	else
		bake_shade(handle, ob, shi, quad, x, y, u, v, NULL, NULL);
}
Пример #2
0
static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad)
{
	ShadeInput *shi = ssamp->shi;
	ShadeResult *shr = ssamp->shr;
	float l, u, v, *v1, *v2, *v3;
	
	/* init */
	if (vlr->v4) {
		shi->u = u = 0.5f;
		shi->v = v = 0.5f;
	}
	else {
		shi->u = u = 1.0f / 3.0f;
		shi->v = v = 1.0f / 3.0f;
	}

	/* setup render coordinates */
	v1 = vlr->v1->co;
	v2 = vlr->v2->co;
	v3 = vlr->v3->co;
	
	/* renderco */
	l = 1.0f - u - v;
	
	shi->co[0] = l * v3[0] + u * v1[0] + v * v2[0];
	shi->co[1] = l * v3[1] + u * v1[1] + v * v2[1];
	shi->co[2] = l * v3[2] + u * v1[2] + v * v2[2];

	shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);

	/* set up view vector */
	copy_v3_v3(shi->view, shi->co);
	normalize_v3(shi->view);
	
	/* cache for shadow */
	shi->samplenr++;

	shi->xs = 0; /* TODO */
	shi->ys = 0;
	
	shade_input_set_normals(shi);

	/* no normal flip */
	if (shi->flippednor)
		shade_input_flip_normals(shi);

	madd_v3_v3fl(shi->co, shi->facenor, -0.0001f); /* ugly.. */

	/* not a pretty solution, but fixes common cases */
	if (shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
		negate_v3(shi->vn);
		negate_v3(shi->vno);
		negate_v3(shi->nmapnorm);
	}

	/* init material vars */
	shade_input_init_material(shi);

	/* render */
	shade_input_set_shade_texco(shi);

	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);
	}

	copy_v3_v3(rad, shr->combined);
}
Пример #3
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;
	}
}
Пример #4
0
static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, float *rad)
{
	ShadeInput *shi= ssamp->shi;
	ShadeResult *shr= ssamp->shr;
	float l, u, v, *v1, *v2, *v3;
	
	/* init */
	if(vlr->v4) {
		shi->u= u= 0.5f;
		shi->v= v= 0.5f;
	}
	else {
		shi->u= u= 1.0f/3.0f;
		shi->v= v= 1.0f/3.0f;
	}

	/* setup render coordinates */
	v1= vlr->v1->co;
	v2= vlr->v2->co;
	v3= vlr->v3->co;
	
	/* renderco */
	l= 1.0f-u-v;
	
	shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0];
	shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1];
	shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2];

	shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2);

	/* set up view vector */
	copy_v3_v3(shi->view, shi->co);
	normalize_v3(shi->view);
	
	/* cache for shadow */
	shi->samplenr++;
	
	shi->xs= 0; // TODO
	shi->ys= 0;
	
	shade_input_set_normals(shi);

	/* no normal flip */
	if(shi->flippednor)
		shade_input_flip_normals(shi);

	madd_v3_v3fl(shi->co, shi->vn, 0.0001f); /* ugly.. */

	/* not a pretty solution, but fixes common cases */
	if(shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) {
		negate_v3(shi->vn);
		negate_v3(shi->vno);
		negate_v3(shi->nmapnorm);
	}

	/* init material vars */
	// note, keep this synced with render_types.h
	memcpy(&shi->r, &shi->mat->r, 23*sizeof(float));
	shi->har= shi->mat->har;
	
	/* render */
	shade_input_set_shade_texco(shi);
	shade_material_loop(shi, shr); /* todo: nodes */
	
	copy_v3_v3(rad, shr->combined);
}