Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions jme3-core/src/main/java/com/jme3/renderer/opengl/GLExt.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,17 @@ public static GLImageFormat[][] getFormatsForCaps(EnumSet<Caps> caps) {
// 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)) {
Expand All @@ -274,11 +278,20 @@ public static GLImageFormat[][] getFormatsForCaps(EnumSet<Caps> caps) {
}

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);
Expand Down
17 changes: 17 additions & 0 deletions jme3-core/src/main/java/com/jme3/texture/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,23 @@ public enum Format {
* 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.
Expand Down
20 changes: 20 additions & 0 deletions jme3-core/src/plugins/java/com/jme3/texture/plugins/DDSLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -341,6 +345,22 @@ private void readPixelFormat() throws IOException {
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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@
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.
*
* @author Kirill Vainer
*/
public class DXTFlipper {
private static final Logger logger = Logger.getLogger(DXTFlipper.class.getName());

private static final ByteBuffer bb = ByteBuffer.allocate(8);

Expand Down Expand Up @@ -202,7 +204,11 @@ private static void flipDXT1orDXTA3Block(byte[] block, int h){
}
}

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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why call ETCFlipper.flipETC(img, w, h, format); if it doesn't do anything? why not just return img?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ETC flipping is not supported: i couldn't figure out how to flip etc compressed textures without decompressing them first, even though it is probably possible (similar to dxt flipping). I don't this this is very important, since compressed textures are usually considered in their final form and they can be flipped during compression if needed, also we didn't even had dxt flipping for a long time. I plan to open an issue for this and hopefully someone that is knowledgeable about etc formats can contribute with the missing code one day.

Basically i don't know how to implement compressed etc flipping, so i wrote all the supporting code in the hope that someone can go into ETCFlipper some day and write the missing piece without the need to understand and modify the dds loader code that has some jme specific logic inside.
We could open a bounty for it.

}
int originalLimit = img.limit();
int blocksX = (int) FastMath.ceil(w / 4f);
int blocksY = (int) FastMath.ceil(h / 4f);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.jme3.texture.plugins;

import java.nio.ByteBuffer;
import java.util.logging.Logger;

import com.jme3.texture.Image.Format;

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;
}
}