From f8e0cedcdb24dba1fee451afd64735849dee8b13 Mon Sep 17 00:00:00 2001
From: Mathias Agopian
+ * At least one light must be added to a scene in order to see anything
+ * (unless the {@link Material.Shading#UNLIT} is used).
+ *
+ * A Light component is created using the {@link LightManager.Builder} and destroyed by calling
+ * {@link LightManager#destroy}.
+ *
+ * Directional lights have a direction, but don't have a position. All light rays are
+ * parallel and come from infinitely far away and from everywhere. Typically a directional light
+ * is used to simulate the sun.
+ *
+ * Directional lights and spot lights are able to cast shadows.
+ *
+ * To create a directional light use {@link Type#DIRECTIONAL} or {@link Type#SUN}, both are similar,
+ * but the later also draws a sun's disk in the sky and its reflection on glossy objects.
+ *
+ * warning: Currently, only a single directional light is supported. If several directional lights
+ * are added to the scene, the dominant one will be used.
+ *
+ * A scene can have multiple point lights.
+ *
+ * Spot lights are similar to point lights but the light they emit is limited to a cone defined by
+ * {@link Builder#spotLightCone} and the light's direction.
+ *
+ * A spot light is therefore defined by a position, a direction and inner and outer cones. The
+ * spot light's influence is limited to inside the outer cone. The inner cone defines the light's
+ * falloff attenuation.
+ * Creation and destruction
+ *
+ * Engine engine = Engine.create();
+ * int sun = EntityManager.get().create();
+ *
+ * LightManager.Builder(Type.SUN)
+ * .castShadows(true)
+ * .build(engine, sun);
+ *
+ * engine.getLightManager().destroy(sun);
+ *
+ *
+ * Light types
+ *
+ * Lights come in three flavors:
+ *
+ *
+ *
+ *
+ * Directional lights
+ * Point lights
+ *
+ * Unlike directional lights, point lights have a position but emit light in all directions.
+ * The intensity of the light diminishes with the inverse square of the distance to the light.
+ * {@link Builder#falloff} controls the distance beyond which the light has no more influence.
+ * Spot lights
+ *
+ * Generally, adding lights to the scene hurts performance, however filament is designed to be + * able to handle hundreds of lights in a scene under certain conditions. Here are some tips + * to keep good performance. + *
+ *+ * CAUTION: this parameter is ignored for all lights except the directional/sun light, + * all other lights use the same value set for the directional/sun light. + *
+ */ public int stepCount = 8; + + /** + * Maximum shadow-occluder distance for screen-space contact shadows (world units). + * (30 cm by default) + *+ * CAUTION: this parameter is ignored for all lights except the directional/sun light, + * all other lights use the same value set for the directional/sun light. + *
+ */ public float maxShadowDistance = 0.3f; } + + /** Typical efficiency of an incandescent light bulb (2.2%) */ public static final float EFFICIENCY_INCANDESCENT = 0.0220f; + + /** Typical efficiency of an halogen light bulb (7.0%) */ public static final float EFFICIENCY_HALOGEN = 0.0707f; + + /** Typical efficiency of a fluorescent light bulb (8.7%) */ public static final float EFFICIENCY_FLUORESCENT = 0.0878f; + + /** Typical efficiency of a LED light bulb (11.7%) */ public static final float EFFICIENCY_LED = 0.1171f; + /** + * Use Builder to construct a Light object instance + */ public static class Builder { @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources private final BuilderFinalizer mFinalizer; private final long mNativeBuilder; + /** + * Creates a light builder and set the light's {@link Type}. + * + * @param type {@link Type} of Light object to create. + */ public Builder(@NonNull Type type) { mNativeBuilder = nCreateBuilder(type.ordinal()); mFinalizer = new BuilderFinalizer(mNativeBuilder); } + /** + * Whether this Light casts shadows (disabled by default) + * + *+ * warning: + * {@link Type#POINT} lights cannot cast shadows. + *
+ * + * @param enable Enables or disables casting shadows from this Light. + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder castShadows(boolean enable) { nBuilderCastShadows(mNativeBuilder, enable); return this; } + /** + * Sets the shadow map options for this light. + * @param options A {@link ShadowOptions} instance + * @return This Builder, for chaining calls. + * @see ShadowOptions + */ @NonNull public Builder shadowOptions(@NonNull ShadowOptions options) { nBuilderShadowOptions(mNativeBuilder, @@ -95,72 +322,244 @@ public class LightManager { return this; } + /** + * Whether this light casts light (enabled by default) + * + *+ * In some situations it can be useful to have a light in the scene that doesn't + * actually emit light, but does cast shadows. + *
+ * + * @param enabled Enables or disables lighting from this Light. + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder castLight(boolean enabled) { nBuilderCastLight(mNativeBuilder, enabled); return this; } + /** + * Sets the initial position of the light in world space. + *+ * note: The Light's position is ignored for directional lights + * ({@link Type#DIRECTIONAL} or {@link Type#SUN}) + *
+ * + * @param x Light's position x coordinate in world space. The default is 0. + * @param y Light's position y coordinate in world space. The default is 0. + * @param z Light's position z coordinate in world space. The default is 0. + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder position(float x, float y, float z) { nBuilderPosition(mNativeBuilder, x, y, z); return this; } + /** + * Sets the initial direction of a light in world space. + *+ * The light direction is specified in world space and should be a unit vector. + *
+ *+ * note: The Light's direction is ignored for {@link Type#POINT} lights. + *
+ * + * @param x light's direction x coordinate (default is 0) + * @param y light's direction y coordinate (default is -1) + * @param z light's direction z coordinate (default is 0) + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder direction(float x, float y, float z) { nBuilderDirection(mNativeBuilder, x, y, z); return this; } + /** + * Sets the initial color of a light. + *+ * The light color is specified in the linear sRGB color-space. The default is white. + *
+ * + * @param linearR red component of the color (default is 1) + * @param linearG green component of the color (default is 1) + * @param linearB blue component of the color (default is 1) + * @return This Builder, for chaining calls. + * @see #setColor + */ @NonNull public Builder color(float linearR, float linearG, float linearB) { nBuilderColor(mNativeBuilder, linearR, linearG, linearB); return this; } + /** + * Sets the initial intensity of a light. + * + * @param intensity This parameter depends on the {@link Type}, for directional lights, + * it specifies the illuminance in lux (or lumen/m^2). + * For point lights and spot lights, it specifies the luminous power + * in lumen. For example, the sun's illuminance is about 100,000 + * lux. + * + * @return This Builder, for chaining calls. + * + * @see #setIntensity + */ @NonNull public Builder intensity(float intensity) { nBuilderIntensity(mNativeBuilder, intensity); return this; } + /** + * Sets the initial intensity of a light in watts. + * + *+ * Lightbulb type | Efficiency + * -----------------+------------ + * Incandescent | 2.2% + * Halogen | 7.0% + * LED | 8.7% + * Fluorescent | 10.7% + *+ * + * + * This call is equivalent to: + *
+ * Builder.intensity(efficiency * 683 * watts); + *+ * + * @param watts Energy consumed by a lightbulb. It is related to the energy produced + * and ultimately the brightness by the efficiency parameter. + * This value is often available on the packaging of commercial + * lightbulbs. + * + * @param efficiency Efficiency in percent. This depends on the type of lightbulb used. + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder intensity(float watts, float efficiency) { nBuilderIntensity(mNativeBuilder, watts, efficiency); return this; } + /** + * Set the falloff distance for point lights and spot lights. + *
+ * At the falloff distance, the light has no more effect on objects. + *
+ * + *+ * The falloff distance essentially defines a sphere of influence around the light, + * and therefore has an impact on performance. Larger falloffs might reduce performance + * significantly, especially when many lights are used. + *
+ * + *+ * Try to avoid having a large number of light's spheres of influence overlap. + *
+ * + * The Light's falloff is ignored for directional lights + * ({@link Type#DIRECTIONAL} or {@link Type#SUN}) + * + * @param radius Falloff distance in world units. Default is 1 meter. + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder falloff(float radius) { nBuilderFalloff(mNativeBuilder, radius); return this; } + /** + * Defines a spot light's angular falloff attenuation. + *+ * A spot light is defined by a position, a direction and two cones, inner and outer. + * These two cones are used to define the angular falloff attenuation of the spot light + * and are defined by the angle from the center axis to where the falloff begins (i.e. + * cones are defined by their half-angle). + *
+ *+ * note: The spot light cone is ignored for directional and point lights. + *
+ * + * @param inner inner cone angle in radian between 0 and pi/2 + * @param outer outer cone angle in radian between inner and pi/2 + * @return This Builder, for chaining calls. + * + * @see Type#SPOT + * @see Type#FOCUSED_SPOT + */ @NonNull public Builder spotLightCone(float inner, float outer) { nBuilderSpotLightCone(mNativeBuilder, inner, outer); return this; } + /** + * Defines the angular radius of the sun, in degrees, between 0.25° and 20.0° + * + * The Sun as seen from Earth has an angular size of 0.526° to 0.545° + * + * @param angularRadius sun's radius in degree. Default is 0.545°. + * @return This Builder, for chaining calls. + */ @NonNull public Builder sunAngularRadius(float angularRadius) { nBuilderAngularRadius(mNativeBuilder, angularRadius); return this; } + /** + * Defines the halo radius of the sun. The radius of the halo is defined as a + * multiplier of the sun angular radius. + * + * @param haloSize radius multiplier. Default is 10.0. + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder sunHaloSize(float haloSize) { nBuilderHaloSize(mNativeBuilder, haloSize); return this; } + /** + * Defines the halo falloff of the sun. The falloff is a dimensionless number + * used as an exponent. + * + * @param haloFalloff halo falloff. Default is 80.0. + * + * @return This Builder, for chaining calls. + */ @NonNull public Builder sunHaloFalloff(float haloFalloff) { nBuilderHaloFalloff(mNativeBuilder, haloFalloff); return this; } + /** + * Adds the Light component to an entity. + * + *+ * If this component already exists on the given entity, it is first destroyed as if + * {@link #destroy} was called. + *
+ * + * warning: + * Currently, only 2048 lights can be created on a given Engine. + * + * @param engine Reference to the {@link Engine} to associate this light with. + * @param entity Entity to add the light component to. + */ public void build(@NonNull Engine engine, @Entity int entity) { if (!nBuilderBuild(mNativeBuilder, engine.getNativeObject(), entity)) { throw new IllegalStateException( @@ -189,10 +588,63 @@ public class LightManager { return Type.values()[nGetType(mNativeObject, i)]; } + /** + * Helper function that returns if a light is a directional light + * + * @param i Instance of the component obtained from getInstance(). + * @return true is this light is a type of directional light + */ + boolean isDirectional(@EntityInstance int i) { + Type type = getType(i); + return type == Type.DIRECTIONAL || type == Type.SUN; + } + + /** + * Helper function that returns if a light is a point light + * + * @param i Instance of the component obtained from getInstance(). + * @return true is this light is a type of point light + */ + boolean isPointLight(@EntityInstance int i) { + return getType(i) == Type.POINT; + } + + /** + * Helper function that returns if a light is a spot light + * + * @param i Instance of the component obtained from getInstance(). + * @return true is this light is a type of spot light + */ + boolean isSpotLight(@EntityInstance int i) { + Type type = getType(i); + return type == Type.SPOT || type == Type.FOCUSED_SPOT; + } + + /** + * Dynamically updates the light's position. + * + *+ * note: The Light's position is ignored for directional lights + * ({@link Type#DIRECTIONAL} or {@link Type#SUN}) + *
+ * + * @param i Instance of the component obtained from getInstance(). + * @param x Light's position x coordinate in world space. The default is 0. + * @param y Light's position y coordinate in world space. The default is 0. + * @param z Light's position z coordinate in world space. The default is 0. + * + * @see Builder#position + */ public void setPosition(@EntityInstance int i, float x, float y, float z) { nSetPosition(mNativeObject, i, x, y, z); } + /** + * returns the light's position in world space + * @param i Instance of the component obtained from getInstance(). + * @param out An array of 3 float to receive the result or null. + * @return An array of 3 float containing the light's position coordinates. + */ @NonNull public float[] getPosition(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) { out = Asserts.assertFloat3(out); @@ -200,10 +652,33 @@ public class LightManager { return out; } + /** + * Dynamically updates the light's direction + * + *+ * The light direction is specified in world space and should be a unit vector. + *
+ *+ * note: The Light's direction is ignored for {@link Type#POINT} lights. + *
+ * + * @param i Instance of the component obtained from getInstance(). + * @param x light's direction x coordinate (default is 0) + * @param y light's direction y coordinate (default is -1) + * @param z light's direction z coordinate (default is 0) + * + * @see Builder#direction + */ public void setDirection(@EntityInstance int i, float x, float y, float z) { nSetDirection(mNativeObject, i, x, y, z); } + /** + * returns the light's direction in world space + * @param i Instance of the component obtained from getInstance(). + * @param out An array of 3 float to receive the result or null. + * @return An array of 3 float containing the light's direction. + */ @NonNull public float[] getDirection(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) { out = Asserts.assertFloat3(out); @@ -211,10 +686,26 @@ public class LightManager { return out; } + /** + * Dynamically updates the light's hue as linear sRGB + * + * @param i Instance of the component obtained from getInstance(). + * @param linearR red component of the color (default is 1) + * @param linearG green component of the color (default is 1) + * @param linearB blue component of the color (default is 1) + * + * @see Builder#color + * @see #getInstance + */ public void setColor(@EntityInstance int i, float linearR, float linearG, float linearB) { nSetColor(mNativeObject, i, linearR, linearG, linearB); } + /** + * Returns the light color + * @param i Instance of the component obtained from getInstance(). + * @return An array of 3 float containing the light's color in linear sRGB + */ @NonNull public float[] getColor(@EntityInstance int i, @Nullable @Size(min = 3) float[] out) { out = Asserts.assertFloat3(out); @@ -222,58 +713,183 @@ public class LightManager { return out; } + /** + * Dynamically updates the light's intensity. The intensity can be negative. + * + * @param i Instance of the component obtained from getInstance(). + * @param intensity This parameter depends on the {@link Type}, for directional lights, + * it specifies the illuminance in lux (or lumen/m^2). + * For point lights and spot lights, it specifies the luminous power + * in lumen. For example, the sun's illuminance is about 100,000 + * lux. + * + * @see Builder#intensity + */ public void setIntensity(@EntityInstance int i, float intensity) { nSetIntensity(mNativeObject, i , intensity); } + /** + * Dynamically updates the light's intensity. The intensity can be negative. + * + *+ * Lightbulb type | Efficiency + * -----------------+------------ + * Incandescent | 2.2% + * Halogen | 7.0% + * LED | 8.7% + * Fluorescent | 10.7% + *+ * + * + * This call is equivalent to: + *
+ * Builder.intensity(efficiency * 683 * watts); + *+ * + * @param i Instance of the component obtained from getInstance(). + * + * @param watts Energy consumed by a lightbulb. It is related to the energy produced + * and ultimately the brightness by the efficiency parameter. + * This value is often available on the packaging of commercial + * lightbulbs. + * + * @param efficiency Efficiency in percent. This depends on the type of lightbulb used. + * + * @return This Builder, for chaining calls. + */ public void setIntensity(@EntityInstance int i, float watts, float efficiency) { nSetIntensity(mNativeObject, i , watts, efficiency); } + /** + * returns the light's luminous intensity in lumens. + *
+ * note: for {@link Type#FOCUSED_SPOT} lights, the returned value depends on the outer cone angle. + *
+ * + * @param i Instance of the component obtained from getInstance(). + * + * @return luminous intensity in lumen. + */ public float getIntensity(@EntityInstance int i) { return nGetIntensity(mNativeObject, i); } + /** + * Set the falloff distance for point lights and spot lights. + * + * @param i Instance of the component obtained from getInstance(). + * @param falloff falloff distance in world units. Default is 1 meter. + * + * @see Builder#falloff + */ public void setFalloff(@EntityInstance int i, float falloff) { nSetFalloff(mNativeObject, i, falloff); } + /** + * returns the falloff distance of this light. + * @param i Instance of the component obtained from getInstance(). + * @return the falloff distance of this light. + */ public float getFalloff(@EntityInstance int i) { return nGetFalloff(mNativeObject, i); } + /** + * Dynamically updates a spot light's cone as angles + * + * @param i Instance of the component obtained from getInstance(). + * @param inner inner cone angle in *radians* between 0 and pi/2 + * @param outer outer cone angle in *radians* between inner and pi/2 + * + * @see Builder#spotLightCone + */ public void setSpotLightCone(@EntityInstance int i, float inner, float outer) { nSetSpotLightCone(mNativeObject, i, inner, outer); } + /** + * Dynamically updates the angular radius of a Type.SUN light + * + * The Sun as seen from Earth has an angular size of 0.526° to 0.545° + * + * @param i Instance of the component obtained from getInstance(). + * @param angularRadius sun's radius in degrees. Default is 0.545°. + */ public void setSunAngularRadius(@EntityInstance int i, float angularRadius) { nSetSunAngularRadius(mNativeObject, i, angularRadius); } + /** + * returns the angular radius if the sun in degrees. + * @param i Instance of the component obtained from getInstance(). + * @return the angular radius if the sun in degrees. + */ public float getSunAngularRadius(@EntityInstance int i) { return nGetSunAngularRadius(mNativeObject, i); } + /** + * Dynamically updates the halo radius of a Type.SUN light. The radius + * of the halo is defined as a multiplier of the sun angular radius. + * + * @param i Instance of the component obtained from getInstance(). + * @param haloSize radius multiplier. Default is 10.0. + */ public void setSunHaloSize(@EntityInstance int i, float haloSize) { nSetSunHaloSize(mNativeObject, i, haloSize); } + /** + * returns the halo size of a Type.SUN light as a multiplier of the + * sun angular radius. + * @param i Instance of the component obtained from getInstance(). + * @return the halo size + */ public float getSunHaloSize(@EntityInstance int i) { return nGetSunHaloSize(mNativeObject, i); } + /** + * Dynamically updates the halo falloff of a Type.SUN light. The falloff + * is a dimensionless number used as an exponent. + * + * @param i Instance of the component obtained from getInstance(). + * @param haloFalloff halo falloff. Default is 80.0. + */ public void setSunHaloFalloff(@EntityInstance int i, float haloFalloff) { nSetSunHaloFalloff(mNativeObject, i, haloFalloff); } + /** + * returns the halo falloff of a Type.SUN light as a dimensionless value. + * @param i Instance of the component obtained from getInstance(). + * @return the halo falloff + */ public float getSunHaloFalloff(@EntityInstance int i) { return nGetSunHaloFalloff(mNativeObject, i); } + /** + * Whether this Light casts shadows (disabled by default) + * + *+ * warning: {@link Type#POINT} cannot cast shadows. + *
+ * + * @param i Instance of the component obtained from getInstance(). + * @param shadowCaster Enables or disables casting shadows from this Light. + */ public void setShadowCaster(@EntityInstance int i, boolean shadowCaster) { nSetShadowCaster(mNativeObject, i, shadowCaster); } + /** + * returns whether this light casts shadows. + * @param i Instance of the component obtained from getInstance(). + */ public boolean isShadowCaster(@EntityInstance int i) { return nIsShadowCaster(mNativeObject, i); } diff --git a/filament/include/filament/LightManager.h b/filament/include/filament/LightManager.h index 1e1421d660..f451245725 100644 --- a/filament/include/filament/LightManager.h +++ b/filament/include/filament/LightManager.h @@ -430,9 +430,9 @@ public: * cones are defined by their half-angle). * * @param inner inner cone angle in *radians* between 0 and @f$ \pi/2 @f$ - + * * @param outer outer cone angle in *radians* between \p inner and @f$ \pi/2 @f$ - + * * @return This Builder, for chaining calls. * * @note @@ -448,7 +448,7 @@ public: * The Sun as seen from Earth has an angular size of 0.526° to 0.545° * * @param angularRadius sun's radius in degree. Default is 0.545°. - + * * @return This Builder, for chaining calls. */ Builder& sunAngularRadius(float angularRadius) noexcept; @@ -654,8 +654,8 @@ public: * Dynamically updates a spot light's cone as angles * * @param i Instance of the component obtained from getInstance(). - * @param inner inner cone angle in *radians* between 0 and @f$ \pi @f$ - * @param outer outer cone angle in *radians* between 0 and @f$ \pi @f$ + * @param inner inner cone angle in *radians* between 0 and pi/2 + * @param outer outer cone angle in *radians* between inner and pi/2 * * @see Builder.spotLightCone() */