|
|
|
@ -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) { |
|
|
|
|