Przeglądaj źródła

Expand support for GL ES / WebGL compatible formats. (#2101)

* Add more WebGL / GLES supported formats

* Add compressonator ETC formats to DDS loader

* ETCFlipper description

---------

Co-authored-by: SceneMax3D <[email protected]>
Riccardo Balbo 1 rok temu
rodzic
commit
70f9da9907

+ 5 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java

@@ -45,6 +45,11 @@ public interface GLExt {
 
     public static final int GL_ALREADY_SIGNALED = 0x911A;
     public static final int GL_COMPRESSED_RGB8_ETC2 = 0x9274;
+    public static final int GL_COMPRESSED_SRGB8_ETC2 = 0x9275;
+    public static final int GL_COMPRESSED_RGBA8_ETC2_EAC = 0x9278;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279;
+    public static final int GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276;
+    public static final int GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277;
     public static final int GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
     public static final int GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
     public static final int GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;

+ 17 - 4
jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java

@@ -242,13 +242,17 @@ public final class GLImageFormats {
         // But for render buffers it's OK.
         format(formatToGL, Format.Depth16, GL.GL_DEPTH_COMPONENT16,  GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_SHORT);
         
-        // NOTE: OpenGL ES 2.0 does not support DEPTH_COMPONENT as internal format -- fallback to 16-bit depth.
-        if (caps.contains(Caps.OpenGLES20)) {
+        
+        if (caps.contains(Caps.WebGL)) {
+            // NOTE: fallback to 24-bit depth as workaround for firefox bug in WebGL 2 where DEPTH_COMPONENT16 is not handled properly
+            format(formatToGL, Format.Depth, GL2.GL_DEPTH_COMPONENT24, GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_INT);
+        } else if (caps.contains(Caps.OpenGLES20)) {
+            // NOTE: OpenGL ES 2.0 does not support DEPTH_COMPONENT as internal format -- fallback to 16-bit depth.
             format(formatToGL, Format.Depth, GL.GL_DEPTH_COMPONENT16, GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_SHORT);
         } else {
             format(formatToGL, Format.Depth, GL.GL_DEPTH_COMPONENT, GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_BYTE);
         }
-        if (caps.contains(Caps.OpenGL20) || caps.contains(Caps.Depth24)) {
+        if (caps.contains(Caps.OpenGLES30) || caps.contains(Caps.OpenGL20) || caps.contains(Caps.Depth24)) {
             format(formatToGL, Format.Depth24, GL2.GL_DEPTH_COMPONENT24,  GL.GL_DEPTH_COMPONENT, GL.GL_UNSIGNED_INT);
         }
         if (caps.contains(Caps.FloatDepthBuffer)) {
@@ -274,11 +278,20 @@ public final class GLImageFormats {
         }
         
         if (caps.contains(Caps.TextureCompressionETC2)) {
+            formatComp(formatToGL, Format.ETC2, GLExt.GL_COMPRESSED_RGBA8_ETC2_EAC, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
+            formatComp(formatToGL, Format.ETC2_ALPHA1, GLExt.GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
             formatComp(formatToGL, Format.ETC1, GLExt.GL_COMPRESSED_RGB8_ETC2, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+            if (caps.contains(Caps.Srgb)) {
+                formatCompSrgb(formatToGL, Format.ETC2, GLExt.GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
+                formatCompSrgb(formatToGL, Format.ETC2_ALPHA1, GLExt.GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE);
+                formatCompSrgb(formatToGL, Format.ETC1, GLExt.GL_COMPRESSED_SRGB8_ETC2, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+            }
         } else if (caps.contains(Caps.TextureCompressionETC1)) {
-            formatComp(formatToGL, Format.ETC1, GLExt.GL_ETC1_RGB8_OES,        GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
+            formatComp(formatToGL, Format.ETC1, GLExt.GL_ETC1_RGB8_OES, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
         }
         
+        
+        
         if(caps.contains(Caps.OpenGL42) || caps.contains(Caps.TextureCompressionBPTC)) {
             formatComp(formatToGL, Format.BC6H_SF16, GLExt.GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
             formatComp(formatToGL, Format.BC6H_UF16, GLExt.GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);

+ 17 - 0
jme3-core/src/main/java/com/jme3/texture/Image.java

@@ -330,6 +330,23 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ {
          * Requires {@link Caps#TextureCompressionETC1}.
          */
         ETC1(4, false, true, false),
+
+        /**
+         * Ericsson Texture Compression 2. Typically used on Android.
+         * Same as {@link #ETC1} but with alpha.
+         * 
+         * Requires {@link Caps#TextureCompressionETC2}.
+         */
+        ETC2(8, false, true, false),
+
+        /**
+         * Ericsson Texture Compression 2. Typically used on Android.
+         * Same as {@link #ETC2} but alpha can be either 1 or 0.
+         * 
+         * Requires {@link Caps#TextureCompressionETC2}.
+         */
+        ETC2_ALPHA1(4, false, true, false),
+
          
         /**
          * 8-bit signed int red.

+ 20 - 0
jme3-core/src/plugins/java/com/jme3/texture/plugins/DDSLoader.java

@@ -86,6 +86,10 @@ public class DDSLoader implements AssetLoader {
     private static final int PF_DX10 = 0x30315844; // a DX10 format
     private static final int PF_BC4S = 0x53344342; // a DX9 file format for BC4 signed
     private static final int PF_BC5S = 0x53354342; // a DX9 file format for BC5 signed
+    private static final int PF_ETC2_RGBA_CSN = 0x41435445; // ETC2 RGBA format notation from Compressonator
+    private static final int PF_ETC2_RGB_CSN = 0x32435445; // ETC2 RGB format notation from Compressonator
+    private static final int PF_ETC_RGB_CSN = 0x20435445; // ETC RGB format notation from Compressonator
+    private static final int PF_ETC2_RGBA1_CSN = 0x50435445; // ETC RGB + Alpha1 format notation from Compressonator
     private static final int DX10DIM_TEXTURE3D = 0x4;
     private static final int DX10MISC_TEXTURECUBE = 0x4;
     private static final double LOG2 = Math.log(2);
@@ -341,6 +345,22 @@ public class DDSLoader implements AssetLoader {
                     bpp = 8;
                     pixelFormat = Format.SIGNED_RGTC2;
                     break;
+                case PF_ETC_RGB_CSN:
+                    bpp = 4;
+                    pixelFormat = Format.ETC1;
+                    break;
+                case PF_ETC2_RGB_CSN:
+                    bpp = 4;
+                    pixelFormat = Format.ETC1;
+                    break;
+                case PF_ETC2_RGBA1_CSN:
+                    bpp = 4;
+                    pixelFormat = Format.ETC2_ALPHA1;
+                    break;
+                case PF_ETC2_RGBA_CSN:
+                    bpp = 8;
+                    pixelFormat = Format.ETC2;
+                    break;                                
                 default:
                     throw new IOException("Unknown fourcc: " + string(fourcc) + ", " + Integer.toHexString(fourcc));
             }

+ 7 - 1
jme3-core/src/plugins/java/com/jme3/texture/plugins/DXTFlipper.java

@@ -36,6 +36,7 @@ import com.jme3.texture.Image.Format;
 import com.jme3.util.BufferUtils;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.logging.Logger;
 
 /**
  * DXTFlipper is a utility class used to flip along Y axis DXT compressed textures.
@@ -43,6 +44,7 @@ import java.nio.ByteOrder;
  * @author Kirill Vainer
  */
 public class DXTFlipper {
+    private static final Logger logger = Logger.getLogger(DXTFlipper.class.getName());
 
     private static final ByteBuffer bb = ByteBuffer.allocate(8);
 
@@ -202,7 +204,11 @@ public class DXTFlipper {
         }
     }
 
-    public static ByteBuffer flipDXT(ByteBuffer img, int w, int h, Format format){
+    public static ByteBuffer flipDXT(ByteBuffer img, int w, int h, Format format) {
+        if (format == Format.ETC1 || format == Format.ETC2 || format == Format.ETC2_ALPHA1) {
+            logger.warning("This is not a DXT format, but ETC. Use flipETC instead.");
+            return ETCFlipper.flipETC(img, w, h, format);
+        }
         int originalLimit = img.limit();
         int blocksX = (int) FastMath.ceil(w / 4f);
         int blocksY = (int) FastMath.ceil(h / 4f);

+ 19 - 0
jme3-core/src/plugins/java/com/jme3/texture/plugins/ETCFlipper.java

@@ -0,0 +1,19 @@
+package com.jme3.texture.plugins;
+
+import java.nio.ByteBuffer;
+import java.util.logging.Logger;
+
+import com.jme3.texture.Image.Format;
+
+/**
+ * A place-holder for future implementation of ETC texture flipping.
+ * 
+*/
+public class ETCFlipper {
+    private static final Logger logger = Logger.getLogger(ETCFlipper.class.getName());
+    
+    public static ByteBuffer flipETC(ByteBuffer img, int w, int h, Format format) {
+        logger.warning("ETC texture flipping is not supported yet");
+        return img;
+    }
+}