Benjamin Guignabert 5 年 前
コミット
25985b8c83

+ 28 - 0
src/Engines/Extensions/engine.multiRender.ts

@@ -4,6 +4,7 @@ import { Logger } from '../../Misc/logger';
 import { Nullable } from '../../types';
 import { Constants } from '../constants';
 import { ThinEngine } from '../thinEngine';
+import { IColor4Like } from '../../Maths/math.like';
 
 declare module "../../Engines/thinEngine" {
     export interface ThinEngine {
@@ -35,9 +36,36 @@ declare module "../../Engines/thinEngine" {
          * @returns the effective sample count (could be 0 if multisample render targets are not supported)
          */
         updateMultipleRenderTargetTextureSampleCount(count: number, textures: Nullable<InternalTexture[]>, samples: number): number;
+
+        /**
+         * Clears attachments from index 1 to last index.
+         * @param color Clear color
+         * @param attachments attachments to clear
+         */
+        clearColorAttachments(texture: InternalTexture, color?: IColor4Like) : void;
+    }
+}
+
+ThinEngine.prototype.clearColorAttachments = function(texture: InternalTexture, color?: IColor4Like): void {
+    // Default clear everything to transparent black
+    const gl = this._gl;
+
+    // Texture created with createMultipleRenderTarget should have its attachments
+    const attachments = texture._attachments!.slice(0);
+    attachments[0] = gl.NONE;
+
+    // We don't clear the first attachments which is cleared with the user clear color
+    gl.drawBuffers(attachments);
+    if (color) {
+        gl.clearColor(color.r, color.g, color.b, color.a);
+    } else {
+        gl.clearColor(0, 0, 0, 0);
     }
+
+    gl.clear(gl.COLOR_BUFFER_BIT);
 }
 
+
 ThinEngine.prototype.unBindMultiColorAttachmentFramebuffer = function(count: number, textures: InternalTexture[], disableGenerateMipMaps: boolean = false, onBeforeUnbind?: () => void): void {
     this._currentRenderTarget = null;
 

+ 6 - 1
src/Engines/thinEngine.ts

@@ -1133,7 +1133,7 @@ export class ThinEngine {
      * @param depth defines if the depth buffer must be cleared
      * @param stencil defines if the stencil buffer must be cleared
      */
-    public clear(color: Nullable<IColor4Like>, backBuffer: boolean, depth: boolean, stencil: boolean = false): void {
+    public clear(color: Nullable<IColor4Like>, backBuffer: boolean, depth: boolean, stencil: boolean = false, texture?: InternalTexture): void {
         this.applyStates();
 
         var mode = 0;
@@ -1141,6 +1141,7 @@ export class ThinEngine {
             this._gl.clearColor(color.r, color.g, color.b, color.a !== undefined ? color.a : 1.0);
             mode |= this._gl.COLOR_BUFFER_BIT;
         }
+
         if (depth) {
             if (this.useReverseDepthBuffer) {
                 this._depthCullingState.depthFunc = this._gl.GREATER;
@@ -1155,6 +1156,10 @@ export class ThinEngine {
             mode |= this._gl.STENCIL_BUFFER_BIT;
         }
         this._gl.clear(mode);
+
+        if (texture) {
+            this.clearColorAttachments(texture);
+        }
     }
 
     private _viewportCached = { x: 0, y: 0, z: 0, w: 0 };

+ 31 - 15
src/Shaders/subSurfaceScattering.fragment.fx

@@ -19,6 +19,8 @@ const int _SssSampleBudget = 40;
 
 #define rcp(x) 1. / x
 #define Sq(x) x * x
+#define SSS_BILATERAL_FILTER true
+// #define SSS_CLAMP_ARTIFACT true
 // #define DEBUG_SSS_SAMPLES true
 
 vec3 EvalBurleyDiffusionProfile(float r, vec3 S)
@@ -60,11 +62,30 @@ vec2 SampleBurleyDiffusionProfile(float u, float rcpS)
     return vec2(r, rcpPdf);
 }
 
+// Computes f(r, s)/p(r, s), s.t. r = sqrt(xy^2 + z^2).
+// Rescaling of the PDF is handled by 'totalWeight'.
+vec3 ComputeBilateralWeight(float xy2, float z, float mmPerUnit, vec3 S, float rcpPdf)
+{
+    #ifndef SSS_BILATERAL_FILTER
+        z = 0.;
+    #endif
+
+    // Note: we perform all computation in millimeters.
+    // So we must convert from world units (using 'mmPerUnit') to millimeters.
+    // Only 'z' requires conversion to millimeters.
+    float r = sqrt(xy2 + (z * mmPerUnit) * (z * mmPerUnit));
+    float area = rcpPdf;
+
+    #if SSS_CLAMP_ARTIFACT
+        return clamp(EvalBurleyDiffusionProfile(r, S) * area, 0.0, 1.0);
+    #else
+        return EvalBurleyDiffusionProfile(r, S) * area;
+    #endif
+}
 
 // TODO : inout vec3 totalIrradiance, inout vec3 totalWeight
 void EvaluateSample(int i, int n, vec3 S, float d, vec3 centerPosVS, float mmPerUnit, float pixelsPerMm,
-                    float phase, vec3 tangentX, vec3 tangentY,
-                    inout vec3 totalIrradiance, inout vec3 totalWeight)
+                    float phase, inout vec3 totalIrradiance, inout vec3 totalWeight)
 {
     // The sample count is loop-invariant.
     float scale  = rcp(float(n));
@@ -103,17 +124,19 @@ void EvaluateSample(int i, int n, vec3 S, float d, vec3 centerPosVS, float mmPer
     xy2      = r * r;
 
     vec4 textureSample = texture2D(irradianceSampler, position);
+    float viewZ = texture2D(depthSampler, position).r;
     vec3 irradiance    = textureSample.rgb;
 
     // Check the results of the stencil test.
-    if (true) //TestLightingForSSS(irradiance))
+    // TODO
+    if (true)
     {
         // Apply bilateral weighting.
-        // float  viewZ  = textureSample.a;
-        // float  relZ   = viewZ - centerPosVS.z;
-        vec3 weight = vec3(1.); //ComputeBilateralWeight(xy2, relZ, mmPerUnit, S, rcpPdf);
+        float relZ = viewZ - centerPosVS.z;
+        vec3 weight = ComputeBilateralWeight(xy2, relZ, mmPerUnit, S, rcpPdf);
 
         // Note: if the texture sample if off-screen, (z = 0) -> (viewZ = far) -> (weight ≈ 0).
+        // TODO : HANDLE OFFSCREN
         totalIrradiance += weight * irradiance;
         totalWeight     += weight;
     }
@@ -207,12 +230,7 @@ void main(void)
         return;
     #endif
 
-	// TODO : TANGENT PLANE
-	vec3 normalVS = vec3(0., 0., 0.);
-    vec3 tangentX = vec3(0., 0., 0.);
-    vec3 tangentY = vec3(0., 0., 0.);
-
-    // TODO : RANDOM ROTATION
+    // we dont perform random rotation since we dont have temporal filter
     float phase = 0.;
 
     int n = min(sampleCount, sampleBudget);
@@ -226,10 +244,8 @@ void main(void)
     {
         // Integrate over the image or tangent plane in the view space.
         EvaluateSample(i, n, S, d, centerPosVS, mmPerUnit, pixelsPerMm,
-                       phase, tangentX, tangentY,
-                       totalIrradiance, totalWeight);
+                       phase, totalIrradiance, totalWeight);
     }
-
     // Total weight is 0 for color channels without scattering.
     totalWeight = max(totalWeight, 1e-12);
 

+ 5 - 1
src/scene.ts

@@ -4074,7 +4074,11 @@ export class Scene extends AbstractScene implements IAnimatable {
 
         // Clear
         if (this.autoClearDepthAndStencil || this.autoClear) {
-            this._engine.clear(this.clearColor, this.autoClear || this.forceWireframe || this.forcePointsCloud, this.autoClearDepthAndStencil, this.autoClearDepthAndStencil);
+            this._engine.clear(this.clearColor, 
+                this.autoClear || this.forceWireframe || this.forcePointsCloud, 
+                this.autoClearDepthAndStencil, 
+                this.autoClearDepthAndStencil,
+                this.highDefinitionPipeline ? this.highDefinitionMRT._texture! : undefined);
         }
 
         // Collects render targets from external components.