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