|
@@ -9,6 +9,8 @@ import jme3tools.converters.RGB565;
|
|
|
|
|
|
import com.jme3.scene.plugins.blender.BlenderContext;
|
|
|
import com.jme3.scene.plugins.blender.textures.TexturePixel;
|
|
|
+import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
|
|
|
+import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
|
|
|
import com.jme3.texture.Image;
|
|
|
import com.jme3.texture.Image.Format;
|
|
|
import com.jme3.util.BufferUtils;
|
|
@@ -29,7 +31,6 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
|
|
|
super(flag, negateTexture, blendType, materialColor, color, blendFactor);
|
|
|
}
|
|
|
|
|
|
- //TODO: implement using base texture
|
|
|
@Override
|
|
|
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
|
|
|
Format format = image.getFormat();
|
|
@@ -43,28 +44,56 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
|
|
|
depth = 1;
|
|
|
}
|
|
|
ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
|
|
|
-
|
|
|
+
|
|
|
+ PixelInputOutput basePixelIO = null;
|
|
|
+ float[][] compressedMaterialColor = null;
|
|
|
+ TexturePixel[] baseTextureColors = null;
|
|
|
+ if(baseImage != null) {
|
|
|
+ basePixelIO = PixelIOFactory.getPixelIO(baseImage.getFormat());
|
|
|
+ compressedMaterialColor = new float[2][4];
|
|
|
+ baseTextureColors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
|
|
|
+ }
|
|
|
+
|
|
|
float[] resultPixel = new float[4];
|
|
|
float[] pixelColor = new float[4];
|
|
|
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
|
|
|
- int dataIndex = 0;
|
|
|
+ int dataIndex = 0, baseXTexelIndex = 0, baseYTexelIndex = 0;
|
|
|
+ float[] alphas = new float[] {1, 1};
|
|
|
while (data.hasRemaining()) {
|
|
|
- switch (format) {
|
|
|
- case DXT3:
|
|
|
- case DXT5:
|
|
|
- newData.putLong(dataIndex, data.getLong());// just copy the 8 bytes of alphas
|
|
|
- dataIndex += 8;
|
|
|
- case DXT1:
|
|
|
- int col0 = RGB565.RGB565_to_ARGB8(data.getShort());
|
|
|
- int col1 = RGB565.RGB565_to_ARGB8(data.getShort());
|
|
|
- colors[0].fromARGB8(col0);
|
|
|
- colors[1].fromARGB8(col1);
|
|
|
- break;
|
|
|
- case DXT1A:
|
|
|
- LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", format);
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new IllegalStateException("Invalid image format type for DDS texture blender: " + format);
|
|
|
+ if(format == Format.DXT1A) {
|
|
|
+ LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", format);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(format == Format.DXT3) {
|
|
|
+ long alpha = data.getLong();
|
|
|
+ //get alpha for first and last pixel that is compressed in the texel
|
|
|
+ byte alpha0 = (byte)(alpha << 4 & 0xFF);
|
|
|
+ byte alpha1 = (byte)(alpha >> 60 & 0xFF);
|
|
|
+ alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
|
|
|
+ alphas[1] = alpha1 >= 0 ? alpha1 / 255.0f : 1.0f - ~alpha1 / 255.0f;
|
|
|
+ dataIndex += 8;
|
|
|
+ } else if(format == Format.DXT5) {
|
|
|
+ byte alpha0 = data.get();
|
|
|
+ byte alpha1 = data.get();
|
|
|
+ alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
|
|
|
+ alphas[1] = alpha1 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
|
|
|
+ //only read the next 6 bytes (these are alpha indexes)
|
|
|
+ data.getInt();
|
|
|
+ data.getShort();
|
|
|
+ dataIndex += 8;
|
|
|
+ }
|
|
|
+ int col0 = RGB565.RGB565_to_ARGB8(data.getShort());
|
|
|
+ int col1 = RGB565.RGB565_to_ARGB8(data.getShort());
|
|
|
+ colors[0].fromARGB8(col0);
|
|
|
+ colors[1].fromARGB8(col1);
|
|
|
+
|
|
|
+ //compressing 16 pixels from the base texture as if they belonged to a texel
|
|
|
+ if(baseImage != null) {
|
|
|
+ //reading pixels (first and last of the 16 colors array)
|
|
|
+ basePixelIO.read(baseImage, baseTextureColors[0], baseXTexelIndex << 2, baseYTexelIndex << 2);//first pixel
|
|
|
+ basePixelIO.read(baseImage, baseTextureColors[1], baseXTexelIndex << 2 + 4, baseYTexelIndex << 2 + 4);//last pixel
|
|
|
+ baseTextureColors[0].toRGBA(compressedMaterialColor[0]);
|
|
|
+ baseTextureColors[1].toRGBA(compressedMaterialColor[1]);
|
|
|
}
|
|
|
|
|
|
// blending colors
|
|
@@ -73,7 +102,8 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
|
|
|
colors[i].negate();
|
|
|
}
|
|
|
colors[i].toRGBA(pixelColor);
|
|
|
- this.blendPixel(resultPixel, materialColor, pixelColor, blenderContext);
|
|
|
+ pixelColor[3] = alphas[i];
|
|
|
+ this.blendPixel(resultPixel, compressedMaterialColor != null ? compressedMaterialColor[i] : materialColor, pixelColor, blenderContext);
|
|
|
colors[i].fromARGB8(1, resultPixel[0], resultPixel[1], resultPixel[2]);
|
|
|
int argb8 = colors[i].toARGB8();
|
|
|
short rgb565 = RGB565.ARGB8_to_RGB565(argb8);
|
|
@@ -84,6 +114,12 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
|
|
|
// just copy the remaining 4 bytes of the current texel
|
|
|
newData.putInt(dataIndex, data.getInt());
|
|
|
dataIndex += 4;
|
|
|
+
|
|
|
+ ++baseXTexelIndex;
|
|
|
+ if(baseXTexelIndex > image.getWidth() >> 2) {
|
|
|
+ baseXTexelIndex = 0;
|
|
|
+ ++baseYTexelIndex;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if(depth > 1) {
|