Пример #1
0
 /**
  * Specifies the angle of the effect.
  *
  * @param angle the angle of the effect.
  * @angle
  * @see #getAngle
  */
 public void setAngle(float angle) {
   this.angle = angle;
   float cos = (float) Math.cos(angle);
   float sin = (float) Math.sin(angle);
   m00 = cos;
   m01 = sin;
   m10 = -sin;
   m11 = cos;
 }
Пример #2
0
  private int getEnvironmentMap(Vector3f normal, int[] inPixels, int width, int height) {
    if (environmentMap != null) {
      float angle = (float) Math.acos(-normal.y);

      float x, y;
      y = angle / ImageMath.PI;

      if (y == 0.0f || y == 1.0f) x = 0.0f;
      else {
        float f = normal.x / (float) Math.sin(angle);

        if (f > 1.0f) f = 1.0f;
        else if (f < -1.0f) f = -1.0f;

        x = (float) Math.acos(f) / ImageMath.PI;
      }
      // A bit of empirical scaling....
      x = ImageMath.clamp(x * envWidth, 0, envWidth - 1);
      y = ImageMath.clamp(y * envHeight, 0, envHeight - 1);
      int ix = (int) x;
      int iy = (int) y;

      float xWeight = x - ix;
      float yWeight = y - iy;
      int i = envWidth * iy + ix;
      int dx = ix == envWidth - 1 ? 0 : 1;
      int dy = iy == envHeight - 1 ? 0 : envWidth;
      return ImageMath.bilinearInterpolate(
          xWeight,
          yWeight,
          envPixels[i],
          envPixels[i + dx],
          envPixels[i + dy],
          envPixels[i + dx + dy]);
    }
    return 0;
  }
Пример #3
0
 /**
  * Prepare the light for rendering.
  *
  * @param width the output image width
  * @param height the output image height
  */
 public void prepare(int width, int height) {
   float lx = (float) (Math.cos(azimuth) * Math.cos(elevation));
   float ly = (float) (Math.sin(azimuth) * Math.cos(elevation));
   float lz = (float) Math.sin(elevation);
   direction = new Vector3f(lx, ly, lz);
   direction.normalize();
   if (type != DISTANT) {
     lx *= distance;
     ly *= distance;
     lz *= distance;
     lx += width * centreX;
     ly += height * centreY;
   }
   position = new Vector3f(lx, ly, lz);
   realColor.set(new Color(color));
   realColor.scale(intensity);
   cosConeAngle = (float) Math.cos(coneAngle);
 }
Пример #4
0
  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((float) width / 2.0f, (float) height / 2.0f, viewDistance);
    Vector3f normal = new Vector3f();
    Color4f c = new Color4f();
    Function2D bump = bumpFunction;

    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();
        }
        Kernel kernel = GaussianFilter.makeKernel(bumpSoftness);
        int[] tmpPixels = new int[bumpWidth * bumpHeight];
        int[] softPixels = new int[bumpWidth * bumpHeight];
        GaussianFilter.convolveAndTranspose(
            kernel,
            bumpPixels,
            tmpPixels,
            bumpWidth,
            bumpHeight,
            true,
            false,
            false,
            ConvolveFilter.CLAMP_EDGES);
        GaussianFilter.convolveAndTranspose(
            kernel,
            tmpPixels,
            softPixels,
            bumpHeight,
            bumpWidth,
            true,
            false,
            false,
            ConvolveFilter.CLAMP_EDGES);
        bump =
            new ImageFunction2D(
                softPixels,
                bumpWidth,
                bumpHeight,
                ImageFunction2D.CLAMP,
                bumpSource == BUMPS_FROM_IMAGE_ALPHA);
      } else
        bump =
            new ImageFunction2D(
                inPixels,
                width,
                height,
                ImageFunction2D.CLAMP,
                bumpSource == BUMPS_FROM_IMAGE_ALPHA);
    }

    Vector3f v1 = new Vector3f();
    Vector3f v2 = new Vector3f();
    Vector3f n = new Vector3f();

    // Loop through each source pixel
    for (int y = 0; y < height; y++) {
      float ny = y;
      position.y = y;
      for (int x = 0; x < width; x++) {
        float nx = x;

        // 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 = width45 * bump.evaluate(nx, ny);
          float m1 = x > 0 ? width45 * bump.evaluate(nx - 1.0f, ny) - m0 : -2;
          float m2 = y > 0 ? width45 * bump.evaluate(nx, ny - 1.0f) - m0 : -2;
          float m3 = x < width - 1 ? width45 * bump.evaluate(nx + 1.0f, ny) - m0 : -2;
          float m4 = y < height - 1 ? width45 * bump.evaluate(nx, ny + 1.0f) - m0 : -2;

          if (m1 != -2 && m4 != -2) {
            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 (m1 != -2 && m2 != -2) {
            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 (m2 != -2 && m3 != -2) {
            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 (m3 != -2 && m4 != -2) {
            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++;
          }

          // Average the four normals
          normal.x /= count;
          normal.y /= count;
          normal.z /= count;
        }

        /* For testing - generate a sphere bump map
        				double dx = x-120;
        				double dy = y-80;
        				double r2 = dx*dx+dy*dy;
        //				double r = Math.sqrt( r2 );
        //				double t = Math.atan2( dy, dx );
        				if ( r2 < 80*80 ) {
        					double z = Math.sqrt( 80*80 - r2 );
        					normal.x = (float)dx;
        					normal.y = (float)dy;
        					normal.z = (float)z;
        					normal.normalize();
        				} else {
        					normal.x = 0;
        					normal.y = 0;
        					normal.z = 1;
        				}
        */

        if (invertBumps) {
          normal.x = -normal.x;
          normal.y = -normal.y;
        }
        position.x = x;

        if (normal.z >= 0) {
          // Get the material colour at this point
          if (environmentMap != null) {
            // FIXME-too much normalizing going on here
            tmpv2.set(viewpoint);
            tmpv2.sub(position);
            tmpv2.normalize();
            tmpv.set(normal);
            tmpv.normalize();

            // Reflect
            tmpv.scale(2.0f * tmpv.dot(tmpv2));
            tmpv.sub(v);

            tmpv.normalize();
            setFromRGB(
                c, getEnvironmentMapP(normal, inPixels, width, height)); // FIXME-interpolate()
            int alpha = inPixels[index] & 0xff000000;
            int rgb = ((int) (c.x * 255) << 16) | ((int) (c.y * 255) << 8) | (int) (c.z * 255);
            outPixels[index++] = alpha | rgb;
          } else outPixels[index++] = 0;
        } else outPixels[index++] = 0;
      }
    }
    return outPixels;
  }
Пример #5
0
  protected Color4f phongShade(
      Vector3f position,
      Vector3f viewpoint,
      Vector3f normal,
      Color4f diffuseColor,
      Color4f specularColor,
      Material material,
      Light[] lightsArray) {
    shadedColor.set(diffuseColor);
    shadedColor.scale(material.ambientIntensity);

    for (int i = 0; i < lightsArray.length; i++) {
      Light light = lightsArray[i];
      n.set(normal);
      l.set(light.position);
      if (light.type != DISTANT) l.sub(position);
      l.normalize();
      float nDotL = n.dot(l);
      if (nDotL >= 0.0) {
        float dDotL = 0;

        v.set(viewpoint);
        v.sub(position);
        v.normalize();

        // Spotlight
        if (light.type == SPOT) {
          dDotL = light.direction.dot(l);
          if (dDotL < light.cosConeAngle) continue;
        }

        n.scale(2.0f * nDotL);
        n.sub(l);
        float rDotV = n.dot(v);

        float rv;
        if (rDotV < 0.0) rv = 0.0f;
        else
          //					rv = (float)Math.pow(rDotV, material.highlight);
          rv =
              rDotV
                  / (material.highlight
                      - material.highlight * rDotV
                      + rDotV); // Fast approximation to pow

        // Spotlight
        if (light.type == SPOT) {
          dDotL = light.cosConeAngle / dDotL;
          float e = dDotL;
          e *= e;
          e *= e;
          e *= e;
          e = (float) Math.pow(dDotL, light.focus * 10) * (1 - e);
          rv *= e;
          nDotL *= e;
        }

        diffuse_color.set(diffuseColor);
        diffuse_color.scale(material.diffuseReflectivity);
        diffuse_color.x *= light.realColor.x * nDotL;
        diffuse_color.y *= light.realColor.y * nDotL;
        diffuse_color.z *= light.realColor.z * nDotL;
        specular_color.set(specularColor);
        specular_color.scale(material.specularReflectivity);
        specular_color.x *= light.realColor.x * rv;
        specular_color.y *= light.realColor.y * rv;
        specular_color.z *= light.realColor.z * rv;
        diffuse_color.add(specular_color);
        diffuse_color.clamp(0, 1);
        shadedColor.add(diffuse_color);
      }
    }
    shadedColor.clamp(0, 1);
    return shadedColor;
  }
Пример #6
0
  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((float) width / 2.0f, (float) 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++;
          }

          // Average the four normals
          normal.x /= count;
          normal.y /= count;
          normal.z /= count;
        }
        if (invertBumps) {
          normal.x = -normal.x;
          normal.y = -normal.y;
        }
        position.x = x;

        if (normal.z >= 0) {
          // Get the material colour at this point
          if (colorSource == COLORS_FROM_IMAGE) setFromRGB(diffuseColor, inPixels[index]);
          else setFromRGB(diffuseColor, material.diffuseColor);
          if (reflectivity != 0 && environmentMap != null) {
            // FIXME-too much normalizing going on here
            tmpv2.set(viewpoint);
            tmpv2.sub(position);
            tmpv2.normalize();
            tmpv.set(normal);
            tmpv.normalize();

            // Reflect
            tmpv.scale(2.0f * tmpv.dot(tmpv2));
            tmpv.sub(v);

            tmpv.normalize();
            setFromRGB(
                envColor, getEnvironmentMap(tmpv, inPixels, width, height)); // FIXME-interpolate()
            diffuseColor.x = reflectivity * envColor.x + areflectivity * diffuseColor.x;
            diffuseColor.y = reflectivity * envColor.y + areflectivity * diffuseColor.y;
            diffuseColor.z = reflectivity * envColor.z + areflectivity * diffuseColor.z;
          }
          // Shade the pixel
          Color4f c =
              phongShade(
                  position, viewpoint, normal, diffuseColor, specularColor, material, lightsArray);
          int alpha = inPixels[index] & 0xff000000;
          int rgb = ((int) (c.x * 255) << 16) | ((int) (c.y * 255) << 8) | (int) (c.z * 255);
          outPixels[index++] = alpha | rgb;
        } else outPixels[index++] = 0;
      }
      float[] t = heightWindow[0];
      heightWindow[0] = heightWindow[1];
      heightWindow[1] = heightWindow[2];
      heightWindow[2] = t;
    }
    return outPixels;
  }