|
@@ -3,10 +3,32 @@ module BABYLON {
|
|
* This renderer is helpfull to fill one of the render target with a geometry buffer.
|
|
* This renderer is helpfull to fill one of the render target with a geometry buffer.
|
|
*/
|
|
*/
|
|
export class GeometryBufferRenderer {
|
|
export class GeometryBufferRenderer {
|
|
|
|
+ /**
|
|
|
|
+ * Constant used to retrieve the position texture index in the G-Buffer textures array
|
|
|
|
+ * using getIndex(GeometryBufferRenderer.POSITION_TEXTURE_INDEX)
|
|
|
|
+ */
|
|
|
|
+ public static readonly POSITION_TEXTURE_TYPE = 1;
|
|
|
|
+ /**
|
|
|
|
+ * Constant used to retrieve the velocity texture index in the G-Buffer textures array
|
|
|
|
+ * using getIndex(GeometryBufferRenderer.VELOCITY_TEXTURE_INDEX)
|
|
|
|
+ */
|
|
|
|
+ public static readonly VELOCITY_TEXTURE_TYPE = 2;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Dictionary used to store the previous transformation matrices of each rendered mesh
|
|
|
|
+ * in order to compute objects velocities when enableVelocity is set to "true"
|
|
|
|
+ * @hidden
|
|
|
|
+ */
|
|
|
|
+ public _previousTransformationMatrices: { [index: number]: Matrix } = { };
|
|
|
|
+
|
|
private _scene: Scene;
|
|
private _scene: Scene;
|
|
private _multiRenderTarget: MultiRenderTarget;
|
|
private _multiRenderTarget: MultiRenderTarget;
|
|
private _ratio: number;
|
|
private _ratio: number;
|
|
private _enablePosition: boolean = false;
|
|
private _enablePosition: boolean = false;
|
|
|
|
+ private _enableVelocity: boolean = false;
|
|
|
|
+
|
|
|
|
+ private _positionIndex: number = -1;
|
|
|
|
+ private _velocityIndex: number = -1;
|
|
|
|
|
|
protected _effect: Effect;
|
|
protected _effect: Effect;
|
|
protected _cachedDefines: string;
|
|
protected _cachedDefines: string;
|
|
@@ -27,14 +49,27 @@ module BABYLON {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Gets wether or not position are enabled for the G buffer.
|
|
|
|
|
|
+ * Returns the index of the given texture type in the G-Buffer textures array
|
|
|
|
+ * @param textureType The texture type constant. For example GeometryBufferRenderer.POSITION_TEXTURE_INDEX
|
|
|
|
+ * @returns the index of the given texture type in the G-Buffer textures array
|
|
|
|
+ */
|
|
|
|
+ public getTextureIndex(textureType: number): number {
|
|
|
|
+ switch (textureType) {
|
|
|
|
+ case GeometryBufferRenderer.POSITION_TEXTURE_TYPE: return this._positionIndex;
|
|
|
|
+ case GeometryBufferRenderer.VELOCITY_TEXTURE_TYPE: return this._velocityIndex;
|
|
|
|
+ default: return -1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Gets a boolean indicating if objects positions are enabled for the G buffer.
|
|
*/
|
|
*/
|
|
public get enablePosition(): boolean {
|
|
public get enablePosition(): boolean {
|
|
return this._enablePosition;
|
|
return this._enablePosition;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Sets wether or not position are enabled for the G buffer.
|
|
|
|
|
|
+ * Sets whether or not objects positions are enabled for the G buffer.
|
|
*/
|
|
*/
|
|
public set enablePosition(enable: boolean) {
|
|
public set enablePosition(enable: boolean) {
|
|
this._enablePosition = enable;
|
|
this._enablePosition = enable;
|
|
@@ -43,6 +78,22 @@ module BABYLON {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * Gets a boolean indicating if objects velocities are enabled for the G buffer.
|
|
|
|
+ */
|
|
|
|
+ public get enableVelocity(): boolean {
|
|
|
|
+ return this._enableVelocity;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Sets wether or not objects velocities are enabled for the G buffer.
|
|
|
|
+ */
|
|
|
|
+ public set enableVelocity(enable: boolean) {
|
|
|
|
+ this._enableVelocity = enable;
|
|
|
|
+ this.dispose();
|
|
|
|
+ this._createRenderTargets();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
* Gets the scene associated with the buffer.
|
|
* Gets the scene associated with the buffer.
|
|
*/
|
|
*/
|
|
public get scene(): Scene {
|
|
public get scene(): Scene {
|
|
@@ -112,6 +163,12 @@ module BABYLON {
|
|
// Buffers
|
|
// Buffers
|
|
if (this._enablePosition) {
|
|
if (this._enablePosition) {
|
|
defines.push("#define POSITION");
|
|
defines.push("#define POSITION");
|
|
|
|
+ defines.push("#define POSITION_INDEX " + this._positionIndex);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (this._enableVelocity) {
|
|
|
|
+ defines.push("#define VELOCITY");
|
|
|
|
+ defines.push("#define VELOCITY_INDEX " + this._velocityIndex);
|
|
}
|
|
}
|
|
|
|
|
|
// Bones
|
|
// Bones
|
|
@@ -137,13 +194,16 @@ module BABYLON {
|
|
attribs.push("world3");
|
|
attribs.push("world3");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Setup textures count
|
|
|
|
+ defines.push("#define RENDER_TARGET_COUNT " + this._multiRenderTarget.textures.length);
|
|
|
|
+
|
|
// Get correct effect
|
|
// Get correct effect
|
|
var join = defines.join("\n");
|
|
var join = defines.join("\n");
|
|
if (this._cachedDefines !== join) {
|
|
if (this._cachedDefines !== join) {
|
|
this._cachedDefines = join;
|
|
this._cachedDefines = join;
|
|
this._effect = this._scene.getEngine().createEffect("geometry",
|
|
this._effect = this._scene.getEngine().createEffect("geometry",
|
|
attribs,
|
|
attribs,
|
|
- ["world", "mBones", "viewProjection", "diffuseMatrix", "view"],
|
|
|
|
|
|
+ ["world", "mBones", "viewProjection", "diffuseMatrix", "view", "previousWorldViewProjection"],
|
|
["diffuseSampler"], join,
|
|
["diffuseSampler"], join,
|
|
undefined, undefined, undefined,
|
|
undefined, undefined, undefined,
|
|
{ buffersCount: this._enablePosition ? 3 : 2 });
|
|
{ buffersCount: this._enablePosition ? 3 : 2 });
|
|
@@ -183,7 +243,17 @@ module BABYLON {
|
|
|
|
|
|
protected _createRenderTargets(): void {
|
|
protected _createRenderTargets(): void {
|
|
var engine = this._scene.getEngine();
|
|
var engine = this._scene.getEngine();
|
|
- var count = this._enablePosition ? 3 : 2;
|
|
|
|
|
|
+ var count = 2;
|
|
|
|
+
|
|
|
|
+ if (this._enablePosition) {
|
|
|
|
+ this._positionIndex = count;
|
|
|
|
+ count++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (this._enableVelocity) {
|
|
|
|
+ this._velocityIndex = count;
|
|
|
|
+ count++;
|
|
|
|
+ }
|
|
|
|
|
|
this._multiRenderTarget = new MultiRenderTarget("gBuffer",
|
|
this._multiRenderTarget = new MultiRenderTarget("gBuffer",
|
|
{ width: engine.getRenderWidth() * this._ratio, height: engine.getRenderHeight() * this._ratio }, count, this._scene,
|
|
{ width: engine.getRenderWidth() * this._ratio, height: engine.getRenderHeight() * this._ratio }, count, this._scene,
|
|
@@ -213,6 +283,11 @@ module BABYLON {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Velocity
|
|
|
|
+ if (!this._previousTransformationMatrices[mesh.uniqueId]) {
|
|
|
|
+ this._previousTransformationMatrices[mesh.uniqueId] = Matrix.Identity();
|
|
|
|
+ }
|
|
|
|
+
|
|
// Culling
|
|
// Culling
|
|
engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
|
|
engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
|
|
|
|
|
|
@@ -247,10 +322,16 @@ module BABYLON {
|
|
this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
|
|
this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Velocity
|
|
|
|
+ this._effect.setMatrix("previousWorldViewProjection", this._previousTransformationMatrices[mesh.uniqueId]);
|
|
|
|
+
|
|
// Draw
|
|
// Draw
|
|
mesh._processRendering(subMesh, this._effect, Material.TriangleFillMode, batch, hardwareInstancedRendering,
|
|
mesh._processRendering(subMesh, this._effect, Material.TriangleFillMode, batch, hardwareInstancedRendering,
|
|
(isInstance, world) => this._effect.setMatrix("world", world));
|
|
(isInstance, world) => this._effect.setMatrix("world", world));
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Velocity
|
|
|
|
+ this._previousTransformationMatrices[mesh.uniqueId] = mesh.getWorldMatrix().multiply(this._scene.getTransformMatrix());
|
|
};
|
|
};
|
|
|
|
|
|
this._multiRenderTarget.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
|
|
this._multiRenderTarget.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
|