Просмотр исходного кода

implementing importance sampling

Benjamin Guignabert 5 лет назад
Родитель
Сommit
9968bb51b8

+ 60 - 1
src/Materials/PBR/pbrBaseMaterial.ts

@@ -54,6 +54,10 @@ export class PBRMaterialDefines extends MaterialDefines
     IMaterialSubSurfaceDefines {
     public PBR = true;
 
+    // Debug
+    public NUM_SAMPLES = 16;
+    public DEBUG_REALTIME_SAMPLING = false;
+
     public MAINUV1 = false;
     public MAINUV2 = false;
     public UV1 = false;
@@ -794,6 +798,44 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         return "PBRBaseMaterial";
     }
 
+    public sampleDirections = [0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1,
+                               0, 0, 1
+                               ];
+
+    public weights = [1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+                        1/16,
+    ];
+
+    public debugRealtimeSampling = false;
+
     /**
      * Enabled the use of logarithmic depth buffers, which is good for wide depth buffers.
      */
@@ -1033,6 +1075,18 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
     private _prepareEffect(mesh: AbstractMesh, defines: PBRMaterialDefines, onCompiled: Nullable<(effect: Effect) => void> = null, onError: Nullable<(effect: Effect, errors: string) => void> = null, useInstances: Nullable<boolean> = null, useClipPlane: Nullable<boolean> = null): Nullable<Effect> {
         this._prepareDefines(mesh, defines, useInstances, useClipPlane);
+
+        if (defines.NUM_SAMPLES != this.sampleDirections.length / 3) {
+            defines.markAsUnprocessed();
+            defines.NUM_SAMPLES = this.sampleDirections.length / 3;
+        }
+
+        if (defines.DEBUG_REALTIME_SAMPLING != this.debugRealtimeSampling) {
+            defines.markAsUnprocessed();
+            defines.DEBUG_REALTIME_SAMPLING = this.debugRealtimeSampling;
+        }
+
+
         if (!defines.isDirty) {
             return null;
         }
@@ -1172,7 +1226,9 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             "vSphericalL2_2", "vSphericalL2_1", "vSphericalL20", "vSphericalL21", "vSphericalL22",
             "vReflectionMicrosurfaceInfos",
             "vTangentSpaceParams", "boneTextureWidth",
-            "vDebugMode"
+            "vDebugMode",
+            "sampleDirections",
+            "weights"
         ];
 
         var samplers = ["albedoSampler", "reflectivitySampler", "ambientSampler", "emissiveSampler",
@@ -1651,6 +1707,9 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             this.bindViewProjection(effect);
             reflectionTexture = this._getReflectionTexture();
 
+            effect.setArray3("sampleDirections", this.sampleDirections);
+            effect.setArray("weights", this.weights);
+
             if (!ubo.useUbo || !this.isFrozen || !ubo.isSync) {
 
                 // Texture uniforms

+ 38 - 0
src/Shaders/ShadersInclude/pbrFragmentSamplersDeclaration.fx

@@ -179,6 +179,44 @@
     #endif
 #endif
 
+// debug
+#ifdef DEBUG_REALTIME_SAMPLING
+    #undef sampleReflectionLod
+
+    uniform vec3 sampleDirections[NUM_SAMPLES];
+    uniform float weights[NUM_SAMPLES];
+    vec4 sampleUnfiltered(samplerCube sampler, vec3 direction, float lod) {
+        // Making a transformation matrix to convert z oriented sample direction to input direction
+        vec3 tangent = abs(direction.z) < 0.999 ? vec3(0., 0., 1.) : vec3(1., 0., 0.);
+        tangent = normalize(cross(tangent, direction));
+        vec3 bitangent = cross(direction, tangent);
+        mat3 tbn = mat3(tangent, bitangent, direction);
+
+        vec3 color = vec3(0.);
+        vec3 v;
+        float vDotD;
+        float totalWeight = 0.;
+        for (int i = 0; i < NUM_SAMPLES; i++) {
+            v = tbn * sampleDirections[i];
+            // v = 2. * dot(v, direction) * v - direction;
+            vDotD = clamp(dot(v, direction), 0.0, 1.0);
+            float solidAngleTexel = 4. * 3.14159 / (6. * 512. * 512.);
+            float solidAngleSample = 1.0 / (float(NUM_SAMPLES) * weights[i]);
+            float lod = 0.5 * log2(solidAngleSample/solidAngleTexel) + 1.;
+            if (vDotD > 0.) {
+                color += textureCubeLodEXT(sampler, v, lod).xyz * vDotD;
+                totalWeight += vDotD;            
+            }
+        }
+
+        color /= totalWeight;
+
+        return vec4(color, 1.0);
+    }
+
+    #define sampleReflectionLod(s, c, l) sampleUnfiltered(s, c, l)
+#endif
+
 #ifdef ENVIRONMENTBRDF
     uniform sampler2D environmentBrdfSampler;
 #endif