Browse Source

Support for base texture blending for DDS textures.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9335 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl 13 years ago
parent
commit
96cfd22510

+ 56 - 20
engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java

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

+ 4 - 1
engine/src/blender/com/jme3/scene/plugins/blender/textures/io/DDSPixelInputOutput.java

@@ -14,8 +14,11 @@ import com.jme3.texture.Image;
  * @author Marcin Roguski (Kaelthas)
  */
 /*package*/ class DDSPixelInputOutput implements PixelInputOutput {
+	/**
+	 * For this class the index should be considered as a pixel index in AWT image format.
+	 */
 	public void read(Image image, TexturePixel pixel, int index) {
-		throw new UnsupportedOperationException("Cannot get the DXT pixel by index because not every index contains the pixel color!");
+		this.read(image, pixel, index % image.getWidth(), index / image.getWidth());
 	}
 
 	public void read(Image image, TexturePixel pixel, int x, int y) {