diff --git a/.github/workflows/screenshot-test-comment.yml b/.github/workflows/screenshot-test-comment.yml index 5b4ae992e9..e63aa3f539 100644 --- a/.github/workflows/screenshot-test-comment.yml +++ b/.github/workflows/screenshot-test-comment.yml @@ -49,8 +49,10 @@ jobs: // Find the ScreenshotTests job let screenshotTestRun = null; + let workflowRunId = null; for (const run of runs.data.workflow_runs) { if (run.name === 'Build jMonkeyEngine') { + workflowRunId = run.id; const jobs = await github.rest.actions.listJobsForWorkflowRun({ owner, repo, @@ -73,9 +75,25 @@ jobs: return; } + core.setOutput('run_url', `https://github.com/${owner}/${repo}/actions/runs/${workflowRunId}`); + // Check if the job failed if (screenshotTestRun.conclusion === 'failure') { - core.setOutput('failed', 'true'); + // Now check if the changed images artifact exists + const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner, + repo, + run_id: workflowRunId + }); + + const artifact = artifacts.data.artifacts.find(a => a.name === 'screenshot-test-report'); + if (artifact) { + core.setOutput('failed', 'true'); + core.setOutput('artifact_url', `https://github.com/${owner}/${repo}/actions/runs/${workflowRunId}/artifacts/${artifact.id}`); + } else { + console.log('Job failed but no changed images were generated.'); + core.setOutput('failed', 'false'); + } } else { core.setOutput('failed', 'false'); } @@ -98,7 +116,8 @@ jobs: The purpose of these tests is to ensure that changes introduced in this PR don't break visual features. They are visual unit tests. 📄 **Where to find the report:** - - Go to the (failed run) > Summary > Artifacts > screenshot-test-report + - **[Direct Download: screenshot-test-report](${{ steps.check-status.outputs.artifact_url }})** + - Alternatively, go to the [failed run summary](${{ steps.check-status.outputs.run_url }}) > Artifacts > screenshot-test-report - Download the zip and open jme3-screenshot-tests/build/reports/ScreenshotDiffReport.html ⚠️ **If you didn't expect to change anything visual:** diff --git a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/OffScreenshotAppState.java b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/OffScreenshotAppState.java new file mode 100644 index 0000000000..17eeac3c86 --- /dev/null +++ b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/OffScreenshotAppState.java @@ -0,0 +1,58 @@ +package org.jmonkeyengine.screenshottests.testframework; + +import com.jme3.app.Application; +import com.jme3.app.state.AbstractAppState; +import com.jme3.app.state.AppStateManager; +import com.jme3.renderer.Renderer; +import com.jme3.system.JmeSystem; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Texture2D; +import com.jme3.util.BufferUtils; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.Path; +import java.util.Optional; + +public class OffScreenshotAppState extends AbstractAppState{ + + private Texture2D renderTexture; + private Renderer renderer; + private FrameBuffer frameBuffer; + private Optional capture = Optional.empty(); + + private ByteBuffer outBuf; + + public void takeScreenshot(Path pathToSaveTo) { + capture = Optional.of(pathToSaveTo); + } + + public OffScreenshotAppState(Texture2D renderTexture, FrameBuffer frameBuffer) { + this.renderTexture = renderTexture; + this.frameBuffer = frameBuffer; + } + + @Override + public void initialize(AppStateManager stateManager, Application app) { + super.initialize(stateManager, app); + renderer = app.getRenderManager().getRenderer(); + outBuf = BufferUtils.createByteBuffer(renderTexture.getImage().getWidth() * renderTexture.getImage().getHeight() * 4); + } + + @Override + public void postRender() { + super.postRender(); + if (capture.isPresent()) { + + renderer.readFrameBuffer(frameBuffer, outBuf); + try { + FileOutputStream fileOutBuf = new FileOutputStream(capture.get().toFile()); + JmeSystem.writeImageFile(fileOutBuf, "png",outBuf, renderTexture.getImage().getWidth(), renderTexture.getImage().getHeight()); + }catch (IOException e) { + throw new RuntimeException(e); + } + capture = Optional.empty(); + } + } +} diff --git a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/PixelSamenessDegree.java b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/PixelSamenessDegree.java index 3fcc2abaed..c2e7a6ef63 100644 --- a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/PixelSamenessDegree.java +++ b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/PixelSamenessDegree.java @@ -38,7 +38,7 @@ */ public enum PixelSamenessDegree{ SAME(1, null), - NEGLIGIBLY_DIFFERENT(1, ColorRGBA.Green), + NEGLIGIBLY_DIFFERENT(3, ColorRGBA.Green), SUBTLY_DIFFERENT(10, ColorRGBA.Blue), MEDIUMLY_DIFFERENT(20, ColorRGBA.Yellow), diff --git a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ScreenshotNoInputAppState.java b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ScreenshotNoInputAppState.java deleted file mode 100644 index 2817bb0e73..0000000000 --- a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ScreenshotNoInputAppState.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (c) 2024 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 org.jmonkeyengine.screenshottests.testframework; - -import com.jme3.app.Application; -import com.jme3.app.state.AbstractAppState; -import com.jme3.app.state.AppStateManager; -import com.jme3.input.controls.ActionListener; -import com.jme3.post.SceneProcessor; -import com.jme3.profile.AppProfiler; -import com.jme3.renderer.Camera; -import com.jme3.renderer.RenderManager; -import com.jme3.renderer.Renderer; -import com.jme3.renderer.ViewPort; -import com.jme3.renderer.queue.RenderQueue; -import com.jme3.system.JmeSystem; -import com.jme3.texture.FrameBuffer; -import com.jme3.util.BufferUtils; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * This is more or less the same as ScreenshotAppState but without the keyboard input - * (because in a headless environment, there is no keyboard and trying to configure it caused - * errors). - * - * @author Richard Tingle (aka richtea) - * - */ -public class ScreenshotNoInputAppState extends AbstractAppState implements ActionListener, SceneProcessor { - - private static final Logger logger = Logger.getLogger(ScreenshotNoInputAppState.class.getName()); - private String filePath; - private boolean capture = false; - private boolean numbered = true; - private Renderer renderer; - private RenderManager rm; - private ByteBuffer outBuf; - private String shotName; - private long shotIndex = 0; - private int width, height; - - /** - * ViewPort to which the SceneProcessor is attached - */ - private ViewPort last; - - /** - * Using this constructor, the screenshot files will be written sequentially to the system - * default storage folder. - */ - public ScreenshotNoInputAppState() { - this(null); - } - - /** - * This constructor allows you to specify the output file path of the screenshot. - * Include the separator at the end of the path. - * Use an empty string to use the application folder. Use NULL to use the system - * default storage folder. - * @param filePath The screenshot file path to use. Include the separator at the end of the path. - */ - public ScreenshotNoInputAppState(String filePath) { - this.filePath = filePath; - } - - /** - * This constructor allows you to specify the output file path of the screenshot. - * Include the separator at the end of the path. - * Use an empty string to use the application folder. Use NULL to use the system - * default storage folder. - * @param filePath The screenshot file path to use. Include the separator at the end of the path. - * @param fileName The name of the file to save the screenshot as. - */ - public ScreenshotNoInputAppState(String filePath, String fileName) { - this.filePath = filePath; - this.shotName = fileName; - } - - /** - * This constructor allows you to specify the output file path of the screenshot and - * a base index for the shot index. - * Include the separator at the end of the path. - * Use an empty string to use the application folder. Use NULL to use the system - * default storage folder. - * @param filePath The screenshot file path to use. Include the separator at the end of the path. - * @param shotIndex The base index for screenshots. The first screenshot will have - * shotIndex + 1 appended, the next shotIndex + 2, and so on. - */ - public ScreenshotNoInputAppState(String filePath, long shotIndex) { - this.filePath = filePath; - this.shotIndex = shotIndex; - } - - /** - * This constructor allows you to specify the output file path of the screenshot and - * a base index for the shot index. - * Include the separator at the end of the path. - * Use an empty string to use the application folder. Use NULL to use the system - * default storage folder. - * @param filePath The screenshot file path to use. Include the separator at the end of the path. - * @param fileName The name of the file to save the screenshot as. - * @param shotIndex The base index for screenshots. The first screenshot will have - * shotIndex + 1 appended, the next shotIndex + 2, and so on. - */ - public ScreenshotNoInputAppState(String filePath, String fileName, long shotIndex) { - this.filePath = filePath; - this.shotName = fileName; - this.shotIndex = shotIndex; - } - - /** - * Set the file path to store the screenshot. - * Include the separator at the end of the path. - * Use an empty string to use the application folder. Use NULL to use the system - * default storage folder. - * @param filePath File path to use to store the screenshot. Include the separator at the end of the path. - */ - public void setFilePath(String filePath) { - this.filePath = filePath; - } - - /** - * Set the file name of the screenshot. - * @param fileName File name to save the screenshot as. - */ - public void setFileName(String fileName) { - this.shotName = fileName; - } - - /** - * Sets the base index that will used for subsequent screenshots. - * - * @param index the desired base index - */ - public void setShotIndex(long index) { - this.shotIndex = index; - } - - /** - * Sets if the filename should be appended with a number representing the - * current sequence. - * @param numberedWanted If numbering is wanted. - */ - public void setIsNumbered(boolean numberedWanted) { - this.numbered = numberedWanted; - } - - @Override - public void initialize(AppStateManager stateManager, Application app) { - if (!super.isInitialized()) { - List vps = app.getRenderManager().getPostViews(); - last = vps.get(vps.size() - 1); - last.addProcessor(this); - - if (shotName == null) { - shotName = app.getClass().getSimpleName(); - } - } - - super.initialize(stateManager, app); - } - - /** - * Clean up this AppState during the first update after it gets detached. - *

- * Because each ScreenshotAppState is also a SceneProcessor (in addition to - * being an AppState) this method is also invoked when the SceneProcessor - * get removed from its ViewPort, leading to an indirect recursion: - *

  1. AppStateManager invokes ScreenshotAppState.cleanup()
  2. - *
  3. cleanup() invokes ViewPort.removeProcessor()
  4. - *
  5. removeProcessor() invokes ScreenshotAppState.cleanup()
  6. - *
  7. ... and so on.
  8. - *
- *

- * In order to break this recursion, this method only removes the - * SceneProcessor if it has not previously been removed. - *

- * A better design would have the AppState and SceneProcessor be 2 distinct - * objects, but doing so now might break applications that rely on them - * being a single object. - */ - @Override - public void cleanup() { - ViewPort viewPort = last; - if (viewPort != null) { - last = null; - viewPort.removeProcessor(this); // XXX indirect recursion! - } - - super.cleanup(); - } - - @Override - public void onAction(String name, boolean value, float tpf) { - if (value) { - capture = true; - } - } - - public void takeScreenshot() { - capture = true; - } - - @Override - public void initialize(RenderManager rm, ViewPort vp) { - renderer = rm.getRenderer(); - this.rm = rm; - reshape(vp, vp.getCamera().getWidth(), vp.getCamera().getHeight()); - } - - @Override - public boolean isInitialized() { - return super.isInitialized() && renderer != null; - } - - @Override - public void reshape(ViewPort vp, int w, int h) { - outBuf = BufferUtils.createByteBuffer(w * h * 4); - width = w; - height = h; - } - - @Override - public void preFrame(float tpf) { - // do nothing - } - - @Override - public void postQueue(RenderQueue rq) { - // do nothing - } - - @Override - public void postFrame(FrameBuffer out) { - if (capture) { - capture = false; - - Camera curCamera = rm.getCurrentCamera(); - int viewX = (int) (curCamera.getViewPortLeft() * curCamera.getWidth()); - int viewY = (int) (curCamera.getViewPortBottom() * curCamera.getHeight()); - int viewWidth = (int) ((curCamera.getViewPortRight() - curCamera.getViewPortLeft()) * curCamera.getWidth()); - int viewHeight = (int) ((curCamera.getViewPortTop() - curCamera.getViewPortBottom()) * curCamera.getHeight()); - - renderer.setViewPort(0, 0, width, height); - renderer.readFrameBuffer(out, outBuf); - renderer.setViewPort(viewX, viewY, viewWidth, viewHeight); - - File file; - String filename; - if (numbered) { - shotIndex++; - filename = shotName + shotIndex; - } else { - filename = shotName; - } - - if (filePath == null) { - file = new File(JmeSystem.getStorageFolder() + File.separator + filename + ".png").getAbsoluteFile(); - } else { - file = new File(filePath + filename + ".png").getAbsoluteFile(); - } - - if (logger.isLoggable(Level.FINE)) { - logger.log(Level.FINE, "Saving ScreenShot to: {0}", file.getAbsolutePath()); - } - - try { - writeImageFile(file); - } catch (IOException ex) { - logger.log(Level.SEVERE, "Error while saving screenshot", ex); - } - } - } - - @Override - public void setProfiler(AppProfiler profiler) { - // not implemented - } - - /** - * Called by postFrame() once the screen has been captured to outBuf. - * - * @param file the output file - * @throws IOException if an I/O error occurs - */ - protected void writeImageFile(File file) throws IOException { - OutputStream outStream = new FileOutputStream(file); - try { - JmeSystem.writeImageFile(outStream, "png", outBuf, width, height); - } finally { - outStream.close(); - } - } -} diff --git a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ScreenshotTest.java b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ScreenshotTest.java index 5bff5d9960..2be281c511 100644 --- a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ScreenshotTest.java +++ b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/ScreenshotTest.java @@ -97,7 +97,8 @@ public void run(){ settings.setResolution(resolution.getWidth(), resolution.getHeight()); settings.setAudioRenderer(null); // Disable audio (for headless) settings.setUseInput(false); //while it will run with inputs on it causes non-fatal errors. - + settings.setGammaCorrection(false); + settings.setRenderer(AppSettings.LWJGL_OPENGL45); String imageFilePrefix = baseImageFileName == null ? calculateImageFilePrefix() : baseImageFileName; TestDriver.bootAppForTest(testType,settings,imageFilePrefix, framesToTakeScreenshotsOn, states); diff --git a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/TestDriver.java b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/TestDriver.java index ca0cfa98a9..434d9755f9 100644 --- a/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/TestDriver.java +++ b/jme3-screenshot-tests/src/main/java/org/jmonkeyengine/screenshottests/testframework/TestDriver.java @@ -36,15 +36,23 @@ import com.jme3.app.SimpleApplication; import com.jme3.app.state.AppState; import com.jme3.app.state.BaseAppState; +import com.jme3.math.ColorRGBA; import com.jme3.math.FastMath; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; import com.jme3.system.AppSettings; import com.jme3.system.JmeContext; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Image; +import com.jme3.texture.Texture; +import com.jme3.texture.Texture2D; import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; +import java.awt.Color; import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.file.Files; @@ -56,7 +64,9 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -98,16 +108,22 @@ public class TestDriver extends BaseAppState{ Collection framesToTakeScreenshotsOn; - ScreenshotNoInputAppState screenshotAppState; + private FrameBuffer offBuffer; + + private Texture2D renderTexture; private CountDownLatch waitLatch; private final int tickToTerminateApp; - public TestDriver(ScreenshotNoInputAppState screenshotAppState, Collection framesToTakeScreenshotsOn){ - this.screenshotAppState = screenshotAppState; + OffScreenshotAppState offScreenshotAppState; + + Map screenshotsAtFrames = new HashMap<>(); + + public TestDriver( Collection framesToTakeScreenshotsOn){ this.framesToTakeScreenshotsOn = framesToTakeScreenshotsOn; this.tickToTerminateApp = framesToTakeScreenshotsOn.stream().mapToInt(i -> i).max().orElse(0) + 1; + } @Override @@ -115,7 +131,15 @@ public void update(float tpf){ super.update(tpf); if(framesToTakeScreenshotsOn.contains(tick)){ - screenshotAppState.takeScreenshot(); + Path screenshotPath = null; + try { + screenshotPath = Files.createTempFile("screenshot_" + tick + "_", ".tmp"); + } catch (IOException e) { + throw new RuntimeException(e); + } + screenshotPath.toFile().deleteOnExit(); + screenshotsAtFrames.put(tick, screenshotPath); + offScreenshotAppState.takeScreenshot(screenshotPath); } if(tick >= tickToTerminateApp){ getApplication().stop(true); @@ -131,6 +155,29 @@ public void update(float tpf){ waitLatch.countDown(); }; + AppSettings settings = app.getContext().getSettings(); + int width = settings.getWidth(); + int height = settings.getHeight(); + renderTexture = new Texture2D(width, height, Image.Format.RGBA8); + renderTexture.setMinFilter(Texture.MinFilter.BilinearNearestMipMap); + renderTexture.setMagFilter(Texture.MagFilter.Bilinear); + + offBuffer = new FrameBuffer(width, height, 1); + offBuffer.setDepthTarget(FrameBuffer.FrameBufferTarget.newTarget(Image.Format.Depth)); + offBuffer.addColorTarget(FrameBuffer.FrameBufferTarget.newTarget(renderTexture)); + offBuffer.setSrgb(true); + + offScreenshotAppState = new OffScreenshotAppState(renderTexture, offBuffer); + + app.getRenderer().setMainFrameBufferOverride(offBuffer); + + + getStateManager().attach(offScreenshotAppState); + } + + @Override + public void render(RenderManager rm) { + super.render(rm); } @Override protected void cleanup(Application app){} @@ -149,21 +196,8 @@ public static void bootAppForTest(TestType testType, AppSettings appSettings, St FastMath.rand.setSeed(0); //try to make things deterministic by setting the random seed Collections.sort(framesToTakeScreenshotsOn); - Path imageTempDir; - - try{ - imageTempDir = Files.createTempDirectory("jmeSnapshotTest"); - } catch(IOException e){ - throw new RuntimeException(e); - } - - ScreenshotNoInputAppState screenshotAppState = new ScreenshotNoInputAppState(imageTempDir.toString() + "/"); - String screenshotAppFileNamePrefix = "Screenshot-"; - screenshotAppState.setFileName(screenshotAppFileNamePrefix); - List states = new ArrayList<>(Arrays.asList(initialStates)); - TestDriver testDriver = new TestDriver(screenshotAppState, framesToTakeScreenshotsOn); - states.add(screenshotAppState); + TestDriver testDriver = new TestDriver(framesToTakeScreenshotsOn); states.add(testDriver); SimpleApplication app = new App(states.toArray(new AppState[0])); @@ -189,42 +223,24 @@ public static void bootAppForTest(TestType testType, AppSettings appSettings, St throw new RuntimeException(e); } - //search the imageTempDir - List imageFiles = new ArrayList<>(); - try(Stream paths = Files.list(imageTempDir)){ - paths.forEach(imageFiles::add); - } catch(IOException e){ - throw new RuntimeException(e); - } - //this resorts with natural numeric ordering (so App10.png comes after App9.png) - imageFiles.sort(new Comparator(){ - @Override - public int compare(Path p1, Path p2){ - return extractNumber(p1).compareTo(extractNumber(p2)); - } - - private Integer extractNumber(Path path){ - String name = path.getFileName().toString(); - int numStart = screenshotAppFileNamePrefix.length(); - int numEnd = name.lastIndexOf(".png"); - return Integer.parseInt(name.substring(numStart, numEnd)); - } - }); - - if(imageFiles.isEmpty()){ + if(testDriver.screenshotsAtFrames.isEmpty()){ fail("No screenshot found in the temporary directory. Did the application crash?"); } - if(imageFiles.size() != framesToTakeScreenshotsOn.size()){ - fail("Not all screenshots were taken, expected " + framesToTakeScreenshotsOn.size() + " but got " + imageFiles.size()); + if(testDriver.screenshotsAtFrames.size() != framesToTakeScreenshotsOn.size()){ + fail("Not all screenshots were taken, expected " + framesToTakeScreenshotsOn.size() + " but got " + testDriver.screenshotsAtFrames.size()); } String failureMessage = null; try { - for(int screenshotIndex=0;screenshotIndex paths = Files.walk(temporaryFolder)) { - paths.sorted((a, b) -> b.getNameCount() - a.getNameCount()) - .forEach(path -> { - try { - Files.delete(path); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } catch (IOException e) { - throw new RuntimeException(e); - } - } /** * Saves the image with the exact file name it needs to go into the resources directory to be a new reference image @@ -374,7 +374,17 @@ private static boolean imagesAreTheSame(BufferedImage img1, BufferedImage img2) for (int y = 0; y < img1.getHeight(); y++) { for (int x = 0; x < img1.getWidth(); x++) { if (img1.getRGB(x, y) != img2.getRGB(x, y)){ - return false; + Color color1 = new Color(img1.getRGB(x, y)); + Color color2 = new Color(img2.getRGB(x, y)); + + double dr = Math.abs(color1.getRed()-color2.getRed()); + double dg = Math.abs(color1.getGreen()-color2.getGreen()); + double db = Math.abs(color1.getBlue()-color2.getBlue()); + + double largestPixelValueDifference = Math.max(dr, Math.max(dg, db)); + if(largestPixelValueDifference>PixelSamenessDegree.NEGLIGIBLY_DIFFERENT.getMaximumAllowedDifference()){ + return false; + } } } } diff --git a/jme3-screenshot-tests/src/test/java/org/jmonkeyengine/screenshottests/simple/SimpleGreyCube.java b/jme3-screenshot-tests/src/test/java/org/jmonkeyengine/screenshottests/simple/SimpleGreyCube.java new file mode 100644 index 0000000000..46f25a548f --- /dev/null +++ b/jme3-screenshot-tests/src/test/java/org/jmonkeyengine/screenshottests/simple/SimpleGreyCube.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2026 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 org.jmonkeyengine.screenshottests.simple; + +import com.jme3.app.Application; +import com.jme3.app.SimpleApplication; +import com.jme3.app.state.BaseAppState; +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.scene.Geometry; +import com.jme3.scene.Node; +import com.jme3.scene.shape.Box; +import org.jmonkeyengine.screenshottests.testframework.ScreenshotTestBase; +import org.jmonkeyengine.screenshottests.testframework.TestResolution; +import org.junit.jupiter.api.Test; + +/** + * @author Richard Tingle (aka richtea) + */ +public class SimpleGreyCube extends ScreenshotTestBase{ + + /** + * This allows the tests themselves to be baselines to ensure they are getting gamma correction + * right. This is a 50% grey cube so the output image should also be 50% grey. + */ + @Test + public void simpleGreyCube(){ + + screenshotTest( + new BaseAppState(){ + @Override + protected void initialize(Application app){ + AssetManager assetManager = app.getAssetManager(); + Node rootNode = ((SimpleApplication)app).getRootNode(); + + Box box = new Box(1.5f,1.5f,1.5f); + Geometry g = new Geometry("box", box); + Material mat = new Material(assetManager,"Common/MatDefs/Misc/Unshaded.j3md"); + mat.setColor("Color", new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f)); + g.setMaterial(mat); + rootNode.attachChild(g); + } + + @Override + protected void cleanup(Application app){} + + @Override + protected void onEnable(){} + + @Override + protected void onDisable(){} + } + ).setTestResolution(new TestResolution(100,100)).run(); + + + } +} diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestIssue2076.testIssue2076_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestIssue2076.testIssue2076_f1.png index f4cbc42002..33b95c84d4 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestIssue2076.testIssue2076_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestIssue2076.testIssue2076_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f10.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f10.png index 028530e9c8..ee09c3ac1a 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f10.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f10.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f60.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f60.png index cca8ae963f..eb63b03d34 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f60.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.animation.TestMotionPath.testMotionPath_f60.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f15.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f15.png index b22da40fc7..9a51c45043 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f15.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f15.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f2.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f2.png index b7f4833cbc..f718c240fa 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f2.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestExplosionEffect.testExplosionEffect_f2.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_localSpace_f45.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_localSpace_f45.png index 1d1c733b3b..ca8fb7d2d3 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_localSpace_f45.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_localSpace_f45.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_worldSpace_f45.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_worldSpace_f45.png index cf72a001e5..86c99a7050 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_worldSpace_f45.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.effects.TestIssue1773.testIssue1773_worldSpace_f45.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f1.png index 61bd29c0b4..5a6a370e50 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f5.png index 603680a81d..ff3811f176 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.export.TestOgreConvert.testOgreConvert_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.gui.TestBitmapText3D.testBitmapText3D_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.gui.TestBitmapText3D.testBitmapText3D_f1.png index 40ea199165..c24683ec1c 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.gui.TestBitmapText3D.testBitmapText3D_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.gui.TestBitmapText3D.testBitmapText3D_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_DefaultDirectionalLight_f12.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_DefaultDirectionalLight_f12.png index 1589f38f1e..23ebee7eb4 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_DefaultDirectionalLight_f12.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_DefaultDirectionalLight_f12.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_HighRoughness_f12.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_HighRoughness_f12.png index ab61568039..6c5b0bb720 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_HighRoughness_f12.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_HighRoughness_f12.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_LowRoughness_f12.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_LowRoughness_f12.png index 564abc0e5d..4b639c66df 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_LowRoughness_f12.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_LowRoughness_f12.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_UpdatedDirectionalLight_f12.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_UpdatedDirectionalLight_f12.png index 4c764f9223..841f14926d 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_UpdatedDirectionalLight_f12.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRLighting.testPBRLighting_UpdatedDirectionalLight_f12.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithRealtimeBaking_f10.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithRealtimeBaking_f10.png index ac5bb874f5..60223661f0 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithRealtimeBaking_f10.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithRealtimeBaking_f10.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithoutRealtimeBaking_f10.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithoutRealtimeBaking_f10.png index ac5bb874f5..60223661f0 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithoutRealtimeBaking_f10.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.light.pbr.TestPBRSimple.testPBRSimple_WithoutRealtimeBaking_f10.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f10.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f10.png index 4608681de3..60d24978b0 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f10.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f10.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f60.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f60.png index 11ac17390f..65c4e50421 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f60.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.material.TestSimpleBumps.testSimpleBumps_f60.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromAbove_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromAbove_f1.png index 4a3e1f2af0..f2cf7868d4 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromAbove_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromAbove_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromFront_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromFront_f1.png index a798a16d34..f97496e5e4 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromFront_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromFront_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromRight_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromRight_f1.png index 8be63bb6fa..3c82f48e65 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromRight_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.model.shape.TestBillboard.testBillboard_fromRight_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestCartoonEdge.testCartoonEdge_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestCartoonEdge.testCartoonEdge_f1.png index 453219b949..aa712c18b0 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestCartoonEdge.testCartoonEdge_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestCartoonEdge.testCartoonEdge_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestFog.testFog_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestFog.testFog_f1.png index da77df67cc..7724ba49ce 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestFog.testFog_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestFog.testFog_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestLightScattering.testLightScattering_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestLightScattering.testLightScattering_f1.png index bf84144b5a..228137327d 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestLightScattering.testLightScattering_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.post.TestLightScattering.testLightScattering_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f1.png index c761934d2d..19419a285e 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f10.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f10.png index 2ddf12bb33..bcbde7f70b 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f10.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.scene.instancing.TestInstanceNodeWithPbr.testInstanceNodeWithPbr_f10.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.simple.SimpleGreyCube.simpleGreyCube_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.simple.SimpleGreyCube.simpleGreyCube_f1.png new file mode 100644 index 0000000000..3c1ab2e7aa Binary files /dev/null and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.simple.SimpleGreyCube.simpleGreyCube_f1.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_FinalRender_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_FinalRender_f5.png index aa8c62dcd4..eb9e6345f7 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_FinalRender_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_FinalRender_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_GeometryNormals_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_GeometryNormals_f5.png index 215274f23d..a3cc76210f 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_GeometryNormals_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_GeometryNormals_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_MetallicMap_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_MetallicMap_f5.png index dbbe6cf3a5..49ef37251b 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_MetallicMap_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_MetallicMap_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_NormalMap_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_NormalMap_f5.png index 791339d4c3..39801970b4 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_NormalMap_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_NormalMap_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_RoughnessMap_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_RoughnessMap_f5.png index 167ec2eeb7..6f0fd8bf72 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_RoughnessMap_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrain.testPBRTerrain_RoughnessMap_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_AmbientOcclusion_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_AmbientOcclusion_f5.png index 5c515e1e26..8fdf0338a0 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_AmbientOcclusion_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_AmbientOcclusion_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_Emissive_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_Emissive_f5.png index f1304956c3..d96c981f77 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_Emissive_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_Emissive_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_FinalRender_f5.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_FinalRender_f5.png index aa8c62dcd4..eb9e6345f7 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_FinalRender_f5.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.terrain.TestPBRTerrainAdvanced.testPBRTerrainAdvanced_FinalRender_f5.png differ diff --git a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.water.TestPostWater.testPostWater_f1.png b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.water.TestPostWater.testPostWater_f1.png index eaeb6f7c02..14bec3a3d6 100644 Binary files a/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.water.TestPostWater.testPostWater_f1.png and b/jme3-screenshot-tests/src/test/resources/org.jmonkeyengine.screenshottests.water.TestPostWater.testPostWater_f1.png differ