From 90bf137894a50c132806e3aa7931756119552fa0 Mon Sep 17 00:00:00 2001 From: "sha..rd" Date: Sun, 3 Apr 2011 21:45:29 +0000 Subject: [PATCH] * Added new renderer capability: NonPowerOfTwoTextures * LwjglRenderer will show warnings when NPOT textures are used and the graphics card doesn't support them * LwjglGL1Renderer will scale textures to POT sizes if NPOT is not supported * Enable simple logging git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7177 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- engine/src/core/com/jme3/renderer/Caps.java | 7 +++- .../desktop/com/jme3/system/JmeSystem.java | 36 ++++++++++--------- .../jme3/renderer/lwjgl/LwjglGL1Renderer.java | 27 +++++++++++++- .../jme3/renderer/lwjgl/LwjglRenderer.java | 21 +++++++++++ .../jme3tools/converters/MipMapGenerator.java | 20 +++++++++++ 5 files changed, 92 insertions(+), 19 deletions(-) diff --git a/engine/src/core/com/jme3/renderer/Caps.java b/engine/src/core/com/jme3/renderer/Caps.java index f9a02346b..6f0457885 100644 --- a/engine/src/core/com/jme3/renderer/Caps.java +++ b/engine/src/core/com/jme3/renderer/Caps.java @@ -139,7 +139,12 @@ public enum Caps { * Supports Format.LATC for textures, this includes * support for ATI's 3Dc texture compression. */ - TextureCompressionLATC, + TextureCompressionLATC, + + /** + * Supports Non-Power-Of-Two (NPOT) textures and framebuffers + */ + NonPowerOfTwoTextures, /// Vertex Buffer features MeshInstancing, diff --git a/engine/src/desktop/com/jme3/system/JmeSystem.java b/engine/src/desktop/com/jme3/system/JmeSystem.java index 55a19229a..3aa6cd39f 100644 --- a/engine/src/desktop/com/jme3/system/JmeSystem.java +++ b/engine/src/desktop/com/jme3/system/JmeSystem.java @@ -37,11 +37,14 @@ import com.jme3.app.SettingsDialog.SelectionListener; import com.jme3.asset.AssetManager; import com.jme3.asset.DesktopAssetManager; import com.jme3.audio.AudioRenderer; +import com.jme3.util.JmeFormatter; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; @@ -318,7 +321,6 @@ public class JmeSystem { } AudioRenderer ar = clazz.newInstance(); -// ar = new QueuedAudioRenderer(ar); return ar; }catch (InstantiationException ex){ logger.log(Level.SEVERE, "Failed to create context", ex); @@ -336,28 +338,28 @@ public class JmeSystem { return; initialized = true; -// try { -// if (!lowPermissions){ -// // can only modify logging settings -// // if permissions are available -// -// JmeFormatter formatter = new JmeFormatter(); + try { + if (!lowPermissions){ + // can only modify logging settings + // if permissions are available + + JmeFormatter formatter = new JmeFormatter(); // Handler fileHandler = new FileHandler("jme.log"); // fileHandler.setFormatter(formatter); // Logger.getLogger("").addHandler(fileHandler); -// -// Handler consoleHandler = new ConsoleHandler(); -// consoleHandler.setFormatter(formatter); -// Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]); -// Logger.getLogger("").addHandler(consoleHandler); -// + + Handler consoleHandler = new ConsoleHandler(); + consoleHandler.setFormatter(formatter); + Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]); + Logger.getLogger("").addHandler(consoleHandler); + // Logger.getLogger("com.jme3").setLevel(Level.FINEST); -// } + } // } catch (IOException ex){ // logger.log(Level.SEVERE, "I/O Error while creating log file", ex); -// } catch (SecurityException ex){ -// logger.log(Level.SEVERE, "Security error in creating log file", ex); -// } + } catch (SecurityException ex){ + logger.log(Level.SEVERE, "Security error in creating log file", ex); + } logger.log(Level.INFO, "Running on {0}", getFullName()); diff --git a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java b/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java index f13489b39..e18e1b27d 100644 --- a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java +++ b/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java @@ -1,5 +1,6 @@ package com.jme3.renderer.lwjgl; +import com.jme3.math.FastMath; import com.jme3.renderer.GL1Renderer; import com.jme3.shader.Shader; import com.jme3.shader.Shader.ShaderSource; @@ -33,6 +34,7 @@ import java.nio.IntBuffer; import java.util.EnumSet; import java.util.logging.Logger; import jme3tools.converters.MipMapGenerator; +import org.lwjgl.opengl.GLContext; import static org.lwjgl.opengl.GL11.*; @@ -47,6 +49,7 @@ public class LwjglGL1Renderer implements GL1Renderer { private final FloatBuffer fb16 = BufferUtils.createFloatBuffer(16); private final RenderContext context = new RenderContext(); private final GLObjectManager objManager = new GLObjectManager(); + private final EnumSet caps = EnumSet.noneOf(Caps.class); private int maxTexSize; private int maxCubeTexSize; @@ -80,13 +83,21 @@ public class LwjglGL1Renderer implements GL1Renderer { } public EnumSet getCaps() { - return EnumSet.noneOf(Caps.class); + return caps; } public void initialize() { //glDisable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + if (GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){ + caps.add(Caps.NonPowerOfTwoTextures); + }else{ + logger.log(Level.WARNING, "Your graphics card does not " + + "support non-power-of-2 textures. " + + "Some features might not work."); + } } public void resetGLObjects() { @@ -470,6 +481,20 @@ public class LwjglGL1Renderer implements GL1Renderer { statistics.onTextureUse(img, true); } + // Check sizes if graphics card doesn't support NPOT + if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){ + if (img.getWidth() != 0 && img.getHeight() != 0){ + if (!FastMath.isPowerOfTwo(img.getWidth()) + || !FastMath.isPowerOfTwo(img.getHeight()) + || img.getWidth() != img.getHeight()){ + + // Resize texture to Power-of-2 size + MipMapGenerator.resizeToPowerOf2(img); + + } + } + } + if (!img.hasMipmaps() && mips) { // No pregenerated mips available, // generate from base level if required diff --git a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java b/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java index f1351bdb2..69f42684b 100644 --- a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java +++ b/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java @@ -34,6 +34,7 @@ package com.jme3.renderer.lwjgl; import com.jme3.light.LightList; import com.jme3.material.RenderState; import com.jme3.math.ColorRGBA; +import com.jme3.math.FastMath; import com.jme3.math.Matrix4f; import com.jme3.math.Quaternion; import com.jme3.math.Vector2f; @@ -316,6 +317,14 @@ public class LwjglRenderer implements Renderer { caps.add(Caps.VertexBufferArray); } + if (ctxCaps.GL_ARB_texture_non_power_of_two){ + caps.add(Caps.NonPowerOfTwoTextures); + }else{ + logger.log(Level.WARNING, "Your graphics card does not " + + "support non-power-of-2 textures. " + + "Some features might not work."); + } + boolean latc = ctxCaps.GL_EXT_texture_compression_latc; boolean atdc = ctxCaps.GL_ATI_texture_compression_3dc; if (latc || atdc) { @@ -1601,6 +1610,18 @@ public class LwjglRenderer implements Renderer { } } + // Check sizes if graphics card doesn't support NPOT + if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){ + if (img.getWidth() != 0 && img.getHeight() != 0){ + if (!FastMath.isPowerOfTwo(img.getWidth()) + || !FastMath.isPowerOfTwo(img.getHeight()) + || img.getWidth() != img.getHeight()){ + logger.log(Level.WARNING, "Encountered NPOT texture {0}, " + + "it might not display correctly.", img); + } + } + } + if (target == GL_TEXTURE_CUBE_MAP) { List data = img.getData(); if (data.size() != 6) { diff --git a/engine/src/tools/jme3tools/converters/MipMapGenerator.java b/engine/src/tools/jme3tools/converters/MipMapGenerator.java index 7b656a9ee..0271c11bc 100644 --- a/engine/src/tools/jme3tools/converters/MipMapGenerator.java +++ b/engine/src/tools/jme3tools/converters/MipMapGenerator.java @@ -32,6 +32,7 @@ package jme3tools.converters; +import com.jme3.math.FastMath; import com.jme3.texture.Image; import com.jme3.texture.Image.Format; import com.jme3.texture.plugins.AWTLoader; @@ -58,6 +59,25 @@ public class MipMapGenerator { return targetImage; } + public static void resizeToPowerOf2(Image image){ + BufferedImage original = ImageToAwt.convert(image, false, true, 0); + int potWidth = FastMath.nearestPowerOfTwo(image.getWidth()); + int potHeight = FastMath.nearestPowerOfTwo(image.getHeight()); + int potSize = Math.max(potWidth, potHeight); + + BufferedImage scaled = scaleDown(original, potSize, potSize); + + AWTLoader loader = new AWTLoader(); + Image output = loader.load(scaled, false); + + image.setWidth(potSize); + image.setHeight(potSize); + image.setDepth(0); + image.setData(output.getData(0)); + image.setFormat(output.getFormat()); + image.setMipMapSizes(null); + } + public static void generateMipMaps(Image image){ BufferedImage original = ImageToAwt.convert(image, false, true, 0); int width = original.getWidth();