浏览代码

Add none linear depth to the depth renderer

sebavan 6 年之前
父节点
当前提交
fc48cb9da3
共有 3 个文件被更改,包括 52 次插入7 次删除
  1. 21 2
      src/Rendering/depthRenderer.ts
  2. 5 4
      src/Rendering/depthRendererSceneComponent.ts
  3. 26 1
      src/Shaders/depth.fragment.fx

+ 21 - 2
src/Rendering/depthRenderer.ts

@@ -25,6 +25,8 @@ export class DepthRenderer {
     private _scene: Scene;
     private _depthMap: RenderTargetTexture;
     private _effect: Effect;
+    private readonly _storeNoneLinearDepth: boolean;
+    private readonly _supportsFloat: boolean;
 
     private _cachedDefines: string;
     private _camera: Nullable<Camera>;
@@ -46,16 +48,23 @@ export class DepthRenderer {
      * @param scene The scene the renderer belongs to
      * @param type The texture type of the depth map (default: Engine.TEXTURETYPE_FLOAT)
      * @param camera The camera to be used to render the depth map (default: scene's active camera)
+     * @param storeNoneLinearDepth Defines whether the depth is stored linearly like in Babylon Shadows or directly like glFragCoord.z
      */
-    constructor(scene: Scene, type: number = Constants.TEXTURETYPE_FLOAT, camera: Nullable<Camera> = null) {
+    constructor(scene: Scene, type: number = Constants.TEXTURETYPE_FLOAT, camera: Nullable<Camera> = null, storeNoneLinearDepth = false) {
         this._scene = scene;
+        this._storeNoneLinearDepth = storeNoneLinearDepth;
+        this._supportsFloat = type !== Constants.TEXTURETYPE_UNSIGNED_BYTE;
+
         DepthRenderer._SceneComponentInitialization(this._scene);
 
         this._camera = camera;
         var engine = scene.getEngine();
 
         // Render target
-        this._depthMap = new RenderTargetTexture("depthMap", { width: engine.getRenderWidth(), height: engine.getRenderHeight() }, this._scene, false, true, type);
+        var format = this._supportsFloat ? Constants.TEXTUREFORMAT_R : Constants.TEXTUREFORMAT_RGBA;
+        this._depthMap = new RenderTargetTexture("depthMap", { width: engine.getRenderWidth(), height: engine.getRenderHeight() }, this._scene, false, true, type,
+            false, undefined, undefined, undefined, undefined,
+            format);
         this._depthMap.wrapU = Texture.CLAMP_ADDRESSMODE;
         this._depthMap.wrapV = Texture.CLAMP_ADDRESSMODE;
         this._depthMap.refreshRate = 1;
@@ -214,6 +223,16 @@ export class DepthRenderer {
             MaterialHelper.PushAttributesForInstances(attribs);
         }
 
+        // None linear depth
+        if (this._storeNoneLinearDepth) {
+            defines.push("#define NONELINEARDEPTH");
+        }
+
+        // Float Mode
+        if (this._supportsFloat) {
+            defines.push("#define FLOAT");
+        }
+
         // Get correct effect
         var join = defines.join("\n");
         if (this._cachedDefines !== join) {

+ 5 - 4
src/Rendering/depthRendererSceneComponent.ts

@@ -15,9 +15,10 @@ declare module "../scene" {
         /**
          * Creates a depth renderer a given camera which contains a depth map which can be used for post processing.
          * @param camera The camera to create the depth renderer on (default: scene's active camera)
+         * @param storeNoneLinearDepth Defines whether the depth is stored linearly like in Babylon Shadows or directly like glFragCoord.z
          * @returns the created depth renderer
          */
-        enableDepthRenderer(camera?: Nullable<Camera>): DepthRenderer;
+        enableDepthRenderer(camera?: Nullable<Camera>, storeNoneLinearDepth?: boolean): DepthRenderer;
 
         /**
          * Disables a depth renderer for a given camera
@@ -27,7 +28,7 @@ declare module "../scene" {
     }
 }
 
-Scene.prototype.enableDepthRenderer = function(camera?: Nullable<Camera>): DepthRenderer {
+Scene.prototype.enableDepthRenderer = function(camera?: Nullable<Camera>, storeNoneLinearDepth = false): DepthRenderer {
     camera = camera || this.activeCamera;
     if (!camera) {
         throw "No camera available to enable depth renderer";
@@ -43,9 +44,9 @@ Scene.prototype.enableDepthRenderer = function(camera?: Nullable<Camera>): Depth
         else if (this.getEngine().getCaps().textureFloatRender) {
             textureType = Constants.TEXTURETYPE_FLOAT;
         } else {
-            throw "Depth renderer does not support int texture type";
+            textureType = Constants.TEXTURETYPE_UNSIGNED_BYTE;
         }
-        this._depthRenderer[camera.id] = new DepthRenderer(this, textureType, camera);
+        this._depthRenderer[camera.id] = new DepthRenderer(this, textureType, camera, storeNoneLinearDepth);
     }
 
     return this._depthRenderer[camera.id];

+ 26 - 1
src/Shaders/depth.fragment.fx

@@ -5,6 +5,19 @@ uniform sampler2D diffuseSampler;
 
 varying float vDepthMetric;
 
+#ifndef FLOAT
+	vec4 pack(float depth)
+	{
+		const vec4 bit_shift = vec4(255.0 * 255.0 * 255.0, 255.0 * 255.0, 255.0, 1.0);
+		const vec4 bit_mask = vec4(0.0, 1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0);
+
+		vec4 res = fract(depth * bit_shift);
+		res -= res.xxyz * bit_mask;
+
+		return res;
+	}
+#endif
+
 void main(void)
 {
 #ifdef ALPHATEST
@@ -12,5 +25,17 @@ void main(void)
 		discard;
 #endif
 
-	gl_FragColor = vec4(vDepthMetric, vDepthMetric * vDepthMetric, 0.0, 1.0);
+#ifdef NONELINEARDEPTH
+	#ifdef FLOAT
+		gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0);
+	#else
+		gl_FragColor = pack(gl_FragCoord.z);
+	#endif
+#else
+	#ifdef FLOAT
+		gl_FragColor = vec4(vDepthMetric, 0.0, 0.0, 1.0);
+	#else
+		gl_FragColor = pack(vDepthMetric);
+	#endif
+#endif
 }