Skip to content

Commit

Permalink
Normal offset shadow bias;
Browse files Browse the repository at this point in the history
Fixed bugs with point shadows;
emissiveIntensity;
heightMapMultiplier;
Shader optimizations.
  • Loading branch information
guycalledfrank committed Dec 19, 2014
1 parent bc7a106 commit 3e4f3b9
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 21 deletions.
8 changes: 8 additions & 0 deletions src/framework/components/light/light_component.js
Expand Up @@ -25,6 +25,7 @@ pc.extend(pc.fw, function () {
* @property {Number} shadowDistance The distance from the viewpoint beyond which shadows are no longer rendered. (Directional lights only)
* @property {Number} shadowResolution The size of the texture used for the shadow map. Avaialable sizes are 64, 128, 256, 512, 1024, 2048.
* @property {Number} shadowBias The depth bias for tuning the appearance of the shadow mapping generated by this light.
* @property {Number} normalOffsetShadowBias Normal offset depth bias.
* @property {Number} range The range of the light. (Point and spot lights only)
* @property {Number} innerConeAngle The angle at which the spotlight cone starts to fade off. (Spot lights only)
* @property {Number} outerConeAngle The angle at which the spotlight cone has faded to nothing. (Spot lights only)
Expand All @@ -43,6 +44,7 @@ pc.extend(pc.fw, function () {
this.on("set_shadowDistance", this.onSetShadowDistance, this);
this.on("set_shadowResolution", this.onSetShadowResolution, this);
this.on("set_shadowBias", this.onSetShadowBias, this);
this.on("set_normalOffsetShadowBias", this.onSetNormalOffsetShadowBias, this);
this.on("set_range", this.onSetRange, this);
this.on("set_innerConeAngle", this.onSetInnerConeAngle, this);
this.on("set_outerConeAngle", this.onSetOuterConeAngle, this);
Expand Down Expand Up @@ -80,6 +82,7 @@ pc.extend(pc.fw, function () {
this.onSetShadowDistance("shadowDistance", this.shadowDistance, this.shadowDistance);
this.onSetShadowResolution("shadowResolution", this.shadowResolution, this.shadowResolution);
this.onSetShadowBias("shadowBias", this.shadowBias, this.shadowBias);
this.onSetNormalOffsetShadowBias("normalOffsetShadowBias", this.normalOffsetShadowBias, this.normalOffsetShadowBias);
this.onSetRange("range", this.range, this.range);
this.onSetInnerConeAngle("innerConeAngle", this.innerConeAngle, this.innerConeAngle);
this.onSetOuterConeAngle("outerConeAngle", this.outerConeAngle, this.outerConeAngle);
Expand Down Expand Up @@ -123,6 +126,11 @@ pc.extend(pc.fw, function () {
light.setShadowBias(-0.01 * newValue);
},

onSetNormalOffsetShadowBias: function (name, oldValue, newValue) {
var light = this.data.model.lights[0];
light.setNormalOffsetShadowBias(newValue);
},

onSetRange: function (name, oldValue, newValue) {
if (this.data.type === 'point' || this.data.type === 'spot') {
var light = this.data.model.lights[0];
Expand Down
1 change: 1 addition & 0 deletions src/framework/components/light/light_data.js
Expand Up @@ -9,6 +9,7 @@ pc.extend(pc.fw, function () {
this.shadowDistance = 40;
this.shadowResolution = 1024;
this.shadowBias = 0.05;
this.normalOffsetShadowBias = 0.0;
this.range = 10;
this.innerConeAngle = 40;
this.outerConeAngle = 45;
Expand Down
20 changes: 18 additions & 2 deletions src/framework/components/light/light_system.js
Expand Up @@ -118,6 +118,21 @@ pc.extend(pc.fw, function () {
castShadows: true
}
}, {
name: 'normalOffsetShadowBias',
displayName: 'Normal Offset Shadow Bias',
description: 'Tunes the shadows to reduce rendering artifacts',
type: 'number',
options: {
min: 0,
max: 1,
decimalPrecision: 5,
step: 0.01
},
defaultValue: 0.0,
filter: {
castShadows: true
}
},{
name: "range",
displayName: "Range",
description: "The distance from the light where its contribution falls to zero",
Expand Down Expand Up @@ -206,7 +221,7 @@ pc.extend(pc.fw, function () {
var implementation = this._createImplementation(data.type);
implementation.initialize(component, data);

properties = ['type', 'model', 'enabled', 'color', 'intensity', 'range', 'falloffMode', 'innerConeAngle', 'outerConeAngle', 'castShadows', 'shadowDistance', 'shadowResolution', 'shadowBias'];
properties = ['type', 'model', 'enabled', 'color', 'intensity', 'range', 'falloffMode', 'innerConeAngle', 'outerConeAngle', 'castShadows', 'shadowDistance', 'shadowResolution', 'shadowBias', 'normalOffsetShadowBias'];
LightComponentSystem._super.initializeComponentData.call(this, component, data, properties);
},

Expand Down Expand Up @@ -253,7 +268,8 @@ pc.extend(pc.fw, function () {
shadowDistance: light.shadowDistance,
shadowResolution: light.shadowResolution,
falloffMode: light.falloffMode,
shadowBias: light.shadowBias
shadowBias: light.shadowBias,
normalOffsetShadowBias: light.normalOffsetShadowBias
};

this.addComponent(clone, data);
Expand Down
Binary file modified src/graphics/programlib/chunks/ambientPrefilteredCube.ps
Binary file not shown.
Binary file modified src/graphics/programlib/chunks/ambientPrefilteredCubeLod.ps
Binary file not shown.
Binary file modified src/graphics/programlib/chunks/base.ps
Binary file not shown.
Binary file modified src/graphics/programlib/chunks/lightSpecularBlinn.ps
Binary file not shown.
Binary file modified src/graphics/programlib/chunks/parallax.ps
Binary file not shown.
Binary file modified src/graphics/programlib/chunks/shadow.ps
Binary file not shown.
10 changes: 6 additions & 4 deletions src/graphics/programlib/programlib_depthrgba.js
Expand Up @@ -43,7 +43,7 @@ pc.gfx.programlib.depthrgba = {
if (options.point) {
code += 'uniform vec3 view_position;\n\n';
code += 'uniform float light_radius;\n\n';
code += 'varying float vDistance;\n\n';
code += 'varying vec3 worldPos;\n\n';
}

// VERTEX SHADER BODY
Expand All @@ -69,7 +69,7 @@ pc.gfx.programlib.depthrgba = {
}

if (options.point) {
code += ' vDistance = distance(view_position, positionW.xyz) / light_radius;\n';
code += ' worldPos = positionW.xyz;\n';
}

code += getSnippet(device, 'common_main_end');
Expand All @@ -87,7 +87,9 @@ pc.gfx.programlib.depthrgba = {
}

if (options.point) {
code += 'varying float vDistance;\n\n';
code += 'varying vec3 worldPos;\n\n';
code += 'uniform vec3 view_position;\n\n';
code += 'uniform float light_radius;\n\n';
}

// Packing a float in GLSL with multiplication and mod
Expand All @@ -110,7 +112,7 @@ pc.gfx.programlib.depthrgba = {
}

if (options.point) {
code += " gl_FragData[0] = packFloat(vDistance);\n"
code += " gl_FragData[0] = packFloat(distance(view_position, worldPos) / light_radius);\n"
} else {
code += ' gl_FragData[0] = packFloat(gl_FragCoord.z);\n';
}
Expand Down
27 changes: 24 additions & 3 deletions src/graphics/programlib/programlib_phong.js
Expand Up @@ -6,7 +6,10 @@ pc.gfx.programlib.phong = {
for(prop in options) {
if (prop==="lights") {
for(var i=0; i<options.lights.length; i++) {
props.push(options.lights[i].getType() + "_" + (options.lights[i].getCastShadows() ? 1 : 0) + "_" + options.lights[i].getFalloffMode());
props.push(options.lights[i].getType() + "_"
+ (options.lights[i].getCastShadows() ? 1 : 0) + "_"
+ options.lights[i].getFalloffMode() + "_"
+ !!options.lights[i].getNormalOffsetShadowBias());
}
} else {
if (options[prop]) props.push(prop);
Expand Down Expand Up @@ -440,9 +443,27 @@ pc.gfx.programlib.phong = {
code += " data.atten *= getLightDiffuse(data);\n";
if (options.lights[i].getCastShadows()) {
if (lightType==pc.scene.LIGHTTYPE_POINT) {
code += " data.atten *= getShadowPoint(data, light"+i+"_shadowMap, light"+i+"_shadowParams);\n";
var shadowCoordArgs = "(data, light"+i+"_shadowMap, light"+i+"_shadowParams);\n";
if (!options.lights[i].getNormalOffsetShadowBias()) {
code += " data.atten *= getShadowPoint" + shadowCoordArgs;
} else {
code += " data.atten *= getShadowPointNormalOffset" + shadowCoordArgs;
}
} else {
code += " getShadowCoord(data, light"+i+"_shadowMatrix, light"+i+"_shadowParams);\n";
var shadowCoordArgs = "(data, light"+i+"_shadowMatrix, light"+i+"_shadowParams);\n";
if (!options.lights[i].getNormalOffsetShadowBias()) {
if (lightType==pc.scene.LIGHTTYPE_SPOT) {
code += " getShadowCoordPersp" + shadowCoordArgs;
} else {
code += " getShadowCoordOrtho" + shadowCoordArgs;
}
} else {
if (lightType==pc.scene.LIGHTTYPE_SPOT) {
code += " getShadowCoordPerspNormalOffset" + shadowCoordArgs;
} else {
code += " getShadowCoordOrthoNormalOffset" + shadowCoordArgs;
}
}
code += " data.atten *= getShadowPCF3x3(data, light"+i+"_shadowMap, light"+i+"_shadowParams);\n";
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/scene/scene_forwardrenderer.js
Expand Up @@ -370,7 +370,7 @@ pc.extend(pc.scene, function () {
directional._shadowCamera._renderTarget.colorBuffer;
scope.resolve(light + "_shadowMap").setValue(shadowMap);
scope.resolve(light + "_shadowMatrix").setValue(directional._shadowMatrix.data);
scope.resolve(light + "_shadowParams").setValue([directional._shadowResolution, directional._shadowResolution, directional._shadowBias]);
scope.resolve(light + "_shadowParams").setValue([directional._shadowResolution, directional._normalOffsetShadowBias, directional._shadowBias]);
}
}
},
Expand Down Expand Up @@ -406,7 +406,7 @@ pc.extend(pc.scene, function () {
point._shadowCamera._renderTarget.colorBuffer;
scope.resolve(light + "_shadowMap").setValue(shadowMap);
scope.resolve(light + "_shadowMatrix").setValue(point._shadowMatrix.data);
scope.resolve(light + "_shadowParams").setValue([point._shadowResolution, point._shadowResolution, point._shadowBias, point.getAttenuationEnd()]);
scope.resolve(light + "_shadowParams").setValue([point._shadowResolution, point._normalOffsetShadowBias, point._shadowBias, point.getAttenuationEnd()]);
}
}

Expand All @@ -431,7 +431,7 @@ pc.extend(pc.scene, function () {
spot._shadowCamera._renderTarget.colorBuffer;
scope.resolve(light + "_shadowMap").setValue(shadowMap);
scope.resolve(light + "_shadowMatrix").setValue(spot._shadowMatrix.data);
scope.resolve(light + "_shadowParams").setValue([spot._shadowResolution, spot._shadowResolution, spot._shadowBias]);
scope.resolve(light + "_shadowParams").setValue([spot._shadowResolution, spot._normalOffsetShadowBias, spot._shadowBias]);
}
}
},
Expand Down
13 changes: 13 additions & 0 deletions src/scene/scene_lightnode.js
Expand Up @@ -35,6 +35,7 @@ pc.extend(pc.scene, function () {
this._shadowDistance = 40;
this._shadowResolution = 1024;
this._shadowBias = -0.0005;
this._normalOffsetShadowBias = 0.0;

this._scene = null;
};
Expand Down Expand Up @@ -73,6 +74,7 @@ pc.extend(pc.scene, function () {

// Shadow properties
clone.setShadowBias(this.getShadowBias());
clone.setNormalOffsetShadowBias(this.getNormalOffsetShadowBias());
clone.setShadowResolution(this.getShadowResolution());
clone.setShadowDistance(this.getShadowDistance());
},
Expand Down Expand Up @@ -190,6 +192,10 @@ pc.extend(pc.scene, function () {
return this._shadowBias;
},

getNormalOffsetShadowBias: function () {
return this._normalOffsetShadowBias;
},

/**
* @function
* @name pc.scene.LightNode#getShadowDistance
Expand Down Expand Up @@ -386,6 +392,13 @@ pc.extend(pc.scene, function () {
this._shadowBias = bias;
},

setNormalOffsetShadowBias: function (bias) {
if ((!this._normalOffsetShadowBias && bias) || (this._normalOffsetShadowBias && !bias)) {
this._scene.updateShaders = true;
}
this._normalOffsetShadowBias = bias;
},

/**
* @function
* @name pc.scene.LightNode#setShadowDistance
Expand Down
32 changes: 23 additions & 9 deletions src/scene/scene_phongmaterial.js
Expand Up @@ -177,6 +177,7 @@ pc.extend(pc.scene, function () {
clone.heightMapTiling = this.heightMapTiling ? this.heightMapTiling.clone() : new pc.Vec2(1, 1);
clone.heightMapOffset = this.heightMapOffset ? this.heightMapOffset.clone() : new pc.Vec2(0, 0);
clone.bumpiness = this.bumpiness;
clone.heightMapMultiplier = this.heightMapMultiplier;

clone.cubeMap = this.cubeMap;
clone.prefilteredCubeMap128 = this.prefilteredCubeMap128;
Expand Down Expand Up @@ -204,6 +205,7 @@ pc.extend(pc.scene, function () {
clone.diffuseMapTint = this.diffuseMapTint;
clone.specularMapTint = this.specularMapTint;
clone.emissiveMapTint = this.emissiveMapTint;
clone.emissiveIntensity = this.emissiveIntensity;

clone.update();
return clone;
Expand Down Expand Up @@ -309,6 +311,9 @@ pc.extend(pc.scene, function () {
case 'bumpMapFactor':
this.bumpiness = param.data;
break;
case 'heightMapMultiplier':
this.heightMapMultiplier = param.data;
break;
case 'cubeMap':
this.cubeMap = _createTexture(param);
break;
Expand Down Expand Up @@ -357,6 +362,9 @@ pc.extend(pc.scene, function () {
case 'emissiveMapTint':
this.emissiveMapTint = param.data;
break;
case 'emissiveIntensity':
this.emissiveIntensity = param.data;
break;
case 'depthTest':
this.depthTest = param.data;
break;
Expand Down Expand Up @@ -438,6 +446,7 @@ pc.extend(pc.scene, function () {
this.heightMapOffset = new pc.Vec2(0, 0);
this.heightMapTransform = null;
this.bumpiness = 1;
this.heightMapMultiplier = 1;

this.cubeMap = null;
this.prefilteredCubeMap128 = null;
Expand Down Expand Up @@ -466,6 +475,7 @@ pc.extend(pc.scene, function () {
this.diffuseMapTint = false;
this.specularMapTint = false;
this.emissiveMapTint = false;
this.emissiveIntensity = 1;

// Array to pass uniforms to renderer
this.ambientUniform = new Float32Array(3);
Expand Down Expand Up @@ -584,9 +594,9 @@ pc.extend(pc.scene, function () {
}

if (!this.emissiveMap || (this.blendMapsWithColors && this.emissiveMapTint)) {
this.emissiveUniform[0] = this.emissive.r;
this.emissiveUniform[1] = this.emissive.g;
this.emissiveUniform[2] = this.emissive.b;
this.emissiveUniform[0] = this.emissive.r * this.emissiveIntensity;
this.emissiveUniform[1] = this.emissive.g * this.emissiveIntensity;
this.emissiveUniform[2] = this.emissive.b * this.emissiveIntensity;
this.setParameter('material_emissive', this.emissiveUniform);
}

Expand Down Expand Up @@ -638,10 +648,14 @@ pc.extend(pc.scene, function () {
} else {
}

if (this.normalMap || this.heightMap) {
if (this.normalMap) {
this.setParameter('material_bumpMapFactor', this.bumpiness);
}

if (this.heightMap) {
this.setParameter('material_heightMapFactor', this.heightMapMultiplier * 0.025);
}

if (this.cubeMap) {
this.setParameter('texture_cubeMap', this.cubeMap);
}
Expand Down Expand Up @@ -755,16 +769,16 @@ pc.extend(pc.scene, function () {
modulateAmbient: this.ambientTint,
diffuseMap: !!this.diffuseMap,
diffuseMapTransform: this._getMapTransformID(this.diffuseMapTransform),
needsDiffuseColor: ((this.diffuse.r!=1) || (this.diffuse.g!=1) || (this.diffuse.b!=1)) && this.diffuseMapTint,
needsDiffuseColor: (this.diffuse.r!=1 || this.diffuse.g!=1 || this.diffuse.b!=1) && this.diffuseMapTint,
specularMap: !!this.specularMap,
specularMapTransform: this._getMapTransformID(this.specularMapTransform),
needsSpecularColor: ((this.specular.r!=1) || (this.specular.g!=1) || (this.specular.b!=1)) && this.specularMapTint,
needsSpecularColor: (this.specular.r!=1 || this.specular.g!=1 || this.specular.b!=1) && this.specularMapTint,
glossMap: !!this.glossMap,
glossMapTransform: this._getMapTransformID(this.glossMapTransform),
needsGlossFloat: true,//this.shininess!=100,
emissiveMap: !!this.emissiveMap,
emissiveMapTransform: this._getMapTransformID(this.emissiveMapTransform),
needsEmissiveColor: ((this.emissive.r!=1) || (this.emissive.g!=1) || (this.emissive.b!=1)) && this.emissiveMapTint,
needsEmissiveColor: (this.emissive.r!=1 || this.emissive.g!=1 || this.emissive.b!=1 || this.emissiveIntensity!=1) && this.emissiveMapTint,
opacityMap: !!this.opacityMap,
opacityMapTransform: this._getMapTransformID(this.opacityMapTransform),
needsOpacityFloat: this.opacity!=1,
Expand All @@ -778,7 +792,7 @@ pc.extend(pc.scene, function () {
lightMap: !!this.lightMap,
aoMap: !!this.aoMap,
aoUvSet: this.aoUvSet,
useSpecular: (!!this.specularMap) || !((this.specular.r===0) && (this.specular.g===0) && (this.specular.b===0))
useSpecular: (!!this.specularMap) || !(this.specular.r===0 && this.specular.g===0 && this.specular.b===0)
|| (!!this.sphereMap) || (!!this.cubeMap) || prefilteredCubeMap,
hdrReflection: prefilteredCubeMap? prefilteredCubeMap128.hdr : (this.cubeMap? this.cubeMap.hdr : (this.sphereMap? this.sphereMap.hdr : false)),
prefilteredCubemap: prefilteredCubeMap,
Expand All @@ -804,7 +818,7 @@ pc.extend(pc.scene, function () {
this.ambientUniform[i] = Math.pow(this.ambient.data[i], 2.2);
this.diffuseUniform[i] = Math.pow(this.diffuse.data[i], 2.2);
this.specularUniform[i] = Math.pow(this.specular.data[i], 2.2);
this.emissiveUniform[i] = Math.pow(this.emissive.data[i], 2.2);
this.emissiveUniform[i] = Math.pow(this.emissive.data[i], 2.2) * this.emissiveIntensity;
}
}

Expand Down

0 comments on commit 3e4f3b9

Please sign in to comment.