The following shows a minimum setup to add lights & shadows to a scene which does not contain an explicit ground mesh.
{
scene: {
parameters: {
// Creates a simple ground which automatically receives shadows
[Parameter.ENVIRONMENT_USEDEFAULT]: true,
},
// ...
},
setup: { /* ... */ },
variants: {
CupToGo: {
glTF: 'https://url.to/3d-file.glb',
lights: {
// Add a simple directional light to the scene
MainLight: {
type: 'directional',
shadowGenerator: { mapSize: 1024 },
},
},
parameters: {
// Set some basic properties for the light
[`MainLight.${Parameter.POSITION}`]: '(1, 1, 0.5)',
[`MainLight.${Parameter.DIRECTION}`]: '(-1, -1, -0.5)',
// Set the "Main" element as a shadow caster
[`Main.${Parameter.CAST_SHADOW}`]: true,
},
elements: {
Main: ['ToGoCup'],
},
},
}
}
Here is an overview of all parameters which can be used to setup & adjust ViewerLights & shadows:
A ViewerLight is a wrapper for Babylon.js lights in context of a Variant to provide all functionalities of a VariantParameterizable. Let's have a look at the following example.
{
scene: { /* ... */ },
setup: {
instances: [
{
name: 'MyStreetInstance',
variant: 'MyStreet',
lazy: false,
parameters: {
[Parameter.VISIBLE]: true,
},
},
],
/* ... */
},
variants: {
'MyStreet': {
/* ... */
lights: {
// fully fledged definition
'MyPoint': {
type: 'baked',
path: 'Point',
},
// shorthand definition for type 'baked'
// Note: 'mini' is the path to the light
'MySpot': 'mini',
},
parameters: {
`MyPoint.${Parameter.VISIBLE}`: true,
`MySpot.${Parameter.VISIBLE}`: false,
},
/* ... */
},
}
}
You are able to commit the appropriate Parameters to every light via its Variant.
const my_instance = await viewer.variantInstances.get('MyStreetInstance');
const my_street_variant = my_instance.variant;
const my_point_light = await my_street_variant.getViewerLight('MyPoint');
// Turn off the light!
my_point_light.commitParameter(Parameter.VISIBLE, false);
There's also the possibility to create lights & adjust Parameters via the spec. See the type
property of the
LightDefinition for available types. Behavior for parameters like DIRECTION, for the
HemisphericLight in the following example, are
defined by the underlying Babylon.js class. See Parameters with scope ViewerLight for detailed info about
available parameters per type.
{
scene: { /* ... */ },
setup: { /* ... */ },
variants: {
'MyStreet': {
/* ... */
lights: {
'MyHemispheric': {
type: 'hemispheric',
},
},
parameters: {
`MyHemispheric.${Parameter.VISIBLE}`: true,
`MyHemispheric.${Parameter.DIRECTION}`: '(0, 1, 0)',
},
/* ... */
},
}
}
You can pass a ShadowGenerator to each light in the
spec. All attributes besides the mandatory mapSize
are passed to the constructor of the Babylon.js implementation.
{
scene: { /* ... */ },
setup: { /* ... */ },
variants: {
'MyStreet': {
/* ... */
lights: {
'MySpot': {
type: 'spot',
shadowGenerator: {
mapSize: 1024, // mandatory
usePoissonSampling: true // optional
},
},
},
parameters: {
`MySpot.${Parameter.VISIBLE}`: true,
`MySpot.${Parameter.INTENSITY}`: 5000,
`MySpot.${Parameter.POSITION}`: '(4.5, 5, 3)',
`MySpot.${Parameter.DIRECTION}`: '(-0.5, -1, 0)',
`MySpot.${Parameter.ANGLE}`: Math.PI, // in radians
`MySpot.${Parameter.EXPONENT}`: 1,
},
/* ... */
},
}
}
Any mesh used in any asset can be defined to cast a shadow from the defined generators. The parameter CAST_SHADOW for each Variant and Element is repsonsible for this feature. Have a look at the following example.
{
scene: { /* ... */ },
setup: { /* ... */ },
variants: {
'MyStreet': {
elements: {
'MyShadowCaster': ['__root__.some_other_path'],
},
parameters: {
`MyShadowCaster.${Parameter.CAST_SHADOW}`: true,
},
/* ... */
}
}
}
const my_instance = await viewer.variantInstances.get('MyStreetInstance');
const my_street_variant = my_instance.variant;
const my_element = await my_street_variant.getElement('MyShadowCaster');
my_element.commitParameter(Parameter.CAST_SHADOW, true);
Now we have a shadow caster, we need meshes to receive those shadows. The parameter RECEIVE_SHADOWS
for each Variant and Element does the trick for you. In the following example, each mesh defined in the
Element MyFancyElement
will receive shadows from all generators.
{
scene: { /* ... */ },
setup: { /* ... */ },
variants: {
'MyStreet': {
elements: {
'MyFancyElement': ['__root__.some_path'],
'MyShadowCaster': ['__root__.some_other_path'],
},
parameters: {
`MyFancyElement.${Parameter.RECEIVE_SHADOWS}`: true,
`MyShadowCaster.${Parameter.CAST_SHADOW}`: true,
},
/* ... */
}
}
}
const my_instance = await viewer.variantInstances.get('MyStreetInstance');
const my_street_variant = my_instance.variant;
const my_element = await my_street_variant.getElement('MyFancyElement');
my_element.commitParameter(Parameter.RECEIVE_SHADOWS, true);
By default, defined Elements like above will cast shadows from all defined ViewerLights in the same
Variant (naturally taking inheritance into account). To overrule that, you can define the light sources for each
shadow casting Element by yourself. Just append the optional fromLights
Parameter to the castShadow
Parameter (or use CAST_SHADOW_FROM_LIGHTS) with the names of the ViewerLights (comma
separated) to the Element like follows.
{
scene: { /* ... */ },
setup: { /* ... */ },
variants: {
'MyStreet': {
lights: {
'MySpot': {
type: 'spot',
shadowGenerator: {
mapSize: 1024,
useBlurExponentialShadowMap: true,
},
},
'MySecondSpot': {
type: 'spot',
shadowGenerator: {
mapSize: 1024,
useBlurExponentialShadowMap: true,
},
},
},
elements: {
'MyFancyElement': ['__root__.some_path'],
'MyShadowCaster': ['__root__.some_other_path'],
},
parameters: {
/* MySpot */
`MySpot.${Parameter.VISIBLE}`: true,
`MySpot.${Parameter.INTENSITY}`: 3000,
`MySpot.${Parameter.POSITION}`: '(4.5, 7, -7)',
`MySpot.${Parameter.DIRECTION}`: '(-90, -180, 120)',
`MySpot.${Parameter.ANGLE}`: 90,
`MySpot.${Parameter.EXPONENT}`: 1,
/* MySecondSpot */
`MySecondSpot.${Parameters.INTENSITY}`: 5000,
`MySecondSpot.${Parameters.POSITION}`: '(4.5, 5, 3)',
`MySecondSpot.${Parameters.DIRECTION}`: '(-90, -180, 0)',
`MySecondSpot.${Parameters.ANGLE}`: 90,
`MySecondSpot.${Parameters.EXPONENT}`: 1,
/* Elements */
`MyFancyElement.${Parameter.RECEIVE_SHADOWS}`: true,
`MyShadowCaster.${Parameter.CAST_SHADOW}`: true,
`MyShadowCaster.${Parameter.CAST_SHADOW_FROM_LIGHTS}`: 'MySpot, MySecondSpot',
},
/* ... */
}
}
}
Generated using TypeDoc