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, ¶s->water_color, paras->opacity, paras->gradation, paras->height - org.y, -dir.y, state->dist); return miTRUE; }
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(¶s->sizeMultiplier); float density = *mi_eval_scalar(¶s->density); float size = *mi_eval_scalar(¶s->size); float sizeVariation = *mi_eval_scalar(¶s->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; }