144 lines
4.4 KiB
JavaScript
144 lines
4.4 KiB
JavaScript
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;
|