/*
 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.scenario.effect;

import com.sun.javafx.geom.BaseBounds;
import com.sun.javafx.geom.DirtyRegionContainer;
import com.sun.javafx.geom.DirtyRegionPool;
import com.sun.javafx.geom.Point2D;
import com.sun.javafx.geom.Rectangle;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.scenario.effect.impl.state.RenderState;
import com.sun.scenario.effect.light.Light;

An effect that applies diffuse and specular lighting to an arbitrary input using a positionable light source.
/** * An effect that applies diffuse and specular lighting to an arbitrary * input using a positionable light source. */
public class PhongLighting extends CoreEffect<RenderState> { private float surfaceScale; private float diffuseConstant; private float specularConstant; private float specularExponent; private Light light;
Constructs a new PhongLighting effect for the given Light, with default values for all other properties, using the default input for source data. This is a convenience constructor that automatically generates a bump map using the default input.
Params:
  • light – the light source
Throws:
/** * Constructs a new {@code PhongLighting} effect for the given * {@code Light}, with default values for all other properties, * using the default input for source data. * This is a convenience constructor that automatically generates a * bump map using the default input. * * @param light the light source * @throws IllegalArgumentException if {@code light} is null */
public PhongLighting(Light light) { this(light, new GaussianShadow(10f), DefaultInput); }
Constructs a new PhongLighting effect for the given Light and the given bump and content input Effects with default values for all other properties.
Params:
  • light – the light source
  • bumpInput – the input containing the bump map
  • contentInput – the input containing the content data
Throws:
/** * Constructs a new {@code PhongLighting} effect for the given * {@code Light} and the given bump and content input {@code Effect}s * with default values for all other properties. * * @param light the light source * @param bumpInput the input containing the bump map * @param contentInput the input containing the content data * @throws IllegalArgumentException if {@code light} is null */
public PhongLighting(Light light, Effect bumpInput, Effect contentInput) { super(bumpInput, contentInput); this.surfaceScale = 1f; this.diffuseConstant = 1f; this.specularConstant = 1f; this.specularExponent = 1f; setLight(light); }
Returns the bump input for this Effect.
Returns:the bump input for this Effect
/** * Returns the bump input for this {@code Effect}. * * @return the bump input for this {@code Effect} */
public final Effect getBumpInput() { return getInputs().get(0); }
Sets the bump input for this Effect to a specific Effect or to the default input if input is null.
Params:
  • bumpInput – the bump input for this Effect
/** * Sets the bump input for this {@code Effect} to a specific * {@code Effect} or to the default input if {@code input} is * {@code null}. * * @param bumpInput the bump input for this {@code Effect} */
public void setBumpInput(Effect bumpInput) { setInput(0, bumpInput); }
Returns the content input for this Effect.
Returns:the content input for this Effect
/** * Returns the content input for this {@code Effect}. * * @return the content input for this {@code Effect} */
public final Effect getContentInput() { return getInputs().get(1); } private Effect getContentInput(Effect defaultInput) { return getDefaultedInput(1, defaultInput); }
Sets the content input for this Effect to a specific Effect or to the default input if input is null.
Params:
  • contentInput – the content input for this Effect
/** * Sets the content input for this {@code Effect} to a specific * {@code Effect} or to the default input if {@code input} is * {@code null}. * * @param contentInput the content input for this {@code Effect} */
public void setContentInput(Effect contentInput) { setInput(1, contentInput); }
Returns the light source.
Returns:the light source
/** * Returns the light source. * * @return the light source */
public Light getLight() { return light; }
Sets the light source.
Params:
  • light – the light source
Throws:
/** * Sets the light source. * * @param light the light source * @throws IllegalArgumentException if {@code light} is null */
public void setLight(Light light) { if (light == null) { throw new IllegalArgumentException("Light must be non-null"); } this.light = light; updatePeerKey("PhongLighting_" + light.getType().name()); }
Returns the diffuse constant.
Returns:the diffuse constant value
/** * Returns the diffuse constant. * * @return the diffuse constant value */
public float getDiffuseConstant() { return diffuseConstant; }
Sets the diffuse constant.
      Min: 0.0
      Max: 2.0
  Default: 1.0
 Identity: n/a
Params:
  • diffuseConstant – the diffuse constant value
Throws:
/** * Sets the diffuse constant. * <pre> * Min: 0.0 * Max: 2.0 * Default: 1.0 * Identity: n/a * </pre> * * @param diffuseConstant the diffuse constant value * @throws IllegalArgumentException if {@code diffuseConstant} is outside * the allowable range */
public void setDiffuseConstant(float diffuseConstant) { if (diffuseConstant < 0f || diffuseConstant > 2f) { throw new IllegalArgumentException("Diffuse constant must be in the range [0,2]"); } float old = this.diffuseConstant; this.diffuseConstant = diffuseConstant; }
Returns the specular constant.
Returns:the specular constant value
/** * Returns the specular constant. * * @return the specular constant value */
public float getSpecularConstant() { return specularConstant; }
Sets the specular constant.
      Min: 0.0
      Max: 2.0
  Default: 1.0
 Identity: n/a
Params:
  • specularConstant – the specular constant value
Throws:
/** * Sets the specular constant. * <pre> * Min: 0.0 * Max: 2.0 * Default: 1.0 * Identity: n/a * </pre> * * @param specularConstant the specular constant value * @throws IllegalArgumentException if {@code specularConstant} is outside * the allowable range */
public void setSpecularConstant(float specularConstant) { if (specularConstant < 0f || specularConstant > 2f) { throw new IllegalArgumentException("Specular constant must be in the range [0,2]"); } float old = this.specularConstant; this.specularConstant = specularConstant; }
Returns the specular exponent.
Returns:the specular exponent value
/** * Returns the specular exponent. * * @return the specular exponent value */
public float getSpecularExponent() { return specularExponent; }
Sets the specular exponent.
      Min:  0.0
      Max: 40.0
  Default:  1.0
 Identity:  n/a
Params:
  • specularExponent – the specular exponent value
Throws:
/** * Sets the specular exponent. * <pre> * Min: 0.0 * Max: 40.0 * Default: 1.0 * Identity: n/a * </pre> * * @param specularExponent the specular exponent value * @throws IllegalArgumentException if {@code specularExponent} is outside * the allowable range */
public void setSpecularExponent(float specularExponent) { if (specularExponent < 0f || specularExponent > 40f) { throw new IllegalArgumentException("Specular exponent must be in the range [0,40]"); } float old = this.specularExponent; this.specularExponent = specularExponent; }
Returns the surface scale.
Returns:the surface scale value
/** * Returns the surface scale. * * @return the surface scale value */
public float getSurfaceScale() { return surfaceScale; }
Sets the surface scale.
      Min:  0.0
      Max: 10.0
  Default:  1.0
 Identity:  n/a
Params:
  • surfaceScale – the surface scale value
Throws:
/** * Sets the surface scale. * <pre> * Min: 0.0 * Max: 10.0 * Default: 1.0 * Identity: n/a * </pre> * * @param surfaceScale the surface scale value * @throws IllegalArgumentException if {@code surfaceScale} is outside * the allowable range */
public void setSurfaceScale(float surfaceScale) { if (surfaceScale < 0f || surfaceScale > 10f) { throw new IllegalArgumentException("Surface scale must be in the range [0,10]"); } float old = this.surfaceScale; this.surfaceScale = surfaceScale; } @Override public BaseBounds getBounds(BaseTransform transform, Effect defaultInput) { // effect inherits its bounds from the content input return getContentInput(defaultInput).getBounds(transform, defaultInput); } @Override public Rectangle getResultBounds(BaseTransform transform, Rectangle outputClip, ImageData... inputDatas) { // result inherits its dimensions from the content input return super.getResultBounds(transform, outputClip, inputDatas[1]); } @Override public Point2D transform(Point2D p, Effect defaultInput) { return getContentInput(defaultInput).transform(p, defaultInput); } @Override public Point2D untransform(Point2D p, Effect defaultInput) { return getContentInput(defaultInput).untransform(p, defaultInput); } @Override public RenderState getRenderState(FilterContext fctx, BaseTransform transform, Rectangle outputClip, Object renderHelper, Effect defaultInput) { // RT-27564 // TODO: Since only the content input is used for the output bounds // we could attempt to factor the bounds of the content input in our // answer for the getInputClip() method of the RenderState, but for // now we will just use (a close copy of) the stock RenderSpaceRenderState object. return new RenderState() { @Override public EffectCoordinateSpace getEffectTransformSpace() { return EffectCoordinateSpace.RenderSpace; } @Override public BaseTransform getInputTransform(BaseTransform filterTransform) { return filterTransform; } @Override public BaseTransform getResultTransform(BaseTransform filterTransform) { return BaseTransform.IDENTITY_TRANSFORM; } @Override public Rectangle getInputClip(int i, Rectangle filterClip) { if (i == 0 && filterClip != null) { Rectangle r = new Rectangle(filterClip); r.grow(1, 1); return r; } return filterClip; } }; } @Override public boolean reducesOpaquePixels() { final Effect contentInput = getContentInput(); return contentInput != null && contentInput.reducesOpaquePixels(); } @Override public DirtyRegionContainer getDirtyRegions(Effect defaultInput, DirtyRegionPool regionPool) { Effect bump = getDefaultedInput(0, defaultInput); DirtyRegionContainer drc1 = bump.getDirtyRegions(defaultInput, regionPool); drc1.grow(1, 1); Effect content = getDefaultedInput(1, defaultInput); DirtyRegionContainer drc2 = content.getDirtyRegions(defaultInput, regionPool); drc1.merge(drc2); regionPool.checkIn(drc2); return drc1; } }