Image: support for RGTC format
This commit is contained in:
parent
f9ce9e246c
commit
6db1d15045
@ -349,7 +349,12 @@ public enum Caps {
|
||||
/**
|
||||
* GPU can provide and accept binary shaders.
|
||||
*/
|
||||
BinaryShader;
|
||||
BinaryShader,
|
||||
|
||||
/**
|
||||
* Supports {@link Format#RGTC} and {@link Format#RTC} texture compression.
|
||||
*/
|
||||
TextureCompressionRGTC;
|
||||
|
||||
/**
|
||||
* Returns true if given the renderer capabilities, the texture
|
||||
|
@ -44,6 +44,8 @@ import java.nio.IntBuffer;
|
||||
public interface GLExt {
|
||||
|
||||
public static final int GL_ALREADY_SIGNALED = 0x911A;
|
||||
public static final int GL_COMPRESSED_RED_RGTC1 = 0x8DBB;
|
||||
public static final int GL_COMPRESSED_RG_RGTC2 = 0x8DBD;
|
||||
public static final int GL_COMPRESSED_RGB8_ETC2 = 0x9274;
|
||||
public static final int GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
|
||||
public static final int GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
|
||||
|
@ -233,6 +233,11 @@ public final class GLImageFormats {
|
||||
formatComp(formatToGL, Format.ETC1, GLExt.GL_ETC1_RGB8_OES, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
|
||||
}
|
||||
|
||||
if (caps.contains(Caps.TextureCompressionRGTC)) {
|
||||
formatComp(formatToGL, Format.RGTC, GLExt.GL_COMPRESSED_RG_RGTC2, GL.GL_RGB, GL.GL_UNSIGNED_BYTE);
|
||||
formatComp(formatToGL, Format.RTC, GLExt.GL_COMPRESSED_RED_RGTC1, GL.GL_RED, GL.GL_UNSIGNED_BYTE);
|
||||
}
|
||||
|
||||
return formatToGL;
|
||||
}
|
||||
}
|
||||
|
@ -348,6 +348,10 @@ public final class GLRenderer implements Renderer {
|
||||
} else if (hasExtension("GL_OES_compressed_ETC1_RGB8_texture")) {
|
||||
caps.add(Caps.TextureCompressionETC1);
|
||||
}
|
||||
|
||||
if (hasExtension("GL_ARB_texture_compression_rgtc")) {
|
||||
caps.add(Caps.TextureCompressionRGTC);
|
||||
}
|
||||
|
||||
// == end texture format extensions ==
|
||||
|
||||
|
@ -299,7 +299,21 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ {
|
||||
*
|
||||
* Requires {@link Caps#TextureCompressionETC1}.
|
||||
*/
|
||||
ETC1(4, false, true, false);
|
||||
ETC1(4, false, true, false),
|
||||
|
||||
/**
|
||||
* RGTC with red channel only.
|
||||
*
|
||||
* Requires {@link Caps#TextureCompressionRGTC}.
|
||||
*/
|
||||
RTC(4, false, true, false),
|
||||
|
||||
/**
|
||||
* RGTC with red and green channels.
|
||||
*
|
||||
* Requires {@link Caps#TextureCompressionRGTC}.
|
||||
*/
|
||||
RGTC(8, false, true, false);
|
||||
|
||||
private int bpp;
|
||||
private boolean isDepth;
|
||||
|
@ -85,6 +85,8 @@ public class DDSLoader implements AssetLoader {
|
||||
private static final int PF_DXT1 = 0x31545844;
|
||||
private static final int PF_DXT3 = 0x33545844;
|
||||
private static final int PF_DXT5 = 0x35545844;
|
||||
private static final int PF_ETC1 = 0x31435445;
|
||||
private static final int PF_ETC_ = 0x20435445; // the underscore represents a space
|
||||
private static final int PF_ATI1 = 0x31495441;
|
||||
private static final int PF_ATI2 = 0x32495441; // 0x41544932;
|
||||
private static final int PF_DX10 = 0x30315844; // a DX10 format
|
||||
@ -94,6 +96,9 @@ public class DDSLoader implements AssetLoader {
|
||||
DX10DIM_TEXTURE3D = 0x4;
|
||||
private static final int DX10MISC_GENERATE_MIPS = 0x1,
|
||||
DX10MISC_TEXTURECUBE = 0x4;
|
||||
private static final int DXGI_FORMAT_BC4_TYPELESS = 79;
|
||||
private static final int DXGI_FORMAT_BC4_UNORM = 80;
|
||||
private static final int DXGI_FORMAT_BC4_SNORM = 81;
|
||||
private static final double LOG2 = Math.log(2);
|
||||
private int width;
|
||||
private int height;
|
||||
@ -105,9 +110,11 @@ public class DDSLoader implements AssetLoader {
|
||||
private int caps2;
|
||||
private boolean directx10;
|
||||
private boolean compressed;
|
||||
private boolean dxtOrRgtc;
|
||||
private boolean texture3D;
|
||||
private boolean grayscaleOrAlpha;
|
||||
private boolean normal;
|
||||
private ColorSpace colorSpace;
|
||||
private Format pixelFormat;
|
||||
private int bpp;
|
||||
private int[] sizes;
|
||||
@ -133,7 +140,8 @@ public class DDSLoader implements AssetLoader {
|
||||
((TextureKey) info.getKey()).setTextureTypeHint(Texture.Type.CubeMap);
|
||||
}
|
||||
ArrayList<ByteBuffer> data = readData(((TextureKey) info.getKey()).isFlipY());
|
||||
return new Image(pixelFormat, width, height, depth, data, sizes, ColorSpace.sRGB);
|
||||
|
||||
return new Image(pixelFormat, width, height, depth, data, sizes, colorSpace);
|
||||
} finally {
|
||||
if (stream != null){
|
||||
stream.close();
|
||||
@ -145,18 +153,24 @@ public class DDSLoader implements AssetLoader {
|
||||
in = new LittleEndien(stream);
|
||||
loadHeader();
|
||||
ArrayList<ByteBuffer> data = readData(false);
|
||||
return new Image(pixelFormat, width, height, depth, data, sizes, ColorSpace.sRGB);
|
||||
return new Image(pixelFormat, width, height, depth, data, sizes, colorSpace);
|
||||
}
|
||||
|
||||
private void loadDX10Header() throws IOException {
|
||||
int dxgiFormat = in.readInt();
|
||||
|
||||
if (dxgiFormat == 0) {
|
||||
pixelFormat = Format.ETC1;
|
||||
bpp = 4;
|
||||
pixelFormat = Format.ETC1;
|
||||
compressed = true;
|
||||
bpp = 4;
|
||||
} else {
|
||||
pixelFormat = DXGIFormat.getJmeFormat(dxgiFormat);
|
||||
if (pixelFormat == null) {
|
||||
throw new IOException("Unsupported DX10 format: " + dxgiFormat);
|
||||
}
|
||||
bpp = pixelFormat.getBitsPerPixel();
|
||||
compressed = pixelFormat.isCompressed();
|
||||
}
|
||||
compressed = true;
|
||||
|
||||
int resDim = in.readInt();
|
||||
if (resDim == DX10DIM_TEXTURE3D) {
|
||||
@ -201,6 +215,7 @@ public class DDSLoader implements AssetLoader {
|
||||
caps2 = in.readInt();
|
||||
in.skipBytes(12);
|
||||
texture3D = false;
|
||||
colorSpace = ColorSpace.sRGB;
|
||||
|
||||
if (!directx10) {
|
||||
if (!is(caps1, DDSCAPS_TEXTURE)) {
|
||||
@ -268,10 +283,12 @@ public class DDSLoader implements AssetLoader {
|
||||
} else {
|
||||
pixelFormat = Image.Format.DXT1;
|
||||
}
|
||||
dxtOrRgtc = true;
|
||||
break;
|
||||
case PF_DXT3:
|
||||
bpp = 8;
|
||||
pixelFormat = Image.Format.DXT3;
|
||||
dxtOrRgtc = true;
|
||||
break;
|
||||
case PF_DXT5:
|
||||
bpp = 8;
|
||||
@ -279,17 +296,24 @@ public class DDSLoader implements AssetLoader {
|
||||
if (swizzle == SWIZZLE_xGxR) {
|
||||
normal = true;
|
||||
}
|
||||
dxtOrRgtc = true;
|
||||
break;
|
||||
/*
|
||||
case PF_ATI1:
|
||||
bpp = 4;
|
||||
pixelFormat = Image.Format.LTC;
|
||||
pixelFormat = Image.Format.RTC;
|
||||
dxtOrRgtc = true;
|
||||
break;
|
||||
case PF_ATI2:
|
||||
bpp = 8;
|
||||
pixelFormat = Image.Format.LATC;
|
||||
pixelFormat = Image.Format.RGTC;
|
||||
dxtOrRgtc = true;
|
||||
break;
|
||||
case PF_ETC1:
|
||||
case PF_ETC_:
|
||||
bpp = 4;
|
||||
pixelFormat = Image.Format.ETC1;
|
||||
dxtOrRgtc = false;
|
||||
break;
|
||||
*/
|
||||
case PF_DX10:
|
||||
compressed = false;
|
||||
directx10 = true;
|
||||
@ -530,6 +554,30 @@ public class DDSLoader implements AssetLoader {
|
||||
return dataBuffer;
|
||||
}
|
||||
|
||||
public ByteBuffer readCompressed2Dor3D(boolean flip, int totalSize) throws IOException {
|
||||
logger.log(Level.FINEST, "Source image format: {0}", pixelFormat);
|
||||
|
||||
ByteBuffer buffer = BufferUtils.createByteBuffer(totalSize * depth);
|
||||
|
||||
// TODO: add support for flipping ETC1
|
||||
|
||||
for (int i = 0; i < depth; i++) {
|
||||
int mipWidth = width;
|
||||
int mipHeight = height;
|
||||
for (int mip = 0; mip < mipMapCount; mip++) {
|
||||
byte[] data = new byte[sizes[mip]];
|
||||
in.readFully(data);
|
||||
buffer.put(data);
|
||||
|
||||
mipWidth = Math.max(mipWidth / 2, 1);
|
||||
mipHeight = Math.max(mipHeight / 2, 1);
|
||||
}
|
||||
}
|
||||
buffer.rewind();
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a DXT compressed image from the InputStream
|
||||
*
|
||||
@ -738,8 +786,10 @@ public class DDSLoader implements AssetLoader {
|
||||
ArrayList<ByteBuffer> allMaps = new ArrayList<ByteBuffer>();
|
||||
if (depth > 1 && !texture3D) {
|
||||
for (int i = 0; i < depth; i++) {
|
||||
if (compressed) {
|
||||
if (compressed && dxtOrRgtc) {
|
||||
allMaps.add(readDXT2D(flip, totalSize));
|
||||
} else if (compressed) {
|
||||
allMaps.add(readCompressed2Dor3D(flip, totalSize));
|
||||
} else if (grayscaleOrAlpha) {
|
||||
allMaps.add(readGrayscale2D(flip, totalSize));
|
||||
} else {
|
||||
@ -747,8 +797,10 @@ public class DDSLoader implements AssetLoader {
|
||||
}
|
||||
}
|
||||
} else if (texture3D) {
|
||||
if (compressed) {
|
||||
if (compressed && dxtOrRgtc) {
|
||||
allMaps.add(readDXT3D(flip, totalSize));
|
||||
} else if (compressed) {
|
||||
allMaps.add(readCompressed2Dor3D(flip, totalSize));
|
||||
} else if (grayscaleOrAlpha) {
|
||||
allMaps.add(readGrayscale3D(flip, totalSize));
|
||||
} else {
|
||||
@ -756,8 +808,10 @@ public class DDSLoader implements AssetLoader {
|
||||
}
|
||||
|
||||
} else {
|
||||
if (compressed) {
|
||||
if (compressed && dxtOrRgtc) {
|
||||
allMaps.add(readDXT2D(flip, totalSize));
|
||||
} else if (compressed) {
|
||||
allMaps.add(readCompressed2Dor3D(flip, totalSize));
|
||||
} else if (grayscaleOrAlpha) {
|
||||
allMaps.add(readGrayscale2D(flip, totalSize));
|
||||
} else {
|
||||
@ -822,7 +876,7 @@ public class DDSLoader implements AssetLoader {
|
||||
buf.append((char) (value & 0xFF));
|
||||
buf.append((char) ((value & 0xFF00) >> 8));
|
||||
buf.append((char) ((value & 0xFF0000) >> 16));
|
||||
buf.append((char) ((value & 0xFF00000) >> 24));
|
||||
buf.append((char) ((value & 0xFF000000) >> 24));
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
@ -213,20 +213,18 @@ public class DXTFlipper {
|
||||
case DXT5:
|
||||
type = 3;
|
||||
break;
|
||||
/*
|
||||
case LATC:
|
||||
case RGTC:
|
||||
type = 4;
|
||||
break;
|
||||
case LTC:
|
||||
case RTC:
|
||||
type = 5;
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// DXT1 uses 8 bytes per block,
|
||||
// DXT3, DXT5, LATC use 16 bytes per block
|
||||
// DXT3, DXT5, RGTC use 16 bytes per block
|
||||
int bpb = type == 1 || type == 5 ? 8 : 16;
|
||||
|
||||
ByteBuffer retImg = BufferUtils.createByteBuffer(blocksX * blocksY * bpb);
|
||||
|
Loading…
x
Reference in New Issue
Block a user