Added support for multilayered images.
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9336 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
96cfd22510
commit
b09e37c9d9
@ -236,26 +236,74 @@ public class TextureHelper extends AbstractBlenderHelper {
|
||||
* @return the decompressed image
|
||||
*/
|
||||
public Image decompress(Image image) {
|
||||
byte[] bytes = null;
|
||||
TexturePixel[] colors = null;
|
||||
ByteBuffer data = image.getData(0);// TODO: support decompression of all data 'layers'
|
||||
data.rewind();
|
||||
Format format = image.getFormat();
|
||||
int depth = image.getDepth();
|
||||
if(depth == 0) {
|
||||
depth = 1;
|
||||
}
|
||||
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
|
||||
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
|
||||
|
||||
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
|
||||
ByteBuffer data = image.getData(dataLayerIndex);
|
||||
data.rewind();
|
||||
|
||||
byte[] bytes = new byte[image.getWidth() * image.getHeight() << 2];
|
||||
DDSTexelData texelData = new DDSTexelData(data.remaining() * 8/format.getBitsPerPixel()/16/*data.remaining() / (format.getBitsPerPixel() << 1)*/,
|
||||
image.getWidth(), image.getHeight(), format != Format.DXT1);
|
||||
switch (format) {
|
||||
case DXT1:// BC1
|
||||
case DXT1A:
|
||||
while (data.hasRemaining()) {
|
||||
short c0 = data.getShort();
|
||||
short c1 = data.getShort();
|
||||
int col0 = RGB565.RGB565_to_ARGB8(c0);
|
||||
int col1 = RGB565.RGB565_to_ARGB8(c1);
|
||||
colors[0].fromARGB8(col0);
|
||||
colors[1].fromARGB8(col1);
|
||||
|
||||
DDSTexelData texelData = new DDSTexelData(data.remaining() / (format.getBitsPerPixel() * 2), image.getWidth(), image.getHeight(), format != Format.DXT1);
|
||||
switch (format) {// TODO: DXT1A
|
||||
case DXT1:// BC1
|
||||
bytes = new byte[image.getWidth() * image.getHeight() * 4];
|
||||
colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
|
||||
while (data.hasRemaining()) {
|
||||
short c0 = data.getShort();
|
||||
short c1 = data.getShort();
|
||||
int col0 = RGB565.RGB565_to_ARGB8(c0);
|
||||
int col1 = RGB565.RGB565_to_ARGB8(c1);
|
||||
colors[0].fromARGB8(col0);
|
||||
colors[1].fromARGB8(col1);
|
||||
if (col0 > col1) {
|
||||
// creating color2 = 2/3color0 + 1/3color1
|
||||
colors[2].fromPixel(colors[0]);
|
||||
colors[2].mult(2);
|
||||
colors[2].add(colors[1]);
|
||||
colors[2].divide(3);
|
||||
|
||||
// creating color3 = 1/3color0 + 2/3color1;
|
||||
colors[3].fromPixel(colors[1]);
|
||||
colors[3].mult(2);
|
||||
colors[3].add(colors[0]);
|
||||
colors[3].divide(3);
|
||||
} else {
|
||||
// creating color2 = 1/2color0 + 1/2color1
|
||||
colors[2].fromPixel(colors[0]);
|
||||
colors[2].add(colors[1]);
|
||||
colors[2].mult(0.5f);
|
||||
|
||||
colors[3].fromARGB8(0);
|
||||
}
|
||||
int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
|
||||
texelData.add(colors, indexes);
|
||||
}
|
||||
break;
|
||||
case DXT3:// BC2
|
||||
while (data.hasRemaining()) {
|
||||
long alpha = data.getLong();
|
||||
float[] alphas = new float[16];
|
||||
long alphasIndex = 0;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
alphasIndex |= i << i * 4;
|
||||
byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
|
||||
alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
|
||||
}
|
||||
|
||||
short c0 = data.getShort();
|
||||
short c1 = data.getShort();
|
||||
int col0 = RGB565.RGB565_to_ARGB8(c0);
|
||||
int col1 = RGB565.RGB565_to_ARGB8(c1);
|
||||
colors[0].fromARGB8(col0);
|
||||
colors[1].fromARGB8(col1);
|
||||
|
||||
if (col0 > col1) {
|
||||
// creating color2 = 2/3color0 + 1/3color1
|
||||
colors[2].fromPixel(colors[0]);
|
||||
colors[2].mult(2);
|
||||
@ -267,106 +315,60 @@ public class TextureHelper extends AbstractBlenderHelper {
|
||||
colors[3].mult(2);
|
||||
colors[3].add(colors[0]);
|
||||
colors[3].divide(3);
|
||||
} else {
|
||||
// creating color2 = 1/2color0 + 1/2color1
|
||||
|
||||
int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
|
||||
texelData.add(colors, indexes, alphas, alphasIndex);
|
||||
}
|
||||
break;
|
||||
case DXT5:// BC3
|
||||
float[] alphas = new float[8];
|
||||
while (data.hasRemaining()) {
|
||||
alphas[0] = data.get() * 255.0f;
|
||||
alphas[1] = data.get() * 255.0f;
|
||||
long alphaIndices = data.get() | data.get() << 8 | data.get() << 16 | data.get() << 24 | data.get() << 32 | data.get() << 40;
|
||||
if (alphas[0] > alphas[1]) {// 6 interpolated alpha values.
|
||||
alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
|
||||
alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
|
||||
alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
|
||||
alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
|
||||
alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
|
||||
alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
|
||||
} else {
|
||||
alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
|
||||
alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
|
||||
alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
|
||||
alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
|
||||
alphas[6] = 0;
|
||||
alphas[7] = 1;
|
||||
}
|
||||
|
||||
short c0 = data.getShort();
|
||||
short c1 = data.getShort();
|
||||
int col0 = RGB565.RGB565_to_ARGB8(c0);
|
||||
int col1 = RGB565.RGB565_to_ARGB8(c1);
|
||||
colors[0].fromARGB8(col0);
|
||||
colors[1].fromARGB8(col1);
|
||||
|
||||
// creating color2 = 2/3color0 + 1/3color1
|
||||
colors[2].fromPixel(colors[0]);
|
||||
colors[2].mult(2);
|
||||
colors[2].add(colors[1]);
|
||||
colors[2].mult(0.5f);
|
||||
colors[2].divide(3);
|
||||
|
||||
colors[3].fromARGB8(0);
|
||||
}
|
||||
int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
|
||||
texelData.add(colors, indexes);
|
||||
}
|
||||
break;
|
||||
case DXT3:// BC2
|
||||
bytes = new byte[image.getWidth() * image.getHeight() * 4];
|
||||
colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
|
||||
while (data.hasRemaining()) {
|
||||
long alpha = data.getLong();
|
||||
float[] alphas = new float[16];
|
||||
long alphasIndex = 0;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
alphasIndex |= i << i * 4;
|
||||
byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
|
||||
alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
|
||||
// creating color3 = 1/3color0 + 2/3color1;
|
||||
colors[3].fromPixel(colors[1]);
|
||||
colors[3].mult(2);
|
||||
colors[3].add(colors[0]);
|
||||
colors[3].divide(3);
|
||||
|
||||
int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
|
||||
texelData.add(colors, indexes, alphas, alphaIndices);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown compressed format: " + format);
|
||||
}
|
||||
|
||||
short c0 = data.getShort();
|
||||
short c1 = data.getShort();
|
||||
int col0 = RGB565.RGB565_to_ARGB8(c0);
|
||||
int col1 = RGB565.RGB565_to_ARGB8(c1);
|
||||
colors[0].fromARGB8(col0);
|
||||
colors[1].fromARGB8(col1);
|
||||
|
||||
// creating color2 = 2/3color0 + 1/3color1
|
||||
colors[2].fromPixel(colors[0]);
|
||||
colors[2].mult(2);
|
||||
colors[2].add(colors[1]);
|
||||
colors[2].divide(3);
|
||||
|
||||
// creating color3 = 1/3color0 + 2/3color1;
|
||||
colors[3].fromPixel(colors[1]);
|
||||
colors[3].mult(2);
|
||||
colors[3].add(colors[0]);
|
||||
colors[3].divide(3);
|
||||
|
||||
int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
|
||||
texelData.add(colors, indexes, alphas, alphasIndex);
|
||||
}
|
||||
break;
|
||||
case DXT5:// BC3
|
||||
bytes = new byte[image.getWidth() * image.getHeight() * 4];
|
||||
colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
|
||||
float[] alphas = new float[8];
|
||||
while (data.hasRemaining()) {
|
||||
alphas[0] = data.get() * 255.0f;
|
||||
alphas[1] = data.get() * 255.0f;
|
||||
long alphaIndices = data.get() | data.get() << 8 | data.get() << 16 | data.get() << 24 | data.get() << 32 | data.get() << 40;
|
||||
if (alphas[0] > alphas[1]) {// 6 interpolated alpha values.
|
||||
alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
|
||||
alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
|
||||
alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
|
||||
alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
|
||||
alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
|
||||
alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
|
||||
} else {
|
||||
alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
|
||||
alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
|
||||
alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
|
||||
alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
|
||||
alphas[6] = 0;
|
||||
alphas[7] = 1;
|
||||
}
|
||||
|
||||
short c0 = data.getShort();
|
||||
short c1 = data.getShort();
|
||||
int col0 = RGB565.RGB565_to_ARGB8(c0);
|
||||
int col1 = RGB565.RGB565_to_ARGB8(c1);
|
||||
colors[0].fromARGB8(col0);
|
||||
colors[1].fromARGB8(col1);
|
||||
|
||||
// creating color2 = 2/3color0 + 1/3color1
|
||||
colors[2].fromPixel(colors[0]);
|
||||
colors[2].mult(2);
|
||||
colors[2].add(colors[1]);
|
||||
colors[2].divide(3);
|
||||
|
||||
// creating color3 = 1/3color0 + 2/3color1;
|
||||
colors[3].fromPixel(colors[1]);
|
||||
colors[3].mult(2);
|
||||
colors[3].add(colors[0]);
|
||||
colors[3].divide(3);
|
||||
|
||||
int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
|
||||
texelData.add(colors, indexes, alphas, alphaIndices);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGGER.fine("Unsupported decompression format.");
|
||||
}
|
||||
|
||||
if (bytes != null) {// writing the data to the result table
|
||||
byte[] pixelBytes = new byte[4];
|
||||
for (int i = 0; i < image.getWidth(); ++i) {
|
||||
for (int j = 0; j < image.getHeight(); ++j) {
|
||||
@ -377,11 +379,15 @@ public class TextureHelper extends AbstractBlenderHelper {
|
||||
bytes[(j * image.getWidth() + i) * 4 + 3] = pixelBytes[3];
|
||||
}
|
||||
}
|
||||
// TODO: think of other image formats (ie. RGB if the texture has no
|
||||
// alpha values)
|
||||
return new Image(Format.RGBA8, image.getWidth(), image.getHeight(), BufferUtils.createByteBuffer(bytes));
|
||||
dataArray.add(BufferUtils.createByteBuffer(bytes));
|
||||
}
|
||||
return image;
|
||||
|
||||
Image result = depth > 1 ? new Image(Format.RGBA8, image.getWidth(), image.getHeight(), depth, dataArray) :
|
||||
new Image(Format.RGBA8, image.getWidth(), image.getHeight(), dataArray.get(0));
|
||||
if(image.getMipMapSizes() != null) {
|
||||
result.setMipMapSizes(image.getMipMapSizes().clone());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,7 +42,6 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
|
||||
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
|
||||
float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f };
|
||||
Format format = image.getFormat();
|
||||
ByteBuffer data = image.getData(0);
|
||||
|
||||
PixelInputOutput basePixelIO = null, pixelReader = PixelIOFactory.getPixelIO(format);
|
||||
TexturePixel basePixel = null, pixel = new TexturePixel();
|
||||
@ -59,44 +58,50 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
|
||||
if (depth == 0) {
|
||||
depth = 1;
|
||||
}
|
||||
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4);
|
||||
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
|
||||
|
||||
float[] resultPixel = new float[4];
|
||||
int dataIndex = 0, x = 0, y = 0, index = 0;
|
||||
while (index < data.limit()) {
|
||||
//getting the proper material color if the base texture is applied
|
||||
if(basePixelIO != null) {
|
||||
basePixelIO.read(baseImage, basePixel, x, y);
|
||||
basePixel.toRGBA(materialColor);
|
||||
}
|
||||
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
|
||||
ByteBuffer data = image.getData(dataLayerIndex);
|
||||
data.rewind();
|
||||
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 4);
|
||||
|
||||
//reading the current texture's pixel
|
||||
pixelReader.read(image, pixel, index);
|
||||
index += image.getFormat().getBitsPerPixel() >> 3;
|
||||
pixel.toRGBA(pixelColor);
|
||||
if (negateTexture) {
|
||||
pixel.negate();
|
||||
int dataIndex = 0, x = 0, y = 0, index = 0;
|
||||
while (index < data.limit()) {
|
||||
//getting the proper material color if the base texture is applied
|
||||
if(basePixelIO != null) {
|
||||
basePixelIO.read(baseImage, basePixel, x, y);
|
||||
basePixel.toRGBA(materialColor);
|
||||
}
|
||||
|
||||
//reading the current texture's pixel
|
||||
pixelReader.read(image, pixel, index);
|
||||
index += image.getFormat().getBitsPerPixel() >> 3;
|
||||
pixel.toRGBA(pixelColor);
|
||||
if (negateTexture) {
|
||||
pixel.negate();
|
||||
}
|
||||
|
||||
this.blendPixel(resultPixel, materialColor, pixelColor, blenderContext);
|
||||
newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f));
|
||||
|
||||
++x;
|
||||
if(x >= width) {
|
||||
x = 0;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
this.blendPixel(resultPixel, materialColor, pixelColor, blenderContext);
|
||||
newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f));
|
||||
|
||||
++x;
|
||||
if(x >= width) {
|
||||
x = 0;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
if(depth > 1) {
|
||||
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
|
||||
dataArray.add(newData);
|
||||
return new Image(Format.RGBA8, width, height, depth, dataArray);
|
||||
} else {
|
||||
return new Image(Format.RGBA8, width, height, newData);
|
||||
}
|
||||
|
||||
Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray) : new Image(Format.RGBA8, width, height, dataArray.get(0));
|
||||
if(image.getMipMapSizes() != null) {
|
||||
result.setMipMapSizes(image.getMipMapSizes().clone());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,8 +2,6 @@ package com.jme3.scene.plugins.blender.textures.blending;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jme3tools.converters.RGB565;
|
||||
|
||||
@ -18,15 +16,12 @@ import com.jme3.util.BufferUtils;
|
||||
/**
|
||||
* The class that is responsible for blending the following texture types:
|
||||
* <li> DXT1
|
||||
* <li> DXT1A
|
||||
* <li> DXT3
|
||||
* <li> DXT5
|
||||
* Not yet supported (but will be):
|
||||
* <li> DXT1A:
|
||||
* @author Marcin Roguski (Kaelthas)
|
||||
*/
|
||||
public class TextureBlenderDDS extends TextureBlenderAWT {
|
||||
private static final Logger LOGGER = Logger.getLogger(TextureBlenderDDS.class.getName());
|
||||
|
||||
public TextureBlenderDDS(int flag, boolean negateTexture, int blendType, float[] materialColor, float[] color, float blendFactor) {
|
||||
super(flag, negateTexture, blendType, materialColor, color, blendFactor);
|
||||
}
|
||||
@ -34,16 +29,13 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
|
||||
@Override
|
||||
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
|
||||
Format format = image.getFormat();
|
||||
ByteBuffer data = image.getData(0);
|
||||
data.rewind();
|
||||
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
int depth = image.getDepth();
|
||||
if (depth == 0) {
|
||||
depth = 1;
|
||||
}
|
||||
ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
|
||||
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
|
||||
|
||||
PixelInputOutput basePixelIO = null;
|
||||
float[][] compressedMaterialColor = null;
|
||||
@ -57,77 +49,77 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
|
||||
float[] resultPixel = new float[4];
|
||||
float[] pixelColor = new float[4];
|
||||
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
|
||||
int dataIndex = 0, baseXTexelIndex = 0, baseYTexelIndex = 0;
|
||||
int baseXTexelIndex = 0, baseYTexelIndex = 0;
|
||||
float[] alphas = new float[] {1, 1};
|
||||
while (data.hasRemaining()) {
|
||||
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
|
||||
for (int i = 0; i < colors.length; ++i) {
|
||||
if (negateTexture) {
|
||||
colors[i].negate();
|
||||
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
|
||||
ByteBuffer data = image.getData(dataLayerIndex);
|
||||
data.rewind();
|
||||
ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
|
||||
System.out.println(dataLayerIndex);
|
||||
while (data.hasRemaining()) {
|
||||
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;
|
||||
newData.putLong(alpha);
|
||||
} 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;
|
||||
newData.put(alpha0);
|
||||
newData.put(alpha1);
|
||||
//only read the next 6 bytes (these are alpha indexes)
|
||||
newData.putInt(data.getInt());
|
||||
newData.putShort(data.getShort());
|
||||
}
|
||||
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]);
|
||||
}
|
||||
colors[i].toRGBA(pixelColor);
|
||||
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);
|
||||
newData.putShort(dataIndex, rgb565);
|
||||
dataIndex += 2;
|
||||
}
|
||||
|
||||
// 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;
|
||||
// blending colors
|
||||
for (int i = 0; i < colors.length; ++i) {
|
||||
if (negateTexture) {
|
||||
colors[i].negate();
|
||||
}
|
||||
colors[i].toRGBA(pixelColor);
|
||||
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);
|
||||
newData.putShort(rgb565);
|
||||
}
|
||||
|
||||
// just copy the remaining 4 bytes of the current texel
|
||||
newData.putInt(data.getInt());
|
||||
|
||||
++baseXTexelIndex;
|
||||
if(baseXTexelIndex > image.getWidth() >> 2) {
|
||||
baseXTexelIndex = 0;
|
||||
++baseYTexelIndex;
|
||||
}
|
||||
}
|
||||
dataArray.add(newData);
|
||||
}
|
||||
|
||||
if(depth > 1) {
|
||||
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
|
||||
dataArray.add(newData);
|
||||
return new Image(format, width, height, depth, dataArray);
|
||||
} else {
|
||||
return new Image(format, width, height, newData);
|
||||
Image result = dataArray.size() > 1 ? new Image(format, width, height, depth, dataArray) : new Image(format, width, height, dataArray.get(0));
|
||||
if(image.getMipMapSizes() != null) {
|
||||
result.setMipMapSizes(image.getMipMapSizes().clone());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,6 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
|
||||
|
||||
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
|
||||
Format format = image.getFormat();
|
||||
ByteBuffer data = image.getData(0);
|
||||
data.rewind();
|
||||
|
||||
PixelInputOutput basePixelIO = null;
|
||||
TexturePixel basePixel = null;
|
||||
@ -53,39 +51,44 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
|
||||
if (depth == 0) {
|
||||
depth = 1;
|
||||
}
|
||||
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4);
|
||||
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
|
||||
|
||||
float[] resultPixel = new float[4];
|
||||
float[] tinAndAlpha = new float[2];
|
||||
int dataIndex = 0, x = 0, y = 0;
|
||||
while (data.hasRemaining()) {
|
||||
//getting the proper material color if the base texture is applied
|
||||
if(basePixelIO != null) {
|
||||
basePixelIO.read(baseImage, basePixel, x, y);
|
||||
basePixel.toRGBA(materialColor);
|
||||
}
|
||||
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
|
||||
ByteBuffer data = image.getData(dataLayerIndex);
|
||||
data.rewind();
|
||||
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 4);
|
||||
|
||||
this.getTinAndAlpha(data, format, negateTexture, tinAndAlpha);
|
||||
this.blendPixel(resultPixel, materialColor, color, tinAndAlpha[0], blendFactor, blendType, blenderContext);
|
||||
newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (tinAndAlpha[1] * 255.0f));
|
||||
|
||||
++x;
|
||||
if(x >= width) {
|
||||
x = 0;
|
||||
++y;
|
||||
int dataIndex = 0, x = 0, y = 0;
|
||||
while (data.hasRemaining()) {
|
||||
//getting the proper material color if the base texture is applied
|
||||
if(basePixelIO != null) {
|
||||
basePixelIO.read(baseImage, basePixel, x, y);
|
||||
basePixel.toRGBA(materialColor);
|
||||
}
|
||||
|
||||
this.getTinAndAlpha(data, format, negateTexture, tinAndAlpha);
|
||||
this.blendPixel(resultPixel, materialColor, color, tinAndAlpha[0], blendFactor, blendType, blenderContext);
|
||||
newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
|
||||
newData.put(dataIndex++, (byte) (tinAndAlpha[1] * 255.0f));
|
||||
|
||||
++x;
|
||||
if(x >= width) {
|
||||
x = 0;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
dataArray.add(newData);
|
||||
}
|
||||
|
||||
if(depth > 1) {
|
||||
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
|
||||
dataArray.add(newData);
|
||||
return new Image(Format.RGBA8, width, height, depth, dataArray);
|
||||
} else {
|
||||
return new Image(Format.RGBA8, width, height, newData);
|
||||
Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray) : new Image(Format.RGBA8, width, height, dataArray.get(0));
|
||||
if(image.getMipMapSizes() != null) {
|
||||
result.setMipMapSizes(image.getMipMapSizes().clone());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -34,7 +34,8 @@ import com.jme3.texture.Image;
|
||||
ByteBuffer data = image.getData().get(0);
|
||||
|
||||
switch (image.getFormat()) {
|
||||
case DXT1: {// BC1
|
||||
case DXT1: // BC1
|
||||
case DXT1A:{
|
||||
data.position(texelIndex * 8);
|
||||
short c0 = data.getShort();
|
||||
short c1 = data.getShort();
|
||||
@ -142,8 +143,6 @@ import com.jme3.texture.Image;
|
||||
indexes = data.getInt();// 4-byte table with color indexes in decompressed table
|
||||
break;
|
||||
}
|
||||
case DXT1A://TODO: implement
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported decompression format.");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user