Home | History | Annotate | Download | only in blending
      1 package com.jme3.scene.plugins.blender.textures.blending;
      2 
      3 import com.jme3.math.FastMath;
      4 import com.jme3.scene.plugins.blender.BlenderContext;
      5 import com.jme3.scene.plugins.blender.materials.MaterialHelper;
      6 
      7 /**
      8  * An abstract class that contains the basic methods used by the classes that
      9  * will derive from it.
     10  *
     11  * @author Marcin Roguski (Kaelthas)
     12  */
     13 /* package */abstract class AbstractTextureBlender implements TextureBlender {
     14 	/**
     15 	 * This method blends the single pixel depending on the blending type.
     16 	 *
     17 	 * @param result
     18 	 *            the result pixel
     19 	 * @param materialColor
     20 	 *            the material color
     21 	 * @param pixelColor
     22 	 *            the pixel color
     23 	 * @param blendFactor
     24 	 *            the blending factor
     25 	 * @param blendtype
     26 	 *            the blending type
     27 	 * @param blenderContext
     28 	 *            the blender context
     29 	 */
     30 	protected void blendPixel(float[] result, float[] materialColor, float[] pixelColor, float blendFactor, int blendtype, BlenderContext blenderContext) {
     31 		float oneMinusFactor = 1.0f - blendFactor, col;
     32 
     33 		switch (blendtype) {
     34 			case MTEX_BLEND:
     35 				result[0] = blendFactor * pixelColor[0] + oneMinusFactor * materialColor[0];
     36 				result[1] = blendFactor * pixelColor[1] + oneMinusFactor * materialColor[1];
     37 				result[2] = blendFactor * pixelColor[2] + oneMinusFactor * materialColor[2];
     38 				break;
     39 			case MTEX_MUL:
     40 				result[0] = (oneMinusFactor + blendFactor * materialColor[0]) * pixelColor[0];
     41 				result[1] = (oneMinusFactor + blendFactor * materialColor[1]) * pixelColor[1];
     42 				result[2] = (oneMinusFactor + blendFactor * materialColor[2]) * pixelColor[2];
     43 				break;
     44 			case MTEX_DIV:
     45 				if (pixelColor[0] != 0.0) {
     46 					result[0] = (oneMinusFactor * materialColor[0] + blendFactor * materialColor[0] / pixelColor[0]) * 0.5f;
     47 				}
     48 				if (pixelColor[1] != 0.0) {
     49 					result[1] = (oneMinusFactor * materialColor[1] + blendFactor * materialColor[1] / pixelColor[1]) * 0.5f;
     50 				}
     51 				if (pixelColor[2] != 0.0) {
     52 					result[2] = (oneMinusFactor * materialColor[2] + blendFactor * materialColor[2] / pixelColor[2]) * 0.5f;
     53 				}
     54 				break;
     55 			case MTEX_SCREEN:
     56 				result[0] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]);
     57 				result[1] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]);
     58 				result[2] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]);
     59 				break;
     60 			case MTEX_OVERLAY:
     61 				if (materialColor[0] < 0.5f) {
     62 					result[0] = pixelColor[0] * (oneMinusFactor + 2.0f * blendFactor * materialColor[0]);
     63 				} else {
     64 					result[0] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]);
     65 				}
     66 				if (materialColor[1] < 0.5f) {
     67 					result[1] = pixelColor[1] * (oneMinusFactor + 2.0f * blendFactor * materialColor[1]);
     68 				} else {
     69 					result[1] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]);
     70 				}
     71 				if (materialColor[2] < 0.5f) {
     72 					result[2] = pixelColor[2] * (oneMinusFactor + 2.0f * blendFactor * materialColor[2]);
     73 				} else {
     74 					result[2] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]);
     75 				}
     76 				break;
     77 			case MTEX_SUB:
     78 				result[0] = materialColor[0] - blendFactor * pixelColor[0];
     79 				result[1] = materialColor[1] - blendFactor * pixelColor[1];
     80 				result[2] = materialColor[2] - blendFactor * pixelColor[2];
     81 				result[0] = FastMath.clamp(result[0], 0.0f, 1.0f);
     82 				result[1] = FastMath.clamp(result[1], 0.0f, 1.0f);
     83 				result[2] = FastMath.clamp(result[2], 0.0f, 1.0f);
     84 				break;
     85 			case MTEX_ADD:
     86 				result[0] = (blendFactor * pixelColor[0] + materialColor[0]) * 0.5f;
     87 				result[1] = (blendFactor * pixelColor[1] + materialColor[1]) * 0.5f;
     88 				result[2] = (blendFactor * pixelColor[2] + materialColor[2]) * 0.5f;
     89 				break;
     90 			case MTEX_DIFF:
     91 				result[0] = oneMinusFactor * materialColor[0] + blendFactor * Math.abs(materialColor[0] - pixelColor[0]);
     92 				result[1] = oneMinusFactor * materialColor[1] + blendFactor * Math.abs(materialColor[1] - pixelColor[1]);
     93 				result[2] = oneMinusFactor * materialColor[2] + blendFactor * Math.abs(materialColor[2] - pixelColor[2]);
     94 				break;
     95 			case MTEX_DARK:
     96 				col = blendFactor * pixelColor[0];
     97 				result[0] = col < materialColor[0] ? col : materialColor[0];
     98 				col = blendFactor * pixelColor[1];
     99 				result[1] = col < materialColor[1] ? col : materialColor[1];
    100 				col = blendFactor * pixelColor[2];
    101 				result[2] = col < materialColor[2] ? col : materialColor[2];
    102 				break;
    103 			case MTEX_LIGHT:
    104 				col = blendFactor * pixelColor[0];
    105 				result[0] = col > materialColor[0] ? col : materialColor[0];
    106 				col = blendFactor * pixelColor[1];
    107 				result[1] = col > materialColor[1] ? col : materialColor[1];
    108 				col = blendFactor * pixelColor[2];
    109 				result[2] = col > materialColor[2] ? col : materialColor[2];
    110 				break;
    111 			case MTEX_BLEND_HUE:
    112 			case MTEX_BLEND_SAT:
    113 			case MTEX_BLEND_VAL:
    114 			case MTEX_BLEND_COLOR:
    115 				System.arraycopy(materialColor, 0, result, 0, 3);
    116 				this.blendHSV(blendtype, result, blendFactor, pixelColor, blenderContext);
    117 				break;
    118 			default:
    119 				throw new IllegalStateException("Unknown blend type: " + blendtype);
    120 		}
    121 	}
    122 
    123 	/**
    124 	 * The method that performs the ramp blending.
    125 	 *
    126 	 * @param type
    127 	 *            the blend type
    128 	 * @param materialRGB
    129 	 *            the rgb value of the material, here the result is stored too
    130 	 * @param fac
    131 	 *            color affection factor
    132 	 * @param pixelColor
    133 	 *            the texture color
    134 	 * @param blenderContext
    135 	 *            the blender context
    136 	 */
    137 	protected void blendHSV(int type, float[] materialRGB, float fac, float[] pixelColor, BlenderContext blenderContext) {
    138 		float oneMinusFactor = 1.0f - fac;
    139 		MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
    140 
    141 		switch (type) {
    142 			case MTEX_BLEND_HUE: {// FIXME: not working well for image textures
    143 									// (works fine for generated textures)
    144 				float[] colorTransformResult = new float[3];
    145 				materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult);
    146 				if (colorTransformResult[0] != 0.0f) {
    147 					float colH = colorTransformResult[0];
    148 					materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult);
    149 					materialHelper.hsvToRgb(colH, colorTransformResult[1], colorTransformResult[2], colorTransformResult);
    150 					materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * colorTransformResult[0];
    151 					materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * colorTransformResult[1];
    152 					materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * colorTransformResult[2];
    153 				}
    154 				break;
    155 			}
    156 			case MTEX_BLEND_SAT: {
    157 				float[] colorTransformResult = new float[3];
    158 				materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult);
    159 				float h = colorTransformResult[0];
    160 				float s = colorTransformResult[1];
    161 				float v = colorTransformResult[2];
    162 				if (s != 0.0f) {
    163 					materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult);
    164 					materialHelper.hsvToRgb(h, (oneMinusFactor * s + fac * colorTransformResult[1]), v, materialRGB);
    165 				}
    166 				break;
    167 			}
    168 			case MTEX_BLEND_VAL: {
    169 				float[] rgbToHsv = new float[3];
    170 				float[] colToHsv = new float[3];
    171 				materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv);
    172 				materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv);
    173 				materialHelper.hsvToRgb(rgbToHsv[0], rgbToHsv[1], (oneMinusFactor * rgbToHsv[2] + fac * colToHsv[2]), materialRGB);
    174 				break;
    175 			}
    176 			case MTEX_BLEND_COLOR: {// FIXME: not working well for image
    177 									// textures (works fine for generated
    178 									// textures)
    179 				float[] rgbToHsv = new float[3];
    180 				float[] colToHsv = new float[3];
    181 				materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv);
    182 				if (colToHsv[2] != 0) {
    183 					materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv);
    184 					materialHelper.hsvToRgb(colToHsv[0], colToHsv[1], rgbToHsv[2], rgbToHsv);
    185 					materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * rgbToHsv[0];
    186 					materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * rgbToHsv[1];
    187 					materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * rgbToHsv[2];
    188 				}
    189 				break;
    190 			}
    191 			default:
    192 				throw new IllegalStateException("Unknown ramp type: " + type);
    193 		}
    194 	}
    195 }
    196