www.doriengunnels.com/blog

DCG_Lighter

by TheRiverside on Nov.30, 2009, under MEL Scripting Final

Well, here it is…

I’ve finally uploaded my final project from my MEL scripting class. I created a small lighting toolkit that can be used to automate several commonly used tasks when lighting a scene in Maya. The script as well as a PDF description on how to use it can be downloaded from my links page.

Enjoy!

Leave a Comment more...

Happy (Late) Turkey Day

by TheRiverside on Nov.28, 2009, under Misc

Well, it’s the Saturday after Thanksgiving, and, as usual, my family is celebrating the holiday on a completely different day. I guess we’re not much for tradition. :)

I took a nice break from working after my finals week from hell (ie: I slept a LOT). Overall, I’m pretty happy with the way my MEL scripting final turned out. After everything was said and done, I ended up with a working lighting toolkit that I feel is very useful and easily expandable. I plan on uploading the scripts to my site after I write up some short documentation. I’ll also need to trim down the demo video (it’s around 9 minutes long).

As far as my Renderman II final went… well, it wasn’t much to look at. I guess that’s what comes from proposing a final that doesn’t actually have a set final produce :) . It sounds kinda cheesy to say “But I learned a lot!” but it’s true. I learned a great deal about the interaction of light-shaders and surface-shaders and this interaction’s possible application in non-photorealistic rendering. I still need to do a write-up on this project… but it’s coming.

My Photorealistic Rendering class went pretty well. However, there is still a lot of work I think needs to be done before I would think any of these projects are reel-ready.

Anyway, Happy belated Thanksgiving!

-Dorien

1 Comment more...

RSL: Manipulating the Termination Angle of a Light

by TheRiverside on Nov.17, 2009, under Renderman II Final Project

In an earlier post, I made notes on how the Renderman Shading Language uses “illuminance” loops to define how a surface shader reacts to light coming from a light source. The “luminance” loop used to define a Lambertian shading model in RSL is:

Nn = normalize(N);
illuminance( P, Nn, PI/2 )
{

Ln = normalize(L);
Ci += Cs * Cl * Ln.Nn;

}

I mentioned that it is possible to change the termination angle of a light. In reality, if a sphere were to be lit from a light source coming from a specific direction, half the sphere would be in light and half would be in shadow. This termination angle can be defined as being 90 degrees from the light’s direction. If this angle were changed to something above 90, the light would theoretically seem to wrap around the surface.

The illuminance statement needs three arguments. The third of which is a cone angle (measured in radians) used by the shader to sample incoming light (see this post). By default, the angle is “PI/2″ (90 degrees). While this angle is not actually measuring the angle between the light’s direction and the light/shadow termination line, they happen to be equal. If the angle in the illuminance statement were changed to “PI” (180 degrees), the whole surface would be lit.

While it’s possible to manipulate this single value, there is a way to make this a little more useful. By default, light has a natural falloff before the surface transitions completely into shadow. It might be useful to define a point where the transition will start (begin to fade from fully illuminated) and where it will end (the point the surface will be completely in shadow).

This can be done using the following block of code:

color lightColor = color(1,1,1);
color diffuseColor = 0;
normal n = normalize(N);
float lightfall_begin_angle = 0;
float lightfall_end_angle = 90;

illuminance(”wrapper”,P, n, PI ) {

//declare illuminance variables

vector l = normalize(L);
float dot = n.l;

//PROCESS LIGHTWRAP
// note: angle = 0 = facing light
// note: angle = 180 = away from light
float lightfall_begin_radian = radians(lightfall_begin_angle);
float lightfall_end_radian = radians(lightfall_end_angle);
float illum = smoothstep(cos(lightfall_end_radian), cos(lightfall_begin_radian), dot);

diffuseColor += Cl * lightColor * illum;
}

1) Define the lightColor and diffuseColor.

2) Normalize the surface normal N.

3) Define the beginning and ending angles for the falloff (measured from the light’s direction vector L).

4) Define the illuminance loop. In this case, the loop will be applied only when using lights with the category of “wrapper”. Notice that instead of the angle defining the cone being PI/2, it is simply PI. This is so that, by default, the entire surface is sampling the light. The falloff will be done inside the illuminance loop, not by it.

5) Normalize the light’s direction vector L.

6) Take the dot product of the normalized normal N and the normalized vector L. This will essentially give the cosine of the two vectors. This means that a point facing the light will have a “dot” value of 1. A point facing 90 degrees from the light will have a “dot” value of 0. A point facing completely away from the light will have a “dot”value of -1.

7) Convert the beginning and ending falloff angles into radians.

8 ) use the “smoothstep” function to apply the gradient. This way, any value before the “lightfall_begin” angle will be white (in light). Any angle above the “lightfall_end” angle will be black (in shadow). There will be a steady gradient between the two values (the falloff). You have to take the cosine of both radian angles so they can be measured against the “dot” value.

1 Comment more...

Photoshop: Cropping a single layer

by TheRiverside on Nov.15, 2009, under Photoshop

Here’s a little trick I just learned. In Photoshop, if you are resizing a layer, you might want to crop that layer to the size of a specific selection. If you invert that selection and press Delete, it only deletes the visible pixels. If you move the layer around, you’ll notice that there are still pixels kept that were out of frame when you pressed Delete.

In order to keep only the pixels in the selection, just make the selection and press Ctrl+J.  I usually use this just to duplicate (or “jump”) a layer.  However, if you have a specific area selected, it will just jump that selection… trashing the rest of the pixels in the process.  Jump the layer and delete the old one… instant single-layer crop.

Leave a Comment more...

RSL: Passing values from lights shaders to surface shaders

by TheRiverside on Nov.12, 2009, under Renderman II Final Project

Sometimes there are parameters defined in a surface shader that would ideally be controlled by the lighting artist. It is possible to have variables edited in the light and passed to the surface shader.

The process is pretty straight-forward:

In the light, define the editable variable. For example:

In the light shader:

light
wrapperlight(

float intensity = 1;
color lightcolor = 1;
string __category = “wrapper”;
float wrapAngleFromLight = 0)

{

(body)

}

Then, define a variable in the body of the surface shader, and use the “lightsource” function to feed the value from the light shader into the value into the surface shader.

In the body of the surface shader:

float wrapAngleInSurface;

illuminance(”-wrapper”, P, n, PI/2 ){

lightsource(”wrapAngleFromLight”, wrapAngleInSurface);
*rest of illuminance statement*

}

In these examples, the lighter can now change “wrapAngleFromLight” in the light itself. The value will be passed to “wrapAngleInSurface” in the surface shader. The surface shader will then use “wrapAngleInSurface” to perform calculations where the value is needed.

Leave a Comment more...

RSL Notes: illuminate, solar, and illuminance functions and Changing the termination angle of lights

by TheRiverside on Nov.12, 2009, under Renderman II Final Project

Just a few RSL notes…

Illuminance loops:

-Illuminance loops are placed in the surface shader and essentially define how the shader interacts with the light coming from incoming light sources.  There are two forms of this loop:

illuminance(string category“, point position){
statement
}

illuminance(string category“, point position, vector axis, float angle){
statement
}

From the Pixar documentation: “The first form specifies that the integral extends over the entire sphere centered at position. The second form integrates over a cone whose apex is on the surface at position.”

The “cone” created in the second form, is essentially a cone eminating from a position on the surface (usually point P , centered on an axis (usually the surface normal), and spread out using a given angle.  By increasing the cone angle, the user is essentially allowing the sampling of more illumination.  A traditional Lambertian shading model can be defined as:

Nn = normalize(N);
illuminance( P, Nn, PI/2 )
{

Ln = normalize(L);
Ci += Cs * Cl * Ln.Nn;

}

Inside the “luminance” statement, the user is now given access to certain variables:

L – vector – incoming light ray direction
Cl – color – incoming light ray color
Ol – incoming light ray color

Knowing these variables, we can see that the above block of code says:

1) normalize the surface normal N.
2) Check if vector L is detected inside a cone emanating from surface point P (centered on the normalized surface normal and spread using the angle 90 degrees).
3) If L is detected, normalize L. Also, Ci (the apparent surface color of the surface) equals Cs (the actual surface color) times Cl (the light’s color) times the dot product of the normalized N and L vectors.

Changing the termination angle of the light
The angle given in the illuminance loop is always measured in radians. In the code block above, the angle used is PI/2 (90 degrees). This essentially means that the light will stop illuminating the surface 90 degrees from the direction the light is pointing. In the case of a sphere, half the sphere will be illuminated. If this angle is changed below 90 degrees, the light will unrealistically cease to have an effect before the natural termination angle of 90 degrees. If the angle is changed above 90 degrees, this will cause the light to seemingly wrap around the object. The ability to change this termination angle is extremely useful, especially when working with non-photorealistic rendering.  Theoretically, if the angle were changed to 180 degrees, the entirety of the surface would be illuminated regardless of light position or direction.

Light category string
It is possible for surface shaders to contain more than one “illuminance” statement. The “category” string given at the beginning of both types of illuminance loops will state which lights will affect the surface in the way given by that particular illuminance statement. The category is given to the light in the light shader using a flag ” __category” (”category” preceded by two underscores). For example:

light
spotlightWrapper(

float intensity = 1;
color lightcolor = 1;
point from = point “shader” (0,0,0);
point to = point “shader” (0,0,1);
float coneangle = radians(30);
float conedeltaangle = radians(5);
float beamdistribution = 2;
string __category = “wrapper”;

)
{

(body)

}

The category is then called in the surface shader like this:

illuminance(“wrapper”,P, n, PI/2 ) {

Ln = normalize(L);
Ci += Cs * Cl * Ln.Nn;

}


“Illuminate” and “Solar” functions:

These two statements are defined in the light shader.  Like the “illuminance” statement, the user is given access to vector L (the light’s direction) and color Cl (the light’s color).

“Illuminate” function

This function is used when defining light coming from a localized light source (ie: spot lights, point lights, etc.)  and the arguements essentially define a 3d cone eminating from the light source.  Again, there are two forms to this statement:

illuminate( point position )
statement

and

illuminate( point position, vector axis, float angle )
statement

From the Pixar docs:
“The first form specifies that light is cast in all directions. The second form specifies that light is cast only inside the given cone. The length of L inside an illuminate statement is equal to the distance between the light source and the surface currently being shaded.”

Essentially, the arguments say:

The lightsource illuminates from point position, aimed down vector axis, and is spread by angle (measured in radians).  In the first form, since light is being cast in all directions, the statement only needs point position.

“Solar” function

The “solar” function is called when illuminating a surface using a directional light (distance light).  With this type of light, there is not point from which the light is emanating.  Instead, a wall of light is coming evenly from a particular direction.

solar( )
statement

solar( vector axis, float angle )
statement

From the Pixar docs:
“The first form specifies that light is being cast from all points at infinity (e.g., an illumination map). The second form specifies that light is being cast from only directions inside a cone.

An example of the solar statement is the specification of a distant light source:

solar( D, 0 )
Cl = intensity * lightcolor;

This defines a light source at infinity that sends light in the direction D. Since the angle of the cone is 0, all rays from this light are parallel.”

4 Comments more...

Interview with Jay Maisel

by TheRiverside on Nov.09, 2009, under Useful Links

Here is a pretty cool interview i found given by Chris Orwig with photographer Jay Maisel. I think a lot of the insight given here can be applied to many other disciplines.

http://www.chrisorwig.com/flipside/2009/11/08/jay-maisel-interview/

Leave a Comment more...

modelPanel problem… fixed!

by TheRiverside on Nov.08, 2009, under MEL Scripting Final

Yeah… I’m kind of an idiot…

if (`modelPanel -exists dcg_lighter_guiElem_modelPanel_lightLooker`) {
deleteUI -panel dcg_lighter_guiElem_modelPanel_lightLooker;
}

I forgot the -panel flag…

I can now close my “Light Looker” window and reopen it without having to create a new scene.

Leave a Comment more...

modelPanel problem fix?

by TheRiverside on Nov.07, 2009, under MEL Scripting Final

Well, I think I might have a solution to the modelPanel issue in my script.

I spoke to my professor today about the issue. He suggested explicitly deleting the UI element using an “if” statement similar to the way you would delete/refresh the entire UI if the script is run twice without the window being closed.

Deleting the UI:

if (`window -exists dcg_fp_lighterUIWindow`) {
deleteUI dcg_fp_lighterUIWindow;
}

Deleting the UI element:

if (`modelPanel -exists dcg_lighter_guiElem_modelPanel`) {
deleteUI dcg_lighter_guiElem_modelPanel;
}

I thought this would fix my script, end war, fix the economy, and eliminate poverty. It turns out that, as it stands, it did none of the above. When I added the delete-modelPanel block to my script, its almost like it ignored it. When the UI is closed and the script is run a second time, it still errors out saying that the name “dcg_lighter_guiElem_modelPanel” is not unique (in other words, it didn’t delete the modelPanel).

I tried each line individually…

modelPanel -exists dcg_lighter_guiElem_modelPanel;

This returned a value of 1… true… it still exists. Ok, let’s delete it…

deleteUI dcg_lighter_guiElem_modelPanel;

Maya crashes…

Sooo… problem not solved… yet…

Leave a Comment more...

GUI Madness!

by TheRiverside on Nov.06, 2009, under MEL Scripting Final

Well, tonight’s been a pretty long and trying night…

As part of my MEL scripting final project, I’m trying to expand upon a “light dropper” script writen by Jordan Rempel (http://jordanrempel.com/links.html).  This script creates a spotlight with the same translation and rotation value as the perspective camera.  Simple… but pretty cool!

I’m trying to provide the user with the ability to press a button, drop a light (in this case a spot light) at the location of the perspective camera, and quickly look through it using a pre-defined modelPanel.  I would also like to be able to have an object selected.  The light would then auto-correct its rotation (while keeping its translation values the same as the perspective camera) and essentially focus on said object.  The user would then have the freedom to fine-tune the light’s location interactively without having to go to “Look Through Selected”, adjust, then switch back to perspective mode.  Every type of Maya light should have a dedicated button.

I honestly thought that this was a pretty straight-forward task.  It was not meant to be the major part of my final by any means…  I have a lot to learn…

Before I could really start, I had to create a rough User Interface consisting of a button to create the spotlight and a modelPanel with which to look through the light (as well as some other layout elements… trying to plan ahead).  I’m quickly starting to feel that modelPanels are the devil.  To make a long story short, I’ve been wading through layout and parenting issues for hours.  ModelPanels seem to interact much differently with Interfaces than other objects.  Also, aparently modelPanels are not deleted when windows are closed.  Thus, if the script is run a second time, the explicit name I gave the modelPanel is no longer unique, resulting in the script crashing.  I tried letting Maya name the modelPanel and storing it under a variable to call back later.  However, say the script is run two dozen times.  There are two dozen newly-created modelPanels now cluttering up your scene.

Anyway, I now have a very temporary GUI to work with.  After all this, beginning to write the light generation procedure seemed extremely easy.  There are, however, a good many kinks that can’t really be worked out until I figure out a way to manage the modelPanel issue.

I shall now leave you with a script I accidently wrote…

When trying to figure out the best way to judge the distance between an object and the newly created light, I came up with this:

global proc dcg_distanceBetweenObjects()
{
string $selection[] = `ls -selection`;
float $translateObject1[] = `xform -query -translation $selection[0]`;
float $translateObject2[] = `xform -query -translation $selection[1]`;
string $distanceBetween = `distanceDimension -endPoint $translateObject1[0] $translateObject1[1] $translateObject1[2]
-startPoint $translateObject2[0] $translateObject2[1] $translateObject2[2]`;
}

Simply select two objects and run the script (excluding the “global proc” line).  A “distanceDimension” will be created used to interactively show the distance between them.

aaaaaaand it’s 4:12 in the AM…

Goodnight.

Leave a Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...

Archives

All entries, chronologically...