package com.jme3.scene.plugins.blender.textures.blending; | |
import com.jme3.math.FastMath; | |
import com.jme3.scene.plugins.blender.BlenderContext; | |
import com.jme3.scene.plugins.blender.materials.MaterialHelper; | |
/** | |
* An abstract class that contains the basic methods used by the classes that | |
* will derive from it. | |
* | |
* @author Marcin Roguski (Kaelthas) | |
*/ | |
/* package */abstract class AbstractTextureBlender implements TextureBlender { | |
/** | |
* This method blends the single pixel depending on the blending type. | |
* | |
* @param result | |
* the result pixel | |
* @param materialColor | |
* the material color | |
* @param pixelColor | |
* the pixel color | |
* @param blendFactor | |
* the blending factor | |
* @param blendtype | |
* the blending type | |
* @param blenderContext | |
* the blender context | |
*/ | |
protected void blendPixel(float[] result, float[] materialColor, float[] pixelColor, float blendFactor, int blendtype, BlenderContext blenderContext) { | |
float oneMinusFactor = 1.0f - blendFactor, col; | |
switch (blendtype) { | |
case MTEX_BLEND: | |
result[0] = blendFactor * pixelColor[0] + oneMinusFactor * materialColor[0]; | |
result[1] = blendFactor * pixelColor[1] + oneMinusFactor * materialColor[1]; | |
result[2] = blendFactor * pixelColor[2] + oneMinusFactor * materialColor[2]; | |
break; | |
case MTEX_MUL: | |
result[0] = (oneMinusFactor + blendFactor * materialColor[0]) * pixelColor[0]; | |
result[1] = (oneMinusFactor + blendFactor * materialColor[1]) * pixelColor[1]; | |
result[2] = (oneMinusFactor + blendFactor * materialColor[2]) * pixelColor[2]; | |
break; | |
case MTEX_DIV: | |
if (pixelColor[0] != 0.0) { | |
result[0] = (oneMinusFactor * materialColor[0] + blendFactor * materialColor[0] / pixelColor[0]) * 0.5f; | |
} | |
if (pixelColor[1] != 0.0) { | |
result[1] = (oneMinusFactor * materialColor[1] + blendFactor * materialColor[1] / pixelColor[1]) * 0.5f; | |
} | |
if (pixelColor[2] != 0.0) { | |
result[2] = (oneMinusFactor * materialColor[2] + blendFactor * materialColor[2] / pixelColor[2]) * 0.5f; | |
} | |
break; | |
case MTEX_SCREEN: | |
result[0] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]); | |
result[1] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]); | |
result[2] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]); | |
break; | |
case MTEX_OVERLAY: | |
if (materialColor[0] < 0.5f) { | |
result[0] = pixelColor[0] * (oneMinusFactor + 2.0f * blendFactor * materialColor[0]); | |
} else { | |
result[0] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]); | |
} | |
if (materialColor[1] < 0.5f) { | |
result[1] = pixelColor[1] * (oneMinusFactor + 2.0f * blendFactor * materialColor[1]); | |
} else { | |
result[1] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]); | |
} | |
if (materialColor[2] < 0.5f) { | |
result[2] = pixelColor[2] * (oneMinusFactor + 2.0f * blendFactor * materialColor[2]); | |
} else { | |
result[2] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]); | |
} | |
break; | |
case MTEX_SUB: | |
result[0] = materialColor[0] - blendFactor * pixelColor[0]; | |
result[1] = materialColor[1] - blendFactor * pixelColor[1]; | |
result[2] = materialColor[2] - blendFactor * pixelColor[2]; | |
result[0] = FastMath.clamp(result[0], 0.0f, 1.0f); | |
result[1] = FastMath.clamp(result[1], 0.0f, 1.0f); | |
result[2] = FastMath.clamp(result[2], 0.0f, 1.0f); | |
break; | |
case MTEX_ADD: | |
result[0] = (blendFactor * pixelColor[0] + materialColor[0]) * 0.5f; | |
result[1] = (blendFactor * pixelColor[1] + materialColor[1]) * 0.5f; | |
result[2] = (blendFactor * pixelColor[2] + materialColor[2]) * 0.5f; | |
break; | |
case MTEX_DIFF: | |
result[0] = oneMinusFactor * materialColor[0] + blendFactor * Math.abs(materialColor[0] - pixelColor[0]); | |
result[1] = oneMinusFactor * materialColor[1] + blendFactor * Math.abs(materialColor[1] - pixelColor[1]); | |
result[2] = oneMinusFactor * materialColor[2] + blendFactor * Math.abs(materialColor[2] - pixelColor[2]); | |
break; | |
case MTEX_DARK: | |
col = blendFactor * pixelColor[0]; | |
result[0] = col < materialColor[0] ? col : materialColor[0]; | |
col = blendFactor * pixelColor[1]; | |
result[1] = col < materialColor[1] ? col : materialColor[1]; | |
col = blendFactor * pixelColor[2]; | |
result[2] = col < materialColor[2] ? col : materialColor[2]; | |
break; | |
case MTEX_LIGHT: | |
col = blendFactor * pixelColor[0]; | |
result[0] = col > materialColor[0] ? col : materialColor[0]; | |
col = blendFactor * pixelColor[1]; | |
result[1] = col > materialColor[1] ? col : materialColor[1]; | |
col = blendFactor * pixelColor[2]; | |
result[2] = col > materialColor[2] ? col : materialColor[2]; | |
break; | |
case MTEX_BLEND_HUE: | |
case MTEX_BLEND_SAT: | |
case MTEX_BLEND_VAL: | |
case MTEX_BLEND_COLOR: | |
System.arraycopy(materialColor, 0, result, 0, 3); | |
this.blendHSV(blendtype, result, blendFactor, pixelColor, blenderContext); | |
break; | |
default: | |
throw new IllegalStateException("Unknown blend type: " + blendtype); | |
} | |
} | |
/** | |
* The method that performs the ramp blending. | |
* | |
* @param type | |
* the blend type | |
* @param materialRGB | |
* the rgb value of the material, here the result is stored too | |
* @param fac | |
* color affection factor | |
* @param pixelColor | |
* the texture color | |
* @param blenderContext | |
* the blender context | |
*/ | |
protected void blendHSV(int type, float[] materialRGB, float fac, float[] pixelColor, BlenderContext blenderContext) { | |
float oneMinusFactor = 1.0f - fac; | |
MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class); | |
switch (type) { | |
case MTEX_BLEND_HUE: {// FIXME: not working well for image textures | |
// (works fine for generated textures) | |
float[] colorTransformResult = new float[3]; | |
materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult); | |
if (colorTransformResult[0] != 0.0f) { | |
float colH = colorTransformResult[0]; | |
materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult); | |
materialHelper.hsvToRgb(colH, colorTransformResult[1], colorTransformResult[2], colorTransformResult); | |
materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * colorTransformResult[0]; | |
materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * colorTransformResult[1]; | |
materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * colorTransformResult[2]; | |
} | |
break; | |
} | |
case MTEX_BLEND_SAT: { | |
float[] colorTransformResult = new float[3]; | |
materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult); | |
float h = colorTransformResult[0]; | |
float s = colorTransformResult[1]; | |
float v = colorTransformResult[2]; | |
if (s != 0.0f) { | |
materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult); | |
materialHelper.hsvToRgb(h, (oneMinusFactor * s + fac * colorTransformResult[1]), v, materialRGB); | |
} | |
break; | |
} | |
case MTEX_BLEND_VAL: { | |
float[] rgbToHsv = new float[3]; | |
float[] colToHsv = new float[3]; | |
materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv); | |
materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv); | |
materialHelper.hsvToRgb(rgbToHsv[0], rgbToHsv[1], (oneMinusFactor * rgbToHsv[2] + fac * colToHsv[2]), materialRGB); | |
break; | |
} | |
case MTEX_BLEND_COLOR: {// FIXME: not working well for image | |
// textures (works fine for generated | |
// textures) | |
float[] rgbToHsv = new float[3]; | |
float[] colToHsv = new float[3]; | |
materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv); | |
if (colToHsv[2] != 0) { | |
materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv); | |
materialHelper.hsvToRgb(colToHsv[0], colToHsv[1], rgbToHsv[2], rgbToHsv); | |
materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * rgbToHsv[0]; | |
materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * rgbToHsv[1]; | |
materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * rgbToHsv[2]; | |
} | |
break; | |
} | |
default: | |
throw new IllegalStateException("Unknown ramp type: " + type); | |
} | |
} | |
} |