Thứ Ba, 23 tháng 6, 2015

[JavaFX 8] Phần 8 (tt) : Hiệu ứng - Effect

Phần 8 (tt) : Hiệu ứng - Effect

17.Lighting :

Hiệu ứng Lighting giả lập một nguồn chiếu sáng trên node, để cho ra node có dạng 3D. Để sử dụng hiệu ứng lighting cho node hoặc group, chúng ta sử dụng lớp Lighting thuộc gói javafx.scene.effect và đưa vào node hoặc group qua phương thức setEffect().

a.Các thuộc tính :

kiểu
Tên thuộc tính
Giá trị mặc định
Miêu tả
Light
Light
DistantLight
Kiểu Light nào được sử dụng.
Effect
bumpInput
null
Sử dụng bump map
Effect
contentInput
null
Sử dụng content input
DoubleProperty
diffuseConstant
1.0
Cường độ khuếch tán, giá trị từ 0 đến 2.
DoubleProperty
specularConstant
0.3
Cường độ phản chiếu, giá trị từ 0 đến 2.
DoubleProperty
specularExponent
2.0
Độ sáng chói, giá trị từ 0 đến 4.
DoubleProperty
surfaceScale
1.5
Chiều cao được gán đến các pixel, giá trị từ 0 đến 10.

b. Thuộc tính surfaceScale :

Để tạo ra hiệu ứng 3D trên bề mặt 2D, lighting dựa vào giá trị opacity của mỗi pixel để xác định chiều cao mỗi pixel sẽ như thế nào khi được chiếu sáng. Transparent pixels (pixel trong suốt) xuất hiện chìm và opaque pixels (pixel không trong suốt) xuất hiện nổi. Để tăng hoặc giảm độ chìm nổi của các pixel, chúng ta sử dụng thuộc tính surfaceScale, giá trị của nó nằm trong khoảng từ 0 đến 10. Giá trị surfaceScale càng cao, thì cảm giác 3D càng rõ nét.
Sử dụng hiệu ứng Lighting với surfaceScale = 10

c. Thuộc tính bumpInput :

BumpInput là input mà thuộc tính surfaceScale chỉ tác động lên input này, những phần khác ngoài bumpInput surfaceScale không tác động đến. Tức là độ chìm nổi chỉ thể hiện trên input này. Mặc định, nếu bumInput là null, node sẽ là bumpInput.
BumpInput là 1 effect thuộc gói javafx.scene.effect. Theo quan điểm của tôi, các effect làm bumpInput  phải có input là ImageInput, nhưng bắt buộc Image đó phải có nền là trong suốt.
Ví dụ :
Đây là image có nền trong suốt
Sử dụng image làm input cho DropShadow và DropShadow này làm bumpInput
Code :
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.ImageInput;
import javafx.scene.effect.Lighting;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class exampleLighting extends Application {

   @Override
   public void start(Stage primaryStage) {

       Image image = new Image("graphics/javafx1.gif", 180, 100, true, true);

// Tạo hiệu ứng DropShadow
       DropShadow dropShadow = new DropShadow();
       dropShadow.setInput(new ImageInput(image, 0, 45));

// Hiệu ứng lighting
       Lighting lighting = new Lighting();
       lighting.setSurfaceScale(10);
// định nghĩa BumpInput
       lighting.setBumpInput(dropShadow);

       Circle circle = new Circle(100, 100, 100);
       circle.setFill(Color.YELLOW);
       circle.setEffect(lighting);

       Group root = new Group();
       root.getChildren().add(circle);

       Scene scene = new Scene(root, 400, 250);

       primaryStage.setTitle("Hello World!");
       primaryStage.setScene(scene);
       primaryStage.show();
   }

   public static void main(String[] args) {
       launch(args);
   }
}

d. Thuộc tính ContentInput :

ContentInput cũng là 1 input và input này cũng là 1 effect, nhưng thuộc tính surfaceScale không tác động đến nó. Mục đích của nó dùng để làm nền thay thế nền của node.
e. Thuộc tính Light :
JavaFX cung cấp 3 kiểu Light được xây dựng sẵn : distant light, point light, và spot light.
** * Distant light :
Distant light còn được gọi là directional light (chiếu sáng định hướng) hay linear light (chiếu sáng tuyến tính). Distant light phát ra các tia sáng song song theo hướng định sẵn chiếu lên node.
Distant light được Sun xây dựng trong Distant class thuộc gói javafx.scene.effect.Light.

Các thuộc tính của Distant :

kiểu
Tên thuộc tính
Giá trị mặc định
Miêu tả
DoubleProperty
azimuth
45
Phương chiếu sáng.
DoubleProperty
elevation
45
Điểm chiếu sáng.
Azimuth là phương chiếu sáng, được tính bằng độ. Ý nghĩa là nó sẽ lệch bao nhiêu độ so với node được chiếu sáng. Giá trị 0 độ được đặt ở vị trí 3 giờ của đồng hồ, 90 độ ở vị trí 6 giờ, 180 ở vị trí 9 giờ, 270 độ ở vị trí 12 giờ tương đương giá trị -90 độ.
Azimuth cắt node tại 2 điểm A, B (hình minh họa bên dưới). Với AB là giao tuyến, chúng ta vẽ một mặt phẳng vuông góc với mặt phẳng chứa node. Trên mặt phẳng này, chúng ta vẽ tiếp 1 đường tròn có đường kính AB. Đường tròn này được gọi là tập hợp điểm elevation. Elevation là 1 điểm nằm trên đường tròn này. Giá trị của elevation được tính bằng độ, ý nghĩa là nó sẽ lệch bao nhiêu độ so với phương chiếu sáng. Tại elevation, các tia sáng song song sẽ chiếu sáng lên node hoặc group.

Cách sử dụng Distant Light :

// Tạo đối tượng Distant với giá trị thuộc tính mặc định
Light.Distant distant = new Light.Distant();
// Tạo đối tượng Distant với giá trị Azimuth = 30, Elevation = 60, Color = Green. Color là màu chiếu sáng dành cho node. Nếu không định nghĩa biến Color, màu chiếu sáng là màu của node
Light.Distant distant = new Light.Distant(30,60, Color.GREEN);

  Một số phương thức của Distant Light :

kiểu trả về
Phương thức
Miêu tả
void
setAzimuth(double value)
Thiết lập giá trị thuộc tính azimuth
double
getAzimuth()
Trả về giá trị thuộc tính azimuth
void
setElevation(double value)
Thiết lập giá trị thuộc tính elevation
double
getElevation()
Trả về giá trị thuộc tính elevation
Ví dụ : Tạo 1 circle với hiệu ứng Lighting có thuộc tính Light là Distant
Code:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.effect.Light;
import javafx.scene.effect.Light.Distant;
import javafx.scene.effect.Lighting;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class exampleDistantLight extends Application {

   Distant distant;

   public void start(Stage primaryStage) {
       // Circle
       Circle circle = new Circle(200, 180, 150, Color.YELLOW);

       // Slider dành cho Arimuth
       Label labelArimuth = new Label("Arimuth : ");
       labelArimuth.setLayoutX(10);
       labelArimuth.setLayoutY(340);
       Slider slideArimuth = new Slider(0, 360, 45);
       slideArimuth.setLayoutX(65);
       slideArimuth.setLayoutY(340);
       slideArimuth.setPrefWidth(300);
       slideArimuth.setShowTickLabels(true);
       slideArimuth.setShowTickMarks(true);

       // Slider dành cho Elevation
       Label labelElevation = new Label("Elevation : ");
       labelElevation.setLayoutX(10);
       labelElevation.setLayoutY(370);
       Slider sliderElevation = new Slider(0, 360, 45);
       sliderElevation.setLayoutX(65);
       sliderElevation.setLayoutY(370);
       sliderElevation.setPrefWidth(300);
       sliderElevation.setShowTickLabels(true);
       sliderElevation.setShowTickMarks(true);

       // Định nghĩa đối tượng Distant
       distant = new Light.Distant();
       distant.setAzimuth(45);
       distant.setElevation(45);

       // Định nghĩa hiệu ứng Lighting
       Lighting lighting = new Lighting();
       lighting.setLight(distant);
       lighting.setSurfaceScale(10);
       //Áp dụng hiệu ứng Lighting vào Circle
       circle.setEffect(lighting);

       // Event khi thay đổi giá trị Arimuth
       slideArimuth.valueProperty().addListener((observable, oldValue, newValue) -> distant.setAzimuth(newValue.doubleValue()));

       // Event khi thay đổi giá trị Elevation
       sliderElevation.valueProperty().addListener((observable, oldValue, newValue) -> distant.setElevation(newValue.doubleValue()));

       Group root = new Group();
       root.getChildren().addAll(circle, slideArimuth, sliderElevation, labelArimuth, labelElevation);

       Scene scene = new Scene(root, 400, 450);
       scene.setFill(Color.GREEN);

       primaryStage.setTitle("HeWorld !");
       primaryStage.setScene(scene);
       primaryStage.show();
   }

   public static void main(String[] args) {
       launch(args);
   }
}

*** Point light :
Point light là một điểm chiếu sáng mà tại đó các tia sáng sẽ chiếu lên node theo dạng lan tỏa, chứ không phải song song như distant light. Mặt trời là 1 ví dụ điển hình của Point light, mặt trời là điểm chiếu sáng mà tại đó phát ra các tia sáng.

Các thuộc tính của Point light  :

kiểu
Tên thuộc tính
Giá trị mặc định
Miêu tả
DoubleProperty
x
0
Tọa độ x của điểm sáng
DoubleProperty
y
0
Tọa độ y của điểm sáng
DoubleProperty
z
0
Độ lan tỏa ánh sáng.

Cách sử dụng Point Light :

// Tạo đối tượng Point với giá trị thuộc tính mặc định
Light.Point point = new Light. Point();
// Tạo đối tượng Point với giá trị x = 30, y = 60, z= 40  ,Color = Green. Color là màu chiếu sáng dành cho node. Nếu không định nghĩa biến Color, màu chiếu sáng là màu của node
Light.Point point = new Light. Point(30,60,40, Color.GREEN);

  Một số phương thức của Point Light :

kiểu trả về
Phương thức
Miêu tả
void
setX(double value)
Thiết lập giá trị thuộc tính x
double
getX()
Trả về giá trị thuộc tính x
void
setY(double value)
Thiết lập giá trị thuộc tính y
double
getY()
Trả về giá trị thuộc tính y
void
setZ(double value)
Thiết lập giá trị thuộc tính z
double
getZ()
Trả về giá trị thuộc tính z
Ví dụ : Tạo 1 circle với hiệu ứng Lighting có thuộc tính Light là Point
Code :
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class examplePointLight extends Application {

   Light.Point point;

   @Override
   public void start(Stage primaryStage) {
       // Circle
       Circle circle = new Circle(200, 180, 150, Color.YELLOW);

       // Slider dành cho Arimuth
       Label labelX = new Label("X : ");
       labelX.setLayoutX(30);
       labelX.setLayoutY(340);
       Slider slideX = new Slider(0, 360, 45);
       slideX.setLayoutX(45);
       slideX.setLayoutY(340);
       slideX.setPrefWidth(300);
       slideX.setShowTickLabels(true);
       slideX.setShowTickMarks(true);

       // Slider dành cho Y
       Label labelY = new Label("Y : ");
       labelY.setLayoutX(30);
       labelY.setLayoutY(370);
       Slider sliderY = new Slider(0, 360, 45);
       sliderY.setLayoutX(45);
       sliderY.setLayoutY(370);
       sliderY.setPrefWidth(300);
       sliderY.setShowTickLabels(true);
       sliderY.setShowTickMarks(true);

       // Slider dành cho Z
       Label labelZ = new Label("Z : ");
       labelZ.setLayoutX(30);
       labelZ.setLayoutY(400);
       Slider sliderZ = new Slider(0, 360, 45);
       sliderZ.setLayoutX(45);
       sliderZ.setLayoutY(400);
       sliderZ.setPrefWidth(300);
       sliderZ.setShowTickLabels(true);
       sliderZ.setShowTickMarks(true);

       // Định nghĩa đối tượng Point light
       point = new Light.Point(50, 50, 50, Color.YELLOW);

       // Định nghĩa hiệu ứng Lighting
       Lighting lighting = new Lighting();
       lighting.setLight(point);
       //Áp dụng hiệu ứng Lighting vào Circle
       circle.setEffect(lighting);

       // Event khi thay đổi giá trị X
       slideX.valueProperty().addListener((observable, oldValue, newValue) -> point.setX(newValue.doubleValue()));

       // Event khi thay đổi giá trị Y
       sliderY.valueProperty().addListener((observable, oldValue, newValue) -> point.setY(newValue.doubleValue()));

       // Event khi thay đổi giá trị Z
       sliderZ.valueProperty().addListener((observable, oldValue, newValue) -> point.setZ(newValue.doubleValue()));

       Group root = new Group();
       root.getChildren().addAll(circle, slideX, sliderY, labelX, labelY, sliderZ, labelZ);

       Scene scene = new Scene(root, 400, 450);
       scene.setFill(Color.GREEN);

       primaryStage.setTitle("HeWorldssdsfffdllo !");
       primaryStage.setScene(scene);
       primaryStage.show();
   }

   public static void main(String[] args) {
       launch(args);
   }
}
***Spot light :
Spot light hoạt động giống như Point Light, trong khi điểm chiếu sáng của Point Light  phát ra các tia sáng khắp bốn hướng, thì Spot Light bị hạn chế chỉ chiếu sáng ở 1 vùng nào đó trên node. Các tia sáng của spot light được giới hạn trong khuôn khổ hình nón có đỉnh là điểm chiếu sáng.
Spot light được định nghĩa trong javafx.scene.effect.Light.Spot class và là lớp con của Point. Do đó, Spot class cũng kế thừa các thuộc tính và phương thức của Point.

Các thuộc tính của Spot  :

kiểu
Tên thuộc tính
Giá trị mặc định
Miêu tả
DoubleProperty
pointAtX
0
Tọa độ x của tâm mặt nón
DoubleProperty
pointAtY
0
Tọa độ y của tâm mặt nón
DoubleProperty
pointAtZ
0
Tọa độ z của tâm mặt nón
DoubleProperty
specularExponent
1.0
Chiều rộng của mặt nón, giá trị từ 0 đến 4
Thuộc tính x,y,z của Point class là đỉnh của hình nón, cũng là điểm chiếu sáng. Nó kết hợp với điểm có tọa độ (pointAtX, pointAtY, pointAtZ) tạo thành trục hình nón, còn chiều rộng của hình nón phụ thuộc vào thuộc tính specularExponent. Giá trị thuộc tính specularExponent càng lớn thì chiều rộng mặt nón càng nhỏ.

Cách sử dụng Spot Light :

// Tạo đối tượng Point với giá trị thuộc tính mặc định
Light.Point.Spot  spot  = new Light. Point.Spot();
// Tạo đối tượng Spot với điểm chiếu sáng có giá trị x = 30, y = 60, z= 40  ,Color = Green. Color là màu chiếu sáng dành cho node. Nếu không định nghĩa biến Color, màu chiếu sáng là màu của node
Light.Point.Spot  spot  = new Light. Point.Spot(30,60,40, Color.GREEN);

  Một số phương thức của Point Light :

kiểu trả về
Phương thức
Miêu tả
void
setPointAtX(double value)
Thiết lập giá trị thuộc tính pointAtX
double
getPointAtX()
Trả về giá trị thuộc tính pointAtX
void
setPointAtY(double value)
Thiết lập giá trị thuộc tính pointAtY
double
getPointAtY()
Trả về giá trị thuộc tính pointAtY
void
setPointAtZ(double value)
Thiết lập giá trị thuộc tính pointAtZ
double
getPointAtZ()
Trả về giá trị thuộc tính pointAtZ
Ví dụ : Tạo 1 circle với hiệu ứng Lighting có thuộc tính Light là Spot
Code :
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class exampleSpotLight extends Application {

   Light.Point.Spot spot;

   @Override
   public void start(Stage primaryStage) {
       // Circle
       Circle circle = new Circle(200, 180, 150, Color.YELLOW);

       // Slider dành cho PointAtX
       Label labelPointAtX = new Label("PointAtX : ");
       labelPointAtX.setLayoutX(10);
       labelPointAtX.setLayoutY(340);
       Slider slidePointAtX = new Slider(-300, 300, 0);
       slidePointAtX.setLayoutX(75);
       slidePointAtX.setLayoutY(340);
       slidePointAtX.setPrefWidth(300);
       slidePointAtX.setShowTickLabels(true);
       slidePointAtX.setShowTickMarks(true);

       // Slider dành cho PointAtY
       Label labelPointAtY = new Label("PointAtY : ");
       labelPointAtY.setLayoutX(10);
       labelPointAtY.setLayoutY(370);
       Slider slidePointAtY = new Slider(-300, 300, 0);
       slidePointAtY.setLayoutX(75);
       slidePointAtY.setLayoutY(370);
       slidePointAtY.setPrefWidth(300);
       slidePointAtY.setShowTickLabels(true);
       slidePointAtY.setShowTickMarks(true);

       // Slider dành cho PointAtZ
       Label labelPointAtZ = new Label("PointAtZ : ");
       labelPointAtZ.setLayoutX(10);
       labelPointAtZ.setLayoutY(400);
       Slider sliderPointAtZ = new Slider(-300, 300, 0);
       sliderPointAtZ.setLayoutX(75);
       sliderPointAtZ.setLayoutY(400);
       sliderPointAtZ.setPrefWidth(300);
       sliderPointAtZ.setShowTickLabels(true);
       sliderPointAtZ.setShowTickMarks(true);
       
       // Slider dành cho SpecularExponent
       Label labelSpecularExponent = new Label("SpecularExponent : ");
       labelSpecularExponent.setLayoutX(10);
       labelSpecularExponent.setLayoutY(430);
       Slider sliderSpecularExponent = new Slider(0, 4, 1);
       sliderSpecularExponent.setLayoutX(120);
       sliderSpecularExponent.setLayoutY(430);
       sliderSpecularExponent.setPrefWidth(250);
       sliderSpecularExponent.setShowTickLabels(true);
       sliderSpecularExponent.setShowTickMarks(true);

       // Định nghĩa đối tượng Distant
       spot = new Light.Spot(100, 100, 100, 4 , Color.YELLOW);

       // Định nghĩa hiệu ứng Lighting
       Lighting lighting = new Lighting();
       lighting.setLight(spot);
       lighting.setSurfaceScale(5);
       //Áp dụng hiệu ứng Lighting vào Circle
       circle.setEffect(lighting);

       // Event khi thay đổi giá trị PointAtX
       slidePointAtX.valueProperty().addListener((observable, oldValue, newValue)
               -> spot.setPointsAtX(newValue.doubleValue()));

       // Event khi thay đổi giá trị PointAtY
       slidePointAtY.valueProperty().addListener((observable, oldValue, newValue)
               -> spot.setPointsAtY(newValue.doubleValue()));

       // Event khi thay đổi giá trị PointAtZ
       sliderPointAtZ.valueProperty().addListener((observable, oldValue, newValue)
               -> spot.setPointsAtZ(newValue.doubleValue()));
       
        // Event khi thay đổi giá trị SpecularExponent
       sliderSpecularExponent.valueProperty().addListener((observable, oldValue, newValue)
               -> spot.setSpecularExponent(newValue.doubleValue()));

       Group root = new Group();
       root.getChildren().addAll(circle, slidePointAtX, slidePointAtY, labelPointAtX, labelPointAtY, sliderPointAtZ, labelPointAtZ, sliderSpecularExponent, labelSpecularExponent);

       Scene scene = new Scene(root, 400, 480);
       scene.setFill(Color.GREEN);

       primaryStage.setTitle("HeWorldssdsfffdllo !");
       primaryStage.setScene(scene);
       primaryStage.show();
   }

   public static void main(String[] args) {
       launch(args);
   }
}