* 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
3.0
sha..rd 14 years ago
parent b6386751e4
commit 90bf137894
  1. 5
      engine/src/core/com/jme3/renderer/Caps.java
  2. 36
      engine/src/desktop/com/jme3/system/JmeSystem.java
  3. 27
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java
  4. 21
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java
  5. 20
      engine/src/tools/jme3tools/converters/MipMapGenerator.java

@ -141,6 +141,11 @@ public enum Caps {
*/ */
TextureCompressionLATC, TextureCompressionLATC,
/**
* Supports Non-Power-Of-Two (NPOT) textures and framebuffers
*/
NonPowerOfTwoTextures,
/// Vertex Buffer features /// Vertex Buffer features
MeshInstancing, MeshInstancing,

@ -37,11 +37,14 @@ import com.jme3.app.SettingsDialog.SelectionListener;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.asset.DesktopAssetManager; import com.jme3.asset.DesktopAssetManager;
import com.jme3.audio.AudioRenderer; import com.jme3.audio.AudioRenderer;
import com.jme3.util.JmeFormatter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; 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.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -318,7 +321,6 @@ public class JmeSystem {
} }
AudioRenderer ar = clazz.newInstance(); AudioRenderer ar = clazz.newInstance();
// ar = new QueuedAudioRenderer(ar);
return ar; return ar;
}catch (InstantiationException ex){ }catch (InstantiationException ex){
logger.log(Level.SEVERE, "Failed to create context", ex); logger.log(Level.SEVERE, "Failed to create context", ex);
@ -336,28 +338,28 @@ public class JmeSystem {
return; return;
initialized = true; initialized = true;
// try { try {
// if (!lowPermissions){ if (!lowPermissions){
// // can only modify logging settings // can only modify logging settings
// // if permissions are available // if permissions are available
//
// JmeFormatter formatter = new JmeFormatter(); JmeFormatter formatter = new JmeFormatter();
// Handler fileHandler = new FileHandler("jme.log"); // Handler fileHandler = new FileHandler("jme.log");
// fileHandler.setFormatter(formatter); // fileHandler.setFormatter(formatter);
// Logger.getLogger("").addHandler(fileHandler); // Logger.getLogger("").addHandler(fileHandler);
//
// Handler consoleHandler = new ConsoleHandler(); Handler consoleHandler = new ConsoleHandler();
// consoleHandler.setFormatter(formatter); consoleHandler.setFormatter(formatter);
// Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]); Logger.getLogger("").removeHandler(Logger.getLogger("").getHandlers()[0]);
// Logger.getLogger("").addHandler(consoleHandler); Logger.getLogger("").addHandler(consoleHandler);
//
// Logger.getLogger("com.jme3").setLevel(Level.FINEST); // Logger.getLogger("com.jme3").setLevel(Level.FINEST);
// } }
// } catch (IOException ex){ // } catch (IOException ex){
// logger.log(Level.SEVERE, "I/O Error while creating log file", ex); // logger.log(Level.SEVERE, "I/O Error while creating log file", ex);
// } catch (SecurityException ex){ } catch (SecurityException ex){
// logger.log(Level.SEVERE, "Security error in creating log file", ex); logger.log(Level.SEVERE, "Security error in creating log file", ex);
// } }
logger.log(Level.INFO, "Running on {0}", getFullName()); logger.log(Level.INFO, "Running on {0}", getFullName());

@ -1,5 +1,6 @@
package com.jme3.renderer.lwjgl; package com.jme3.renderer.lwjgl;
import com.jme3.math.FastMath;
import com.jme3.renderer.GL1Renderer; import com.jme3.renderer.GL1Renderer;
import com.jme3.shader.Shader; import com.jme3.shader.Shader;
import com.jme3.shader.Shader.ShaderSource; import com.jme3.shader.Shader.ShaderSource;
@ -33,6 +34,7 @@ import java.nio.IntBuffer;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.logging.Logger; import java.util.logging.Logger;
import jme3tools.converters.MipMapGenerator; import jme3tools.converters.MipMapGenerator;
import org.lwjgl.opengl.GLContext;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
@ -47,6 +49,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
private final FloatBuffer fb16 = BufferUtils.createFloatBuffer(16); private final FloatBuffer fb16 = BufferUtils.createFloatBuffer(16);
private final RenderContext context = new RenderContext(); private final RenderContext context = new RenderContext();
private final GLObjectManager objManager = new GLObjectManager(); private final GLObjectManager objManager = new GLObjectManager();
private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
private int maxTexSize; private int maxTexSize;
private int maxCubeTexSize; private int maxCubeTexSize;
@ -80,13 +83,21 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
public EnumSet<Caps> getCaps() { public EnumSet<Caps> getCaps() {
return EnumSet.noneOf(Caps.class); return caps;
} }
public void initialize() { public void initialize() {
//glDisable(GL_DEPTH_TEST); //glDisable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 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() { public void resetGLObjects() {
@ -470,6 +481,20 @@ public class LwjglGL1Renderer implements GL1Renderer {
statistics.onTextureUse(img, true); 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) { if (!img.hasMipmaps() && mips) {
// No pregenerated mips available, // No pregenerated mips available,
// generate from base level if required // generate from base level if required

@ -34,6 +34,7 @@ package com.jme3.renderer.lwjgl;
import com.jme3.light.LightList; import com.jme3.light.LightList;
import com.jme3.material.RenderState; import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
@ -316,6 +317,14 @@ public class LwjglRenderer implements Renderer {
caps.add(Caps.VertexBufferArray); 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 latc = ctxCaps.GL_EXT_texture_compression_latc;
boolean atdc = ctxCaps.GL_ATI_texture_compression_3dc; boolean atdc = ctxCaps.GL_ATI_texture_compression_3dc;
if (latc || atdc) { 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) { if (target == GL_TEXTURE_CUBE_MAP) {
List<ByteBuffer> data = img.getData(); List<ByteBuffer> data = img.getData();
if (data.size() != 6) { if (data.size() != 6) {

@ -32,6 +32,7 @@
package jme3tools.converters; package jme3tools.converters;
import com.jme3.math.FastMath;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Image.Format; import com.jme3.texture.Image.Format;
import com.jme3.texture.plugins.AWTLoader; import com.jme3.texture.plugins.AWTLoader;
@ -58,6 +59,25 @@ public class MipMapGenerator {
return targetImage; 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){ public static void generateMipMaps(Image image){
BufferedImage original = ImageToAwt.convert(image, false, true, 0); BufferedImage original = ImageToAwt.convert(image, false, true, 0);
int width = original.getWidth(); int width = original.getWidth();

Loading…
Cancel
Save