Ver código fonte

Drivers workaround: do not crash if lower mips cannot be computed.

Riccardo Balbo 1 ano atrás
pai
commit
0804ecd44e

+ 4 - 1
jme3-core/src/main/java/com/jme3/environment/EnvironmentProbeControl.java

@@ -136,7 +136,10 @@ public class EnvironmentProbeControl extends LightProbe implements Control {
         baker.bakeSphericalHarmonicsCoefficients();
 
         setPrefilteredMap(baker.getSpecularIBL());
-        setNbMipMaps(getPrefilteredEnvMap().getImage().getMipMapSizes().length);
+        
+        int[] mipSizes = getPrefilteredEnvMap().getImage().getMipMapSizes();
+        setNbMipMaps(mipSizes != null ? mipSizes.length : 1);
+        
         setShCoeffs(baker.getSphericalHarmonicsCoefficients());
         setPosition(Vector3f.ZERO);
         setReady(true);

+ 5 - 2
jme3-core/src/main/java/com/jme3/environment/LightProbeFactory2.java

@@ -70,10 +70,13 @@ public class LightProbeFactory2 {
         baker.bakeSphericalHarmonicsCoefficients();
         
         LightProbe probe = new LightProbe();
-
+ 
         probe.setPosition(pos);
         probe.setPrefilteredMap(baker.getSpecularIBL());
-        probe.setNbMipMaps(probe.getPrefilteredEnvMap().getImage().getMipMapSizes().length);
+        
+        int[] mipSizes = probe.getPrefilteredEnvMap().getImage().getMipMapSizes();
+        probe.setNbMipMaps(mipSizes != null ? mipSizes.length : 1);
+        
         probe.setShCoeffs(baker.getSphericalHarmonicsCoefficients());
         probe.setReady(true);
 

+ 5 - 0
jme3-core/src/main/java/com/jme3/environment/baker/GenericEnvBaker.java

@@ -254,4 +254,9 @@ public abstract class GenericEnvBaker implements EnvBaker {
         tx.getImage().clearUpdateNeeded();
     }
 
+    protected int limitMips(int nbMipMaps, int baseW, int baseH,RenderManager rm) {
+        if (nbMipMaps > 6) nbMipMaps = 6;
+        return nbMipMaps;
+    }
+
 }

+ 72 - 37
jme3-core/src/main/java/com/jme3/environment/baker/IBLGLEnvBaker.java

@@ -33,6 +33,10 @@
 
 package com.jme3.environment.baker;
 
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 import com.jme3.asset.AssetManager;
 import com.jme3.material.Material;
 import com.jme3.math.FastMath;
@@ -58,7 +62,9 @@ import com.jme3.ui.Picture;
  * 
  * @author Riccardo Balbo
  */
-public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker{
+public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker {
+    private final Logger LOGGER=Logger.getLogger(IBLHybridEnvBakerLight.class.getName());
+
     protected Texture2D brtf;
     protected TextureCubeMap irradiance;
     protected TextureCubeMap specular;
@@ -82,11 +88,13 @@ public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker{
         specular.setMinFilter(MinFilter.Trilinear);
         specular.setWrap(WrapMode.EdgeClamp);
         specular.getImage().setColorSpace(ColorSpace.Linear);
-        int nbMipMaps=(int)(Math.log(specular_size)/Math.log(2)+1);
-        if(nbMipMaps>6)nbMipMaps=6;
+        
+        int nbMipMaps = (int) (Math.log(specular_size) / Math.log(2) + 1);
+        nbMipMaps = limitMips(nbMipMaps, specular.getImage().getWidth(), specular.getImage().getHeight(),rm);
+        
         int[] sizes=new int[nbMipMaps];
         for(int i=0;i<nbMipMaps;i++){
-            int size=(int)FastMath.pow(2,nbMipMaps-1-i);
+            int size = (int) FastMath.pow(2, nbMipMaps - 1 - i);
             sizes[i]=size*size*(specular.getImage().getFormat().getBitsPerPixel()/8);
         }
         specular.getImage().setMipMapSizes(sizes);
@@ -103,9 +111,42 @@ public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker{
         return specular;
     }
        
-    public TextureCubeMap getIrradiance(){
+    public TextureCubeMap getIrradiance() {
         return irradiance;
     }
+    
+    private void bakeSpecularIBL(int mip, float roughness, Material mat, Geometry screen) throws Exception {
+        mat.setFloat("Roughness", roughness);
+
+        int mipWidth = (int) (specular.getImage().getWidth() * FastMath.pow(0.5f, mip));
+        int mipHeight = (int) (specular.getImage().getHeight() * FastMath.pow(0.5f, mip));
+
+        FrameBuffer specularbakers[] = new FrameBuffer[6];
+        for (int i = 0; i < 6; i++) {
+            specularbakers[i] = new FrameBuffer(mipWidth, mipHeight, 1);
+            specularbakers[i].setSrgb(false);
+            specularbakers[i].addColorTarget(FrameBufferTarget.newTarget(specular).level(mip).face(i));
+            specularbakers[i].setMipMapsGenerationHint(false);
+        }
+
+        for (int i = 0; i < 6; i++) {
+            FrameBuffer specularbaker = specularbakers[i];
+            mat.setInt("FaceId", i);
+
+            screen.updateLogicalState(0);
+            screen.updateGeometricState();
+
+            renderManager.setCamera(getCam(i, specularbaker.getWidth(), specularbaker.getHeight(), Vector3f.ZERO, 1, 1000), false);
+            renderManager.getRenderer().setFrameBuffer(specularbaker);
+            renderManager.renderGeometry(screen);
+
+            if (isTexturePulling()) pull(specularbaker, specular, i);
+
+        }
+        for (int i = 0; i < 6; i++) {
+            specularbakers[i].dispose();
+        }
+    }
 
     @Override
     public void bakeSpecularIBL() {
@@ -117,44 +158,38 @@ public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker{
         mat.setTexture("EnvMap",env);
         screen.setMaterial(mat);
 
-        if (isTexturePulling())startPulling();
-        
-        for (int mip = 0; mip < specular.getImage().getMipMapSizes().length; mip++) {
-            int mipWidth = (int) (specular.getImage().getWidth() * FastMath.pow(0.5f, mip));
-            int mipHeight = (int) (specular.getImage().getHeight() * FastMath.pow(0.5f, mip));
-
-            FrameBuffer specularbakers[] = new FrameBuffer[6];
-            for (int i = 0; i < 6; i++) {
-                specularbakers[i] = new FrameBuffer(mipWidth, mipHeight, 1);
-                specularbakers[i].setSrgb(false);
-                specularbakers[i].addColorTarget(FrameBufferTarget.newTarget(specular).level(mip).face(i));
-            }
-
-            float roughness = (float) mip / (float) (specular.getImage().getMipMapSizes().length - 1);
-            mat.setFloat("Roughness", roughness);
-
-            for (int i = 0; i < 6; i++) {
-                FrameBuffer specularbaker = specularbakers[i];
-                mat.setInt("FaceId", i);
-
-                screen.updateLogicalState(0);
-                screen.updateGeometricState();
+        if (isTexturePulling()) startPulling();
 
-                renderManager.setCamera(getCam(i, specularbaker.getWidth(), specularbaker.getHeight(), Vector3f.ZERO, 1, 1000), false);
-                renderManager.getRenderer().setFrameBuffer(specularbaker);
-                renderManager.renderGeometry(screen);
-
-                if (isTexturePulling())  pull(specularbaker, specular,i);               
-                
+        int mip = 0;
+        for (; mip < specular.getImage().getMipMapSizes().length; mip++) {
+            try {
+                float roughness = (float) mip / (float) (specular.getImage().getMipMapSizes().length - 1);
+                bakeSpecularIBL(mip, roughness, mat, screen);
+            } catch (Exception e) {
+                LOGGER.log(Level.WARNING,"Error while computing mip level " + mip,e);
+                break;
             }
-            for (int i = 0; i < 6; i++) {
-                specularbakers[i].dispose();
+        }
+        
+        if (mip < specular.getImage().getMipMapSizes().length) {
+            
+            int[] sizes = specular.getImage().getMipMapSizes();            
+            sizes=Arrays.copyOf(sizes,mip);
+            specular.getImage().setMipMapSizes(sizes);
+            specular.getImage().setMipmapsGenerated(true);
+            if (sizes.length <= 1 ) {
+                try {
+                    LOGGER.log(Level.WARNING,"Workaround driver BUG: only one mip level available, regenerate it with higher roughness (shiny fix)");
+                    bakeSpecularIBL(0, 1f, mat, screen);
+                } catch (Exception e) {
+                    LOGGER.log(Level.FINE,"Error while recomputing mip level 0",e);
+                }
             }
         }
         
-        if (isTexturePulling())endPulling(specular);
+        if (isTexturePulling()) endPulling(specular);
         specular.getImage().clearUpdateNeeded();
-        // specular.setMinFilter(MinFilter.Trilinear);        
+      
     }
 
     @Override

+ 64 - 33
jme3-core/src/main/java/com/jme3/environment/baker/IBLHybridEnvBakerLight.java

@@ -32,6 +32,10 @@
 
 package com.jme3.environment.baker;
 
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 import com.jme3.asset.AssetManager;
 import com.jme3.environment.util.EnvMapUtils;
 import com.jme3.material.Material;
@@ -58,6 +62,7 @@ import com.jme3.texture.image.ColorSpace;
  * @author Riccardo Balbo
  */
 public class IBLHybridEnvBakerLight extends GenericEnvBaker implements IBLEnvBakerLight {
+    private final Logger LOGGER=Logger.getLogger(IBLHybridEnvBakerLight.class.getName());
     protected TextureCubeMap specular;
     protected Vector3f[] shCoef;
 
@@ -70,10 +75,11 @@ public class IBLHybridEnvBakerLight extends GenericEnvBaker implements IBLEnvBak
         specular.setWrap(WrapMode.EdgeClamp);
         specular.setMagFilter(MagFilter.Bilinear);
         specular.setMinFilter(MinFilter.Trilinear);
-
         specular.getImage().setColorSpace(ColorSpace.Linear);
+
         int nbMipMaps = (int) (Math.log(specular_size) / Math.log(2) + 1);
-        if (nbMipMaps > 6) nbMipMaps = 6;
+        nbMipMaps = limitMips(nbMipMaps, specular.getImage().getWidth(), specular.getImage().getHeight(),rm);
+
         int[] sizes = new int[nbMipMaps];
         for (int i = 0; i < nbMipMaps; i++) {
             int size = (int) FastMath.pow(2, nbMipMaps - 1 - i);
@@ -89,6 +95,39 @@ public class IBLHybridEnvBakerLight extends GenericEnvBaker implements IBLEnvBak
         return true;
     }
 
+    private void bakeSpecularIBL(int mip, float roughness, Material mat, Geometry screen) throws Exception {
+        mat.setFloat("Roughness", roughness);
+
+        int mipWidth = (int) (specular.getImage().getWidth() * FastMath.pow(0.5f, mip));
+        int mipHeight = (int) (specular.getImage().getHeight() * FastMath.pow(0.5f, mip));
+
+        FrameBuffer specularbakers[] = new FrameBuffer[6];
+        for (int i = 0; i < 6; i++) {
+            specularbakers[i] = new FrameBuffer(mipWidth, mipHeight, 1);
+            specularbakers[i].setSrgb(false);
+            specularbakers[i].addColorTarget(FrameBufferTarget.newTarget(specular).level(mip).face(i));
+            specularbakers[i].setMipMapsGenerationHint(false);
+        }
+
+        for (int i = 0; i < 6; i++) {
+            FrameBuffer specularbaker = specularbakers[i];
+            mat.setInt("FaceId", i);
+
+            screen.updateLogicalState(0);
+            screen.updateGeometricState();
+
+            renderManager.setCamera(getCam(i, specularbaker.getWidth(), specularbaker.getHeight(), Vector3f.ZERO, 1, 1000), false);
+            renderManager.getRenderer().setFrameBuffer(specularbaker);
+            renderManager.renderGeometry(screen);
+
+            if (isTexturePulling()) pull(specularbaker, specular, i);
+
+        }
+        for (int i = 0; i < 6; i++) {
+            specularbakers[i].dispose();
+        }
+    }
+
     @Override
     public void bakeSpecularIBL() {
         Box boxm = new Box(1, 1, 1);
@@ -101,38 +140,30 @@ public class IBLHybridEnvBakerLight extends GenericEnvBaker implements IBLEnvBak
 
         if (isTexturePulling()) startPulling();
 
-        for (int mip = 0; mip < specular.getImage().getMipMapSizes().length; mip++) {
-            int mipWidth = (int) (specular.getImage().getWidth() * FastMath.pow(0.5f, mip));
-            int mipHeight = (int) (specular.getImage().getHeight() * FastMath.pow(0.5f, mip));
-
-            FrameBuffer specularbakers[] = new FrameBuffer[6];
-            for(int i=0;i<6;i++){
-                specularbakers[i]=new FrameBuffer(mipWidth,mipHeight,1);
-                specularbakers[i].setSrgb(false);
-                specularbakers[i].addColorTarget(FrameBufferTarget.newTarget(specular).level(mip).face(i));
-                specularbakers[i].setMipMapsGenerationHint(false);
+        int mip = 0;
+        for (; mip < specular.getImage().getMipMapSizes().length; mip++) {
+            try {
+                float roughness = (float) mip / (float) (specular.getImage().getMipMapSizes().length - 1);
+                bakeSpecularIBL(mip, roughness, mat, screen);
+            } catch (Exception e) {
+                LOGGER.log(Level.WARNING,"Error while computing mip level " + mip,e);
+                break;
             }
-
-
-            float roughness = (float) mip / (float) (specular.getImage().getMipMapSizes().length - 1);
-            mat.setFloat("Roughness", roughness);
-
-            for (int i = 0; i < 6; i++) {
-                FrameBuffer specularbaker = specularbakers[i];
-                mat.setInt("FaceId", i);
-
-                screen.updateLogicalState(0);
-                screen.updateGeometricState();
-
-                renderManager.setCamera(getCam(i, specularbaker.getWidth(), specularbaker.getHeight(), Vector3f.ZERO, 1, 1000), false);
-                renderManager.getRenderer().setFrameBuffer(specularbaker);
-                renderManager.renderGeometry(screen);
-
-                if (isTexturePulling()) pull(specularbaker, specular, i);
-
-            }
-            for (int i = 0; i < 6; i++) {
-                specularbakers[i].dispose();
+        }
+        
+        if (mip < specular.getImage().getMipMapSizes().length) {
+       
+            int[] sizes = specular.getImage().getMipMapSizes();            
+            sizes=Arrays.copyOf(sizes,mip);
+            specular.getImage().setMipMapSizes(sizes);
+            specular.getImage().setMipmapsGenerated(true);
+            if (sizes.length <= 1) {
+                try {
+                    LOGGER.log(Level.WARNING,"Workaround driver BUG: only one mip level available, regenerate it with higher roughness (shiny fix)");
+                    bakeSpecularIBL(0, 1f, mat, screen);
+                } catch (Exception e) {
+                    LOGGER.log(Level.FINE,"Error while recomputing mip level 0",e);
+                }
             }
         }