protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
int index = 0;
int[] outPixels = new int[width * height];
float width45 = Math.abs(6.0f * bumpHeight);
boolean invertBumps = bumpHeight < 0;
Vector3f position = new Vector3f(0.0f, 0.0f, 0.0f);
Vector3f viewpoint = new Vector3f(width / 2.0f, height / 2.0f, viewDistance);
Vector3f normal = new Vector3f();
Color4f envColor = new Color4f();
Color4f diffuseColor = new Color4f( new Color(material.diffuseColor) );
Color4f specularColor = new Color4f( new Color(material.specularColor) );
Function2D bump = bumpFunction;
// Apply the bump softness
if (bumpSource == BUMPS_FROM_IMAGE || bumpSource == BUMPS_FROM_IMAGE_ALPHA || bumpSource == BUMPS_FROM_MAP || bump == null) {
if ( bumpSoftness != 0 ) {
int bumpWidth = width;
int bumpHeight = height;
int[] bumpPixels = inPixels;
if ( bumpSource == BUMPS_FROM_MAP && bumpFunction instanceof ImageFunction2D ) {
ImageFunction2D if2d = (ImageFunction2D)bumpFunction;
bumpWidth = if2d.getWidth();
bumpHeight = if2d.getHeight();
bumpPixels = if2d.getPixels();
}
int [] tmpPixels = new int[bumpWidth * bumpHeight];
int [] softPixels = new int[bumpWidth * bumpHeight];
/*
for (int i = 0; i < 3; i++ ) {
BoxBlurFilter.blur( bumpPixels, tmpPixels, bumpWidth, bumpHeight, (int)bumpSoftness );
BoxBlurFilter.blur( tmpPixels, softPixels, bumpHeight, bumpWidth, (int)bumpSoftness );
}
*/
Kernel kernel = GaussianFilter.makeKernel( bumpSoftness );
GaussianFilter.convolveAndTranspose( kernel, bumpPixels, tmpPixels, bumpWidth, bumpHeight, true, false, false, GaussianFilter.WRAP_EDGES );
GaussianFilter.convolveAndTranspose( kernel, tmpPixels, softPixels, bumpHeight, bumpWidth, true, false, false, GaussianFilter.WRAP_EDGES );
bump = new ImageFunction2D(softPixels, bumpWidth, bumpHeight, ImageFunction2D.CLAMP, bumpSource == BUMPS_FROM_IMAGE_ALPHA);
final Function2D bbump = bump;
if ( bumpShape != 0 ) {
bump = new Function2D() {
private Function2D original = bbump;
public float evaluate(float x, float y) {
float v = original.evaluate( x, y );
switch ( bumpShape ) {
case 1:
// v = v > 0.5f ? 0.5f : v;
v *= ImageMath.smoothStep( 0.45f, 0.55f, v );
break;
case 2:
v = v < 0.5f ? 0.5f : v;
break;
case 3:
v = ImageMath.triangle( v );
break;
case 4:
v = ImageMath.circleDown( v );
break;
case 5:
v = ImageMath.gain( v, 0.75f );
break;
}
return v;
}
};
}
} else if ( bumpSource != BUMPS_FROM_MAP )
bump = new ImageFunction2D(inPixels, width, height, ImageFunction2D.CLAMP, bumpSource == BUMPS_FROM_IMAGE_ALPHA);
}
float reflectivity = material.reflectivity;
float areflectivity = (1-reflectivity);
Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f();
Vector3f n = new Vector3f();
Light[] lightsArray = new Light[lights.size()];
lights.copyInto(lightsArray);
for (int i = 0; i < lightsArray.length; i++)
lightsArray[i].prepare(width, height);
float[][] heightWindow = new float[3][width];
for (int x = 0; x < width; x++)
heightWindow[1][x] = width45*bump.evaluate(x, 0);
// Loop through each source pixel
for (int y = 0; y < height; y++) {
boolean y0 = y > 0;
boolean y1 = y < height-1;
position.y = y;
for (int x = 0; x < width; x++)
heightWindow[2][x] = width45*bump.evaluate(x, y+1);
for (int x = 0; x < width; x++) {
boolean x0 = x > 0;
boolean x1 = x < width-1;
// Calculate the normal at this point
if (bumpSource != BUMPS_FROM_BEVEL) {
// Complicated and slower method
// Calculate four normals using the gradients in +/- X/Y directions
int count = 0;
normal.x = normal.y = normal.z = 0;
float m0 = heightWindow[1][x];
float m1 = x0 ? heightWindow[1][x-1]-m0 : 0;
float m2 = y0 ? heightWindow[0][x]-m0 : 0;
float m3 = x1 ? heightWindow[1][x+1]-m0 : 0;
float m4 = y1 ? heightWindow[2][x]-m0 : 0;
if (x0 && y1) {
v1.x = -1.0f; v1.y = 0.0f; v1.z = m1;
v2.x = 0.0f; v2.y = 1.0f; v2.z = m4;
n.cross(v1, v2);
n.normalize();
if (n.z < 0.0)
n.z = -n.z;
normal.add(n);
count++;
}
if (x0 && y0) {
v1.x = -1.0f; v1.y = 0.0f; v1.z = m1;
v2.x = 0.0f; v2.y = -1.0f; v2.z = m2;
n.cross(v1, v2);
n.normalize();
if (n.z < 0.0)
n.z = -n.z;
normal.add(n);
count++;
}
if (y0 && x1) {
v1.x = 0.0f; v1.y = -1.0f; v1.z = m2;
v2.x = 1.0f; v2.y = 0.0f; v2.z = m3;
n.cross(v1, v2);
n.normalize();
if (n.z < 0.0)
n.z = -n.z;
normal.add(n);
count++;
}
if (x1 && y1) {
v1.x = 1.0f; v1.y = 0.0f; v1.z = m3;
v2.x = 0.0f; v2.y = 1.0f; v2.z = m4;
n.cross(v1, v2);
n.normalize();
if (n.z < 0.0)
n.z = -n.z;
normal.add(n);
count++;
}