Ejemplo n.º 1
0
/* For ease of use, I've also introduced a 'reflection' and 'reflection color' parameter, which isn't 
 * physically correct. This works as an RGB tint/gain on out-scattered light, but doesn't affect the light 
 * that is transmitted through the volume. While having wavelength dependent absorption/scattering is more correct,
 * it also makes it harder to control the overall look of the volume since coloring the outscattered light results
 * in the inverse color being transmitted through the rest of the volume.
 */
static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float *endco)
{
	float radiance[3] = {0.f, 0.f, 0.f};
	float tr[3] = {1.f, 1.f, 1.f};
	float p[3] = {co[0], co[1], co[2]};
	float step_vec[3] = {endco[0] - co[0], endco[1] - co[1], endco[2] - co[2]};
	const float stepsize = shi->mat->vol.stepsize;
	
	float t0 = 0.f;
	float pt0 = t0;
	float t1 = normalize_v3(step_vec);	/* returns vector length */
	
	t0 += stepsize * ((shi->mat->vol.stepsize_type == MA_VOL_STEP_CONSTANT) ? 0.5f : BLI_thread_frand(shi->thread));
	p[0] += t0 * step_vec[0];
	p[1] += t0 * step_vec[1];
	p[2] += t0 * step_vec[2];
	mul_v3_fl(step_vec, stepsize);
	
	for (; t0 < t1; pt0 = t0, t0 += stepsize) {
		const float density = vol_get_density(shi, p);
		
		if (density > 0.00001f) {
			float scatter_col[3] = {0.f, 0.f, 0.f}, emit_col[3];
			const float stepd = (t0 - pt0) * density;
			
			/* transmittance component (alpha) */
			vol_get_transmittance_seg(shi, tr, stepsize, co, density);
			
			if (t0 > t1 * 0.25f) {
				/* only use depth cutoff after we've traced a little way into the volume */
				if (luminance(tr) < shi->mat->vol.depth_cutoff) break;
			}
			
			vol_get_emission(shi, emit_col, p);
			
			if (shi->obi->volume_precache) {
				float p2[3];
				
				p2[0] = p[0] + (step_vec[0] * 0.5f);
				p2[1] = p[1] + (step_vec[1] * 0.5f);
				p2[2] = p[2] + (step_vec[2] * 0.5f);
				
				vol_get_precached_scattering(&R, shi, scatter_col, p2);
			} else
				vol_get_scattering(shi, scatter_col, p);
			
			radiance[0] += stepd * tr[0] * (emit_col[0] + scatter_col[0]);
			radiance[1] += stepd * tr[1] * (emit_col[1] + scatter_col[1]);
			radiance[2] += stepd * tr[2] * (emit_col[2] + scatter_col[2]);
		}
		add_v3_v3(p, step_vec);
	}
	
	/* multiply original color (from behind volume) with transmittance over entire distance */
	mul_v3_v3v3(col, tr, col);
	add_v3_v3(col, radiance);
	
	/* alpha <-- transmission luminance */
	col[3] = 1.0f - luminance(tr);
}
Ejemplo n.º 2
0
/* Iterate over the 3d voxel grid, and fill the voxels with scattering information
 *
 * It's stored in memory as 3 big float grids next to each other, one for each RGB channel.
 * I'm guessing the memory alignment may work out better this way for the purposes
 * of doing linear interpolation, but I haven't actually tested this theory! :)
 */
static void *vol_precache_part(void *data)
{
	VolPrecachePart *pa =  (VolPrecachePart *)data;
	ObjectInstanceRen *obi = pa->obi;
	RayObject *tree = pa->tree;
	ShadeInput *shi = pa->shi;
	float scatter_col[3] = {0.f, 0.f, 0.f};
	float co[3];
	int x, y, z;
	const int res[3]= {pa->res[0], pa->res[1], pa->res[2]};

	for (z= pa->minz; z < pa->maxz; z++) {
		co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f));
		
		for (y= pa->miny; y < pa->maxy; y++) {
			co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f));
			
			for (x=pa->minx; x < pa->maxx; x++) {
				co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f));
				
				// don't bother if the point is not inside the volume mesh
				if (!point_inside_obi(tree, obi, co)) {
					obi->volume_precache->data_r[ V_I(x, y, z, res) ] = -1.0f;
					obi->volume_precache->data_g[ V_I(x, y, z, res) ] = -1.0f;
					obi->volume_precache->data_b[ V_I(x, y, z, res) ] = -1.0f;
					continue;
				}
				
				VecCopyf(shi->view, co);
				Normalize(shi->view);
				vol_get_scattering(shi, scatter_col, co);
			
				obi->volume_precache->data_r[ V_I(x, y, z, res) ] = scatter_col[0];
				obi->volume_precache->data_g[ V_I(x, y, z, res) ] = scatter_col[1];
				obi->volume_precache->data_b[ V_I(x, y, z, res) ] = scatter_col[2];
			}
		}
	}
	
	pa->done = 1;
	
	return 0;
}