Exemplo n.º 1
0
DLLEXPORT miBoolean Submerge(miColor *result, miState *state,
		    struct Submerge_param *paras)
{
  miVector org;
  miVector dir;

  if (state->type >=miRAY_LIGHT)
    return miTRUE;

  mi_point_to_world(state, &org, &state->org);
  mi_vector_to_world(state, &dir, &state->dir);

  lume_clipped_underwater(result, &paras->water_color,
			  paras->opacity, paras->gradation,
			  paras->height - org.y, -dir.y,
			  state->dist);

  return miTRUE;
}
Exemplo n.º 2
0
DLLEXPORT miBoolean Mist(miColor *result, miState *state,
		    struct Mist_param *paras)
{
  double thickness, weight;
  miColor fog_color;

 if (state->type >=miRAY_LIGHT)
   return miTRUE;


  /* Below we determine the vitual "thickness" of the fog we've
     traveled through... Thickness can be thought of as the number
     of fog particles we've struck. */

  {
    if (paras->layering_on)
      {
	double s, h, l, k, d;  /* main variables */
	miVector dir, org;

	mi_point_to_world(state, &org, &state->org);
	mi_vector_to_world(state, &dir, &state->dir);

	k = 1.0 / paras->layering_height;
	l = state->dist;
	s = k * dir.y;
	h = k * (org.y - paras->layering_baseline);
	d = K_LAYERING_DENSITY;

	if (s == 0)
	  s = 1.0 / BIG_NUMBER;  /* I know, I'm sorry, I won't
				    do it again. */


	/* Do the algorithm.  
	   (See "Tale of a Shader Company", Jan 24, 1997) */

	{
	  double t;

	  t = pow(d,h) / s / log(d);
	  

	  /* infinite distance case */
	  if (l == 0) 
	    {
	      if (s < 0)
		thickness = BIG_NUMBER;
	      else
		thickness = -t;
	    }

	  /* finite distance case */
	  else
	    thickness = t * (pow(d,s*l) - 1.0);
	}

      }



    /* else no layering, assume constant density */

    else
      thickness = state->dist;


    /* a hack to deal with infinity (==0) */
    if (thickness == 0)
      thickness = BIG_NUMBER;   /* I lied. */
  }



  /* Below we deal with the falloff.
     Given a "thickness" of fog that the ray has travelled through,
     compute a "weight" for the fog coloration. */
  {

    if (paras->falloff_linear_on)
      weight = range_scale(thickness,
			   paras->falloff_linear_start,
			   paras->falloff_linear_end,
			   0,1);


    if (paras->falloff_realistic_on)
      weight = 1.0 - pow(K_DENSITY, 
		   paras->falloff_realistic_density * thickness);


    if (paras->falloff_custom_on)
      {
	double scaled_thick;
	double scaled_mid;

	scaled_thick = range_scale(thickness,
				   paras->falloff_custom_start,
				   paras->falloff_custom_end,
				   0,1);

	scaled_mid   =  range_scale(paras->falloff_custom_mid,
				    paras->falloff_custom_start,
				    paras->falloff_custom_end,
				    0,1);

	weight = bias(scaled_thick, scaled_mid);
      
      }


    /* Do not stray, my little friend */
    weight = clamp(weight, 0, 1);

    /* Bring within transparency setting */
    weight = range_scale(weight, 0, 1, 0, 1.0 - paras->transparency);
  }



  
  /* Below deal with determining the color of the fog */
  {
    if (paras->color_solid_on)
      fog_color = paras->color_solid_color;

    if (paras->color_map_on)
      {
	miVector map_point;

	/* Determine the map coord point */
	{
	  miVector dir;

	  mi_vector_to_world(state, &dir, &state->dir);

	  map_point.x = atan2(dir.z,dir.x) / (2.0 * PI);
	  map_point.y = -acos(dir.y)/PI;
	  map_point.z = 0;
	}

	lume_lookup_color_texture(&fog_color, state,
				paras->color_map_filename,
				&map_point);
	
      }
  }




  /* Mix the incoming color with the fog's color according to
     the weight */

  result->r = weight * fog_color.r  +  (1.0 - weight) * result->r;
  result->g = weight * fog_color.g  +  (1.0 - weight) * result->g;
  result->b = weight * fog_color.b  +  (1.0 - weight) * result->b;

  if (paras->alpha_on)
    result->a = weight  +  (1.0 - weight) * result->a;


  return miTRUE;
}
miTag createMeshParticles(miState *state, mrParticleGeoShader_paras *paras, PartioContainer& pc)
{
	mi_info("Creating mesh particles for cache file: %s", pc.cacheFileName.c_str());
	if( ! pc.good())
	{
		mi_error("Invalid PartioContainer.");
		return miNULLTAG;
	}

	Partio::ParticleAttribute posAttr;
	if(!pc.assertAttribute("position", posAttr))
		return miNULLTAG;

	Partio::ParticleAttribute idAttr;
	bool hasId = true;
	if(!pc.assertAttribute("id", idAttr))
		hasId = false;

	Partio::ParticleAttribute radiusPPAttr;
	bool hasRadiusPP = true;
	if(!pc.assertAttribute("radiusPP", radiusPPAttr))
		hasRadiusPP = false;

	Partio::ParticleAttribute velocityAttr;
	bool hasVelocity = true;
	if(!pc.assertAttribute("velocity", velocityAttr))
		hasVelocity = false;
	
	miObject *obj = beginObject();

	float *fpos;
	srand(123345);
	int numParticles = pc.data->numParticles();
	float sizeMultiplier = *mi_eval_scalar(&paras->sizeMultiplier);
	float density = *mi_eval_scalar(&paras->density);
	float size = *mi_eval_scalar(&paras->size);
	float sizeVariation = *mi_eval_scalar(&paras->sizeVariation);

	// particle number can vary because of density value
	int numWrittenParticles = 0;

	// define vectors
	for(int vtxId = 0; vtxId < numParticles; vtxId++)
	{
		miVector pos;
		fpos = (float *)pc.data->data<float>(posAttr, vtxId);

		int id = vtxId;
		if( hasId)
			id = *pc.data->data<int>(idAttr, vtxId);

		float radiusPP = 1.0f;
		if( hasRadiusPP )
			radiusPP = *pc.data->data<float>(radiusPPAttr, vtxId);

		miVector vel = {0.0, 0.0, 0.0};
		if(hasVelocity)
		{
			float *v;
			v = (float *)pc.data->data<float>(velocityAttr, vtxId);
			vel.x = v[0];
			vel.y = v[1];
			vel.z = v[2];
			// velocity ist distance/sekunde, eine velocity von 24 legt also eine Distanz von 1 Einheit pro frame bei 24fps zurück
			// zusätzlich muss man noch den shutter angle beachten, bei 140° sind das -.2 -> 0.2 also 0.4 * 1 und damit grob .4 Einheiten
			float factor = 1.0f/24.0f * 0.4f;
			mi_vector_mul(&vel, factor);
		}

		pos.x = fpos[0];
		pos.y = fpos[1];
		pos.z = fpos[2];

		miVector camPos = pos;

		// ich transformiere das particle in camera space und gehe dann einfach size/2 nach rechts und oben
		miMatrix matrix;
		mi_matrix_ident(matrix);
		miInstance *inst = (miInstance *)mi_db_access(state->instance);
		mi_matrix_copy(matrix, inst->tf.global_to_local);
		mi_db_unpin(state->instance);
		
		mi_point_from_world(state, &camPos, &pos);
		mi_point_from_world(state, &camPos, &camPos);
		mi_point_to_camera(state, &camPos, &camPos);

		float psize = radiusPP * sizeMultiplier;
		int pId = vtxId;
		double rndVal = rnd(id * state->camera->frame + 5);
		if( rndVal > density)
			continue;
		
		float srndVal = (rndVal - 0.5f) * 2.0f;
		psize *= size + (size * srndVal * sizeVariation * 0.5f);
		psize = fabs(psize);
		if(psize == 0.0f)
			continue;

		miVector upRight, bottomLeft;
		upRight = camPos;
		upRight.x += psize/2.0f;
		upRight.y += psize/2.0f;
		bottomLeft = camPos;
		bottomLeft.x -= psize/2.0f;
		bottomLeft.y -= psize/2.0f;

		// checkScreenSpace in Screenspace und testet auf minPixelSize. 
		if(!checkScreenSpace(state, paras, camPos, bottomLeft, upRight) )
			continue;
		numWrittenParticles++;

		miVector v0, v1, v2, v3;
		v0 = bottomLeft;
		v2 = upRight;
		v1 = bottomLeft;
		v1.y = upRight.y;
		v3 = upRight;
		v3.y = bottomLeft.y;

		mi_point_from_camera(state, &v0, &v0);
		mi_point_from_camera(state, &v1, &v1);
		mi_point_from_camera(state, &v2, &v2);
		mi_point_from_camera(state, &v3, &v3);

		mi_point_to_world(state, &v0, &v0);
		mi_point_to_world(state, &v1, &v1);
		mi_point_to_world(state, &v2, &v2);
		mi_point_to_world(state, &v3, &v3);

		miVector v01, v02, v03;
		mi_vector_sub(&v01, &v0, &v1);
		mi_vector_sub(&v02, &v0, &v2);
		mi_vector_sub(&v03, &v0, &v3);
		mi_vector_transform(&v01, &v01, matrix);
		mi_vector_transform(&v02, &v02, matrix);
		mi_vector_transform(&v03, &v03, matrix);
		mi_vector_add(&v1, &v0, &v01);
		mi_vector_add(&v2, &v0, &v02);
		mi_vector_add(&v3, &v0, &v03);

		// add geometry vectors 
		// e.g. -0.5 -0.5 0.5
		add_vector(v0.x, v0.y, v0.z);
		add_vector(v1.x, v1.y, v1.z);
		add_vector(v2.x, v2.y, v2.z);
		add_vector(v3.x, v3.y, v3.z);

		// single motion vector per particle
		add_vector(vel.x, vel.y, vel.z);

	}

	// uv coordinates
	miVector uvw;
	uvw.x = uvw.y = uvw.z = 0.0f;
	uvw.z = 123.0f;
	mi_api_vector_xyz_add( &uvw );
	uvw.x = 1.0;
	mi_api_vector_xyz_add( &uvw );
	uvw.y = 1.0;
	mi_api_vector_xyz_add( &uvw );
	uvw.x = 0.0;
	mi_api_vector_xyz_add( &uvw );


	// define vertices
	// depending on the attributes we have x vectors per vertex:
	// 0: pos1
	// 1: pos2
	// 2: pos3
	// 3: pos4
	// 4: vel
	// tex0 = numWrittenParticles * 5 - 4

	// num done particles für rnd density
	int texIndex = numWrittenParticles * 5;
	for(int vtxId = 0; vtxId < numWrittenParticles; vtxId++)
	{
		int vertexIndex = vtxId * 5;
		int mvIndex = vtxId * 5 + 4;
		// add vertex definitions
		// e.g. v 0 n 8 t 32 m 46
		mi_api_vertex_add(vertexIndex);
		mi_api_vertex_tex_add( texIndex, -1, -1);
		mi_api_vertex_motion_add(mvIndex);

		mi_api_vertex_add(vertexIndex + 1);
		mi_api_vertex_tex_add( texIndex + 1, -1, -1);
		mi_api_vertex_motion_add(mvIndex);

		mi_api_vertex_add(vertexIndex + 2);
		mi_api_vertex_tex_add( texIndex + 2, -1, -1);
		mi_api_vertex_motion_add(mvIndex);

		mi_api_vertex_add(vertexIndex + 3);
		mi_api_vertex_tex_add( texIndex + 3, -1, -1);
		mi_api_vertex_motion_add(mvIndex);
	}


	// add poly for every particle

	for( int pId = 0; pId < numWrittenParticles; pId++)
	{
		int vtxId = pId * 4;
		mi_api_poly_begin_tag(1, miNULLTAG);

		mi_api_poly_index_add(vtxId);
		mi_api_poly_index_add(vtxId + 1);
		mi_api_poly_index_add(vtxId + 2);
		mi_api_poly_index_add(vtxId + 3);

		mi_api_poly_end();

	}
	miTag objTag = finishObject();
	return objTag;
   
}