import Base from '../core/Base';
import Vector3 from '../math/Vector3';
import PerspectiveCamera from '../camera/Perspective';
import FrameBuffer from '../FrameBuffer';
var targets = ['px', 'nx', 'py', 'ny', 'pz', 'nz'];
/**
* Pass rendering scene to a environment cube map
*
* @constructor clay.prePass.EnvironmentMap
* @extends clay.core.Base
* @example
* // Example of car reflection
* var envMap = new clay.TextureCube({
* width: 256,
* height: 256
* });
* var envPass = new clay.prePass.EnvironmentMap({
* position: car.position,
* texture: envMap
* });
* var carBody = car.getChildByName('body');
* carBody.material.enableTexture('environmentMap');
* carBody.material.set('environmentMap', envMap);
* ...
* animation.on('frame', function(frameTime) {
* envPass.render(renderer, scene);
* renderer.render(scene, camera);
* });
*/
var EnvironmentMapPass = Base.extend(function() {
var ret = /** @lends clay.prePass.EnvironmentMap# */ {
/**
* Camera position
* @type {clay.Vector3}
* @memberOf clay.prePass.EnvironmentMap#
*/
position: new Vector3(),
/**
* Camera far plane
* @type {number}
* @memberOf clay.prePass.EnvironmentMap#
*/
far: 1000,
/**
* Camera near plane
* @type {number}
* @memberOf clay.prePass.EnvironmentMap#
*/
near: 0.1,
/**
* Environment cube map
* @type {clay.TextureCube}
* @memberOf clay.prePass.EnvironmentMap#
*/
texture: null,
/**
* Used if you wan't have shadow in environment map
* @type {clay.prePass.ShadowMap}
*/
shadowMapPass: null,
};
var cameras = ret._cameras = {
px: new PerspectiveCamera({ fov: 90 }),
nx: new PerspectiveCamera({ fov: 90 }),
py: new PerspectiveCamera({ fov: 90 }),
ny: new PerspectiveCamera({ fov: 90 }),
pz: new PerspectiveCamera({ fov: 90 }),
nz: new PerspectiveCamera({ fov: 90 })
};
cameras.px.lookAt(Vector3.POSITIVE_X, Vector3.NEGATIVE_Y);
cameras.nx.lookAt(Vector3.NEGATIVE_X, Vector3.NEGATIVE_Y);
cameras.py.lookAt(Vector3.POSITIVE_Y, Vector3.POSITIVE_Z);
cameras.ny.lookAt(Vector3.NEGATIVE_Y, Vector3.NEGATIVE_Z);
cameras.pz.lookAt(Vector3.POSITIVE_Z, Vector3.NEGATIVE_Y);
cameras.nz.lookAt(Vector3.NEGATIVE_Z, Vector3.NEGATIVE_Y);
// FIXME In windows, use one framebuffer only renders one side of cubemap
ret._frameBuffer = new FrameBuffer();
return ret;
}, /** @lends clay.prePass.EnvironmentMap# */ {
/**
* @param {string} target
* @return {clay.Camera}
*/
getCamera: function (target) {
return this._cameras[target];
},
/**
* @param {clay.Renderer} renderer
* @param {clay.Scene} scene
* @param {boolean} [notUpdateScene=false]
*/
render: function(renderer, scene, notUpdateScene) {
var _gl = renderer.gl;
if (!notUpdateScene) {
scene.update();
}
// Tweak fov
// http://the-witness.net/news/2012/02/seamless-cube-map-filtering/
var n = this.texture.width;
var fov = 2 * Math.atan(n / (n - 0.5)) / Math.PI * 180;
for (var i = 0; i < 6; i++) {
var target = targets[i];
var camera = this._cameras[target];
Vector3.copy(camera.position, this.position);
camera.far = this.far;
camera.near = this.near;
camera.fov = fov;
if (this.shadowMapPass) {
camera.update();
// update boundingBoxLastFrame
var bbox = scene.getBoundingBox();
bbox.applyTransform(camera.viewMatrix);
scene.viewBoundingBoxLastFrame.copy(bbox);
this.shadowMapPass.render(renderer, scene, camera, true);
}
this._frameBuffer.attach(
this.texture, _gl.COLOR_ATTACHMENT0,
_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i
);
this._frameBuffer.bind(renderer);
renderer.render(scene, camera, true);
this._frameBuffer.unbind(renderer);
}
},
/**
* @param {clay.Renderer} renderer
*/
dispose: function (renderer) {
this._frameBuffer.dispose(renderer);
}
});
export default EnvironmentMapPass;