io3fix
Version:
toolkit for interior apps
194 lines (173 loc) • 5.49 kB
JavaScript
export default {
schema: {
preset: {
type: 'string',
default: 'studio'
},
intensity: {
type: 'float',
default: 1
},
saturation: {
type: 'float',
default: 1
}
},
init: function () {
var cameraEl = document.querySelector('a-entity[camera]') || document.querySelector('a-camera')
if (!cameraEl) {
console.warn('this scene has no camera, add one to make the lighting work')
return
}
this.cam = cameraEl.object3D
// main
this.staticLights = document.createElement('a-entity')
this.staticLights.id = 'static-lights'
this.movingWithCamera = document.createElement('a-entity')
this.movingWithCamera.id = 'moving-lights'
this.rotatingWithCamera = document.createElement('a-entity')
this.rotatingWithCamera.id = 'rotating-lights'
this.el.appendChild(this.staticLights)
this.el.appendChild(this.movingWithCamera)
this.el.appendChild(this.rotatingWithCamera)
},
update: function () {
if (this.camera) this.cam = this.camera.object3D
// clear existing lights
while (this.movingWithCamera.hasChildNodes()) {
this.movingWithCamera.removeChild(this.movingWithCamera.lastChild);
}
while (this.rotatingWithCamera.hasChildNodes()) {
this.rotatingWithCamera.removeChild(this.rotatingWithCamera.lastChild);
}
while (this.staticLights.hasChildNodes()) {
this.staticLights.removeChild(this.staticLights.lastChild);
}
// create new light setup
createLighting[this.data.preset](
this.movingWithCamera,
this.rotatingWithCamera,
this.staticLights,
this.data.intensity,
this.data.saturation
)
},
remove: function () {
// tear down light setup
this.el.removeChild(this.staticLights)
this.el.removeChild(this.movingWithCamera)
this.el.removeChild(this.rotatingWithCamera)
},
tick: function (dt) {
if (!this.movingWithCamera) return
// set position from camera
this.movingWithCamera.setAttribute('position', this.cam.position)
// set y rotation - convert rad to deg
var lightRotation = {x: 0, y: this.cam.rotation.y * 180 / Math.PI, z: 0}
this.rotatingWithCamera.setAttribute('rotation', AFRAME.utils.coordinates.stringify(lightRotation))
}
}
// configs
var SHADOW_CAMERA_NEAR = 1
var SHADOW_CAMERA_FAR = 60
var SHADOW_SIZE = 20 // real size of shadow map in meters
var SHADOW_MAP_SIZE = 1024 // pixel size of shadow map
var SHADOW_BIAS = 0.001
// var SHADOW_DARKNESS = 0.2
// light presets
var createLighting = {
studio: function(movingWithCamera, rotatingWithCamera, staticLights, intensity, saturation) {
// target for moving directional lights
addElement({
'id': 'light-target',
'position': {x: 0, y: 0, z:-2}
}, movingWithCamera)
// shadow casting top down light
addElement({
'light': {
type: 'directional',
color: '#333',
intensity: 1,
target: '#light-target',
castShadow: true,
shadowCameraLeft: -SHADOW_SIZE / 2,
shadowCameraRight: SHADOW_SIZE / 2,
shadowCameraBottom: -SHADOW_SIZE / 2,
shadowCameraTop: SHADOW_SIZE / 2,
shadowMapHeight: SHADOW_MAP_SIZE,
shadowMapWidth: SHADOW_MAP_SIZE,
shadowBias: SHADOW_BIAS,
shadowCameraNear: SHADOW_CAMERA_NEAR,
shadowCameraFar: SHADOW_CAMERA_FAR
},
'position': {x: 0, y: 10, z:-2},
'id': 'shadow-light'
}, movingWithCamera)
// hemisphere light for yellow - blue tint
addElement({
'light': {
type: 'hemisphere',
// yellow
color: 'hsl(35, ' + Math.round(15 * saturation) + '%, 60%)',
// blue
groundColor: 'hsl(220, ' + Math.round(10 * saturation) + '%, 65%)',
intensity: 0.4 * intensity
},
// positioning left equals rotation by 90°
'position': {x: -2, y: 0, z:0},
'rotation': {x: 0, y: 45, z:0},
'id': 'hemisphere-color'
}, rotatingWithCamera)
// hemisphere light for brightness from front
addElement({
'light': {
type: 'hemisphere',
color: 'hsl(0, 0%, 0%)',
groundColor: 'hsl(0, 0%, 80%)',
intensity: 0.3 * intensity
},
// positioning front equals rotation by 90°
'position': {x: 0, y: 1, z:0},
'id': 'hemisphere-white'
}, rotatingWithCamera)
// lights for specular
// blue
addElement({
'light': {
type: 'directional',
color: 'hsl(200, ' + Math.round(10 * saturation) + '%, 60%)',
intensity: 0.25 * intensity,
// target: '#light-target'
},
'position': {x: 2, y: 2, z:-1},
'id': 'specular-blue'
}, rotatingWithCamera)
// yellow
addElement({
'light': {
type: 'directional',
color: 'hsl(35, ' + Math.round(10 * saturation) + '%, 60%)',
intensity: 0.35 * intensity,
// target: '#light-target'
},
'position': {x: -2, y: 1, z:2},
'id': 'specular-yellow'
}, rotatingWithCamera)
// overall ambient light
addElement({
'light': {
type: 'ambient',
color: '#FFF',
intensity: 0.45
},
'id': 'ambient-light'
}, staticLights)
}
}
function addElement(attributes, parent) {
var el = document.createElement('a-entity')
Object.keys(attributes).forEach(function(key) {
el.setAttribute(key, attributes[key])
})
parent.appendChild(el)
}