Compare commits
4 Commits
master
...
accellbake
Author | SHA1 | Date | |
---|---|---|---|
|
ec01833fa1 | ||
|
c91b2dd3f0 | ||
|
b14bb34176 | ||
|
f1ab3be46c |
@ -0,0 +1,104 @@
|
|||||||
|
package com.jme3.environment;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.environment.baker.IBLGLEnvBakerLight;
|
||||||
|
import com.jme3.light.LightProbe;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.renderer.RenderManager;
|
||||||
|
import com.jme3.renderer.ViewPort;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.scene.control.Control;
|
||||||
|
import com.jme3.texture.Image.Format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SmartLightProbe
|
||||||
|
*/
|
||||||
|
public class EnvironmentProbeControl extends LightProbe implements Control {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RenderManager renderManager;
|
||||||
|
AssetManager assetManager;
|
||||||
|
int envMapSize;
|
||||||
|
Spatial spatial;
|
||||||
|
boolean BAKE_NEEDED=true;
|
||||||
|
Function<Geometry,Boolean> filter=(s)->{
|
||||||
|
return s.getUserData("tags.env")!=null;
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void tag(Spatial s){
|
||||||
|
if(s instanceof Node){
|
||||||
|
Node n=(Node)s;
|
||||||
|
for(Spatial sx:n.getChildren()){
|
||||||
|
tag(sx);
|
||||||
|
}
|
||||||
|
}else if(s instanceof Geometry){
|
||||||
|
s.setUserData("tags.env", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnvironmentProbeControl(RenderManager rm,AssetManager am, int size){
|
||||||
|
renderManager=rm;
|
||||||
|
assetManager=am;
|
||||||
|
envMapSize=size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Control cloneForSpatial(Spatial spatial) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpatial(Spatial spatial) {
|
||||||
|
|
||||||
|
spatial.addLight(this);
|
||||||
|
this.spatial=spatial;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(float tpf) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderManager rm, ViewPort vp) {
|
||||||
|
if(BAKE_NEEDED){
|
||||||
|
BAKE_NEEDED=false;
|
||||||
|
rebakeNow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rebake(){
|
||||||
|
BAKE_NEEDED=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebakeNow() {
|
||||||
|
System.out.println("BAKE");
|
||||||
|
|
||||||
|
IBLGLEnvBakerLight baker = new IBLGLEnvBakerLight(renderManager, assetManager, Format.RGB16F, Format.Depth,
|
||||||
|
envMapSize, envMapSize);
|
||||||
|
|
||||||
|
|
||||||
|
baker.bakeEnvironment(spatial, Vector3f.ZERO, 0.001f, 1000f,filter);
|
||||||
|
baker.bakeSpecularIBL();
|
||||||
|
baker.bakeSphericalHarmonicsCoefficients();
|
||||||
|
|
||||||
|
|
||||||
|
// probe.setPosition(Vector3f.ZERO);
|
||||||
|
setPrefilteredMap(baker.getSpecularIBL());
|
||||||
|
setNbMipMaps(getPrefilteredEnvMap().getImage().getMipMapSizes().length);
|
||||||
|
setShCoeffs(baker.getSphericalHarmonicsCoefficients());
|
||||||
|
setPosition(Vector3f.ZERO);
|
||||||
|
setReady(true);
|
||||||
|
|
||||||
|
baker.clean();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2019 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.jme3.environment;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.environment.baker.IBLGLEnvBakerLight;
|
||||||
|
import com.jme3.environment.util.EnvMapUtils;
|
||||||
|
import com.jme3.light.LightProbe;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.renderer.RenderManager;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.texture.Image.Format;
|
||||||
|
|
||||||
|
|
||||||
|
public class LightProbeFactory2 {
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
baker.bakeEnvironment(scene,pos, frustumNear,frustumFar,null);
|
||||||
|
baker.bakeSpecularIBL();
|
||||||
|
baker.bakeSphericalHarmonicsCoefficients();
|
||||||
|
|
||||||
|
LightProbe probe = new LightProbe();
|
||||||
|
|
||||||
|
probe.setPosition(pos);
|
||||||
|
probe.setPrefilteredMap(baker.getSpecularIBL());
|
||||||
|
probe.setNbMipMaps(probe.getPrefilteredEnvMap().getImage().getMipMapSizes().length);
|
||||||
|
probe.setShCoeffs(baker.getSphericalHarmonicsCoefficients());
|
||||||
|
probe.setReady(true);
|
||||||
|
|
||||||
|
baker.clean();
|
||||||
|
|
||||||
|
return probe;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For debuging porpose only
|
||||||
|
* Will return a Node meant to be added to a GUI presenting the 2 cube maps in a cross pattern with all the mip maps.
|
||||||
|
*
|
||||||
|
* @param manager the asset manager
|
||||||
|
* @return a debug node
|
||||||
|
*/
|
||||||
|
public static Node getDebugGui(AssetManager manager, LightProbe probe) {
|
||||||
|
if (!probe.isReady()) {
|
||||||
|
throw new UnsupportedOperationException("This EnvProbe is not ready yet, try to test isReady()");
|
||||||
|
}
|
||||||
|
|
||||||
|
Node debugNode = new Node("debug gui probe");
|
||||||
|
Node debugPfemCm = EnvMapUtils.getCubeMapCrossDebugViewWithMipMaps(probe.getPrefilteredEnvMap(), manager);
|
||||||
|
debugNode.attachChild(debugPfemCm);
|
||||||
|
debugPfemCm.setLocalTranslation(520, 0, 0);
|
||||||
|
|
||||||
|
return debugNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.jme3.environment.baker;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.texture.TextureCubeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* And environment baker. It bakes the environment. ( ͡° ͜ʖ ͡°)
|
||||||
|
*
|
||||||
|
* @author Riccardo Balbo
|
||||||
|
*/
|
||||||
|
public interface EnvBaker {
|
||||||
|
public void bakeEnvironment(Spatial scene, Vector3f position, float frustumNear, float frustumFar,Function<Geometry,Boolean> filter);
|
||||||
|
public TextureCubeMap getEnvMap();
|
||||||
|
public void clean();
|
||||||
|
}
|
@ -0,0 +1,171 @@
|
|||||||
|
package com.jme3.environment.baker;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.environment.baker.EnvBaker;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.math.Quaternion;
|
||||||
|
import com.jme3.math.Vector2f;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.renderer.Camera;
|
||||||
|
import com.jme3.renderer.RenderManager;
|
||||||
|
import com.jme3.renderer.ViewPort;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.texture.FrameBuffer;
|
||||||
|
import com.jme3.texture.Image.Format;
|
||||||
|
import com.jme3.texture.Texture.MagFilter;
|
||||||
|
import com.jme3.texture.Texture.MinFilter;
|
||||||
|
import com.jme3.texture.Texture.WrapMode;
|
||||||
|
import com.jme3.texture.TextureCubeMap;
|
||||||
|
import com.jme3.texture.image.ColorSpace;
|
||||||
|
import com.jme3.util.BufferUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the environment into a cubemap
|
||||||
|
*
|
||||||
|
* @author Riccardo Balbo
|
||||||
|
*/
|
||||||
|
public abstract class GenericEnvBaker implements EnvBaker{
|
||||||
|
|
||||||
|
protected static Vector3f[] axisX=new Vector3f[6];
|
||||||
|
protected static Vector3f[] axisY=new Vector3f[6];
|
||||||
|
protected static Vector3f[] axisZ=new Vector3f[6];
|
||||||
|
static{
|
||||||
|
//PositiveX axis(left, up, direction)
|
||||||
|
axisX[0]=Vector3f.UNIT_Z.mult(1.0F);
|
||||||
|
axisY[0]=Vector3f.UNIT_Y.mult(-1.0F);
|
||||||
|
axisZ[0]=Vector3f.UNIT_X.mult(1.0F);
|
||||||
|
//NegativeX
|
||||||
|
axisX[1]=Vector3f.UNIT_Z.mult(-1.0F);
|
||||||
|
axisY[1]=Vector3f.UNIT_Y.mult(-1.0F);
|
||||||
|
axisZ[1]=Vector3f.UNIT_X.mult(-1.0F);
|
||||||
|
//PositiveY
|
||||||
|
axisX[2]=Vector3f.UNIT_X.mult(-1.0F);
|
||||||
|
axisY[2]=Vector3f.UNIT_Z.mult(1.0F);
|
||||||
|
axisZ[2]=Vector3f.UNIT_Y.mult(1.0F);
|
||||||
|
//NegativeY
|
||||||
|
axisX[3]=Vector3f.UNIT_X.mult(-1.0F);
|
||||||
|
axisY[3]=Vector3f.UNIT_Z.mult(-1.0F);
|
||||||
|
axisZ[3]=Vector3f.UNIT_Y.mult(-1.0F);
|
||||||
|
//PositiveZ
|
||||||
|
axisX[4]=Vector3f.UNIT_X.mult(-1.0F);
|
||||||
|
axisY[4]=Vector3f.UNIT_Y.mult(-1.0F);
|
||||||
|
axisZ[4]=Vector3f.UNIT_Z;
|
||||||
|
//NegativeZ
|
||||||
|
axisX[5]=Vector3f.UNIT_X.mult(1.0F);
|
||||||
|
axisY[5]=Vector3f.UNIT_Y.mult(-1.0F);
|
||||||
|
axisZ[5]=Vector3f.UNIT_Z.mult(-1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TextureCubeMap env;
|
||||||
|
protected Format depthFormat;
|
||||||
|
|
||||||
|
|
||||||
|
protected final RenderManager renderManager;
|
||||||
|
protected final AssetManager assetManager;
|
||||||
|
protected final Camera cam;
|
||||||
|
protected final boolean copyToRam;
|
||||||
|
|
||||||
|
|
||||||
|
public GenericEnvBaker(
|
||||||
|
RenderManager rm,
|
||||||
|
AssetManager am,
|
||||||
|
Format colorFormat,
|
||||||
|
Format depthFormat,
|
||||||
|
int env_size,
|
||||||
|
boolean copyToRam
|
||||||
|
){
|
||||||
|
this.copyToRam=copyToRam;
|
||||||
|
this.depthFormat=depthFormat;
|
||||||
|
|
||||||
|
renderManager=rm;
|
||||||
|
assetManager=am;
|
||||||
|
|
||||||
|
|
||||||
|
cam=new Camera(128,128);
|
||||||
|
|
||||||
|
env=new TextureCubeMap(env_size,env_size,colorFormat);
|
||||||
|
env.setMagFilter(MagFilter.Bilinear);
|
||||||
|
env.setMinFilter(MinFilter.BilinearNoMipMaps);
|
||||||
|
env.setWrap(WrapMode.EdgeClamp);
|
||||||
|
env.getImage().setColorSpace(ColorSpace.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureCubeMap getEnvMap(){
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera getCam(int id,int w,int h,Vector3f position,float frustumNear,float frustumFar){
|
||||||
|
cam.resize(w,h,false);
|
||||||
|
cam.setLocation(position);
|
||||||
|
cam.setFrustumPerspective(90.0F,1F,frustumNear,frustumFar);
|
||||||
|
cam.setRotation(new Quaternion().fromAxes(axisX[id],axisY[id],axisZ[id]));
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clean(){
|
||||||
|
env.getImage().dispose();
|
||||||
|
System.gc();
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bakeEnvironment(Spatial scene, Vector3f position, float frustumNear, float frustumFar,Function<Geometry,Boolean> filter) {
|
||||||
|
FrameBuffer envbaker=new FrameBuffer(env.getImage().getWidth(),env.getImage().getHeight(),1);
|
||||||
|
envbaker.setDepthTarget(FrameBuffer.newTarget(depthFormat));
|
||||||
|
envbaker.setSrgb(false);
|
||||||
|
|
||||||
|
for(int i=0;i<6;i++) envbaker.addColorTarget(FrameBuffer.newTarget(env).face(TextureCubeMap.Face.values()[i]));
|
||||||
|
|
||||||
|
for(int i=0;i<6;i++){
|
||||||
|
envbaker.setTargetIndex(i);
|
||||||
|
|
||||||
|
ViewPort viewPort=new ViewPort("EnvBaker",getCam(i,envbaker.getWidth(),envbaker.getHeight(),position,frustumNear,frustumFar));
|
||||||
|
viewPort.setClearFlags(true,true,true);
|
||||||
|
viewPort.setBackgroundColor(ColorRGBA.Pink);
|
||||||
|
|
||||||
|
viewPort.setOutputFrameBuffer(envbaker);
|
||||||
|
viewPort.clearScenes();
|
||||||
|
viewPort.attachScene(scene);
|
||||||
|
|
||||||
|
scene.updateLogicalState(0);
|
||||||
|
scene.updateModelBound();
|
||||||
|
scene.updateGeometricState();
|
||||||
|
|
||||||
|
Function<Geometry,Boolean> ofilter= renderManager.getRenderFilter();
|
||||||
|
|
||||||
|
renderManager.setRenderFilter(filter);
|
||||||
|
renderManager.renderViewPort(viewPort,0.16f);
|
||||||
|
renderManager.setRenderFilter(ofilter);
|
||||||
|
|
||||||
|
if(copyToRam){
|
||||||
|
ByteBuffer face=BufferUtils.createByteBuffer(
|
||||||
|
(
|
||||||
|
env.getImage().getWidth()*env.getImage().getHeight()*(
|
||||||
|
env.getImage().getFormat().getBitsPerPixel()/8
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
renderManager.getRenderer().readFrameBufferWithFormat(envbaker, face,env.getImage().getFormat());
|
||||||
|
face.rewind();
|
||||||
|
env.getImage().setData(i,face);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
env.getImage().clearUpdateNeeded();
|
||||||
|
|
||||||
|
envbaker.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.jme3.environment.baker;
|
||||||
|
|
||||||
|
import com.jme3.texture.Texture2D;
|
||||||
|
import com.jme3.texture.TextureCubeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environment baker, but this one is for Imaged Base Lighting
|
||||||
|
*
|
||||||
|
* @author Riccardo Balbo
|
||||||
|
*/
|
||||||
|
public interface IBLEnvBaker extends EnvBaker{
|
||||||
|
public Texture2D genBRTF() ;
|
||||||
|
|
||||||
|
public void bakeIrradiance();
|
||||||
|
public void bakeSpecularIBL() ;
|
||||||
|
|
||||||
|
public TextureCubeMap getSpecularIBL();
|
||||||
|
public TextureCubeMap getIrradiance();
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.jme3.environment.baker;
|
||||||
|
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.texture.TextureCubeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An environment baker for IBL, that uses spherical harmonics for irradiance.
|
||||||
|
*
|
||||||
|
* @author Riccardo Balbo
|
||||||
|
*/
|
||||||
|
public interface IBLEnvBakerLight extends EnvBaker{
|
||||||
|
public void bakeSpecularIBL();
|
||||||
|
public void bakeSphericalHarmonicsCoefficients();
|
||||||
|
|
||||||
|
public TextureCubeMap getSpecularIBL();
|
||||||
|
public Vector3f[] getSphericalHarmonicsCoefficients();
|
||||||
|
}
|
@ -0,0 +1,182 @@
|
|||||||
|
package com.jme3.environment.baker;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.environment.baker.IBLEnvBaker;
|
||||||
|
import com.jme3.material.Material;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.renderer.Camera;
|
||||||
|
import com.jme3.renderer.RenderManager;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.shape.Box;
|
||||||
|
import com.jme3.texture.FrameBuffer;
|
||||||
|
import com.jme3.texture.Image.Format;
|
||||||
|
import com.jme3.texture.Texture.MagFilter;
|
||||||
|
import com.jme3.texture.Texture.MinFilter;
|
||||||
|
import com.jme3.texture.Texture.WrapMode;
|
||||||
|
import com.jme3.texture.Texture2D;
|
||||||
|
import com.jme3.texture.TextureCubeMap;
|
||||||
|
import com.jme3.texture.image.ColorSpace;
|
||||||
|
import com.jme3.ui.Picture;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An env baker for IBL that runs on the GPU
|
||||||
|
*
|
||||||
|
* @author Riccardo Balbo
|
||||||
|
*/
|
||||||
|
public class IBLGLEnvBaker extends GenericEnvBaker implements IBLEnvBaker{
|
||||||
|
protected Texture2D brtf;
|
||||||
|
protected TextureCubeMap irradiance;
|
||||||
|
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,false);
|
||||||
|
|
||||||
|
irradiance=new TextureCubeMap(irradiance_size,irradiance_size,format);
|
||||||
|
irradiance.setMagFilter(MagFilter.Bilinear);
|
||||||
|
irradiance.setMinFilter(MinFilter.BilinearNoMipMaps);
|
||||||
|
irradiance.setWrap(WrapMode.EdgeClamp);
|
||||||
|
irradiance.getImage().setColorSpace(ColorSpace.Linear);
|
||||||
|
|
||||||
|
specular=new TextureCubeMap(specular_size,specular_size,format);
|
||||||
|
specular.setMagFilter(MagFilter.Bilinear);
|
||||||
|
specular.setMinFilter(MinFilter.BilinearNoMipMaps);
|
||||||
|
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[] sizes=new int[nbMipMaps];
|
||||||
|
for(int i=0;i<nbMipMaps;i++){
|
||||||
|
int size=(int)FastMath.pow(2,nbMipMaps-1-i);
|
||||||
|
sizes[i]=size*size*(specular.getImage().getFormat().getBitsPerPixel()/8);
|
||||||
|
}
|
||||||
|
specular.getImage().setMipMapSizes(sizes);
|
||||||
|
|
||||||
|
brtf=new Texture2D(brtf_size,brtf_size,format);
|
||||||
|
brtf.setMagFilter(MagFilter.Bilinear);
|
||||||
|
brtf.setMinFilter(MinFilter.BilinearNoMipMaps);
|
||||||
|
brtf.setWrap(WrapMode.EdgeClamp);
|
||||||
|
brtf.getImage().setColorSpace(ColorSpace.Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TextureCubeMap getSpecularIBL(){
|
||||||
|
return specular;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureCubeMap getIrradiance(){
|
||||||
|
return irradiance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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);
|
||||||
|
screen.setMaterial(mat);
|
||||||
|
|
||||||
|
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 specularbaker=new FrameBuffer(mipWidth,mipHeight,1);
|
||||||
|
specularbaker.setSrgb(false);
|
||||||
|
|
||||||
|
for(int i=0;i<6;i++)specularbaker.addColorTarget( FrameBuffer.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++){
|
||||||
|
specularbaker.setTargetIndex(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);
|
||||||
|
}
|
||||||
|
specularbaker.dispose();
|
||||||
|
}
|
||||||
|
specular.setMinFilter(MinFilter.Trilinear);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Texture2D genBRTF() {
|
||||||
|
|
||||||
|
Picture screen=new Picture("BakeScreen",true);
|
||||||
|
screen.setWidth(1);
|
||||||
|
screen.setHeight(1);
|
||||||
|
|
||||||
|
FrameBuffer brtfbaker=new FrameBuffer(brtf.getImage().getWidth(),brtf.getImage().getHeight(),1);
|
||||||
|
brtfbaker.setSrgb(false);
|
||||||
|
brtfbaker.addColorTarget(FrameBuffer.newTarget(brtf));
|
||||||
|
|
||||||
|
Camera envcam=getCam(0,brtf.getImage().getWidth(),brtf.getImage().getHeight(),Vector3f.ZERO,1,1000);
|
||||||
|
|
||||||
|
Material mat=new Material(assetManager,"Common/IBL/IBLKernels.j3md");
|
||||||
|
mat.setBoolean("UseBRDF",true);
|
||||||
|
screen.setMaterial(mat);
|
||||||
|
|
||||||
|
renderManager.getRenderer().setFrameBuffer(brtfbaker);
|
||||||
|
renderManager.setCamera(envcam,false);
|
||||||
|
|
||||||
|
screen.updateLogicalState(0);
|
||||||
|
screen.updateGeometricState();
|
||||||
|
renderManager.renderGeometry(screen);
|
||||||
|
|
||||||
|
brtfbaker.dispose();
|
||||||
|
|
||||||
|
return brtf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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);
|
||||||
|
irradiancebaker.setSrgb(false);
|
||||||
|
|
||||||
|
for(int i=0;i<6;i++) irradiancebaker.addColorTarget(FrameBuffer.newTarget(irradiance).face(TextureCubeMap.Face.values()[i]));
|
||||||
|
|
||||||
|
Material mat=new Material(assetManager,"Common/IBL/IBLKernels.j3md");
|
||||||
|
mat.setBoolean("UseIrradiance",true);
|
||||||
|
mat.setTexture("EnvMap",env);
|
||||||
|
screen.setMaterial(mat);
|
||||||
|
|
||||||
|
for(int i=0;i<6;i++){
|
||||||
|
irradiancebaker.setTargetIndex(i);
|
||||||
|
|
||||||
|
mat.setInt("FaceId",i);
|
||||||
|
|
||||||
|
screen.updateLogicalState(0);
|
||||||
|
screen.updateGeometricState();
|
||||||
|
|
||||||
|
renderManager.setCamera(
|
||||||
|
getCam(i,irradiancebaker.getWidth(),irradiancebaker.getHeight(),Vector3f.ZERO,1,1000)
|
||||||
|
,false);
|
||||||
|
renderManager.getRenderer().setFrameBuffer(irradiancebaker);
|
||||||
|
renderManager.renderGeometry(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
irradiancebaker.dispose();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package com.jme3.environment.baker;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.environment.baker.IBLEnvBakerLight;
|
||||||
|
import com.jme3.environment.util.EnvMapUtils;
|
||||||
|
import com.jme3.material.Material;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.renderer.RenderManager;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.shape.Box;
|
||||||
|
import com.jme3.texture.FrameBuffer;
|
||||||
|
import com.jme3.texture.TextureCubeMap;
|
||||||
|
import com.jme3.texture.Image.Format;
|
||||||
|
import com.jme3.texture.Texture.MagFilter;
|
||||||
|
import com.jme3.texture.Texture.MinFilter;
|
||||||
|
import com.jme3.texture.Texture.WrapMode;
|
||||||
|
import com.jme3.texture.image.ColorSpace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An env baker for IBL that runs on the GPU
|
||||||
|
*
|
||||||
|
* @author Riccardo Balbo
|
||||||
|
*/
|
||||||
|
public class IBLGLEnvBakerLight extends GenericEnvBaker implements IBLEnvBakerLight{
|
||||||
|
protected TextureCubeMap specular;
|
||||||
|
protected Vector3f[] shCoef;
|
||||||
|
public IBLGLEnvBakerLight(RenderManager rm,AssetManager am,
|
||||||
|
Format format,
|
||||||
|
Format depthFormat,
|
||||||
|
int env_size,
|
||||||
|
int specular_size
|
||||||
|
|
||||||
|
){
|
||||||
|
super(rm,am,format,depthFormat,env_size,true);
|
||||||
|
|
||||||
|
specular=new TextureCubeMap(specular_size,specular_size,format);
|
||||||
|
specular.setMagFilter(MagFilter.Bilinear);
|
||||||
|
specular.setMinFilter(MinFilter.BilinearNoMipMaps);
|
||||||
|
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[] sizes=new int[nbMipMaps];
|
||||||
|
for(int i=0;i<nbMipMaps;i++){
|
||||||
|
int size=(int)FastMath.pow(2,nbMipMaps-1-i);
|
||||||
|
sizes[i]=size*size*(specular.getImage().getFormat().getBitsPerPixel()/8);
|
||||||
|
}
|
||||||
|
specular.getImage().setMipMapSizes(sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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);
|
||||||
|
screen.setMaterial(mat);
|
||||||
|
|
||||||
|
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 specularbaker=new FrameBuffer(mipWidth,mipHeight,1);
|
||||||
|
specularbaker.setSrgb(false);
|
||||||
|
for(int i=0;i<6;i++)specularbaker.addColorTarget( FrameBuffer.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++){
|
||||||
|
specularbaker.setTargetIndex(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);
|
||||||
|
}
|
||||||
|
specularbaker.dispose();
|
||||||
|
}
|
||||||
|
specular.setMinFilter(MinFilter.Trilinear);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextureCubeMap getSpecularIBL() {
|
||||||
|
return specular;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bakeSphericalHarmonicsCoefficients() {
|
||||||
|
shCoef=EnvMapUtils.getSphericalHarmonicsCoefficents(getEnvMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3f[] getSphericalHarmonicsCoefficients(){
|
||||||
|
return shCoef;
|
||||||
|
}
|
||||||
|
}
|
@ -57,6 +57,7 @@ import com.jme3.util.SafeArrayList;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,7 +91,15 @@ public class RenderManager {
|
|||||||
private LightFilter lightFilter = new DefaultLightFilter();
|
private LightFilter lightFilter = new DefaultLightFilter();
|
||||||
private TechniqueDef.LightMode preferredLightMode = TechniqueDef.LightMode.MultiPass;
|
private TechniqueDef.LightMode preferredLightMode = TechniqueDef.LightMode.MultiPass;
|
||||||
private int singlePassLightBatchSize = 1;
|
private int singlePassLightBatchSize = 1;
|
||||||
|
private Function<Geometry,Boolean> renderFilter;
|
||||||
|
|
||||||
|
public void setRenderFilter(Function<Geometry,Boolean> filter){
|
||||||
|
renderFilter=filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function<Geometry,Boolean> getRenderFilter(){
|
||||||
|
return renderFilter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a high-level rendering interface over the
|
* Create a high-level rendering interface over the
|
||||||
@ -557,6 +566,7 @@ public class RenderManager {
|
|||||||
* @see com.jme3.material.Material#render(com.jme3.scene.Geometry, com.jme3.renderer.RenderManager)
|
* @see com.jme3.material.Material#render(com.jme3.scene.Geometry, com.jme3.renderer.RenderManager)
|
||||||
*/
|
*/
|
||||||
public void renderGeometry(Geometry geom) {
|
public void renderGeometry(Geometry geom) {
|
||||||
|
if(renderFilter!=null&&!renderFilter.apply(geom))return;
|
||||||
if (geom.isIgnoreTransform()) {
|
if (geom.isIgnoreTransform()) {
|
||||||
setWorldMatrix(Matrix4f.IDENTITY);
|
setWorldMatrix(Matrix4f.IDENTITY);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1729,12 +1729,12 @@ public final class GLRenderer implements Renderer {
|
|||||||
convertAttachmentSlot(rb.getSlot()),
|
convertAttachmentSlot(rb.getSlot()),
|
||||||
convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()),
|
convertTextureType(tex.getType(), image.getMultiSamples(), rb.getFace()),
|
||||||
image.getId(),
|
image.getId(),
|
||||||
0);
|
rb.getLevel());
|
||||||
} else {
|
} else {
|
||||||
glfbo.glFramebufferTextureLayerEXT(GLFbo.GL_FRAMEBUFFER_EXT,
|
glfbo.glFramebufferTextureLayerEXT(GLFbo.GL_FRAMEBUFFER_EXT,
|
||||||
convertAttachmentSlot(rb.getSlot()),
|
convertAttachmentSlot(rb.getSlot()),
|
||||||
image.getId(),
|
image.getId(),
|
||||||
0,
|
rb.getLevel(),
|
||||||
rb.getLayer());
|
rb.getLayer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ public class FrameBuffer extends NativeObject {
|
|||||||
* buffer that will be rendered to. <code>RenderBuffer</code>s
|
* buffer that will be rendered to. <code>RenderBuffer</code>s
|
||||||
* are attached to an attachment slot on a <code>FrameBuffer</code>.
|
* are attached to an attachment slot on a <code>FrameBuffer</code>.
|
||||||
*/
|
*/
|
||||||
public class RenderBuffer {
|
public static class RenderBuffer {
|
||||||
|
|
||||||
Texture tex;
|
Texture tex;
|
||||||
Image.Format format;
|
Image.Format format;
|
||||||
@ -98,6 +98,7 @@ public class FrameBuffer extends NativeObject {
|
|||||||
int slot = SLOT_UNDEF;
|
int slot = SLOT_UNDEF;
|
||||||
int face = -1;
|
int face = -1;
|
||||||
int layer = -1;
|
int layer = -1;
|
||||||
|
int level = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The image format of the render buffer.
|
* @return The image format of the render buffer.
|
||||||
@ -121,6 +122,10 @@ public class FrameBuffer extends NativeObject {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do not use.
|
* Do not use.
|
||||||
*/
|
*/
|
||||||
@ -167,6 +172,60 @@ public class FrameBuffer extends NativeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class FrameBufferTextureTarget extends RenderBuffer {
|
||||||
|
private FrameBufferTextureTarget(){}
|
||||||
|
void setTexture(Texture tx){
|
||||||
|
this.tex=tx;
|
||||||
|
this.format=tx.getImage().getFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFormat(Format f){
|
||||||
|
this.format=f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameBufferTextureTarget layer(int i){
|
||||||
|
this.layer=i;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameBufferTextureTarget level(int i){
|
||||||
|
this.level=i;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameBufferTextureTarget face(TextureCubeMap.Face f){
|
||||||
|
return face(f.ordinal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FrameBufferTextureTarget face(int f){
|
||||||
|
this.face=f;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FrameBufferBufferTarget extends RenderBuffer {
|
||||||
|
private FrameBufferBufferTarget(){}
|
||||||
|
void setFormat(Format f){
|
||||||
|
this.format=f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FrameBufferTextureTarget newTarget(Texture tx){
|
||||||
|
FrameBufferTextureTarget t=new FrameBufferTextureTarget();
|
||||||
|
t.setTexture(tx);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FrameBufferBufferTarget newTarget(Format format){
|
||||||
|
FrameBufferBufferTarget t=new FrameBufferBufferTarget();
|
||||||
|
t.setFormat(format);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Creates a new FrameBuffer with the given width, height, and number
|
* Creates a new FrameBuffer with the given width, height, and number
|
||||||
@ -207,12 +266,62 @@ public class FrameBuffer extends NativeObject {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void addColorTarget(FrameBufferBufferTarget colorBuf){
|
||||||
|
colorBuf.slot=colorBufs.size();
|
||||||
|
colorBufs.add(colorBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addColorTarget(FrameBufferTextureTarget colorBuf){
|
||||||
|
// checkSetTexture(colorBuf.getTexture(), false); // TODO: this won't work for levels.
|
||||||
|
colorBuf.slot=colorBufs.size();
|
||||||
|
colorBufs.add(colorBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepthTarget(FrameBufferBufferTarget depthBuf){
|
||||||
|
if (!depthBuf.getFormat().isDepthFormat())
|
||||||
|
throw new IllegalArgumentException("Depth buffer format must be depth.");
|
||||||
|
this.depthBuf = depthBuf;
|
||||||
|
this.depthBuf.slot = this.depthBuf.getFormat().isDepthStencilFormat() ? SLOT_DEPTH_STENCIL : SLOT_DEPTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepthTarget(FrameBufferTextureTarget depthBuf){
|
||||||
|
checkSetTexture(depthBuf.getTexture(), true);
|
||||||
|
this.depthBuf = depthBuf;
|
||||||
|
this.depthBuf.slot = depthBuf.getTexture().getImage().getFormat().isDepthStencilFormat() ? SLOT_DEPTH_STENCIL : SLOT_DEPTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumColorTargets(){
|
||||||
|
return colorBufs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderBuffer getColorTarget(int index){
|
||||||
|
return colorBufs.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderBuffer getColorTarget() {
|
||||||
|
if (colorBufs.isEmpty())
|
||||||
|
return null;
|
||||||
|
if (colorBufIndex<0 || colorBufIndex>=colorBufs.size()) {
|
||||||
|
return colorBufs.get(0);
|
||||||
|
}
|
||||||
|
return colorBufs.get(colorBufIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderBuffer getDepthTarget() {
|
||||||
|
return depthBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the use of a depth buffer for this <code>FrameBuffer</code>.
|
* Enables the use of a depth buffer for this <code>FrameBuffer</code>.
|
||||||
*
|
*
|
||||||
* @param format The format to use for the depth buffer.
|
* @param format The format to use for the depth buffer.
|
||||||
* @throws IllegalArgumentException If <code>format</code> is not a depth format.
|
* @throws IllegalArgumentException If <code>format</code> is not a depth format.
|
||||||
|
* @deprecated Use setDepthTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setDepthBuffer(Image.Format format){
|
public void setDepthBuffer(Image.Format format){
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -230,7 +339,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
*
|
*
|
||||||
* @param format The format to use for the color buffer.
|
* @param format The format to use for the color buffer.
|
||||||
* @throws IllegalArgumentException If <code>format</code> is not a color format.
|
* @throws IllegalArgumentException If <code>format</code> is not a color format.
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setColorBuffer(Image.Format format){
|
public void setColorBuffer(Image.Format format){
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -323,7 +434,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
* only target.
|
* only target.
|
||||||
*
|
*
|
||||||
* @param tex The color texture to set.
|
* @param tex The color texture to set.
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setColorTexture(Texture2D tex){
|
public void setColorTexture(Texture2D tex){
|
||||||
clearColorTargets();
|
clearColorTargets();
|
||||||
addColorTexture(tex);
|
addColorTexture(tex);
|
||||||
@ -336,7 +449,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
* only target.
|
* only target.
|
||||||
*
|
*
|
||||||
* @param tex The color texture array to set.
|
* @param tex The color texture array to set.
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setColorTexture(TextureArray tex, int layer){
|
public void setColorTexture(TextureArray tex, int layer){
|
||||||
clearColorTargets();
|
clearColorTargets();
|
||||||
addColorTexture(tex, layer);
|
addColorTexture(tex, layer);
|
||||||
@ -350,7 +465,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
*
|
*
|
||||||
* @param tex The cube-map texture to set.
|
* @param tex The cube-map texture to set.
|
||||||
* @param face The face of the cube-map to render to.
|
* @param face The face of the cube-map to render to.
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setColorTexture(TextureCubeMap tex, TextureCubeMap.Face face) {
|
public void setColorTexture(TextureCubeMap tex, TextureCubeMap.Face face) {
|
||||||
clearColorTargets();
|
clearColorTargets();
|
||||||
addColorTexture(tex, face);
|
addColorTexture(tex, face);
|
||||||
@ -372,7 +489,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
*
|
*
|
||||||
* @param format the format of the color buffer
|
* @param format the format of the color buffer
|
||||||
* @see #addColorTexture(com.jme3.texture.Texture2D)
|
* @see #addColorTexture(com.jme3.texture.Texture2D)
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void addColorBuffer(Image.Format format){
|
public void addColorBuffer(Image.Format format){
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -387,6 +506,8 @@ public class FrameBuffer extends NativeObject {
|
|||||||
colorBufs.add(colorBuf);
|
colorBufs.add(colorBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a color texture to use for this framebuffer.
|
* Add a color texture to use for this framebuffer.
|
||||||
* If MRT is enabled, then each subsequently added texture can be
|
* If MRT is enabled, then each subsequently added texture can be
|
||||||
@ -396,7 +517,10 @@ public class FrameBuffer extends NativeObject {
|
|||||||
*
|
*
|
||||||
* @param tex The texture to add.
|
* @param tex The texture to add.
|
||||||
* @see #addColorBuffer(com.jme3.texture.Image.Format)
|
* @see #addColorBuffer(com.jme3.texture.Image.Format)
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void addColorTexture(Texture2D tex) {
|
public void addColorTexture(Texture2D tex) {
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -420,7 +544,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
* is rendered to by the shader.
|
* is rendered to by the shader.
|
||||||
*
|
*
|
||||||
* @param tex The texture array to add.
|
* @param tex The texture array to add.
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void addColorTexture(TextureArray tex, int layer) {
|
public void addColorTexture(TextureArray tex, int layer) {
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -446,7 +572,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
*
|
*
|
||||||
* @param tex The cube-map texture to add.
|
* @param tex The cube-map texture to add.
|
||||||
* @param face The face of the cube-map to render to.
|
* @param face The face of the cube-map to render to.
|
||||||
|
* @deprecated Use addColorTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void addColorTexture(TextureCubeMap tex, TextureCubeMap.Face face) {
|
public void addColorTexture(TextureCubeMap tex, TextureCubeMap.Face face) {
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -467,7 +595,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
* Set the depth texture to use for this framebuffer.
|
* Set the depth texture to use for this framebuffer.
|
||||||
*
|
*
|
||||||
* @param tex The color texture to set.
|
* @param tex The color texture to set.
|
||||||
|
* @deprecated Use setDepthTarget
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setDepthTexture(Texture2D tex){
|
public void setDepthTexture(Texture2D tex){
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -480,6 +610,15 @@ public class FrameBuffer extends NativeObject {
|
|||||||
depthBuf.tex = tex;
|
depthBuf.tex = tex;
|
||||||
depthBuf.format = img.getFormat();
|
depthBuf.format = img.getFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param tex
|
||||||
|
* @param layer
|
||||||
|
* @deprecated Use setDepthTarget
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void setDepthTexture(TextureArray tex, int layer){
|
public void setDepthTexture(TextureArray tex, int layer){
|
||||||
if (id != -1)
|
if (id != -1)
|
||||||
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
throw new UnsupportedOperationException("FrameBuffer already initialized.");
|
||||||
@ -496,7 +635,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The number of color buffers attached to this texture.
|
* @return The number of color buffers attached to this texture.
|
||||||
|
* @deprecated Use getNumColorTargets
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public int getNumColorBuffers(){
|
public int getNumColorBuffers(){
|
||||||
return colorBufs.size();
|
return colorBufs.size();
|
||||||
}
|
}
|
||||||
@ -504,7 +645,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
/**
|
/**
|
||||||
* @param index
|
* @param index
|
||||||
* @return The color buffer at the given index.
|
* @return The color buffer at the given index.
|
||||||
|
* @deprecated Use getColorTarget(int)
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public RenderBuffer getColorBuffer(int index){
|
public RenderBuffer getColorBuffer(int index){
|
||||||
return colorBufs.get(index);
|
return colorBufs.get(index);
|
||||||
}
|
}
|
||||||
@ -513,7 +656,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
* @return The color buffer with the index set by {@link #setTargetIndex(int)}, or null
|
* @return The color buffer with the index set by {@link #setTargetIndex(int)}, or null
|
||||||
* if no color buffers are attached.
|
* if no color buffers are attached.
|
||||||
* If MRT is disabled, the first color buffer is returned.
|
* If MRT is disabled, the first color buffer is returned.
|
||||||
|
* @deprecated Use getColorTarget()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public RenderBuffer getColorBuffer() {
|
public RenderBuffer getColorBuffer() {
|
||||||
if (colorBufs.isEmpty())
|
if (colorBufs.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
@ -526,7 +671,9 @@ public class FrameBuffer extends NativeObject {
|
|||||||
/**
|
/**
|
||||||
* @return The depth buffer attached to this FrameBuffer, or null
|
* @return The depth buffer attached to this FrameBuffer, or null
|
||||||
* if no depth buffer is attached
|
* if no depth buffer is attached
|
||||||
|
* @deprecated Use getDepthTarget()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public RenderBuffer getDepthBuffer() {
|
public RenderBuffer getDepthBuffer() {
|
||||||
return depthBuf;
|
return depthBuf;
|
||||||
}
|
}
|
||||||
|
101
jme3-core/src/main/resources/Common/IBL/IBLKernels.frag
Normal file
101
jme3-core/src/main/resources/Common/IBL/IBLKernels.frag
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* This code is based on the following articles:
|
||||||
|
* https://learnopengl.com/PBR/IBL/Diffuse-irradiance
|
||||||
|
* https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||||
|
* - Riccardo Balbo
|
||||||
|
*/
|
||||||
|
#import "Common/IBL/Math.glsllib"
|
||||||
|
|
||||||
|
out vec4 outFragColor;
|
||||||
|
in vec2 TexCoords;
|
||||||
|
in vec3 LocalPos;
|
||||||
|
|
||||||
|
uniform samplerCube m_EnvMap;
|
||||||
|
uniform float m_Roughness;
|
||||||
|
uniform int m_FaceId;
|
||||||
|
|
||||||
|
void brdfKernel(){
|
||||||
|
float NdotV=TexCoords.x;
|
||||||
|
float m_Roughness=TexCoords.y;
|
||||||
|
vec3 V;
|
||||||
|
V.x = sqrt(1.0 - NdotV*NdotV);
|
||||||
|
V.y = 0.0;
|
||||||
|
V.z = NdotV;
|
||||||
|
float A = 0.0;
|
||||||
|
float B = 0.0;
|
||||||
|
vec3 N = vec3(0.0, 0.0, 1.0);
|
||||||
|
const uint SAMPLE_COUNT = 1024u;
|
||||||
|
for(uint i = 0u; i < SAMPLE_COUNT; i++){
|
||||||
|
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||||
|
vec3 H = ImportanceSampleGGX(Xi, N, m_Roughness);
|
||||||
|
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||||
|
float NdotL = max(L.z, 0.0);
|
||||||
|
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_Vis = (G * VdotH) / (NdotH * NdotV);
|
||||||
|
float Fc = pow(1.0 - VdotH, 5.0);
|
||||||
|
A += (1.0 - Fc) * G_Vis;
|
||||||
|
B += Fc * G_Vis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
A /= float(SAMPLE_COUNT);
|
||||||
|
B /= float(SAMPLE_COUNT);
|
||||||
|
outFragColor.rg=vec2(A, B);
|
||||||
|
outFragColor.ba=vec2(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void irradianceKernel(){
|
||||||
|
// the sample direction equals the hemisphere's orientation
|
||||||
|
vec3 N = normalize(LocalPos);
|
||||||
|
vec3 irradiance = vec3(0.0);
|
||||||
|
vec3 up = vec3(0.0, 1.0, 0.0);
|
||||||
|
vec3 right = cross(up, N);
|
||||||
|
up = cross(N, right);
|
||||||
|
float sampleDelta = 0.025;
|
||||||
|
float nrSamples = 0.0;
|
||||||
|
for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta){
|
||||||
|
for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta){
|
||||||
|
// spherical to cartesian (in tangent space)
|
||||||
|
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
||||||
|
// tangent space to world
|
||||||
|
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
|
||||||
|
irradiance += texture(m_EnvMap, sampleVec).rgb * cos(theta) * sin(theta);
|
||||||
|
nrSamples++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
irradiance = PI * irradiance * (1.0 / float(nrSamples));
|
||||||
|
outFragColor = vec4(irradiance, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void prefilteredEnvKernel(){
|
||||||
|
vec3 N = normalize(LocalPos);
|
||||||
|
vec3 R = N;
|
||||||
|
vec3 V = R;
|
||||||
|
const uint SAMPLE_COUNT = 1024u;
|
||||||
|
float totalWeight = 0.0;
|
||||||
|
vec3 prefilteredColor = vec3(0.0);
|
||||||
|
for(uint i = 0u; i < SAMPLE_COUNT; ++i) {
|
||||||
|
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||||
|
vec3 H = ImportanceSampleGGX(Xi, N, m_Roughness);
|
||||||
|
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
if(NdotL > 0.0) {
|
||||||
|
prefilteredColor += texture(m_EnvMap, L).rgb * NdotL;
|
||||||
|
totalWeight += NdotL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prefilteredColor = prefilteredColor / totalWeight;
|
||||||
|
outFragColor = vec4(prefilteredColor, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
#if defined(SIBL)
|
||||||
|
prefilteredEnvKernel();
|
||||||
|
#elif defined(IRRADIANCE)
|
||||||
|
irradianceKernel();
|
||||||
|
#else
|
||||||
|
brdfKernel();
|
||||||
|
#endif
|
||||||
|
}
|
37
jme3-core/src/main/resources/Common/IBL/IBLKernels.j3md
Normal file
37
jme3-core/src/main/resources/Common/IBL/IBLKernels.j3md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
MaterialDef IBLKernels {
|
||||||
|
|
||||||
|
MaterialParameters {
|
||||||
|
TextureCubeMap EnvMap -LINEAR
|
||||||
|
Float Roughness
|
||||||
|
Int FaceId : 0
|
||||||
|
Boolean UseBRDF
|
||||||
|
Boolean UseIrradiance
|
||||||
|
Boolean UseSpecularIBL
|
||||||
|
}
|
||||||
|
|
||||||
|
Technique {
|
||||||
|
|
||||||
|
VertexShader GLSL150: Common/IBL/IBLKernels.vert
|
||||||
|
FragmentShader GLSL150: Common/IBL/IBLKernels.frag
|
||||||
|
|
||||||
|
WorldParameters {
|
||||||
|
WorldMatrix
|
||||||
|
ViewMatrix
|
||||||
|
ProjectionMatrix
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderState {
|
||||||
|
DepthWrite Off
|
||||||
|
DepthTest Off
|
||||||
|
DepthFunc Equal
|
||||||
|
FaceCull Off
|
||||||
|
}
|
||||||
|
|
||||||
|
Defines {
|
||||||
|
BRDF:UseBRDF
|
||||||
|
IRRADIANCE: UseIrradiance
|
||||||
|
SIBL: UseSpecularIBL
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
29
jme3-core/src/main/resources/Common/IBL/IBLKernels.vert
Normal file
29
jme3-core/src/main/resources/Common/IBL/IBLKernels.vert
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* This code is based on the following articles:
|
||||||
|
* https://learnopengl.com/PBR/IBL/Diffuse-irradiance
|
||||||
|
* https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||||
|
* - Riccardo Balbo
|
||||||
|
*/
|
||||||
|
in vec3 inPosition;
|
||||||
|
in vec2 inTexCoord;
|
||||||
|
in vec3 inNormal;
|
||||||
|
|
||||||
|
out vec2 TexCoords;
|
||||||
|
out vec3 LocalPos;
|
||||||
|
|
||||||
|
uniform mat4 g_ViewMatrix;
|
||||||
|
uniform mat4 g_WorldMatrix;
|
||||||
|
uniform mat4 g_ProjectionMatrix;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
LocalPos = inPosition.xyz;
|
||||||
|
TexCoords = inTexCoord.xy;
|
||||||
|
#ifdef BRDF
|
||||||
|
vec2 pos = inPosition.xy * 2.0 - 1.0;
|
||||||
|
gl_Position = vec4(pos, 0.0, 1.0);
|
||||||
|
#else
|
||||||
|
mat4 rotView = mat4(mat3(g_ViewMatrix)); // remove translation from the view matrix
|
||||||
|
vec4 clipPos = g_ProjectionMatrix * rotView * vec4(LocalPos, 1.0);
|
||||||
|
gl_Position = clipPos.xyww;
|
||||||
|
#endif
|
||||||
|
}
|
66
jme3-core/src/main/resources/Common/IBL/Math.glsllib
Normal file
66
jme3-core/src/main/resources/Common/IBL/Math.glsllib
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* This code is based on the following articles:
|
||||||
|
* https://learnopengl.com/PBR/IBL/Diffuse-irradiance
|
||||||
|
* https://learnopengl.com/PBR/IBL/Specular-IBL
|
||||||
|
* - Riccardo Balbo
|
||||||
|
*/
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
|
float RadicalInverse_VdC(uint bits) {
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Hammersley(uint i, uint N){
|
||||||
|
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){
|
||||||
|
float a = roughness*roughness;
|
||||||
|
|
||||||
|
float phi = 2.0 * PI * Xi.x;
|
||||||
|
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||||
|
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||||
|
|
||||||
|
// from spherical coordinates to cartesian coordinates
|
||||||
|
vec3 H;
|
||||||
|
H.x = cos(phi) * sinTheta;
|
||||||
|
H.y = sin(phi) * sinTheta;
|
||||||
|
H.z = cosTheta;
|
||||||
|
|
||||||
|
// from tangent-space vector to world-space sample vector
|
||||||
|
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||||
|
vec3 tangent = normalize(cross(up, N));
|
||||||
|
vec3 bitangent = cross(N, tangent);
|
||||||
|
|
||||||
|
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||||
|
return normalize(sampleVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness){
|
||||||
|
float a = roughness;
|
||||||
|
float k = (a * a) / 2.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness){
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
@ -34,6 +34,7 @@ package jme3test.light.pbr;
|
|||||||
import com.jme3.app.SimpleApplication;
|
import com.jme3.app.SimpleApplication;
|
||||||
import com.jme3.environment.EnvironmentCamera;
|
import com.jme3.environment.EnvironmentCamera;
|
||||||
import com.jme3.environment.LightProbeFactory;
|
import com.jme3.environment.LightProbeFactory;
|
||||||
|
import com.jme3.environment.LightProbeFactory2;
|
||||||
import com.jme3.environment.generation.JobProgressAdapter;
|
import com.jme3.environment.generation.JobProgressAdapter;
|
||||||
import com.jme3.environment.util.EnvMapUtils;
|
import com.jme3.environment.util.EnvMapUtils;
|
||||||
import com.jme3.environment.util.LightsDebugState;
|
import com.jme3.environment.util.LightsDebugState;
|
||||||
@ -59,7 +60,8 @@ import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
|
|||||||
* @author nehon
|
* @author nehon
|
||||||
*/
|
*/
|
||||||
public class TestPBRLighting extends SimpleApplication {
|
public class TestPBRLighting extends SimpleApplication {
|
||||||
|
private static final boolean USE_ACCELERATED_BAKING=true;
|
||||||
|
private static final int RESOLUTION=256;
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
TestPBRLighting app = new TestPBRLighting();
|
TestPBRLighting app = new TestPBRLighting();
|
||||||
app.start();
|
app.start();
|
||||||
@ -107,7 +109,7 @@ public class TestPBRLighting extends SimpleApplication {
|
|||||||
model.setMaterial(pbrMat);
|
model.setMaterial(pbrMat);
|
||||||
|
|
||||||
|
|
||||||
final EnvironmentCamera envCam = new EnvironmentCamera(256, new Vector3f(0, 3f, 0));
|
final EnvironmentCamera envCam = new EnvironmentCamera(RESOLUTION, new Vector3f(0, 3f, 0));
|
||||||
stateManager.attach(envCam);
|
stateManager.attach(envCam);
|
||||||
|
|
||||||
// EnvironmentManager envManager = new EnvironmentManager();
|
// EnvironmentManager envManager = new EnvironmentManager();
|
||||||
@ -195,18 +197,21 @@ public class TestPBRLighting extends SimpleApplication {
|
|||||||
|
|
||||||
if (frame == 2) {
|
if (frame == 2) {
|
||||||
modelNode.removeFromParent();
|
modelNode.removeFromParent();
|
||||||
final LightProbe probe = LightProbeFactory.makeProbe(stateManager.getState(EnvironmentCamera.class), rootNode, new JobProgressAdapter<LightProbe>() {
|
LightProbe probe;
|
||||||
|
if(USE_ACCELERATED_BAKING){
|
||||||
@Override
|
probe= LightProbeFactory2.makeProbe(renderManager, assetManager, RESOLUTION, Vector3f.ZERO, 1f, 1000f, rootNode);
|
||||||
public void done(LightProbe result) {
|
}else{
|
||||||
System.err.println("Done rendering env maps");
|
probe = LightProbeFactory.makeProbe(stateManager.getState(EnvironmentCamera.class), rootNode, new JobProgressAdapter<LightProbe>() {
|
||||||
tex = EnvMapUtils.getCubeMapCrossDebugViewWithMipMaps(result.getPrefilteredEnvMap(), assetManager);
|
@Override
|
||||||
}
|
public void done(LightProbe result) {
|
||||||
});
|
System.err.println("Done rendering env maps");
|
||||||
|
tex = EnvMapUtils.getCubeMapCrossDebugViewWithMipMaps(result.getPrefilteredEnvMap(), assetManager);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
((SphereProbeArea) probe.getArea()).setRadius(100);
|
((SphereProbeArea) probe.getArea()).setRadius(100);
|
||||||
rootNode.addLight(probe);
|
rootNode.addLight(probe);
|
||||||
//getStateManager().getState(EnvironmentManager.class).addEnvProbe(probe);
|
//getStateManager().getState(EnvironmentManager.class).addEnvProbe(probe);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (frame > 10 && modelNode.getParent() == null) {
|
if (frame > 10 && modelNode.getParent() == null) {
|
||||||
rootNode.attachChild(modelNode);
|
rootNode.attachChild(modelNode);
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package jme3test.light.pbr;
|
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication;
|
||||||
|
import com.jme3.environment.EnvironmentProbeControl;
|
||||||
|
import com.jme3.material.Material;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.util.SkyFactory;
|
||||||
|
import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TestPBRSimple
|
||||||
|
*/
|
||||||
|
public class TestPBRSimple extends SimpleApplication{
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new TestPBRSimple().start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleInitApp() {
|
||||||
|
|
||||||
|
Geometry model = (Geometry) assetManager.loadModel("Models/Tank/tank.j3o");
|
||||||
|
MikktspaceTangentGenerator.generate(model);
|
||||||
|
|
||||||
|
Material pbrMat = assetManager.loadMaterial("Models/Tank/tank.j3m");
|
||||||
|
model.setMaterial(pbrMat);
|
||||||
|
|
||||||
|
rootNode.attachChild(model);
|
||||||
|
|
||||||
|
|
||||||
|
EnvironmentProbeControl envProbe=new EnvironmentProbeControl(renderManager,assetManager,256);
|
||||||
|
rootNode.addControl(envProbe);
|
||||||
|
|
||||||
|
Spatial sky = SkyFactory.createSky(assetManager, "Textures/Sky/Path.hdr", SkyFactory.EnvMapType.EquirectMap);
|
||||||
|
rootNode.attachChild(sky);
|
||||||
|
EnvironmentProbeControl.tag(sky);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user