diff --git a/.idea/misc.xml b/.idea/misc.xml
index ac8fa666b5..6548e9d6d2 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,11 +1,7 @@
-
-
-
-
diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/PointLightHelper.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/PointLightHelper.java
index fac2ef6d3d..098b4f7cf8 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/PointLightHelper.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/scene/PointLightHelper.java
@@ -56,6 +56,12 @@ protected NGNode createPeerImpl(Node node) {
return pointLightAccessor.doCreatePeer(node);
}
+ @Override
+ protected void updatePeerImpl(Node node) {
+ super.updatePeerImpl(node);
+ pointLightAccessor.doUpdatePeer(node);
+ }
+
public static void setPointLightAccessor(final PointLightAccessor newAccessor) {
if (pointLightAccessor != null) {
throw new IllegalStateException();
@@ -66,7 +72,7 @@ public static void setPointLightAccessor(final PointLightAccessor newAccessor) {
public interface PointLightAccessor {
NGNode doCreatePeer(Node node);
+ void doUpdatePeer(Node node);
}
}
-
diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGPointLight.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGPointLight.java
index 3495aeaece..66303d2092 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGPointLight.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGPointLight.java
@@ -26,11 +26,85 @@
package com.sun.javafx.sg.prism;
/**
- * TODO: 3D - Need documentation
+ * The peer of the {@code PointLight} class. Holds the default values of {@code PointLight}'s
+ * properties and updates the visuals via {@link NGNode#visualsChanged} when one of the current
+ * values changes. The peer receives its changes by {@code PointLight.doUpdatePeer} calls.
*/
public class NGPointLight extends NGLightBase {
+ /** Constant attenuation factor default value */
+ private static final double DEFAULT_CA = 1;
+ /** Linear attenuation factor default value */
+ private static final double DEFAULT_LA = 0;
+ /** Quadratic attenuation factor default value */
+ private static final double DEFAULT_QA = 0;
+ /** Max range default value */
+ private static final double DEFAULT_MAX_RANGE = Double.POSITIVE_INFINITY;
+
public NGPointLight() {
}
+ public static double getDefaultCa() {
+ return DEFAULT_CA;
+ }
+
+ public static double getDefaultLa() {
+ return DEFAULT_LA;
+ }
+
+ public static double getDefaultQa() {
+ return DEFAULT_QA;
+ }
+
+ public static double getDefaultMaxRange() {
+ return DEFAULT_MAX_RANGE;
+ }
+
+
+ private double ca = DEFAULT_CA;
+
+ public double getCa() {
+ return ca;
+ }
+
+ public void setCa(double ca) {
+ this.ca = ca;
+ visualsChanged();
+ }
+
+
+ private double la = DEFAULT_LA;
+
+ public double getLa() {
+ return la;
+ }
+
+ public void setLa(double la) {
+ this.la = la;
+ visualsChanged();
+ }
+
+
+ private double qa = DEFAULT_QA;
+
+ public double getQa() {
+ return qa;
+ }
+
+ public void setQa(double qa) {
+ this.qa = qa;
+ visualsChanged();
+ }
+
+
+ private double maxRange = DEFAULT_MAX_RANGE;
+
+ public double getMaxRange() {
+ return maxRange;
+ }
+
+ public void setMaxRange(double maxRange) {
+ this.maxRange = maxRange < 0 ? 0 : maxRange;
+ visualsChanged();
+ }
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGShape3D.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGShape3D.java
index bc42b78b1a..80cac380f5 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGShape3D.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/sg/prism/NGShape3D.java
@@ -109,14 +109,18 @@ private void renderMeshView(Graphics g) {
int pointLightIdx = 0;
if (g.getLights() == null || g.getLights()[0] == null) {
// If no lights are in scene apply default light. Default light
- // is a single point white point light at camera eye position.
+ // is a single white point light at camera eye position.
meshView.setAmbientLight(0.0f, 0.0f, 0.0f);
Vec3d cameraPos = g.getCameraNoClone().getPositionInWorld(null);
meshView.setPointLight(pointLightIdx++,
- (float)cameraPos.x,
- (float)cameraPos.y,
- (float)cameraPos.z,
- 1.0f, 1.0f, 1.0f, 1.0f);
+ (float)cameraPos.x,
+ (float)cameraPos.y,
+ (float)cameraPos.z,
+ 1.0f, 1.0f, 1.0f, 1.0f,
+ (float) NGPointLight.getDefaultCa(),
+ (float) NGPointLight.getDefaultLa(),
+ (float) NGPointLight.getDefaultQa(),
+ (float) NGPointLight.getDefaultMaxRange());
} else {
float ambientRed = 0.0f;
float ambientBlue = 0.0f;
@@ -132,7 +136,7 @@ private void renderMeshView(Graphics g) {
float gL = lightBase.getColor().getGreen();
float bL = lightBase.getColor().getBlue();
/* TODO: 3D
- * There is a limit on the number of lights that can affect
+ * There is a limit on the number of point lights that can affect
* a 3D shape. (Currently we simply select the first 3)
* Thus it is important to select the most relevant lights.
*
@@ -155,7 +159,11 @@ private void renderMeshView(Graphics g) {
(float)lightWT.getMxt(),
(float)lightWT.getMyt(),
(float)lightWT.getMzt(),
- rL, gL, bL, 1.0f);
+ rL, gL, bL, 1.0f,
+ (float) light.getCa(),
+ (float) light.getLa(),
+ (float) light.getQa(),
+ (float) light.getMaxRange());
}
} else if (lightBase instanceof NGAmbientLight) {
// Accumulate ambient lights
@@ -172,8 +180,11 @@ private void renderMeshView(Graphics g) {
}
// TODO: 3D Required for D3D implementation of lights, which is limited to 3
while (pointLightIdx < 3) {
- // Reset any previously set lights
- meshView.setPointLight(pointLightIdx++, 0, 0, 0, 0, 0, 0, 0);
+ // Reset any previously set lights
+ meshView.setPointLight(pointLightIdx++,
+ 0, 0, 0, // x y z
+ 0, 0, 0, 0, // r g b w
+ 1, 0, 0, 0); // ca la qa maxRange
}
meshView.render(g);
@@ -193,8 +204,8 @@ public void setMesh(NGTriangleMesh triangleMesh) {
@Override
protected void renderContent(Graphics g) {
if (!Platform.isSupported(ConditionalFeature.SCENE3D) ||
- material == null ||
- g instanceof com.sun.prism.PrinterGraphics)
+ material == null ||
+ g instanceof com.sun.prism.PrinterGraphics)
{
return;
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java
index 86e101e959..eccd613846 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/javafx/tk/Toolkit.java
@@ -28,7 +28,6 @@
import javafx.application.ConditionalFeature;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.geometry.Dimension2D;
-import javafx.scene.Scene;
import javafx.scene.effect.BlurType;
import javafx.scene.image.Image;
import javafx.scene.image.PixelFormat;
@@ -51,11 +50,9 @@
import javafx.scene.shape.StrokeType;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Modality;
-import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.security.AccessControlContext;
@@ -63,7 +60,6 @@
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -82,7 +78,6 @@
import com.sun.javafx.runtime.VersionInfo;
import com.sun.javafx.runtime.async.AsyncOperation;
import com.sun.javafx.runtime.async.AsyncOperationListener;
-import com.sun.javafx.scene.SceneHelper;
import com.sun.javafx.scene.text.TextLayoutFactory;
import com.sun.javafx.sg.prism.NGCamera;
import com.sun.javafx.sg.prism.NGLightBase;
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/MeshView.java b/modules/javafx.graphics/src/main/java/com/sun/prism/MeshView.java
index 489ad70e6b..d831d37d23 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/MeshView.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/MeshView.java
@@ -46,9 +46,9 @@ public interface MeshView {
public void setAmbientLight(float r, float g, float b);
- public void setPointLight(int index,
- float x, float y, float z,
- float r, float g, float b, float w);
+ public void setPointLight(int index, float x, float y, float z,
+ float r, float g, float b, float w,
+ float ca, float la, float qa, float maxRange);
public void render(Graphics g);
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DContext.java b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DContext.java
index 3dc9080e10..e6ba86ffc1 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DContext.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DContext.java
@@ -233,10 +233,10 @@ protected State updateRenderTarget(RenderTarget target, NGCamera camera,
// Set projection view matrix
res = nSetProjViewMatrix(pContext, depthTest,
- projViewTx.get(0), projViewTx.get(1), projViewTx.get(2), projViewTx.get(3),
- projViewTx.get(4), projViewTx.get(5), projViewTx.get(6), projViewTx.get(7),
- projViewTx.get(8), projViewTx.get(9), projViewTx.get(10), projViewTx.get(11),
- projViewTx.get(12), projViewTx.get(13), projViewTx.get(14), projViewTx.get(15));
+ projViewTx.get(0), projViewTx.get(1), projViewTx.get(2), projViewTx.get(3),
+ projViewTx.get(4), projViewTx.get(5), projViewTx.get(6), projViewTx.get(7),
+ projViewTx.get(8), projViewTx.get(9), projViewTx.get(10), projViewTx.get(11),
+ projViewTx.get(12), projViewTx.get(13), projViewTx.get(14), projViewTx.get(15));
validate(res);
cameraPos = camera.getPositionInWorld(cameraPos);
@@ -293,17 +293,17 @@ protected void updateShaderTransform(Shader shader, BaseTransform xform) {
res = nResetTransform(pContext);
} else if (perspectiveTransform.isIdentity()) {
res = nSetTransform(pContext,
- xform.getMxx(), xform.getMxy(), xform.getMxz(), xform.getMxt(),
- xform.getMyx(), xform.getMyy(), xform.getMyz(), xform.getMyt(),
- xform.getMzx(), xform.getMzy(), xform.getMzz(), xform.getMzt(),
- 0.0, 0.0, 0.0, 1.0);
+ xform.getMxx(), xform.getMxy(), xform.getMxz(), xform.getMxt(),
+ xform.getMyx(), xform.getMyy(), xform.getMyz(), xform.getMyt(),
+ xform.getMzx(), xform.getMzy(), xform.getMzz(), xform.getMzt(),
+ 0.0, 0.0, 0.0, 1.0);
} else {
scratchTx.setIdentity().mul(xform).mul(perspectiveTransform);
res = nSetTransform(pContext,
- scratchTx.get(0), scratchTx.get(1), scratchTx.get(2), scratchTx.get(3),
- scratchTx.get(4), scratchTx.get(5), scratchTx.get(6), scratchTx.get(7),
- scratchTx.get(8), scratchTx.get(9), scratchTx.get(10), scratchTx.get(11),
- scratchTx.get(12), scratchTx.get(13), scratchTx.get(14), scratchTx.get(15));
+ scratchTx.get(0), scratchTx.get(1), scratchTx.get(2), scratchTx.get(3),
+ scratchTx.get(4), scratchTx.get(5), scratchTx.get(6), scratchTx.get(7),
+ scratchTx.get(8), scratchTx.get(9), scratchTx.get(10), scratchTx.get(11),
+ scratchTx.get(12), scratchTx.get(13), scratchTx.get(14), scratchTx.get(15));
}
validate(res);
}
@@ -374,28 +374,28 @@ D3DFrameStats getFrameStats(boolean reset, D3DFrameStats result) {
*/
private static native int nSetRenderTarget(long pContext, long pDest, boolean depthBuffer, boolean msaa);
private static native int nSetTexture(long pContext, long pTex, int texUnit,
- boolean linear, int wrapMode);
+ boolean linear, int wrapMode);
private static native int nResetTransform(long pContext);
private static native int nSetTransform(long pContext,
- double m00, double m01, double m02, double m03,
- double m10, double m11, double m12, double m13,
- double m20, double m21, double m22, double m23,
- double m30, double m31, double m32, double m33);
+ double m00, double m01, double m02, double m03,
+ double m10, double m11, double m12, double m13,
+ double m20, double m21, double m22, double m23,
+ double m30, double m31, double m32, double m33);
private static native void nSetWorldTransformToIdentity(long pContext);
private static native void nSetWorldTransform(long pContext,
- double m00, double m01, double m02, double m03,
- double m10, double m11, double m12, double m13,
- double m20, double m21, double m22, double m23,
- double m30, double m31, double m32, double m33);
+ double m00, double m01, double m02, double m03,
+ double m10, double m11, double m12, double m13,
+ double m20, double m21, double m22, double m23,
+ double m30, double m31, double m32, double m33);
private static native int nSetCameraPosition(long pContext, double x, double y, double z);
private static native int nSetProjViewMatrix(long pContext, boolean isOrtho,
- double m00, double m01, double m02, double m03,
- double m10, double m11, double m12, double m13,
- double m20, double m21, double m22, double m23,
- double m30, double m31, double m32, double m33);
+ double m00, double m01, double m02, double m03,
+ double m10, double m11, double m12, double m13,
+ double m20, double m21, double m22, double m23,
+ double m30, double m31, double m32, double m33);
private static native int nResetClipRect(long pContext);
private static native int nSetClipRect(long pContext,
- int x1, int y1, int x2, int y2);
+ int x1, int y1, int x2, int y2);
private static native int nSetBlendEnabled(long pContext, int mode);
private static native int nSetDeviceParametersFor2D(long pContext);
private static native int nSetDeviceParametersFor3D(long pContext);
@@ -403,32 +403,33 @@ private static native int nSetClipRect(long pContext,
private static native long nCreateD3DMesh(long pContext);
private static native void nReleaseD3DMesh(long pContext, long nativeHandle);
private static native boolean nBuildNativeGeometryShort(long pContext, long nativeHandle,
- float[] vertexBuffer, int vertexBufferLength, short[] indexBuffer, int indexBufferLength);
+ float[] vertexBuffer, int vertexBufferLength, short[] indexBuffer, int indexBufferLength);
private static native boolean nBuildNativeGeometryInt(long pContext, long nativeHandle,
- float[] vertexBuffer, int vertexBufferLength, int[] indexBuffer, int indexBufferLength);
+ float[] vertexBuffer, int vertexBufferLength, int[] indexBuffer, int indexBufferLength);
private static native long nCreateD3DPhongMaterial(long pContext);
private static native void nReleaseD3DPhongMaterial(long pContext, long nativeHandle);
private static native void nSetDiffuseColor(long pContext, long nativePhongMaterial,
- float r, float g, float b, float a);
+ float r, float g, float b, float a);
private static native void nSetSpecularColor(long pContext, long nativePhongMaterial,
- boolean set, float r, float g, float b, float a);
+ boolean set, float r, float g, float b, float a);
private static native void nSetMap(long pContext, long nativePhongMaterial,
- int mapType, long texID);
+ int mapType, long texID);
private static native long nCreateD3DMeshView(long pContext, long nativeMesh);
private static native void nReleaseD3DMeshView(long pContext, long nativeHandle);
private static native void nSetCullingMode(long pContext, long nativeMeshView,
- int cullingMode);
+ int cullingMode);
private static native void nSetMaterial(long pContext, long nativeMeshView,
- long nativePhongMaterialInfo);
+ long nativePhongMaterialInfo);
private static native void nSetWireframe(long pContext, long nativeMeshView,
- boolean wireframe);
+ boolean wireframe);
private static native void nSetAmbientLight(long pContext, long nativeMeshView,
- float r, float g, float b);
+ float r, float g, float b);
private static native void nSetPointLight(long pContext, long nativeMeshView,
- int index, float x, float y, float z, float r, float g, float b, float w);
+ int index, float x, float y, float z, float r, float g, float b, float w,
+ float ca, float la, float qa, float maxRange);
private static native void nRenderMeshView(long pContext, long nativeMeshView);
private static native int nDrawIndexedQuads(long pContext,
- float coords[], byte colors[], int numVertices);
+ float coords[], byte colors[], int numVertices);
/*
@@ -436,11 +437,11 @@ private static native int nDrawIndexedQuads(long pContext,
* @param nDstRTT can be NULL if a valide render target is set
*/
private static native void nBlit(long pContext, long nSrcRTT, long nDstRTT,
- int srcX0, int srcY0, int srcX1, int srcY1,
- int dstX0, int dstY0, int dstX1, int dstY1);
+ int srcX0, int srcY0, int srcX1, int srcY1,
+ int dstX0, int dstY0, int dstX1, int dstY1);
private static native boolean nGetFrameStats(long pContext,
- D3DFrameStats returnValue, boolean bReset);
+ D3DFrameStats returnValue, boolean bReset);
private static native boolean nIsRTTVolatile(long contextHandle);
@@ -483,13 +484,13 @@ void releaseD3DMesh(long nativeHandle) {
}
boolean buildNativeGeometry(long nativeHandle, float[] vertexBuffer, int vertexBufferLength,
- short[] indexBuffer, int indexBufferLength) {
+ short[] indexBuffer, int indexBufferLength) {
return nBuildNativeGeometryShort(pContext, nativeHandle, vertexBuffer,
vertexBufferLength, indexBuffer, indexBufferLength);
}
boolean buildNativeGeometry(long nativeHandle, float[] vertexBuffer, int vertexBufferLength,
- int[] indexBuffer, int indexBufferLength) {
+ int[] indexBuffer, int indexBufferLength) {
return nBuildNativeGeometryInt(pContext, nativeHandle, vertexBuffer,
vertexBufferLength, indexBuffer, indexBufferLength);
}
@@ -543,15 +544,16 @@ void setMaterial(long nativeMeshView, long nativePhongMaterial) {
}
void setWireframe(long nativeMeshView, boolean wireframe) {
- nSetWireframe(pContext, nativeMeshView, wireframe);
+ nSetWireframe(pContext, nativeMeshView, wireframe);
}
void setAmbientLight(long nativeMeshView, float r, float g, float b) {
nSetAmbientLight(pContext, nativeMeshView, r, g, b);
}
- void setPointLight(long nativeMeshView, int index, float x, float y, float z, float r, float g, float b, float w) {
- nSetPointLight(pContext, nativeMeshView, index, x, y, z, r, g, b, w);
+ void setPointLight(long nativeMeshView, int index, float x, float y, float z,
+ float r, float g, float b, float w, float ca, float la, float qa, float maxRange) {
+ nSetPointLight(pContext, nativeMeshView, index, x, y, z, r, g, b, w, ca, la, qa, maxRange);
}
@Override
@@ -603,7 +605,7 @@ public void blit(RTTexture srcRTT, RTTexture dstRTT,
long dstNativeHandle = dstRTT == null ? 0L : ((D3DTexture)dstRTT).getNativeSourceHandle();
long srcNativeHandle = ((D3DTexture)srcRTT).getNativeSourceHandle();
nBlit(pContext, srcNativeHandle, dstNativeHandle,
- srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1);
+ srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1);
}
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DMeshView.java b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DMeshView.java
index 08b0056747..85c0eed1aa 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DMeshView.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/d3d/D3DMeshView.java
@@ -45,7 +45,7 @@ class D3DMeshView extends BaseMeshView {
private D3DPhongMaterial material;
private D3DMeshView(D3DContext context, long nativeHandle, D3DMesh mesh,
- Disposer.Record disposerRecord) {
+ Disposer.Record disposerRecord) {
super(disposerRecord);
this.context = context;
this.mesh = mesh;
@@ -81,10 +81,11 @@ public void setAmbientLight(float r, float g, float b) {
}
@Override
- public void setPointLight(int index, float x, float y, float z, float r, float g, float b, float w) {
+ public void setPointLight(int index, float x, float y, float z, float r, float g, float b, float w,
+ float ca, float la, float qa, float maxRange) {
// NOTE: We only support up to 3 point lights at the present
if (index >= 0 && index <= 2) {
- context.setPointLight(nativeHandle, index, x, y, z, r, g, b, w);
+ context.setPointLight(nativeHandle, index, x, y, z, r, g, b, w, ca, la, qa, maxRange);
}
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Context.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Context.java
index 41f1e5b819..eccad0ab55 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Context.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Context.java
@@ -449,8 +449,8 @@ void setAmbientLight(long nativeHandle, float r, float g, float b) {
glContext.setAmbientLight(nativeHandle, r, g, b);
}
- void setPointLight(long nativeHandle, int index, float x, float y, float z, float r, float g, float b, float w) {
- glContext.setPointLight(nativeHandle, index, x, y, z, r, g, b, w);
+ void setPointLight(long nativeHandle, int index, float x, float y, float z, float r, float g, float b, float w, float ra, float ca, float la, float qa) {
+ glContext.setPointLight(nativeHandle, index, x, y, z, r, g, b, w, ra, ca, la, qa);
}
@Override
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Light.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Light.java
index b593985914..1fd58272fa 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Light.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2Light.java
@@ -32,8 +32,14 @@ class ES2Light {
float x, y, z = 0;
float r, g, b, w = 1;
+ float range, ca = 1.0f;
+ float la, qa = 0.0f;
ES2Light(float ix, float iy, float iz, float ir, float ig, float ib, float iw) {
+ this(ix, iy, iz, ir, ig, ib, iw, 1.0f, 1.0f, 0.0f, 0.0f);
+ }
+
+ ES2Light(float ix, float iy, float iz, float ir, float ig, float ib, float iw, float irange, float ica, float ila, float iqa) {
x = ix;
y = iy;
z = iz;
@@ -41,5 +47,9 @@ class ES2Light {
g = ig;
b = ib;
w = iw;
+ range = irange;
+ ca = ica;
+ la = ila;
+ qa = iqa;
}
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2MeshView.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2MeshView.java
index eaf70e2b94..e4f8dd01d4 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2MeshView.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2MeshView.java
@@ -101,11 +101,12 @@ float getAmbientLightBlue() {
}
@Override
- public void setPointLight(int index, float x, float y, float z, float r, float g, float b, float w) {
+ public void setPointLight(int index, float x, float y, float z, float r, float g, float b, float w,
+ float ca, float la, float qa, float maxRange) {
// NOTE: We only support up to 3 point lights at the present
if (index >= 0 && index <= 2) {
- lights[index] = new ES2Light(x, y, z, r, g, b, w);
- context.setPointLight(nativeHandle, index, x, y, z, r, g, b, w);
+ lights[index] = new ES2Light(x, y, z, r, g, b, w, maxRange, ca, la, qa);
+ context.setPointLight(nativeHandle, index, x, y, z, r, g, b, w, maxRange, ca, la, qa);
}
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2PhongShader.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2PhongShader.java
index a9c5360f23..552a40b0f6 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2PhongShader.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/ES2PhongShader.java
@@ -208,6 +208,7 @@ static void setShaderParamaters(ES2Shader shader, ES2MeshView meshView, ES2Conte
if (light != null && light.w > 0) {
shader.setConstant("lights[" + i + "].pos", light.x, light.y, light.z, light.w);
shader.setConstant("lights[" + i + "].color", light.r, light.g, light.b);
+ shader.setConstant("lights[" + i + "].atten", light.range, light.ca, light.la, light.qa);
i++;
}
}
diff --git a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java
index 9a38b5fa47..b394040da0 100644
--- a/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java
+++ b/modules/javafx.graphics/src/main/java/com/sun/prism/es2/GLContext.java
@@ -252,7 +252,7 @@ private static native void nSetWireframe(long nativeCtxInfo, long nativeMeshView
private static native void nSetAmbientLight(long nativeCtxInfo, long nativeMeshViewInfo,
float r, float g, float b);
private static native void nSetPointLight(long nativeCtxInfo, long nativeMeshViewInfo,
- int index, float x, float y, float z, float r, float g, float b, float w);
+ int index, float x, float y, float z, float r, float g, float b, float w, float ra, float ca, float la, float qa);
private static native void nRenderMeshView(long nativeCtxInfo, long nativeMeshViewInfo);
private static native void nBlit(long nativeCtxInfo, int srcFBO, int dstFBO,
int srcX0, int srcY0, int srcX1, int srcY1,
@@ -808,8 +808,8 @@ void setAmbientLight(long nativeMeshViewInfo, float r, float g, float b) {
nSetAmbientLight(nativeCtxInfo, nativeMeshViewInfo, r, g, b);
}
- void setPointLight(long nativeMeshViewInfo, int index, float x, float y, float z, float r, float g, float b, float w) {
- nSetPointLight(nativeCtxInfo, nativeMeshViewInfo, index, x, y, z, r, g, b, w);
+ void setPointLight(long nativeMeshViewInfo, int index, float x, float y, float z, float r, float g, float b, float w, float ra, float ca, float la, float qa) {
+ nSetPointLight(nativeCtxInfo, nativeMeshViewInfo, index, x, y, z, r, g, b, w, ra, ca, la, qa);
}
void renderMeshView(long nativeMeshViewInfo) {
diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/LightBase.java b/modules/javafx.graphics/src/main/java/javafx/scene/LightBase.java
index 812fce3a34..53ed2bc92e 100644
--- a/modules/javafx.graphics/src/main/java/javafx/scene/LightBase.java
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/LightBase.java
@@ -41,8 +41,10 @@
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
@@ -71,8 +73,8 @@
*/
public abstract class LightBase extends Node {
static {
- // This is used by classes in different packages to get access to
- // private and package private methods.
+ // This is used by classes in different packages to get access to
+ // private and package private methods.
LightBaseHelper.setLightBaseAccessor(new LightBaseHelper.LightBaseAccessor() {
@Override
public void doMarkDirty(Node node, DirtyBits dirtyBit) {
@@ -86,7 +88,7 @@ public void doUpdatePeer(Node node) {
@Override
public BaseBounds doComputeGeomBounds(Node node,
- BaseBounds bounds, BaseTransform tx) {
+ BaseBounds bounds, BaseTransform tx) {
return ((LightBase) node).doComputeGeomBounds(bounds, tx);
}
@@ -120,7 +122,7 @@ protected LightBase(Color color) {
if (!Platform.isSupported(ConditionalFeature.SCENE3D)) {
String logname = LightBase.class.getName();
PlatformLogger.getLogger(logname).warning("System can't support "
- + "ConditionalFeature.SCENE3D");
+ + "ConditionalFeature.SCENE3D");
}
setColor(color);
@@ -238,6 +240,20 @@ void scenesChanged(final Scene newScene, final SubScene newSubScene,
}
}
+ /**
+ * For use by implementing subclasses. Treat as protected.
+ *
+ * Creates and returns a SimpleDoubleProperty with an invalidation scheme.
+ */
+ DoubleProperty getLightDoubleProperty(String name, double initialValue) {
+ return new SimpleDoubleProperty(this, name, initialValue) {
+ @Override
+ protected void invalidated() {
+ NodeHelper.markDirty(LightBase.this, DirtyBits.NODE_LIGHT);
+ }
+ };
+ }
+
private void markOwnerDirty() {
// if the light is part of the scene/subScene, we will need to notify
// the owner to mark the entire scene/subScene dirty.
diff --git a/modules/javafx.graphics/src/main/java/javafx/scene/PointLight.java b/modules/javafx.graphics/src/main/java/javafx/scene/PointLight.java
index 98c0bf88a7..49006f2c3e 100644
--- a/modules/javafx.graphics/src/main/java/javafx/scene/PointLight.java
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/PointLight.java
@@ -26,18 +26,35 @@
package javafx.scene;
import com.sun.javafx.scene.DirtyBits;
-import com.sun.javafx.scene.NodeHelper;
import com.sun.javafx.scene.PointLightHelper;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.sg.prism.NGPointLight;
+
+import javafx.beans.property.DoubleProperty;
import javafx.scene.paint.Color;
+import javafx.scene.paint.PhongMaterial;
/**
- * Defines a point light source object. A light source that has a
- * fixed point in space and radiates light equally in all directions
- * away from itself.
+ * A light source that radiates light equally in all directions away from itself. The location of the light
+ * source is a single point in space. Any pixel within the range of the light will be illuminated by it,
+ * unless it belongs to a {@code Shape3D} outside of its {@code scope}.
+ *
+ * The light's intensity can be set to decrease over distance by attenuating it. The attenuation formula
+ *
+ * {@code attn = 1 / (ca + la * dist + qa * dist^2)}
+ *
+ * defines 3 coefficients: {@code ca}, {@code la}, and {@code qa}, which control the constant, linear, and
+ * quadratic behaviors of intensity falloff over distance, respectively. The effective color of the light
+ * at a given point in space is {@code color * attn}. It is possible, albeit unrealistic, to specify negative
+ * values to attenuation coefficients. This allows the resulting attenuation factor to be negative, which
+ * results in the light's color being subtracted from the material instead of added to it, thus creating a
+ * "shadow caster".
+ *
+ * For a realistic effect, {@code maxRange} should be set to a distance at which the attenuation is close to 0
+ * as this will give a soft cutoff.
*
* @since JavaFX 8.0
+ * @see PhongMaterial
*/
public class PointLight extends LightBase {
static {
@@ -46,16 +63,21 @@ public class PointLight extends LightBase {
public NGNode doCreatePeer(Node node) {
return ((PointLight) node).doCreatePeer();
}
+
+ @Override
+ public void doUpdatePeer(Node node) {
+ ((PointLight) node).doUpdatePeer();
+ }
});
}
{
- // To initialize the class helper at the begining each constructor of this class
+ // To initialize the class helper at the beginning each constructor of this class
PointLightHelper.initHelper(this);
}
/**
- * Creates a new instance of {@code PointLight} class with a default Color.WHITE light source.
+ * Creates a new instance of {@code PointLight} class with a default {@code Color.WHITE} light source.
*/
public PointLight() {
super();
@@ -70,10 +92,142 @@ public PointLight(Color color) {
super(color);
}
+ /**
+ * The maximum range of this {@code PointLight}. For a pixel to be affected by this light, its distance to
+ * the light source must be less than or equal to the light's maximum range. Any negative value will treated
+ * as 0.
+ *
+ * Lower {@code maxRange} values can give better performance as pixels outside the range of the light
+ * will not require complex calculation. The attenuation formula can be used to calculate a realistic
+ * {@code maxRange} value by finding the where the attenuation is close enough to 0.
+ *
+ * Nodes that are inside the light's range can still be excluded from the light's effect
+ * by removing them from its {@link #getScope() scope}. If a node is known to always be
+ * outside of the light's range, it is more performant to exclude it from its scope.
+ *
+ * @defaultValue {@code Double.POSITIVE_INFINITY}
+ * @since 13
+ */
+ private DoubleProperty maxRange;
+
+ public final void setMaxRange(double value) {
+ maxRangeProperty().set(value);
+ }
+
+ private static final double DEFAULT_MAX_RANGE = NGPointLight.getDefaultMaxRange();
+
+ public final double getMaxRange() {
+ return maxRange == null ? DEFAULT_MAX_RANGE : maxRange.get();
+ }
+
+ public final DoubleProperty maxRangeProperty() {
+ if (maxRange == null) {
+ maxRange = getLightDoubleProperty("maxRange", DEFAULT_MAX_RANGE);
+ }
+ return maxRange;
+ }
+
+ /**
+ * The constant attenuation coefficient. This is the term {@code ca} in the attenuation formula:
+ *
+ * {@code attn = 1 / (ca + la * dist + qa * dist^2)}
+ *
+ * where {@code dist} is the distance between the light source and the pixel.
+ *
+ * @defaultValue {@code 1}
+ * @since 13
+ */
+ private DoubleProperty constantAttenuation;
+
+ public final void setConstantAttenuation(double value) {
+ constantAttenuationProperty().set(value);
+ }
+
+ private static final double DEFAULT_CONSTANT_ATTENUATION = NGPointLight.getDefaultCa();
+
+ public final double getConstantAttenuation() {
+ return constantAttenuation == null ? DEFAULT_CONSTANT_ATTENUATION : constantAttenuation.get();
+ }
+
+ public final DoubleProperty constantAttenuationProperty() {
+ if (constantAttenuation == null) {
+ constantAttenuation = getLightDoubleProperty("constantAttenuation", DEFAULT_CONSTANT_ATTENUATION);
+ }
+ return constantAttenuation;
+ }
+
+ /**
+ * The linear attenuation coefficient. This is the term {@code la} in the attenuation formula:
+ *
+ * {@code attn = 1 / (ca + la * dist + qa * dist^2)}
+ *
+ * where {@code dist} is the distance between the light source and the pixel.
+ *
+ * @defaultValue {@code 0}
+ * @since 13
+ */
+ private DoubleProperty linearAttenuation;
+
+ public final void setLinearAttenuation(double value) {
+ linearAttenuationProperty().set(value);
+ }
+
+ private static final double DEFAULT_LINEAR_CONSTANT = NGPointLight.getDefaultLa();
+
+ public final double getLinearAttenuation() {
+ return linearAttenuation == null ? DEFAULT_LINEAR_CONSTANT : linearAttenuation.get();
+ }
+
+ public final DoubleProperty linearAttenuationProperty() {
+ if (linearAttenuation == null) {
+ linearAttenuation = getLightDoubleProperty("linearAttenuation", DEFAULT_LINEAR_CONSTANT);
+ }
+ return linearAttenuation;
+ }
+
+ /**
+ * The quadratic attenuation coefficient. This is the term {@code qa} in the attenuation formula:
+ *
+ * {@code attn = 1 / (ca + la * dist + qa * dist^2)}
+ *
+ * where {@code dist} is the distance between the light source and the pixel.
+ *
+ * @defaultValue {@code 0}
+ * @since 13
+ */
+ private DoubleProperty quadraticAttenuation;
+
+ public final void setQuadraticAttenuation(double value) {
+ quadraticAttenuationProperty().set(value);
+ }
+
+ private static final double DEFAULT_QUADRATIC_CONSTANT = NGPointLight.getDefaultQa();
+
+ public final double getQuadraticAttenuation() {
+ return quadraticAttenuation == null ? DEFAULT_QUADRATIC_CONSTANT : quadraticAttenuation.get();
+ }
+
+ public final DoubleProperty quadraticAttenuationProperty() {
+ if (quadraticAttenuation == null) {
+ quadraticAttenuation = getLightDoubleProperty("quadraticAttenuation", DEFAULT_QUADRATIC_CONSTANT);
+ }
+ return quadraticAttenuation;
+ }
+
/*
* Note: This method MUST only be called via its accessor method.
*/
private NGNode doCreatePeer() {
return new NGPointLight();
}
+
+ private void doUpdatePeer() {
+ if (isDirty(DirtyBits.NODE_LIGHT)) {
+ NGPointLight peer = getPeer();
+ peer.setCa(getConstantAttenuation());
+ peer.setLa(getLinearAttenuation());
+ peer.setQa(getQuadraticAttenuation());
+ peer.setMaxRange(getMaxRange());
+ }
+ }
}
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/D3DContext.cc b/modules/javafx.graphics/src/main/native-prism-d3d/D3DContext.cc
index bdcb107ae2..a7c2f37846 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/D3DContext.cc
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/D3DContext.cc
@@ -516,13 +516,13 @@ JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetAmbientLight
*/
JNIEXPORT void JNICALL Java_com_sun_prism_d3d_D3DContext_nSetPointLight
(JNIEnv *env, jclass, jlong ctx, jlong nativeMeshView, jint index,
- jfloat x, jfloat y, jfloat z, jfloat r, jfloat g, jfloat b, jfloat w)
+ jfloat x, jfloat y, jfloat z, jfloat r, jfloat g, jfloat b, jfloat w,
+ jfloat ca, jfloat la, jfloat qa, jfloat range)
{
TraceLn(NWT_TRACE_INFO, "D3DContext_nSetPointLight");
D3DMeshView *meshView = (D3DMeshView *) jlong_to_ptr(nativeMeshView);
RETURN_IF_NULL(meshView);
-
- meshView->setPointLight(index, x, y, z, r, g, b, w);
+ meshView->setPointLight(index, x, y, z, r, g, b, w, ca, la, qa, range);
}
/*
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.cc b/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.cc
index 8edc6aa1b3..8d3e11f84e 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.cc
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.cc
@@ -43,6 +43,10 @@ D3DLight::D3DLight() {
position[2] = 0;
position[3] = 0; // padding since SetPixelShaderConstantF only takes vec4f; position[3] is unused
w = 0;
+ attenuation[0] = 1;
+ attenuation[1] = 0;
+ attenuation[2] = 0;
+ attenuation[3] = 0;
}
void D3DLight::setColor(float r, float g, float b) {
@@ -56,3 +60,7 @@ void D3DLight::setPosition(float x, float y, float z) {
position[1] = y;
position[2] = z;
}
+
+/*void D3DLight::setRange(float r) {
+ range = r;
+}*/
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.h b/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.h
index 2d0cf9177d..7e85301b9e 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.h
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/D3DLight.h
@@ -36,13 +36,14 @@ class D3DLight {
virtual ~D3DLight();
void setColor(float r, float g, float b);
void setPosition(float x, float y, float z);
+// void setRange(float r);
float position[4]; // Only need x, y, z. The last float is needed for padding when upload to shader.
float color[3];
float w;
+ float attenuation[4]; // ca, la, qa, range
private:
};
#endif /* D3DLIGHT_H */
-
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.cc b/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.cc
index 522dfac0a5..f1ffcb4d1d 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.cc
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.cc
@@ -73,7 +73,8 @@ void D3DMeshView::setAmbientLight(float r, float g, float b) {
}
void D3DMeshView::setPointLight(int index, float x, float y, float z,
- float r, float g, float b, float w) {
+ float r, float g, float b, float w,
+ float ca, float la, float qa, float range) {
// NOTE: We only support up to 3 point lights at the present
if (index >= 0 && index <= 2) {
lights[index].position[0] = x;
@@ -83,6 +84,10 @@ void D3DMeshView::setPointLight(int index, float x, float y, float z,
lights[index].color[1] = g;
lights[index].color[2] = b;
lights[index].w = w;
+ lights[index].attenuation[0] = ca;
+ lights[index].attenuation[1] = la;
+ lights[index].attenuation[2] = qa;
+ lights[index].attenuation[3] = range;
lightsDirty = TRUE;
}
}
@@ -154,19 +159,30 @@ void D3DMeshView::render() {
return;
}
- float lightsColor[12];
- for (int i = 0, j = 0; i < 3; i++) {
+ float lightsColor[12]; // 3 lights x (3 color + 1 padding)
+ float lightsAttenuation[12]; // 3 lights x (3 attenuation factors + 1 range)
+ for (int i = 0, c = 0, r = 0; i < 3; i++) {
float w = lights[i].w;
- lightsColor[j++] = lights[i].color[0] * w;
- lightsColor[j++] = lights[i].color[1] * w;
- lightsColor[j++] = lights[i].color[2] * w;
- lightsColor[j++] = 1;
+ lightsColor[c++] = lights[i].color[0] * w;
+ lightsColor[c++] = lights[i].color[1] * w;
+ lightsColor[c++] = lights[i].color[2] * w;
+ lightsColor[c++] = 1;
+
+ lightsAttenuation[r++] = lights[i].attenuation[0];
+ lightsAttenuation[r++] = lights[i].attenuation[1];
+ lightsAttenuation[r++] = lights[i].attenuation[2];
+ lightsAttenuation[r++] = lights[i].attenuation[3];
}
status = SUCCEEDED(device->SetPixelShaderConstantF(PSR_LIGHTCOLOR, lightsColor, 3));
if (!status) {
cout << "D3DMeshView.render() - SetPixelShaderConstantF (PSR_LIGHTCOLOR) failed !!!" << endl;
return;
}
+ status = SUCCEEDED(device->SetPixelShaderConstantF(PSR_LIGHT_ATTENUATION, lightsAttenuation, 3));
+ if (!status) {
+ cout << "D3DMeshView.render() - SetPixelShaderConstantF (PSR_LIGHT_ATTENUATION) failed !!!" << endl;
+ return;
+ }
int bm = pShader->getBumpMode(material->isBumpMap());
int sm = pShader->getSpecularMode(material->isSpecularMap(), material->isSpecularColor());
@@ -208,4 +224,4 @@ void D3DMeshView::render() {
SUCCEEDED(device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0,
mesh->getNumVertices(), 0, (mesh->getNumIndices()/3)));
-}
+}
\ No newline at end of file
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.h b/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.h
index 6ab7206869..00d97af13e 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.h
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/D3DMeshView.h
@@ -40,7 +40,8 @@ class D3DMeshView {
void setWireframe(bool wf);
void setAmbientLight(float r, float g, float b);
void setPointLight(int index, float x, float y, float z,
- float r, float g, float b, float w);
+ float r, float g, float b, float w,
+ float ca, float la, float qa, float range);
void computeNumLights();
void render();
@@ -50,11 +51,10 @@ class D3DMeshView {
D3DPhongMaterial *material;
D3DLight lights[3];
float ambientLightColor[3];
- int numLights;
+ int numLights;
bool lightsDirty;
int cullMode;
bool wireframe;
};
#endif /* D3DMESHVIEW_H */
-
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/D3DPhongShader.h b/modules/javafx.graphics/src/main/native-prism-d3d/D3DPhongShader.h
index efe080f7d5..d397cf751f 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/D3DPhongShader.h
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/D3DPhongShader.h
@@ -39,10 +39,11 @@
#define VSR_WORLDMATRIX 30
// PSR implies Pixel Shader Registers
-// we have 32 constants for ps 2.0
+// we have 224 float constants for ps 3.0
#define PSR_DIFFUSECOLOR 0
#define PSR_SPECULARCOLOR 1
-#define PSR_LIGHTCOLOR 4
+#define PSR_LIGHTCOLOR 4 // 3 lights + 2 reserve
+#define PSR_LIGHT_ATTENUATION 9 // 3 lights + 2 reserve
// SR implies Sampler Registers
#define SR_DIFFUSEMAP 0
@@ -107,4 +108,3 @@ static const int maxLights = 3;
};
#endif /* D3DPHONGSHADER_H */
-
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psConstants.h b/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psConstants.h
index 8e02cb2a40..fcb7f171f0 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psConstants.h
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psConstants.h
@@ -30,5 +30,6 @@ static const int numMaxLights = 5;
float4 gDiffuseColor : register(c0);
float4 gSpecularColor : register(c1); // specular power is in the alpha
float4 gLightColor[numMaxLights] : register(c4); // [c4 .. c8]
+float4 gLightAttenuation[numMaxLights] : register(c9); // [c9 .. c13]
-float4 gSomethingElse : register(c9);
+float4 gSomethingElse : register(c14);
diff --git a/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psMath.h b/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psMath.h
index 7b96bd2fa1..f65de0bcd6 100644
--- a/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psMath.h
+++ b/modules/javafx.graphics/src/main/native-prism-d3d/hlsl/psMath.h
@@ -63,9 +63,18 @@ void phong(
in out float3 d, in out float3 s, int _s, int _e)
{
float3 refl = reflect(e, n);
- for (int i=_s; i<_e; i++) {
- float3 l = normalize(L[i].xyz);
- d += saturate(dot(n,l))*gLightColor[i].xyz;
- s += pow(saturate(dot(-refl, l)), power)*gLightColor[i].xyz;
+ for (int i = _s; i < _e; i++) {
+ float range = gLightAttenuation[i].w;
+ float dist = length(L[i].xyz);
+ if (dist <= range) {
+ float ca = gLightAttenuation[i].x;
+ float la = gLightAttenuation[i].y;
+ float qa = gLightAttenuation[i].z;
+ float attn = 1.0 / (ca + la * dist + qa * dist * dist);
+
+ float3 l = normalize(L[i].xyz);
+ d += saturate(dot(n, l)) * gLightColor[i].xyz * attn;
+ s += pow(saturate(dot(-refl, l)), power) * gLightColor[i].xyz * attn;
+ }
}
}
diff --git a/modules/javafx.graphics/src/main/native-prism-es2/GLContext.c b/modules/javafx.graphics/src/main/native-prism-es2/GLContext.c
index ba6bc1bd29..6e1c30831b 100644
--- a/modules/javafx.graphics/src/main/native-prism-es2/GLContext.c
+++ b/modules/javafx.graphics/src/main/native-prism-es2/GLContext.c
@@ -2122,6 +2122,10 @@ JNIEXPORT jlong JNICALL Java_com_sun_prism_es2_GLContext_nCreateES2MeshView
meshViewInfo->pointLightPosition[1] = 0;
meshViewInfo->pointLightPosition[2] = 0;
meshViewInfo->pointLightWeight = 0;
+ meshViewInfo->pointLightRange = 1;
+ meshViewInfo->pointLightAttenuation[0] = 1;
+ meshViewInfo->pointLightAttenuation[1] = 0;
+ meshViewInfo->pointLightAttenuation[2] = 0;
return ptr_to_jlong(meshViewInfo);
}
@@ -2265,7 +2269,7 @@ JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetAmbientLight
*/
JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetPointLight
(JNIEnv *env, jclass class, jlong nativeCtxInfo, jlong nativeMeshViewInfo,
- jint index, jfloat x, jfloat y, jfloat z, jfloat r, jfloat g, jfloat b, jfloat w)
+ jint index, jfloat x, jfloat y, jfloat z, jfloat r, jfloat g, jfloat b, jfloat w, jfloat range, jfloat ca, jfloat la, jfloat qa)
{
ContextInfo *ctxInfo = (ContextInfo *) jlong_to_ptr(nativeCtxInfo);
MeshViewInfo *meshViewInfo = (MeshViewInfo *) jlong_to_ptr(nativeMeshViewInfo);
@@ -2281,6 +2285,10 @@ JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nSetPointLight
meshViewInfo->pointLightColor[1] = g;
meshViewInfo->pointLightColor[2] = b;
meshViewInfo->pointLightWeight = w;
+ meshViewInfo->pointLightRange = range;
+ meshViewInfo->pointLightAttenuation[0] = ca;
+ meshViewInfo->pointLightAttenuation[1] = la;
+ meshViewInfo->pointLightAttenuation[2] = qa;
}
/*
@@ -2339,4 +2347,3 @@ JNIEXPORT void JNICALL Java_com_sun_prism_es2_GLContext_nRenderMeshView
ctxInfo->glBindBuffer(GL_ARRAY_BUFFER, 0);
ctxInfo->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
-
diff --git a/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h b/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h
index aede70b041..3d0402730f 100644
--- a/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h
+++ b/modules/javafx.graphics/src/main/native-prism-es2/PrismES2Defs.h
@@ -380,6 +380,10 @@ struct MeshViewInfoRec {
GLfloat pointLightWeight;
GLfloat pointLightPosition[3];
GLfloat pointLightColor[3];
+
+ GLfloat pointLightRange;
+ GLfloat pointLightAttenuation[3];
+
GLboolean cullEnable;
GLenum cullMode;
GLenum fillMode;
diff --git a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main.vert b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main.vert
index ee8dca946d..f950e59bcb 100644
--- a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main.vert
+++ b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main.vert
@@ -35,6 +35,7 @@ attribute vec4 tangent;
struct Light {
vec4 pos;
vec3 color;
+ vec4 atten;
};
//3 lights used
@@ -50,13 +51,12 @@ vec3 getLocalVector(vec3 global, vec3 tangentFrame[3]) {
void main()
{
- vec3 tangentFrame[3];
-
+ vec3 tangentFrame[3];
vec4 worldPos = worldMatrix * vec4(pos, 1.0);
// Note: The breaking of a vector and scale computation statement into
- // 2 separate statements is intentional to workaround a shader
- // compiler bug on the Freescale iMX6 platform. See RT-37789 for details.
+ // 2 separate statements is intentional to workaround a shader
+ // compiler bug on the Freescale iMX6 platform. See RT-37789 for details.
vec3 t1 = tangent.xyz * tangent.yzx;
t1 *= 2.0;
vec3 t2 = tangent.zxy * tangent.www;
@@ -73,9 +73,7 @@ void main()
tangentFrame[2] = vec3(r1.z, r2.y, t4.x);
tangentFrame[2] *= (tangent.w>=0.0) ? 1.0 : -1.0;
- mat3 sWorldMatrix = mat3(worldMatrix[0].xyz,
- worldMatrix[1].xyz,
- worldMatrix[2].xyz);
+ mat3 sWorldMatrix = mat3(worldMatrix[0].xyz, worldMatrix[1].xyz, worldMatrix[2].xyz);
//Translate the tangent frame to world space.
tangentFrame[0] = sWorldMatrix * tangentFrame[0];
diff --git a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main1Light.frag b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main1Light.frag
index 51ee88ca46..084af33b81 100644
--- a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main1Light.frag
+++ b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main1Light.frag
@@ -55,6 +55,7 @@ vec4 apply_selfIllum();
struct Light {
vec4 pos;
vec3 color;
+ vec4 atten;
};
uniform vec3 ambientColor;
@@ -65,26 +66,30 @@ varying vec4 lightTangentSpacePositions[3];
void main()
{
- gl_FragColor = vec4(0.0,0.0,0.0,1.0);
- vec4 diffuse = apply_diffuse();
+ float dist = (lights[0].pos.xyz - gl_Position);
+ if(dist <= lights[0].atten.range){
+ gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+ vec4 diffuse = apply_diffuse();
- if (diffuse.a == 0.0) discard;
+ if (diffuse.a == 0.0) discard;
- vec3 n = apply_normal();
+ vec3 n = apply_normal();
- vec3 d = vec3(0.0);
- vec3 s = vec3(0.0);
+ vec3 d = vec3(0.0);
+ vec3 s = vec3(0.0);
- vec3 refl = reflect(normalize(eyePos), n);
- vec4 specular = apply_specular();
- float power = specular.a;
+ vec3 refl = reflect(normalize(eyePos), n);
+ vec4 specular = apply_specular();
+ float power = specular.a;
- vec3 l = normalize(lightTangentSpacePositions[0].xyz);
- d = clamp(dot(n,l), 0.0, 1.0)*(lights[0].color).rgb;
- s = pow(clamp(dot(-refl, l), 0.0, 1.0), power)*lights[0].color.rgb;
+ vec3 l = normalize(lightTangentSpacePositions[0].xyz);
+ float att = 1.0 / (lights[0].atten.ca + lights[0].atten.la * dist + lights[0].atten.qa * (dist * dist));
+ d = clamp(dot(n,l), 0.0, 1.0)*(lights[0].color).rgb * att;
+ s = pow(clamp(dot(-refl, l), 0.0, 1.0), power)*lights[0].color.rgb * att;
- vec3 rez = (ambientColor+d) * diffuse.xyz + s*specular.rgb;
- rez += apply_selfIllum().xyz;
+ vec3 rez = (ambientColor+d) * (diffuse.xyz + s*specular.rgb);
+ rez += apply_selfIllum().xyz;
- gl_FragColor = vec4(clamp(rez, 0.0, 1.0) , diffuse.a);
+ gl_FragColor = vec4(clamp(rez, 0.0, 1.0) , diffuse.a);
+ }
}
diff --git a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main2Lights.frag b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main2Lights.frag
index 44f7cbd52e..3cc34c5c98 100644
--- a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main2Lights.frag
+++ b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main2Lights.frag
@@ -55,6 +55,7 @@ vec4 apply_selfIllum();
struct Light {
vec4 pos;
vec3 color;
+ vec4 atten;
};
uniform vec3 ambientColor;
@@ -74,21 +75,22 @@ void main()
vec3 d = vec3(0.0);
vec3 s = vec3(0.0);
+ vec3 rez = vec3(0.0);
vec3 refl = reflect(normalize(eyePos), n);
vec4 specular = apply_specular();
float power = specular.a;
- vec3 l = normalize(lightTangentSpacePositions[0].xyz);
- d = clamp(dot(n,l), 0.0, 1.0)*(lights[0].color).rgb;
- s = pow(clamp(dot(-refl, l), 0.0, 1.0), power)*lights[0].color.rgb;
-
- l = normalize(lightTangentSpacePositions[1].xyz);
- d += clamp(dot(n,l), 0.0, 1.0)*(lights[1].color).rgb;
- s += pow(clamp(dot(-refl, l), 0.0, 1.0), power) * lights[1].color.rgb;
-
- vec3 rez = (ambientColor+d) * diffuse.xyz + s*specular.rgb;
+ for(int i=0;i<2;++i){
+ float dist = (lights[i].pos.xyz - gl_Position);
+ if(dist <= lights[i].atten.range){
+ vec3 l = normalize(lightTangentSpacePositions[i].xyz);
+ float att = 1.0 / (lights[i].atten.ca + lights[i].atten.la * dist + lights[i].atten.qa * (dist * dist));
+ d += clamp(dot(n,l), 0.0, 1.0)*(lights[i].color).rgb * att;
+ s += pow(clamp(dot(-refl, l), 0.0, 1.0), power) * lights[i].color.rgb *att;
+ rez = (ambientColor+d) * (diffuse.xyz + s*specular.rgb);
+ }
+ }
rez += apply_selfIllum().xyz;
-
gl_FragColor = vec4(clamp(rez, 0.0, 1.0) , diffuse.a);
}
diff --git a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main3Lights.frag b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main3Lights.frag
index 012ae079d6..6cf25813c4 100644
--- a/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main3Lights.frag
+++ b/modules/javafx.graphics/src/main/resources/com/sun/prism/es2/glsl/main3Lights.frag
@@ -55,6 +55,7 @@ vec4 apply_selfIllum();
struct Light {
vec4 pos;
vec3 color;
+ vec4 atten;
};
uniform vec3 ambientColor;
@@ -74,25 +75,22 @@ void main()
vec3 d = vec3(0.0);
vec3 s = vec3(0.0);
+ vec3 rez = vec3(0.0);
vec3 refl = reflect(normalize(eyePos), n);
vec4 specular = apply_specular();
float power = specular.a;
- vec3 l = normalize(lightTangentSpacePositions[0].xyz);
- d = clamp(dot(n,l), 0.0, 1.0)*(lights[0].color).rgb;
- s = pow(clamp(dot(-refl, l), 0.0, 1.0), power) * lights[0].color.rgb;
-
- l = normalize(lightTangentSpacePositions[1].xyz);
- d += clamp(dot(n,l), 0.0, 1.0)*(lights[1].color).rgb;
- s += pow(clamp(dot(-refl, l), 0.0, 1.0), power) * lights[1].color.rgb;
-
- l = normalize(lightTangentSpacePositions[2].xyz);
- d += clamp(dot(n,l), 0.0, 1.0)*(lights[2].color).rgb;
- s += pow(clamp(dot(-refl, l), 0.0, 1.0), power) * lights[2].color.rgb;
-
- vec3 rez = (ambientColor+d) * diffuse.xyz + s*specular.rgb;
+ for(int i=0;i<3;++i){
+ float dist = (lights[i].pos.xyz - gl_Position);
+ if(dist <= lights[i].atten.range){
+ vec3 l = normalize(lightTangentSpacePositions[i].xyz);
+ float att = 1.0 / (lights[i].atten.ca + lights[i].atten.la * dist + lights[i].atten.qa * (dist * dist));
+ d += clamp(dot(n,l), 0.0, 1.0)*(lights[i].color).rgb * att;
+ s += pow(clamp(dot(-refl, l), 0.0, 1.0), power) * lights[i].color.rgb *att;
+ rez = (ambientColor+d) * (diffuse.xyz + s*specular.rgb);
+ }
+ }
rez += apply_selfIllum().xyz;
-
gl_FragColor = vec4(clamp(rez, 0.0, 1.0) , diffuse.a);
}