Skip to content

Commit

Permalink
Drivers workaround: do not crash if lower mips cannot be computed.
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardobl committed Oct 14, 2023
1 parent d756e17 commit 0804ecd
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,10 @@ void rebakeNow(RenderManager renderManager) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,13 @@ public static LightProbe makeProbe(RenderManager rm,
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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,9 @@ protected void endPulling(Texture tx) {
tx.getImage().clearUpdateNeeded();
}

protected int limitMips(int nbMipMaps, int baseW, int baseH,RenderManager rm) {
if (nbMipMaps > 6) nbMipMaps = 6;
return nbMipMaps;
}

}
109 changes: 72 additions & 37 deletions jme3-core/src/main/java/com/jme3/environment/baker/IBLGLEnvBaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -58,7 +62,9 @@
*
* @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;
Expand All @@ -82,11 +88,13 @@ public IBLGLEnvBaker(RenderManager rm,AssetManager am,
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);
Expand All @@ -103,9 +111,42 @@ public TextureCubeMap getSpecularIBL(){
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() {
Expand All @@ -117,44 +158,38 @@ public void bakeSpecularIBL() {
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -58,6 +62,7 @@
* @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;

Expand All @@ -70,10 +75,11 @@ public IBLHybridEnvBakerLight(RenderManager rm, AssetManager am, Format format,
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);
Expand All @@ -89,6 +95,39 @@ public boolean isTexturePulling() { // always pull textures from gpu
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);
Expand All @@ -101,38 +140,30 @@ public void bakeSpecularIBL() {

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);
}
}
}

Expand Down

0 comments on commit 0804ecd

Please sign in to comment.