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); }