Thursday, November 21, 2013

[Note] Rendering Equation




Differential Solid Angle:
Since light is measured as energy per unit surface area, when we talk about incoming light, we actually mean the amount of light from a small region instead of a beam with single direction.

Differential solid angle is used here for this purpose.
(radius equals to 1 so it's ignored)
it can be treated as a tiny flat region on the unit hemisphere of the object surface element , and because it's tiny and flat, we can assume this region is uniformly illuminated.

The region where the lights come from doesn't have to be on the hemisphere, it can be from some other surface area in the scene. In this case, the differential solid angle formula needs to be changed a bit:

 

 

BRDF:
BRDF is used to describe how much light is reflected. It's defined as a ratio of reflected light in direction Wo to the amount of light hitting the surface element from direction Wi.

if incoming light is from a region on the hemisphere:

dw is the differential solid angle, and remember it's a tiny area that is uniformly illuminated, so we multiply it by Li to get the total amount of light from that region. And because we need to know the amount of light hitting the object surface element, we have to project light from that region onto the surface element. That's where the cosine comes from.

From this BRDF formula, we can get a basic reflection equation:
Lo = BRDF * Li * cos(theta) * dw

if incoming light is from other surface in the scene which mostly is the case, we need to replace the differential solid angle with the one just mentioned above:

 
 

here we get G (geometry factor) =  

so reflection equation becomes Lo = BRDF * Li * G * V * dA
V here stands for visibility between 2 surface points.

OK, all the formulas above are based on one area of light in and one light out. However, in reality, there should be countless lights from every direction contributing to the final reflected light in the direction of an observer. So no doubt, integral !!

 

fr function inside integral is BRDF


Rendering Equation:
Finally time to get the rendering equation!! Basically, we just need to grab the reflection equation above, and add emitted radiance in it because the surface element itself may also be an emitter:

 

Monday, July 15, 2013

MapKit Test


Just a simple test of MapKit Framework, including MKMapView navigation, adding pins via annotation and overlay :)


Sunday, July 7, 2013

Cocoa MVC




In order to help myself understand how Cocoa MVC works, I wrote a very simple program with implementations including Target-Action, delegate, datasource and KVO mechanism. What it does is to simply allow user to add/remove data in/from the tableview. It also allows editing of contents. When value in the tableview is edited, it would pop up a window displaying "Database Updated!!!". Each row has different color based on salary amount (red if >= 1000, otherwise green).

Here is the code snippet:

controller conforms to datasource and delegate protocol. Properly connections between controller and xib.

@interface TableController : NSObject <NSTableViewDataSource, NSTableViewDelegate> {
    IBOutlet NSTableView *tableview;
    NSMutableArray *database;
}

-(IBAction)add:(id)sender;
-(IBAction)remove:(id)sender;

@end


Target-Action setting for Add button; for each data, add an observer for KVO(Key-Value Observing). reloadData to enforce viewer to update itself via methods from datasource protocol. 

-(IBAction)add:(id)sender {
    Person *person = [[Person alloc]init];
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    [person addObserver:self forKeyPath:@"salary" options:NSKeyValueObservingOptionNew context:nil];
    [database addObject:person];
    [tableview reloadData];
}


For remove button, before removing takes place, remove its observer.

[person removeObserver:self forKeyPath:@"name"];
[person removeObserver:self forKeyPath:@"salary"];


Due to controller being the observer for person object, when user edits values in tableview which in turn changes values of person object, it would notify controller about the changes, here I just simply make it pop up a window.

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSAlert *alert = [[NSAlert alloc]init];
    [alert setMessageText:@"Database Updated!!!"];
    [alert addButtonWithTitle:@"OK"];
    [alert runModal];
}


Implement few methods from datasource protocol, when viewer needs to be updated or user enter new values, it would call these methods for setup.

-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {

    return [database count];
}

-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

    Person *person = [database objectAtIndex:row];
    NSString *identifier = [tableColumn identifier];
    return [person valueForKey:identifier];
}

-(void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    Person *person = [database objectAtIndex:row];
    NSString *identifier = [tableColumn identifier];
    [person setValue:object forKey:identifier];
}


Use delegate protocol to colorize cell based on salary amount

-(void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

    Person *person = [database objectAtIndex:row];
    if(person.salary >= 1000)
    {
        [cell setBackgroundColor:[NSColor redColor]];
        [cell setDrawsBackground:YES];
    }
    else {
        [cell setBackgroundColor:[NSColor greenColor]];
        [cell setDrawsBackground:YES];

    }
}



Friday, June 22, 2012

SPH Fluid Simulation

Recalled from the previous post, there are 2 major approaches used to describe the fluid motion, Eulerian and Lagrangian. Eulerian is grid-based, measuring properties at fixed points in space. Physical values are stored on grids. Lagrangian is particle-based, measuring properties as particles drift through the flow. Physical values are stored on each particle. Both methods have pros and cons. The prevalent methods used nowadays are mostly the hybrids. (e.g. FLIP is the hybrid between particle-based and volume-based).

Let's start from the particle-based approach and take SPH (Smoothed Particle Hydrodynamics) for example. Via discrete particles located arbitrary in space , SPH utilizes weighted summation from adjacent particles to interpolate values and derivative of continuous field.

SPH uses smoothing kernel (W) to determine which adjacent particles have how much contribution of values on one particular point in space. The selected smoothing kernel should be normalized, positive, even and last but not least, no kernel interaction outside the range of the radius "h". The derivatives of the field could be approximated with analytical differentiation:


Since the physical value at point j doesn't directly depend on other components in space, thus, the gradient of the field only has effect on the smoothing kernel. Same for Laplacian.


With above SPH equations, we can start to approximate each term in Navier-Stokes's Equation. Since the main idea of Lagrangian method is the particle itself moves with the fluid, thus the advection term can be ignored, which simplify the equation a lot. For other terms (e.g. density, pressure, viscosity, external forces, etc), they all can be approximated with SPH approach. I won't paste the equation for each term here since they all can be found from lots of material online, and the main purpose of this article is just for getting myself familiar with the big picture and techniques behind the scene. However, there is a thing worth mentioning,  if just using SPH equation above to directly approximate something like pressure and viscosity force, we will confront an asymmertric problem. Think about a situation, if there are only 2 particles with contact in space, the pressure of one particle only uses the pressure force of another, and since the pressure for each partilce may be different, the result pressure will not be symmetrical. These can be fixed with few ways to rewrite the equation.

OK. With the above knowledge, let's talk about the advantages and disadvantages of SPH. There are several benefits of using particle-based approach over pure grid-based method. First of all, the equation is more intuitive and easier to implement. Second, since SPH stores mass on particles, it guarantees the conservation of mass w/o extra calculation. Third, SPH doesn't have to track fluid boundaries; it supports free surface effect. But there still has to be a way for mesh generation for rendering since SPH doesn't contain topology info.

The obvious drawback of using particle methods is the need of large numbers of particles to get more accurate result, which enhances computational cost. The other thing is the density summation would cause problems when neighboring particles have different rest densities (i.e. different masses). This would lead to incorrect pressure and have weird gaps (break into pieces?). Some solutions have been introduced which involves alternative density computation, formulas rewriting and new surface tension model.

What if we need the boundary to limit the movement of particles? One way could be adding boundary particles to prevent penetration and inverse the velocity. Another way is to use Ghost Particles. There is a technical paper about Ghost SPH in the upcoming Siggraph 2012: http://www.cs.ubc.ca/~rbridson/docs/schechter-siggraph2012-ghostsph.pdf