/** * Add a color texture to use for this framebuffer. * If MRT is enabled, then each subsequently added texture can be * rendered to through a shader that writes to the array <code>gl_FragData</code>. * If MRT is not enabled, then the index set with {@link FrameBuffer#setTargetIndex(int) } * is rendered to by the shader. * * @param tex The cube-map texture to add. * @param face The face of the cube-map to render to. */ public void addColorTexture(TextureCubeMap tex, TextureCubeMap.Face face) { if (id != -1) throw new UnsupportedOperationException("FrameBuffer already initialized."); Image img = tex.getImage(); checkSetTexture(tex, false); RenderBuffer colorBuf = new RenderBuffer(); colorBuf.slot = colorBufs.size(); colorBuf.tex = tex; colorBuf.format = img.getFormat(); colorBuf.face = face.ordinal(); colorBufs.add(colorBuf); }
/** * initialize the pem map * @param size the size of the map * @param imageFormat the format of the image * @return the initialized prefiltered env map */ public static TextureCubeMap createPrefilteredEnvMap(int size, Image.Format imageFormat) { TextureCubeMap pem = new TextureCubeMap(size, size, imageFormat); pem.setMagFilter(Texture.MagFilter.Bilinear); pem.setMinFilter(Texture.MinFilter.Trilinear); pem.getImage().setColorSpace(ColorSpace.Linear); int nbMipMap = Math.min(6, (int) (Math.log(size) / Math.log(2))); CubeMapWrapper targetWrapper = new CubeMapWrapper(pem); targetWrapper.initMipMaps(nbMipMap); return pem; } }
/** * initialize the Irradiancemap * @param size the size of the map * @param imageFormat the format of the image * @return the initialized Irradiance map */ public static TextureCubeMap createIrradianceMap(int size, Image.Format imageFormat) { TextureCubeMap irrMap = new TextureCubeMap(size, size, imageFormat); irrMap.setMagFilter(Texture.MagFilter.Bilinear); irrMap.setMinFilter(Texture.MinFilter.BilinearNoMipMaps); irrMap.getImage().setColorSpace(ColorSpace.Linear); return irrMap; }
/** * Creates a CubeMapWrapper for the given cube map * Note that the cube map must be initialized, and the mipmaps sizes should * be set if relevant for them to be readable/writable * @param cubeMap the cubemap to wrap. */ public CubeMapWrapper(TextureCubeMap cubeMap) { image = cubeMap.getImage(); if (image.hasMipmaps()) { int nbMipMaps = image.getMipMapSizes().length; sizes = new int[nbMipMaps]; mipMapRaster = new MipMapImageRaster(image, 0); for (int i = 0; i < nbMipMaps; i++) { sizes[i] = Math.max(1, image.getWidth() >> i); } } else { sizes = new int[1]; sizes[0] = image.getWidth(); } raster = new DefaultImageRaster(image, 0,0 , false); }
@Override public void render(final RenderManager renderManager) { if (jobs.isEmpty()) { return; } final SnapshotJob job = jobs.get(0); for (int i = 0; i < 6; i++) { viewports[i].clearScenes(); viewports[i].attachScene(job.scene); renderManager.renderViewPort(viewports[i], 0.16f); buffers[i] = BufferUtils.createByteBuffer(size * size * imageFormat.getBitsPerPixel() / 8); renderManager.getRenderer().readFrameBufferWithFormat(framebuffers[i], buffers[i], imageFormat); images[i] = new Image(imageFormat, size, size, buffers[i], ColorSpace.Linear); MipMapGenerator.generateMipMaps(images[i]); } final TextureCubeMap map = EnvMapUtils.makeCubeMap(images[0], images[1], images[2], images[3], images[4], images[5], imageFormat); debugEnv = map; job.callback.done(map); map.getImage().dispose(); jobs.remove(0); }
@Override public void done(Integer result) { if (globalListener != null) { if (result < 6) { globalListener.step("Prefiltered env map face " + result + " generated"); } else { globalListener.step("Irradiance map generated"); } } jobState.done[index] = true; if (jobState.isDone()) { probe.setNbMipMaps(probe.getPrefilteredEnvMap().getImage().getMipMapSizes().length); probe.setReady(true); if (globalListener != null) { globalListener.done(probe); } jobState.executor.shutdownNow(); } } }
float weight; if (cubeMap.getImage().getData(0) == null) { throw new IllegalStateException("The cube map must contain Efficient data, if you rendered the cube map on the GPU please use renderer.readFrameBuffer, to create a CPU image"); int width = cubeMap.getImage().getWidth(); int height = cubeMap.getImage().getHeight();
public static Node getCubeMapCrossDebugViewWithMipMaps(TextureCubeMap cubeMap, AssetManager assetManager) { Node n = new Node("CubeMapDebug" + cubeMap.getName()); int size = cubeMap.getImage().getWidth(); int nbMips = cubeMap.getImage().getMipMapSizes().length; Picture[] pics = new Picture[6*nbMips]; int guiOffset = 0; for (int mipLevel = 0; mipLevel < nbMips; mipLevel++) { size = Math.max(1, cubeMap.getImage().getWidth() >> mipLevel); int dataSize = cubeMap.getImage().getMipMapSizes()[mipLevel]; byte[] dataArray = new byte[dataSize]; for (int i = 0; i < 6; i++) { ByteBuffer bb = cubeMap.getImage().getData(i); Texture2D tex = new Texture2D(new Image(cubeMap.getImage().getFormat(), size, size, data, cubeMap.getImage().getColorSpace())); Quad q = new Quad(cubeMap.getImage().getWidth() * 4 + nbMips, guiOffset + size); Geometry g = new Geometry("bg", q); Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
/** * Internally called to generate the maps. * This method will spawn 7 thread (one for the Irradiance spherical harmonics generator, and one for each face of the prefiltered env map). * Those threads will be executed in a ScheduledThreadPoolExecutor that will be shutdown when the generation is done. * * @param envMap the raw env map rendered by the env camera * @param probe the LightProbe to generate maps for * @param app the Application * @param listener a progress listener. (can be null if no progress reporting is needed) */ private static void generatePbrMaps(TextureCubeMap envMap, final LightProbe probe, Application app, EnvMapUtils.GenerationType genType, final JobProgressListener<LightProbe> listener) { IrradianceSphericalHarmonicsGenerator irrShGenerator; PrefilteredEnvMapFaceGenerator[] pemGenerators = new PrefilteredEnvMapFaceGenerator[6]; final JobState jobState = new JobState(new ScheduledThreadPoolExecutor(7)); irrShGenerator = new IrradianceSphericalHarmonicsGenerator(app, new JobListener(listener, jobState, probe, 6)); int size = envMap.getImage().getWidth(); irrShGenerator.setGenerationParam(EnvMapUtils.duplicateCubeMap(envMap), probe); jobState.executor.execute(irrShGenerator); for (int i = 0; i < pemGenerators.length; i++) { pemGenerators[i] = new PrefilteredEnvMapFaceGenerator(app, i, new JobListener(listener, jobState, probe, i)); pemGenerators[i].setGenerationParam(EnvMapUtils.duplicateCubeMap(envMap), size, EnvMapUtils.FixSeamsMethod.None, genType, probe.getPrefilteredEnvMap()); jobState.executor.execute(pemGenerators[i]); } }
probe.getPrefilteredEnvMap().getImage().dispose();
/** * Make a duplicate of this cube Map. That means that it's another instant * od TextureCubeMap, but the underlying buffers are duplicates of the * original ones. see {@link ByteBuffer#duplicate()} * * Use this if you need to read from the map from multiple threads, it * should garanty the thread safety. Note that if you want to write to the * cube map you have to make sure that the different thread do not write to * the same area of the buffer. The position, limit and mark are not an * issue. * * @param sourceMap * @return */ public static TextureCubeMap duplicateCubeMap(TextureCubeMap sourceMap) { Image srcImg = sourceMap.getImage(); Image cubeImage = new Image(srcImg.getFormat(), srcImg.getWidth(), srcImg.getHeight(), null, srcImg.getColorSpace()); for (ByteBuffer d : srcImg.getData()) { cubeImage.addData(d.duplicate()); } cubeImage.setMipMapSizes(srcImg.getMipMapSizes()); TextureCubeMap cubeMap = new TextureCubeMap(cubeImage); cubeMap.setAnisotropicFilter(sourceMap.getAnisotropicFilter()); cubeMap.setMagFilter(sourceMap.getMagFilter()); cubeMap.setMinFilter(sourceMap.getMinFilter()); cubeMap.setWrap(sourceMap.getWrap(Texture.WrapAxis.S)); return cubeMap; }
/** * Add a color texture to use for this framebuffer. * If MRT is enabled, then each subsequently added texture can be * rendered to through a shader that writes to the array <code>gl_FragData</code>. * If MRT is not enabled, then the index set with {@link FrameBuffer#setTargetIndex(int) } * is rendered to by the shader. * * @param tex The cube-map texture to add. * @param face The face of the cube-map to render to. */ public void addColorTexture(TextureCubeMap tex, TextureCubeMap.Face face) { if (id != -1) throw new UnsupportedOperationException("FrameBuffer already initialized."); Image img = tex.getImage(); checkSetTexture(tex, false); RenderBuffer colorBuf = new RenderBuffer(); colorBuf.slot = colorBufs.size(); colorBuf.tex = tex; colorBuf.format = img.getFormat(); colorBuf.face = face.ordinal(); colorBufs.add(colorBuf); }
/** * initialize the pem map * @param size the size of the map * @param imageFormat the format of the image * @return the initialized prefiltered env map */ public static TextureCubeMap createPrefilteredEnvMap(int size, Image.Format imageFormat) { TextureCubeMap pem = new TextureCubeMap(size, size, imageFormat); pem.setMagFilter(Texture.MagFilter.Bilinear); pem.setMinFilter(Texture.MinFilter.Trilinear); pem.getImage().setColorSpace(ColorSpace.Linear); int nbMipMap = Math.min(6, (int) (Math.log(size) / Math.log(2))); CubeMapWrapper targetWrapper = new CubeMapWrapper(pem); targetWrapper.initMipMaps(nbMipMap); return pem; } }
/** * initialize the Irradiancemap * @param size the size of the map * @param imageFormat the format of the image * @return the initialized Irradiance map */ public static TextureCubeMap createIrradianceMap(int size, Image.Format imageFormat) { TextureCubeMap irrMap = new TextureCubeMap(size, size, imageFormat); irrMap.setMagFilter(Texture.MagFilter.Bilinear); irrMap.setMinFilter(Texture.MinFilter.BilinearNoMipMaps); irrMap.getImage().setColorSpace(ColorSpace.Linear); return irrMap; }
/** * Creates a CubeMapWrapper for the given cube map * Note that the cube map must be initialized, and the mipmaps sizes should * be set if relevant for them to be readable/writable * @param cubeMap the cubemap to wrap. */ public CubeMapWrapper(TextureCubeMap cubeMap) { image = cubeMap.getImage(); if (image.hasMipmaps()) { int nbMipMaps = image.getMipMapSizes().length; sizes = new int[nbMipMaps]; mipMapRaster = new MipMapImageRaster(image, 0); for (int i = 0; i < nbMipMaps; i++) { sizes[i] = Math.max(1, image.getWidth() >> i); } } else { sizes = new int[1]; sizes[0] = image.getWidth(); } raster = new DefaultImageRaster(image, 0,0 , false); }
@Override public void render(final RenderManager renderManager) { if (jobs.isEmpty()) { return; } final SnapshotJob job = jobs.get(0); for (int i = 0; i < 6; i++) { viewports[i].clearScenes(); viewports[i].attachScene(job.scene); renderManager.renderViewPort(viewports[i], 0.16f); buffers[i] = BufferUtils.createByteBuffer(size * size * imageFormat.getBitsPerPixel() / 8); renderManager.getRenderer().readFrameBufferWithFormat(framebuffers[i], buffers[i], imageFormat); images[i] = new Image(imageFormat, size, size, buffers[i], ColorSpace.Linear); MipMapGenerator.generateMipMaps(images[i]); } final TextureCubeMap map = EnvMapUtils.makeCubeMap(images[0], images[1], images[2], images[3], images[4], images[5], imageFormat); debugEnv = map; job.callback.done(map); map.getImage().dispose(); jobs.remove(0); }
@Override public void done(Integer result) { if (globalListener != null) { if (result < 6) { globalListener.step("Prefiltered env map face " + result + " generated"); } else { globalListener.step("Irradiance map generated"); } } jobState.done[index] = true; if (jobState.isDone()) { probe.setNbMipMaps(probe.getPrefilteredEnvMap().getImage().getMipMapSizes().length); probe.setReady(true); if (globalListener != null) { globalListener.done(probe); } jobState.executor.shutdownNow(); } } }