Adding Brightness to PV3D Light Source


Many thanks to Ralph Hauwert who wrote PV3D 2.0. As I work through his many classes, I really get the feeling that I am standing on the shoulders of a giant. I got to meet him in LA, where I took his PV3D RMI Certification class. I flew 1500 miles from Kentucky to take his course, and it was worth 100 times every dime I spent to get there.


If you want a sunrise you’ve got to have brightness control. The PV3D point light source only has a distance parameter: used primarily to calculate the angle of the triangle normals – no brightness factor. But adding brightness is all too easy, and in this post we’ll show you how to do it!

We’re going to get right down to the nitty-gritty here, so to learn more about how lights works in Papervision3D (normals, cross products, dot products, etc…) buy the book. There, I explain it all!

Shaders from Light to Dark

Shaders from Light to Dark





If I had any doubt as to where the physics should go, working with light totally solidified it for me. Physics goes into the DisplayObject3D class! And in this case, we just add a simple brightness parameter as shown below:

public function get brightness():Number

return this._brightness;

public function set brightness(value:Number):void
this._brightness = value;


And since my light is a display object it immediately inherits the brightness. Ha! You thought this was going to be hard – it isn’t!

Updating Shaders

Now all you have to do is update all the shaders with your new brightness parameter and boom – you’re done. In Papervision3D there are 5 shaders: flat, cell, gouraud, phong, and environment. And we explain each one in detail in the book.

So open up the Shaders which are located in the


and make the following modifications:


Open up the FlatShadeMaterial and multiply the light brightness by the zd factor.

zAngle = zd*0xff*light.brightness;


Open up the GouraudShadeMaterial and multiply the light brightness by the po, p1, and p2 factors.

p0 *= 127*light.brightness;
p1 *= 127*light.brightness;

p2 *= 127*light.brightness;

Cell, Phong, Environment (three-in-one)

Open up the EnvMapMaterial class and make the following changes:

It seems like a lot, but all you do is multiply the dot product function by (2-light.brightness) .

The changes are in bold below:

p0 = lightmapHalfwidth*(face3D.v0.normal.x * lightMatrix.n11 + face3D.v0.normal.y * lightMatrix.n12 + face3D.v0.normal.z * lightMatrix.n13)*(2-light.brightness) +lightmapHalfwidth;

q0 = lightmapHalfheight*(face3D.v0.normal.x * lightMatrix.n21 + face3D.v0.normal.y * lightMatrix.n22 + face3D.v0.normal.z * lightMatrix.n23)*(2-light.brightness)+lightmapHalfheight;

p1 = lightmapHalfwidth*(face3D.v1.normal.x * lightMatrix.n11 + face3D.v1.normal.y * lightMatrix.n12 + face3D.v1.normal.z * lightMatrix.n13)*(2-light.brightness)+lightmapHalfwidth;

q1 = lightmapHalfheight*(face3D.v1.normal.x * lightMatrix.n21 + face3D.v1.normal.y * lightMatrix.n22 + face3D.v1.normal.z * lightMatrix.n23)*(2-light.brightness)+lightmapHalfheight;

p2 = lightmapHalfwidth*(face3D.v2.normal.x * lightMatrix.n11 + face3D.v2.normal.y * lightMatrix.n12 + face3D.v2.normal.z * lightMatrix.n13)*(2-light.brightness)+lightmapHalfwidth;

q2 = lightmapHalfheight*(face3D.v2.normal.x * lightMatrix.n21 + face3D.v2.normal.y * lightMatrix.n22 + face3D.v2.normal.z * lightMatrix.n23)*(2-light.brightness)+lightmapHalfheight;

That’s it. Just run your shaders like you normally do adjusting your brightness in your animation loop and TaDah! instant rising sun!

Big Note

Keep your brightness value between 0 or 1 or your program will freak, and in the down-loadable source above I renamed the Shader material classes adding a “Brightness” name at the end of them. You don’t have to do this. I did this as a precautionary measure… if I mess up (and I do), I can always go back to the original class.

To see the wrapper file for the shaders download the source above or click the more button below:

Brightness Wrapper Class

package {
// Flash imports
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.StageAlign;
import flash.display.StageScaleMode;

import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.shadematerials.CellMaterialBrightness;
import org.papervision3d.materials.shadematerials.EnvMapMaterialBrightness;
import org.papervision3d.materials.shadematerials.FlatShadeMaterialBrightness;
import org.papervision3d.materials.shadematerials.GouraudMaterialBrightness;
import org.papervision3d.materials.shadematerials.PhongMaterialBrightness;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.view.BasicView;

public class FiveShadersBright extends BasicView {

// Declare Cylinder variables
private var cyl1:Cylinder;
private var cyl2:Cylinder;
private var cyl3:Cylinder;
private var cyl4:Cylinder;
private var cyl5:Cylinder;
// Declare Cylinder holder
private var myHolder:DisplayObject3D;
private var vpX:Number = stage.stageWidth/2;
private var vpY:Number = stage.stageHeight/2;
private var light:PointLight3D;

// Brightness
private var oscbright:Number=0;

public function FiveShadersBright() {
super(0, 0, true, false);

// Initialise Papervision3D

// Create your objects


private function initPV3D():void {

// Set Stage
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
// Set the background to black
opaqueBackground = 0xffffff;

// Place your camera
camera.x = 0;
camera.y = 400;
camera.z = -100;

private function createObjects():void {

// Create your point light source
light = new PointLight3D(true);
light.x = 100;
light.y = 1000;
light.z = -400;

// Create your flat shade material and apply it to your cylinder
var flatShadedMaterial:MaterialObject3D = new FlatShadeMaterialBrightness(light, 0x7799FF, 0x000522);
cyl1 = new Cylinder(flatShadedMaterial, 50, 10, 20, 10);
cyl1.x = -240;

// Create your cell material and apply it to your cylinder
var cellMaterial:MaterialObject3D = new CellMaterialBrightness(light, 0x7799FF, 0x000522, 5);
cyl2 = new Cylinder(cellMaterial, 50, 10, 20,10);
cyl2.x = -120;

// Create your gouraud material and apply it to your cylinder
var gouraudMaterial:MaterialObject3D = new GouraudMaterialBrightness(light, 0x7799FF, 0x000522);
cyl3 = new Cylinder(gouraudMaterial, 50, 10, 20, 10);
cyl3.x = 0;

// Create your phong material and apply it to your cylinder
var phongMaterial:MaterialObject3D = new PhongMaterialBrightness(light, 0x7799FF, 0x000522, 150);
cyl4 = new Cylinder(phongMaterial, 50, 10, 20, 10);
cyl4.x = 120;

// Add and image for your enviornment map
var img:Loader = new Loader();
img.load(new URLRequest(“assets/envmap15.jpg”));
img.contentLoaderInfo.addEventListener(Event.COMPLETE, initenv);

// Create your environment material and apply it to your cylinder
function initenv(event:Event):void{
var envMap:BitmapData =;
var environment:EnvMapMaterialBrightness = new EnvMapMaterialBrightness(light, envMap, envMap, 0x555555);
cyl5 = new Cylinder(environment,50,10,20,10);
cyl5.x = 240;

// Create a holder container for your cylinders
myHolder = new DisplayObject3D();

// Add your Cylinders and light to the scene

// Start rendering the scene

override protected function onRenderTick(event:Event=null):void {

// Rotate your cylinders
/* cyl1.yaw(-2);

cyl5.roll(-2); */

// Rotate Hoder Container
var angleX:Number = (mouseY – vpY) * .5;
var angleY:Number = (mouseX – vpX) * .5;

myHolder.rotationZ = -angleY;
myHolder.rotationX = -angleX;

// Call the Basic View renderer



Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: