159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.scene.plugins.blender.textures.blending; 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.ByteBuffer; 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.ArrayList; 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level; 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger; 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.BlenderContext; 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Image; 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture; 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture2D; 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture3D; 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Image.Format; 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The class that is responsible for blending the following texture types: 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGBA8 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> ABGR8 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> BGR8 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB8 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Not yet supported (but will be): 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> ARGB4444: 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB10: 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB111110F: 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB16: 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB16F: 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB16F_to_RGB111110F: 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB16F_to_RGB9E5: 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB32F: 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB565: 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB5A1: 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGB9E5: 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGBA16: 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <li> RGBA16F 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Marcin Roguski (Kaelthas) 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class TextureBlenderAWT extends AbstractTextureBlender { 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final Logger LOGGER = Logger.getLogger(TextureBlenderAWT.class.getName()); 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext) { 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f }; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Format format = texture.getImage().getFormat(); 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ByteBuffer data = texture.getImage().getData(0); 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta data.rewind(); 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int width = texture.getImage().getWidth(); 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int height = texture.getImage().getHeight(); 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int depth = texture.getImage().getDepth(); 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (depth == 0) { 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta depth = 1; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4); 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float[] resultPixel = new float[4]; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int dataIndex = 0; 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (data.hasRemaining()) { 59a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta this.setupMaterialColor(data, format, neg, pixelColor); 60a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta this.blendPixel(resultPixel, materialColor, pixelColor, affectFactor, blendType, blenderContext); 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f)); 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f)); 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f)); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (texture.getType() == Texture.Type.TwoDimensional) { 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return new Texture2D(new Image(Format.RGBA8, width, height, newData)); 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1); 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dataArray.add(newData); 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return new Texture3D(new Image(Format.RGBA8, width, height, depth, dataArray)); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method alters the material color in a way dependent on the type of 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the image. For example the color remains untouched if the texture is of 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Luminance type. The luminance defines the interaction between the 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * material color and color defined for texture blending. If the type has 3 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * or more color channels then the material color is replaced with the 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * texture's color and later blended with the defined blend color. All alpha 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * values (if present) are ignored and not used during blending. 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param data 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the image data 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param imageFormat 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the format of the image 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param neg 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * defines it the result color should be nagated 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param materialColor 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the material's color (value may be changed) 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return texture intensity for the current pixel 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected float setupMaterialColor(ByteBuffer data, Format imageFormat, boolean neg, float[] materialColor) { 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float tin = 0.0f; 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte pixelValue = data.get();// at least one byte is always taken :) 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float firstPixelValue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (imageFormat) { 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGBA8: 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[0] = firstPixelValue; 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[3] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case ABGR8: 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[3] = firstPixelValue; 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case BGR8: 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[2] = firstPixelValue; 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[3] = 1.0f; 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB8: 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[0] = firstPixelValue; 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pixelValue = data.get(); 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[3] = 1.0f; 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case ARGB4444: 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB10: 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB111110F: 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB16: 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB16F: 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB16F_to_RGB111110F: 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB16F_to_RGB9E5: 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB32F: 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB565: 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB5A1: 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGB9E5: 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGBA16: 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGBA16F: 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RGBA32F:// TODO: implement these textures 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", imageFormat); 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta default: 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Invalid image format type for AWT texture blender: " + imageFormat); 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (neg) { 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[0] = 1.0f - materialColor[0]; 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[1] = 1.0f - materialColor[1]; 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta materialColor[2] = 1.0f - materialColor[2]; 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Blender formula for texture intensity calculation: 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 0.35*texres.tr+0.45*texres.tg+0.2*texres.tb 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tin = 0.35f * materialColor[0] + 0.45f * materialColor[1] + 0.2f * materialColor[2]; 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return tin; 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 163