コード例 #1
0
bool DSLightChunk::operator == (const StateChunk &other) const
{
    const DSLightChunk *tother = dynamic_cast<const DSLightChunk *>(&other);

    if(!tother)
        return false;

    if(tother == this)
        return true;

    if(!getAmbient  ().equals(tother->getAmbient  (),
                              TypeTraits<Real32>::getDefaultEps()) ||
       !getDiffuse  ().equals(tother->getDiffuse  (),
                              TypeTraits<Real32>::getDefaultEps()) ||
       !getSpecular ().equals(tother->getSpecular (),
                              TypeTraits<Real32>::getDefaultEps()) ||
       !getPosition ().equals(tother->getPosition (),
                              TypeTraits<Real32>::getDefaultEps()) ||
       !getDirection().equals(tother->getDirection(),
                              TypeTraits<Real32>::getDefaultEps()) ||

        getConstantAttenuation () != tother->getConstantAttenuation () ||
        getLinearAttenuation   () != tother->getLinearAttenuation   () ||
        getQuadraticAttenuation() != tother->getQuadraticAttenuation() ||
        getCutoff              () != tother->getCutoff              () ||
        getExponent            () != tother->getExponent            ()
      )
    {
        return false;
    }

    return true;
}
コード例 #2
0
ファイル: Material.cpp プロジェクト: luk2010/GRE
const Color& Material::getDiffuse() const
{
    auto ptr = lock();
    if ( ptr )
        return ptr->getDiffuse();
    throw GreInvalidUserException("Material");
}
コード例 #3
0
Colour PhongMaterial::getColour(const Vector3D& normal, const Vector3D& viewDirection,
                                const std::list<Light*>& lights, const Colour& ambient, 
                                const Point3D& poi, const Primitive* primitive) const
{
  // Get diffuse coefficients
  Colour kd = getDiffuse(primitive, poi);

  // First add ambient light.
  Colour c = kd * ambient;

  for (std::list<Light*>::const_iterator it = lights.begin(); it != lights.end(); it++) {
    Light* light = (*it);

    Vector3D lightDirection = light->position - poi; // Note this needs to point towards the light.
    lightDirection.normalize();

    double dist = lightDirection.length();
    Vector3D r = -lightDirection + 2 * (lightDirection.dot(normal)) * normal;

    Colour contribution = (kd + m_ks * ( pow(r.dot(viewDirection), m_shininess) / normal.dot(lightDirection) )) *
                          light->colour * lightDirection.dot(normal) * 
                          (1 / (light->falloff[0] + light->falloff[1] * dist +
                                light->falloff[2] * dist * dist)); 

    // Ignore negative contributions
    if (contribution.R() >= 0 && contribution.G() >= 0 && contribution.B() >= 0) {
      c = c + contribution;
    }
  }

  return c;
}
コード例 #4
0
ファイル: OSGDVRVolume.cpp プロジェクト: mlimper/OpenSG1x
//! output the instance for debug purposes
void DVRVolume::dump(      UInt32    uiIndent, 
                     const BitVector         ) const
{
    DVRVolumePtr thisP(*this);

    thisP.dump(uiIndent, FCDumpFlags::RefCount);

    indentLog(uiIndent, PLOG);
    PLOG << "DVRVolume at " << this << std::endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\trenderMaterial: " << getRenderMaterial() << std::endl;

    if (getRenderMaterial() != NullFC)
        getRenderMaterial()->dump(uiIndent);
    
    indentLog(uiIndent, PLOG);
    PLOG << "\ttextureStorage: " << getTextureStorage() << std::endl;

    if (getTextureStorage() != NullFC)
        getTextureStorage()->dump(uiIndent);
    
#if 0
    indentLog(uiIndent, PLOG);
    PLOG << "\tambient: " << getAmbient() << endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\tdiffuse: " << getDiffuse()  << endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\tspecular: " << getSpecular()  << endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\tshininess: " << getShininess()  << endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\temission: " << getEmission()  << endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\ttransparency: " << getTransparency()  << endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\tlit: " << getLit() << endl;

    indentLog(uiIndent, PLOG);
    PLOG << "\tChunks: " << endl;

    for(MFStateChunkPtr::const_iterator i = _mfChunks.begin();
            i != _mfChunks.end(); i++)
    {
        indentLog(uiIndent, PLOG);
        PLOG << "\t" << *i << endl;
    }
#endif
    
    indentLog(uiIndent, PLOG);
    PLOG << "DVRVolume end " << this << std::endl;
}
コード例 #5
0
StatePtr PhongMaterial::makeState(void)
{
    StatePtr state = State::create();

    prepareLocalChunks();

    Color3f v3;
    Color4f v4;
    float alpha = 1.f - getTransparency();

    prepareLocalChunks();

    beginEditCP(_materialChunk);
    v3 = getAmbient();
    v4.setValuesRGBA(v3[0], v3[1], v3[2], alpha);
    _materialChunk->setAmbient(v4);

    v3 = getDiffuse();
    v4.setValuesRGBA(v3[0], v3[1], v3[2], alpha);
    _materialChunk->setDiffuse(v4);

    v3 = getSpecular();
    v4.setValuesRGBA(v3[0], v3[1], v3[2], alpha);
    _materialChunk->setSpecular(v4);

    _materialChunk->setShininess(getShininess());

    v3 = getEmission();
    v4.setValuesRGBA(v3[0], v3[1], v3[2], alpha);
    _materialChunk->setEmission(v4);

    _materialChunk->setLit(getLit());
    _materialChunk->setColorMaterial(getColorMaterial());
    endEditCP  (_materialChunk);
    state->addChunk(_materialChunk);

    if(isTransparent())
        state->addChunk(_blendChunk);

    if(_vpChunk != NullFC)
        state->addChunk(_vpChunk);

    createFragmentProgram();

    if(_fpChunk != NullFC)
        state->addChunk(_fpChunk);

    for(MFStateChunkPtr::iterator i  = _mfChunks.begin();
            i != _mfChunks.end();
            ++i)
    {
        state->addChunk(*i);
    }

    return state;
}
コード例 #6
0
ファイル: Candle.cpp プロジェクト: FatherNuno/ProjetoCG
void Candle::draw() {

	//Material

	GLfloat candle_amb[] = {0.55f,0.27f,0.05f,1.0f};
	GLfloat candle_diff[] = {0.92f,0.61f,0.1f,1.0f};
	GLfloat candle_spec[] = {0.53f,0.0f,0.0f,1.0f};
	GLfloat candle_shine = 128;
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, candle_amb);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, candle_diff);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, candle_spec);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, candle_shine);

	//Solido

	glColor3d(1.0, 1.5, 0);

	glPushMatrix();
	glTranslated(getPosition()->getX(), getPosition()->getY(), 0.625);

	glScalef(1.0, 1.0, 10);
	glutSolidCube(0.025);
	glPopMatrix();

	//Propriedades Luz

	GLfloat amb[] = { getAmbient()->getX(), getAmbient()->getY(), getAmbient()->getZ(), getAmbient()->getW() };
	GLfloat diffuse[] = { getDiffuse()->getX(), getDiffuse()->getY(), getDiffuse()->getZ(),getDiffuse()->getW() };
	GLfloat specular[] = { getSpecular()->getX(), getSpecular()->getY(), getSpecular()->getZ(), getSpecular()->getW() };
	GLfloat pos[] = { getPosition()->getX(), getPosition()->getY(), 1.0, 1.0 };

	glLightfv(_num, GL_AMBIENT, amb);
	glLightfv(_num, GL_DIFFUSE, diffuse);
	glLightfv(_num, GL_SPECULAR, specular);
	glLightfv(_num, GL_POSITION, pos);

	//atenuacao da luz
	glLightf(_num, GL_CONSTANT_ATTENUATION, 0);
	glLightf(_num, GL_LINEAR_ATTENUATION, 0);
	glLightf(_num, GL_QUADRATIC_ATTENUATION, 7);	
}
コード例 #7
0
ファイル: phong.cpp プロジェクト: winmad/winmad-s-raytracer
Color3 getPhong(const Vector3& p , const Vector3& visionDir ,
	const Vector3& normal , const Vector3& lightSourcePos ,
	const Color3& lightIntensity , Geometry* obj , const Real& directCoe)
{
	Vector3 lightDir = lightSourcePos - p;
	lightDir.normalize();
	Vector3 reflecDir = normal * ((normal ^ lightDir) * 2.0) - lightDir;
	reflecDir.normalize();
	Color3 diffuseIntensity = getDiffuse(lightDir , normal , 
		lightIntensity , obj->get_diffuse_color(p));
	Color3 specularIntensity = getSpecular(reflecDir , visionDir , 
		lightIntensity , obj->get_material().specular);
	Color3 ambientIntensity = getAmbient(lightIntensity , obj->get_material().ambient);
	Color3 res = (diffuseIntensity + specularIntensity) * directCoe + ambientIntensity;
	res.clamp();
	return res;
}
コード例 #8
0
ファイル: kernel.c プロジェクト: arichnad/raytrace-opencl
Vector getPixel(Ray ray, Stack * stack, real magnitude, real refractiveIndex, int depth, ulong *seed) {
	ItemPtr item = getClosestItem(ray);

	if(item==NULL) {
		return ZERO;
	}

	Vector point = getIntersectPoint(item, ray) + ray.from;
	int specularRoughness = getSpecularRoughness(item, point);
	Vector normal = getNormal(item, ray, point);

	Vector diffuseColor = ZERO;
	Vector specularColor = ZERO;

	Ray reflection;
	reflection.ray = reflect(ray.ray, normal);
	reflection.from = point+(reflection.ray*.001f);

	if(length2(getDiffuse(item, point))>0 || length2(getSpecular(item, point))>0) {
		for(int i=0;i<lightNumber;i++) {
			ItemPtr light = &lights[i];
			Vector lightVector = light->center-point;
			Vector lightPixel = fast_normalize(lightVector);

			real diffuseFactor = dot(normal, lightPixel);
			real specularFactor = dot(reflection.ray, lightPixel);

			if(diffuseFactor>0 || specularFactor>0) {
				int hitLight=0;
				
				Ray movedLightRay;
				movedLightRay.from=reflection.from;
				
				Vector right = getRight(lightPixel);
				Vector up = getUp(lightPixel, right);
				for(int i=0;i<SHADOW_RUNS;i++) {
					//TODO:  this can be much faster methinks
					real r = random(seed)*2-1;
					real u = random(seed)*sqrt(1-r*r);
					movedLightRay.ray = fast_normalize(lightVector+right*r*light->radius+up*u*light->radius);

					ItemPtr closestItem = getClosestItem(movedLightRay);
					if(closestItem!=NULL && closestItem->type==LIGHT) {
						hitLight++;
					}
				}
				if(hitLight > 0) {
					real lightValue = ((real)hitLight) / SHADOW_RUNS;
					if(diffuseFactor>0) {
						diffuseFactor *= lightValue;
						diffuseColor = diffuseColor+light->light*diffuseFactor;
					}
					if(specularFactor>0) {
						specularFactor = lightValue * pow(specularFactor, specularRoughness);
						specularColor = specularColor+light->light*specularFactor;
					}
				}
			}
		}
	}

	Vector color = (diffuseColor*getDiffuse(item, point)+specularColor*getSpecular(item, point)) * magnitude;

	if(depth > 0) {
		Ray refraction;
		if(getRefraction(item, point)) {
			refraction.ray = refract(ray.ray, normal, item, refractiveIndex);
			refraction.from = point+(refraction.ray*.001f);
			if(length2(refraction.ray)>0) {
				push(stack, depth-1, refraction, magnitude, getRefraction(item, point));
			}
		}

		if(getReflection(item, point) > 0) {
			push(stack, depth-1, reflection, magnitude * getReflection(item, point), refractiveIndex);
		}
	}

	return color;
}
コード例 #9
0
	void main(void *arg)
	{
		const color WHITE(1.0f);
		//-----------------------------------------
		const color Cs(i_color());
		color diffuse_color(1.0f, 1.0f, 1.0f);
		scalar diffuse_weight = i_diffuse();
		color specular_color(i_specularColor());
		scalar specular_weight= 0.2f;//cosinePower
		scalar roughness = 0.0f;
		int specular_mode = 1;//[0,3]
		scalar glossiness = 1.0f;
		color reflection_color(i_reflectedColor());
		scalar reflection_weight = 0.5f;
		color  refraction_color(1.0f, 1.0f, 1.0f);
		scalar refraction_weight= 0.0f;//zero will lead a dark image
		scalar refraction_glossiness = 0.5f;
		scalar refraction_thickness= 2.0f;//surfaceThickness
		color  translucency_color(i_transparency());
		scalar translucency_weight = i_translucence();
		scalar anisotropy = 1.0f;
		scalar rotation = 0.0f;
		scalar ior = 1.5f;//refractiveIndex
		bool fresnel_by_ior = eiTRUE;
		scalar fresnel_0_degree_refl = 0.2f;
		scalar fresnel_90_degree_refl = 1.0f;
		scalar fresnel_curve= 5.0f;
		bool is_metal = eiTRUE;
		int diffuse_samples = 8;
		int reflection_samples= 4;
		int refraction_samples= 4;
		scalar cutoff_threshold = LIQ_SCALAR_EPSILON;
		eiTag bump_shader = eiNULL_TAG;
		scalar bump_factor= 0.3f;

  		if( liq_UserDefinedNormal() == 0 )
  		{
  			i_normalCamera() = N;
  		}
		//-----------------------------------------
		vector In = normalize( I );
		normal Nn = normalize( i_normalCamera() );
		normal Nf = ShadingNormal(Nn);
		vector V = -In;
		//-----------------------------------------



		// specular is the percentage of specular lighting
		// limit weights in range [0, 1]
		specular_weight = clamp(specular_weight, 0.0f, 1.0f);
		refraction_weight = clamp(refraction_weight, 0.0f, 1.0f);
		translucency_weight = clamp(translucency_weight, 0.0f, 1.0f);
		// automatically compute Kd, Ks, Kt in an energy conserving way
		diffuse_weight = clamp(diffuse_weight, 0.0f, 1.0f);
		reflection_weight = clamp(reflection_weight, 0.0f, 1.0f);
		// the energy balancing between reflection and refraction is 
		// dominated by Fresnel law
		//color Kt(refraction_color * (spec * refr * (1.0f - trans)) * (is_metal?Cs:WHITE));
		
		// this is a monolithic shader which also serves as shadow shader
		if (ray_type == EI_RAY_SHADOW)
		{
			main_shadow(arg, refraction_color * (specular_weight * refraction_weight * (1.0f - translucency_weight)), 
				refraction_thickness, cutoff_threshold);
			return;
		}

		// for surface shader, we call bump shader
		eiTag shader = bump_shader;
		if (shader != eiNULL_TAG)
		{
			call_bump_shader(shader, bump_factor);
		}

		//color Kc(refraction_color * (spec * refr * trans) * (is_metal?Cs:WHITE));
		// non-reflected energy is absorbed
		//color Ks(specular_color * spec * (1.0f - refl) * (is_metal?Cs:WHITE));
		//color Kr(reflection_color * (spec * refl) * (is_metal?Cs:WHITE));
		// surface color will impact specular for metal material
		//const color Cs(surface_color);

//		const color Kd( Cs *(1.0f - spec) * diff );
//		const int spec_mode = clamp(specular_mode, 0, 3);

		computeSurface(
			i_color(),//outColor(),//out->Ci,//
			i_transparency(),//out->Oi,//
			i_matteOpacityMode(),
			i_matteOpacity(),
			o_outColor(),//out->Ci,//
			o_outTransparency()//out->Oi//
		);
		out->Ci = o_outColor();
		out->Oi = o_outTransparency();

		// apply rotation
		scalar deg = rotation;
		if (deg != 0.0f)
		{
			dPdu = rotate_vector(dPdu, N, radians(deg));
			dPdv = cross(dPdu, N);
			u_axis = normalize(dPdu);
			v_axis = normalize(dPdv);
		}

		// set the glossiness scale based on the chosen BSDF
		scalar glossiness_scale = 370.37f;
		if (specular_mode == 1)
		{
			glossiness_scale = 125.0f;
		}
		else if (specular_mode == 3)
		{
			// scale to make the same glossiness parameter 
			// results in similar lobe for different BSDFs
			glossiness_scale = 22.88f;
		}

//		scalar aniso = anisotropy;
		int refl_samples = reflection_samples;
		int refr_samples = refraction_samples;

		// prepare outgoing direction in local frame
		const vector wo(normalize(to_local(V)));
		// construct BSDFs
		OrenNayar Rd(roughness);
		scalar shiny_u = glossiness;
		if (shiny_u < eiSCALAR_EPS)
		{
			shiny_u = eiSCALAR_EPS;
			refl_samples = 1;
		}
		shiny_u = max(0.0f, glossiness_scale / shiny_u);
		scalar shiny_v = max(0.0f, shiny_u * anisotropy);
		
		scalar IOR = ior;
		eiBool fresn_by_ior = fresnel_by_ior;
		scalar fresn_0_degree_refl = fresnel_0_degree_refl;
		scalar fresn_90_degree_refl = fresnel_90_degree_refl;
		scalar fresn_curve = fresnel_curve;

		union {
			eiByte by_ior[sizeof(FresnelByIOR)];
			eiByte schlick[sizeof(FresnelSchlick)];
		} F_storage;

		union {
			eiByte by_ior[sizeof(FresnelByIOR)];
			eiByte schlick[sizeof(FresnelSchlick)];
		} invF_storage;

		Fresnel *F = NULL;
		Fresnel *invF = NULL;
		if (fresn_by_ior)
		{
			F = new (F_storage.by_ior) FresnelByIOR(IOR);
			invF = new (invF_storage.by_ior) InvFresnelByIOR(IOR);
		}
		else
		{
			F = new (F_storage.schlick) FresnelSchlick(
				fresn_0_degree_refl, 
				fresn_90_degree_refl, 
				fresn_curve);
			invF = new (invF_storage.schlick) InvFresnelSchlick(
				fresn_0_degree_refl, 
				fresn_90_degree_refl, 
				fresn_curve);
		}

		union {
			eiByte ward[sizeof(Ward)];
			eiByte phong[sizeof(StretchedPhong)];
			eiByte blinn[sizeof(Blinn)];
			eiByte cooktorrance[sizeof(CookTorrance)];
		} Rs_storage;

		BSDF *Rs = NULL;
		switch (specular_mode)
		{
		case 0:
 			Rs = new (Rs_storage.ward) Ward(F, shiny_u, shiny_v);
			break;
		case 1:
			Rs = new (Rs_storage.phong) StretchedPhong(F, shiny_u);
			break;
		case 2:
			Rs = new (Rs_storage.blinn) Blinn(F, shiny_u);
			break;
		case 3:
			Rs = new (Rs_storage.cooktorrance) CookTorrance(F, 1.0f / shiny_u);
			break;
		}

		SpecularReflection Rr(F);

		scalar refr_shiny_u = refraction_glossiness;
		if (refr_shiny_u < eiSCALAR_EPS)
		{
			refr_shiny_u = eiSCALAR_EPS;
			refr_samples = 1;
		}
		refr_shiny_u = max(0.0f, glossiness_scale / refr_shiny_u);
		scalar refr_shiny_v = max(0.0f, shiny_u * anisotropy);

		union {
			eiByte ward[sizeof(Ward)];
			eiByte phong[sizeof(StretchedPhong)];
			eiByte blinn[sizeof(Blinn)];
			eiByte cooktorrance[sizeof(CookTorrance)];
		} Rts_storage;

		BSDF *Rts = NULL;
		switch (specular_mode)
		{
		case 0:
			Rts = new (Rts_storage.ward) Ward(invF, refr_shiny_u, refr_shiny_v);
			break;
		case 1:
			Rts = new (Rts_storage.phong) StretchedPhong(invF, refr_shiny_u);
			break;
		case 2:
			Rts = new (Rts_storage.blinn) Blinn(invF, refr_shiny_u);
			break;
		case 3:
			Rts = new (Rts_storage.cooktorrance) CookTorrance(invF, 1.0f / refr_shiny_u);
			break;
		}

		scalar refr_thickness = refraction_thickness;

		// internal scale for refraction thickness, make it smaller
		BRDFtoBTDF Rt(Rts, IOR, refr_thickness * 0.1f, this);
		
		color Cdiffuse(0.0f);
		color Cspecular(0.0f);

		// don't integrate direct lighting if the ray hits the back face
 		if (dot_nd < 0.0f)
 		{
 			// integrate direct lighting from the front side
 			//out->Ci += integrate_direct_lighting(/*Kd*/diffuse(), Rd, wo);
 			//out->Ci *= i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);
			Cdiffuse += i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);

 			//out->Ci += integrate_direct_lighting(Ks, *Rs, wo);
 			//out->Ci += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);
			Cspecular += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);

		}

		// integrate for translucency from the back side
		if (!almost_black( refraction_color * (specular_weight * refraction_weight * translucency_weight)*(is_metal?Cs:WHITE) ) && //almost_black(Kc)
			(refr_thickness > 0.0f || dot_nd > 0.0f))
		{
			vector old_dPdu(dPdu);
			vector old_dPdv(dPdv);
			vector old_u_axis(u_axis);
			vector old_v_axis(v_axis);
			normal old_N(N);
			vector new_wo(wo);

			if (dot_nd < 0.0f)
			{
				dPdu = old_dPdv;
				dPdv = old_dPdu;
				u_axis = old_v_axis;
				v_axis = old_u_axis;
				N = -N;
				new_wo = vector(wo.y, wo.x, -wo.z);
			}
			
			// integrate direct lighting from the back side
			//out->Ci += Kc * integrate_direct_lighting(/*Kd*/i_diffuse(), Rd, new_wo);
			//out->Ci += i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);
			Cdiffuse += i_diffuse() * getDiffuse(Nf, eiFALSE, eiFALSE);

			//out->Ci += Kc * integrate_direct_lighting(Ks, *Rs, new_wo);
			//out->Ci += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);
			Cspecular += i_specularColor() * getPhong (Nf, V, i_cosinePower(), eiFALSE, eiFALSE);

			N = old_N;
			u_axis = old_u_axis;
			v_axis = old_v_axis;
			dPdu = old_dPdu;
			dPdv = old_dPdv;
		}


		scalar cutoff_thresh = cutoff_threshold;
				
		color CReflectSpecular(0.0f);
 		// integrate indirect specular lighting
		if (!almost_black( specular_color * (specular_weight * (1.0f - reflection_weight))*(is_metal?Cs:WHITE) ) && dot_nd < 0.0f)//almost_black(Ks)
 		{
 			IntegrateOptions opt;
 			opt.ray_type = EI_RAY_REFLECT_GLOSSY;
 			opt.min_samples = opt.max_samples = refl_samples;
 			opt.cutoff_threshold = cutoff_thresh;

			CReflectSpecular = integrate(wo, *Rs, opt);
  		}

		color CSpecularReflection(0.0f);
		// integrate perfect specular reflection
		if (!almost_black(reflection_color * (specular_weight * reflection_weight) * (is_metal?Cs:WHITE)) && dot_nd < 0.0f)//almost_black(Kr)
		{
			IntegrateOptions opt;
			opt.ray_type = EI_RAY_REFLECT_GLOSSY;
			opt.min_samples = opt.max_samples = 1; // force one sample for reflection
			opt.cutoff_threshold = cutoff_thresh;
			// the direct lighting of this BRDF is not accounted, 
			// so we trace lights here to compensate
			opt.trace_lights = eiTRUE;
			
			CSpecularReflection = integrate(wo, Rr, opt);
		}

		color CReflectDiffuse(0.0f);
		// integrate indirect diffuse lighting (color bleeding)
		if (!almost_black( Cs *(1.0f - specular_weight) * diffuse_weight ) && dot_nd < 0.0f)//almost_black(Kd)
		{
			IntegrateOptions opt;
			opt.ray_type = EI_RAY_REFLECT_DIFFUSE;
			opt.min_samples = opt.max_samples = diffuse_samples;
			opt.cutoff_threshold = cutoff_thresh;

			CReflectDiffuse = integrate(wo, Rd, opt);
		}

		color CRefraction(0.0f);
		// integrate refraction
		if ( !almost_black(refraction_color * specular_weight * refraction_weight * (1.0f-translucency_weight)*(is_metal?Cs:WHITE)) ) //almost_black(Kt)
		{
			IntegrateOptions opt;
			opt.ray_type = EI_RAY_REFRACT_GLOSSY;
			if (IOR == 1.0f)
			{
				opt.ray_type = EI_RAY_TRANSPARENT;
			}
			opt.min_samples = opt.max_samples = refr_samples;
			opt.cutoff_threshold = cutoff_thresh;
			// account for refractive caustics
			opt.trace_lights = eiTRUE;

			CRefraction = integrate(wo, Rt, opt);
		}

		out->Ci *= (Cdiffuse 

					+ CReflectDiffuse *
					  Cs *(1.0f - specular_weight) * diffuse_weight//Kd
					);

		out->Ci += (Cspecular 

					+ CReflectSpecular* 
					  specular_color   * specular_weight * (1.0f - reflection_weight)*(is_metal?Cs:WHITE)//Ks
					
					+ CSpecularReflection* 
					  reflection_color * specular_weight * reflection_weight * (is_metal?Cs:WHITE)//Kr
					
					+ CRefraction*
					  refraction_color * specular_weight * refraction_weight * (1.0f-translucency_weight) * (is_metal?Cs:WHITE)//Kt			
					);

#ifdef USE_AOV_aov_ambient
		aov_ambient() += ( i_ambientColor() 
							*(CReflectDiffuse *
							  Cs *(1.0f - specular_weight) * diffuse_weight//Kd
							 )
						 ) * (1.0f - o_outTransparency());
#endif
#ifdef USE_AOV_aov_diffuse
		aov_diffuse() += ( Cdiffuse * i_color() ) * (1.0f - o_outTransparency());
#endif
#ifdef USE_AOV_aov_specular
		aov_specular() += (Cspecular
							+ CReflectSpecular* 
							specular_color   * specular_weight * (1.0f - reflection_weight)*(is_metal?Cs:WHITE)//Ks

							+ CSpecularReflection* 
							reflection_color * specular_weight * reflection_weight * (is_metal?Cs:WHITE)//Kr

							+ CRefraction*
							refraction_color * specular_weight * refraction_weight * (1.0f-translucency_weight) * (is_metal?Cs:WHITE)//Kt			
							);
#endif


		if ( ! less_than( &i_transparency(), LIQ_SCALAR_EPSILON ) )
		{//transparent
			out->Ci = out->Ci * ( 1.0f - i_transparency() ) + trace_transparent() * i_transparency();
		}//else{ opacity }

		Rs->~BSDF();
		Rts->~BSDF();
	}