Sunday, 24 February 2013

scattering material


Our first try with a material with lots of scattering. Almost all of the color of the dragon comes from photon beams being scattered around inside the dragon. It is still painfully slow, and we still haven't used a proper phase function, but I think the soft appearance of the model is a step in the right direction. 


Update with more passes:


Friday, 22 February 2013

Merlot

Rendering of liquids of different concentrations from http://graphics.ucsd.edu/~henrik/papers/acquiring_scattering_properties/

Only a couple of passes on each render.


Merlot

Concentration - 1%


Concentration - 50%

Concentration - 100%

Coke
Concentration - 1%

Concentration - 50%

Concentration - 100%

Chardonnay





Thursday, 14 February 2013

Scattering

First attempt at scattering. One beam is emitted from the left.
Scattering and absorb coefficient = 0.1
Each beam is "traversed" in a Woodcock tracking style with stepsizes given by
-ln ( 1 - rand()) / (max extinction coefficient)

If (rand() < ext / max ext) we scatter.
"ext" is the extinction coefficient in the given point (heterogene media) and "max ext" is the maximum extinction coefficient available in this media.
This means that in homogene media, scattering occur for each step. In heterogene media, scattering is also dependent on how thick the media is at a given point.
In the image below each beam is allowed to scatter every time, the "break off"-beam has right now a complete random direction. Maximum depth of the "scatter-tree" was 4. Whether scattering is allowed might instead be determined by how much light is left in a beam.
Only one initial beam is emitted.

































Only one initial beam is emitted.
In the image below, each beam may scatter once, with a max depth of 4.:






The code for our scattering can be seen below.


while(s < beam.t)
{
//Woodcock tracking over the scattering coefficients
float r = randomRayGenerator.randNum();
s += -log((1-r))/maxScatter;

if(s > beam.t) break;

//if heterogen we have to get the scatter coefficient at the current point
if (hetero) pointExt = beam.pm->getScatter(beam.origin + s*beam.direction, beam.color);

if(((float)rand()/(float)RAND_MAX) < pointExt/maxScatter )  //does a scattering event occur?
{
beam.allowScatter = false;
scatter++;
//the flux of the scattered beam
Vector3 f = beam.flux * exp(-s*beam.pm->getAbsorb(Vector3(0),                                                                                               beam.color));
Vector3 origin = beam.origin + beam.direction*s;

//new ray from the medias phase function
Ray beamRay = randomRayGenerator.rayInCone(origin, beam.direction, beam.pm->getPhase(beam.color));

Beam tempBeam = Beam(origin, beamRay.d, f, beam.radius, beam.scatterDepth + 1, beam.color);
//Bookkeeping
tempBeam.setParMedia(beam.pm);
if(useKDtree){
tempBeam.maxExt = beam.maxExt;
tempBeam.maxScatter = beam.maxScatter;
tempBeam.hasUsedKDtree = false;
}
if(hetero)
{
tempBeam.numberOfPoints = 0;
}
HitInfo beamHitInfo;
//Trace the new beam and add it to the scattering queue. 
if(trace(beamHitInfo, beamRay)){
int depth = 0;
beamHitInfo.material->traceBeam(tempBeam, beamHitInfo, *this, depth+1);
} else { // beam doesn't hit anything.
Vector3 dest = origin + (beamRay.d*maxDistance); 
tempBeam.setT(maxDistance);
tempBeam.setDestination(dest);
if(hetero)
{
tempBeam.woodCockTracking(*this);
}
if(!useKDtree)addBeam(tempBeam);
}
return; 
}
}