|
@@ -30,13 +30,11 @@
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
*/
|
|
|
|
|
|
-
|
|
|
|
package com.jme3.environment.baker;
|
|
package com.jme3.environment.baker;
|
|
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
import java.util.logging.Logger;
|
|
-
|
|
|
|
import com.jme3.asset.AssetManager;
|
|
import com.jme3.asset.AssetManager;
|
|
import com.jme3.material.Material;
|
|
import com.jme3.material.Material;
|
|
import com.jme3.math.FastMath;
|
|
import com.jme3.math.FastMath;
|
|
@@ -56,65 +54,69 @@ import com.jme3.texture.FrameBuffer.FrameBufferTarget;
|
|
import com.jme3.texture.image.ColorSpace;
|
|
import com.jme3.texture.image.ColorSpace;
|
|
import com.jme3.ui.Picture;
|
|
import com.jme3.ui.Picture;
|
|
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* Fully accelerated env baker for IBL that runs entirely on the GPU
|
|
* Fully accelerated env baker for IBL that runs entirely on the GPU
|
|
*
|
|
*
|
|
* @author Riccardo Balbo
|
|
* @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());
|
|
|
|
|
|
+ private final Logger LOGGER = Logger.getLogger(IBLHybridEnvBakerLight.class.getName());
|
|
|
|
|
|
protected Texture2D brtf;
|
|
protected Texture2D brtf;
|
|
protected TextureCubeMap irradiance;
|
|
protected TextureCubeMap irradiance;
|
|
protected TextureCubeMap specular;
|
|
protected TextureCubeMap specular;
|
|
- public IBLGLEnvBaker(RenderManager rm,AssetManager am,
|
|
|
|
- Format format,
|
|
|
|
- Format depthFormat,
|
|
|
|
- int env_size,int specular_size,
|
|
|
|
- int irradiance_size,
|
|
|
|
- int brtf_size
|
|
|
|
- ){
|
|
|
|
- super(rm,am,format,depthFormat,env_size);
|
|
|
|
-
|
|
|
|
- irradiance=new TextureCubeMap(irradiance_size,irradiance_size,format);
|
|
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Create a new IBL env baker
|
|
|
|
+ * @param rm The render manager used to render the env scene
|
|
|
|
+ * @param am The asset manager used to load the baking shaders
|
|
|
|
+ * @param format The format of the color buffers
|
|
|
|
+ * @param depthFormat The format of the depth buffers
|
|
|
|
+ * @param env_size The size in pixels of the output environment cube map (eg. 1024)
|
|
|
|
+ * @param specular_size The size in pixels of the output specular cube map (eg. 1024)
|
|
|
|
+ * @param irradiance_size The size in pixels of the output irradiance cube map (eg. 512)
|
|
|
|
+ * @param brtf_size The size in pixels of the output brtf map (eg. 512)
|
|
|
|
+ */
|
|
|
|
+ public IBLGLEnvBaker(RenderManager rm, AssetManager am, Format format, Format depthFormat, int env_size, int specular_size, int irradiance_size, int brtf_size) {
|
|
|
|
+ super(rm, am, format, depthFormat, env_size);
|
|
|
|
+
|
|
|
|
+ irradiance = new TextureCubeMap(irradiance_size, irradiance_size, format);
|
|
irradiance.setMagFilter(MagFilter.Bilinear);
|
|
irradiance.setMagFilter(MagFilter.Bilinear);
|
|
irradiance.setMinFilter(MinFilter.BilinearNoMipMaps);
|
|
irradiance.setMinFilter(MinFilter.BilinearNoMipMaps);
|
|
irradiance.setWrap(WrapMode.EdgeClamp);
|
|
irradiance.setWrap(WrapMode.EdgeClamp);
|
|
irradiance.getImage().setColorSpace(ColorSpace.Linear);
|
|
irradiance.getImage().setColorSpace(ColorSpace.Linear);
|
|
|
|
|
|
- specular=new TextureCubeMap(specular_size,specular_size,format);
|
|
|
|
|
|
+ specular = new TextureCubeMap(specular_size, specular_size, format);
|
|
specular.setMagFilter(MagFilter.Bilinear);
|
|
specular.setMagFilter(MagFilter.Bilinear);
|
|
specular.setMinFilter(MinFilter.Trilinear);
|
|
specular.setMinFilter(MinFilter.Trilinear);
|
|
specular.setWrap(WrapMode.EdgeClamp);
|
|
specular.setWrap(WrapMode.EdgeClamp);
|
|
specular.getImage().setColorSpace(ColorSpace.Linear);
|
|
specular.getImage().setColorSpace(ColorSpace.Linear);
|
|
-
|
|
|
|
|
|
+
|
|
int nbMipMaps = (int) (Math.log(specular_size) / Math.log(2) + 1);
|
|
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++){
|
|
|
|
|
|
+ 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);
|
|
|
|
|
|
+ sizes[i] = size * size * (specular.getImage().getFormat().getBitsPerPixel() / 8);
|
|
}
|
|
}
|
|
specular.getImage().setMipMapSizes(sizes);
|
|
specular.getImage().setMipMapSizes(sizes);
|
|
|
|
|
|
- brtf=new Texture2D(brtf_size,brtf_size,format);
|
|
|
|
|
|
+ brtf = new Texture2D(brtf_size, brtf_size, format);
|
|
brtf.setMagFilter(MagFilter.Bilinear);
|
|
brtf.setMagFilter(MagFilter.Bilinear);
|
|
brtf.setMinFilter(MinFilter.BilinearNoMipMaps);
|
|
brtf.setMinFilter(MinFilter.BilinearNoMipMaps);
|
|
brtf.setWrap(WrapMode.EdgeClamp);
|
|
brtf.setWrap(WrapMode.EdgeClamp);
|
|
brtf.getImage().setColorSpace(ColorSpace.Linear);
|
|
brtf.getImage().setColorSpace(ColorSpace.Linear);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- public TextureCubeMap getSpecularIBL(){
|
|
|
|
|
|
+ public TextureCubeMap getSpecularIBL() {
|
|
return specular;
|
|
return specular;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
public TextureCubeMap getIrradiance() {
|
|
public TextureCubeMap getIrradiance() {
|
|
return irradiance;
|
|
return irradiance;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
private void bakeSpecularIBL(int mip, float roughness, Material mat, Geometry screen) throws Exception {
|
|
private void bakeSpecularIBL(int mip, float roughness, Material mat, Geometry screen) throws Exception {
|
|
mat.setFloat("Roughness", roughness);
|
|
mat.setFloat("Roughness", roughness);
|
|
|
|
|
|
@@ -136,7 +138,7 @@ public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker {
|
|
screen.updateLogicalState(0);
|
|
screen.updateLogicalState(0);
|
|
screen.updateGeometricState();
|
|
screen.updateGeometricState();
|
|
|
|
|
|
- renderManager.setCamera(getCam(i, specularbaker.getWidth(), specularbaker.getHeight(), Vector3f.ZERO, 1, 1000), false);
|
|
|
|
|
|
+ renderManager.setCamera(updateAndGetInternalCamera(i, specularbaker.getWidth(), specularbaker.getHeight(), Vector3f.ZERO, 1, 1000), false);
|
|
renderManager.getRenderer().setFrameBuffer(specularbaker);
|
|
renderManager.getRenderer().setFrameBuffer(specularbaker);
|
|
renderManager.renderGeometry(screen);
|
|
renderManager.renderGeometry(screen);
|
|
|
|
|
|
@@ -150,12 +152,12 @@ public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker {
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public void bakeSpecularIBL() {
|
|
public void bakeSpecularIBL() {
|
|
- Box boxm=new Box(1,1,1);
|
|
|
|
- Geometry screen=new Geometry("BakeBox",boxm);
|
|
|
|
-
|
|
|
|
- Material mat=new Material(assetManager,"Common/IBL/IBLKernels.j3md");
|
|
|
|
- mat.setBoolean("UseSpecularIBL",true);
|
|
|
|
- mat.setTexture("EnvMap",env);
|
|
|
|
|
|
+ Box boxm = new Box(1, 1, 1);
|
|
|
|
+ Geometry screen = new Geometry("BakeBox", boxm);
|
|
|
|
+
|
|
|
|
+ Material mat = new Material(assetManager, "Common/IBL/IBLKernels.j3md");
|
|
|
|
+ mat.setBoolean("UseSpecularIBL", true);
|
|
|
|
+ mat.setTexture("EnvMap", env);
|
|
screen.setMaterial(mat);
|
|
screen.setMaterial(mat);
|
|
|
|
|
|
if (isTexturePulling()) startPulling();
|
|
if (isTexturePulling()) startPulling();
|
|
@@ -166,102 +168,99 @@ public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker {
|
|
float roughness = (float) mip / (float) (specular.getImage().getMipMapSizes().length - 1);
|
|
float roughness = (float) mip / (float) (specular.getImage().getMipMapSizes().length - 1);
|
|
bakeSpecularIBL(mip, roughness, mat, screen);
|
|
bakeSpecularIBL(mip, roughness, mat, screen);
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- LOGGER.log(Level.WARNING,"Error while computing mip level " + mip,e);
|
|
|
|
|
|
+ LOGGER.log(Level.WARNING, "Error while computing mip level " + mip, e);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
if (mip < specular.getImage().getMipMapSizes().length) {
|
|
if (mip < specular.getImage().getMipMapSizes().length) {
|
|
-
|
|
|
|
- int[] sizes = specular.getImage().getMipMapSizes();
|
|
|
|
- sizes=Arrays.copyOf(sizes,mip);
|
|
|
|
|
|
+
|
|
|
|
+ int[] sizes = specular.getImage().getMipMapSizes();
|
|
|
|
+ sizes = Arrays.copyOf(sizes, mip);
|
|
specular.getImage().setMipMapSizes(sizes);
|
|
specular.getImage().setMipMapSizes(sizes);
|
|
specular.getImage().setMipmapsGenerated(true);
|
|
specular.getImage().setMipmapsGenerated(true);
|
|
- if (sizes.length <= 1 ) {
|
|
|
|
|
|
+ if (sizes.length <= 1) {
|
|
try {
|
|
try {
|
|
- LOGGER.log(Level.WARNING,"Workaround driver BUG: only one mip level available, regenerate it with higher roughness (shiny fix)");
|
|
|
|
|
|
+ LOGGER.log(Level.WARNING, "Workaround driver BUG: only one mip level available, regenerate it with higher roughness (shiny fix)");
|
|
bakeSpecularIBL(0, 1f, mat, screen);
|
|
bakeSpecularIBL(0, 1f, mat, screen);
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- LOGGER.log(Level.FINE,"Error while recomputing mip level 0",e);
|
|
|
|
|
|
+ LOGGER.log(Level.FINE, "Error while recomputing mip level 0", e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
if (isTexturePulling()) endPulling(specular);
|
|
if (isTexturePulling()) endPulling(specular);
|
|
specular.getImage().clearUpdateNeeded();
|
|
specular.getImage().clearUpdateNeeded();
|
|
-
|
|
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public Texture2D genBRTF() {
|
|
public Texture2D genBRTF() {
|
|
-
|
|
|
|
- Picture screen=new Picture("BakeScreen",true);
|
|
|
|
|
|
+
|
|
|
|
+ Picture screen = new Picture("BakeScreen", true);
|
|
screen.setWidth(1);
|
|
screen.setWidth(1);
|
|
screen.setHeight(1);
|
|
screen.setHeight(1);
|
|
|
|
|
|
- FrameBuffer brtfbaker=new FrameBuffer(brtf.getImage().getWidth(),brtf.getImage().getHeight(),1);
|
|
|
|
|
|
+ FrameBuffer brtfbaker = new FrameBuffer(brtf.getImage().getWidth(), brtf.getImage().getHeight(), 1);
|
|
brtfbaker.setSrgb(false);
|
|
brtfbaker.setSrgb(false);
|
|
brtfbaker.addColorTarget(FrameBufferTarget.newTarget(brtf));
|
|
brtfbaker.addColorTarget(FrameBufferTarget.newTarget(brtf));
|
|
|
|
|
|
- if(isTexturePulling())startPulling();
|
|
|
|
|
|
+ if (isTexturePulling()) startPulling();
|
|
|
|
|
|
- Camera envcam=getCam(0,brtf.getImage().getWidth(),brtf.getImage().getHeight(),Vector3f.ZERO,1,1000);
|
|
|
|
|
|
+ Camera envcam = updateAndGetInternalCamera(0, brtf.getImage().getWidth(), brtf.getImage().getHeight(), Vector3f.ZERO, 1, 1000);
|
|
|
|
|
|
- Material mat=new Material(assetManager,"Common/IBL/IBLKernels.j3md");
|
|
|
|
- mat.setBoolean("UseBRDF",true);
|
|
|
|
|
|
+ Material mat = new Material(assetManager, "Common/IBL/IBLKernels.j3md");
|
|
|
|
+ mat.setBoolean("UseBRDF", true);
|
|
screen.setMaterial(mat);
|
|
screen.setMaterial(mat);
|
|
|
|
|
|
renderManager.getRenderer().setFrameBuffer(brtfbaker);
|
|
renderManager.getRenderer().setFrameBuffer(brtfbaker);
|
|
- renderManager.setCamera(envcam,false);
|
|
|
|
|
|
+ renderManager.setCamera(envcam, false);
|
|
|
|
|
|
screen.updateLogicalState(0);
|
|
screen.updateLogicalState(0);
|
|
- screen.updateGeometricState();
|
|
|
|
|
|
+ screen.updateGeometricState();
|
|
renderManager.renderGeometry(screen);
|
|
renderManager.renderGeometry(screen);
|
|
|
|
|
|
- if(isTexturePulling()) pull(brtfbaker,brtf,0);
|
|
|
|
-
|
|
|
|
|
|
+ if (isTexturePulling()) pull(brtfbaker, brtf, 0);
|
|
|
|
+
|
|
brtfbaker.dispose();
|
|
brtfbaker.dispose();
|
|
|
|
|
|
if (isTexturePulling()) endPulling(brtf);
|
|
if (isTexturePulling()) endPulling(brtf);
|
|
brtf.getImage().clearUpdateNeeded();
|
|
brtf.getImage().clearUpdateNeeded();
|
|
-
|
|
|
|
|
|
+
|
|
return brtf;
|
|
return brtf;
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public void bakeIrradiance() {
|
|
public void bakeIrradiance() {
|
|
-
|
|
|
|
- Box boxm=new Box(1,1,1);
|
|
|
|
- Geometry screen=new Geometry("BakeBox",boxm);
|
|
|
|
-
|
|
|
|
|
|
|
|
- FrameBuffer irradiancebaker=new FrameBuffer(irradiance.getImage().getWidth(),irradiance.getImage().getHeight(),1);
|
|
|
|
|
|
+ Box boxm = new Box(1, 1, 1);
|
|
|
|
+ Geometry screen = new Geometry("BakeBox", boxm);
|
|
|
|
+
|
|
|
|
+ FrameBuffer irradiancebaker = new FrameBuffer(irradiance.getImage().getWidth(), irradiance.getImage().getHeight(), 1);
|
|
irradiancebaker.setSrgb(false);
|
|
irradiancebaker.setSrgb(false);
|
|
|
|
|
|
- if(isTexturePulling())startPulling();
|
|
|
|
-
|
|
|
|
- for(int i=0;i<6;i++) irradiancebaker.addColorTarget(FrameBufferTarget.newTarget(irradiance).face(TextureCubeMap.Face.values()[i]));
|
|
|
|
|
|
+ if (isTexturePulling()) startPulling();
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < 6; i++) irradiancebaker.addColorTarget(FrameBufferTarget.newTarget(irradiance).face(TextureCubeMap.Face.values()[i]));
|
|
|
|
|
|
- Material mat=new Material(assetManager,"Common/IBL/IBLKernels.j3md");
|
|
|
|
- mat.setBoolean("UseIrradiance",true);
|
|
|
|
- mat.setTexture("EnvMap",env);
|
|
|
|
|
|
+ Material mat = new Material(assetManager, "Common/IBL/IBLKernels.j3md");
|
|
|
|
+ mat.setBoolean("UseIrradiance", true);
|
|
|
|
+ mat.setTexture("EnvMap", env);
|
|
screen.setMaterial(mat);
|
|
screen.setMaterial(mat);
|
|
|
|
|
|
- for(int i=0;i<6;i++){
|
|
|
|
|
|
+ for (int i = 0; i < 6; i++) {
|
|
irradiancebaker.setTargetIndex(i);
|
|
irradiancebaker.setTargetIndex(i);
|
|
|
|
|
|
- mat.setInt("FaceId",i);
|
|
|
|
|
|
+ mat.setInt("FaceId", i);
|
|
|
|
|
|
screen.updateLogicalState(0);
|
|
screen.updateLogicalState(0);
|
|
screen.updateGeometricState();
|
|
screen.updateGeometricState();
|
|
|
|
|
|
- renderManager.setCamera(
|
|
|
|
- getCam(i,irradiancebaker.getWidth(),irradiancebaker.getHeight(),Vector3f.ZERO,1,1000)
|
|
|
|
- ,false);
|
|
|
|
|
|
+ renderManager.setCamera(updateAndGetInternalCamera(i, irradiancebaker.getWidth(), irradiancebaker.getHeight(), Vector3f.ZERO, 1, 1000), false);
|
|
renderManager.getRenderer().setFrameBuffer(irradiancebaker);
|
|
renderManager.getRenderer().setFrameBuffer(irradiancebaker);
|
|
renderManager.renderGeometry(screen);
|
|
renderManager.renderGeometry(screen);
|
|
|
|
|
|
- if(isTexturePulling()) pull(irradiancebaker,irradiance,i);
|
|
|
|
|
|
+ if (isTexturePulling()) pull(irradiancebaker, irradiance, i);
|
|
}
|
|
}
|
|
|
|
|
|
irradiancebaker.dispose();
|
|
irradiancebaker.dispose();
|
|
@@ -271,5 +270,4 @@ public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
}
|
|
}
|