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.
|
* 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
|
* Returns true if given the renderer capabilities, the texture
|
||||||
|
@ -44,6 +44,8 @@ import java.nio.IntBuffer;
|
|||||||
public interface GLExt {
|
public interface GLExt {
|
||||||
|
|
||||||
public static final int GL_ALREADY_SIGNALED = 0x911A;
|
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_RGB8_ETC2 = 0x9274;
|
||||||
public static final int GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
|
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_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);
|
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;
|
return formatToGL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,6 +349,10 @@ public final class GLRenderer implements Renderer {
|
|||||||
caps.add(Caps.TextureCompressionETC1);
|
caps.add(Caps.TextureCompressionETC1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasExtension("GL_ARB_texture_compression_rgtc")) {
|
||||||
|
caps.add(Caps.TextureCompressionRGTC);
|
||||||
|
}
|
||||||
|
|
||||||
// == end texture format extensions ==
|
// == end texture format extensions ==
|
||||||
|
|
||||||
if (hasExtension("GL_ARB_vertex_array_object") || caps.contains(Caps.OpenGL30)) {
|
if (hasExtension("GL_ARB_vertex_array_object") || caps.contains(Caps.OpenGL30)) {
|
||||||
|
@ -299,7 +299,21 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ {
|
|||||||
*
|
*
|
||||||
* Requires {@link Caps#TextureCompressionETC1}.
|
* 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 int bpp;
|
||||||
private boolean isDepth;
|
private boolean isDepth;
|
||||||
|
@ -85,6 +85,8 @@ public class DDSLoader implements AssetLoader {
|
|||||||
private static final int PF_DXT1 = 0x31545844;
|
private static final int PF_DXT1 = 0x31545844;
|
||||||
private static final int PF_DXT3 = 0x33545844;
|
private static final int PF_DXT3 = 0x33545844;
|
||||||
private static final int PF_DXT5 = 0x35545844;
|
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_ATI1 = 0x31495441;
|
||||||
private static final int PF_ATI2 = 0x32495441; // 0x41544932;
|
private static final int PF_ATI2 = 0x32495441; // 0x41544932;
|
||||||
private static final int PF_DX10 = 0x30315844; // a DX10 format
|
private static final int PF_DX10 = 0x30315844; // a DX10 format
|
||||||
@ -94,6 +96,9 @@ public class DDSLoader implements AssetLoader {
|
|||||||
DX10DIM_TEXTURE3D = 0x4;
|
DX10DIM_TEXTURE3D = 0x4;
|
||||||
private static final int DX10MISC_GENERATE_MIPS = 0x1,
|
private static final int DX10MISC_GENERATE_MIPS = 0x1,
|
||||||
DX10MISC_TEXTURECUBE = 0x4;
|
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 static final double LOG2 = Math.log(2);
|
||||||
private int width;
|
private int width;
|
||||||
private int height;
|
private int height;
|
||||||
@ -105,9 +110,11 @@ public class DDSLoader implements AssetLoader {
|
|||||||
private int caps2;
|
private int caps2;
|
||||||
private boolean directx10;
|
private boolean directx10;
|
||||||
private boolean compressed;
|
private boolean compressed;
|
||||||
|
private boolean dxtOrRgtc;
|
||||||
private boolean texture3D;
|
private boolean texture3D;
|
||||||
private boolean grayscaleOrAlpha;
|
private boolean grayscaleOrAlpha;
|
||||||
private boolean normal;
|
private boolean normal;
|
||||||
|
private ColorSpace colorSpace;
|
||||||
private Format pixelFormat;
|
private Format pixelFormat;
|
||||||
private int bpp;
|
private int bpp;
|
||||||
private int[] sizes;
|
private int[] sizes;
|
||||||
@ -133,7 +140,8 @@ public class DDSLoader implements AssetLoader {
|
|||||||
((TextureKey) info.getKey()).setTextureTypeHint(Texture.Type.CubeMap);
|
((TextureKey) info.getKey()).setTextureTypeHint(Texture.Type.CubeMap);
|
||||||
}
|
}
|
||||||
ArrayList<ByteBuffer> data = readData(((TextureKey) info.getKey()).isFlipY());
|
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 {
|
} finally {
|
||||||
if (stream != null){
|
if (stream != null){
|
||||||
stream.close();
|
stream.close();
|
||||||
@ -145,18 +153,24 @@ public class DDSLoader implements AssetLoader {
|
|||||||
in = new LittleEndien(stream);
|
in = new LittleEndien(stream);
|
||||||
loadHeader();
|
loadHeader();
|
||||||
ArrayList<ByteBuffer> data = readData(false);
|
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 {
|
private void loadDX10Header() throws IOException {
|
||||||
int dxgiFormat = in.readInt();
|
int dxgiFormat = in.readInt();
|
||||||
|
|
||||||
if (dxgiFormat == 0) {
|
if (dxgiFormat == 0) {
|
||||||
pixelFormat = Format.ETC1;
|
pixelFormat = Format.ETC1;
|
||||||
bpp = 4;
|
compressed = true;
|
||||||
|
bpp = 4;
|
||||||
} else {
|
} else {
|
||||||
|
pixelFormat = DXGIFormat.getJmeFormat(dxgiFormat);
|
||||||
|
if (pixelFormat == null) {
|
||||||
throw new IOException("Unsupported DX10 format: " + dxgiFormat);
|
throw new IOException("Unsupported DX10 format: " + dxgiFormat);
|
||||||
|
}
|
||||||
|
bpp = pixelFormat.getBitsPerPixel();
|
||||||
|
compressed = pixelFormat.isCompressed();
|
||||||
}
|
}
|
||||||
compressed = true;
|
|
||||||
|
|
||||||
int resDim = in.readInt();
|
int resDim = in.readInt();
|
||||||
if (resDim == DX10DIM_TEXTURE3D) {
|
if (resDim == DX10DIM_TEXTURE3D) {
|
||||||
@ -201,6 +215,7 @@ public class DDSLoader implements AssetLoader {
|
|||||||
caps2 = in.readInt();
|
caps2 = in.readInt();
|
||||||
in.skipBytes(12);
|
in.skipBytes(12);
|
||||||
texture3D = false;
|
texture3D = false;
|
||||||
|
colorSpace = ColorSpace.sRGB;
|
||||||
|
|
||||||
if (!directx10) {
|
if (!directx10) {
|
||||||
if (!is(caps1, DDSCAPS_TEXTURE)) {
|
if (!is(caps1, DDSCAPS_TEXTURE)) {
|
||||||
@ -268,10 +283,12 @@ public class DDSLoader implements AssetLoader {
|
|||||||
} else {
|
} else {
|
||||||
pixelFormat = Image.Format.DXT1;
|
pixelFormat = Image.Format.DXT1;
|
||||||
}
|
}
|
||||||
|
dxtOrRgtc = true;
|
||||||
break;
|
break;
|
||||||
case PF_DXT3:
|
case PF_DXT3:
|
||||||
bpp = 8;
|
bpp = 8;
|
||||||
pixelFormat = Image.Format.DXT3;
|
pixelFormat = Image.Format.DXT3;
|
||||||
|
dxtOrRgtc = true;
|
||||||
break;
|
break;
|
||||||
case PF_DXT5:
|
case PF_DXT5:
|
||||||
bpp = 8;
|
bpp = 8;
|
||||||
@ -279,17 +296,24 @@ public class DDSLoader implements AssetLoader {
|
|||||||
if (swizzle == SWIZZLE_xGxR) {
|
if (swizzle == SWIZZLE_xGxR) {
|
||||||
normal = true;
|
normal = true;
|
||||||
}
|
}
|
||||||
|
dxtOrRgtc = true;
|
||||||
break;
|
break;
|
||||||
/*
|
|
||||||
case PF_ATI1:
|
case PF_ATI1:
|
||||||
bpp = 4;
|
bpp = 4;
|
||||||
pixelFormat = Image.Format.LTC;
|
pixelFormat = Image.Format.RTC;
|
||||||
|
dxtOrRgtc = true;
|
||||||
break;
|
break;
|
||||||
case PF_ATI2:
|
case PF_ATI2:
|
||||||
bpp = 8;
|
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;
|
break;
|
||||||
*/
|
|
||||||
case PF_DX10:
|
case PF_DX10:
|
||||||
compressed = false;
|
compressed = false;
|
||||||
directx10 = true;
|
directx10 = true;
|
||||||
@ -530,6 +554,30 @@ public class DDSLoader implements AssetLoader {
|
|||||||
return dataBuffer;
|
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
|
* Reads a DXT compressed image from the InputStream
|
||||||
*
|
*
|
||||||
@ -738,8 +786,10 @@ public class DDSLoader implements AssetLoader {
|
|||||||
ArrayList<ByteBuffer> allMaps = new ArrayList<ByteBuffer>();
|
ArrayList<ByteBuffer> allMaps = new ArrayList<ByteBuffer>();
|
||||||
if (depth > 1 && !texture3D) {
|
if (depth > 1 && !texture3D) {
|
||||||
for (int i = 0; i < depth; i++) {
|
for (int i = 0; i < depth; i++) {
|
||||||
if (compressed) {
|
if (compressed && dxtOrRgtc) {
|
||||||
allMaps.add(readDXT2D(flip, totalSize));
|
allMaps.add(readDXT2D(flip, totalSize));
|
||||||
|
} else if (compressed) {
|
||||||
|
allMaps.add(readCompressed2Dor3D(flip, totalSize));
|
||||||
} else if (grayscaleOrAlpha) {
|
} else if (grayscaleOrAlpha) {
|
||||||
allMaps.add(readGrayscale2D(flip, totalSize));
|
allMaps.add(readGrayscale2D(flip, totalSize));
|
||||||
} else {
|
} else {
|
||||||
@ -747,8 +797,10 @@ public class DDSLoader implements AssetLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (texture3D) {
|
} else if (texture3D) {
|
||||||
if (compressed) {
|
if (compressed && dxtOrRgtc) {
|
||||||
allMaps.add(readDXT3D(flip, totalSize));
|
allMaps.add(readDXT3D(flip, totalSize));
|
||||||
|
} else if (compressed) {
|
||||||
|
allMaps.add(readCompressed2Dor3D(flip, totalSize));
|
||||||
} else if (grayscaleOrAlpha) {
|
} else if (grayscaleOrAlpha) {
|
||||||
allMaps.add(readGrayscale3D(flip, totalSize));
|
allMaps.add(readGrayscale3D(flip, totalSize));
|
||||||
} else {
|
} else {
|
||||||
@ -756,8 +808,10 @@ public class DDSLoader implements AssetLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (compressed) {
|
if (compressed && dxtOrRgtc) {
|
||||||
allMaps.add(readDXT2D(flip, totalSize));
|
allMaps.add(readDXT2D(flip, totalSize));
|
||||||
|
} else if (compressed) {
|
||||||
|
allMaps.add(readCompressed2Dor3D(flip, totalSize));
|
||||||
} else if (grayscaleOrAlpha) {
|
} else if (grayscaleOrAlpha) {
|
||||||
allMaps.add(readGrayscale2D(flip, totalSize));
|
allMaps.add(readGrayscale2D(flip, totalSize));
|
||||||
} else {
|
} else {
|
||||||
@ -822,7 +876,7 @@ public class DDSLoader implements AssetLoader {
|
|||||||
buf.append((char) (value & 0xFF));
|
buf.append((char) (value & 0xFF));
|
||||||
buf.append((char) ((value & 0xFF00) >> 8));
|
buf.append((char) ((value & 0xFF00) >> 8));
|
||||||
buf.append((char) ((value & 0xFF0000) >> 16));
|
buf.append((char) ((value & 0xFF0000) >> 16));
|
||||||
buf.append((char) ((value & 0xFF00000) >> 24));
|
buf.append((char) ((value & 0xFF000000) >> 24));
|
||||||
|
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
@ -213,20 +213,18 @@ public class DXTFlipper {
|
|||||||
case DXT5:
|
case DXT5:
|
||||||
type = 3;
|
type = 3;
|
||||||
break;
|
break;
|
||||||
/*
|
case RGTC:
|
||||||
case LATC:
|
|
||||||
type = 4;
|
type = 4;
|
||||||
break;
|
break;
|
||||||
case LTC:
|
case RTC:
|
||||||
type = 5;
|
type = 5;
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// DXT1 uses 8 bytes per block,
|
// 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;
|
int bpb = type == 1 || type == 5 ? 8 : 16;
|
||||||
|
|
||||||
ByteBuffer retImg = BufferUtils.createByteBuffer(blocksX * blocksY * bpb);
|
ByteBuffer retImg = BufferUtils.createByteBuffer(blocksX * blocksY * bpb);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user