TVector3 PrimitiveSuperellipsoid::normalAt( const TIntersection &inter ) const { float x = fabsf( inter.pointWorldSpace[__X] ); float y = fabsf( inter.pointWorldSpace[__Y] ); float z = fabsf( inter.pointWorldSpace[__Z] ); float k = powerf( powerf( x, power[__X] ) + powerf( y, power[__X] ), power[__Y] - 1.0f ); TVector3 N; N[__X] = k * SGNX(inter.pointWorldSpace[__X]) * powerf( x, power[__X] - 1.0f ); N[__Y] = k * SGNX(inter.pointWorldSpace[__Y]) * powerf( y, power[__X] - 1.0f ); // FIXME ? N[__Z] = SGNX(inter.pointWorldSpace[__Z]) * powerf( z, power[__Z] - 1.0f ); N.normalize(); return N; }
TColor LightSquare::getColor( const TWorld &world, const TRay &ray, const TRay &lightRay ) { const TFinish *finish = ray.intersection.texture->finish; stats.increase( TStatistic::STATISTIC_DIFFUSE ); // Diffuse float diffuse = 0.0f; if ( finish->diffuseFactor > 0.0f ) { // FIXME: create a light ray for each dot in square and compute average value // we compute angle between lightRay (from intersection to center of square) // this "trick" is a good approximation if dotSize is small float angleLight = ray.intersection.normal | lightRay.direction; if ( angleLight > 0.0f ) //--float intensity = powf( angleLight, finish->brilliance ); // FIXME diffuse = angleLight * finish->diffuseFactor; } // Specular float specular = 0.0f; if ( finish->specularFactor > 0.0f ) { TVector3 H = lightRay.direction - ray.direction; H.normalize(); float angleSpecular = H | ray.intersection.normal; if ( angleSpecular > 0.0f ) { float intensity = powf( angleSpecular, finish->specularRoughness ); specular = intensity * finish->specularFactor; } } // Phong float phong = 0.0f; if ( finish->phongFactor > 0.0f ) { TVector3 R = reflectVector( ray.direction, ray.intersection.normal ); float anglePhong = R | lightRay.direction; if ( anglePhong > 0.0f ) { float intensity = powf( anglePhong, finish->phongSize ); phong = intensity * finish->phongFactor; } } return color * ( brightness * ( diffuse + specular + phong ) ); }
bool LightSquare::computeLighting( const TWorld &world, const TRay &ray, TLighting &lighting ) { lighting.light = this; lighting.visible = isLighten( ray.intersection.pointWorldSpace ); // If point not in light volume, return false (no diffuse component) if ( !lighting.visible ) return false; const TFinish *finish = ray.intersection.texture->finish; // reset lighting lighting.shadow = 0.0f; lighting.diffuse = 0.0f; lighting.specular = 0.0f; lighting.phong = 0.0f; float att = 0.0f; TRay lightRay; TPoint3 *dotGridIdx = dotGrid; for ( int i = 0; i < numDots; i++, dotGridIdx++ ) { // create a lightRay from dot in grid to intersection lightRay.direction = *dotGridIdx - ray.intersection.pointWorldSpace; float dist2 = lightRay.direction.magnitudeSquared(); lightRay.direction *= fastInvSqrt( dist2 ); // normalize vector lightRay.origin = ray.intersection.pointWorldSpace + lightRay.direction * 0.1f; // origin is intersection lightRay.reverseDirection = inverseVector( lightRay.direction ); lightRay.target = *dotGridIdx; stats.increase( TStatistic::STATISTIC_LIGHT_RAY ); // TODO att += brightness; // if shadow: proceed with next lightRay if ( world.findFirstIntersection( lightRay, ray.intersection, dist2, shadowCache ) ) continue; // if no shadow: add 1.0f (no shadow) to lighting.shadow lighting.shadow += 1.0f; stats.increase( TStatistic::STATISTIC_DIFFUSE ); // Diffuse if ( finish->diffuseFactor > 0.0f ) { float angleLight = ray.intersection.normal | lightRay.direction; if ( angleLight > 0.0f ) //--float intensity = powf( angleLight, finish->brilliance ); // FIXME lighting.diffuse += angleLight * finish->diffuseFactor; } // Specular if ( finish->specularFactor > 0.0f ) { TVector3 H = lightRay.direction - ray.direction; H.normalize(); float angleSpecular = H | ray.intersection.normal; if ( angleSpecular > 0.0f ) { float intensity = powf( angleSpecular, finish->specularRoughness ); lighting.specular += intensity * finish->specularFactor; } } // Phong if ( finish->phongFactor > 0.0f ) { TVector3 R = reflectVector( ray.direction, ray.intersection.normal ); float anglePhong = R | lightRay.direction; if ( anglePhong > 0.0f ) { float intensity = powf( anglePhong, finish->phongSize ); lighting.phong += intensity * finish->phongFactor; } } } // If full shadow, return false (no diffuse component) if ( lighting.shadow <= 0.0f ) return false; // att, shadow, diffuse, specular and phong must be scaled by oneOverNumDots (=N) // att * N * shadow * N * ( diffuse * N + specular * N + phong * N ) // = N*N * ( att * shadow * ( N * ( diffuse + specular + phong ) ) // = N*N*N * ( att * shadow * ( diffuse + specular + phong ) ) lighting.color = color * ( (oneOverNumDots*oneOverNumDots*oneOverNumDots) * att * lighting.shadow * ( lighting.diffuse + lighting.specular + lighting.phong ) ); return true; }
bool LightSquare::computeLighting( const TWorld &world, const TRay &ray, TLighting &lighting ) { lighting.light = this; lighting.visible = isLighten( ray.intersection.pointWorldSpace ); // If point not in light volume, return false (no diffuse component) if ( !lighting.visible ) return false; stats.increase( TStatistic::STATISTIC_LIGHT_RAY ); // Compute vector from intersection to light TRay lightRay; lightRay.direction = location - ray.intersection.pointWorldSpace; float dist2 = lightRay.direction.magnitudeSquared(); // get vector length // test attenuation float att = brightness; //--TODO if ( attenuation ) //--TODO att = ( brightness / ( 1.0f + dist2 ) ); //--TODO if ( att < lightAttenuation ) //--TODO return false; lightRay.direction *= fastInvSqrt( dist2 ); // normalize vector //-- lightRay.origin = ray.intersection.pointWorldSpace + lightRay.direction * 0.1f; // origin is intersection //-- lightRay.reverseDirection = inverseVector( lightRay.direction ); //-- lightRay.target = location; lightRay.kind = TRay::RAY_SHADOW; // Shadow //-- if ( globalSettings::shadowOn //-- && world.findFirstIntersection( lightRay, ray.intersection, dist2, shadowCache ) ) { //-- // If full shadow, return false (no diffuse component) //-- lighting.shadow = 0.0f; // shadow //-- return false; //-- } //-- else //-- lighting.shadow = 1.0f; // no shadow if ( globalSettings::shadowOn ) { lighting.shadow = getAmountShadow( world, ray ); // If full shadow, return false (no diffuse component) if ( lighting.shadow <= 0.0f ) return false; } else lighting.shadow = 1.0f; const TFinish *finish = ray.intersection.texture->finish; stats.increase( TStatistic::STATISTIC_DIFFUSE ); // Diffuse lighting.diffuse = 0.0f; if ( finish->diffuseFactor > 0.0f ) { // FIXME: create a light ray for each dot in square and compute average value // we compute angle between lightRay (from intersection to center of square) // this "trick" is a good approximation if dotSize is small float angleLight = ray.intersection.normal | lightRay.direction; if ( angleLight > 0.0f ) //--float intensity = powf( angleLight, finish->brilliance ); // FIXME lighting.diffuse = angleLight * finish->diffuseFactor; } // Specular lighting.specular = 0.0f; if ( finish->specularFactor > 0.0f ) { TVector3 H = lightRay.direction - ray.direction; H.normalize(); float angleSpecular = H | ray.intersection.normal; if ( angleSpecular > 0.0f ) { float intensity = powf( angleSpecular, finish->specularRoughness ); lighting.specular = intensity * finish->specularFactor; } } // Phong lighting.phong = 0.0f; if ( finish->phongFactor > 0.0f ) { TVector3 R = reflectVector( ray.direction, ray.intersection.normal ); float anglePhong = R | lightRay.direction; if ( anglePhong > 0.0f ) { float intensity = powf( anglePhong, finish->phongSize ); lighting.phong = intensity * finish->phongFactor; } } lighting.color = color * ( att * lighting.shadow * ( lighting.diffuse + lighting.specular + lighting.phong ) ); return true; }
TColor PigmentNoisy::getColor( const TPoint3 &hitPoint ) const { TVector3 p = TurbulenceNoise::getNoise3( hitPoint - anchor ); p.normalize(); return TColor( p[0], p[1], p[2]); }