浏览代码

Merge pull request #2439 from riccardobl/fixPBR

 PBR Fixes: Apply band factor to spherical harmonic coefficients in accelerated baker light and prevent fireflies artifacts
Ryan McDonough 3 月之前
父节点
当前提交
8cec96fffa

+ 3 - 2
jme3-core/src/main/java/com/jme3/environment/EnvironmentProbeControl.java

@@ -287,8 +287,9 @@ public class EnvironmentProbeControl extends LightProbe implements Control {
     }
 
     void rebakeNow(RenderManager renderManager) {
-        IBLHybridEnvBakerLight baker = new IBLGLEnvBakerLight(renderManager, assetManager, Format.RGB16F, Format.Depth,
-                envMapSize, envMapSize);
+        IBLHybridEnvBakerLight baker = new IBLGLEnvBakerLight(renderManager, assetManager, Format.RGB16F,
+                Format.Depth,
+                        envMapSize, envMapSize);
                     
         baker.setTexturePulling(isRequiredSavableResults());
         baker.bakeEnvironment(spatial, getPosition(), frustumNear, frustumFar, filter);

+ 3 - 1
jme3-core/src/main/java/com/jme3/environment/FastLightProbeFactory.java

@@ -33,6 +33,7 @@ package com.jme3.environment;
 
 import com.jme3.asset.AssetManager;
 import com.jme3.environment.baker.IBLGLEnvBakerLight;
+import com.jme3.environment.baker.IBLHybridEnvBakerLight;
 import com.jme3.environment.util.EnvMapUtils;
 import com.jme3.light.LightProbe;
 import com.jme3.math.Vector3f;
@@ -74,7 +75,8 @@ public class FastLightProbeFactory {
      * @return The baked LightProbe
      */
     public static LightProbe makeProbe(RenderManager rm, AssetManager am, int size, Vector3f pos, float frustumNear, float frustumFar, Spatial scene) {
-        IBLGLEnvBakerLight baker = new IBLGLEnvBakerLight(rm, am, Format.RGB16F, Format.Depth, size, size);
+        IBLHybridEnvBakerLight baker = new IBLGLEnvBakerLight(rm, am, Format.RGB16F, Format.Depth, size,
+                        size);
 
         baker.setTexturePulling(true);
         baker.bakeEnvironment(scene, pos, frustumNear, frustumFar, null);

+ 4 - 2
jme3-core/src/main/java/com/jme3/environment/baker/IBLGLEnvBakerLight.java

@@ -34,6 +34,7 @@ package com.jme3.environment.baker;
 import java.nio.ByteBuffer;
 import java.util.logging.Logger;
 import com.jme3.asset.AssetManager;
+import com.jme3.environment.util.EnvMapUtils;
 import com.jme3.material.Material;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.FastMath;
@@ -130,11 +131,12 @@ public class IBLGLEnvBakerLight extends IBLHybridEnvBakerLight {
                 int s = renderOnT;
                 renderOnT = renderOnT == 0 ? 1 : 0;
                 mat.setTexture("ShCoef", shCoefTx[s]);
-                mat.setInt("FaceId", faceId);
             } else {
                 renderOnT = 0;
             }
 
+            mat.setInt("FaceId", faceId);
+
             screen.updateLogicalState(0);
             screen.updateGeometricState();
 
@@ -169,7 +171,7 @@ public class IBLGLEnvBakerLight extends IBLHybridEnvBakerLight {
             if (remapMaxValue > 0) shCoef[i].divideLocal(remapMaxValue);
             shCoef[i].multLocal(4.0f * FastMath.PI / weightAccum);
         }
-
+        EnvMapUtils.prepareShCoefs(shCoef);
         img.dispose();
 
     }

+ 1 - 0
jme3-core/src/main/java/com/jme3/environment/baker/IBLHybridEnvBakerLight.java

@@ -200,6 +200,7 @@ public class IBLHybridEnvBakerLight extends GenericEnvBaker implements IBLEnvBak
     @Override
     public void bakeSphericalHarmonicsCoefficients() {
         shCoef = EnvMapUtils.getSphericalHarmonicsCoefficents(getEnvMap());
+        EnvMapUtils.prepareShCoefs(shCoef);
     }
 
     @Override

+ 14 - 7
jme3-core/src/main/resources/Common/IBL/IBLKernels.frag

@@ -34,7 +34,7 @@ void brdfKernel(){
         float NdotH = max(H.z, 0.0);
         float VdotH = max(dot(V, H), 0.0);
         if(NdotL > 0.0){
-            float G = GeometrySmith(N, V, L, m_Roughness);
+            float G = GeometrySmith(N, V, L, m_Roughness*m_Roughness);
             float G_Vis = (G * VdotH) / (NdotH * NdotV);
             float Fc = pow(1.0 - VdotH, 5.0);
             A += (1.0 - Fc) * G_Vis;
@@ -75,9 +75,7 @@ void prefilteredEnvKernel(){
     vec3 R = N;
     vec3 V = R;
 
-    // float a2 = m_Roughness;
-    float a2 = m_Roughness * m_Roughness; // jme impl, why?
-    a2 *= a2;
+    float a2 = m_Roughness * m_Roughness; 
 
     const uint SAMPLE_COUNT = 1024u;
     float totalWeight = 0.0;   
@@ -85,16 +83,25 @@ void prefilteredEnvKernel(){
     for(uint i = 0u; i < SAMPLE_COUNT; ++i) {
         vec4 Xi = Hammersley(i, SAMPLE_COUNT);
         vec3 H  = ImportanceSampleGGX(Xi, a2, N);
-        float VoH = dot(V,H);
+        float VoH = max(dot(V, H), 0.0);
         vec3 L  = normalize(2.0 * VoH * H - V);
         float NdotL = max(dot(N, L), 0.0);
         if(NdotL > 0.0) {
+            vec3 sampleColor = texture(m_EnvMap, L).rgb;
+            
+            float luminance = dot(sampleColor, vec3(0.2126, 0.7152, 0.0722));
+            if (luminance > 64.0) { // TODO use average?
+                sampleColor *= 64.0/luminance;
+            }
+            
             // TODO: use mipmap
-            prefilteredColor += texture(m_EnvMap, L).rgb * NdotL;
+            prefilteredColor += sampleColor * NdotL;
             totalWeight      += NdotL;
         }
+
     }
-    prefilteredColor = prefilteredColor / totalWeight;
+
+    if(totalWeight > 0.001) prefilteredColor /= totalWeight;       
     outFragColor = vec4(prefilteredColor, 1.0);
 }